summaryrefslogtreecommitdiffstats
path: root/dom/security/test/cors
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /dom/security/test/cors
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/security/test/cors')
-rw-r--r--dom/security/test/cors/file_CrossSiteXHR_cache_server.sjs49
-rw-r--r--dom/security/test/cors/file_CrossSiteXHR_inner.html121
-rw-r--r--dom/security/test/cors/file_CrossSiteXHR_inner.jarbin0 -> 1105 bytes
-rw-r--r--dom/security/test/cors/file_CrossSiteXHR_inner_data.sjs103
-rw-r--r--dom/security/test/cors/file_CrossSiteXHR_server.sjs179
-rw-r--r--dom/security/test/cors/mochitest.ini11
-rw-r--r--dom/security/test/cors/test_CrossSiteXHR.html1461
-rw-r--r--dom/security/test/cors/test_CrossSiteXHR_cache.html587
-rw-r--r--dom/security/test/cors/test_CrossSiteXHR_origin.html174
9 files changed, 2685 insertions, 0 deletions
diff --git a/dom/security/test/cors/file_CrossSiteXHR_cache_server.sjs b/dom/security/test/cors/file_CrossSiteXHR_cache_server.sjs
new file mode 100644
index 000000000..8ee4ddbf5
--- /dev/null
+++ b/dom/security/test/cors/file_CrossSiteXHR_cache_server.sjs
@@ -0,0 +1,49 @@
+function handleRequest(request, response)
+{
+ var query = {};
+ request.queryString.split('&').forEach(function (val) {
+ var [name, value] = val.split('=');
+ query[name] = unescape(value);
+ });
+
+ if ("setState" in query) {
+ setState("test/dom/security/test_CrossSiteXHR_cache:secData",
+ query.setState);
+
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("hi");
+
+ return;
+ }
+
+ var isPreflight = request.method == "OPTIONS";
+
+ // Send response
+
+ secData =
+ eval(getState("test/dom/security/test_CrossSiteXHR_cache:secData"));
+
+ if (secData.allowOrigin)
+ response.setHeader("Access-Control-Allow-Origin", secData.allowOrigin);
+
+ if (secData.withCred)
+ response.setHeader("Access-Control-Allow-Credentials", "true");
+
+ if (isPreflight) {
+ if (secData.allowHeaders)
+ response.setHeader("Access-Control-Allow-Headers", secData.allowHeaders);
+
+ if (secData.allowMethods)
+ response.setHeader("Access-Control-Allow-Methods", secData.allowMethods);
+
+ if (secData.cacheTime)
+ response.setHeader("Access-Control-Max-Age", secData.cacheTime.toString());
+
+ return;
+ }
+
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "application/xml", false);
+ response.write("<res>hello pass</res>\n");
+}
diff --git a/dom/security/test/cors/file_CrossSiteXHR_inner.html b/dom/security/test/cors/file_CrossSiteXHR_inner.html
new file mode 100644
index 000000000..9268f0ed7
--- /dev/null
+++ b/dom/security/test/cors/file_CrossSiteXHR_inner.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML>
+<!--
+ NOTE! The content of this file is duplicated in file_CrossSiteXHR_inner.jar
+ and file_CrossSiteXHR_inner_data.sjs
+ Please update those files if you update this one.
+-->
+
+<html>
+<head>
+<script>
+function trimString(stringValue) {
+ return stringValue.replace(/^\s+|\s+$/g, '');
+};
+
+window.addEventListener("message", function(e) {
+
+ sendData = null;
+
+ req = eval(e.data);
+ var res = {
+ didFail: false,
+ events: [],
+ progressEvents: 0,
+ status: 0,
+ responseText: "",
+ statusText: "",
+ responseXML: null,
+ sendThrew: false
+ };
+
+ var xhr = new XMLHttpRequest();
+ for (type of ["load", "abort", "error", "loadstart", "loadend"]) {
+ xhr.addEventListener(type, function(e) {
+ res.events.push(e.type);
+ }, false);
+ }
+ xhr.addEventListener("readystatechange", function(e) {
+ res.events.push("rs" + xhr.readyState);
+ }, false);
+ xhr.addEventListener("progress", function(e) {
+ res.progressEvents++;
+ }, false);
+ if (req.uploadProgress) {
+ xhr.upload.addEventListener(req.uploadProgress, function(e) {
+ res.progressEvents++;
+ }, false);
+ }
+ xhr.onerror = function(e) {
+ res.didFail = true;
+ };
+ xhr.onloadend = function (event) {
+ res.status = xhr.status;
+ try {
+ res.statusText = xhr.statusText;
+ } catch (e) {
+ delete(res.statusText);
+ }
+ res.responseXML = xhr.responseXML ?
+ (new XMLSerializer()).serializeToString(xhr.responseXML) :
+ null;
+ res.responseText = xhr.responseText;
+
+ res.responseHeaders = {};
+ for (responseHeader in req.responseHeaders) {
+ res.responseHeaders[responseHeader] =
+ xhr.getResponseHeader(responseHeader);
+ }
+ res.allResponseHeaders = {};
+ var splitHeaders = xhr.getAllResponseHeaders().split("\r\n");
+ for (var i = 0; i < splitHeaders.length; i++) {
+ var headerValuePair = splitHeaders[i].split(":");
+ if(headerValuePair[1] != null) {
+ var headerName = trimString(headerValuePair[0]);
+ var headerValue = trimString(headerValuePair[1]);
+ res.allResponseHeaders[headerName] = headerValue;
+ }
+ }
+ post(e, res);
+ }
+
+ if (req.withCred)
+ xhr.withCredentials = true;
+ if (req.body)
+ sendData = req.body;
+
+ res.events.push("opening");
+ // Allow passign in falsy usernames/passwords so we can test them
+ try {
+ xhr.open(req.method, req.url, true,
+ ("username" in req) ? req.username : "",
+ ("password" in req) ? req.password : "aa");
+ } catch (ex) {
+ res.didFail = true;
+ post(e, res);
+ }
+
+ for (header in req.headers) {
+ xhr.setRequestHeader(header, req.headers[header]);
+ }
+
+ res.events.push("sending");
+ try {
+ xhr.send(sendData);
+ } catch (ex) {
+ res.didFail = true;
+ res.sendThrew = true;
+ post(e, res);
+ }
+
+}, false);
+
+function post(e, res) {
+ e.source.postMessage(res.toSource(), "http://mochi.test:8888");
+}
+
+</script>
+</head>
+<body>
+Inner page
+</body>
+</html>
diff --git a/dom/security/test/cors/file_CrossSiteXHR_inner.jar b/dom/security/test/cors/file_CrossSiteXHR_inner.jar
new file mode 100644
index 000000000..bdb0eb440
--- /dev/null
+++ b/dom/security/test/cors/file_CrossSiteXHR_inner.jar
Binary files differ
diff --git a/dom/security/test/cors/file_CrossSiteXHR_inner_data.sjs b/dom/security/test/cors/file_CrossSiteXHR_inner_data.sjs
new file mode 100644
index 000000000..2908921e2
--- /dev/null
+++ b/dom/security/test/cors/file_CrossSiteXHR_inner_data.sjs
@@ -0,0 +1,103 @@
+var data = '<!DOCTYPE HTML>\n\
+<html>\n\
+<head>\n\
+<script>\n\
+window.addEventListener("message", function(e) {\n\
+\n\
+ sendData = null;\n\
+\n\
+ req = eval(e.data);\n\
+ var res = {\n\
+ didFail: false,\n\
+ events: [],\n\
+ progressEvents: 0\n\
+ };\n\
+ \n\
+ var xhr = new XMLHttpRequest();\n\
+ for (type of ["load", "abort", "error", "loadstart", "loadend"]) {\n\
+ xhr.addEventListener(type, function(e) {\n\
+ res.events.push(e.type);\n\
+ }, false);\n\
+ }\n\
+ xhr.addEventListener("readystatechange", function(e) {\n\
+ res.events.push("rs" + xhr.readyState);\n\
+ }, false);\n\
+ xhr.addEventListener("progress", function(e) {\n\
+ res.progressEvents++;\n\
+ }, false);\n\
+ if (req.uploadProgress) {\n\
+ xhr.upload.addEventListener(req.uploadProgress, function(e) {\n\
+ res.progressEvents++;\n\
+ }, false);\n\
+ }\n\
+ xhr.onerror = function(e) {\n\
+ res.didFail = true;\n\
+ };\n\
+ xhr.onloadend = function (event) {\n\
+ res.status = xhr.status;\n\
+ try {\n\
+ res.statusText = xhr.statusText;\n\
+ } catch (e) {\n\
+ delete(res.statusText);\n\
+ }\n\
+ res.responseXML = xhr.responseXML ?\n\
+ (new XMLSerializer()).serializeToString(xhr.responseXML) :\n\
+ null;\n\
+ res.responseText = xhr.responseText;\n\
+\n\
+ res.responseHeaders = {};\n\
+ for (responseHeader in req.responseHeaders) {\n\
+ res.responseHeaders[responseHeader] =\n\
+ xhr.getResponseHeader(responseHeader);\n\
+ }\n\
+ res.allResponseHeaders = {};\n\
+ var splitHeaders = xhr.getAllResponseHeaders().split("\\r\\n");\n\
+ for (var i = 0; i < splitHeaders.length; i++) {\n\
+ var headerValuePair = splitHeaders[i].split(":");\n\
+ if(headerValuePair[1] != null){\n\
+ var headerName = trimString(headerValuePair[0]);\n\
+ var headerValue = trimString(headerValuePair[1]); \n\
+ res.allResponseHeaders[headerName] = headerValue;\n\
+ }\n\
+ }\n\
+ post(e, res);\n\
+ }\n\
+\n\
+ if (req.withCred)\n\
+ xhr.withCredentials = true;\n\
+ if (req.body)\n\
+ sendData = req.body;\n\
+\n\
+ res.events.push("opening");\n\
+ xhr.open(req.method, req.url, true);\n\
+\n\
+ for (header in req.headers) {\n\
+ xhr.setRequestHeader(header, req.headers[header]);\n\
+ }\n\
+\n\
+ res.events.push("sending");\n\
+ xhr.send(sendData);\n\
+\n\
+}, false);\n\
+\n\
+function post(e, res) {\n\
+ e.source.postMessage(res.toSource(), "*");\n\
+}\n\
+function trimString(stringValue) {\n\
+ return stringValue.replace("/^\s+|\s+$/g","");\n\
+};\n\
+\n\
+</script>\n\
+</head>\n\
+<body>\n\
+Inner page\n\
+</body>\n\
+</html>'
+
+function handleRequest(request, response)
+{
+ response.setStatusLine(null, 302, "Follow me");
+ response.setHeader("Location", "data:text/html," + escape(data));
+ response.setHeader("Content-Type", "text/plain");
+ response.write("Follow that guy!");
+}
diff --git a/dom/security/test/cors/file_CrossSiteXHR_server.sjs b/dom/security/test/cors/file_CrossSiteXHR_server.sjs
new file mode 100644
index 000000000..66d110468
--- /dev/null
+++ b/dom/security/test/cors/file_CrossSiteXHR_server.sjs
@@ -0,0 +1,179 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function handleRequest(request, response)
+{
+ var query = {};
+ request.queryString.split('&').forEach(function (val) {
+ var [name, value] = val.split('=');
+ query[name] = unescape(value);
+ });
+
+ var isPreflight = request.method == "OPTIONS";
+
+ var bodyStream = new BinaryInputStream(request.bodyInputStream);
+ var bodyBytes = [];
+ while ((bodyAvail = bodyStream.available()) > 0)
+ Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail));
+
+ var body = decodeURIComponent(
+ escape(String.fromCharCode.apply(null, bodyBytes)));
+
+ if (query.hop) {
+ query.hop = parseInt(query.hop, 10);
+ hops = eval(query.hops);
+ var curHop = hops[query.hop - 1];
+ query.allowOrigin = curHop.allowOrigin;
+ query.allowHeaders = curHop.allowHeaders;
+ query.allowMethods = curHop.allowMethods;
+ query.allowCred = curHop.allowCred;
+ query.noAllowPreflight = curHop.noAllowPreflight;
+ if (curHop.setCookie) {
+ query.setCookie = unescape(curHop.setCookie);
+ }
+ if (curHop.cookie) {
+ query.cookie = unescape(curHop.cookie);
+ }
+ query.noCookie = curHop.noCookie;
+ }
+
+ // Check that request was correct
+
+ if (!isPreflight && query.body && body != query.body) {
+ sendHttp500(response, "Wrong body. Expected " + query.body + " got " +
+ body);
+ return;
+ }
+
+ if (!isPreflight && "headers" in query) {
+ headers = eval(query.headers);
+ for(headerName in headers) {
+ // Content-Type is changed if there was a body
+ if (!(headerName == "Content-Type" && body) &&
+ (!request.hasHeader(headerName) ||
+ request.getHeader(headerName) != headers[headerName])) {
+ var actual = request.hasHeader(headerName) ? request.getHeader(headerName)
+ : "<missing header>";
+ sendHttp500(response,
+ "Header " + headerName + " had wrong value. Expected " +
+ headers[headerName] + " got " + actual);
+ return;
+ }
+ }
+ }
+
+ if (isPreflight && "requestHeaders" in query &&
+ request.getHeader("Access-Control-Request-Headers") != query.requestHeaders) {
+ sendHttp500(response,
+ "Access-Control-Request-Headers had wrong value. Expected " +
+ query.requestHeaders + " got " +
+ request.getHeader("Access-Control-Request-Headers"));
+ return;
+ }
+
+ if (isPreflight && "requestMethod" in query &&
+ request.getHeader("Access-Control-Request-Method") != query.requestMethod) {
+ sendHttp500(response,
+ "Access-Control-Request-Method had wrong value. Expected " +
+ query.requestMethod + " got " +
+ request.getHeader("Access-Control-Request-Method"));
+ return;
+ }
+
+ if ("origin" in query && request.getHeader("Origin") != query.origin) {
+ sendHttp500(response,
+ "Origin had wrong value. Expected " + query.origin + " got " +
+ request.getHeader("Origin"));
+ return;
+ }
+
+ if ("cookie" in query) {
+ cookies = {};
+ request.getHeader("Cookie").split(/ *; */).forEach(function (val) {
+ var [name, value] = val.split('=');
+ cookies[name] = unescape(value);
+ });
+
+ query.cookie.split(",").forEach(function (val) {
+ var [name, value] = val.split('=');
+ if (cookies[name] != value) {
+ sendHttp500(response,
+ "Cookie " + name + " had wrong value. Expected " + value +
+ " got " + cookies[name]);
+ return;
+ }
+ });
+ }
+
+ if (query.noCookie && request.hasHeader("Cookie")) {
+ sendHttp500(response,
+ "Got cookies when didn't expect to: " + request.getHeader("Cookie"));
+ return;
+ }
+
+ // Send response
+
+ if (!isPreflight && query.status) {
+ response.setStatusLine(null, query.status, query.statusMessage);
+ }
+ if (isPreflight && query.preflightStatus) {
+ response.setStatusLine(null, query.preflightStatus, "preflight status");
+ }
+
+ if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight))
+ response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
+
+ if (query.allowCred)
+ response.setHeader("Access-Control-Allow-Credentials", "true");
+
+ if (query.setCookie)
+ response.setHeader("Set-Cookie", query.setCookie + "; path=/");
+
+ if (isPreflight) {
+ if (query.allowHeaders)
+ response.setHeader("Access-Control-Allow-Headers", query.allowHeaders);
+
+ if (query.allowMethods)
+ response.setHeader("Access-Control-Allow-Methods", query.allowMethods);
+ }
+ else {
+ if (query.responseHeaders) {
+ let responseHeaders = eval(query.responseHeaders);
+ for (let responseHeader in responseHeaders) {
+ response.setHeader(responseHeader, responseHeaders[responseHeader]);
+ }
+ }
+
+ if (query.exposeHeaders)
+ response.setHeader("Access-Control-Expose-Headers", query.exposeHeaders);
+ }
+
+ if (!isPreflight && query.hop && query.hop < hops.length) {
+ newURL = hops[query.hop].server +
+ "/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?" +
+ "hop=" + (query.hop + 1) + "&hops=" + escape(query.hops);
+ if ("headers" in query) {
+ newURL += "&headers=" + escape(query.headers);
+ }
+ response.setStatusLine(null, 307, "redirect");
+ response.setHeader("Location", newURL);
+
+ return;
+ }
+
+ // Send response body
+ if (!isPreflight && request.method != "HEAD") {
+ response.setHeader("Content-Type", "application/xml", false);
+ response.write("<res>hello pass</res>\n");
+ }
+ if (isPreflight && "preflightBody" in query) {
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write(query.preflightBody);
+ }
+}
+
+function sendHttp500(response, text) {
+ response.setStatusLine(null, 500, text);
+}
diff --git a/dom/security/test/cors/mochitest.ini b/dom/security/test/cors/mochitest.ini
new file mode 100644
index 000000000..095b0d09d
--- /dev/null
+++ b/dom/security/test/cors/mochitest.ini
@@ -0,0 +1,11 @@
+[DEFAULT]
+support-files =
+ file_CrossSiteXHR_cache_server.sjs
+ file_CrossSiteXHR_inner.html
+ file_CrossSiteXHR_inner.jar
+ file_CrossSiteXHR_inner_data.sjs
+ file_CrossSiteXHR_server.sjs
+
+[test_CrossSiteXHR.html]
+[test_CrossSiteXHR_cache.html]
+[test_CrossSiteXHR_origin.html]
diff --git a/dom/security/test/cors/test_CrossSiteXHR.html b/dom/security/test/cors/test_CrossSiteXHR.html
new file mode 100644
index 000000000..b3cda3b87
--- /dev/null
+++ b/dom/security/test/cors/test_CrossSiteXHR.html
@@ -0,0 +1,1461 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
+ <title>Test for Cross Site 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="initTest()">
+<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">
+
+const runPreflightTests = 1;
+const runCookieTests = 1;
+const runRedirectTests = 1;
+
+var gen;
+
+function initTest() {
+ SimpleTest.waitForExplicitFinish();
+ // Allow all cookies, then do the actual test initialization
+ SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, initTestCallback);
+}
+
+function initTestCallback() {
+ window.addEventListener("message", function(e) {
+ gen.send(e.data);
+ }, false);
+
+ gen = runTest();
+
+ gen.next()
+}
+
+function runTest() {
+ var loader = document.getElementById('loader');
+ var loaderWindow = loader.contentWindow;
+ loader.onload = function () { gen.next() };
+
+ // Test preflight-less requests
+ basePath = "/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?"
+ baseURL = "http://mochi.test:8888" + basePath;
+
+ // Test preflighted requests
+ loader.src = "http://example.org/tests/dom/security/test/cors/file_CrossSiteXHR_inner.html";
+ origin = "http://example.org";
+ yield undefined;
+
+ tests = [// Plain request
+ { pass: 1,
+ method: "GET",
+ noAllowPreflight: 1,
+ },
+
+ // undefined username
+ { pass: 1,
+ method: "GET",
+ noAllowPreflight: 1,
+ username: undefined
+ },
+
+ // undefined username and password
+ { pass: 1,
+ method: "GET",
+ noAllowPreflight: 1,
+ username: undefined,
+ password: undefined
+ },
+
+ // nonempty username
+ { pass: 0,
+ method: "GET",
+ noAllowPreflight: 1,
+ username: "user",
+ },
+
+ // nonempty password
+ // XXXbz this passes for now, because we ignore passwords
+ // without usernames in most cases.
+ { pass: 1,
+ method: "GET",
+ noAllowPreflight: 1,
+ password: "password",
+ },
+
+ // Default allowed headers
+ { pass: 1,
+ method: "GET",
+ headers: { "Content-Type": "text/plain",
+ "Accept": "foo/bar",
+ "Accept-Language": "sv-SE" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "Content-Type": "foo/bar",
+ "Accept": "foo/bar",
+ "Accept-Language": "sv-SE" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "Content-Type": "foo/bar, text/plain" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "Content-Type": "foo/bar, text/plain, garbage" },
+ noAllowPreflight: 1,
+ },
+
+ // Custom headers
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "X-My-Header",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header": "secondValue" },
+ allowHeaders: "x-my-header, long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my%-header": "myValue" },
+ allowHeaders: "x-my%-header",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "y-my-header",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header y-my-header",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header, y-my-header z",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header, y-my-he(ader",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "myheader": "" },
+ allowMethods: "myheader",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "User-Agent": "myValue" },
+ allowHeaders: "User-Agent",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "User-Agent": "myValue" },
+ },
+
+ // Multiple custom headers
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "second-header": "secondValue",
+ "third-header": "thirdValue" },
+ allowHeaders: "x-my-header, second-header, third-header",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "second-header": "secondValue",
+ "third-header": "thirdValue" },
+ allowHeaders: "x-my-header,second-header,third-header",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "second-header": "secondValue",
+ "third-header": "thirdValue" },
+ allowHeaders: "x-my-header ,second-header ,third-header",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "second-header": "secondValue",
+ "third-header": "thirdValue" },
+ allowHeaders: "x-my-header , second-header , third-header",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "second-header": "secondValue" },
+ allowHeaders: ", x-my-header, , ,, second-header, , ",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "second-header": "secondValue" },
+ allowHeaders: "x-my-header, second-header, unused-header",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "y-my-header": "secondValue" },
+ allowHeaders: "x-my-header",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "",
+ "y-my-header": "" },
+ allowHeaders: "x-my-header",
+ },
+
+ // HEAD requests
+ { pass: 1,
+ method: "HEAD",
+ noAllowPreflight: 1,
+ },
+
+ // HEAD with safe headers
+ { pass: 1,
+ method: "HEAD",
+ headers: { "Content-Type": "text/plain",
+ "Accept": "foo/bar",
+ "Accept-Language": "sv-SE" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "HEAD",
+ headers: { "Content-Type": "foo/bar",
+ "Accept": "foo/bar",
+ "Accept-Language": "sv-SE" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "HEAD",
+ headers: { "Content-Type": "foo/bar, text/plain" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "HEAD",
+ headers: { "Content-Type": "foo/bar, text/plain, garbage" },
+ noAllowPreflight: 1,
+ },
+
+ // HEAD with custom headers
+ { pass: 1,
+ method: "HEAD",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ },
+ { pass: 0,
+ method: "HEAD",
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 0,
+ method: "HEAD",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "",
+ },
+ { pass: 0,
+ method: "HEAD",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "y-my-header",
+ },
+ { pass: 0,
+ method: "HEAD",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header y-my-header",
+ },
+
+ // POST tests
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ noAllowPreflight: 1,
+ },
+ { pass: 1,
+ method: "POST",
+ },
+ { pass: 1,
+ method: "POST",
+ noAllowPreflight: 1,
+ },
+
+ // POST with standard headers
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain" },
+ noAllowPreflight: 1,
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "multipart/form-data" },
+ noAllowPreflight: 1,
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "foo/bar" },
+ },
+ { pass: 0,
+ method: "POST",
+ headers: { "Content-Type": "foo/bar" },
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "Accept": "foo/bar",
+ "Accept-Language": "sv-SE" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "foo/bar, text/plain" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "foo/bar, text/plain, garbage" },
+ noAllowPreflight: 1,
+ },
+
+ // POST with custom headers
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Accept": "foo/bar",
+ "Accept-Language": "sv-SE",
+ "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ },
+ { pass: 1,
+ method: "POST",
+ headers: { "Content-Type": "text/plain",
+ "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "foo/bar",
+ "x-my-header": "myValue" },
+ allowHeaders: "x-my-header, content-type",
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "foo/bar" },
+ noAllowPreflight: 1,
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "foo/bar",
+ "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ },
+ { pass: 1,
+ method: "POST",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header, $_%",
+ },
+
+ // Other methods
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowHeaders: "DELETE",
+ },
+ { pass: 0,
+ method: "DELETE",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "POST, PUT, DELETE",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "POST, DELETE, PUT",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE, POST, PUT",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "POST ,PUT ,DELETE",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "POST,PUT,DELETE",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "POST , PUT , DELETE",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: " ,, PUT ,, , , DELETE , ,",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "PUT",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "DELETEZ",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "DELETE PUT",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "DELETE, PUT Z",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "DELETE, PU(T",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "PUT DELETE",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "PUT Z, DELETE",
+ },
+ { pass: 0,
+ method: "DELETE",
+ allowMethods: "PU(T, DELETE",
+ },
+ { pass: 0,
+ method: "MYMETHOD",
+ allowMethods: "myMethod",
+ },
+ { pass: 0,
+ method: "PUT",
+ allowMethods: "put",
+ },
+
+ // Progress events
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain" },
+ uploadProgress: "progress",
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain" },
+ uploadProgress: "progress",
+ noAllowPreflight: 1,
+ },
+
+ // Status messages
+ { pass: 1,
+ method: "GET",
+ noAllowPreflight: 1,
+ status: 404,
+ statusMessage: "nothin' here",
+ },
+ { pass: 1,
+ method: "GET",
+ noAllowPreflight: 1,
+ status: 401,
+ statusMessage: "no can do",
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "foo/bar" },
+ allowHeaders: "content-type",
+ status: 500,
+ statusMessage: "server boo",
+ },
+ { pass: 1,
+ method: "GET",
+ noAllowPreflight: 1,
+ status: 200,
+ statusMessage: "Yes!!",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "header value" },
+ allowHeaders: "x-my-header",
+ preflightStatus: 400
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "header value" },
+ allowHeaders: "x-my-header",
+ preflightStatus: 200
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "header value" },
+ allowHeaders: "x-my-header",
+ preflightStatus: 204
+ },
+
+ // exposed headers
+ { pass: 1,
+ method: "GET",
+ responseHeaders: { "x-my-header": "x header" },
+ exposeHeaders: "x-my-header",
+ expectedResponseHeaders: ["x-my-header"],
+ },
+ { pass: 0,
+ method: "GET",
+ origin: "http://invalid",
+ responseHeaders: { "x-my-header": "x header" },
+ exposeHeaders: "x-my-header",
+ expectedResponseHeaders: [],
+ },
+ { pass: 1,
+ method: "GET",
+ responseHeaders: { "x-my-header": "x header" },
+ expectedResponseHeaders: [],
+ },
+ { pass: 1,
+ method: "GET",
+ responseHeaders: { "x-my-header": "x header" },
+ exposeHeaders: "x-my-header y",
+ expectedResponseHeaders: [],
+ },
+ { pass: 1,
+ method: "GET",
+ responseHeaders: { "x-my-header": "x header" },
+ exposeHeaders: "y x-my-header",
+ expectedResponseHeaders: [],
+ },
+ { pass: 1,
+ method: "GET",
+ responseHeaders: { "x-my-header": "x header" },
+ exposeHeaders: "x-my-header, y-my-header z",
+ expectedResponseHeaders: [],
+ },
+ { pass: 1,
+ method: "GET",
+ responseHeaders: { "x-my-header": "x header" },
+ exposeHeaders: "x-my-header, y-my-hea(er",
+ expectedResponseHeaders: [],
+ },
+ { pass: 1,
+ method: "GET",
+ responseHeaders: { "x-my-header": "x header",
+ "y-my-header": "y header" },
+ exposeHeaders: " , ,,y-my-header,z-my-header, ",
+ expectedResponseHeaders: ["y-my-header"],
+ },
+ { pass: 1,
+ method: "GET",
+ responseHeaders: { "Cache-Control": "cacheControl header",
+ "Content-Language": "contentLanguage header",
+ "Expires":"expires header",
+ "Last-Modified":"lastModified header",
+ "Pragma":"pragma header",
+ "Unexpected":"unexpected header" },
+ expectedResponseHeaders: ["Cache-Control","Content-Language","Content-Type","Expires","Last-Modified","Pragma"],
+ },
+ // Check that sending a body in the OPTIONS response works
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ preflightBody: "I'm a preflight response body",
+ },
+ ];
+
+ if (!runPreflightTests) {
+ tests = [];
+ }
+
+ for (test of tests) {
+ var req = {
+ url: baseURL + "allowOrigin=" + escape(test.origin || origin),
+ method: test.method,
+ headers: test.headers,
+ uploadProgress: test.uploadProgress,
+ body: test.body,
+ responseHeaders: test.responseHeaders,
+ };
+
+ if (test.pass) {
+ req.url += "&origin=" + escape(origin) +
+ "&requestMethod=" + test.method;
+ }
+
+ if ("username" in test) {
+ req.username = test.username;
+ }
+
+ if ("password" in test) {
+ req.password = test.password;
+ }
+
+ if (test.noAllowPreflight)
+ req.url += "&noAllowPreflight";
+
+ if (test.pass && "headers" in test) {
+ function isUnsafeHeader(name) {
+ lName = name.toLowerCase();
+ return lName != "accept" &&
+ lName != "accept-language" &&
+ (lName != "content-type" ||
+ ["text/plain",
+ "multipart/form-data",
+ "application/x-www-form-urlencoded"]
+ .indexOf(test.headers[name].toLowerCase()) == -1);
+ }
+ req.url += "&headers=" + escape(test.headers.toSource());
+ reqHeaders =
+ escape(Object.keys(test.headers)
+ .filter(isUnsafeHeader)
+ .map(String.toLowerCase)
+ .sort()
+ .join(","));
+ req.url += reqHeaders ? "&requestHeaders=" + reqHeaders : "";
+ }
+ if ("allowHeaders" in test)
+ req.url += "&allowHeaders=" + escape(test.allowHeaders);
+ if ("allowMethods" in test)
+ req.url += "&allowMethods=" + escape(test.allowMethods);
+ if (test.body)
+ req.url += "&body=" + escape(test.body);
+ if (test.status) {
+ req.url += "&status=" + test.status;
+ req.url += "&statusMessage=" + escape(test.statusMessage);
+ }
+ if (test.preflightStatus)
+ req.url += "&preflightStatus=" + test.preflightStatus;
+ if (test.responseHeaders)
+ req.url += "&responseHeaders=" + escape(test.responseHeaders.toSource());
+ if (test.exposeHeaders)
+ req.url += "&exposeHeaders=" + escape(test.exposeHeaders);
+ if (test.preflightBody)
+ req.url += "&preflightBody=" + escape(test.preflightBody);
+
+ loaderWindow.postMessage(req.toSource(), origin);
+ res = eval(yield);
+
+ if (test.pass) {
+ is(res.didFail, false,
+ "shouldn't have failed in test for " + test.toSource());
+ if (test.status) {
+ is(res.status, test.status, "wrong status in test for " + test.toSource());
+ is(res.statusText, test.statusMessage, "wrong status text for " + test.toSource());
+ }
+ else {
+ is(res.status, 200, "wrong status in test for " + test.toSource());
+ is(res.statusText, "OK", "wrong status text for " + test.toSource());
+ }
+ if (test.method !== "HEAD") {
+ is(res.responseXML, "<res>hello pass</res>",
+ "wrong responseXML in test for " + test.toSource());
+ is(res.responseText, "<res>hello pass</res>\n",
+ "wrong responseText in test for " + test.toSource());
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs3,rs4,load,loadend",
+ "wrong responseText in test for " + test.toSource());
+ }
+ else {
+ is(res.responseXML, null,
+ "wrong responseXML in test for " + test.toSource());
+ is(res.responseText, "",
+ "wrong responseText in test for " + test.toSource());
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs4,load,loadend",
+ "wrong responseText in test for " + test.toSource());
+ }
+ if (test.responseHeaders) {
+ for (header in test.responseHeaders) {
+ if (test.expectedResponseHeaders.indexOf(header) == -1) {
+ is(res.responseHeaders[header], null,
+ "|xhr.getResponseHeader()|wrong response header (" + header + ") in test for " +
+ test.toSource());
+ is(res.allResponseHeaders[header], undefined,
+ "|xhr.getAllResponseHeaderss()|wrong response header (" + header + ") in test for " +
+ test.toSource());
+ }
+ else {
+ is(res.responseHeaders[header], test.responseHeaders[header],
+ "|xhr.getResponseHeader()|wrong response header (" + header + ") in test for " +
+ test.toSource());
+ is(res.allResponseHeaders[header], test.responseHeaders[header],
+ "|xhr.getAllResponseHeaderss()|wrong response header (" + header + ") in test for " +
+ test.toSource());
+ }
+ }
+ }
+ }
+ else {
+ is(res.didFail, true,
+ "should have failed in test for " + test.toSource());
+ is(res.status, 0, "wrong status in test for " + test.toSource());
+ is(res.statusText, "", "wrong status text for " + test.toSource());
+ is(res.responseXML, null,
+ "wrong responseXML in test for " + test.toSource());
+ is(res.responseText, "",
+ "wrong responseText in test for " + test.toSource());
+ if (!res.sendThrew) {
+ if (test.username) {
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs4,error,loadend",
+ "wrong events in test for " + test.toSource());
+ } else {
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs4,error,loadend",
+ "wrong events in test for " + test.toSource());
+ }
+ }
+ is(res.progressEvents, 0,
+ "wrong events in test for " + test.toSource());
+ if (test.responseHeaders) {
+ for (header in test.responseHeaders) {
+ is(res.responseHeaders[header], null,
+ "wrong response header (" + header + ") in test for " +
+ test.toSource());
+ }
+ }
+ }
+ }
+
+ // Test cookie behavior
+ tests = [{ pass: 1,
+ method: "GET",
+ withCred: 1,
+ allowCred: 1,
+ },
+ { pass: 0,
+ method: "GET",
+ withCred: 1,
+ allowCred: 0,
+ },
+ { pass: 0,
+ method: "GET",
+ withCred: 1,
+ allowCred: 1,
+ origin: "*",
+ },
+ { pass: 1,
+ method: "GET",
+ withCred: 0,
+ allowCred: 1,
+ origin: "*",
+ },
+ { pass: 1,
+ method: "GET",
+ setCookie: "a=1",
+ withCred: 1,
+ allowCred: 1,
+ },
+ { pass: 1,
+ method: "GET",
+ cookie: "a=1",
+ withCred: 1,
+ allowCred: 1,
+ },
+ { pass: 1,
+ method: "GET",
+ noCookie: 1,
+ withCred: 0,
+ allowCred: 1,
+ },
+ { pass: 0,
+ method: "GET",
+ noCookie: 1,
+ withCred: 1,
+ allowCred: 1,
+ },
+ { pass: 1,
+ method: "GET",
+ setCookie: "a=2",
+ withCred: 0,
+ allowCred: 1,
+ },
+ { pass: 1,
+ method: "GET",
+ cookie: "a=1",
+ withCred: 1,
+ allowCred: 1,
+ },
+ { pass: 1,
+ method: "GET",
+ setCookie: "a=2",
+ withCred: 1,
+ allowCred: 1,
+ },
+ { pass: 1,
+ method: "GET",
+ cookie: "a=2",
+ withCred: 1,
+ allowCred: 1,
+ },
+ ];
+
+ if (!runCookieTests) {
+ tests = [];
+ }
+
+ for (test of tests) {
+ req = {
+ url: baseURL + "allowOrigin=" + escape(test.origin || origin),
+ method: test.method,
+ headers: test.headers,
+ withCred: test.withCred,
+ };
+
+ if (test.allowCred)
+ req.url += "&allowCred";
+
+ if (test.setCookie)
+ req.url += "&setCookie=" + escape(test.setCookie);
+ if (test.cookie)
+ req.url += "&cookie=" + escape(test.cookie);
+ if (test.noCookie)
+ req.url += "&noCookie";
+
+ if ("allowHeaders" in test)
+ req.url += "&allowHeaders=" + escape(test.allowHeaders);
+ if ("allowMethods" in test)
+ req.url += "&allowMethods=" + escape(test.allowMethods);
+
+ loaderWindow.postMessage(req.toSource(), origin);
+
+ res = eval(yield);
+ if (test.pass) {
+ is(res.didFail, false,
+ "shouldn't have failed in test for " + test.toSource());
+ is(res.status, 200, "wrong status in test for " + test.toSource());
+ is(res.statusText, "OK", "wrong status text for " + test.toSource());
+ is(res.responseXML, "<res>hello pass</res>",
+ "wrong responseXML in test for " + test.toSource());
+ is(res.responseText, "<res>hello pass</res>\n",
+ "wrong responseText in test for " + test.toSource());
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs3,rs4,load,loadend",
+ "wrong responseText in test for " + test.toSource());
+ }
+ else {
+ is(res.didFail, true,
+ "should have failed in test for " + test.toSource());
+ is(res.status, 0, "wrong status in test for " + test.toSource());
+ is(res.statusText, "", "wrong status text for " + test.toSource());
+ is(res.responseXML, null,
+ "wrong responseXML in test for " + test.toSource());
+ is(res.responseText, "",
+ "wrong responseText in test for " + test.toSource());
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs4,error,loadend",
+ "wrong events in test for " + test.toSource());
+ is(res.progressEvents, 0,
+ "wrong events in test for " + test.toSource());
+ }
+ }
+
+ // Make sure to clear cookies to avoid affecting other tests
+ document.cookie = "a=; path=/; expires=Thu, 01-Jan-1970 00:00:01 GMT"
+ is(document.cookie, "", "No cookies should be left over");
+
+
+ // Test redirects
+ is(loader.src, "http://example.org/tests/dom/security/test/cors/file_CrossSiteXHR_inner.html");
+ is(origin, "http://example.org");
+
+ tests = [{ pass: 1,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ ],
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://example.org",
+ allowOrigin: origin
+ },
+ ],
+ },
+ { pass: 1,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://example.org",
+ allowOrigin: "*"
+ },
+ ],
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://example.org",
+ },
+ ],
+ },
+ { pass: 1,
+ method: "GET",
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin
+ },
+ ],
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://example.org",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://test2.example.org:8000",
+ allowOrigin: origin
+ },
+ { server: "http://sub2.xn--lt-uia.example.org",
+ allowOrigin: origin
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: origin
+ },
+ ],
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://test2.example.org:8000",
+ allowOrigin: origin
+ },
+ { server: "http://sub2.xn--lt-uia.example.org",
+ allowOrigin: "*"
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: "*"
+ },
+ ],
+ },
+ { pass: 1,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://test2.example.org:8000",
+ allowOrigin: "*"
+ },
+ { server: "http://sub2.xn--lt-uia.example.org",
+ allowOrigin: "*"
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: "*"
+ },
+ ],
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://test2.example.org:8000",
+ allowOrigin: origin
+ },
+ { server: "http://sub2.xn--lt-uia.example.org",
+ allowOrigin: "x"
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: origin
+ },
+ ],
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://test2.example.org:8000",
+ allowOrigin: origin
+ },
+ { server: "http://sub2.xn--lt-uia.example.org",
+ allowOrigin: "*"
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: origin
+ },
+ ],
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin
+ },
+ { server: "http://test2.example.org:8000",
+ allowOrigin: origin
+ },
+ { server: "http://sub2.xn--lt-uia.example.org",
+ allowOrigin: "*"
+ },
+ { server: "http://sub1.test1.example.org",
+ },
+ ],
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain" },
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ },
+ ],
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "my-header": "myValue",
+ },
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "my-header": "myValue",
+ },
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "my-header": "myValue",
+ },
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "my-header": "myValue",
+ },
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ { server: "http://example.org",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "my-header": "myValue",
+ },
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ noAllowPreflight: 1,
+ },
+ ],
+ },
+ { pass: 1,
+ method: "DELETE",
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowMethods: "DELETE",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "DELETE",
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowMethods: "DELETE",
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: origin,
+ allowMethods: "DELETE",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "DELETE",
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowMethods: "DELETE",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowMethods: "DELETE",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "DELETE",
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowMethods: "DELETE",
+ },
+ { server: "http://example.org",
+ allowOrigin: origin,
+ allowMethods: "DELETE",
+ },
+ ],
+ },
+ { pass: 0,
+ method: "DELETE",
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowMethods: "DELETE",
+ noAllowPreflight: 1,
+ },
+ ],
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "my-header": "myValue",
+ },
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin,
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: origin,
+ },
+ ],
+ },
+ { pass: 0,
+ method: "DELETE",
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin,
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: origin,
+ },
+ ],
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "my-header": "myValue",
+ },
+ hops: [{ server: "http://example.com",
+ },
+ { server: "http://sub1.test1.example.org",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ ],
+ },
+ { pass: 1,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain" },
+ hops: [{ server: "http://example.org",
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ },
+ ],
+ },
+ { pass: 0,
+ method: "POST",
+ body: "hi there",
+ headers: { "Content-Type": "text/plain",
+ "my-header": "myValue",
+ },
+ hops: [{ server: "http://example.com",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ { server: "http://example.org",
+ allowOrigin: origin,
+ allowHeaders: "my-header",
+ },
+ ],
+ },
+
+ // test redirects with different credentials settings
+ {
+ // Initialize by setting a cookies for same- and cross- origins.
+ pass: 1,
+ method: "GET",
+ hops: [{ server: origin,
+ setCookie: escape("a=1"),
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowCred: 1,
+ setCookie: escape("a=2"),
+ },
+ ],
+ withCred: 1,
+ },
+ { pass: 1,
+ method: "GET",
+ hops: [{ server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ noCookie: 1,
+ },
+ ],
+ withCred: 0,
+ },
+ { pass: 1,
+ method: "GET",
+ hops: [{ server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ allowCred: 1,
+ cookie: escape("a=2"),
+ },
+ ],
+ withCred: 1,
+ },
+ // expected fail because allow-credentials CORS header is not set
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: "http://example.com",
+ allowOrigin: origin,
+ cookie: escape("a=2"),
+ },
+ ],
+ withCred: 1,
+ },
+ { pass: 1,
+ method: "GET",
+ hops: [{ server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: "http://example.com",
+ allowOrigin: '*',
+ noCookie: 1,
+ },
+ ],
+ withCred: 0,
+ },
+ { pass: 0,
+ method: "GET",
+ hops: [{ server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: origin,
+ cookie: escape("a=1"),
+ },
+ { server: "http://example.com",
+ allowOrigin: '*',
+ allowCred: 1,
+ cookie: escape("a=2"),
+ },
+ ],
+ withCred: 1,
+ },
+ ];
+
+ if (!runRedirectTests) {
+ tests = [];
+ }
+
+ for (test of tests) {
+ req = {
+ url: test.hops[0].server + basePath + "hop=1&hops=" +
+ escape(test.hops.toSource()),
+ method: test.method,
+ headers: test.headers,
+ body: test.body,
+ withCred: test.withCred,
+ };
+
+ if (test.pass) {
+ if (test.body)
+ req.url += "&body=" + escape(test.body);
+ }
+
+ loaderWindow.postMessage(req.toSource(), origin);
+
+ res = eval(yield);
+ if (test.pass) {
+ is(res.didFail, false,
+ "shouldn't have failed in test for " + test.toSource());
+ is(res.status, 200, "wrong status in test for " + test.toSource());
+ is(res.statusText, "OK", "wrong status text for " + test.toSource());
+ is(res.responseXML, "<res>hello pass</res>",
+ "wrong responseXML in test for " + test.toSource());
+ is(res.responseText, "<res>hello pass</res>\n",
+ "wrong responseText in test for " + test.toSource());
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs3,rs4,load,loadend",
+ "wrong responseText in test for " + test.toSource());
+ }
+ else {
+ is(res.didFail, true,
+ "should have failed in test for " + test.toSource());
+ is(res.status, 0, "wrong status in test for " + test.toSource());
+ is(res.statusText, "", "wrong status text for " + test.toSource());
+ is(res.responseXML, null,
+ "wrong responseXML in test for " + test.toSource());
+ is(res.responseText, "",
+ "wrong responseText in test for " + test.toSource());
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs4,error,loadend",
+ "wrong events in test for " + test.toSource());
+ is(res.progressEvents, 0,
+ "wrong progressevents in test for " + test.toSource());
+ }
+ }
+
+
+ SimpleTest.finish();
+
+ yield undefined;
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/security/test/cors/test_CrossSiteXHR_cache.html b/dom/security/test/cors/test_CrossSiteXHR_cache.html
new file mode 100644
index 000000000..3252eff4a
--- /dev/null
+++ b/dom/security/test/cors/test_CrossSiteXHR_cache.html
@@ -0,0 +1,587 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
+ <title>Test for Cross Site 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">
+<iframe id=loader></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("This test needs to generate artificial pauses, hence it uses timeouts. There is no way around it, unfortunately. :(");
+
+window.addEventListener("message", function(e) {
+ gen.send(e.data);
+}, false);
+
+gen = runTest();
+
+function runTest() {
+ var loader = document.getElementById('loader');
+ var loaderWindow = loader.contentWindow;
+ loader.onload = function () { gen.next() };
+
+ loader.src = "http://example.org/tests/dom/security/test/cors/file_CrossSiteXHR_inner.html";
+ origin = "http://example.org";
+ yield undefined;
+
+ tests = [{ pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ cacheTime: 3600
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "y-my-header": "second" },
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "y-my-header": "hello" },
+ allowHeaders: "y-my-header",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "y-my-header": "hello" },
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "y-my-header": "hello" },
+ allowHeaders: "y-my-header,x-my-header",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue",
+ "y-my-header": "second" },
+ },
+ { newTest: "*******" },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ cacheTime: 2
+ },
+ { pause: 2.1 },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header, y-my-header",
+ cacheTime: 3600
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "y-my-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "z-my-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ cacheTime: "\t 3600 \t ",
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ cacheTime: "3600 3",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ cacheTime: "asdf",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "first-header": "myValue" },
+ allowHeaders: "first-header",
+ cacheTime: 2,
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "second-header": "myValue" },
+ allowHeaders: "second-header",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "third-header": "myValue" },
+ allowHeaders: "third-header",
+ cacheTime: 2,
+ },
+ { pause: 2.1 },
+ { pass: 1,
+ method: "GET",
+ headers: { "second-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "first-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "first-header": "myValue" },
+ allowHeaders: "first-header",
+ cacheTime: 2,
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "second-header": "myValue" },
+ allowHeaders: "second-header",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "third-header": "myValue" },
+ allowHeaders: "third-header",
+ cacheTime: 2,
+ },
+ { pause: 2.1 },
+ { pass: 1,
+ method: "GET",
+ headers: { "second-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "third-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 0,
+ method: "DELETE",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ cacheTime: 3600
+ },
+ { pass: 1,
+ method: "DELETE",
+ },
+ { pass: 1,
+ method: "DELETE",
+ },
+ { pass: 0,
+ method: "PATCH",
+ },
+ { pass: 1,
+ method: "PATCH",
+ allowMethods: "PATCH",
+ },
+ { pass: 0,
+ method: "PATCH",
+ },
+ { pass: 1,
+ method: "PATCH",
+ allowMethods: "PATCH",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "PATCH",
+ },
+ { pass: 0,
+ method: "DELETE",
+ },
+ { pass: 0,
+ method: "PUT",
+ },
+ { newTest: "*******" },
+ { pass: 0,
+ method: "DELETE",
+ },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ cacheTime: 2
+ },
+ { pause: 2.1 },
+ { pass: 0,
+ method: "DELETE",
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE, PUT",
+ cacheTime: 3600
+ },
+ { pass: 1,
+ method: "DELETE",
+ },
+ { pass: 1,
+ method: "PUT",
+ },
+ { pass: 0,
+ method: "PATCH",
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "FIRST",
+ allowMethods: "FIRST",
+ cacheTime: 2,
+ },
+ { pass: 1,
+ method: "SECOND",
+ allowMethods: "SECOND",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "THIRD",
+ allowMethods: "THIRD",
+ cacheTime: 2,
+ },
+ { pause: 2.1 },
+ { pass: 1,
+ method: "SECOND",
+ },
+ { pass: 0,
+ method: "FIRST",
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "FIRST",
+ allowMethods: "FIRST",
+ cacheTime: 2,
+ },
+ { pass: 1,
+ method: "SECOND",
+ allowMethods: "SECOND",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "THIRD",
+ allowMethods: "THIRD",
+ cacheTime: 2,
+ },
+ { pause: 2.1 },
+ { pass: 1,
+ method: "SECOND",
+ },
+ { pass: 0,
+ method: "THIRD",
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "x-value" },
+ allowHeaders: "x-my-header",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "x-value" }
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "y-my-header": "y-value" }
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "x-value" }
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "x-value" },
+ allowHeaders: "x-my-header",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "x-value" },
+ },
+ { pass: 0,
+ method: "PUT",
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "x-value" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "x-value" },
+ allowHeaders: "x-my-header",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "x-value" },
+ },
+ { pass: 0,
+ method: "GET",
+ noOrigin: 1,
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "x-value" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "DELETE"
+ },
+ { pass: 0,
+ method: "PUT"
+ },
+ { pass: 0,
+ method: "DELETE"
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "DELETE"
+ },
+ { pass: 0,
+ method: "DELETE",
+ headers: { "my-header": "value" },
+ },
+ { pass: 0,
+ method: "DELETE"
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ cacheTime: 3600,
+ },
+ { pass: 1,
+ method: "DELETE"
+ },
+ { pass: 0,
+ method: "GET",
+ noOrigin: 1,
+ },
+ { pass: 0,
+ method: "DELETE"
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ withCred: true,
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ cacheTime: 3600
+ },
+ { pass: 1,
+ method: "GET",
+ withCred: true,
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ withCred: true,
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ cacheTime: 3600
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "y-my-header": "myValue" },
+ allowHeaders: "y-my-header",
+ cacheTime: 2
+ },
+ { pass: 1,
+ method: "GET",
+ headers: { "y-my-header": "myValue" },
+ },
+ { pass: 1,
+ method: "GET",
+ withCred: true,
+ headers: { "x-my-header": "myValue" },
+ },
+ { pause: 2.1 },
+ { pass: 1,
+ method: "GET",
+ withCred: true,
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "y-my-header": "myValue" },
+ },
+ { pass: 0,
+ method: "GET",
+ withCred: true,
+ headers: { "y-my-header": "myValue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ cacheTime: 3600
+ },
+ { pass: 0,
+ method: "GET",
+ headers: { "DELETE": "myvalue" },
+ },
+ { newTest: "*******" },
+ { pass: 1,
+ method: "GET",
+ headers: { "x-my-header": "myValue" },
+ allowHeaders: "x-my-header",
+ cacheTime: 3600
+ },
+ { pass: 0,
+ method: "3600",
+ headers: { "x-my-header": "myvalue" },
+ },
+ ];
+
+ for (let i = 0; i < 110; i++) {
+ tests.push({ newTest: "*******" },
+ { pass: 1,
+ method: "DELETE",
+ allowMethods: "DELETE",
+ cacheTime: 3600,
+ });
+ }
+
+ baseURL = "http://mochi.test:8888/tests/dom/security/test/cors/" +
+ "file_CrossSiteXHR_cache_server.sjs?";
+ setStateURL = baseURL + "setState=";
+
+ var unique = Date.now();
+ for (test of tests) {
+ if (test.newTest) {
+ unique++;
+ continue;
+ }
+ if (test.pause) {
+ setTimeout(function() { gen.next() }, test.pause * 1000);
+ yield undefined;
+ continue;
+ }
+
+ req = {
+ url: baseURL + "c=" + unique,
+ method: test.method,
+ headers: test.headers,
+ withCred: test.withCred,
+ };
+
+ sec = { allowOrigin: test.noOrigin ? "" : origin,
+ allowHeaders: test.allowHeaders,
+ allowMethods: test.allowMethods,
+ cacheTime: test.cacheTime,
+ withCred: test.withCred };
+ xhr = new XMLHttpRequest();
+ xhr.open("POST", setStateURL + escape(sec.toSource()), true);
+ xhr.onloadend = function() { gen.next(); }
+ xhr.send();
+ yield undefined;
+
+ loaderWindow.postMessage(req.toSource(), origin);
+
+ res = eval(yield);
+
+ testName = test.toSource() + " (index " + tests.indexOf(test) + ")";
+
+ if (test.pass) {
+ is(res.didFail, false,
+ "shouldn't have failed in test for " + testName);
+ is(res.status, 200, "wrong status in test for " + testName);
+ is(res.responseXML, "<res>hello pass</res>",
+ "wrong responseXML in test for " + testName);
+ is(res.responseText, "<res>hello pass</res>\n",
+ "wrong responseText in test for " + testName);
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs3,rs4,load,loadend",
+ "wrong events in test for " + testName);
+ }
+ else {
+ is(res.didFail, true,
+ "should have failed in test for " + testName);
+ is(res.status, 0, "wrong status in test for " + testName);
+ is(res.responseXML, null,
+ "wrong responseXML in test for " + testName);
+ is(res.responseText, "",
+ "wrong responseText in test for " + testName);
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs4,error,loadend",
+ "wrong events in test for " + testName);
+ is(res.progressEvents, 0,
+ "wrong events in test for " + testName);
+ }
+ }
+
+ SimpleTest.finish();
+
+ yield undefined;
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/security/test/cors/test_CrossSiteXHR_origin.html b/dom/security/test/cors/test_CrossSiteXHR_origin.html
new file mode 100644
index 000000000..1012ae593
--- /dev/null
+++ b/dom/security/test/cors/test_CrossSiteXHR_origin.html
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
+ <title>Test for Cross Site 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>
+<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();
+SimpleTest.requestLongerTimeout(2);
+
+var origins =
+ [{ server: 'http://example.org' },
+ { server: 'http://example.org:80',
+ origin: 'http://example.org'
+ },
+ { server: 'http://sub1.test1.example.org' },
+ { server: 'http://test2.example.org:8000' },
+ { server: 'http://sub1.\xe4lt.example.org:8000',
+ origin: 'http://sub1.xn--lt-uia.example.org:8000'
+ },
+ { server: 'http://sub2.\xe4lt.example.org',
+ origin: 'http://sub2.xn--lt-uia.example.org'
+ },
+ { server: 'http://ex\xe4mple.test',
+ origin: 'http://xn--exmple-cua.test'
+ },
+ { server: 'http://xn--exmple-cua.test' },
+ { server: 'http://\u03c0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1.\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae',
+ origin: 'http://xn--hxajbheg2az3al.xn--jxalpdlp'
+ },
+ { origin: 'http://example.org',
+ file: 'jar:http://example.org/tests/dom/security/test/cors/file_CrossSiteXHR_inner.jar!/file_CrossSiteXHR_inner.html'
+ },
+ { origin: 'null',
+ file: 'http://example.org/tests/dom/security/test/cors/file_CrossSiteXHR_inner_data.sjs'
+ },
+ ];
+
+ //['https://example.com:443'],
+ //['https://sub1.test1.example.com:443'],
+
+window.addEventListener("message", function(e) {
+ gen.send(e.data);
+}, false);
+
+gen = runTest();
+
+function runTest() {
+ var loader = document.getElementById('loader');
+ var loaderWindow = loader.contentWindow;
+ loader.onload = function () { gen.next() };
+
+ // Test preflight-less requests
+ basePath = "/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?"
+ baseURL = "http://mochi.test:8888" + basePath;
+
+ for (originEntry of origins) {
+ origin = originEntry.origin || originEntry.server;
+
+ loader.src = originEntry.file ||
+ (originEntry.server + "/tests/dom/security/test/cors/file_CrossSiteXHR_inner.html");
+ yield undefined;
+
+ var isNullOrigin = origin == "null";
+
+ port = /:\d+/;
+ passTests = [
+ origin,
+ "*",
+ " \t " + origin + "\t \t",
+ "\t \t* \t ",
+ ];
+ failTests = [
+ "",
+ " ",
+ port.test(origin) ? origin.replace(port, "")
+ : origin + ":1234",
+ port.test(origin) ? origin.replace(port, ":")
+ : origin + ":",
+ origin + ".",
+ origin + "/",
+ origin + "#",
+ origin + "?",
+ origin + "\\",
+ origin + "%",
+ origin + "@",
+ origin + "/hello",
+ "foo:bar@" + origin,
+ "* " + origin,
+ origin + " " + origin,
+ "allow <" + origin + ">",
+ "<" + origin + ">",
+ "<*>",
+ origin.substr(0, 5) == "https" ? origin.replace("https", "http")
+ : origin.replace("http", "https"),
+ origin.replace("://", "://www."),
+ origin.replace("://", ":// "),
+ origin.replace(/\/[^.]+\./, "/"),
+ ];
+
+ if (isNullOrigin) {
+ passTests = ["*", "\t \t* \t ", "null"];
+ failTests = failTests.filter(function(v) { return v != origin });
+ }
+
+ for (allowOrigin of passTests) {
+ req = {
+ url: baseURL +
+ "allowOrigin=" + escape(allowOrigin) +
+ "&origin=" + escape(origin),
+ method: "GET",
+ };
+ loaderWindow.postMessage(req.toSource(), isNullOrigin ? "*" : origin);
+
+ res = eval(yield);
+ is(res.didFail, false, "shouldn't have failed for " + allowOrigin);
+ is(res.status, 200, "wrong status for " + allowOrigin);
+ is(res.statusText, "OK", "wrong status text for " + allowOrigin);
+ is(res.responseXML,
+ "<res>hello pass</res>",
+ "wrong responseXML in test for " + allowOrigin);
+ is(res.responseText, "<res>hello pass</res>\n",
+ "wrong responseText in test for " + allowOrigin);
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs3,rs4,load,loadend",
+ "wrong responseText in test for " + allowOrigin);
+ }
+
+ for (allowOrigin of failTests) {
+ req = {
+ url: baseURL + "allowOrigin=" + escape(allowOrigin),
+ method: "GET",
+ };
+ loaderWindow.postMessage(req.toSource(), isNullOrigin ? "*" : origin);
+
+ res = eval(yield);
+ is(res.didFail, true, "should have failed for " + allowOrigin);
+ is(res.responseText, "", "should have no text for " + allowOrigin);
+ is(res.status, 0, "should have no status for " + allowOrigin);
+ is(res.statusText, "", "wrong status text for " + allowOrigin);
+ is(res.responseXML, null, "should have no XML for " + allowOrigin);
+ is(res.events.join(","),
+ "opening,rs1,sending,loadstart,rs2,rs4,error,loadend",
+ "wrong events in test for " + allowOrigin);
+ is(res.progressEvents, 0,
+ "wrong events in test for " + allowOrigin);
+ }
+ }
+
+ SimpleTest.finish();
+
+ yield undefined;
+}
+
+addLoadEvent(function() {
+ SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, function() {
+ gen.next();
+ });
+});
+</script>
+</pre>
+</body>
+</html>