Bug 918751 - Throw NetworkErrors instead of failures where appropriate for some XHR web platform tests. r=bz, r=keeler, r=Mossop, r=paul
This commit is contained in:
@@ -273,13 +273,6 @@ function loadSnippets()
|
||||
// Try to update from network.
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.timeout = 5000;
|
||||
try {
|
||||
xhr.open("GET", updateURL, true);
|
||||
} catch (ex) {
|
||||
showSnippets();
|
||||
loadCompleted();
|
||||
return;
|
||||
}
|
||||
// Even if fetching should fail we don't want to spam the server, thus
|
||||
// set the last update time regardless its results. Will retry tomorrow.
|
||||
gSnippetsMap.set("snippets-last-update", Date.now());
|
||||
@@ -291,7 +284,14 @@ function loadSnippets()
|
||||
showSnippets();
|
||||
loadCompleted();
|
||||
};
|
||||
try {
|
||||
xhr.open("GET", updateURL, true);
|
||||
xhr.send(null);
|
||||
} catch (ex) {
|
||||
showSnippets();
|
||||
loadCompleted();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
showSnippets();
|
||||
loadCompleted();
|
||||
|
||||
@@ -940,12 +940,6 @@ Experiments.Experiments.prototype = {
|
||||
_httpGetRequest: function (url) {
|
||||
this._log.trace("httpGetRequest(" + url + ")");
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||
try {
|
||||
xhr.open("GET", url);
|
||||
} catch (e) {
|
||||
this._log.error("httpGetRequest() - Error opening request to " + url + ": " + e);
|
||||
return Promise.reject(new Error("Experiments - Error opening XHR for " + url));
|
||||
}
|
||||
|
||||
this._networkRequest = xhr;
|
||||
let deferred = Promise.defer();
|
||||
@@ -972,12 +966,19 @@ Experiments.Experiments.prototype = {
|
||||
this._networkRequest = null;
|
||||
};
|
||||
|
||||
try {
|
||||
xhr.open("GET", url);
|
||||
|
||||
if (xhr.channel instanceof Ci.nsISupportsPriority) {
|
||||
xhr.channel.priority = Ci.nsISupportsPriority.PRIORITY_LOWEST;
|
||||
}
|
||||
|
||||
xhr.timeout = MANIFEST_FETCH_TIMEOUT_MSEC;
|
||||
xhr.send(null);
|
||||
} catch (e) {
|
||||
this._log.error("httpGetRequest() - Error opening request to " + url + ": " + e);
|
||||
return Promise.reject(new Error("Experiments - Error opening XHR for " + url));
|
||||
}
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
|
||||
@@ -72,12 +72,12 @@ AppValidator.checkManifest = function (manifestURL) {
|
||||
|
||||
try {
|
||||
req.open("GET", manifestURL, true);
|
||||
req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
|
||||
} catch (e) {
|
||||
error = strings.formatStringFromName("validator.invalidManifestURL", [manifestURL], 1);
|
||||
deferred.reject(error);
|
||||
return deferred.promise;
|
||||
}
|
||||
req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
|
||||
|
||||
req.onload = function () {
|
||||
let manifest = null;
|
||||
@@ -228,12 +228,12 @@ AppValidator.prototype.validateLaunchPath = function (manifest) {
|
||||
req.overrideMimeType("text/plain");
|
||||
try {
|
||||
req.open("HEAD", indexURL, true);
|
||||
req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
|
||||
} catch (e) {
|
||||
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
|
||||
deferred.resolve();
|
||||
return deferred.promise;
|
||||
}
|
||||
req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
|
||||
req.onload = () => {
|
||||
if (req.status >= 400)
|
||||
this.error(strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [indexURL, req.status], 2));
|
||||
|
||||
@@ -106,12 +106,6 @@ exports.items = [
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
|
||||
try {
|
||||
xhr.open("GET", args.url, true);
|
||||
} catch(e) {
|
||||
return l10n.lookup("jsbInvalidURL");
|
||||
}
|
||||
|
||||
let deferred = context.defer();
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
@@ -128,7 +122,12 @@ exports.items = [
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
xhr.open("GET", args.url, true);
|
||||
xhr.send(null);
|
||||
} catch(e) {
|
||||
return l10n.lookup("jsbInvalidURL");
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ onmessage = function(e) {
|
||||
document.body.removeChild(iframe);
|
||||
}).then(function() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
try {
|
||||
xhr.open("GET", blobURL);
|
||||
try {
|
||||
xhr.send();
|
||||
ok(false, "The URL should be done!");
|
||||
} catch(e) {
|
||||
ok(true, "The URL should be done!");
|
||||
|
||||
@@ -34,20 +34,20 @@ function runTest() {
|
||||
URL.revokeObjectURL(url + test.part);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
try {
|
||||
xhr.open('GET', url + test.part);
|
||||
} catch(e) {
|
||||
ok(test.revoke, "This should fail!");
|
||||
runTest();
|
||||
return;
|
||||
}
|
||||
|
||||
xhr.onload = function() {
|
||||
is(xhr.responseText, 'hello world', 'URL: ' + url + test.part);
|
||||
runTest();
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.send();
|
||||
} catch(e) {
|
||||
ok(test.revoke, "This should fail!");
|
||||
runTest();
|
||||
return;
|
||||
}
|
||||
ok(!test.revoke, "This should succeed!");
|
||||
}
|
||||
|
||||
|
||||
@@ -497,6 +497,7 @@ WifiGeoPositionProvider.prototype = {
|
||||
|
||||
try {
|
||||
xhr.open("POST", url, true);
|
||||
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
|
||||
} catch (e) {
|
||||
this.notifyListener("notifyError",
|
||||
[POSITION_UNAVAILABLE]);
|
||||
@@ -505,7 +506,6 @@ WifiGeoPositionProvider.prototype = {
|
||||
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
xhr.responseType = "json";
|
||||
xhr.mozBackgroundRequest = true;
|
||||
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
|
||||
xhr.timeout = Services.prefs.getIntPref("geo.wifi.xhr.timeout");
|
||||
xhr.ontimeout = (function() {
|
||||
LOG("Location request XHR timed out.")
|
||||
|
||||
@@ -1526,11 +1526,11 @@ XMLHttpRequestMainThread::OpenInternal(const nsACString& aMethod,
|
||||
mFlagAborted = false;
|
||||
mFlagTimedOut = false;
|
||||
|
||||
// The channel should really be created on send(), but we have a chrome-only
|
||||
// XHR.channel API which necessitates creating the channel now, while doing
|
||||
// the rest of the channel-setup later at send-time.
|
||||
rv = CreateChannel();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Per spec we should only create the channel on send(), but we have internal
|
||||
// code that relies on the channel being created now, and that code is not
|
||||
// always IsSystemXHR(). However, we're not supposed to throw channel-creation
|
||||
// errors during open(), so we silently ignore those here.
|
||||
CreateChannel();
|
||||
|
||||
// Step 12
|
||||
if (mState != State::opened) {
|
||||
@@ -2632,7 +2632,7 @@ XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
|
||||
|
||||
// Per spec, we throw on sync errors, but not async.
|
||||
if (mFlagSynchronous) {
|
||||
return rv;
|
||||
return NS_ERROR_DOM_NETWORK_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2724,19 +2724,25 @@ XMLHttpRequestMainThread::SendInternal(const RequestBodyBase* aBody)
|
||||
{
|
||||
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
PopulateNetworkInterfaceId();
|
||||
// Steps 1 and 2
|
||||
if (mState != State::opened || mFlagSend) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsresult rv = CheckInnerWindowCorrectness();
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
if (mState != State::opened || // Step 1
|
||||
mFlagSend || // Step 2
|
||||
!mChannel) { // Gecko-specific
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
// If open() failed to create the channel, then throw a network error
|
||||
// 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;
|
||||
}
|
||||
|
||||
PopulateNetworkInterfaceId();
|
||||
|
||||
// XXX We should probably send a warning to the JS console
|
||||
// if there are no event listeners set and we are doing
|
||||
// an asynchronous call.
|
||||
@@ -2893,7 +2899,7 @@ XMLHttpRequestMainThread::SendInternal(const RequestBodyBase* aBody)
|
||||
if (!mChannel) {
|
||||
// Per spec, silently fail on async request failures; throw for sync.
|
||||
if (mFlagSynchronous) {
|
||||
return NS_ERROR_FAILURE;
|
||||
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.
|
||||
|
||||
@@ -181,7 +181,6 @@ function getHSTSStatus(host, resultList) {
|
||||
var uri = "https://" + host.name + "/";
|
||||
req.open("GET", uri, true);
|
||||
req.timeout = REQUEST_TIMEOUT;
|
||||
req.channel.notificationCallbacks = new RedirectAndAuthStopper();
|
||||
|
||||
let errorhandler = (evt) => {
|
||||
dump(`ERROR: error making request to ${host.name} (type=${evt.type})\n`);
|
||||
@@ -205,6 +204,7 @@ function getHSTSStatus(host, resultList) {
|
||||
};
|
||||
|
||||
try {
|
||||
req.channel.notificationCallbacks = new RedirectAndAuthStopper();
|
||||
req.send();
|
||||
}
|
||||
catch (e) {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
[send-after-setting-document-domain.htm]
|
||||
type: testharness
|
||||
expected: ERROR
|
||||
[loading documents from the origin document.domain was set to should throw]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[send-authentication-basic-cors-not-enabled.htm]
|
||||
type: testharness
|
||||
[XMLHttpRequest: send() - "Basic" authenticated CORS requests with user name and password passed to open() (asserts failure)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
[send-non-same-origin.sub.htm]
|
||||
type: testharness
|
||||
[XMLHttpRequest: send() - non same-origin (mailto:test@example.org)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: send() - non same-origin (tel:+31600000000)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: send() - non same-origin (http://www2.web-platform.test:8000/)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: send() - non same-origin (javascript:alert('FAIL'))]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: send() - non same-origin (folder.txt)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
[send-redirect-bogus-sync.htm]
|
||||
type: testharness
|
||||
[XMLHttpRequest: send() - Redirects (bogus Location header; sync) (301: foobar://abcd)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: send() - Redirects (bogus Location header; sync) (302: http://z)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: send() - Redirects (bogus Location header; sync) (302: mailto:someone@example.org)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: send() - Redirects (bogus Location header; sync) (303: http://z)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: send() - Redirects (bogus Location header; sync) (303: tel:1234567890)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[send-redirect-infinite-sync.htm]
|
||||
type: testharness
|
||||
[XMLHttpRequest: send() - Redirects (infinite loop; sync) (301)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[xmlhttprequest-network-error-sync.htm]
|
||||
type: testharness
|
||||
[XMLHttpRequest: members during network errors (sync)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>XMLHttpRequest: send() with document.domain set: loading documents from original origin after setting document.domain</title>
|
||||
<script src="send-after-setting-document-domain-window-helper.js"></script>
|
||||
<link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[3]" />
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
run_test(function() {
|
||||
document.domain = document.domain; // this is not a noop, it does actually change the security context
|
||||
var client = new XMLHttpRequest();
|
||||
client.open("GET", "status.py?content=hello", false);
|
||||
client.send(null);
|
||||
assert_equals(client.responseText, "hello");
|
||||
document.domain = document.domain.replace(/^\w+\./, "");
|
||||
client.open("GET", "status.py?content=hello2", false);
|
||||
client.send(null);
|
||||
assert_equals(client.responseText, "hello2");
|
||||
}, "loading documents from original origin after setting document.domain");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>XMLHttpRequest: send() with document.domain set: loading documents from the origin document.domain was set to should throw</title>
|
||||
<script src="send-after-setting-document-domain-window-helper.js"></script>
|
||||
<link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[3]" />
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
run_test(function() {
|
||||
document.domain = document.domain.replace(/^\w+\./, "");
|
||||
var client = new XMLHttpRequest();
|
||||
client.open("GET", location.protocol + "//" + document.domain + location.pathname.replace(/[^\/]*$/, "") + "status.py?content=hello3", false);
|
||||
assert_throws("NetworkError", function() {
|
||||
client.send(null);
|
||||
});
|
||||
}, "loading documents from the origin document.domain was set to should throw");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,29 @@
|
||||
function assert_equals(value, expected) {
|
||||
if (value != expected) {
|
||||
throw "Got wrong value.\nExpected '" + expected + "',\ngot '" + value + "'";
|
||||
}
|
||||
}
|
||||
|
||||
function assert_throws(expected_exc, func) {
|
||||
try {
|
||||
func.call(this);
|
||||
} catch(e) {
|
||||
var actual = e.name || e.type;
|
||||
if (actual != expected_exc) {
|
||||
throw "Got wrong exception.\nExpected '" + expected_exc + "',\ngot '" + actual + "'.";
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw "Expected exception, but none was thrown";
|
||||
}
|
||||
|
||||
function run_test(test, name) {
|
||||
var result = {passed: true, message: null, name: name};
|
||||
try {
|
||||
test();
|
||||
} catch(e) {
|
||||
result.passed = false;
|
||||
result.message = e + "";
|
||||
}
|
||||
opener.postMessage(result, "*");
|
||||
}
|
||||
@@ -4,35 +4,36 @@
|
||||
<title>XMLHttpRequest: send() with document.domain set</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<!-- The spec doesn't seem to explicitly cover this case (as of June 2013) -->
|
||||
<link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[3]" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
// first make sure we actually run off a domain with at least three parts, in order to be able to shorten it..
|
||||
if (location.hostname.split(/\./).length < 3) {
|
||||
location.href = location.protocol+'//www2.'+location.host+location.pathname
|
||||
}
|
||||
var test_base_url = location.protocol+'//www2.'+location.host+"/XMLHttpRequest/resources/",
|
||||
test_windows = [
|
||||
window.open(test_base_url + "send-after-setting-document-domain-window-1.htm"),
|
||||
window.open(test_base_url + "send-after-setting-document-domain-window-2.htm"),
|
||||
],
|
||||
num_tests_left = test_windows.length;
|
||||
|
||||
test(function() {
|
||||
document.domain = document.domain // this is not a noop, it does actually change the security context
|
||||
var client = new XMLHttpRequest()
|
||||
client.open("GET", "resources/status.py?content=hello", false)
|
||||
client.send(null)
|
||||
assert_equals(client.responseText, "hello")
|
||||
document.domain = document.domain.replace(/^\w+\./, '')
|
||||
client.open("GET", "resources/status.py?content=hello2", false)
|
||||
client.send(null)
|
||||
assert_equals(client.responseText, "hello2")
|
||||
}, "loading documents from original origin after setting document.domain")
|
||||
// try to load a document from the origin document.domain was set to
|
||||
test(function () {
|
||||
var client = new XMLHttpRequest()
|
||||
client.open("GET", location.protocol + '//' + document.domain + location.pathname.replace(/[^\/]*$/, '') + "resources/status.py?content=hello3", false)
|
||||
// AFAIK this should throw
|
||||
assert_throws('NetworkError', function(){client.send(null)})
|
||||
}, "loading documents from the origin document.domain was set to should throw")
|
||||
async_test(function(wrapper_test) {
|
||||
window.addEventListener("message", function(evt) {
|
||||
// run a shadow test that just forwards the results
|
||||
async_test(function(test) {
|
||||
assert_true(evt.data.passed, evt.data.message);
|
||||
test.done();
|
||||
}, evt.data.name);
|
||||
|
||||
// after last result comes in, close all test
|
||||
// windows and complete the wrapper test.
|
||||
if (--num_tests_left == 0) {
|
||||
for (var i=0; i<test_windows.length; ++i) {
|
||||
test_windows[i].close();
|
||||
}
|
||||
wrapper_test.done();
|
||||
}
|
||||
}, false);
|
||||
}, "All tests ran");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -221,10 +221,10 @@ function downloadFile(url) {
|
||||
xhr.responseType = "arraybuffer";
|
||||
try {
|
||||
xhr.open("GET", url);
|
||||
xhr.send(null);
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
xhr.send(null);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user