Bug 780718 - Return false from DOMRequestService is preventDefault was called on events. r=sicking
☠☠ backed out by f4495eb1c973 ☠ ☠
authorWes Johnston <wjohnston@mozilla.com>
Wed, 08 Aug 2012 12:35:15 -0700
changeset 107347 c030a8af8abd549cc765a4ac11de7ae47a659e03
parent 107346 0f7d2d447ed501408c8d86707f921c0ae038515d
child 107348 6dd4e5c2fe0a0911a7d9289802889fefa42bfc5e
push id1490
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 18:29:50 +0000
treeherdermozilla-beta@f335e7dacdc1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs780718
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 780718 - Return false from DOMRequestService is preventDefault was called on events. r=sicking
dom/base/DOMRequest.cpp
dom/base/DOMRequest.h
dom/base/nsIDOMDOMRequest.idl
dom/base/test/test_domrequest.html
dom/bluetooth/BluetoothReplyRunnable.cpp
dom/devicestorage/DeviceStorageRequestChild.cpp
dom/devicestorage/nsDeviceStorage.cpp
dom/file/ArchiveRequest.cpp
dom/file/FileRequest.cpp
--- a/dom/base/DOMRequest.cpp
+++ b/dom/base/DOMRequest.cpp
@@ -107,77 +107,77 @@ DOMRequest::GetError(nsIDOMDOMError** aE
                "Error should be null when pending");
 
   NS_IF_ADDREF(*aError = mError);
 
   return NS_OK;
 }
 
 void
-DOMRequest::FireSuccess(jsval aResult)
+DOMRequest::FireSuccess(jsval aResult, bool* aDefaultActionEnabled)
 {
   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
   NS_ASSERTION(!mError, "mError shouldn't have been set!");
   NS_ASSERTION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
 
   mDone = true;
   if (JSVAL_IS_GCTHING(aResult)) {
     RootResultVal();
   }
   mResult = aResult;
 
-  FireEvent(NS_LITERAL_STRING("success"), false, false);
+  FireEvent(NS_LITERAL_STRING("success"), false, false, aDefaultActionEnabled);
 }
 
 void
-DOMRequest::FireError(const nsAString& aError)
+DOMRequest::FireError(const nsAString& aError, bool* aDefaultActionEnabled)
 {
   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
   NS_ASSERTION(!mError, "mError shouldn't have been set!");
   NS_ASSERTION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
 
   mDone = true;
   mError = DOMError::CreateWithName(aError);
 
-  FireEvent(NS_LITERAL_STRING("error"), true, true);
+  FireEvent(NS_LITERAL_STRING("error"), true, true, aDefaultActionEnabled);
 }
 
 void
-DOMRequest::FireError(nsresult aError)
+DOMRequest::FireError(nsresult aError, bool* aDefaultActionEnabled)
 {
   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
   NS_ASSERTION(!mError, "mError shouldn't have been set!");
   NS_ASSERTION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
 
   mDone = true;
   mError = DOMError::CreateForNSResult(aError);
 
-  FireEvent(NS_LITERAL_STRING("error"), true, true);
+  FireEvent(NS_LITERAL_STRING("error"), true, true, aDefaultActionEnabled);
 }
 
 void
-DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable)
+DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable,
+                      bool* aDefaultActionEnabled)
 {
   if (NS_FAILED(CheckInnerWindowCorrectness())) {
     return;
   }
 
   nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nullptr, nullptr);
   nsresult rv = event->InitEvent(aType, aBubble, aCancelable);
   if (NS_FAILED(rv)) {
     return;
   }
 
   rv = event->SetTrusted(true);
   if (NS_FAILED(rv)) {
     return;
   }
 
