Bug 709991 - Fire onerror instead of throwing on network errors for async XHRs. r=bz

This commit is contained in:
Thomas Wisniewski 2016-07-30 00:24:56 -04:00
Родитель c6165ca8ee
Коммит 6a1fb99d2b
13 изменённых файлов: 74 добавлений и 60 удалений

Просмотреть файл

@ -41,16 +41,13 @@ add_task(function* test() {
yield ContentTask.spawn(browser2, blobURL, function(url) {
return new Promise(resolve => {
var xhr = new content.window.XMLHttpRequest();
xhr.onerror = function() { resolve("SendErrored"); }
xhr.onload = function() { resolve("SendLoaded"); }
xhr.open("GET", url);
try {
xhr.send();
resolve("SendSucceeded");
} catch(e) {
resolve("SendThrew");
}
xhr.send();
});
}).then(status => {
is(status, "SendThrew", "Using a blob URI from one user context id in another should not work");
is(status, "SendErrored", "Using a blob URI from one user context id in another should not work");
});
info("Creating a tab with UCI = 1...");

Просмотреть файл

@ -31,18 +31,15 @@ add_task(function* test() {
yield ContentTask.spawn(privateTab, blobURL, function(url) {
return new Promise(resolve => {
var xhr = new content.window.XMLHttpRequest();
xhr.onerror = function() { resolve("SendErrored"); }
xhr.onload = function() { resolve("SendLoaded"); }
xhr.open("GET", url);
try {
xhr.send();
resolve("OpenSucceeded");
} catch(e) {
resolve("OpenThrew");
}
xhr.send();
});
}).then(status => {
is(status, "OpenThrew", "Using a blob URI from one user context id in another should not work");
is(status, "SendErrored", "Using a blob URI from one user context id in another should not work");
});
yield BrowserTestUtils.closeWindow(win);
yield BrowserTestUtils.closeWindow(privateWin);
});
});

Просмотреть файл

@ -529,9 +529,12 @@ this.ContentSearch = {
createInstance(Ci.nsIXMLHttpRequest);
xhr.open("GET", uri, true);
xhr.responseType = "arraybuffer";
xhr.onloadend = () => {
xhr.onload = () => {
deferred.resolve(xhr.response);
};
xhr.onerror = xhr.onabort = xhr.ontimeout = () => {
deferred.resolve(null);
};
try {
// This throws if the URI is erroneously encoded.
xhr.send();

Просмотреть файл

@ -392,7 +392,10 @@ function arrayBufferFromDataURI(uri) {
createInstance(Ci.nsIXMLHttpRequest);
xhr.open("GET", uri, true);
xhr.responseType = "arraybuffer";
xhr.onloadend = () => {
xhr.onerror = () => {
deferred.resolve(null);
};
xhr.onload = () => {
deferred.resolve(xhr.response);
};
try {

Просмотреть файл

@ -121,18 +121,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
return p;
}
function testXHR(url, shouldThrow) {
function testXHR(url, shouldError) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", () => { ok(!shouldThrow, "XHR succeeded for " + url); resolve(); });
xhr.addEventListener("error", () => { ok(false, "Unexpected XHR error: " + url); resolve(); });
try {
xhr.open("GET", url, true);
xhr.send();
} catch (e) {
ok(shouldThrow, "XHR threw for " + url);
resolve();
}
xhr.addEventListener("load", () => { ok(!shouldError, `XHR to ${url} should succeed`); resolve(); });
xhr.addEventListener("error", () => { ok(shouldError, `XHR to ${url} should fail`); resolve(); });
xhr.open("GET", url, true);
xhr.send();
});
}
@ -142,12 +137,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
testLoad.bind(null, 'moz-extension://cherise', navigateFromChromeWithLocation)()
.then(testLoad.bind(null, 'moz-extension://cherise', navigateFromChromeWithWebNav))
.then(testLoad.bind(null, 'moz-extension://cherise', navigateWithLocation, /* shouldThrow = */ true))
.then(testXHR.bind(null, 'moz-extension://cherise', /* shouldThrow = */ true))
.then(testXHR.bind(null, 'moz-extension://cherise', /* shouldError = */ true))
.then(setWhitelistCallback.bind(null, /cherise/))
.then(testLoad.bind(null, 'moz-extension://cherise', navigateWithLocation))
.then(testXHR.bind(null, 'moz-extension://cherise'))
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithLocation, /* shouldThrow = */ true))
.then(testXHR.bind(null, 'moz-extension://liebchen', /* shouldThrow = */ true))
.then(testXHR.bind(null, 'moz-extension://liebchen', /* shouldError = */ true))
.then(setWhitelistCallback.bind(null, /cherise|liebchen/))
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithLocation))
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithSrc))

Просмотреть файл

