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
This commit is contained in:
Thomas Wisniewski 2017-09-29 11:36:55 -04:00
parent d26e95be10
commit 81d59581ae
5 changed files with 39 additions and 32 deletions

View File

@ -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();
});
}

View File

@ -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();

View File

@ -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<ProgressEventType>(
"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<ProgressEventType>(
"dom::XMLHttpRequestMainThread::CloseRequestWithError",
this,
&XMLHttpRequestMainThread::CloseRequestWithError,
ProgressEventType::error));
}
return MaybeSilentSendFailure(NS_ERROR_DOM_NETWORK_ERR);
}
return rv;

View File

@ -308,6 +308,7 @@ public:
private:
virtual ~XMLHttpRequestMainThread();
nsresult MaybeSilentSendFailure(nsresult aRv);
nsresult SendInternal(const BodyExtractorBase* aBody);
bool IsCrossSiteCORSRequest() const;

View File

@ -1,5 +0,0 @@
[Blob-XHR-revoke.html]
type: testharness
[Revoke blob URL before open(), network error (after send())]
expected: FAIL