-  bool dummy;
-  DispatchEvent(event, &dummy);
+  DispatchEvent(event, aDefaultActionEnabled);
 }
 
 void
 DOMRequest::RootResultVal()
 {
   NS_ASSERTION(!mRooted, "Don't call me if already rooted!");
   NS_HOLD_JS_OBJECTS(this, DOMRequest);
   mRooted = true;
@@ -200,25 +200,29 @@ DOMRequestService::CreateRequest(nsIDOMW
   NS_ENSURE_STATE(aWindow);
   NS_ADDREF(*aRequest = new DOMRequest(aWindow));
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMRequestService::FireSuccess(nsIDOMDOMRequest* aRequest,
-                               const jsval& aResult)
+                               const jsval& aResult,
+                               bool* aDefaultActionEnabled)
 {
+  NS_ENSURE_ARG_POINTER(aDefaultActionEnabled);
   NS_ENSURE_STATE(aRequest);
-  static_cast<DOMRequest*>(aRequest)->FireSuccess(aResult);
+  static_cast<DOMRequest*>(aRequest)->FireSuccess(aResult, aDefaultActionEnabled);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMRequestService::FireError(nsIDOMDOMRequest* aRequest,
-                             const nsAString& aError)
+                             const nsAString& aError,
+                             bool* aDefaultActionEnabled)
 {
+  NS_ENSURE_ARG_POINTER(aDefaultActionEnabled);
   NS_ENSURE_STATE(aRequest);
-  static_cast<DOMRequest*>(aRequest)->FireError(aError);
+  static_cast<DOMRequest*>(aRequest)->FireError(aError, aDefaultActionEnabled);
 
   return NS_OK;
 }
--- a/dom/base/DOMRequest.h
+++ b/dom/base/DOMRequest.h
@@ -32,32 +32,33 @@ protected:
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMDOMREQUEST
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DOMRequest,
                                                          nsDOMEventTargetHelper)
 
-  void FireSuccess(jsval aResult);
-  void FireError(const nsAString& aError);
-  void FireError(nsresult aError);
+  void FireSuccess(jsval aResult, bool* aDefaultActionEnabled);
+  void FireError(const nsAString& aError, bool* aDefaultActionEnabled);
+  void FireError(nsresult aError, bool* aDefaultActionEnabled);
 
   DOMRequest(nsIDOMWindow* aWindow);
   DOMRequest();
 
   virtual ~DOMRequest()
   {
     if (mRooted) {
       UnrootResultVal();
     }
   }
 
 protected:
-  void FireEvent(const nsAString& aType, bool aBubble, bool aCancelable);
+  void FireEvent(const nsAString& aType, bool aBubble, bool aCancelable,
+                 bool* aDefaultActionEnabled);
 
   virtual void RootResultVal();
   virtual void UnrootResultVal();
 
   void Init(nsIDOMWindow* aWindow);
 };
 
 class DOMRequestService MOZ_FINAL : public nsIDOMRequestService
--- a/dom/base/nsIDOMDOMRequest.idl
+++ b/dom/base/nsIDOMDOMRequest.idl
@@ -16,16 +16,16 @@ interface nsIDOMDOMRequest : nsIDOMEvent
 
   readonly attribute jsval result;
   readonly attribute nsIDOMDOMError error;
 
   attribute nsIDOMEventListener onsuccess;
   attribute nsIDOMEventListener onerror;
 };
 
-[scriptable, builtinclass, uuid(eebcdf29-f8fa-4c36-bbc7-2146b1cbaf7b)]
+[scriptable, builtinclass, uuid(46afe27a-d407-4eb8-95c4-aefbd2b63540)]
 interface nsIDOMRequestService : nsISupports
 {
   nsIDOMDOMRequest createRequest(in nsIDOMWindow window);
 
-  void fireSuccess(in nsIDOMDOMRequest request, in jsval result);
-  void fireError(in nsIDOMDOMRequest request, in DOMString error);
+  bool fireSuccess(in nsIDOMDOMRequest request, in jsval result);
+  bool fireError(in nsIDOMDOMRequest request, in DOMString error);
 };
