From 81d59581ae0fe072ceacf69bb274dca326518c03 Mon Sep 17 00:00:00 2001 From: Thomas Wisniewski Date: Fri, 29 Sep 2017 11:36:55 -0400 Subject: [PATCH] Bug 1341609 - Don't throw on async XHR send() failures when open() created no channel; r=baku MozReview-Commit-ID: IKVSbdRXoP8 --HG-- extra : rebase_source : 6f85751dae1bf7413598a3ddc381bee86545de9b --- dom/file/tests/test_blobURL_expiring.html | 13 ++++--- .../tests/test_blob_fragment_and_query.html | 15 ++++---- dom/xhr/XMLHttpRequestMainThread.cpp | 37 ++++++++++++------- dom/xhr/XMLHttpRequestMainThread.h | 1 + .../FileAPI/blob/Blob-XHR-revoke.html.ini | 5 --- 5 files changed, 39 insertions(+), 32 deletions(-) delete mode 100644 testing/web-platform/meta/FileAPI/blob/Blob-XHR-revoke.html.ini diff --git a/dom/file/tests/test_blobURL_expiring.html b/dom/file/tests/test_blobURL_expiring.html index a4a796849f68..42a37de3f6c5 100644 --- a/dom/file/tests/test_blobURL_expiring.html +++ b/dom/file/tests/test_blobURL_expiring.html @@ -25,14 +25,15 @@ onmessage = function(e) { }).then(function() { var xhr = new XMLHttpRequest(); xhr.open("GET", blobURL); - try { - xhr.send(); - ok(false, "The URL should be done!"); - } catch(e) { + xhr.onerror = function() { ok(true, "The URL should be done!"); + SimpleTest.finish(); } - - SimpleTest.finish(); + xhr.onload = function() { + ok(false, "The URL should be done!"); + SimpleTest.finish(); + } + xhr.send(); }); } diff --git a/dom/file/tests/test_blob_fragment_and_query.html b/dom/file/tests/test_blob_fragment_and_query.html index bc454e69c9f8..516879ba1130 100644 --- a/dom/file/tests/test_blob_fragment_and_query.html +++ b/dom/file/tests/test_blob_fragment_and_query.html @@ -31,24 +31,25 @@ function runTest() { var test = tests.shift(); - URL.revokeObjectURL(url + test.part); + if (test.revoke) { + URL.revokeObjectURL(url + test.part); + } var xhr = new XMLHttpRequest(); xhr.open('GET', url + test.part); xhr.onload = function() { + ok(!test.revoke, "Not-revoked URL should send()"); is(xhr.responseText, 'hello world', 'URL: ' + url + test.part); runTest(); } - try { - xhr.send(); - } catch(e) { - ok(test.revoke, "This should fail!"); + xhr.onerror = function() { + ok(test.revoke, "Revoked URL should fail on send()"); runTest(); - return; } - ok(!test.revoke, "This should succeed!"); + + xhr.send(); } SimpleTest.waitForExplicitFinish(); diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index 4c1ddf90d81f..4c62b815d88d 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -2932,6 +2932,26 @@ XMLHttpRequestMainThread::Send(JSContext* aCx, } } +nsresult +XMLHttpRequestMainThread::MaybeSilentSendFailure(nsresult aRv) +{ + // Per spec, silently fail on async request failures; throw for sync. + if (mFlagSynchronous) { + mState = State::done; + return NS_ERROR_DOM_NETWORK_ERR; + } + + // Defer the actual sending of async events just in case listeners + // are attached after the send() method is called. + Unused << NS_WARN_IF(NS_FAILED( + DispatchToMainThread(NewRunnableMethod( + "dom::XMLHttpRequestMainThread::CloseRequestWithError", + this, + &XMLHttpRequestMainThread::CloseRequestWithError, + ProgressEventType::error)))); + return NS_OK; +} + nsresult XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody) { @@ -2958,7 +2978,8 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody) // as per spec. We really should create the channel here in send(), but // we have internal code relying on the channel being created in open(). if (!mChannel) { - return NS_ERROR_DOM_NETWORK_ERR; + mFlagSend = true; // so CloseRequestWithError sets us to DONE. + return MaybeSilentSendFailure(NS_ERROR_DOM_NETWORK_ERR); } PopulateNetworkInterfaceId(); @@ -3111,19 +3132,7 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody) } if (!mChannel) { - // Per spec, silently fail on async request failures; throw for sync. - if (mFlagSynchronous) { - mState = State::done; - return NS_ERROR_DOM_NETWORK_ERR; - } else { - // Defer the actual sending of async events just in case listeners - // are attached after the send() method is called. - return DispatchToMainThread(NewRunnableMethod( - "dom::XMLHttpRequestMainThread::CloseRequestWithError", - this, - &XMLHttpRequestMainThread::CloseRequestWithError, - ProgressEventType::error)); - } + return MaybeSilentSendFailure(NS_ERROR_DOM_NETWORK_ERR); } return rv; diff --git a/dom/xhr/XMLHttpRequestMainThread.h b/dom/xhr/XMLHttpRequestMainThread.h index 6a5829e60b7a..b218eb42df54 100644 --- a/dom/xhr/XMLHttpRequestMainThread.h +++ b/dom/xhr/XMLHttpRequestMainThread.h @@ -308,6 +308,7 @@ public: private: virtual ~XMLHttpRequestMainThread(); + nsresult MaybeSilentSendFailure(nsresult aRv); nsresult SendInternal(const BodyExtractorBase* aBody); bool IsCrossSiteCORSRequest() const; diff --git a/testing/web-platform/meta/FileAPI/blob/Blob-XHR-revoke.html.ini b/testing/web-platform/meta/FileAPI/blob/Blob-XHR-revoke.html.ini deleted file mode 100644 index 822f89542812..000000000000 --- a/testing/web-platform/meta/FileAPI/blob/Blob-XHR-revoke.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[Blob-XHR-revoke.html] - type: testharness - [Revoke blob URL before open(), network error (after send())] - expected: FAIL -