summaryrefslogtreecommitdiffstats
path: root/dom/xhr/tests
diff options
context:
space:
mode:
Diffstat (limited to 'dom/xhr/tests')
-rw-r--r--dom/xhr/tests/browser.ini5
-rw-r--r--dom/xhr/tests/browser_xhr_onchange_leak.html25
-rw-r--r--dom/xhr/tests/browser_xhr_onchange_leak.js23
-rw-r--r--dom/xhr/tests/common_temporaryFileBlob.js100
-rw-r--r--dom/xhr/tests/echo.sjs21
-rw-r--r--dom/xhr/tests/empty.html0
-rw-r--r--dom/xhr/tests/file_XHRDocURI.html9
-rw-r--r--dom/xhr/tests/file_XHRDocURI.html^headers^3
-rw-r--r--dom/xhr/tests/file_XHRDocURI.sjs13
-rw-r--r--dom/xhr/tests/file_XHRDocURI.text1
-rw-r--r--dom/xhr/tests/file_XHRDocURI.text^headers^3
-rw-r--r--dom/xhr/tests/file_XHRDocURI.xml1
-rw-r--r--dom/xhr/tests/file_XHRDocURI.xml^headers^3
-rw-r--r--dom/xhr/tests/file_XHRResponseURL.js303
-rw-r--r--dom/xhr/tests/file_XHRResponseURL.sjs14
-rw-r--r--dom/xhr/tests/file_XHRResponseURL.text1
-rw-r--r--dom/xhr/tests/file_XHRResponseURL.text^headers^3
-rw-r--r--dom/xhr/tests/file_XHRResponseURL_nocors.text1
-rw-r--r--dom/xhr/tests/file_XHRSendData.sjs30
-rw-r--r--dom/xhr/tests/file_XHRSendData_doc.xml2
-rw-r--r--dom/xhr/tests/file_XHRSendData_doc.xml^headers^1
-rw-r--r--dom/xhr/tests/file_XHR_anon.sjs24
-rw-r--r--dom/xhr/tests/file_XHR_binary1.binbin0 -> 12 bytes
-rw-r--r--dom/xhr/tests/file_XHR_binary1.bin^headers^1
-rw-r--r--dom/xhr/tests/file_XHR_binary2.binbin0 -> 65536 bytes
-rw-r--r--dom/xhr/tests/file_XHR_fail1.txt1
-rw-r--r--dom/xhr/tests/file_XHR_fail1.txt^headers^2
-rw-r--r--dom/xhr/tests/file_XHR_fail1b.txt1
-rw-r--r--dom/xhr/tests/file_XHR_header.sjs6
-rw-r--r--dom/xhr/tests/file_XHR_pass1.xml1
-rw-r--r--dom/xhr/tests/file_XHR_pass2.txt1
-rw-r--r--dom/xhr/tests/file_XHR_pass3.txt1
-rw-r--r--dom/xhr/tests/file_XHR_pass3.txt^headers^2
-rw-r--r--dom/xhr/tests/file_XHR_system_redirect.html5
-rw-r--r--dom/xhr/tests/file_XHR_system_redirect.html^headers^2
-rw-r--r--dom/xhr/tests/file_XHR_timeout.sjs15
-rw-r--r--dom/xhr/tests/file_html_in_xhr.html16
-rw-r--r--dom/xhr/tests/file_html_in_xhr.sjs15
-rw-r--r--dom/xhr/tests/file_html_in_xhr2.html1
-rw-r--r--dom/xhr/tests/file_html_in_xhr3.html1
-rw-r--r--dom/xhr/tests/file_sync_xhr_document_write_with_iframe.html21
-rw-r--r--dom/xhr/tests/iframe_sync_xhr_unload.html18
-rw-r--r--dom/xhr/tests/mochitest.ini115
-rw-r--r--dom/xhr/tests/progressserver.sjs52
-rw-r--r--dom/xhr/tests/relativeLoad_import.js5
-rw-r--r--dom/xhr/tests/relativeLoad_worker.js27
-rw-r--r--dom/xhr/tests/relativeLoad_worker2.js9
-rw-r--r--dom/xhr/tests/responseIdentical.sjs17
-rw-r--r--dom/xhr/tests/subdir/relativeLoad_sub_import.js5
-rw-r--r--dom/xhr/tests/subdir/relativeLoad_sub_worker.js26
-rw-r--r--dom/xhr/tests/subdir/relativeLoad_sub_worker2.js9
-rw-r--r--dom/xhr/tests/sync_xhr_unload.sjs15
-rw-r--r--dom/xhr/tests/temporaryFileBlob.sjs33
-rw-r--r--dom/xhr/tests/terminateSyncXHR_worker.js19
-rw-r--r--dom/xhr/tests/test_XHR.html393
-rw-r--r--dom/xhr/tests/test_XHRDocURI.html513
-rw-r--r--dom/xhr/tests/test_XHRResponseURL.html69
-rw-r--r--dom/xhr/tests/test_XHRSendData.html267
-rw-r--r--dom/xhr/tests/test_XHR_anon.html180
-rw-r--r--dom/xhr/tests/test_XHR_header.html31
-rw-r--r--dom/xhr/tests/test_XHR_onuploadprogress.html40
-rw-r--r--dom/xhr/tests/test_XHR_parameters.html97
-rw-r--r--dom/xhr/tests/test_XHR_system.html99
-rw-r--r--dom/xhr/tests/test_XHR_timeout.html60
-rw-r--r--dom/xhr/tests/test_XHR_timeout.js342
-rw-r--r--dom/xhr/tests/test_bug1300552.html29
-rw-r--r--dom/xhr/tests/test_html_in_xhr.html113
-rw-r--r--dom/xhr/tests/test_relativeLoad.html52
-rw-r--r--dom/xhr/tests/test_sync_xhr_document_write_with_iframe.html28
-rw-r--r--dom/xhr/tests/test_sync_xhr_timer.xhtml52
-rw-r--r--dom/xhr/tests/test_sync_xhr_unload.html36
-rw-r--r--dom/xhr/tests/test_temporaryFileBlob.html40
-rw-r--r--dom/xhr/tests/test_worker_terminateSyncXHR.html45
-rw-r--r--dom/xhr/tests/test_worker_xhr.html73
-rw-r--r--dom/xhr/tests/test_worker_xhr2.html38
-rw-r--r--dom/xhr/tests/test_worker_xhrAbort.html44
-rw-r--r--dom/xhr/tests/test_worker_xhr_3rdparty.html74
-rw-r--r--dom/xhr/tests/test_worker_xhr_cors_redirect.html35
-rw-r--r--dom/xhr/tests/test_worker_xhr_headers.html86
-rw-r--r--dom/xhr/tests/test_worker_xhr_implicit_cancel.html44
-rw-r--r--dom/xhr/tests/test_worker_xhr_parameters.html64
-rw-r--r--dom/xhr/tests/test_worker_xhr_parameters.js75
-rw-r--r--dom/xhr/tests/test_worker_xhr_responseURL.html76
-rw-r--r--dom/xhr/tests/test_worker_xhr_system.html52
-rw-r--r--dom/xhr/tests/test_worker_xhr_system.js30
-rw-r--r--dom/xhr/tests/test_worker_xhr_timeout.html58
-rw-r--r--dom/xhr/tests/test_xhr_abort_after_load.html96
-rw-r--r--dom/xhr/tests/test_xhr_forbidden_headers.html96
-rw-r--r--dom/xhr/tests/test_xhr_overridemimetype_throws_on_invalid_state.html61
-rw-r--r--dom/xhr/tests/test_xhr_progressevents.html333
-rw-r--r--dom/xhr/tests/test_xhr_send.html83
-rw-r--r--dom/xhr/tests/test_xhr_send_readystate.html39
-rw-r--r--dom/xhr/tests/test_xhr_withCredentials.html35
-rw-r--r--dom/xhr/tests/worker_bug1300552.js33
-rw-r--r--dom/xhr/tests/worker_file_getcookie.sjs15
-rw-r--r--dom/xhr/tests/worker_temporaryFileBlob.js29
-rw-r--r--dom/xhr/tests/worker_terminateSyncXHR_frame.html25
-rw-r--r--dom/xhr/tests/worker_testXHR.txt1
-rw-r--r--dom/xhr/tests/worker_xhr_cors_redirect.js10
-rw-r--r--dom/xhr/tests/worker_xhr_cors_redirect.sjs10
-rw-r--r--dom/xhr/tests/worker_xhr_headers_server.sjs66
-rw-r--r--dom/xhr/tests/worker_xhr_headers_worker.js16
-rw-r--r--dom/xhr/tests/xhr2_worker.js163
-rw-r--r--dom/xhr/tests/xhrAbort_worker.js92
-rw-r--r--dom/xhr/tests/xhr_implicit_cancel_worker.js10
-rw-r--r--dom/xhr/tests/xhr_worker.js84
106 files changed, 5560 insertions, 0 deletions
diff --git a/dom/xhr/tests/browser.ini b/dom/xhr/tests/browser.ini
new file mode 100644
index 000000000..6bf9a3fc8
--- /dev/null
+++ b/dom/xhr/tests/browser.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+support-files =
+ browser_xhr_onchange_leak.html
+[browser_blobFromFile.js]
+[browser_xhr_onchange_leak.js] \ No newline at end of file
diff --git a/dom/xhr/tests/browser_xhr_onchange_leak.html b/dom/xhr/tests/browser_xhr_onchange_leak.html
new file mode 100644
index 000000000..56eb45533
--- /dev/null
+++ b/dom/xhr/tests/browser_xhr_onchange_leak.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test page for https://bugzilla.mozilla.org/show_bug.cgi?id=1336811
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test page for Bug 1336811</title>
+</head>
+<body onload="onload();">
+<p><span id="samplepage">sample page</span></p>
+<script type="application/javascript">
+ function onload() {
+ var request = new XMLHttpRequest;
+ request.open("GET", "about:blank");
+ request.onreadystatechange = function() {
+ request.foo = request;
+ }
+ request.foo = request;
+ request.send();
+ request.foo = request;
+ }
+</script>
+</body>
+</html>
diff --git a/dom/xhr/tests/browser_xhr_onchange_leak.js b/dom/xhr/tests/browser_xhr_onchange_leak.js
new file mode 100644
index 000000000..f4dbb7e3e
--- /dev/null
+++ b/dom/xhr/tests/browser_xhr_onchange_leak.js
@@ -0,0 +1,23 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+// Bug 1336811 - An XHR that has a .onreadystatechange waiting should
+// not leak forever once the tab is closed. CC optimizations need to be
+// turned off once it is closed.
+
+add_task(function* test() {
+ const url = "http://mochi.test:8888/browser/dom/xhr/tests/browser_xhr_onchange_leak.html";
+ let newTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+ let browser = gBrowser.selectedBrowser;
+ let done = yield ContentTask.spawn(browser,{}, function*(browser){
+ let doc = content.document;
+ let promise = ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", true);
+ content.location = "about:home";
+ yield promise;
+ return true;
+ });
+ is(done, true, "need to check something");
+ yield BrowserTestUtils.removeTab(newTab);
+});
diff --git a/dom/xhr/tests/common_temporaryFileBlob.js b/dom/xhr/tests/common_temporaryFileBlob.js
new file mode 100644
index 000000000..81a66238d
--- /dev/null
+++ b/dom/xhr/tests/common_temporaryFileBlob.js
@@ -0,0 +1,100 @@
+var data = new Array(256).join("1234567890ABCDEF");
+
+function createXHR() {
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", "temporaryFileBlob.sjs");
+ xhr.responseType = 'blob';
+ xhr.send({toString: function() { return data; }});
+ return xhr;
+}
+
+function test_simple() {
+ info("Simple test");
+
+ var xhr = createXHR();
+
+ xhr.onloadend = function() {
+ ok(xhr.response instanceof Blob, "We have a blob!");
+ is(xhr.response.size, data.length, "Data length matches");
+
+ var fr = new FileReader();
+ fr.readAsText(xhr.response);
+ fr.onload = function() {
+ is(fr.result, data, "Data content matches");
+ next();
+ }
+ }
+}
+
+function test_abort() {
+ info("Aborting during onloading");
+
+ var xhr = createXHR();
+
+ xhr.onprogress = function() {
+ xhr.abort();
+ }
+
+ xhr.onloadend = function() {
+ ok(!xhr.response, "We should not have a Blob!");
+ next();
+ }
+}
+
+function test_reuse() {
+ info("Reuse test");
+
+ var xhr = createXHR();
+
+ var count = 0;
+ xhr.onloadend = function() {
+ ok(xhr.response instanceof Blob, "We have a blob!");
+ is(xhr.response.size, data.length, "Data length matches");
+
+ var fr = new FileReader();
+ fr.readAsText(xhr.response);
+ fr.onload = function() {
+ is(fr.result, data, "Data content matches");
+ if (++count > 2) {
+ next();
+ return;
+ }
+
+ xhr.open("POST", "temporaryFileBlob.sjs");
+ xhr.responseType = 'blob';
+ xhr.send({toString: function() { return data; }});
+ }
+ }
+}
+
+function test_worker_generic(test) {
+ var w = new Worker('worker_temporaryFileBlob.js');
+ w.onmessage = function(e) {
+ if (e.data.type == 'info') {
+ info(e.data.msg);
+ } else if (e.data.type == 'check') {
+ ok(e.data.what, e.data.msg);
+ } else if (e.data.type == 'finish') {
+ next();
+ } else {
+ ok(false, 'Something wrong happened');
+ }
+ }
+
+ w.postMessage(test);
+}
+
+function test_worker() {
+ info("XHR in workers");
+ test_worker_generic('simple');
+}
+
+function test_worker_abort() {
+ info("XHR in workers");
+ test_worker_generic('abort');
+}
+
+function test_worker_reuse() {
+ info("XHR in workers");
+ test_worker_generic('reuse');
+}
diff --git a/dom/xhr/tests/echo.sjs b/dom/xhr/tests/echo.sjs
new file mode 100644
index 000000000..6e3242c9f
--- /dev/null
+++ b/dom/xhr/tests/echo.sjs
@@ -0,0 +1,21 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function handleRequest(request, response)
+{
+ response.setHeader("Content-Type", "text/plain");
+ if (request.method == "GET") {
+ response.write(request.queryString);
+ return;
+ }
+
+ var bodyStream = new BinaryInputStream(request.bodyInputStream);
+ var body = "";
+ var bodyAvail;
+ while ((bodyAvail = bodyStream.available()) > 0)
+ body += String.fromCharCode.apply(null, bodyStream.readByteArray(bodyAvail));
+
+ response.write(body);
+}
diff --git a/dom/xhr/tests/empty.html b/dom/xhr/tests/empty.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/dom/xhr/tests/empty.html
diff --git a/dom/xhr/tests/file_XHRDocURI.html b/dom/xhr/tests/file_XHRDocURI.html
new file mode 100644
index 000000000..8dbbb0549
--- /dev/null
+++ b/dom/xhr/tests/file_XHRDocURI.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest return document URIs</title>
+ </head>
+ <body>
+ <div id="data">data</div>
+ </body>
+</html>
diff --git a/dom/xhr/tests/file_XHRDocURI.html^headers^ b/dom/xhr/tests/file_XHRDocURI.html^headers^
new file mode 100644
index 000000000..ddfd8c0a9
--- /dev/null
+++ b/dom/xhr/tests/file_XHRDocURI.html^headers^
@@ -0,0 +1,3 @@
+HTTP 200 OK
+Access-Control-Allow-Origin: *
+Content-Type: text/html
diff --git a/dom/xhr/tests/file_XHRDocURI.sjs b/dom/xhr/tests/file_XHRDocURI.sjs
new file mode 100644
index 000000000..275b1e96e
--- /dev/null
+++ b/dom/xhr/tests/file_XHRDocURI.sjs
@@ -0,0 +1,13 @@
+function handleRequest(aRequest, aResponse)
+{
+ var url = aRequest.queryString.match(/\burl=([^#&]*)/);
+ if (!url) {
+ aResponse.setStatusLine(aRequest.httpVersion, 404, "Not Found");
+ return;
+ }
+
+ url = decodeURIComponent(url[1]);
+ aResponse.setStatusLine(aRequest.httpVersion, 302, "Found");
+ aResponse.setHeader("Cache-Control", "no-cache", false);
+ aResponse.setHeader("Location", url, false);
+}
diff --git a/dom/xhr/tests/file_XHRDocURI.text b/dom/xhr/tests/file_XHRDocURI.text
new file mode 100644
index 000000000..c1dead8d7
--- /dev/null
+++ b/dom/xhr/tests/file_XHRDocURI.text
@@ -0,0 +1 @@
+<res>data</res>
diff --git a/dom/xhr/tests/file_XHRDocURI.text^headers^ b/dom/xhr/tests/file_XHRDocURI.text^headers^
new file mode 100644
index 000000000..b2fe7cdeb
--- /dev/null
+++ b/dom/xhr/tests/file_XHRDocURI.text^headers^
@@ -0,0 +1,3 @@
+HTTP 200 OK
+Access-Control-Allow-Origin: *
+Content-Type: text/plain
diff --git a/dom/xhr/tests/file_XHRDocURI.xml b/dom/xhr/tests/file_XHRDocURI.xml
new file mode 100644
index 000000000..c1a9a5256
--- /dev/null
+++ b/dom/xhr/tests/file_XHRDocURI.xml
@@ -0,0 +1 @@
+<res xml:base="http://www.example.com/">data</res>
diff --git a/dom/xhr/tests/file_XHRDocURI.xml^headers^ b/dom/xhr/tests/file_XHRDocURI.xml^headers^
new file mode 100644
index 000000000..f47804337
--- /dev/null
+++ b/dom/xhr/tests/file_XHRDocURI.xml^headers^
@@ -0,0 +1,3 @@
+HTTP 200 OK
+Access-Control-Allow-Origin: *
+Content-Type: application/xml
diff --git a/dom/xhr/tests/file_XHRResponseURL.js b/dom/xhr/tests/file_XHRResponseURL.js
new file mode 100644
index 000000000..7c48201b2
--- /dev/null
+++ b/dom/xhr/tests/file_XHRResponseURL.js
@@ -0,0 +1,303 @@
+"use strict";
+
+// utility functions for worker/window communication
+
+function isInWorker() {
+ try {
+ return !(self instanceof Window);
+ } catch (e) {
+ return true;
+ }
+}
+
+function message(aData) {
+ if (isInWorker()) {
+ self.postMessage(aData);
+ } else {
+ self.postMessage(aData, "*");
+ }
+}
+message.ping = 0;
+message.pong = 0;
+
+function is(aActual, aExpected, aMessage) {
+ var obj = {
+ type: "is",
+ actual: aActual,
+ expected: aExpected,
+ message: aMessage
+ };
+ ++message.ping;
+ message(obj);
+}
+
+function ok(aBool, aMessage) {
+ var obj = {
+ type: "ok",
+ bool: aBool,
+ message: aMessage
+ };
+ ++message.ping;
+ message(obj);
+}
+
+function info(aMessage) {
+ var obj = {
+ type: "info",
+ message: aMessage
+ };
+ ++message.ping;
+ message(obj);
+}
+
+function request(aURL) {
+ return new Promise(function (aResolve, aReject) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", aURL);
+ xhr.addEventListener("load", function () {
+ xhr.succeeded = true;
+ aResolve(xhr);
+ });
+ xhr.addEventListener("error", function () {
+ xhr.succeeded = false;
+ aResolve(xhr);
+ });
+ xhr.send();
+ });
+}
+
+function createSequentialRequest(aParameters, aTest) {
+ var sequence = aParameters.reduce(function (aPromise, aParam) {
+ return aPromise.then(function () {
+ return request(aParam.requestURL);
+ }).then(function (aXHR) {
+ return aTest(aXHR, aParam);
+ });
+ }, Promise.resolve());
+
+ return sequence;
+}
+
+function testSuccessResponse() {
+ var blob = new Blob(["data"], {type: "text/plain"});
+ var blobURL = URL.createObjectURL(blob);
+
+ var parameters = [
+ // tests that start with same-origin request
+ {
+ message: "request to same-origin without redirect",
+ requestURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ responseURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text"
+ },
+ {
+ message: "request to same-origin redirect to same-origin URL",
+ requestURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ responseURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text"
+ },
+ {
+ message: "request to same-origin redirects several times and finally go to same-origin URL",
+ requestURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text"),
+ responseURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text"
+ },
+ {
+ message: "request to same-origin redirect to cross-origin URL",
+ requestURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ responseURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ },
+ {
+ message: "request to same-origin redirects several times and finally go to cross-origin URL",
+ requestURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text"),
+ responseURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ },
+
+ // tests that start with cross-origin request
+ {
+ message: "request to cross-origin without redirect",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ responseURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text"
+ },
+ {
+ message: "request to cross-origin redirect back to same-origin URL",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ responseURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text"
+ },
+ {
+ message: "request to cross-origin redirect to the same cross-origin URL",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ responseURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ },
+ {
+ message: "request to cross-origin redirect to another cross-origin URL",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ responseURL: "http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ },
+ {
+ message: "request to cross-origin redirects several times and finally go to same-origin URL",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text"),
+ responseURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ },
+ {
+ message: "request to cross-origin redirects several times and finally go to the same cross-origin URL",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text"),
+ responseURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ },
+ {
+ message: "request to cross-origin redirects several times and finally go to another cross-origin URL",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text"),
+ responseURL: "http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ },
+ {
+ message: "request to cross-origin redirects to another cross-origin and finally go to the other cross-origin URL",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://test1.example.com/tests/dom/xhr/tests/file_XHRResponseURL.text"),
+ responseURL: "http://test1.example.com/tests/dom/xhr/tests/file_XHRResponseURL.text",
+ },
+ {
+ message: "request URL has fragment",
+ requestURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text#fragment",
+ responseURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text"
+ },
+
+ // tests for non-http(s) URL
+ {
+ message: "request to data: URL",
+ requestURL: "data:text/plain,data",
+ responseURL: "data:text/plain,data"
+ },
+ {
+ message: "request to blob: URL",
+ requestURL: blobURL,
+ responseURL: blobURL
+ }
+ ];
+
+ var sequence = createSequentialRequest(parameters, function (aXHR, aParam) {
+ ok(aXHR.succeeded, "assert request succeeded");
+ is(aXHR.responseURL, aParam.responseURL, aParam.message);
+ });
+
+ sequence.then(function () {
+ URL.revokeObjectURL(blobURL);
+ });
+
+ return sequence;
+}
+
+function testFailedResponse() {
+ info("test not to leak responseURL for denied cross-origin request");
+ var parameters = [
+ {
+ message: "should be empty for denied cross-origin request without redirect",
+ requestURL: "http://example.com/tests/dom/xhr/tests/file_XHRResponseURL_nocors.text"
+ },
+ {
+ message: "should be empty for denied cross-origin request with redirect",
+ requestURL: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL_nocors.text"
+ }
+ ];
+
+ var sequence = createSequentialRequest(parameters, function (aXHR, aParam) {
+ ok(!aXHR.succeeded, "assert request failed");
+ is(aXHR.responseURL, "" , aParam.message);
+ });
+
+ return sequence;
+}
+
+function testNotToLeakResponseURLWhileDoingRedirects() {
+ info("test not to leak responeseURL while doing redirects");
+
+ if (isInWorker()) {
+ return testNotToLeakResponseURLWhileDoingRedirectsInWorker();
+ } else {
+ return testNotToLeakResponseURLWhileDoingRedirectsInWindow();
+ }
+}
+
+function testNotToLeakResponseURLWhileDoingRedirectsInWindow() {
+ var xhr = new XMLHttpRequest();
+ var requestObserver = {
+ observe: function (aSubject, aTopic, aData) {
+ is(xhr.readyState, XMLHttpRequest.OPENED, "assert for XHR state");
+ is(xhr.responseURL, "",
+ "responseURL should return empty string before HEADERS_RECEIVED");
+ }
+ };
+ SpecialPowers.addObserver(requestObserver, "specialpowers-http-notify-request", false);
+
+ return new Promise(function (aResolve, aReject) {
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text");
+ xhr.addEventListener("load", function () {
+ SpecialPowers.removeObserver(requestObserver, "specialpowers-http-notify-request");
+ aResolve();
+ });
+ xhr.addEventListener("error", function () {
+ ok(false, "unexpected request falilure");
+ SpecialPowers.removeObserver(requestObserver, "specialpowers-http-notify-request");
+ aResolve();
+ });
+ xhr.send();
+ });
+}
+
+function testNotToLeakResponseURLWhileDoingRedirectsInWorker() {
+ var xhr = new XMLHttpRequest();
+ var testRedirect = function (e) {
+ if (e.data === "request" && xhr.readyState === XMLHttpRequest.OPENED) {
+ is(xhr.responseURL, "",
+ "responseURL should return empty string before HEADERS_RECEIVED");
+ }
+ };
+
+ return new Promise(function (aResolve, aReject) {
+ self.addEventListener("message", testRedirect);
+ message({type: "redirect_test", status: "start"});
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text");
+ xhr.addEventListener("load", function () {
+ self.removeEventListener("message", testRedirect);
+ message({type: "redirect_test", status: "end"});
+ aResolve();
+ });
+ xhr.addEventListener("error", function (e) {
+ ok(false, "unexpected request falilure");
+ self.removeEventListener("message", testRedirect);
+ message({type: "redirect_test", status: "end"});
+ aResolve();
+ });
+ xhr.send();
+ });
+}
+
+function waitForAllMessagesProcessed() {
+ return new Promise(function (aResolve, aReject) {
+ var id = setInterval(function () {
+ if (message.ping === message.pong) {
+ clearInterval(id);
+ aResolve();
+ }
+ }, 100);
+ });
+}
+
+
+self.addEventListener("message", function (aEvent) {
+ if (aEvent.data === "start") {
+ ok("responseURL" in (new XMLHttpRequest()),
+ "XMLHttpRequest should have responseURL attribute");
+ is((new XMLHttpRequest()).responseURL, "",
+ "responseURL should be empty string if response's url is null");
+
+ var promise = testSuccessResponse();
+ promise.then(function () {
+ return testFailedResponse();
+ }).then(function () {
+ return testNotToLeakResponseURLWhileDoingRedirects();
+ }).then(function () {
+ return waitForAllMessagesProcessed();
+ }).then(function () {
+ message("done");
+ });
+ }
+ if (aEvent.data === "pong") {
+ ++message.pong;
+ }
+});
diff --git a/dom/xhr/tests/file_XHRResponseURL.sjs b/dom/xhr/tests/file_XHRResponseURL.sjs
new file mode 100644
index 000000000..5ac0a346c
--- /dev/null
+++ b/dom/xhr/tests/file_XHRResponseURL.sjs
@@ -0,0 +1,14 @@
+function handleRequest(aRequest, aResponse)
+{
+ var url = aRequest.queryString.match(/\burl=([^#&]*)/);
+ if (!url) {
+ aResponse.setStatusLine(aRequest.httpVersion, 404, "Not Found");
+ return;
+ }
+ url = decodeURIComponent(url[1]);
+
+ aResponse.setStatusLine(aRequest.httpVersion, 302, "Found");
+ aResponse.setHeader("Access-Control-Allow-Origin", "*", false);
+ aResponse.setHeader("Cache-Control", "no-cache", false);
+ aResponse.setHeader("Location", url, false);
+}
diff --git a/dom/xhr/tests/file_XHRResponseURL.text b/dom/xhr/tests/file_XHRResponseURL.text
new file mode 100644
index 000000000..1269488f7
--- /dev/null
+++ b/dom/xhr/tests/file_XHRResponseURL.text
@@ -0,0 +1 @@
+data
diff --git a/dom/xhr/tests/file_XHRResponseURL.text^headers^ b/dom/xhr/tests/file_XHRResponseURL.text^headers^
new file mode 100644
index 000000000..b2fe7cdeb
--- /dev/null
+++ b/dom/xhr/tests/file_XHRResponseURL.text^headers^
@@ -0,0 +1,3 @@
+HTTP 200 OK
+Access-Control-Allow-Origin: *
+Content-Type: text/plain
diff --git a/dom/xhr/tests/file_XHRResponseURL_nocors.text b/dom/xhr/tests/file_XHRResponseURL_nocors.text
new file mode 100644
index 000000000..1269488f7
--- /dev/null
+++ b/dom/xhr/tests/file_XHRResponseURL_nocors.text
@@ -0,0 +1 @@
+data
diff --git a/dom/xhr/tests/file_XHRSendData.sjs b/dom/xhr/tests/file_XHRSendData.sjs
new file mode 100644
index 000000000..0ccbe8a45
--- /dev/null
+++ b/dom/xhr/tests/file_XHRSendData.sjs
@@ -0,0 +1,30 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function handleRequest(request, response)
+{
+ if (request.hasHeader("Content-Type"))
+ response.setHeader("Result-Content-Type",
+ request.getHeader("Content-Type"));
+
+ response.setHeader("Content-Type", "text/plain; charset=ISO-8859-1");
+
+ var body = new BinaryInputStream(request.bodyInputStream);
+ var avail;
+ var bytes = [];
+ while ((avail = body.available()) > 0)
+ Array.prototype.push.apply(bytes, body.readByteArray(avail));
+
+ var data = String.fromCharCode.apply(null, bytes);
+ response.setHeader("Result-Content-Length", "" + data.length);
+ if (data.indexOf("TEST_REDIRECT_STR") >= 0) {
+ var newURL = "http://" + data.split("&url=")[1];
+ response.setStatusLine(null, 307, "redirect");
+ response.setHeader("Location", newURL, false);
+ }
+ else {
+ response.write(data);
+ }
+}
diff --git a/dom/xhr/tests/file_XHRSendData_doc.xml b/dom/xhr/tests/file_XHRSendData_doc.xml
new file mode 100644
index 000000000..2e385258c
--- /dev/null
+++ b/dom/xhr/tests/file_XHRSendData_doc.xml
@@ -0,0 +1,2 @@
+<!-- comment -->
+<out>hi</out>
diff --git a/dom/xhr/tests/file_XHRSendData_doc.xml^headers^ b/dom/xhr/tests/file_XHRSendData_doc.xml^headers^
new file mode 100644
index 000000000..b0f1ebfbf
--- /dev/null
+++ b/dom/xhr/tests/file_XHRSendData_doc.xml^headers^
@@ -0,0 +1 @@
+Content-Type: application/xml; charset=ISO-8859-1
diff --git a/dom/xhr/tests/file_XHR_anon.sjs b/dom/xhr/tests/file_XHR_anon.sjs
new file mode 100644
index 000000000..755c4cdf3
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_anon.sjs
@@ -0,0 +1,24 @@
+function handleRequest(request, response) {
+ let invalidHeaders = ["Cookie"];
+ let headers = {};
+
+ if (request.queryString == "expectAuth=true") {
+ if (request.hasHeader("Authorization")) {
+ headers["authorization"] = request.getHeader("Authorization");
+ } else {
+ response.setStatusLine(null, 401, "Authentication required");
+ response.setHeader("WWW-Authenticate", "basic realm=\"testrealm\"", true);
+ }
+ } else {
+ invalidHeaders.push("Authorization");
+ }
+
+ for (let header of invalidHeaders) {
+ if (request.hasHeader(header)) {
+ response.setStatusLine(null, 500, "Server Error");
+ headers[header.toLowerCase()] = request.getHeader(header);
+ }
+ }
+
+ response.write(JSON.stringify(headers));
+}
diff --git a/dom/xhr/tests/file_XHR_binary1.bin b/dom/xhr/tests/file_XHR_binary1.bin
new file mode 100644
index 000000000..39e527bfc
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_binary1.bin
Binary files differ
diff --git a/dom/xhr/tests/file_XHR_binary1.bin^headers^ b/dom/xhr/tests/file_XHR_binary1.bin^headers^
new file mode 100644
index 000000000..8e8c8d859
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_binary1.bin^headers^
@@ -0,0 +1 @@
+Content-Type: application/binary
diff --git a/dom/xhr/tests/file_XHR_binary2.bin b/dom/xhr/tests/file_XHR_binary2.bin
new file mode 100644
index 000000000..9f442b092
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_binary2.bin
Binary files differ
diff --git a/dom/xhr/tests/file_XHR_fail1.txt b/dom/xhr/tests/file_XHR_fail1.txt
new file mode 100644
index 000000000..462209d8d
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_fail1.txt
@@ -0,0 +1 @@
+redirect file
diff --git a/dom/xhr/tests/file_XHR_fail1.txt^headers^ b/dom/xhr/tests/file_XHR_fail1.txt^headers^
new file mode 100644
index 000000000..41c235932
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_fail1.txt^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: http://example.com/tests/dom/xhr/tests/file_XHR_pass2.txt
diff --git a/dom/xhr/tests/file_XHR_fail1b.txt b/dom/xhr/tests/file_XHR_fail1b.txt
new file mode 100644
index 000000000..8944657af
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_fail1b.txt
@@ -0,0 +1 @@
+hello pass
diff --git a/dom/xhr/tests/file_XHR_header.sjs b/dom/xhr/tests/file_XHR_header.sjs
new file mode 100644
index 000000000..937e90a02
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_header.sjs
@@ -0,0 +1,6 @@
+// SJS file for getAllResponseRequests vs getResponseRequest
+function handleRequest(request, response)
+{
+ response.setHeader("X-Custom-Header-Bytes", "…", false);
+ response.write("42");
+}
diff --git a/dom/xhr/tests/file_XHR_pass1.xml b/dom/xhr/tests/file_XHR_pass1.xml
new file mode 100644
index 000000000..06826d6c6
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_pass1.xml
@@ -0,0 +1 @@
+<res>hello</res>
diff --git a/dom/xhr/tests/file_XHR_pass2.txt b/dom/xhr/tests/file_XHR_pass2.txt
new file mode 100644
index 000000000..0d7f879f9
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_pass2.txt
@@ -0,0 +1 @@
+hello pass
diff --git a/dom/xhr/tests/file_XHR_pass3.txt b/dom/xhr/tests/file_XHR_pass3.txt
new file mode 100644
index 000000000..462209d8d
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_pass3.txt
@@ -0,0 +1 @@
+redirect file
diff --git a/dom/xhr/tests/file_XHR_pass3.txt^headers^ b/dom/xhr/tests/file_XHR_pass3.txt^headers^
new file mode 100644
index 000000000..fb5056c38
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_pass3.txt^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: file_XHR_pass2.txt
diff --git a/dom/xhr/tests/file_XHR_system_redirect.html b/dom/xhr/tests/file_XHR_system_redirect.html
new file mode 100644
index 000000000..8267b01d0
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_system_redirect.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html>
+<body>
+</body>
+</html> \ No newline at end of file
diff --git a/dom/xhr/tests/file_XHR_system_redirect.html^headers^ b/dom/xhr/tests/file_XHR_system_redirect.html^headers^
new file mode 100644
index 000000000..cefb165b0
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_system_redirect.html^headers^
@@ -0,0 +1,2 @@
+HTTP 302 Found
+Location: file:///etc/passwd
diff --git a/dom/xhr/tests/file_XHR_timeout.sjs b/dom/xhr/tests/file_XHR_timeout.sjs
new file mode 100644
index 000000000..b349d122e
--- /dev/null
+++ b/dom/xhr/tests/file_XHR_timeout.sjs
@@ -0,0 +1,15 @@
+var timer = null;
+
+function handleRequest(request, response)
+{
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function()
+ {
+ response.setStatusLine(null, 200, "OK");
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("hello");
+ response.finish();
+ }, 3000 /* milliseconds */, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
diff --git a/dom/xhr/tests/file_html_in_xhr.html b/dom/xhr/tests/file_html_in_xhr.html
new file mode 100644
index 000000000..d77aeb440
--- /dev/null
+++ b/dom/xhr/tests/file_html_in_xhr.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html><!-- Þ -->
+<meta charset="Windows-1251">
+<script>
+document.documentElement.setAttribute("data-fail", "FAIL");
+</script>
+<script src="file_html_in_xhr.sjs"></script>
+<script src="file_html_in_xhr.sjs" defer></script>
+<script src="file_html_in_xhr.sjs" async></script>
+<link type="stylesheet" href="file_html_in_xhr.sjs">
+<body onload='document.documentElement.setAttribute("data-fail", "FAIL");'>
+<img src="file_html_in_xhr.sjs">
+<iframe src="file_html_in_xhr.sjs"></iframe>
+<video poster="file_html_in_xhr.sjs" src="file_html_in_xhr.sjs"></video>
+<object data="file_html_in_xhr.sjs"></object>
+<noscript><div></div></noscript>
diff --git a/dom/xhr/tests/file_html_in_xhr.sjs b/dom/xhr/tests/file_html_in_xhr.sjs
new file mode 100644
index 000000000..8f4075ae7
--- /dev/null
+++ b/dom/xhr/tests/file_html_in_xhr.sjs
@@ -0,0 +1,15 @@
+function handleRequest(request, response)
+{
+ response.setHeader("Content-Type", "text/javascript", false);
+ if (request.queryString.indexOf("report") != -1) {
+ if (getState("loaded") == "loaded") {
+ response.write("ok(false, 'This script was not supposed to get fetched.'); continueAfterReport();");
+ } else {
+ response.write("ok(true, 'This script was not supposed to get fetched.'); continueAfterReport();");
+ }
+ } else {
+ setState("loaded", "loaded");
+ response.write('document.documentElement.setAttribute("data-fail", "FAIL");');
+ }
+}
+
diff --git a/dom/xhr/tests/file_html_in_xhr2.html b/dom/xhr/tests/file_html_in_xhr2.html
new file mode 100644
index 000000000..046052c75
--- /dev/null
+++ b/dom/xhr/tests/file_html_in_xhr2.html
@@ -0,0 +1 @@
+<meta charset="windows-1251">Þ
diff --git a/dom/xhr/tests/file_html_in_xhr3.html b/dom/xhr/tests/file_html_in_xhr3.html
new file mode 100644
index 000000000..ff43ca409
--- /dev/null
+++ b/dom/xhr/tests/file_html_in_xhr3.html
@@ -0,0 +1 @@
+SUCCESS
diff --git a/dom/xhr/tests/file_sync_xhr_document_write_with_iframe.html b/dom/xhr/tests/file_sync_xhr_document_write_with_iframe.html
new file mode 100644
index 000000000..060389427
--- /dev/null
+++ b/dom/xhr/tests/file_sync_xhr_document_write_with_iframe.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<body>
+<script>
+function syncXHR() {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", window.location, false);
+ xhr.send(null);
+}
+
+addEventListener('load', evt => {
+ syncXHR();
+ document.open();
+ document.write(
+ '<body>' +
+ '<iframe src="about:blank"></iframe>' +
+ '<script>window.opener.postMessage("DONE", "*");</' + 'script>' +
+ '</body>');
+ document.close();
+}, { once: true });
+</script>
+</body>
diff --git a/dom/xhr/tests/iframe_sync_xhr_unload.html b/dom/xhr/tests/iframe_sync_xhr_unload.html
new file mode 100644
index 000000000..d58b1994c
--- /dev/null
+++ b/dom/xhr/tests/iframe_sync_xhr_unload.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <script type="application/javascript">
+
+function o() {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "sync_xhr_unload.sjs", false);
+ try { xhr.send(); } catch(e) {}
+}
+
+window.addEventListener("beforeunload", o, false);
+window.addEventListener("unload", o, false)
+
+ </script>
+</body>
+</html>
+
diff --git a/dom/xhr/tests/mochitest.ini b/dom/xhr/tests/mochitest.ini
new file mode 100644
index 000000000..35ba1e3db
--- /dev/null
+++ b/dom/xhr/tests/mochitest.ini
@@ -0,0 +1,115 @@
+[DEFAULT]
+support-files =
+ echo.sjs
+ temporaryFileBlob.sjs
+ file_html_in_xhr.html
+ file_html_in_xhr.sjs
+ file_html_in_xhr2.html
+ file_html_in_xhr3.html
+ file_XHRDocURI.text
+ file_XHRDocURI.text^headers^
+ file_XHRDocURI.xml
+ file_XHRDocURI.xml^headers^
+ file_XHRDocURI.html
+ file_XHRDocURI.html^headers^
+ file_XHRDocURI.sjs
+ file_XHRResponseURL.js
+ file_XHRResponseURL.sjs
+ file_XHRResponseURL.text
+ file_XHRResponseURL.text^headers^
+ file_XHRResponseURL_nocors.text
+ file_XHRSendData.sjs
+ file_XHRSendData_doc.xml
+ file_XHRSendData_doc.xml^headers^
+ file_XHR_anon.sjs
+ file_XHR_binary1.bin
+ file_XHR_binary1.bin^headers^
+ file_XHR_binary2.bin
+ file_XHR_fail1.txt
+ file_XHR_fail1.txt^headers^
+ file_XHR_header.sjs
+ file_XHR_pass1.xml
+ file_XHR_pass2.txt
+ file_XHR_pass3.txt
+ file_XHR_pass3.txt^headers^
+ file_XHR_system_redirect.html
+ file_XHR_system_redirect.html^headers^
+ file_XHR_timeout.sjs
+ progressserver.sjs
+ worker_terminateSyncXHR_frame.html
+ terminateSyncXHR_worker.js
+ worker_testXHR.txt
+ xhr_worker.js
+ xhr2_worker.js
+ xhrAbort_worker.js
+ test_worker_xhr_parameters.js
+ test_worker_xhr_system.js
+ worker_xhr_cors_redirect.js
+ worker_xhr_cors_redirect.sjs
+ worker_xhr_headers_server.sjs
+ worker_xhr_headers_worker.js
+ worker_file_getcookie.sjs
+ xhr_implicit_cancel_worker.js
+ relativeLoad_import.js
+ relativeLoad_worker.js
+ relativeLoad_worker2.js
+ responseIdentical.sjs
+ subdir/relativeLoad_sub_worker.js
+ subdir/relativeLoad_sub_worker2.js
+ subdir/relativeLoad_sub_import.js
+ common_temporaryFileBlob.js
+ worker_temporaryFileBlob.js
+ worker_bug1300552.js
+ sync_xhr_unload.sjs
+ iframe_sync_xhr_unload.html
+ empty.html
+ file_sync_xhr_document_write_with_iframe.html
+
+[test_bug1300552.html]
+[test_html_in_xhr.html]
+[test_relativeLoad.html]
+skip-if = buildapp == 'b2g' # b2g(Failed to load script: relativeLoad_import.js) b2g-debug(Failed to load script: relativeLoad_import.js) b2g-desktop(Failed to load script: relativeLoad_import.js)
+[test_sync_xhr_timer.xhtml]
+skip-if = toolkit == 'android'
+[test_sync_xhr_unload.html]
+[test_temporaryFileBlob.html]
+[test_worker_terminateSyncXHR.html]
+skip-if = buildapp == 'b2g'
+[test_worker_xhr.html]
+[test_worker_xhr2.html]
+[test_worker_xhr_3rdparty.html]
+[test_worker_xhr_cors_redirect.html]
+[test_worker_xhr_headers.html]
+[test_worker_xhr_implicit_cancel.html]
+[test_worker_xhr_parameters.html]
+skip-if = buildapp == 'b2g'
+[test_worker_xhr_responseURL.html]
+[test_worker_xhr_system.html]
+[test_worker_xhr_timeout.html]
+[test_worker_xhrAbort.html]
+skip-if = (os == "win") || (os == "mac") || toolkit == 'android' #bug 798220
+[test_XHR.html]
+[test_xhr_abort_after_load.html]
+skip-if = toolkit == 'android'
+[test_XHR_anon.html]
+[test_xhr_forbidden_headers.html]
+[test_XHR_header.html]
+[test_XHR_onuploadprogress.html]
+[test_xhr_overridemimetype_throws_on_invalid_state.html]
+skip-if = buildapp == 'b2g' # Requires webgl support
+[test_XHR_parameters.html]
+skip-if = buildapp == 'b2g' # b2g(86 total, 4 failing - testing mozAnon - got false, expected true) b2g-debug(86 total, 4 failing - testing mozAnon - got false, expected true) b2g-desktop(86 total, 4 failing - testing mozAnon - got false, expected true)
+[test_xhr_progressevents.html]
+skip-if = toolkit == 'android'
+[test_xhr_send.html]
+[test_xhr_send_readystate.html]
+[test_XHR_system.html]
+skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(12 total, 2 failing - .mozSystem == true - got false, expected true + ) b2g-desktop(12 total, 2 failing - .mozSystem == true - got false, expected true + )
+[test_XHR_timeout.html]
+skip-if = buildapp == 'b2g' || (android_version == '18' && debug) # b2g(flaky on B2G, bug 960743) b2g-debug(flaky on B2G, bug 960743) b2g-desktop(flaky on B2G, bug 960743)
+support-files = test_XHR_timeout.js
+[test_xhr_withCredentials.html]
+[test_XHRDocURI.html]
+[test_XHRResponseURL.html]
+[test_XHRSendData.html]
+[test_sync_xhr_document_write_with_iframe.html]
diff --git a/dom/xhr/tests/progressserver.sjs b/dom/xhr/tests/progressserver.sjs
new file mode 100644
index 000000000..945f79557
--- /dev/null
+++ b/dom/xhr/tests/progressserver.sjs
@@ -0,0 +1,52 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function setReq(req) {
+ setObjectState("dom/xhr/tests/progressserver", req);
+}
+
+function getReq() {
+ var req;
+ getObjectState("dom/xhr/tests/progressserver", function(v) {
+ req = v;
+ });
+ return req;
+}
+
+function handleRequest(request, response)
+{
+ var pairs = request.queryString.split('&');
+ var command = pairs.shift();
+ dump("received '" + command + "' command\n");
+
+ var bodyStream = new BinaryInputStream(request.bodyInputStream);
+ var body = "";
+ var bodyAvail;
+ while ((bodyAvail = bodyStream.available()) > 0)
+ body += String.fromCharCode.apply(null, bodyStream.readByteArray(bodyAvail));
+
+ if (command == "open") {
+ response.processAsync();
+ setReq(response);
+
+ response.setHeader("Cache-Control", "no-cache", false);
+ pairs.forEach(function (val) {
+ var [name, value] = val.split('=');
+ response.setHeader(name, unescape(value), false);
+ });
+ response.write(body);
+ return;
+ }
+
+ if (command == "send") {
+ getReq().write(body);
+ }
+ else if (command == "close") {
+ getReq().finish();
+ setReq(null);
+ }
+ response.setHeader("Content-Type", "text/plain");
+ response.write("ok");
+}
diff --git a/dom/xhr/tests/relativeLoad_import.js b/dom/xhr/tests/relativeLoad_import.js
new file mode 100644
index 000000000..114d1883c
--- /dev/null
+++ b/dom/xhr/tests/relativeLoad_import.js
@@ -0,0 +1,5 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+const workerURL = "relativeLoad_worker.js";
diff --git a/dom/xhr/tests/relativeLoad_worker.js b/dom/xhr/tests/relativeLoad_worker.js
new file mode 100644
index 000000000..42959db30
--- /dev/null
+++ b/dom/xhr/tests/relativeLoad_worker.js
@@ -0,0 +1,27 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+const importURL = "relativeLoad_import.js";
+
+onmessage = function(event) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "worker_testXHR.txt", false);
+ xhr.send(null);
+ if (xhr.status != 200 ||
+ xhr.responseText != "A noisy noise annoys an oyster.") {
+ throw "Couldn't get xhr text from where we wanted it!";
+ }
+
+ importScripts(importURL);
+ var worker = new Worker("relativeLoad_worker2.js");
+ worker.onerror = function(event) {
+ throw event.message;
+ };
+ worker.onmessage = function(event) {
+ if (event.data != workerURL) {
+ throw "Bad data!";
+ }
+ postMessage(workerURL);
+ }
+};
diff --git a/dom/xhr/tests/relativeLoad_worker2.js b/dom/xhr/tests/relativeLoad_worker2.js
new file mode 100644
index 000000000..e9fbdf903
--- /dev/null
+++ b/dom/xhr/tests/relativeLoad_worker2.js
@@ -0,0 +1,9 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+const importURL = "relativeLoad_import.js";
+
+importScripts(importURL);
+
+postMessage(workerURL);
diff --git a/dom/xhr/tests/responseIdentical.sjs b/dom/xhr/tests/responseIdentical.sjs
new file mode 100644
index 000000000..f1986819a
--- /dev/null
+++ b/dom/xhr/tests/responseIdentical.sjs
@@ -0,0 +1,17 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+// Simply sending back the same data that is received
+function handleRequest(request, response)
+{
+ var body = "";
+ var bodyStream = new BinaryInputStream(request.bodyInputStream);
+ var bytes = [], avail = 0;
+ while ((avail = bodyStream.available()) > 0)
+ body += String.fromCharCode.apply(String, bodyStream.readByteArray(avail));
+
+ response.setHeader("Content-Type", "application/octet-stream", false);
+ response.write(body);
+}
diff --git a/dom/xhr/tests/subdir/relativeLoad_sub_import.js b/dom/xhr/tests/subdir/relativeLoad_sub_import.js
new file mode 100644
index 000000000..cac2a6f04
--- /dev/null
+++ b/dom/xhr/tests/subdir/relativeLoad_sub_import.js
@@ -0,0 +1,5 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+const workerSubURL = "subdir/relativeLoad_sub_worker.js";
diff --git a/dom/xhr/tests/subdir/relativeLoad_sub_worker.js b/dom/xhr/tests/subdir/relativeLoad_sub_worker.js
new file mode 100644
index 000000000..f725cfb61
--- /dev/null
+++ b/dom/xhr/tests/subdir/relativeLoad_sub_worker.js
@@ -0,0 +1,26 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+const importSubURL = "relativeLoad_sub_import.js";
+
+onmessage = function(event) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "testXHR.txt", false);
+ xhr.send(null);
+ if (xhr.status != 404) {
+ throw "Loaded an xhr from the wrong location!";
+ }
+
+ importScripts(importSubURL);
+ var worker = new Worker("relativeLoad_sub_worker2.js");
+ worker.onerror = function(event) {
+ throw event.data;
+ };
+ worker.onmessage = function(event) {
+ if (event.data != workerSubURL) {
+ throw "Bad data!";
+ }
+ postMessage(workerSubURL);
+ };
+};
diff --git a/dom/xhr/tests/subdir/relativeLoad_sub_worker2.js b/dom/xhr/tests/subdir/relativeLoad_sub_worker2.js
new file mode 100644
index 000000000..f47a29ee6
--- /dev/null
+++ b/dom/xhr/tests/subdir/relativeLoad_sub_worker2.js
@@ -0,0 +1,9 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+const importSubURL = "relativeLoad_sub_import.js";
+
+importScripts(importSubURL);
+
+postMessage(workerSubURL);
diff --git a/dom/xhr/tests/sync_xhr_unload.sjs b/dom/xhr/tests/sync_xhr_unload.sjs
new file mode 100644
index 000000000..4185056e3
--- /dev/null
+++ b/dom/xhr/tests/sync_xhr_unload.sjs
@@ -0,0 +1,15 @@
+var timer = null;
+
+function handleRequest(request, response)
+{
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function()
+ {
+ response.setStatusLine(null, 200, "OK");
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("hello");
+ response.finish();
+ }, 30000 /* milliseconds */, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
diff --git a/dom/xhr/tests/temporaryFileBlob.sjs b/dom/xhr/tests/temporaryFileBlob.sjs
new file mode 100644
index 000000000..ff3410c78
--- /dev/null
+++ b/dom/xhr/tests/temporaryFileBlob.sjs
@@ -0,0 +1,33 @@
+const CC = Components.Constructor;
+
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
+ "nsIBinaryOutputStream",
+ "setOutputStream");
+const Timer = CC("@mozilla.org/timer;1",
+ "nsITimer",
+ "initWithCallback");
+
+function handleRequest(request, response) {
+ var bodyStream = new BinaryInputStream(request.bodyInputStream);
+ var bodyBytes = [];
+ while ((bodyAvail = bodyStream.available()) > 0)
+ Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail));
+
+ var bos = new BinaryOutputStream(response.bodyOutputStream);
+
+ response.processAsync();
+
+ var part = bodyBytes.splice(0, 256);
+ bos.writeByteArray(part, part.length);
+
+ response.timer1 = new Timer(function(timer) {
+ bos.writeByteArray(bodyBytes, bodyBytes.length);
+ }, 1000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+
+ response.timer2 = new Timer(function(timer) {
+ response.finish();
+ }, 2000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
diff --git a/dom/xhr/tests/terminateSyncXHR_worker.js b/dom/xhr/tests/terminateSyncXHR_worker.js
new file mode 100644
index 000000000..c86baeb42
--- /dev/null
+++ b/dom/xhr/tests/terminateSyncXHR_worker.js
@@ -0,0 +1,19 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+onmessage = function(event) {
+ throw "No messages should reach me!";
+}
+
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "worker_testXHR.txt", false);
+xhr.addEventListener("loadstart", function ()
+{
+ // Tell the parent to terminate us.
+ postMessage("TERMINATE");
+ // And wait for it to do so.
+ while(1) { true; }
+});
+xhr.send(null);
diff --git a/dom/xhr/tests/test_XHR.html b/dom/xhr/tests/test_XHR.html
new file mode 100644
index 000000000..143805a9e
--- /dev/null
+++ b/dom/xhr/tests/test_XHR.html
@@ -0,0 +1,393 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for XMLHttpRequest</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="gen.next();">
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+"use strict";
+SimpleTest.waitForExplicitFinish();
+
+var gen = runTests();
+function continueTest() { gen.next(); }
+
+function runTests() {
+
+var path = "/tests/dom/xhr/tests/";
+
+var passFiles = [['file_XHR_pass1.xml', 'GET', 200, 'OK', 'text/xml'],
+ ['file_XHR_pass2.txt', 'GET', 200, 'OK', 'text/plain'],
+ ['file_XHR_pass3.txt', 'GET', 200, 'OK', 'text/plain'],
+ ['data:text/xml,%3Cres%3Ehello%3C/res%3E%0A', 'GET', 200, 'OK', 'text/xml'],
+ ['data:text/plain,hello%20pass%0A', 'GET', 200, 'OK', 'text/plain'],
+ ['data:,foo', 'GET', 200, 'OK', 'text/plain;charset=US-ASCII', 'foo'],
+ ['data:text/plain;base64,Zm9v', 'GET', 200, 'OK', 'text/plain', 'foo'],
+ ['data:text/plain,foo#bar', 'GET', 200, 'OK', 'text/plain', 'foo'],
+ ['data:text/plain,foo%23bar', 'GET', 200, 'OK', 'text/plain', 'foo#bar'],
+ ];
+
+var blob = new Blob(["foo"], { type: "text/plain" });
+var blobURL = URL.createObjectURL(blob);
+
+passFiles.push([blobURL, 'GET', 200, 'OK', 'text/plain', 'foo']);
+
+var failFiles = [['//example.com' + path + 'file_XHR_pass1.xml', 'GET'],
+ ['ftp://localhost' + path + 'file_XHR_pass1.xml', 'GET'],
+ ['file_XHR_fail1.txt', 'GET'],
+ ];
+
+for (i = 0; i < passFiles.length; ++i) {
+ // Function to give our hacked is() a scope
+ (function(oldIs) {
+ function is(actual, expected, message) {
+ oldIs(actual, expected, message + " for " + passFiles[i][0]);
+ }
+ xhr = new XMLHttpRequest();
+ is(xhr.getResponseHeader("Content-Type"), null, "should be null");
+ is(xhr.getAllResponseHeaders(), "", "should be empty string");
+ is(xhr.responseType, "", "wrong initial responseType");
+ xhr.open(passFiles[i][1], passFiles[i][0], false);
+ xhr.send(null);
+ is(xhr.status, passFiles[i][2], "wrong status");
+ is(xhr.statusText, passFiles[i][3], "wrong statusText");
+ is(xhr.getResponseHeader("Content-Type"), passFiles[i][4], "wrong content type");
+ var headers = xhr.getAllResponseHeaders();
+ ok(/(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) &&
+ RegExp.$1 === passFiles[i][4], "wrong response headers");
+ if (xhr.responseXML) {
+ is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement),
+ passFiles[i][5] || "<res>hello</res>", "wrong responseXML");
+ is(xhr.response, passFiles[i][5] || "<res>hello</res>\n", "wrong response");
+ }
+ else {
+ is(xhr.responseText, passFiles[i][5] || "hello pass\n", "wrong responseText");
+ is(xhr.response, passFiles[i][5] || "hello pass\n", "wrong response");
+ }
+ })(is);
+}
+
+URL.revokeObjectURL(blobURL);
+
+for (i = 0; i < failFiles.length; ++i) {
+ xhr = new XMLHttpRequest();
+ var didthrow = false;
+ try {
+ xhr.open(failFiles[i][1], failFiles[i][0], false);
+ xhr.send(null);
+ }
+ catch (e) {
+ didthrow = true;
+ }
+ if (!didthrow) {
+ is(xhr.status, 301, "wrong status");
+ is(xhr.responseText, "redirect file\n", "wrong response");
+ }
+ else {
+ ok(1, "should have thrown or given incorrect result");
+ }
+}
+
+function checkResponseTextAccessThrows(xhr) {
+ var didthrow = false;
+ try { xhr.responseText } catch (e) { didthrow = true; }
+ ok(didthrow, "should have thrown when accessing responseText");
+}
+function checkResponseXMLAccessThrows(xhr) {
+ var didthrow = false;
+ try { xhr.responseXML } catch (e) { didthrow = true; }
+ ok(didthrow, "should have thrown when accessing responseXML");
+}
+function checkSetResponseType(xhr, type) {
+ var didthrow = false;
+ try { xhr.responseType = type; } catch (e) { didthrow = true; }
+ is(xhr.responseType, type, "responseType should be " + type);
+ ok(!didthrow, "should not have thrown when setting responseType");
+}
+function checkSetResponseTypeThrows(xhr, type) {
+ var didthrow = false;
+ try { xhr.responseType = type; } catch (e) { didthrow = true; }
+ ok(didthrow, "should have thrown when setting responseType");
+}
+function checkOpenThrows(xhr, method, url, async) {
+ var didthrow = false;
+ try { xhr.open(method, url, async); } catch (e) { didthrow = true; }
+ ok(didthrow, "should have thrown when open is called");
+}
+
+// test if setting responseType before calling open() works
+xhr = new XMLHttpRequest();
+checkSetResponseType(xhr, "");
+checkSetResponseType(xhr, "text");
+checkSetResponseType(xhr, "document");
+checkSetResponseType(xhr, "arraybuffer");
+checkSetResponseType(xhr, "blob");
+checkSetResponseType(xhr, "json");
+checkSetResponseType(xhr, "moz-chunked-text");
+checkSetResponseType(xhr, "moz-chunked-arraybuffer");
+checkOpenThrows(xhr, "GET", "file_XHR_pass2.txt", false);
+
+// test response (sync, responseType is not changeable)
+xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_pass2.txt', false);
+checkSetResponseTypeThrows(xhr, "");
+checkSetResponseTypeThrows(xhr, "text");
+checkSetResponseTypeThrows(xhr, "document");
+checkSetResponseTypeThrows(xhr, "arraybuffer");
+checkSetResponseTypeThrows(xhr, "blob");
+checkSetResponseTypeThrows(xhr, "json");
+checkSetResponseTypeThrows(xhr, "moz-chunked-text");
+checkSetResponseTypeThrows(xhr, "moz-chunked-arraybuffer");
+xhr.send(null);
+checkSetResponseTypeThrows(xhr, "document");
+is(xhr.status, 200, "wrong status");
+is(xhr.response, "hello pass\n", "wrong response");
+
+// test response (responseType='document')
+xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_pass1.xml');
+xhr.responseType = 'document';
+xhr.onloadend = continueTest;
+xhr.send(null);
+yield undefined;
+checkSetResponseTypeThrows(xhr, "document");
+is(xhr.status, 200, "wrong status");
+checkResponseTextAccessThrows(xhr);
+is((new XMLSerializer()).serializeToString(xhr.response.documentElement),
+ "<res>hello</res>",
+ "wrong response");
+
+// test response (responseType='text')
+xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_pass2.txt');
+xhr.responseType = 'text';
+xhr.onloadend = continueTest;
+xhr.send(null);
+yield undefined;
+is(xhr.status, 200, "wrong status");
+checkResponseXMLAccessThrows(xhr);
+is(xhr.response, "hello pass\n", "wrong response");
+
+// test response (responseType='arraybuffer')
+function arraybuffer_equals_to(ab, s) {
+ is(ab.byteLength, s.length, "wrong arraybuffer byteLength");
+
+ var u8v = new Uint8Array(ab);
+ is(String.fromCharCode.apply(String, u8v), s, "wrong values");
+}
+
+// with a simple text file
+xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_pass2.txt');
+xhr.responseType = 'arraybuffer';
+xhr.onloadend = continueTest;
+xhr.send(null);
+yield undefined;
+is(xhr.status, 200, "wrong status");
+checkResponseTextAccessThrows(xhr);
+checkResponseXMLAccessThrows(xhr);
+var ab = xhr.response;
+ok(ab != null, "should have a non-null arraybuffer");
+arraybuffer_equals_to(ab, "hello pass\n");
+
+// test reusing the same XHR (Bug 680816)
+xhr.open("GET", 'file_XHR_binary1.bin');
+xhr.responseType = 'arraybuffer';
+xhr.onloadend = continueTest;
+xhr.send(null);
+yield undefined;
+is(xhr.status, 200, "wrong status");
+var ab2 = xhr.response;
+ok(ab2 != null, "should have a non-null arraybuffer");
+ok(ab2 != ab, "arraybuffer on XHR reuse should be distinct");
+arraybuffer_equals_to(ab, "hello pass\n");
+arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
+
+// with a binary file
+xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_binary1.bin');
+xhr.responseType = 'arraybuffer';
+xhr.onloadend = continueTest;
+xhr.send(null);
+yield undefined;
+is(xhr.status, 200, "wrong status");
+checkResponseTextAccessThrows(xhr);
+checkResponseXMLAccessThrows(xhr);
+ab = xhr.response;
+ok(ab != null, "should have a non-null arraybuffer");
+arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
+is(xhr.response, xhr.response, "returns the same ArrayBuffer");
+
+// test response (responseType='json')
+var xhr = new XMLHttpRequest();
+xhr.open("POST", 'responseIdentical.sjs');
+xhr.responseType = 'json';
+var jsonObjStr = JSON.stringify({title: "aBook", author: "john"});
+xhr.onloadend = continueTest;
+xhr.send(jsonObjStr);
+yield undefined;
+is(xhr.status, 200, "wrong status");
+checkResponseTextAccessThrows(xhr);
+checkResponseXMLAccessThrows(xhr);
+is(JSON.stringify(xhr.response), jsonObjStr, "correct result");
+is(xhr.response, xhr.response, "returning the same object on each access");
+
+// with invalid json
+var xhr = new XMLHttpRequest();
+xhr.open("POST", 'responseIdentical.sjs');
+xhr.responseType = 'json';
+xhr.onloadend = continueTest;
+xhr.send("{");
+yield undefined;
+is(xhr.status, 200, "wrong status");
+checkResponseTextAccessThrows(xhr);
+checkResponseXMLAccessThrows(xhr);
+is(xhr.response, null, "Bad JSON should result in null response.");
+is(xhr.response, null, "Bad JSON should result in null response even 2nd time.");
+
+// Test status/statusText in all readyStates
+xhr = new XMLHttpRequest();
+function checkXHRStatus() {
+ if (xhr.readyState == xhr.UNSENT || xhr.readyState == xhr.OPENED) {
+ is(xhr.status, 0, "should be 0 before getting data");
+ is(xhr.statusText, "", "should be empty before getting data");
+ }
+ else {
+ is(xhr.status, 200, "should be 200 when we have data");
+ is(xhr.statusText, "OK", "should be OK when we have data");
+ }
+}
+checkXHRStatus();
+xhr.open("GET", 'file_XHR_binary1.bin');
+checkXHRStatus();
+xhr.responseType = 'arraybuffer';
+xhr.send(null);
+xhr.onreadystatechange = continueTest;
+while (xhr.readyState != 4) {
+ checkXHRStatus();
+ yield undefined;
+}
+checkXHRStatus();
+
+// test response (responseType='blob')
+var responseTypes = ['blob', 'moz-blob'];
+for (var i = 0; i < responseTypes.length; i++) {
+ var t = responseTypes[i];
+ // with a simple text file
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", 'file_XHR_pass2.txt');
+ xhr.responseType = t;
+ xhr.onloadend = continueTest;
+ xhr.send(null);
+ yield undefined;
+ is(xhr.status, 200, "wrong status");
+ checkResponseTextAccessThrows(xhr);
+ checkResponseXMLAccessThrows(xhr);
+ var b = xhr.response;
+ ok(b, "should have a non-null blob");
+ ok(b instanceof Blob, "should be a Blob");
+ ok(!(b instanceof File), "should not be a File");
+ is(b.size, "hello pass\n".length, "wrong blob size");
+
+ var fr = new FileReader();
+ fr.onload = continueTest;
+ fr.readAsBinaryString(b);
+ yield undefined;
+ ok(fr.result, "hello pass\n", "wrong values");
+
+ // with a binary file
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", 'file_XHR_binary1.bin', true);
+ xhr.send(null);
+ xhr.onreadystatechange = continueTest;
+ while(xhr.readyState != 2)
+ yield undefined;
+
+ is(xhr.status, 200, "wrong status");
+ xhr.responseType = t;
+
+ while(xhr.readyState != 4)
+ yield undefined;
+
+ xhr.onreadystatechange = null;
+
+ b = xhr.response;
+ ok(b != null, "should have a non-null blob");
+ is(b.size, 12, "wrong blob size");
+
+ fr = new FileReader();
+ fr.readAsBinaryString(b);
+ xhr = null; // kill the XHR object
+ b = null;
+ SpecialPowers.gc();
+ fr.onload = continueTest;
+ yield undefined;
+ is(fr.result, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", "wrong values");
+
+ // with a larger binary file
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", 'file_XHR_binary2.bin', true);
+ xhr.responseType = t;
+ xhr.send(null);
+ xhr.onreadystatechange = continueTest;
+
+ while (xhr.readyState != 4)
+ yield undefined;
+
+ xhr.onreadystatechange = null;
+
+ var b = xhr.response;
+ ok(b != null, "should have a non-null blob");
+ is(b.size, 65536, "wrong blob size");
+
+ fr = new FileReader();
+ fr.readAsArrayBuffer(b);
+ fr.onload = continueTest;
+ xhr = null; // kill the XHR object
+ b = null;
+ SpecialPowers.gc();
+ yield undefined;
+
+ var u8 = new Uint8Array(fr.result);
+ for (var i = 0; i < 65536; i++) {
+ if (u8[i] !== (i & 255)) {
+ break;
+ }
+ }
+ is(i, 65536, "wrong value at offset " + i);
+}
+
+var client = new XMLHttpRequest();
+client.open("GET", "file_XHR_pass1.xml", true);
+client.send();
+client.onreadystatechange = function() {
+ if(client.readyState == 4) {
+ try {
+ is(client.responseXML, null, "responseXML should be null.");
+ is(client.responseText, "", "responseText should be empty string.");
+ is(client.response, "", "response should be empty string.");
+ is(client.status, 0, "status should be 0.");
+ is(client.statusText, "", "statusText should be empty string.");
+ is(client.getAllResponseHeaders(), "",
+ "getAllResponseHeaders() should return empty string.");
+ } catch(ex) {
+ ok(false, "Shouldn't throw! [" + ex + "]");
+ }
+ }
+}
+client.abort();
+
+SimpleTest.finish();
+yield undefined;
+
+} /* runTests */
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHRDocURI.html b/dom/xhr/tests/test_XHRDocURI.html
new file mode 100644
index 000000000..e3bd1d311
--- /dev/null
+++ b/dom/xhr/tests/test_XHRDocURI.html
@@ -0,0 +1,513 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=459470
+-->
+<head>
+ <title>XMLHttpRequest return document URIs</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <base href="http://example.org/">
+</head>
+<body onload="startTest();">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=459470">Mozilla Bug 459470</a><br />
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=859095">Mozilla Bug 859095</a>
+
+<p id="display">
+<iframe id=loader></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+SimpleTest.waitForExplicitFinish();
+var gen;
+
+function startTest() {
+ // The test uses history API, so don't do anything before load event has been
+ // handled.
+ SimpleTest.executeSoon(function() {
+ gen = runTest();
+ gen.next();
+ });
+}
+
+function testXMLDocURI(aDoc, aExpects) {
+ is(aDoc.documentURI, aExpects.documentURI, "wrong url");
+ is(aDoc.baseURI, aExpects.baseURI, "wrong base");
+ is(aDoc.documentElement.baseURI, aExpects.elementBaseURI,
+ "wrong base (xml:base)");
+}
+
+function testChromeXMLDocURI(aDoc, aExpects) {
+ is(aDoc.documentURI, aExpects.documentURI, "wrong url");
+ is(aDoc.documentURIObject.spec, aExpects.documentURI,
+ "wrong url (.documentObjectURI)");
+ is(aDoc.baseURI, aExpects.baseURI, "wrong base");
+ is(aDoc.baseURIObject.spec, aExpects.baseURI,
+ "wrong base (.baseURIObject)");
+ is(aDoc.documentElement.baseURI, aExpects.elementBaseURI,
+ "wrong base (xml:base)");
+ is(aDoc.documentElement.baseURIObject.spec, aExpects.elementBaseURI,
+ "wrong base (.baseURIObject, xml:base)");
+}
+
+function testHTMLDocURI(aDoc, aExpects) {
+ is(aDoc.documentURI, aExpects.documentURI, "wrong url");
+ is(aDoc.baseURI, aExpects.baseURI, "wrong base");
+
+ var base = aDoc.createElement("base");
+ var newBaseURI = "http://www.example.com/";
+ base.href = newBaseURI;
+ aDoc.head.appendChild(base);
+ is(aDoc.baseURI, newBaseURI, "wrong base (after <base> changed)");
+}
+
+function testChromeHTMLDocURI(aDoc, aNonChromeBaseURI, aExpects) {
+ is(aDoc.documentURI, aExpects.documentURI, "wrong url");
+ is(aDoc.documentURIObject.spec, aExpects.documentURI,
+ "wrong url (.documentURIObject)");
+ is(aDoc.baseURI, aExpects.baseURI, "wrong base");
+ is(aDoc.baseURIObject.spec, aExpects.baseURI,
+ "wrong url (.baseURIObject)");
+
+ aDoc.body.setAttributeNS("http://www.w3.org/XML/1998/namespace", "base",
+ aNonChromeBaseURI);
+ is(aDoc.body.baseURI, aNonChromeBaseURI,
+ "wrong base (doc base and xml:base are same)");
+ is(aDoc.body.baseURIObject.spec, aNonChromeBaseURI,
+ "wrong base (.baseURIObject, doc base and xml:base are same)")
+ var attr = aDoc.getElementById("data").getAttributeNode("id");
+ is(attr.baseURI, aNonChromeBaseURI,
+ "wrong attr base (doc base and xml:base are same)")
+ is(attr.baseURIObject.spec, aNonChromeBaseURI,
+ "wrong attr base (.baseURIObject, doc base and xml:base are same)")
+
+ var base = aDoc.createElement("base");
+ var newBaseURI = "http://www.example.com/";
+ base.href = newBaseURI;
+ aDoc.head.appendChild(base);
+ is(aDoc.baseURI, newBaseURI, "wrong base (after <base> changed)");
+ is(aDoc.baseURIObject.spec, newBaseURI,
+ "wrong base (.baseURIObject, after <base> changed)");
+}
+
+function testCloneDocURI(aDoc) {
+ var clone = aDoc.cloneNode(true);
+ is(clone.documentURI, aDoc.documentURI, "wrong url (clone)");
+ is(clone.baseURI, aDoc.baseURI, "wrong base (clone)");
+}
+
+function runTest() {
+ is(document.baseURI, "http://example.org/", "wrong doc baseURI");
+
+ // use content XHR and access URI properties from content privileged script
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ elementBaseURI: "http://www.example.com/"
+ };
+ testXMLDocURI(xhr.responseXML, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html",
+ baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html"
+ };
+ testHTMLDocURI(xhr.response, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.text");
+ xhr.onreadystatechange = function(e) {
+ is(xhr.responseXML, null, "should not have document");
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ elementBaseURI: "http://www.example.com/"
+ };
+ testXMLDocURI(xhr.responseXML, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html",
+ baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html"
+ };
+ testHTMLDocURI(xhr.response, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ elementBaseURI: "http://www.example.com/"
+ };
+ testXMLDocURI(xhr.responseXML, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html",
+ baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html"
+ };
+ testHTMLDocURI(xhr.response, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.text");
+ xhr.onreadystatechange = function(e) {
+ is(xhr.responseXML, null, "should not have document");
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+
+ // use content XHR and access URI properties from chrome privileged script
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ elementBaseURI: "http://www.example.com/"
+ };
+ var xml = SpecialPowers.wrap(xhr.responseXML);
+ testChromeXMLDocURI(xml, expects);
+ testCloneDocURI(xml);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html",
+ baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html"
+ };
+ var doc = SpecialPowers.wrap(xhr.response);
+ testChromeHTMLDocURI(doc, "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html", expects);
+ testCloneDocURI(doc);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: document.documentURI,
+ baseURI: document.baseURI,
+ elementBaseURI: "http://www.example.com/"
+ };
+ var xml = SpecialPowers.wrap(xhr.responseXML);
+ testChromeXMLDocURI(xml, expects);
+ testCloneDocURI(xml);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: document.documentURI,
+ baseURI: document.baseURI
+ };
+ var doc = SpecialPowers.wrap(xhr.response);
+ testChromeHTMLDocURI(doc, "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html", expects);
+ testCloneDocURI(doc);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: document.documentURI,
+ baseURI: document.baseURI,
+ elementBaseURI: "http://www.example.com/"
+ };
+ var xml = SpecialPowers.wrap(xhr.responseXML);
+ testChromeXMLDocURI(xml, expects);
+ testCloneDocURI(xml);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest;
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: document.documentURI,
+ baseURI: document.baseURI
+ };
+ var doc = SpecialPowers.wrap(xhr.response);
+ testChromeHTMLDocURI(doc, "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html", expects);
+ testCloneDocURI(doc);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+
+ // use the systemXHR special privilege
+ SpecialPowers.addPermission("systemXHR", true, document);
+ xhr = new XMLHttpRequest({mozAnon: false, mozSystem: true});
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ elementBaseURI: "http://www.example.com/"
+ };
+ testXMLDocURI(xhr.responseXML, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest({mozAnon: false, mozSystem: true});
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html",
+ baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.html"
+ };
+ testHTMLDocURI(xhr.response, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest({mozAnon: false, mozSystem: true});
+ xhr.open("GET", "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ elementBaseURI: "http://www.example.com/"
+ };
+ testXMLDocURI(xhr.responseXML, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest({mozAnon: false, mozSystem: true});
+ xhr.open("GET", "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html",
+ baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html"
+ };
+ testHTMLDocURI(xhr.response, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest({mozAnon: false, mozSystem: true});
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml");
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.responseXML) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
+ elementBaseURI: "http://www.example.com/"
+ };
+ testXMLDocURI(xhr.responseXML, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ xhr = new XMLHttpRequest({mozAnon: false, mozSystem: true});
+ xhr.open("GET", "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html");
+ xhr.responseType = "document";
+ xhr.onreadystatechange = function(e) {
+ if (!xhr.response) {
+ return;
+ }
+ var expects = {
+ documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html",
+ baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.html"
+ };
+ testHTMLDocURI(xhr.response, expects);
+ if (xhr.readyState == 4) {
+ gen.next();
+ }
+ };
+ xhr.send();
+ yield undefined;
+
+ history.pushState({}, "pushStateTest", window.location.href + "/pushStateTest");
+ ok(document.documentURI.indexOf("pushStateTest") > -1);
+
+ var chromeDoc = SpecialPowers.wrap(document);
+ ok(chromeDoc.documentURI.indexOf("pushStateTest") > -1);
+
+ SimpleTest.executeSoon(function() { gen.next(); });
+
+ yield undefined;
+
+ history.back();
+ SimpleTest.executeSoon(function() { gen.next(); });
+
+ yield undefined;
+
+ SimpleTest.finish();
+ SpecialPowers.removePermission("systemXHR", document);
+ yield undefined;
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHRResponseURL.html b/dom/xhr/tests/test_XHRResponseURL.html
new file mode 100644
index 000000000..17e8c627a
--- /dev/null
+++ b/dom/xhr/tests/test_XHRResponseURL.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=998076
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 998076</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="file_XHRResponseURL.js"></script>
+ <script type="application/javascript">
+
+/** Test for Bug 998076 **/
+"use strict";
+
+window.addEventListener("message", function (aEvent) {
+ var data = aEvent.data;
+ if (data === "done") {
+ SimpleTest.finish();
+ return;
+ }
+ if (data === "start") {
+ return;
+ }
+ if (data.type === "is") {
+ SimpleTest.is(data.actual, data.expected, data.message);
+ window.postMessage("pong", "*");
+ return;
+ }
+ if (data.type === "ok") {
+ SimpleTest.ok(data.bool, data.message);
+ window.postMessage("pong", "*");
+ return;
+ }
+ if (data.type === "info") {
+ SimpleTest.info(data.message);
+ window.postMessage("pong", "*");
+ return;
+ }
+ if (data.type === "todo") {
+ SimpleTest.todo(data.bool, data.message);
+ window.postMessage("pong", "*");
+ return;
+ }
+ if (data.type === "todo_is") {
+ SimpleTest.todo_is(data.actual, data.expected, data.message);
+ window.postMessage("pong", "*");
+ return;
+ }
+});
+
+function runTests() {
+ SimpleTest.waitForExplicitFinish();
+ window.postMessage("start", "*");
+}
+
+ </script>
+</head>
+<body onload="runTests()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=998076">Mozilla Bug 998076</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHRSendData.html b/dom/xhr/tests/test_XHRSendData.html
new file mode 100644
index 000000000..c210efc9c
--- /dev/null
+++ b/dom/xhr/tests/test_XHRSendData.html
@@ -0,0 +1,267 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=464848
+-->
+<head>
+ <title>XMLHttpRequest send data and headers</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="createFiles();">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=464848">Mozilla Bug 464848</a>
+<p id="display">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+SimpleTest.waitForExplicitFinish();
+
+var testData = "blahblahblahblahblahblahblaaaaaaaah. blah.";
+var extensions = [".txt",".png",".jpg",".gif",".xml", "noext"];
+var fileTypes = ["text/plain", "image/png", "image/jpeg", "image/gif", "text/xml", null];
+var gen = runTests();
+var testDOMFiles;
+
+function createFiles() {
+ var filesToCreate = new Array();
+ extensions.forEach(function (extension) {
+ filesToCreate.push({name: "testfile" + extension, data: testData});
+ });
+ SpecialPowers.createFiles(filesToCreate,
+ function (files) {
+ testDOMFiles = files;
+ gen.next();
+ },
+ function (msg) {
+ testDOMFiles = new Array;
+ ok(false, "File creation error: " + msg);
+ gen.next();
+ });
+};
+
+
+function continueTest() { gen.next(); }
+
+function runTests() {
+xhr = new XMLHttpRequest();
+xhr.open("GET", "file_XHRSendData_doc.xml", false);
+xhr.send();
+testDoc1 = xhr.responseXML;
+is(testDoc1.inputEncoding, "windows-1252", "wrong encoding");
+
+testDoc2 = document.implementation.createDocument("", "", null);
+testDoc2.appendChild(testDoc2.createComment(" doc 2 "));
+testDoc2.appendChild(testDoc2.createElement("res"));
+testDoc2.documentElement.appendChild(testDoc2.createTextNode("text"));
+is(testDoc2.inputEncoding, "UTF-8", "wrong encoding");
+
+// arraybuffer test objects
+var shortArray = new ArrayBuffer(1);
+var shortInt8View = new Uint8Array(shortArray);
+shortInt8View[0] = 3;
+
+var longArray = new ArrayBuffer(512);
+var longInt8View = new Uint8Array(longArray);
+for (var i = 0; i < longInt8View.length; i++) {
+ longInt8View[i] = i % 255;
+}
+
+// arraybufferview test objects
+var longArraySlice = longArray.slice(256, 384);
+var longInt32View1 = new Int32Array(longArraySlice)
+var longInt32View2 = new Int32Array(longArray, 256, 32)
+var longInt16View1 = new Uint16Array(longArraySlice)
+var longInt16View2 = new Uint16Array(longArray, 256, 64)
+var longInt8View1 = new Int8Array(longArraySlice)
+var longInt8View2 = new Int8Array(longArray, 256, 128)
+
+tests = [{ body: null,
+ resBody: "",
+ },
+ { body: undefined,
+ resBody: "",
+ },
+ { body: "hi",
+ resBody: "hi",
+ resContentType: "text/plain;charset=UTF-8",
+ },
+ { body: "r\xe4ksm\xf6rg\xe5s",
+ resBody: "r\xc3\xa4ksm\xc3\xb6rg\xc3\xa5s",
+ resContentType: "text/plain;charset=UTF-8",
+ },
+ { body: "hi",
+ contentType: "",
+ resBody: "hi",
+ resContentType: "text/plain;charset=UTF-8",
+ },
+ { body: "hi",
+ contentType: "foo/bar",
+ resBody: "hi",
+ resContentType: "foo/bar",
+ },
+ { body: "hi",
+ contentType: "foo/bar; baz=bin",
+ resBody: "hi",
+ resContentType: "foo/bar; baz=bin",
+ },
+ { body: "hi",
+ contentType: "foo/bar; charset=ascii; baz=bin",
+ resBody: "hi",
+ resContentType: "foo/bar; charset=UTF-8; baz=bin",
+ },
+ { body: "hi",
+ contentType: "foo/bar; charset=uTf-8",
+ resBody: "hi",
+ resContentType: "foo/bar; charset=uTf-8",
+ },
+ { body: testDoc1,
+ resBody: "<!-- comment -->\n<out>hi</out>",
+ resContentType: "application/xml;charset=UTF-8",
+ },
+ { body: testDoc1,
+ contentType: "foo/bar",
+ resBody: "<!-- comment -->\n<out>hi</out>",
+ resContentType: "foo/bar",
+ },
+ { body: testDoc1,
+ contentType: "foo/bar; charset=ascii; baz=bin",
+ resBody: "<!-- comment -->\n<out>hi</out>",
+ resContentType: "foo/bar; charset=UTF-8; baz=bin",
+ },
+ { body: testDoc1,
+ contentType: "foo/bar; charset=wIndows-1252",
+ resBody: "<!-- comment -->\n<out>hi</out>",
+ resContentType: "foo/bar; charset=UTF-8",
+ },
+ { body: testDoc2,
+ resBody: "<!-- doc 2 -->\n<res>text</res>",
+ resContentType: "application/xml;charset=UTF-8",
+ },
+ { body: testDoc2,
+ contentType: "foo/bar",
+ resBody: "<!-- doc 2 -->\n<res>text</res>",
+ resContentType: "foo/bar",
+ },
+ { body: testDoc2,
+ contentType: "foo/bar; charset=ascii; baz=bin",
+ resBody: "<!-- doc 2 -->\n<res>text</res>",
+ resContentType: "foo/bar; charset=UTF-8; baz=bin",
+ },
+ { body: testDoc2,
+ contentType: "foo/bar; charset=uTf-8",
+ resBody: "<!-- doc 2 -->\n<res>text</res>",
+ resContentType: "foo/bar; charset=uTf-8",
+ },
+ { //will trigger a redirect test server-side
+ body: ("TEST_REDIRECT_STR&url=" + window.location.host + window.location.pathname),
+ redirect: true,
+ },
+ { body: shortArray,
+ resBody: shortArray,
+ resType: "arraybuffer"
+ },
+ { body: longArray,
+ resBody: longArray,
+ resType: "arraybuffer"
+ },
+ { body: longInt32View1,
+ resBody: longArraySlice,
+ resType: "arraybuffer"
+ },
+ { body: longInt32View2,
+ resBody: longArraySlice,
+ resType: "arraybuffer"
+ },
+ { body: longInt16View1,
+ resBody: longArraySlice,
+ resType: "arraybuffer"
+ },
+ { body: longInt16View2,
+ resBody: longArraySlice,
+ resType: "arraybuffer"
+ },
+ { body: longInt8View1,
+ resBody: longArraySlice,
+ resType: "arraybuffer"
+ },
+ { body: longInt8View2,
+ resBody: longArraySlice,
+ resType: "arraybuffer"
+ },
+ ];
+
+for (var i = 0; i < testDOMFiles.length; i++) {
+ tests.push({ body: testDOMFiles[i],
+ resBody: testData,
+ resContentType: fileTypes[i],
+ resContentLength: testData.length,
+ });
+}
+
+try {
+ for (test of tests) {
+ xhr = new XMLHttpRequest;
+ xhr.open("POST", "file_XHRSendData.sjs", !!test.resType);
+ if (test.contentType)
+ xhr.setRequestHeader("Content-Type", test.contentType);
+ if (test.resType) {
+ xhr.responseType = test.resType;
+ xhr.onloadend = continueTest;
+ }
+ xhr.send(test.body);
+ if (test.resType)
+ yield undefined;
+
+ if (test.resContentType) {
+ is(xhr.getResponseHeader("Result-Content-Type"), test.resContentType,
+ "Wrong Content-Type sent");
+ }
+ else {
+ is(xhr.getResponseHeader("Result-Content-Type"), null);
+ }
+
+ if (test.resContentLength) {
+ is(xhr.getResponseHeader("Result-Content-Length"),
+ String(test.resContentLength),
+ "Wrong Content-Length sent");
+ }
+
+ if (test.resType == "arraybuffer") {
+ is_identical_arraybuffer(xhr.response, test.resBody);
+ }
+ else if (test.body instanceof Document) {
+ is(xhr.responseText.replace("\r\n", "\n"), test.resBody, "Wrong body");
+ }
+ else if (!test.redirect) {
+ is(xhr.responseText, test.resBody, "Wrong body");
+ }
+ else {
+ // If we're testing redirect, determine whether the body is
+ // this document by looking for the relevant bug url
+ is(xhr.responseText.indexOf("https://bugzilla.mozilla.org/show_bug.cgi?id=464848") >= 0, true,
+ "Wrong page for redirect");
+ }
+ }
+} catch (e) {
+}
+
+function is_identical_arraybuffer(ab1, ab2) {
+ is(ab1.byteLength, ab2.byteLength, "arraybuffer byteLengths not equal");
+ u8v1 = new Uint8Array(ab1);
+ u8v2 = new Uint8Array(ab2);
+ is(String.fromCharCode.apply(String, u8v1),
+ String.fromCharCode.apply(String, u8v2), "arraybuffer values not equal");
+}
+
+SimpleTest.finish();
+yield undefined;
+} /* runTests */
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHR_anon.html b/dom/xhr/tests/test_XHR_anon.html
new file mode 100644
index 000000000..ed9271a04
--- /dev/null
+++ b/dom/xhr/tests/test_XHR_anon.html
@@ -0,0 +1,180 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for XMLHttpRequest with system privileges</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setup();">
+<p id="display">
+<iframe id="loader"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+// An XHR with the anon flag set will not send cookie and auth information.
+const TEST_URL = "http://example.com/tests/dom/xhr/tests/file_XHR_anon.sjs";
+document.cookie = "foo=bar";
+
+let am = {
+ authMgr: null,
+
+ init: function() {
+ this.authMgr = SpecialPowers.Cc["@mozilla.org/network/http-auth-manager;1"]
+ .getService(SpecialPowers.Ci.nsIHttpAuthManager)
+ },
+
+ addIdentity: function() {
+ this.authMgr.setAuthIdentity("http", "example.com", -1, "basic", "testrealm",
+ "", "example.com", "user1", "password1");
+ },
+
+ tearDown: function() {
+ this.authMgr.clearAll();
+ },
+}
+
+var tests = [ test1, test2, test2a, test3, test3, test3, test4, test4, test4, test5, test5, test5 ];
+
+function runTests() {
+ if (!tests.length) {
+ am.tearDown();
+
+ // Resetting the cookie.
+ document.cookie = "foo=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+}
+
+function test1() {
+ am.addIdentity();
+
+ let xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
+ is(xhr.mozAnon, true, "test1: .mozAnon == true");
+ xhr.open("GET", TEST_URL);
+ xhr.onload = function onload() {
+ is(xhr.status, 200, "test1: " + xhr.responseText);
+ am.tearDown();
+ runTests();
+ };
+ xhr.onerror = function onerror() {
+ ok(false, "Got an error event!");
+ am.tearDown();
+ runTests();
+ }
+ xhr.send();
+}
+
+function test2() {
+ am.addIdentity();
+
+ let xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
+ is(xhr.mozAnon, true, "test2: .mozAnon == true");
+ xhr.open("GET", TEST_URL + "?expectAuth=true", true,
+ "user2name", "pass2word");
+ xhr.onload = function onload() {
+ is(xhr.status, 200, "test2: " + xhr.responseText);
+ let response = JSON.parse(xhr.responseText);
+ is(response.authorization, "Basic dXNlcjJuYW1lOnBhc3Myd29yZA==");
+ am.tearDown();
+ runTests();
+ };
+ xhr.onerror = function onerror() {
+ ok(false, "Got an error event!");
+ am.tearDown();
+ runTests();
+ }
+ xhr.send();
+}
+
+function test2a() {
+ am.addIdentity();
+
+ let xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
+ is(xhr.mozAnon, true, "test2: .mozAnon == true");
+ xhr.open("GET", TEST_URL + "?expectAuth=true", true,
+ "user1", "pass2word");
+ xhr.onload = function onload() {
+ is(xhr.status, 200, "test2: " + xhr.responseText);
+ let response = JSON.parse(xhr.responseText);
+ is(response.authorization, "Basic dXNlcjE6cGFzczJ3b3Jk");
+ am.tearDown();
+ runTests();
+ };
+ xhr.onerror = function onerror() {
+ ok(false, "Got an error event!");
+ am.tearDown();
+ runTests();
+ }
+ xhr.send();
+}
+
+function test3() {
+ am.addIdentity();
+
+ let xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
+ is(xhr.mozAnon, true, "test3: .mozAnon == true");
+ xhr.open("GET", TEST_URL + "?expectAuth=true", true);
+ xhr.onload = function onload() {
+ is(xhr.status, 401, "test3: " + xhr.responseText);
+ am.tearDown();
+ runTests();
+ };
+ xhr.onerror = function onerror() {
+ ok(false, "Got an error event!");
+ am.tearDown();
+ runTests();
+ }
+ xhr.send();
+}
+
+function test4() {
+ let xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
+ is(xhr.mozAnon, true, "test4: .mozAnon == true");
+ xhr.open("GET", TEST_URL + "?expectAuth=true", true);
+ xhr.onload = function onload() {
+ is(xhr.status, 401, "test4: " + xhr.responseText);
+ runTests();
+ };
+ xhr.onerror = function onerror() {
+ ok(false, "Got an error event!");
+ runTests();
+ }
+ xhr.send();
+}
+
+function test5() {
+ let xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
+ is(xhr.mozAnon, true, "test5: .mozAnon == true");
+ xhr.open("GET", TEST_URL + "?expectAuth=true", true,
+ "user2name", "pass2word");
+ xhr.onload = function onload() {
+ is(xhr.status, 200, "test5: " + xhr.responseText);
+ let response = JSON.parse(xhr.responseText);
+ is(response.authorization, "Basic dXNlcjJuYW1lOnBhc3Myd29yZA==");
+ runTests();
+ };
+ xhr.onerror = function onerror() {
+ ok(false, "Got an error event!");
+ runTests();
+ }
+ xhr.send();
+}
+
+function setup() {
+ am.init();
+ SimpleTest.waitForExplicitFinish();
+ SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], runTests);
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHR_header.html b/dom/xhr/tests/test_XHR_header.html
new file mode 100644
index 000000000..e213b25c7
--- /dev/null
+++ b/dom/xhr/tests/test_XHR_header.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for XMLHttpRequest.GetResponseHeader(foo) byte-inflates the output</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta charset="utf-8">
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+"use strict";
+SimpleTest.waitForExplicitFinish();
+
+let xhr = new XMLHttpRequest();
+xhr.open('GET', 'file_XHR_header.sjs', true);
+xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ ok(xhr.getResponseHeader('X-Custom-Header-Bytes') == "\xE2\x80\xA6", 'getResponseHeader byte-inflates the output');
+ SimpleTest.finish();
+ }
+}
+xhr.send(null);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHR_onuploadprogress.html b/dom/xhr/tests/test_XHR_onuploadprogress.html
new file mode 100644
index 000000000..10c4fd20d
--- /dev/null
+++ b/dom/xhr/tests/test_XHR_onuploadprogress.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=743666
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 743666</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=743666">Mozilla Bug 743666</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 743666 **/
+
+var called = false;
+function uploadprogress()
+{
+ called = true;
+}
+
+var xhr = new XMLHttpRequest();
+xhr.upload.onprogress = uploadprogress;
+var event = new ProgressEvent("progress");
+xhr.upload.dispatchEvent(event);
+ok(called,
+ "XMLHttpRequest.upload.onprogress sets upload progress event listener");
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHR_parameters.html b/dom/xhr/tests/test_XHR_parameters.html
new file mode 100644
index 000000000..b99bb9dfe
--- /dev/null
+++ b/dom/xhr/tests/test_XHR_parameters.html
@@ -0,0 +1,97 @@
+
+
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for XMLHttpRequest with system privileges</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="runTests();">
+<p id="display">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+function runTests() {
+ SimpleTest.waitForExplicitFinish();
+
+ let validParameters = [
+ undefined,
+ null,
+ {},
+ {mozSystem: ""},
+ {mozSystem: 0},
+ {mozAnon: 1},
+ {mozAnon: []},
+ {get mozAnon() { return true; }},
+ 0,
+ 7,
+ Math.PI,
+ "string",
+ true,
+ false,
+ ];
+
+ let invalidParameters = [
+ {get mozSystem() { throw "Bla"; } },
+ ];
+
+ let havePrivileges = false;
+
+ function testValidParameter(value) {
+ let xhr;
+ try {
+ xhr = new XMLHttpRequest(value);
+ } catch (ex) {
+ ok(false, "Got unexpected exception: " + ex);
+ return;
+ }
+ ok(xhr instanceof XMLHttpRequest, "passed " + JSON.stringify(value));
+
+ // If the page doesnt have privileges to create a system XHR,
+ // this flag will always be false no matter what is passed.
+ let expectedAnon = Boolean(value && value.mozAnon);
+ let expectedSystem = false;
+ if (havePrivileges) {
+ expectedSystem = Boolean(value && value.mozSystem);
+ }
+ is(xhr.mozAnon, expectedAnon, "testing mozAnon");
+ is(xhr.mozSystem, expectedSystem, "testing mozSystem");
+ }
+
+ function testInvalidParameter(value) {
+ let expectedError;
+ try {
+ new XMLHttpRequest(value);
+ ok(false, "invalid parameter did not cause exception: " +
+ JSON.stringify(value));
+ } catch (ex) {
+ expectedError = ex;
+ }
+ ok(expectedError, "invalid parameter raised exception as expected: " +
+ JSON.stringify(expectedError))
+ }
+
+ // Run the tests once without API privileges...
+ validParameters.forEach(testValidParameter);
+ invalidParameters.forEach(testInvalidParameter);
+
+ // ...and once with privileges.
+ havePrivileges = true;
+ SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], function() {
+ validParameters.forEach(testValidParameter);
+ invalidParameters.forEach(testInvalidParameter);
+
+ SimpleTest.finish();
+ });
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHR_system.html b/dom/xhr/tests/test_XHR_system.html
new file mode 100644
index 000000000..1d61e3f77
--- /dev/null
+++ b/dom/xhr/tests/test_XHR_system.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for XMLHttpRequest with system privileges</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="runTests();">
+<p id="display">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+let tests = [];
+
+const PROTECTED_URL = "file:///etc/passwd";
+const REDIRECT_URL = window.location.protocol + "//" + window.location.host + "/tests/dom/xhr/tests/file_XHR_system_redirect.html";
+const CROSSSITE_URL = "http://example.com/tests/dom/xhr/tests/test_XHR_system.html";
+
+tests.push(function test_cross_origin() {
+ // System XHR can load cross-origin resources.
+
+ is(window.location.hostname, "mochi.test", "correct origin");
+
+ let xhr = new XMLHttpRequest({mozSystem: true});
+ is(xhr.mozSystem, true, ".mozSystem == true");
+ xhr.open("GET", CROSSSITE_URL);
+ xhr.onload = function onload() {
+ is(xhr.status, 200, "correct HTTP status");
+ ok(xhr.responseText != null, "HTTP response non-null");
+ ok(xhr.responseText.length, "HTTP response not empty");
+ runNextTest();
+ };
+ xhr.onerror = function onerror(event) {
+ ok(false, "Got an error event: " + event);
+ runNextTest();
+ }
+ xhr.send();
+});
+
+tests.push(function test_file_uri() {
+ // System XHR is not permitted to access file:/// URIs.
+
+ let xhr = new XMLHttpRequest({mozSystem: true});
+ is(xhr.mozSystem, true, ".mozSystem == true");
+ xhr.open("GET", PROTECTED_URL);
+ xhr.onload = function() {
+ ok(false, "Should not have loaded");
+ 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() {
+ // System XHR won't load file:/// URIs even if an HTTP resource redirects there.
+
+ let xhr = new XMLHttpRequest({mozSystem: true});
+ is(xhr.mozSystem, true, ".mozSystem == true");
+ xhr.open("GET", REDIRECT_URL);
+ xhr.onload = function onload() {
+ ok(false, "Should not have loaded");
+ runNextTest();
+ };
+ xhr.onerror = function onerror(event) {
+ ok(true, "Got an error event: " + event);
+ is(xhr.status, 0, "HTTP status is 0");
+ runNextTest();
+ }
+ xhr.send();
+});
+
+
+function runNextTest() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+ tests.shift()();
+}
+
+function runTests() {
+ SimpleTest.waitForExplicitFinish();
+
+ SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], runNextTest);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHR_timeout.html b/dom/xhr/tests/test_XHR_timeout.html
new file mode 100644
index 000000000..14422d9f4
--- /dev/null
+++ b/dom/xhr/tests/test_XHR_timeout.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=525816
+-->
+<head>
+ <title>Test for Bug 525816</title>
+ <script type="application/javascript"
+ src="/MochiKit/MochiKit.js"></script>
+ <script type="application/javascript"
+ src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet"
+ type="text/css"
+ href="/tests/SimpleTest/test.css">
+</head>
+<body>
+
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=525816"
+ >Mozilla Bug 525816 (XMLHttpRequest timeout)</a>
+<p id="display"></p>
+<div id="content">
+ This test takes over 1 minute to run, probably over 2 minutes.
+</div>
+<pre id="test">
+<script class="testbody"
+ type="text/javascript"
+ src="test_XHR_timeout.js"></script>
+<script type="text/javascript">
+ window.addEventListener("message", function (event) {
+ if (event.data == "done") {
+ SimpleTest.finish();
+ return;
+ }
+ if (event.data == "start") {
+ return;
+ }
+ if (event.data.type == "is") {
+ SimpleTest.is(event.data.got, event.data.expected, event.data.msg);
+ return;
+ }
+ if (event.data.type == "ok") {
+ SimpleTest.ok(event.data.bool, event.data.msg);
+ return;
+ }
+ });
+ // Final test harness setup and launch.
+ (function() {
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestLongerTimeout(TestRequests.length);
+ SimpleTest.requestFlakyTimeout("This is testing XHR timeouts.");
+ var msg = "This test will take approximately " + (TestRequests.length * 10)
+ msg += " seconds to complete, at most.";
+ document.getElementById("content").firstChild.nodeValue = msg;
+ window.postMessage("start", "*");
+ })();
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_XHR_timeout.js b/dom/xhr/tests/test_XHR_timeout.js
new file mode 100644
index 000000000..203700887
--- /dev/null
+++ b/dom/xhr/tests/test_XHR_timeout.js
@@ -0,0 +1,342 @@
+/* Notes:
+ - All times are expressed in milliseconds in this test suite.
+ - Test harness code is at the end of this file.
+ - We generate only one request at a time, to avoid overloading the HTTP
+ request handlers.
+ */
+
+var inWorker = false;
+try {
+ inWorker = !(self instanceof Window);
+} catch (e) {
+ inWorker = true;
+}
+
+function message(data) {
+ if (inWorker)
+ self.postMessage(data);
+ else
+ self.postMessage(data, "*");
+}
+
+function is(got, expected, msg) {
+ var obj = {};
+ obj.type = "is";
+ obj.got = got;
+ obj.expected = expected;
+ obj.msg = msg;
+
+ message(obj);
+}
+
+function ok(bool, msg) {
+ var obj = {};
+ obj.type = "ok";
+ obj.bool = bool;
+ obj.msg = msg;
+
+ message(obj);
+}
+
+/**
+ * Generate and track results from a XMLHttpRequest with regards to timeouts.
+ *
+ * @param {String} id The test description.
+ * @param {Number} timeLimit The initial setting for the request timeout.
+ * @param {Number} resetAfter (Optional) The time after sending the request, to
+ * reset the timeout.
+ * @param {Number} resetTo (Optional) The delay to reset the timeout to.
+ *
+ * @note The actual testing takes place in handleEvent(event).
+ * The requests are generated in startXHR().
+ *
+ * @note If resetAfter and resetTo are omitted, only the initial timeout setting
+ * applies.
+ *
+ * @constructor
+ * @implements DOMEventListener
+ */
+function RequestTracker(async, id, timeLimit /*[, resetAfter, resetTo]*/) {
+ this.async = async;
+ this.id = id;
+ this.timeLimit = timeLimit;
+
+ if (arguments.length > 3) {
+ this.mustReset = true;
+ this.resetAfter = arguments[3];
+ this.resetTo = arguments[4];
+ }
+
+ this.hasFired = false;
+}
+RequestTracker.prototype = {
+ /**
+ * Start the XMLHttpRequest!
+ */
+ startXHR: function() {
+ var req = new XMLHttpRequest();
+ this.request = req;
+ req.open("GET", "file_XHR_timeout.sjs", this.async);
+ var me = this;
+ function handleEvent(e) { return me.handleEvent(e); };
+ req.onerror = handleEvent;
+ req.onload = handleEvent;
+ req.onabort = handleEvent;
+ req.ontimeout = handleEvent;
+
+ req.timeout = this.timeLimit;
+
+ if (this.mustReset) {
+ var resetTo = this.resetTo;
+ self.setTimeout(function() {
+ req.timeout = resetTo;
+ }, this.resetAfter);
+ }
+
+ req.send(null);
+ },
+
+ /**
+ * Get a message describing this test.
+ *
+ * @returns {String} The test description.
+ */
+ getMessage: function() {
+ var rv = this.id + ", ";
+ if (this.mustReset) {
+ rv += "original timeout at " + this.timeLimit + ", ";
+ rv += "reset at " + this.resetAfter + " to " + this.resetTo;
+ }
+ else {
+ rv += "timeout scheduled at " + this.timeLimit;
+ }
+ return rv;
+ },
+
+ /**
+ * Check the event received, and if it's the right (and only) one we get.
+ *
+ * @param {DOMProgressEvent} evt An event of type "load" or "timeout".
+ */
+ handleEvent: function(evt) {
+ if (this.hasFired) {
+ ok(false, "Only one event should fire: " + this.getMessage());
+ return;
+ }
+ this.hasFired = true;
+
+ var type = evt.type, expectedType;
+ // The XHR responds after 3000 milliseconds with a load event.
+ var timeLimit = this.mustReset && (this.resetAfter < Math.min(3000, this.timeLimit)) ?
+ this.resetTo :
+ this.timeLimit;
+ if ((timeLimit == 0) || (timeLimit >= 3000)) {
+ expectedType = "load";
+ }
+ else {
+ expectedType = "timeout";
+ }
+ is(type, expectedType, this.getMessage());
+ TestCounter.testComplete();
+ }
+};
+
+/**
+ * Generate and track XMLHttpRequests which will have abort() called on.
+ *
+ * @param shouldAbort {Boolean} True if we should call abort at all.
+ * @param abortDelay {Number} The time in ms to wait before calling abort().
+ */
+function AbortedRequest(shouldAbort, abortDelay) {
+ this.shouldAbort = shouldAbort;
+ this.abortDelay = abortDelay;
+ this.hasFired = false;
+}
+AbortedRequest.prototype = {
+ /**
+ * Start the XMLHttpRequest!
+ */
+ startXHR: function() {
+ var req = new XMLHttpRequest();
+ this.request = req;
+ req.open("GET", "file_XHR_timeout.sjs");
+ var me = this;
+ function handleEvent(e) { return me.handleEvent(e); };
+ req.onerror = handleEvent;
+ req.onload = handleEvent;
+ req.onabort = handleEvent;
+ req.ontimeout = handleEvent;
+
+ req.timeout = 2000;
+ var _this = this;
+
+ function abortReq() {
+ req.abort();
+ }
+
+ if (!this.shouldAbort) {
+ self.setTimeout(function() {
+ try {
+ _this.noEventsFired();
+ }
+ catch (e) {
+ ok(false, "Unexpected error: " + e);
+ TestCounter.testComplete();
+ }
+ }, 5000);
+ }
+ else {
+ // Abort events can only be triggered on sent requests.
+ req.send();
+ if (this.abortDelay == -1) {
+ abortReq();
+ }
+ else {
+ self.setTimeout(abortReq, this.abortDelay);
+ }
+ }
+ },
+
+ /**
+ * Ensure that no events fired at all, especially not our timeout event.
+ */
+ noEventsFired: function() {
+ ok(!this.hasFired, "No events should fire for an unsent, unaborted request");
+ // We're done; if timeout hasn't fired by now, it never will.
+ TestCounter.testComplete();
+ },
+
+ /**
+ * Get a message describing this test.
+ *
+ * @returns {String} The test description.
+ */
+ getMessage: function() {
+ return "time to abort is " + this.abortDelay + ", timeout set at 2000";
+ },
+
+ /**
+ * Check the event received, and if it's the right (and only) one we get.
+ *
+ * @param {DOMProgressEvent} evt An event of type "load" or "timeout".
+ */
+ handleEvent: function(evt) {
+ if (this.hasFired) {
+ ok(false, "Only abort event should fire: " + this.getMessage());
+ return;
+ }
+ this.hasFired = true;
+
+ var expectedEvent = (this.abortDelay >= 2000) ? "timeout" : "abort";
+ is(evt.type, expectedEvent, this.getMessage());
+ TestCounter.testComplete();
+ }
+};
+
+var SyncRequestSettingTimeoutAfterOpen = {
+ startXHR: function() {
+ var pass = false;
+ var req = new XMLHttpRequest();
+ req.open("GET", "file_XHR_timeout.sjs", false);
+ try {
+ req.timeout = 1000;
+ }
+ catch (e) {
+ pass = true;
+ }
+ ok(pass, "Synchronous XHR must not allow a timeout to be set");
+ TestCounter.testComplete();
+ }
+};
+
+var SyncRequestSettingTimeoutBeforeOpen = {
+ startXHR: function() {
+ var pass = false;
+ var req = new XMLHttpRequest();
+ req.timeout = 1000;
+ try {
+ req.open("GET", "file_XHR_timeout.sjs", false);
+ }
+ catch (e) {
+ pass = true;
+ }
+ ok(pass, "Synchronous XHR must not allow a timeout to be set");
+ TestCounter.testComplete();
+ }
+};
+
+var TestRequests = [
+ // Simple timeouts.
+ new RequestTracker(true, "no time out scheduled, load fires normally", 0),
+ new RequestTracker(true, "load fires normally", 5000),
+ new RequestTracker(true, "timeout hit before load", 2000),
+
+ // Timeouts reset after a certain delay.
+ new RequestTracker(true, "load fires normally with no timeout set, twice", 0, 2000, 0),
+ new RequestTracker(true, "load fires normally with same timeout set twice", 5000, 2000, 5000),
+ new RequestTracker(true, "timeout fires normally with same timeout set twice", 2000, 1000, 2000),
+
+ new RequestTracker(true, "timeout disabled after initially set", 5000, 2000, 0),
+ new RequestTracker(true, "timeout overrides load after a delay", 5000, 1000, 2000),
+ new RequestTracker(true, "timeout enabled after initially disabled", 0, 2000, 5000),
+
+ new RequestTracker(true, "timeout set to expiring value after load fires", 5000, 4000, 1000),
+ new RequestTracker(true, "timeout set to expired value before load fires", 5000, 2000, 1000),
+ new RequestTracker(true, "timeout set to non-expiring value after timeout fires", 1000, 2000, 5000),
+
+ // Aborted requests.
+ new AbortedRequest(false),
+ new AbortedRequest(true, -1),
+ new AbortedRequest(true, 5000),
+];
+
+var MainThreadTestRequests = [
+ new AbortedRequest(true, 0),
+ new AbortedRequest(true, 1000),
+
+ // Synchronous requests.
+ SyncRequestSettingTimeoutAfterOpen,
+ SyncRequestSettingTimeoutBeforeOpen
+];
+
+var WorkerThreadTestRequests = [
+ // Simple timeouts.
+ new RequestTracker(false, "no time out scheduled, load fires normally", 0),
+ new RequestTracker(false, "load fires normally", 5000),
+ new RequestTracker(false, "timeout hit before load", 2000),
+
+ // Reset timeouts don't make much sense with a sync request ...
+];
+
+if (inWorker) {
+ TestRequests = TestRequests.concat(WorkerThreadTestRequests);
+} else {
+ TestRequests = TestRequests.concat(MainThreadTestRequests);
+}
+
+// This code controls moving from one test to another.
+var TestCounter = {
+ testComplete: function() {
+ // Allow for the possibility there are other events coming.
+ self.setTimeout(function() {
+ TestCounter.next();
+ }, 5000);
+ },
+
+ next: function() {
+ var test = TestRequests.shift();
+
+ if (test) {
+ test.startXHR();
+ }
+ else {
+ message("done");
+ }
+ }
+};
+
+self.addEventListener("message", function (event) {
+ if (event.data == "start") {
+ TestCounter.next();
+ }
+});
diff --git a/dom/xhr/tests/test_bug1300552.html b/dom/xhr/tests/test_bug1300552.html
new file mode 100644
index 000000000..04f076f9d
--- /dev/null
+++ b/dom/xhr/tests/test_bug1300552.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1300552</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <script type="application/javascript">
+
+var w = new Worker('worker_bug1300552.js');
+w.onmessage = function(e) {
+ if (e.data.type == 'info') {
+ info(e.data.msg);
+ } else if (e.data.type == 'check') {
+ ok(e.data.what, e.data.msg);
+ } else if (e.data.type == 'finish') {
+ SimpleTest.finish();
+ } else {
+ ok(false, 'Something wrong happened');
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+ </script>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_html_in_xhr.html b/dom/xhr/tests/test_html_in_xhr.html
new file mode 100644
index 000000000..ccfb71947
--- /dev/null
+++ b/dom/xhr/tests/test_html_in_xhr.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=651072
+-->
+<head>
+ <title>Test for Bug 651072</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload=runTest();>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=651072">Mozilla Bug 651072</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 651072 **/
+SimpleTest.waitForExplicitFinish();
+
+var xhr = new XMLHttpRequest();
+
+function runTest() {
+ xhr.onreadystatechange = function() {
+ if (this.readyState == 4) {
+ ok(this.responseXML, "Should have gotten responseXML");
+ is(this.responseXML.characterSet, "windows-1251", "Wrong character encoding");
+ is(this.responseXML.documentElement.firstChild.data, " \u042E ", "Decoded using the wrong encoding.");
+ try {
+ this.responseText;
+ ok(false, "responseText access should have thrown.");
+ } catch (e) {
+ is(e.name, "InvalidStateError", "Should have thrown InvalidStateError.");
+ is(e.code, 11, "Should have thrown INVALID_STATE_ERR.");
+ }
+ is(this.responseXML.getElementsByTagName("div").length, 1, "There should be one div.");
+ ok(!this.responseXML.documentElement.hasAttribute("data-fail"), "Should not have a data-fail attribute.");
+ var scripts = this.responseXML.getElementsByTagName("script");
+ is(scripts.length, 4, "Unexpected number of scripts.");
+ while (scripts.length) {
+ // These should not run when moved to another doc
+ document.body.appendChild(scripts[0]);
+ }
+ var s = document.createElement("script");
+ s.src = "file_html_in_xhr.sjs?report=1";
+ document.body.appendChild(s);
+ }
+ }
+ xhr.open("GET", "file_html_in_xhr.html", true);
+ xhr.responseType = "document";
+ xhr.send();
+}
+
+function continueAfterReport() {
+ xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (this.readyState == 4) {
+ is(this.responseText.indexOf("\u042E"), -1, "Honored meta in default mode.");
+ is(this.responseText.indexOf("\uFFFD"), 29, "Honored meta in default mode 2.");
+ is(this.responseXML, null, "responseXML should be null for HTML in the default mode");
+ testNonParsingText();
+ }
+ }
+ xhr.open("GET", "file_html_in_xhr2.html");
+ xhr.send();
+}
+
+function testNonParsingText() {
+ xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (this.readyState == 4) {
+ is(this.responseText.indexOf("\u042E"), -1, "Honored meta in text mode.");
+ is(this.responseText.indexOf("\uFFFD"), 29, "Honored meta in text mode 2.");
+ testChunkedText();
+ }
+ }
+ xhr.open("GET", "file_html_in_xhr2.html");
+ xhr.responseType = "text";
+ xhr.send();
+}
+
+function testChunkedText() {
+ xhr = new XMLHttpRequest();
+ xhr.onprogress = function() {
+ is(this.responseText.indexOf("\u042E"), -1, "Honored meta in chunked text mode.");
+ }
+ xhr.onreadystatechange = function() {
+ if (this.readyState == 4) {
+ testSyncXHR();
+ }
+ }
+ xhr.open("GET", "file_html_in_xhr2.html");
+ xhr.responseType = "moz-chunked-text";
+ xhr.send();
+}
+
+function testSyncXHR() {
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", "file_html_in_xhr3.html", false);
+ xhr.send();
+ is(xhr.responseText, "SUCCESS\n", "responseText should be ready by now");
+ is(xhr.responseXML, null, "responseXML should be null in the sync case");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/xhr/tests/test_relativeLoad.html b/dom/xhr/tests/test_relativeLoad.html
new file mode 100644
index 000000000..fd471b894
--- /dev/null
+++ b/dom/xhr/tests/test_relativeLoad.html
@@ -0,0 +1,52 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads relative load
+-->
+<head>
+ <title>Test for DOM Worker Threads</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ var index = -1;
+
+ var urls = [
+ "relativeLoad_worker.js",
+ "subdir/relativeLoad_sub_worker.js"
+ ];
+
+ function messageHandler(event) {
+ if (index >= 0) {
+ is(event.data, urls[index], "Bad url!");
+ if (index == urls.length - 1) {
+ SimpleTest.finish();
+ return;
+ }
+ }
+
+ var worker = new Worker(urls[++index]);
+ worker.onmessage = messageHandler;
+ worker.onerror = function(event) {
+ ok(false, "Worker had an error: " + event.message);
+ SimpleTest.finish();
+ };
+ worker.postMessage("start");
+ }
+
+ messageHandler();
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/xhr/tests/test_sync_xhr_document_write_with_iframe.html b/dom/xhr/tests/test_sync_xhr_document_write_with_iframe.html
new file mode 100644
index 000000000..eaddc2feb
--- /dev/null
+++ b/dom/xhr/tests/test_sync_xhr_document_write_with_iframe.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug </title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script>
+function runTest() {
+ let w = window.open('file_sync_xhr_document_write_with_iframe.html');
+ addEventListener('message', evt => {
+ is(evt.data, 'DONE');
+ w.close();
+ SimpleTest.finish();
+ }, { once: true });
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_sync_xhr_timer.xhtml b/dom/xhr/tests/test_sync_xhr_timer.xhtml
new file mode 100644
index 000000000..ce6572362
--- /dev/null
+++ b/dom/xhr/tests/test_sync_xhr_timer.xhtml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=
+-->
+<head>
+ <title>Test for Bug </title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+<![CDATA[
+
+var counter = 0;
+var xhr;
+
+function syncXHR() {
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", window.location, false);
+ xhr.send(null);
+}
+
+function increaseCounter() {
+ ++counter;
+ ok(counter <= 2, "Too many increaseCounter() calls!");
+ if (counter == 2) {
+ ok(true, "increaseCounter() should be called twice!");
+ SimpleTest.finish();
+ }
+}
+
+function runTest() {
+ setTimeout(syncXHR, 0);
+ setTimeout(increaseCounter, 0);
+ setTimeout(increaseCounter, 0);
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_sync_xhr_unload.html b/dom/xhr/tests/test_sync_xhr_unload.html
new file mode 100644
index 000000000..b11ab1f75
--- /dev/null
+++ b/dom/xhr/tests/test_sync_xhr_unload.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1307122</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="common_temporaryFileBlob.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+info("Creating the iframe...");
+var ifr = document.createElement('iframe');
+
+ifr.addEventListener("load", function ifr_load1() {
+ info("Iframe loaded");
+
+ ifr.removeEventListener("load", ifr_load1);
+ ifr.src = "empty.html";
+
+ ifr.addEventListener("load", function ifr_load2() {
+ ok(true, "Test passed");
+ SimpleTest.finish();
+ });
+
+});
+
+ifr.src = "iframe_sync_xhr_unload.html";
+document.body.appendChild(ifr);
+
+ </script>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_temporaryFileBlob.html b/dom/xhr/tests/test_temporaryFileBlob.html
new file mode 100644
index 000000000..e4db56abd
--- /dev/null
+++ b/dom/xhr/tests/test_temporaryFileBlob.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1202006</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="common_temporaryFileBlob.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <script type="application/javascript">
+
+var tests = [
+ // from common_temporaryFileBlob.js:
+ test_simple,
+ test_reuse,
+ test_abort,
+
+ test_worker,
+ test_worker_reuse,
+ test_worker_abort,
+];
+
+function next() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+}
+
+SpecialPowers.pushPrefEnv({ "set" : [[ "dom.blob.memoryToTemporaryFile", 1 ]] },
+ next);
+SimpleTest.waitForExplicitFinish();
+
+ </script>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_worker_terminateSyncXHR.html b/dom/xhr/tests/test_worker_terminateSyncXHR.html
new file mode 100644
index 000000000..11cea07d9
--- /dev/null
+++ b/dom/xhr/tests/test_worker_terminateSyncXHR.html
@@ -0,0 +1,45 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads XHR(Bug 450452 )
+-->
+<head>
+ <title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
+<p id="display"></p>
+<div id="content">
+ <iframe id="iframe" src="worker_terminateSyncXHR_frame.html"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ var ifr = document.getElementById("iframe");
+
+ window.onmessage = function(event) {
+ if (event.data == "TERMINATE") {
+ ok(true, "Got TERMINATE");
+ ifr.parentNode.removeChild(ifr);
+ SimpleTest.finish();
+ } else {
+ ok(false, "Unexpected message: " + event.data);
+ }
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ window.onload = function() {
+ ifr.contentWindow.doStuff();
+ }
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/xhr/tests/test_worker_xhr.html b/dom/xhr/tests/test_worker_xhr.html
new file mode 100644
index 000000000..0e875b7f4
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr.html
@@ -0,0 +1,73 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads XHR(Bug 450452 )
+-->
+<head>
+ <title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ var worker = new Worker("xhr_worker.js");
+
+ var gotUploadLoad = false, gotLoadend = false;
+
+ worker.onmessage = function(event) {
+ is(event.target, worker);
+ var args = event.data;
+ switch (args.type) {
+ case "progress": {
+ ok(parseInt(args.current) <= parseInt(args.total));
+ } break;
+ case "error": {
+ ok(false, "XHR error: " + args.error);
+ } break;
+ case "upload.load": {
+ gotUploadLoad = true;
+ } break;
+ case "load": {
+ ok(gotUploadLoad, "Should have gotten upload load event");
+ gotLoadend = true;
+ is(args.data, "A noisy noise annoys an oyster.", "correct data");
+ document.getElementById("content").textContent = args.data;
+ } break;
+ case "loadend": {
+ ok(gotLoadend, "Should have gotten load.");
+ SimpleTest.finish();
+ break;
+ }
+ default: {
+ ok(false, "Unexpected message");
+ SimpleTest.finish();
+ }
+ }
+ };
+
+ worker.onerror = function(event) {
+ is(event.target, worker);
+ ok(false, "Worker had an error:" + event.message);
+ SimpleTest.finish();
+ }
+
+ worker.postMessage("worker_testXHR.txt");
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/xhr/tests/test_worker_xhr2.html b/dom/xhr/tests/test_worker_xhr2.html
new file mode 100644
index 000000000..5f1816e45
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr2.html
@@ -0,0 +1,38 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads XHR(Bug 450452 )
+-->
+<head>
+ <title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ var worker = new Worker("xhr2_worker.js");
+
+ worker.onmessage = function(event) {
+ is(event.data, "done", "Got correct result");
+ SimpleTest.finish();
+ }
+ worker.postMessage("worker_testXHR.txt");
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/xhr/tests/test_worker_xhrAbort.html b/dom/xhr/tests/test_worker_xhrAbort.html
new file mode 100644
index 000000000..0f4b93c5a
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhrAbort.html
@@ -0,0 +1,44 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads XHR(Bug 450452 )
+-->
+<head>
+ <title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script language="javascript" src="xhrAbort_worker.js"></script>
+<script class="testbody" language="javascript">
+
+ function postMessage(data) {
+ dump(data.toString() + "\n");
+
+ var worker = new Worker("xhrAbort_worker.js");
+
+ worker.onmessage = function(event) {
+ is (data.toString(), event.data.toString(), "Got different results!");
+ SimpleTest.finish();
+ };
+
+ worker.postMessage("start");
+ }
+
+ runTest();
+
+ SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_worker_xhr_3rdparty.html b/dom/xhr/tests/test_worker_xhr_3rdparty.html
new file mode 100644
index 000000000..46951012a
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_3rdparty.html
@@ -0,0 +1,74 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads XHR(Bug 450452 )
+-->
+<head>
+ <title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ var worker = new Worker("xhr_worker.js");
+
+ var gotUploadLoad = false, gotLoadend = false;
+
+ worker.onmessage = function(event) {
+ is(event.target, worker);
+ var args = event.data;
+ switch (args.type) {
+ case "progress": {
+ ok(parseInt(args.current) <= parseInt(args.total));
+ } break;
+ case "error": {
+ ok(false, "XHR error: " + args.error);
+ } break;
+ case "upload.load": {
+ gotUploadLoad = true;
+ } break;
+ case "load": {
+ ok(gotUploadLoad, "Should have gotten upload load event");
+ gotLoadend = true;
+ is(args.data, "a=cookie_is_set", "correct data");
+ document.getElementById("content").textContent = args.data;
+ } break;
+ case "loadend": {
+ ok(gotLoadend, "Should have gotten load.");
+ SimpleTest.finish();
+ break;
+ }
+ default: {
+ ok(false, "Unexpected message");
+ SimpleTest.finish();
+ }
+ }
+ };
+
+ worker.onerror = function(event) {
+ is(event.target, worker);
+ ok(false, "Worker had an error:" + event.message);
+ SimpleTest.finish();
+ }
+
+ document.cookie = "a=cookie_is_set";
+ SpecialPowers.pushPrefEnv({ set: [[ "network.cookie.cookieBehavior", 1 ]] },
+ () => worker.postMessage("worker_file_getcookie.sjs"));
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_worker_xhr_cors_redirect.html b/dom/xhr/tests/test_worker_xhr_cors_redirect.html
new file mode 100644
index 000000000..40967d5d8
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_cors_redirect.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1206121</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+"use strict";
+
+var worker = new Worker("worker_xhr_cors_redirect.js");
+worker.onmessage = function(e) {
+ is(e.data, 200, "We want to read 200 here.");
+ runTests();
+};
+
+var tests = [ 'http://example.com/tests/dom/xhr/tests/worker_xhr_cors_redirect.sjs',
+ 'http://example.com/tests/dom/xhr/tests/worker_xhr_cors_redirect.sjs?redirect',
+ 'worker_xhr_cors_redirect.sjs?redirect' ];
+function runTests() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ worker.postMessage(tests.shift());
+}
+
+SimpleTest.waitForExplicitFinish();
+ </script>
+</head>
+<body onload="runTests()">
+</body>
+</html>
diff --git a/dom/xhr/tests/test_worker_xhr_headers.html b/dom/xhr/tests/test_worker_xhr_headers.html
new file mode 100644
index 000000000..1416ababd
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_headers.html
@@ -0,0 +1,86 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Test for XHR Headers</title>
+ <script src="/tests/SimpleTest/SimpleTest.js">
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+ </head>
+ <body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ <script class="testbody">
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+
+var path =
+ location.pathname.substring(0, location.pathname.lastIndexOf("/") + 1);
+var filenamePrefix = "worker_xhr_headers_";
+var serverFilename = filenamePrefix + "server.sjs";
+var workerFilename = filenamePrefix + "worker.js";
+var otherHost = "example.com";
+
+info("Informing server about the current host");
+
+var xhr = new XMLHttpRequest();
+xhr.open("POST", path + serverFilename);
+xhr.setRequestHeader("options-host", otherHost);
+xhr.setRequestHeader("empty", "");
+xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ info("Launching worker");
+
+ var worker = new Worker(path + workerFilename);
+ worker.postMessage("http://" + otherHost + path + serverFilename);
+
+ worker.onmessage = function(event) {
+ ok(event.data.response === "", "Worker responded, saw no response");
+
+ var loopCount = 0;
+
+ function checkServer() {
+ var xhr2 = new XMLHttpRequest();
+ xhr2.open("GET", path + serverFilename);
+ xhr2.onreadystatechange = function() {
+ if (xhr2.readyState == 4) {
+ if (xhr2.responseText) {
+ is(xhr2.responseText,
+ "Success: expected OPTIONS request with '" +
+ event.data.header + "' header",
+ "Server saw expected requests");
+ SimpleTest.finish();
+ } else if (++loopCount < 30) {
+ setTimeout(checkServer, 1000);
+ } else {
+ ok(false, "Server never saw any requests");
+ SimpleTest.finish();
+ }
+ }
+ };
+
+ info("Checking server status (" + loopCount + ")");
+ xhr2.send();
+ }
+
+ checkServer();
+ };
+
+ worker.onerror = function(event) {
+ ok(false, "Worker had an error: '" + event.message + "'");
+ event.preventDefault();
+ SimpleTest.finish();
+ };
+ }
+};
+xhr.send();
+
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/dom/xhr/tests/test_worker_xhr_implicit_cancel.html b/dom/xhr/tests/test_worker_xhr_implicit_cancel.html
new file mode 100644
index 000000000..a9efb14b9
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_implicit_cancel.html
@@ -0,0 +1,44 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads XHR(Bug 450452 )
+-->
+<head>
+ <title>Test for DOM Worker Threads XHR (Bug 450452 )</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450452">DOM Worker Threads XHR (Bug 450452)</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ var worker = new Worker("xhr_implicit_cancel_worker.js");
+
+ worker.onmessage = function(event) {
+ is(event.target, worker, "Expected event target for message");
+ ok(true, "Worker didn't have an error");
+ SimpleTest.finish();
+ };
+
+ worker.onerror = function(event) {
+ is(event.target, worker, "Expected event target for error");
+ ok(false, "Worker had an error:" + event.message);
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/xhr/tests/test_worker_xhr_parameters.html b/dom/xhr/tests/test_worker_xhr_parameters.html
new file mode 100644
index 000000000..ae880aabb
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_parameters.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for XMLHttpRequest with system privileges</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+function message(event) {
+ if (event.data.test == 'ok')
+ ok(event.data.a, event.data.event);
+ else if(event.data.test == 'is')
+ is(event.data.a, event.data.b, event.data.event);
+ else if(event.data.test == 'finish') {
+ run();
+ }
+};
+
+function test1() {
+ var worker = new Worker("test_worker_xhr_parameters.js");
+ worker.onmessage = message;
+
+ // Run the tests once without API privileges...
+ worker.postMessage(false);
+}
+
+function test2() {
+ // ...and once with privileges.
+ SpecialPowers.pushPermissions([{type: "systemXHR", allow: true, context: document}],
+ function () {
+ var worker = new Worker("test_worker_xhr_parameters.js");
+ worker.onmessage = message;
+ worker.postMessage(true);
+ }
+ );
+}
+
+var tests = [ test1, test2 ];
+function run() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var func = tests.shift();
+ func();
+}
+
+SimpleTest.waitForExplicitFinish();
+run();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_worker_xhr_parameters.js b/dom/xhr/tests/test_worker_xhr_parameters.js
new file mode 100644
index 000000000..80db35a43
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_parameters.js
@@ -0,0 +1,75 @@
+function ok(what, msg) {
+ postMessage({ event: msg, test: 'ok', a: what });
+}
+
+function is(a, b, msg) {
+ postMessage({ event: msg, test: 'is', a: a, b: b });
+}
+
+// This is a copy of dom/xhr/tests/test_XHR_parameters.js
+var validParameters = [
+ undefined,
+ null,
+ {},
+ {mozSystem: ""},
+ {mozSystem: 0},
+ {mozAnon: 1},
+ {mozAnon: []},
+ {get mozAnon() { return true; }},
+ 0,
+ 7,
+ Math.PI,
+ "string",
+ true,
+ false,
+];
+
+var invalidParameters = [
+ {get mozSystem() { throw "Bla"; } },
+];
+
+
+function testParameters(havePrivileges) {
+
+ function testValidParameter(value) {
+ var xhr;
+ try {
+ xhr = new XMLHttpRequest(value);
+ } catch (ex) {
+ ok(false, "Got unexpected exception: " + ex);
+ return;
+ }
+ ok(!!xhr, "passed " + JSON.stringify(value));
+
+ // If the page doesnt have privileges to create a system or anon XHR,
+ // these flags will always be false no matter what is passed.
+ var expectedAnon = false;
+ var expectedSystem = false;
+ if (havePrivileges) {
+ expectedAnon = Boolean(value && value.mozAnon);
+ expectedSystem = Boolean(value && value.mozSystem);
+ }
+ is(xhr.mozAnon, expectedAnon, "testing mozAnon");
+ is(xhr.mozSystem, expectedSystem, "testing mozSystem");
+ }
+
+
+ function testInvalidParameter(value) {
+ try {
+ new XMLHttpRequest(value);
+ ok(false, "invalid parameter did not cause exception: " +
+ JSON.stringify(value));
+ } catch (ex) {
+ ok(true, "invalid parameter raised exception as expected: " +
+ JSON.stringify(ex));
+ }
+ }
+
+ validParameters.forEach(testValidParameter);
+ invalidParameters.forEach(testInvalidParameter);
+}
+
+self.onmessage = function onmessage(event) {
+ testParameters(event.data);
+ postMessage({test: "finish"});
+};
diff --git a/dom/xhr/tests/test_worker_xhr_responseURL.html b/dom/xhr/tests/test_worker_xhr_responseURL.html
new file mode 100644
index 000000000..424d0b95d
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_responseURL.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=998076
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 998076</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+/** Test for Bug 998076 **/
+"use strict";
+
+var worker = new Worker("../../../dom/xhr/tests/file_XHRResponseURL.js");
+
+var requestObserver = {
+ observe: function (aSubject, aTopic, aData) {
+ worker.postMessage("request");
+ }
+};
+
+worker.addEventListener("message", function (aEvent) {
+ var data = aEvent.data;
+ if (data == "done") {
+ SimpleTest.finish();
+ return;
+ }
+ if (data == "start") {
+ return;
+ }
+ if (data.type == "is") {
+ SimpleTest.is(data.actual, data.expected, data.message);
+ worker.postMessage("pong");
+ return;
+ }
+ if (data.type == "ok") {
+ SimpleTest.ok(data.bool, data.message);
+ worker.postMessage("pong");
+ return;
+ }
+ if (data.type == "info") {
+ SimpleTest.info(data.message);
+ worker.postMessage("pong");
+ return;
+ }
+ if (data.type === "redirect_test") {
+ if (data.status === "start") {
+ SpecialPowers.addObserver(requestObserver, "specialpowers-http-notify-request", false);
+ return;
+ }
+ if (data.status === "end") {
+ SpecialPowers.removeObserver(requestObserver, "specialpowers-http-notify-request");
+ return;
+ }
+ }
+});
+
+function runTests() {
+ SimpleTest.waitForExplicitFinish();
+ worker.postMessage("start");
+}
+
+ </script>
+</head>
+<body onload="runTests()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=998076">Mozilla Bug 998076</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_worker_xhr_system.html b/dom/xhr/tests/test_worker_xhr_system.html
new file mode 100644
index 000000000..6de0016e2
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_system.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for XMLHttpRequest with system privileges</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+function message(event) {
+ if (event.data.test == 'ok')
+ ok(event.data.a, event.data.event);
+ else if(event.data.test == 'is')
+ is(event.data.a, event.data.b, event.data.event);
+ else if(event.data.test == 'finish') {
+ run();
+ }
+};
+
+function test1() {
+ var worker = new Worker("test_worker_xhr_system.js");
+ worker.onmessage = message;
+ worker.postMessage(true);
+}
+
+var tests = [ test1 ];
+function run() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var func = tests.shift();
+ func();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], run);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_worker_xhr_system.js b/dom/xhr/tests/test_worker_xhr_system.js
new file mode 100644
index 000000000..5ad63225c
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_system.js
@@ -0,0 +1,30 @@
+function ok(what, msg) {
+ postMessage({ event: msg, test: 'ok', a: what });
+}
+
+function is(a, b, msg) {
+ postMessage({ event: msg, test: 'is', a: a, b: b });
+}
+
+self.onmessage = function onmessage(event) {
+
+ // An XHR with system privileges will be able to do cross-site calls.
+
+ const TEST_URL = "http://example.com/tests/dom/xhr/tests/test_XHR_system.html";
+ is(location.hostname, "mochi.test", "hostname should be mochi.test");
+
+ var xhr = new XMLHttpRequest({mozSystem: true});
+ is(xhr.mozSystem, true, ".mozSystem == true");
+ xhr.open("GET", TEST_URL);
+ xhr.onload = function onload() {
+ is(xhr.status, 200);
+ ok(xhr.responseText != null);
+ ok(xhr.responseText.length);
+ postMessage({test: "finish"});
+ };
+ xhr.onerror = function onerror() {
+ ok(false, "Got an error event!");
+ postMessage({test: "finish"});
+ }
+ xhr.send();
+};
diff --git a/dom/xhr/tests/test_worker_xhr_timeout.html b/dom/xhr/tests/test_worker_xhr_timeout.html
new file mode 100644
index 000000000..d9bb6a7ae
--- /dev/null
+++ b/dom/xhr/tests/test_worker_xhr_timeout.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=498998
+-->
+<head>
+ <title>Test for Bug 498998</title>
+ <script type="application/javascript"
+ src="/MochiKit/MochiKit.js"></script>
+ <script type="application/javascript"
+ src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet"
+ type="text/css"
+ href="/tests/SimpleTest/test.css">
+</head>
+<body>
+
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=498998"
+ >Mozilla Bug 498998 (Worker XMLHttpRequest timeout)</a>
+<p id="display"></p>
+<div id="content">
+ This test takes over 1 minute to run, probably over 2 minutes.
+</div>
+<pre id="test">
+<script type="text/javascript">
+ var worker = new Worker("../../../dom/xhr/tests/test_XHR_timeout.js");
+
+ worker.addEventListener("message", function (event) {
+ if (event.data == "done") {
+ SimpleTest.finish();
+ return;
+ }
+ if (event.data == "start") {
+ return;
+ }
+ if (event.data.type == "is") {
+ SimpleTest.is(event.data.got, event.data.expected, event.data.msg);
+ return;
+ }
+ if (event.data.type == "ok") {
+ SimpleTest.ok(event.data.bool, event.data.msg);
+ return;
+ }
+ });
+ // Final test harness setup and launch.
+ (function() {
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestLongerTimeout(20);
+ var msg = "This test will take approximately " + (20 * 10)
+ msg += " seconds to complete, at most.";
+ document.getElementById("content").firstChild.nodeValue = msg;
+ worker.postMessage("start");
+ })();
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_xhr_abort_after_load.html b/dom/xhr/tests/test_xhr_abort_after_load.html
new file mode 100644
index 000000000..780c11253
--- /dev/null
+++ b/dom/xhr/tests/test_xhr_abort_after_load.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test bug 482935</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href=" /tests/SimpleTest/test.css" />
+</head>
+<body onload="onWindowLoad()">
+<script class="testbody" type="text/javascript">"use strict";
+SimpleTest.waitForExplicitFinish();
+
+var url = "file_XHR_pass1.xml";
+
+function onWindowLoad() {
+ runTest();
+}
+
+function runTest() {
+ var testFunctions = [
+ startTest1,
+ startTest2,
+ startTest3,
+ ];
+
+ function nextTest() {
+ if (testFunctions.length == 0) {
+ SimpleTest.finish();
+ return;
+ }
+ (testFunctions.shift())();
+ }
+
+ nextTest();
+
+ var xhr;
+ function startTest1() {
+ xhr = new XMLHttpRequest();
+ xhr.onload = onLoad1;
+ xhr.open("GET", url);
+ xhr.send();
+ }
+
+ function onLoad1() {
+ is(xhr.readyState, xhr.DONE, "readyState should be DONE");
+ xhr.onabort = onAbort1;
+ xhr.abort();
+
+ function onAbort1(e) {
+ ok(false, e.type + " event should not be fired!");
+ }
+
+ is(xhr.readyState, xhr.UNSENT, "readyState should be UNSENT");
+ nextTest();
+ }
+
+ function startTest2() {
+ xhr = new XMLHttpRequest();
+ xhr.onloadstart = onAfterSend;
+ xhr.open("GET", url);
+ xhr.send();
+ }
+
+ function startTest3() {
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+ xhr.send();
+ onAfterSend();
+ }
+
+ function onAfterSend() {
+ is(xhr.readyState, xhr.OPENED, "readyState should be OPENED");
+ var sent = false;
+ try {
+ xhr.send();
+ } catch (e) {
+ sent = true;
+ }
+ ok(sent, "send() flag should be set");
+ var aborted = false;
+ xhr.onabort = onAbort2;
+ xhr.abort();
+
+ function onAbort2() {
+ is(xhr.readyState, xhr.DONE, "readyState should be DONE");
+ aborted = true;
+ }
+
+ ok(aborted, "abort event should be fired");
+ is(xhr.readyState, xhr.UNSENT, "readyState should be UNSENT");
+ nextTest();
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_xhr_forbidden_headers.html b/dom/xhr/tests/test_xhr_forbidden_headers.html
new file mode 100644
index 000000000..fc076731e
--- /dev/null
+++ b/dom/xhr/tests/test_xhr_forbidden_headers.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=308484
+-->
+<head>
+ <title>Test for Bug 308484</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=308484">Mozilla Bug 308484</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 308484 **/
+
+var headers = [
+ "aCCept-chaRset",
+ "acCePt-eNcoDing",
+ "aCcEsS-cOnTrOl-ReQuEsT-mEtHoD",
+ "aCcEsS-cOnTrOl-ReQuEsT-hEaDeRs",
+ "coNnEctIon",
+ "coNtEnt-LEngth",
+ "CoOKIe",
+ "cOOkiE2",
+ "DATE",
+ "dNT",
+ "exPeCt",
+ "hOSt",
+ "keep-alive",
+ "oRiGiN",
+ "reFERer",
+ "te",
+ "trAiLer",
+ "trANsfEr-eNcoDiNg",
+ "uPGraDe",
+ "viA",
+ "pRoxy-",
+ "sEc-",
+ "proxy-fOobar",
+ "sec-bAZbOx"
+];
+var i, request;
+
+function startTest() {
+ // Try setting headers in unprivileged context
+ request = new XMLHttpRequest();
+ request.open("GET", window.location.href);
+ for (i = 0; i < headers.length; i++)
+ request.setRequestHeader(headers[i], "test" + i);
+ request.send(); // headers aren't set on the channel until send()
+
+ // Read out headers
+ var channel = SpecialPowers.wrap(request).channel.QueryInterface(SpecialPowers.Ci.nsIHttpChannel);
+ for (i = 0; i < headers.length; i++) {
+ // Retrieving Content-Length will throw an exception
+ var value = null;
+ try {
+ value = channel.getRequestHeader(headers[i]);
+ }
+ catch(e) {}
+
+ isnot(value, "test" + i, "Setting " + headers[i] + " header in unprivileged context");
+ }
+
+ // Try setting headers in privileged context
+ request = new XMLHttpRequest({mozAnon: true, mozSystem: true});
+ request.open("GET", window.location.href);
+ for (i = 0; i < headers.length; i++)
+ request.setRequestHeader(headers[i], "test" + i);
+ request.send(); // headers aren't set on the channel until send()
+
+ // Read out headers
+ var channel = SpecialPowers.wrap(request).channel.QueryInterface(SpecialPowers.Ci.nsIHttpChannel);
+ for (i = 0; i < headers.length; i++) {
+ var value = channel.getRequestHeader(headers[i]);
+ is(value, "test" + i, "Setting " + headers[i] + " header in privileged context");
+ }
+
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+ SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], startTest);
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_xhr_overridemimetype_throws_on_invalid_state.html b/dom/xhr/tests/test_xhr_overridemimetype_throws_on_invalid_state.html
new file mode 100644
index 000000000..bdbbf1591
--- /dev/null
+++ b/dom/xhr/tests/test_xhr_overridemimetype_throws_on_invalid_state.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test bug 482935</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href=" /tests/SimpleTest/test.css" />
+</head>
+<body onload="onWindowLoad()">
+<script class="testbody" type="text/javascript">"use strict";
+SimpleTest.waitForExplicitFinish();
+
+var url = "file_XHR_pass1.xml";
+
+function onWindowLoad() {
+ runTest();
+}
+
+function runTest() {
+ var testFunctions = [
+ function() { testOverMimeTypeThrowsDuringReadyState(3, "application/xml"); },
+ function() { testOverMimeTypeThrowsDuringReadyState(3, "application/xml;charset=Shift-JIS"); },
+ function() { testOverMimeTypeThrowsDuringReadyState(4, "application/xml"); },
+ function() { testOverMimeTypeThrowsDuringReadyState(4, "application/xml;charset=Shift-JIS"); },
+ ];
+
+ function nextTest() {
+ if (testFunctions.length == 0) {
+ SimpleTest.finish();
+ return;
+ }
+ (testFunctions.shift())();
+ }
+
+ nextTest();
+
+ function testOverMimeTypeThrowsDuringReadyState(readyState, mimeType) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === readyState) {
+ try {
+ xhr.overrideMimeType(mimeType);
+ ok(false, "No exception thrown, but expected InvalidStateError" +
+ " for readyState=" + readyState + ", mimeType=" + mimeType);
+ } catch(exc) {
+ is(exc.name, "InvalidStateError", "Expected InvalidStateError, got " + exc.name +
+ " for readyState=" + readyState + ", mimeType=" + mimeType);
+ }
+ }
+ if (xhr.readyState === 4) {
+ is(xhr.responseXML, null, "responseXML was not null" +
+ " for readyState=" + readyState + ", mimeType=" + mimeType);
+ nextTest();
+ }
+ }
+ xhr.open("GET", url);
+ xhr.send();
+ }
+}
+</script>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_xhr_progressevents.html b/dom/xhr/tests/test_xhr_progressevents.html
new file mode 100644
index 000000000..f22927daf
--- /dev/null
+++ b/dom/xhr/tests/test_xhr_progressevents.html
@@ -0,0 +1,333 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for XMLHttpRequest Progress Events</title>
+ <script type="text/javascript" src="/MochiKit/packed.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="gen.next();">
+<pre id=l></pre>
+<script type="application/javascript;version=1.7">
+SimpleTest.waitForExplicitFinish();
+
+var gen = runTests();
+
+function log(s) {
+ // Uncomment these to get debugging information
+ /*
+ document.getElementById("l").textContent += s + "\n";
+ dump(s + "\n");
+ */
+}
+
+function getEvent(e) {
+ log("got event: " + e.type + " (" + e.target.readyState + ")");
+ gen.send(e);
+}
+
+function startsWith(a, b) {
+ return a.substr(0, b.length) === b;
+}
+
+function updateProgress(e, data, testName) {
+ var test = " while running " + testName;
+ is(e.type, "progress", "event type" + test);
+
+ let response;
+ if (data.nodata) {
+ is(e.target.response, null, "response should be null" + test);
+ response = null;
+ }
+ else if (data.text) {
+ is(typeof e.target.response, "string", "response should be a string" + test);
+ response = e.target.response;
+ }
+ else if (data.blob) {
+ ok(e.target.response instanceof Blob, "response should be a Blob" + test);
+ response = e.target.response;
+ }
+ else {
+ ok(e.target.response instanceof ArrayBuffer, "response should be an ArrayBuffer" + test);
+ response = bufferToString(e.target.response);
+ }
+ is(e.target.response, e.target.response, "reflexivity should hold" + test);
+
+ if (!data.nodata && !data.encoded) {
+ if (data.blob) {
+ is(e.loaded, response.size, "event.loaded matches response size" + test);
+ }
+ else if (!data.chunked) {
+ is(e.loaded, response.length, "event.loaded matches response size" + test);
+ }
+ else {
+ is(e.loaded - data.receivedBytes, response.length,
+ "event.loaded grew by response size" + test);
+ }
+ }
+ ok(e.loaded > data.receivedBytes, "event.loaded increased" + test);
+ ok(e.loaded - data.receivedBytes <= data.pendingBytes,
+ "event.loaded didn't increase too much" + test);
+
+ if (!data.nodata && !data.blob) {
+ var newData;
+ ok(startsWith(response, data.receivedResult),
+ "response strictly grew" + test);
+ newData = response.substr(data.receivedResult.length);
+
+ if (!data.encoded) {
+ ok(newData.length > 0, "sanity check for progress" + test);
+ }
+ ok(startsWith(data.pendingResult, newData), "new data matches expected" + test);
+ }
+
+ is(e.lengthComputable, "total" in data, "lengthComputable" + test);
+ if ("total" in data) {
+ is(e.total, data.total, "total" + test);
+ }
+
+ if (!data.nodata && !data.blob) {
+ data.pendingResult = data.pendingResult.substr(newData.length);
+ }
+ data.pendingBytes -= e.loaded - data.receivedBytes;
+ data.receivedResult = response;
+ data.receivedBytes = e.loaded;
+}
+
+function sendData(s) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", "progressserver.sjs?send");
+ // The Blob constructor encodes String elements as UTF-8;
+ // for straight bytes, manually convert to ArrayBuffer first
+ var buffer = new Uint8Array(s.length);
+ for (var i = 0; i < s.length; ++i) {
+ buffer[i] = s.charCodeAt(i) & 0xff;
+ };
+ xhr.send(new Blob([buffer]));
+}
+
+function closeConn() {
+ log("in closeConn");
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", "progressserver.sjs?close");
+ xhr.send();
+ return xhr;
+}
+
+var longString = "long";
+while(longString.length < 65536)
+ longString += longString;
+
+function utf8encode(s) {
+ return unescape(encodeURIComponent(s));
+}
+
+function bufferToString(buffer) {
+ return String.fromCharCode.apply(String, new Uint8Array(buffer));
+}
+
+function runTests() {
+ var xhr = new XMLHttpRequest();
+ xhr.onprogress = xhr.onload = xhr.onerror = xhr.onreadystatechange = xhr.onloadend = getEvent;
+
+ var responseTypes = [{ type: "text", text: true },
+ { type: "arraybuffer", text: false, nodata: true },
+ { type: "blob", text: false, nodata: true, blob: true },
+ { type: "moz-blob", text: false, nodata: false, blob: true },
+ { type: "document", text: true, nodata: true },
+ { type: "json", text: true, nodata: true },
+ { type: "", text: true },
+ { type: "moz-chunked-text", text: true, chunked: true },
+ { type: "moz-chunked-arraybuffer", text: false, chunked: true },
+ ];
+ var responseType;
+ var fileExpectedResult = "";
+ for (var i = 0; i < 65536; i++) {
+ fileExpectedResult += String.fromCharCode(i & 255);
+ }
+ while (responseType = responseTypes.shift()) {
+ let tests = [{ open: "Content-Type=text/plain", name: "simple test" },
+ { data: "hello world" },
+ { data: "\u0000\u0001\u0002\u0003" },
+ { data: longString },
+ { data: "x" },
+ { close: true },
+ { open: "Content-Type=text/plain&Content-Length=20", name: "with length", total: 20 },
+ // 5 bytes from the "ready" in the open step
+ { data: "abcde" },
+ { data: "0123456789" },
+ { close: true },
+ { open: "Content-Type=application/xml", name: "without length, as xml" },
+ { data: "<out>" },
+ { data: "text" },
+ { data: "</foo>invalid" },
+ { close: true },
+ { open: "Content-Type=text/plain;charset%3dutf-8", name: "utf8 data", encoded: true },
+ { data: utf8encode("räksmörgås"), utf16: "räksmörgås" },
+ { data: utf8encode("Ã…").substr(0,1), utf16: "" },
+ { data: utf8encode("Ã…").substr(1), utf16: "Ã…" },
+ { data: utf8encode("aöb").substr(0,2), utf16: "a" },
+ { data: utf8encode("aöb").substr(2), utf16: "öb" },
+ { data: utf8encode("a\u867Eb").substr(0,3), utf16: "a" },
+ { data: utf8encode("a\u867Eb").substr(3,1), utf16: "\u867E" },
+ { data: utf8encode("a\u867Eb").substr(4), utf16: "b" },
+ { close: true },
+ ];
+ if (responseType.blob) {
+ tests.push({ file: "file_XHR_binary2.bin", name: "cacheable data", total: 65536 },
+ { close: true },
+ { file: "file_XHR_binary2.bin", name: "cached data", total: 65536 },
+ { close: true });
+ }
+ let testState = { index: 0 };
+
+ for (let i = 0; i < tests.length; ++i) {
+ let test = tests[i];
+ testState.index++;
+ if ("open" in test || "file" in test) {
+ log("opening " + testState.name);
+ testState = { name: test.name + " for " + responseType.type,
+ index: 0,
+ pendingResult: "ready",
+ pendingBytes: 5,
+ receivedResult: "",
+ receivedBytes: 0,
+ total: test.total,
+ encoded: test.encoded,
+ nodata: responseType.nodata,
+ chunked: responseType.chunked,
+ text: responseType.text,
+ blob: responseType.blob,
+ file: test.file };
+
+ xhr.onreadystatechange = null;
+ if (testState.file)
+ xhr.open("GET", test.file);
+ else
+ xhr.open("POST", "progressserver.sjs?open&" + test.open);
+ xhr.responseType = responseType.type;
+ xhr.send("ready");
+ xhr.onreadystatechange = getEvent;
+
+ let e = yield undefined;
+ is(e.type, "readystatechange", "should readystate to headers-received starting " + testState.name);
+ is(xhr.readyState, xhr.HEADERS_RECEIVED, "should be in state HEADERS_RECEIVED starting " + testState.name);
+
+ e = yield undefined;
+ is(e.type, "readystatechange", "should readystate to loading starting " + testState.name);
+ is(xhr.readyState, xhr.LOADING, "should be in state LOADING starting " + testState.name);
+ if (typeof testState.total == "undefined")
+ delete testState.total;
+ }
+ if ("file" in test) {
+ testState.pendingBytes = testState.total;
+ testState.pendingResult = fileExpectedResult;
+ }
+ if ("close" in test) {
+ log("closing");
+ let xhrClose;
+ if (!testState.file)
+ xhrClose = closeConn();
+
+ e = yield undefined;
+ is(e.type, "readystatechange", "should readystate to done closing " + testState.name);
+ is(xhr.readyState, xhr.DONE, "should be in state DONE closing " + testState.name);
+ log("readystate to 4");
+
+ if (responseType.chunked) {
+ xhr.responseType;
+ is(xhr.response, null, "chunked data has null response for " + testState.name);
+ }
+
+ e = yield undefined;
+ is(e.type, "load", "should fire load closing " + testState.name);
+ is(e.lengthComputable, e.total != 0, "length should " + (e.total == 0 ? "not " : "") + "be computable during load closing " + testState.name);
+ log("got load");
+
+ if (responseType.chunked) {
+ is(xhr.response, null, "chunked data has null response for " + testState.name);
+ }
+
+ e = yield undefined;
+ is(e.type, "loadend", "should fire loadend closing " + testState.name);
+ is(e.lengthComputable, e.total != 0, "length should " + (e.total == 0 ? "not " : "") + "be computable during loadend closing " + testState.name);
+ log("got loadend");
+
+ // if we closed the connection using an explicit request, make sure that goes through before
+ // running the next test in order to avoid reordered requests from closing the wrong
+ // connection.
+ if (xhrClose && xhrClose.readyState != xhrClose.DONE) {
+ log("wait for closeConn to finish");
+ xhrClose.onloadend = getEvent;
+ yield undefined;
+ is(xhrClose.readyState, xhrClose.DONE, "closeConn finished");
+ }
+
+ if (responseType.chunked) {
+ is(xhr.response, null, "chunked data has null response for " + testState.name);
+ }
+
+ if (!testState.nodata && !responseType.blob || responseType.chunked) {
+ // This branch intentionally left blank
+ // Under these conditions we check the response during updateProgress
+ }
+ else if (responseType.type === "arraybuffer") {
+ is(bufferToString(xhr.response), testState.pendingResult,
+ "full response for " + testState.name);
+ }
+ else if (responseType.blob) {
+ let reader = new FileReader;
+ reader.readAsBinaryString(xhr.response);
+ reader.onloadend = getEvent;
+ yield undefined;
+
+ is(reader.result, testState.pendingResult,
+ "full response in blob for " + testState.name);
+ }
+
+ testState.name = "";
+ }
+ if ("data" in test) {
+ log("sending");
+ if (responseType.text) {
+ testState.pendingResult += "utf16" in test ? test.utf16 : test.data;
+ }
+ else {
+ testState.pendingResult += test.data;
+ }
+ testState.pendingBytes = test.data.length;
+ sendData(test.data);
+ }
+
+ while(testState.pendingBytes) {
+ log("waiting for more bytes: " + testState.pendingBytes);
+ e = yield undefined;
+ // Readystate can fire several times between each progress event.
+ if (e.type === "readystatechange")
+ continue;
+
+ updateProgress(e, testState, "data for " + testState.name + "[" + testState.index + "]");
+ if (responseType.chunked) {
+ testState.receivedResult = "";
+ }
+ }
+
+ if (!testState.nodata && !testState.blob) {
+ is(testState.pendingResult, "",
+ "should have consumed the expected result");
+ }
+
+ log("done with this test");
+ }
+
+ is(testState.name, "", "forgot to close last test");
+ }
+
+ SimpleTest.finish();
+ yield undefined;
+}
+
+</script>
+
+</body>
+</html>
diff --git a/dom/xhr/tests/test_xhr_send.html b/dom/xhr/tests/test_xhr_send.html
new file mode 100644
index 000000000..6633dcb15
--- /dev/null
+++ b/dom/xhr/tests/test_xhr_send.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1096263
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1096263</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1096263 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function simpleGetTest() {
+ var x = new XMLHttpRequest();
+ x.open("GET", "echo.sjs");
+ x.onload = function() {
+ ok(true, "Should have processed GET");
+ simplePostTest();
+ }
+ x.send({});
+}
+
+function simplePostTest() {
+ var x = new XMLHttpRequest();
+ x.open("POST", "echo.sjs");
+ x.onload = function() {
+ is(x.responseText, "somedata", "Should have processed POST");
+ undefinedPostTest();
+ }
+ x.send({toString: function() { return "somedata"; }});
+}
+
+function undefinedPostTest() {
+ var x = new XMLHttpRequest();
+ x.open("POST", "echo.sjs");
+ x.onload = function() {
+ is(x.responseText, "undefined", "Should have processed POST");
+ nullPostTest();
+ }
+ x.send({toString: function() { return undefined; }});
+}
+
+function nullPostTest() {
+ var x = new XMLHttpRequest();
+ x.open("POST", "echo.sjs");
+ x.onload = function() {
+ is(x.responseText, "null", "Should have processed POST");
+ testExceptionInToString();
+ }
+ x.send({toString: function() { return null; }});
+}
+
+function testExceptionInToString() {
+ var x = new XMLHttpRequest();
+ x.open("GET", "echo.sjs");
+ x.onload = function() {
+ ok(false);
+ SimpleTest.finish();
+ }
+ try {
+ x.send({toString: function() { throw "dummy"; }});
+ } catch(ex) {
+ is(ex, "dummy");
+ SimpleTest.finish();
+ }
+}
+
+ </script>
+</head>
+<body onload="simpleGetTest()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1096263">Mozilla Bug 1096263</a>
+<p id="display"></p>
+<div id="content">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_xhr_send_readystate.html b/dom/xhr/tests/test_xhr_send_readystate.html
new file mode 100644
index 000000000..1c86681de
--- /dev/null
+++ b/dom/xhr/tests/test_xhr_send_readystate.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=814064
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 814064</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=814064">Mozilla Bug 814064</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 814064 **/
+var xhr = new XMLHttpRequest();
+var firings = 0;
+function readyStateHandler() {
+ is(xhr.readyState, XMLHttpRequest.OPENED, "Should be in OPENED state");
+ ++firings;
+}
+xhr.onreadystatechange = readyStateHandler;
+xhr.open("GET", "");
+is(firings, 1, "Should have fired the readystatechange handler");
+xhr.send();
+is(firings, 1, "Should not have fired the readystatechange handler");
+xhr.onreadystatechange = null;
+xhr.abort();
+is(firings, 1, "Should not have fired the handler no-longer-registered handler");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/test_xhr_withCredentials.html b/dom/xhr/tests/test_xhr_withCredentials.html
new file mode 100644
index 000000000..71d7dcccf
--- /dev/null
+++ b/dom/xhr/tests/test_xhr_withCredentials.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=814050
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 814050</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=814050">Mozilla Bug 814050</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 814050, but modified now that the spec has changed **/
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "", false);
+xhr.withCredentials = true;
+ok(true, "Should not throw on withCredentials sets for sync XHR");
+
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "", true);
+xhr.withCredentials = true;
+ok(true, "Should not throw on withCredentials sets for async XHR");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/xhr/tests/worker_bug1300552.js b/dom/xhr/tests/worker_bug1300552.js
new file mode 100644
index 000000000..fbc58b880
--- /dev/null
+++ b/dom/xhr/tests/worker_bug1300552.js
@@ -0,0 +1,33 @@
+function info(msg) {
+ postMessage({type: 'info', msg: msg});
+}
+
+function ok(a, msg) {
+ postMessage({type: 'check', what: !!a, msg: msg});
+}
+
+function finish() {
+ postMessage({type: 'finish'});
+}
+
+info("Creating XHR...");
+var xhr = new XMLHttpRequest();
+xhr.open("POST", "echo.sjs");
+xhr.responseType = 'arraybuffer';
+
+info("Sending some data...");
+var data = new Array(256).join("1234567890ABCDEF");
+xhr.send({toString: function() { return data; }});
+
+var aborted = false;
+
+xhr.onprogress = function() {
+ info("Onprogress, we abort!");
+ aborted = true;
+ xhr.abort();
+}
+
+xhr.onloadend = function() {
+ ok(aborted, "We are still alive after an abort()!");
+ finish();
+}
diff --git a/dom/xhr/tests/worker_file_getcookie.sjs b/dom/xhr/tests/worker_file_getcookie.sjs
new file mode 100644
index 000000000..b5204bdd7
--- /dev/null
+++ b/dom/xhr/tests/worker_file_getcookie.sjs
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+function handleRequest(request, response) {
+ try {
+ var cookie = request.getHeader("Cookie");
+ } catch (e) {
+ cookie = "EMPTY_COOKIE";
+ }
+
+ // avoid confusing cache behaviors.
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-type", "text/plain", false);
+ response.setStatusLine(request.httpVersion, "200", "OK");
+ response.write(cookie);
+}
diff --git a/dom/xhr/tests/worker_temporaryFileBlob.js b/dom/xhr/tests/worker_temporaryFileBlob.js
new file mode 100644
index 000000000..db40f72a8
--- /dev/null
+++ b/dom/xhr/tests/worker_temporaryFileBlob.js
@@ -0,0 +1,29 @@
+importScripts('common_temporaryFileBlob.js');
+
+function info(msg) {
+ postMessage({type: 'info', msg: msg});
+}
+
+function ok(a, msg) {
+ postMessage({type: 'check', what: !!a, msg: msg});
+}
+
+function is(a, b, msg) {
+ ok(a === b, msg);
+}
+
+function next() {
+ postMessage({type: 'finish'});
+}
+
+onmessage = function(e) {
+ if (e.data == 'simple') {
+ test_simple();
+ } else if (e.data == 'abort') {
+ test_abort();
+ } else if (e.data == 'reuse') {
+ test_reuse();
+ } else {
+ ok(false, 'Something wrong happened');
+ }
+}
diff --git a/dom/xhr/tests/worker_terminateSyncXHR_frame.html b/dom/xhr/tests/worker_terminateSyncXHR_frame.html
new file mode 100644
index 000000000..04bd53ff1
--- /dev/null
+++ b/dom/xhr/tests/worker_terminateSyncXHR_frame.html
@@ -0,0 +1,25 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Test for SharedWorker</title>
+ </head>
+ <body>
+ <script type="text/javascript">
+ function doStuff() {
+ var worker = new Worker("terminateSyncXHR_worker.js");
+
+ worker.onmessage = function(event) {
+ parent.postMessage(event.data, "*");
+ };
+
+ worker.onerror = function(event) {
+ parent.postMessage("ERROR!", "*");
+ }
+ }
+ </script>
+ </body>
+</html>
diff --git a/dom/xhr/tests/worker_testXHR.txt b/dom/xhr/tests/worker_testXHR.txt
new file mode 100644
index 000000000..2beab22c6
--- /dev/null
+++ b/dom/xhr/tests/worker_testXHR.txt
@@ -0,0 +1 @@
+A noisy noise annoys an oyster. \ No newline at end of file
diff --git a/dom/xhr/tests/worker_xhr_cors_redirect.js b/dom/xhr/tests/worker_xhr_cors_redirect.js
new file mode 100644
index 000000000..c006b4a2e
--- /dev/null
+++ b/dom/xhr/tests/worker_xhr_cors_redirect.js
@@ -0,0 +1,10 @@
+onmessage = function(e) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', e.data, true);
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState === 4) {
+ postMessage(xhr.status);
+ }
+ };
+ xhr.send();
+};
diff --git a/dom/xhr/tests/worker_xhr_cors_redirect.sjs b/dom/xhr/tests/worker_xhr_cors_redirect.sjs
new file mode 100644
index 000000000..07e8ed5dc
--- /dev/null
+++ b/dom/xhr/tests/worker_xhr_cors_redirect.sjs
@@ -0,0 +1,10 @@
+function handleRequest(request, response) {
+ response.setHeader("Access-Control-Allow-Origin", "*");
+
+ if (request.queryString == 'redirect') {
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location", "worker_xhr_cors_redirect.sjs");
+ } else {
+ response.write("'hello world'");
+ }
+}
diff --git a/dom/xhr/tests/worker_xhr_headers_server.sjs b/dom/xhr/tests/worker_xhr_headers_server.sjs
new file mode 100644
index 000000000..624abb9fc
--- /dev/null
+++ b/dom/xhr/tests/worker_xhr_headers_server.sjs
@@ -0,0 +1,66 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+"use strict";
+
+function handleRequest(request, response) {
+ switch (request.method) {
+ case "POST":
+ try {
+ var optionsHost = request.getHeader("options-host");
+ } catch(e) { }
+
+ var headerFound = false;
+ if (optionsHost) {
+ setState("postHost", request.host);
+ setState("optionsHost", optionsHost);
+ headerFound = true;
+ }
+
+ try {
+ var emptyHeader = "nada" + request.getHeader("empty");
+ } catch(e) { }
+
+ if (emptyHeader && emptyHeader == "nada") {
+ setState("emptyHeader", "nada");
+ headerFound = true;
+ }
+ if (headerFound) {
+ return;
+ } else {
+ break;
+ }
+
+ case "OPTIONS":
+ if (getState("optionsHost") == request.host) {
+ try {
+ var optionsHeader =
+ request.getHeader("Access-Control-Request-Headers");
+ } catch(e) { }
+ setState("optionsHeader", "'" + optionsHeader + "'");
+ }
+ break;
+
+ case "GET":
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+
+ if (getState("postHost") == request.host &&
+ getState("emptyHeader") == "nada") {
+ var result = getState("optionsHeader");
+ if (result) {
+ response.write("Success: expected OPTIONS request with " + result +
+ " header");
+ } else if (getState("badGet") == 1) {
+ response.write("Error: unexpected GET request");
+ }
+ } else {
+ setState("badGet", "1");
+ response.write("Error: this response should never be seen");
+ }
+ return;
+ }
+
+ response.setStatusLine(request.httpVersion, 501, "Not Implemented");
+}
diff --git a/dom/xhr/tests/worker_xhr_headers_worker.js b/dom/xhr/tests/worker_xhr_headers_worker.js
new file mode 100644
index 000000000..af88b83ca
--- /dev/null
+++ b/dom/xhr/tests/worker_xhr_headers_worker.js
@@ -0,0 +1,16 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+"use strict";
+
+var customHeader = "custom-key";
+var customHeaderValue = "custom-key-value";
+
+self.onmessage = function(event) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", event.data, false);
+ xhr.setRequestHeader(customHeader, customHeaderValue);
+ xhr.send();
+ postMessage({ response: xhr.responseText, header: customHeader });
+}
diff --git a/dom/xhr/tests/xhr2_worker.js b/dom/xhr/tests/xhr2_worker.js
new file mode 100644
index 000000000..d355020c9
--- /dev/null
+++ b/dom/xhr/tests/xhr2_worker.js
@@ -0,0 +1,163 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+onmessage = function(event) {
+ const url = event.data;
+
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ xhr.send();
+
+ const refText = xhr.responseText;
+
+ function getResponse(type) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ if (type !== undefined) {
+ xhr.responseType = type;
+ }
+ xhr.send();
+ return xhr.response;
+ }
+
+ if (getResponse() != refText) {
+ throw new Error("unset responseType failed");
+ }
+
+ if (getResponse("") != refText) {
+ throw new Error("'' responseType failed");
+ }
+
+ if (getResponse("text") != refText) {
+ throw new Error("'text' responseType failed");
+ }
+
+ var array = new Uint8Array(getResponse("arraybuffer"));
+ if (String.fromCharCode.apply(String, array) != refText) {
+ throw new Error("'arraybuffer' responseType failed");
+ }
+
+ var blob = getResponse("blob");
+ if (new FileReaderSync().readAsText(blob) != refText) {
+ throw new Error("'blob' responseType failed");
+ }
+
+ // Make sure that we get invalid state exceptions when getting the wrong
+ // property.
+
+ function testResponseTextException(type) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ xhr.responseType = type;
+ xhr.send();
+
+ var exception;
+
+ try {
+ xhr.responseText;
+ }
+ catch(e) {
+ exception = e;
+ }
+
+ if (!exception) {
+ throw new Error("Failed to throw when getting responseText on '" + type +
+ "' type");
+ }
+
+ if (exception.name != "InvalidStateError") {
+ throw new Error("Unexpected error when getting responseText on '" + type +
+ "' type");
+ }
+
+ if (exception.code != DOMException.INVALID_STATE_ERR) {
+ throw new Error("Unexpected error code when getting responseText on '" + type +
+ "' type");
+ }
+ }
+
+ testResponseTextException("arraybuffer");
+ testResponseTextException("blob");
+
+ // Make sure "document" works, but returns text.
+ xhr = new XMLHttpRequest();
+
+ if (xhr.responseType != "text") {
+ throw new Error("Default value for responseType is wrong!");
+ }
+
+ xhr.open("GET", url, false);
+ xhr.responseType = "document";
+ xhr.send();
+
+ if (xhr.responseText != refText) {
+ throw new Error("'document' type not working correctly");
+ }
+
+ // Make sure setting responseType before open or after send fails.
+ var exception;
+
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+ xhr.responseType = "text";
+ xhr.onload = function(event) {
+ if (event.target.response != refText) {
+ throw new Error("Bad response!");
+ }
+
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+ xhr.responseType = "moz-chunked-text";
+
+ var lastIndex = 0;
+ xhr.onprogress = function(event) {
+ if (refText.substr(lastIndex, xhr.response.length) != xhr.response) {
+ throw new Error("Bad chunk!");
+ }
+
+ lastIndex += xhr.response.length;
+ };
+
+ xhr.onload = function(event) {
+ if (lastIndex != refText.length) {
+ throw new Error("Didn't see all the data!");
+ }
+
+ setTimeout(function() {
+ if (xhr.response !== null) {
+ throw new Error("Should have gotten null response outside of event!");
+ }
+ postMessage("done");
+ }, 0);
+ }
+
+ xhr.send(null);
+ };
+ xhr.send();
+
+ exception = null;
+
+ try {
+ xhr.responseType = "arraybuffer";
+ }
+ catch(e) {
+ exception = e;
+ }
+
+ if (!exception) {
+ throw new Error("Failed to throw when setting responseType after " +
+ "calling send()");
+ }
+
+ if (exception.name != "InvalidStateError") {
+ throw new Error("Unexpected error when setting responseType after " +
+ "calling send()");
+ }
+
+ if (exception.code != DOMException.INVALID_STATE_ERR) {
+ throw new Error("Unexpected error code when setting responseType after " +
+ "calling send()");
+ }
+}
diff --git a/dom/xhr/tests/xhrAbort_worker.js b/dom/xhr/tests/xhrAbort_worker.js
new file mode 100644
index 000000000..281781761
--- /dev/null
+++ b/dom/xhr/tests/xhrAbort_worker.js
@@ -0,0 +1,92 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+function runTest() {
+ var xhr = new XMLHttpRequest();
+
+ var events = [];
+ function pushEvent(event) {
+ var readyState, responseText, status, statusText;
+
+ try {
+ readyState = xhr.readyState;
+ }
+ catch (e) {
+ readyState = "[exception]";
+ }
+
+ try {
+ responseText = xhr.responseText;
+ }
+ catch (e) {
+ responseText = "[exception]";
+ }
+
+ try {
+ status = xhr.status;
+ }
+ catch (e) {
+ status = "[exception]";
+ }
+
+ try {
+ statusText = xhr.statusText;
+ }
+ catch (e) {
+ statusText = "[exception]";
+ }
+
+ var str = event.type + "(" + readyState + ", '" + responseText + "', " +
+ status + ", '" + statusText + "'";
+ if ((("ProgressEvent" in this) && event instanceof ProgressEvent) ||
+ (("WorkerProgressEvent" in this) && event instanceof WorkerProgressEvent)) {
+ str += ", progressEvent";
+ }
+ str += ")";
+
+ events.push(str);
+ }
+
+ xhr.onerror = function(event) {
+ throw new Error("Error: " + xhr.statusText);
+ }
+
+ xhr.onload = function(event) {
+ throw new Error("Shouldn't have gotten load event!");
+ };
+
+ var seenAbort;
+ xhr.onabort = function(event) {
+ if (seenAbort) {
+ throw new Error("Already seen the abort event!");
+ }
+ seenAbort = true;
+
+ pushEvent(event);
+ postMessage(events);
+ };
+
+ xhr.onreadystatechange = function(event) {
+ pushEvent(event);
+ if (xhr.readyState == xhr.HEADERS_RECEIVED) {
+ xhr.abort();
+ }
+ };
+
+ xhr.open("GET", "worker_testXHR.txt");
+ xhr.overrideMimeType("text/plain");
+ xhr.send(null);
+}
+
+function messageListener(event) {
+ switch (event.data) {
+ case "start":
+ runTest();
+ break;
+ default:
+ throw new Error("Bad message!");
+ }
+}
+
+addEventListener("message", messageListener, false);
diff --git a/dom/xhr/tests/xhr_implicit_cancel_worker.js b/dom/xhr/tests/xhr_implicit_cancel_worker.js
new file mode 100644
index 000000000..2045452ca
--- /dev/null
+++ b/dom/xhr/tests/xhr_implicit_cancel_worker.js
@@ -0,0 +1,10 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "worker_testXHR.txt");
+xhr.send(null);
+xhr.open("GET", "worker_testXHR.txt");
+xhr.send(null);
+postMessage("done");
diff --git a/dom/xhr/tests/xhr_worker.js b/dom/xhr/tests/xhr_worker.js
new file mode 100644
index 000000000..178c391b6
--- /dev/null
+++ b/dom/xhr/tests/xhr_worker.js
@@ -0,0 +1,84 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+var xhr = new XMLHttpRequest();
+
+function onload(event) {
+ if (event.target != xhr) {
+ throw "onload event.target != xhr";
+ }
+
+ if (event.target.status != 200) {
+ var message = { type: "error",
+ error: event.target.status };
+ postMessage(message);
+ }
+
+ var message = { type: "load",
+ data: xhr.responseText };
+ postMessage(message);
+}
+
+xhr.onload = onload;
+xhr.addEventListener("load", onload, false);
+xhr.removeEventListener("load", onload, false);
+if (!xhr.onload) {
+ var message = { type: "error",
+ error: "Lost message listener!" };
+ postMessage(message);
+}
+
+xhr.onerror = function(event) {
+ if (event.target != xhr) {
+ throw "onerror event.target != xhr";
+ }
+ var message = { type: "error",
+ error: event.target.status };
+ postMessage(message);
+};
+xhr.onerror = xhr.onerror;
+if (!xhr.onerror || xhr.onerror != xhr.onerror) {
+ throw "onerror wasn't set properly";
+}
+
+function onprogress(event) {
+ if (event.target != xhr) {
+ throw "onprogress event.target != xhr";
+ }
+ var message = { type: "progress",
+ current: event.loaded,
+ total: event.total };
+ postMessage(message);
+}
+xhr.addEventListener("progress", onprogress, false);
+
+xhr.addEventListener("foopety", function(event) {}, false);
+xhr.removeEventListener("doopety", function(event) {}, false);
+
+xhr.onloadend = function(event) {
+ var message = { type: "loadend" };
+ postMessage(message);
+}
+
+var upload = xhr.upload;
+upload.onprogress = function(event) { };
+upload.addEventListener("foo", function(event) { }, false);
+upload.removeEventListener("foo", function(event) { }, false);
+upload.addEventListener("load", function(event) { }, false);
+upload.removeEventListener("foo", function(event) { }, false);
+upload.onload = function(event) {
+ var message = { type: "upload.load" };
+ postMessage(message);
+}
+
+onmessage = function(event) {
+ if (xhr.DONE != 4 || XMLHttpRequest.DONE != 4) {
+ throw "xhr constants not correct!";
+ }
+ if (xhr.readystate > xhr.UNSENT) {
+ throw "XHR already running!";
+ }
+ xhr.open("POST", event.data);
+ xhr.send("Data to send");
+}