--- a/dom/base/test/test_domrequest.html
+++ b/dom/base/test/test_domrequest.html
@@ -30,34 +30,44 @@ is(req.result, undefined, "result is und
 is(req.onsuccess, null, "onsuccess is null");
 is(req.onerror, null, "onerror is null");
 
 // fire success
 var ev = null;
 req.onsuccess = function(e) {
   ev = e;
 }
-reqserv.fireSuccess(req, "my result");
+is(reqserv.fireSuccess(req, "my result"), true, "prevent default not detected");
 ok(ev, "got success event");
 is(ev.type, "success", "correct type during success");
 is(ev.target, req, "correct target during success");
 is(req.readyState, "done", "correct readyState after success");
 is(req.error, null, "correct error after success");
 is(req.result, "my result", "correct result after success");
 
 // fire error
 req = reqserv.createRequest(window);
 ev = null;
 req.onerror = function(e) {
   ev = e;
 }
-reqserv.fireError(req, "OhMyError");
+is(reqserv.fireError(req, "OhMyError"), true, "prevent default not detected");
 ok(ev, "got success event");
 is(ev.type, "error", "correct type during error");
 is(ev.target, req, "correct target during error");
 is(req.readyState, "done", "correct readyState after error");
 is(req.error.name, "OhMyError", "correct error after error");
 is(req.result, undefined, "correct result after error");
 
+// Test calling preventDefault on events
+req.onsuccess = function(e) e.preventDefault();
+reqserv.fireSuccess(req, "my result");
+is(reqserv.fireSuccess(req, "my result"), false, "prevent default detected");
+
+// fire error
+req.onerror = function(e) e.preventDefault();
+reqserv.fireError(req, "OhMyError");
+is(reqserv.fireError(req, "OhMyError"), false, "prevent default detected");
+
 </script>
 </pre>
 </body>
 </html>
--- a/dom/bluetooth/BluetoothReplyRunnable.cpp
+++ b/dom/bluetooth/BluetoothReplyRunnable.cpp
@@ -16,34 +16,34 @@ BluetoothReplyRunnable::FireReply(const 
   nsCOMPtr<nsIDOMRequestService> rs =
     do_GetService("@mozilla.org/dom/dom-request-service;1");
   
   if (!rs) {
     NS_WARNING("No DOMRequest Service!");
     return NS_ERROR_FAILURE;
   }
   
-  
+  bool allowDefault;
   return mReply->type() == BluetoothReply::TBluetoothReplySuccess ?
-    rs->FireSuccess(mDOMRequest, aVal) :
-    rs->FireError(mDOMRequest, mReply->get_BluetoothReplyError().error());
+    rs->FireSuccess(mDOMRequest, aVal, &allowDefault) :
+    rs->FireError(mDOMRequest, mReply->get_BluetoothReplyError().error(), &allowDefault);
 }
 
 nsresult
 BluetoothReplyRunnable::FireErrorString()
 {
   nsCOMPtr<nsIDOMRequestService> rs =
     do_GetService("@mozilla.org/dom/dom-request-service;1");
   
   if (!rs) {
     NS_WARNING("No DOMRequest Service!");
     return NS_ERROR_FAILURE;
   }
-  
-  return rs->FireError(mDOMRequest, mErrorString);
+  bool allowDefault;
+  return rs->FireError(mDOMRequest, mErrorString, &allowDefault);
 }
 
 NS_IMETHODIMP
 BluetoothReplyRunnable::Run()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsresult rv;
--- a/dom/devicestorage/DeviceStorageRequestChild.cpp
+++ b/dom/devicestorage/DeviceStorageRequestChild.cpp
@@ -31,24 +31,26 @@ DeviceStorageRequestChild::~DeviceStorag
 bool
 DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aValue)
 {
   switch (aValue.type()) {
 
     case DeviceStorageResponseValue::TErrorResponse:
     {
       ErrorResponse r = aValue;
-      mRequest->FireError(r.error());
+      bool allowDefault;
+      mRequest->FireError(r.error(), &allowDefault);
       break;
     }
 
     case DeviceStorageResponseValue::TSuccessResponse:
     {
       jsval result = StringToJsval(mRequest->GetOwner(), mFile->mPath);
-      mRequest->FireSuccess(result);
+      bool allowDefault;
+      mRequest->FireSuccess(result, &allowDefault);
       break;
     }
 
     case DeviceStorageResponseValue::TBlobResponse:
     {
       BlobResponse r = aValue;
 
       // I am going to hell for this.  bent says he'll save me.
@@ -60,17 +62,18 @@ DeviceStorageRequestChild::Recv__delete_
       mimeType.AssignWithConversion(r.contentType());
 
       nsCOMPtr<nsIDOMBlob> blob = new nsDOMMemoryFile(buffer,
                                                       bits.Length(),
                                                       mFile->mPath,
                                                       mimeType);
 
       jsval result = BlobToJsval(mRequest->GetOwner(), blob);
-      mRequest->FireSuccess(result);
+      bool allowDefault;
+      mRequest->FireSuccess(result, &allowDefault);
       break;
     }
 
     case DeviceStorageResponseValue::TEnumerationResponse:
     {
       EnumerationResponse r = aValue;
       nsDOMDeviceStorageCursor* cursor = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
 
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -533,17 +533,18 @@ public:
       mError.Append(NS_LITERAL_STRING("null path"));
     }
   }
 
   NS_IMETHOD Run()
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-    mRequest->FireError(mError);
+    bool allowDefault;
+    mRequest->FireError(mError, &allowDefault);
     mRequest = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<DOMRequest> mRequest;
   nsString mError;
 };