@ -16,6 +16,9 @@ addEventListener("message", function(e) {
iframe.src = mess.iframe;
else if ("xhr" in mess) {
let xhr = new XMLHttpRequest();
xhr.onerror = function() {
sendItUp({ didError: true });
}
xhr.onload = function() {
sendItUp({ text: xhr.responseText });
}

Просмотреть файл

@ -213,7 +213,7 @@ function runTest([imgFile, audioFile, docFile, xhrFile]) {
is((yield), "inner loaded", "correct gen.next()");
inner.contentWindow.postMessage(JSON.stringify({xhr:fileurl}), "*");
var res = (yield);
is(res.didThrow, true, "load failed successfully");
is(res.didError, true, "load failed successfully");
SimpleTest.finish();

Просмотреть файл

@ -760,9 +760,15 @@ function runTest() {
is(res.responseText, "",
"wrong responseText in test for " + test.toSource());
if (!res.sendThrew) {
is(res.events.join(","),
"opening,rs1,sending,loadstart,rs2,rs4,error,loadend",
"wrong events in test for " + test.toSource());
if (test.username) {
is(res.events.join(","),
"opening,rs1,sending,loadstart,rs4,error,loadend",
"wrong events in test for " + test.toSource());
} else {
is(res.events.join(","),
"opening,rs1,sending,loadstart,rs2,rs4,error,loadend",
"wrong events in test for " + test.toSource());
}
}
is(res.progressEvents, 0,
"wrong events in test for " + test.toSource());

Просмотреть файл

@ -2766,7 +2766,12 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
mChannel->SetNotificationCallbacks(mNotificationCallbacks);
mChannel = nullptr;
return rv;
mErrorLoad = true;
// Per spec, we throw on sync errors, but not async.
if (mFlagSynchronous) {
return rv;
}
}
mWaitingForOnStopRequest = true;
@ -2839,7 +2844,18 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
}
if (!mChannel) {
return NS_ERROR_FAILURE;
// Per spec, silently fail on async request failures; throw for sync.
if (mFlagSynchronous) {
return NS_ERROR_FAILURE;
} else {
// Defer the actual sending of async events just in case listeners
// are attached after the send() method is called.
NS_DispatchToCurrentThread(
NewRunnableMethod<ProgressEventType>(this,
&XMLHttpRequestMainThread::CloseRequestWithError,
ProgressEventType::error));
return NS_OK;
}
}
return rv;

Просмотреть файл

@ -48,17 +48,16 @@ tests.push(function test_file_uri() {
let xhr = new XMLHttpRequest({mozSystem: true});
is(xhr.mozSystem, true, ".mozSystem == true");
xhr.open("GET", PROTECTED_URL);
let error;
try {
xhr.send();
} catch (ex) {
error = ex;
xhr.onload = function() {
ok(false, "Should not have loaded");
runNextTest();
}
ok(!!error, "got exception");
is(error.name, "NS_ERROR_DOM_BAD_URI");
is(error.message, "Access to restricted URI denied");
runNextTest();
xhr.onerror = function(event) {
ok(true, "Got an error event: " + event);
is(xhr.status, 0, "HTTP status is 0");
runNextTest();
}
xhr.send();
});
tests.push(function test_redirect_to_file_uri() {

Просмотреть файл

@ -37,6 +37,9 @@ let xhr = function (method, url, responseType) {
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function() {
resolve(null);
};
xhr.responseType = responseType;
xhr.send();
});
@ -48,13 +51,8 @@ let jarURL = "jar:http://mochi.test:8888/tests/modules/libjar/test/mochitest/bug
add_task(function* () {
for (let shouldBlock of [false, true]) {
yield pushPref("network.jar.block-remote-files", shouldBlock);
try {
let response = yield xhr("GET", jarURL, "document");
didBlock = false;
} catch (e) {
didBlock = true;
}
ok(didBlock === shouldBlock,
let response = yield xhr("GET", jarURL, "document");
ok(shouldBlock === (response === null),
"Remote jars should be blocked if and only if the 'network.jar.block-remote-files' pref is active.");
}
});

Просмотреть файл

@ -182,15 +182,17 @@ function getHSTSStatus(host, resultList) {
req.open("GET", uri, true);
req.timeout = REQUEST_TIMEOUT;
req.channel.notificationCallbacks = new RedirectAndAuthStopper();
req.onreadystatechange = function(event) {
if (!inResultList && req.readyState == 4) {
req.onload = function(event) {
if (!inResultList) {
inResultList = true;
var header = req.getResponseHeader("strict-transport-security");
resultList.push(processStsHeader(host, header, req.status,
req.channel.securityInfo));
}
};
req.onerror = function(e) {
dump("ERROR: network error making request to " + host.name + ": " + e + "\n");
};
try {
req.send();
}

Просмотреть файл

@ -1,5 +0,0 @@
[send-authentication-basic-cors.htm]
type: testharness
[XMLHttpRequest: send() - "Basic" authenticated CORS requests with user name and password passed to open() (asserts failure)]
expected: FAIL