Bug 780718 - Return false from DOMRequestService is preventDefault was called on events. r=sicking
--- 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/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
@@ -532,17 +532,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;
};
@@ -573,17 +574,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)
@@ -788,17 +790,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
@@ -83,18 +83,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;
}
@@ -104,18 +106,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);
@@ -143,20 +146,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)
{