mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-02 05:48:38 +09:00
Potential attack: session supercookie. [Moz Notes](https://bugzilla.mozilla.org/show_bug.cgi?id=1334776#c5): "The problem is that for unknown header names we store the first one we see and then later we case-insensitively match against that name *globally*. That means you can track if a user agent has already seen a certain header name used (by using a different casing and observing whether it gets normalized). This would allow you to see if a user has used a sensitive service that uses custom header names, or allows you to track a user across sites, by teaching the browser about a certain header case once and then observing if different casings get normalized to that. What we should do instead is only store the casing for a header name for each header list and not globally. That way it only leaks where it's expected (and necessary) to leak." [Moz fix note](https://bugzilla.mozilla.org/show_bug.cgi?id=1334776#c8): "nsHttpAtom now holds the old nsHttpAtom and a string that is case sensitive (only for not standard headers). So nsHttpAtom holds a pointer to a header name. (header names are store on a static structure). This is how it used to be. I left that part the same but added a nsCString which holds a string that was used to resoled the header name. So when we parse headers we call ResolveHeader with a char*. If it is a new header name the char* will be stored in a HttpHeapAtom, nsHttpAtom::_val will point to HttpHeapAtom::value and the same strings will be stored in mLocalCaseSensitiveHeader. For the first resolve request they will be the same but for the following maybe not. At the end this nsHttpAtom will be stored in nsHttpHeaderArray. For all operation we will used the old char* except when we are returning it to a script using VisitHeaders."
1461 lines
50 KiB
HTML
1461 lines
50 KiB
HTML
<!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.toLowerCase()], 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>
|