@@ -574,17 +575,18 @@ ContinueCursorEvent::Run() {
     nsRefPtr<DeviceStorageFile> file = cursor->mFiles[0];
     cursor->mFiles.RemoveElementAt(0);
 
     // todo, this blob needs to be opened in the parent.  This will be signifincally easier when bent lands
     val = nsIFileToJsval(cursor->GetOwner(), file);
     cursor->mOkToCallContinue = true;
   }
 
-  mRequest->FireSuccess(val);
+  bool allowDefault;
+  mRequest->FireSuccess(val, &allowDefault);
   mRequest = nullptr;
   return NS_OK;
 }
 
 class InitCursorEvent : public nsRunnable
 {
 public:
     InitCursorEvent(DOMRequest* aRequest, DeviceStorageFile* aFile)
@@ -789,17 +791,18 @@ public:
 
     jsval result = JSVAL_NULL;
     if (mFile) {
       result = nsIFileToJsval(mRequest->GetOwner(), mFile);
     } else {
       result = StringToJsval(mRequest->GetOwner(), mPath);
     }
 
-    mRequest->FireSuccess(result);
+    bool allowDefault;
+    mRequest->FireSuccess(result, &allowDefault);
     mRequest = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsString mPath;
   nsRefPtr<DOMRequest> mRequest;
--- a/dom/file/ArchiveRequest.cpp
+++ b/dom/file/ArchiveRequest.cpp
@@ -85,18 +85,20 @@ ArchiveRequest::GetReader(nsIDOMArchiveR
 
 // Here the request is processed:
 void
 ArchiveRequest::Run()
 {
   // Register this request to the reader.
   // When the reader is ready to return data, a 'Ready()' will be called
   nsresult rv = mArchiveReader->RegisterRequest(this);
-  if (NS_FAILED(rv))
-    FireError(rv);
+  if (NS_FAILED(rv)) {
+    bool allowDefault;
+    FireError(rv, &allowDefault);
+  }
 }
 
 void
 ArchiveRequest::OpGetFilenames()
 {
   mOperation = GetFilenames;
 }
 
@@ -106,18 +108,19 @@ ArchiveRequest::OpGetFile(const nsAStrin
   mOperation = GetFile;
   mFilename = aFilename;
 }
 
 nsresult
 ArchiveRequest::ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
                             nsresult aStatus)
 {
+  bool allowDefault;
   if (aStatus != NS_OK) {
-    FireError(aStatus);
+    FireError(aStatus, &allowDefault);
     return NS_OK;
   }
 
   jsval result;
   nsresult rv;
 
   nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   NS_ENSURE_STATE(sc);
@@ -145,20 +148,20 @@ ArchiveRequest::ReaderReady(nsTArray<nsC
       NS_WARNING("Get*Result failed!");
     }
   } else {
     NS_WARNING("Failed to enter correct compartment!");
     rv = NS_ERROR_FAILURE;
   }
 
   if (NS_SUCCEEDED(rv)) {
-    FireSuccess(result);
+    FireSuccess(result, &allowDefault);
   }
   else {
-    FireError(rv);
+    FireError(rv, &allowDefault);
   }
 
   return NS_OK;
 }
 
 nsresult
 ArchiveRequest::GetFilenamesResult(JSContext* aCx,
                                    jsval* aValue,
--- a/dom/file/FileRequest.cpp
+++ b/dom/file/FileRequest.cpp
@@ -57,18 +57,19 @@ FileRequest::PreHandleEvent(nsEventChain
 nsresult
 FileRequest::NotifyHelperCompleted(FileHelper* aFileHelper)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsresult rv = aFileHelper->mResultCode;
 
   // If the request failed then fire error event and return.
+  bool allowDefault;
   if (NS_FAILED(rv)) {
-    FireError(rv);
+    FireError(rv, &allowDefault);
     return NS_OK;
   }
 
   // Otherwise we need to get the result from the helper.
   jsval result;
 
   nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   NS_ENSURE_STATE(sc);
@@ -88,20 +89,20 @@ FileRequest::NotifyHelperCompleted(FileH
     }
   }
   else {
     NS_WARNING("Failed to enter correct compartment!");
     rv = NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
   }
 
   if (NS_SUCCEEDED(rv)) {
-    FireSuccess(result);
+    FireSuccess(result, &allowDefault);
   }
   else {
-    FireError(rv);
+    FireError(rv, &allowDefault);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 FileRequest::GetLockedFile(nsIDOMLockedFile** aLockedFile)
 {