Update web-platform-tests to revision 8a2ceb5f18911302b7a5c1cd2791f4ab50ad4326

This commit is contained in:
Josh Matthews 2017-10-12 09:25:50 -04:00
parent 462c272380
commit 1f531f66ea
5377 changed files with 174916 additions and 84369 deletions

View file

@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that asynchronous XMLHttpRequests handle redirects according to the CORS standard.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script>
function runTest(test, path, credentials, expectSuccess) {
const xhr = new XMLHttpRequest();
xhr.withCredentials = credentials;
xhr.open("GET", "resources/redirect.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN + path, true);
xhr.onload = test.step_func_done(function() {
assert_true(expectSuccess);
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.");
});
xhr.onerror = test.step_func_done(function() {
assert_false(expectSuccess);
assert_equals(xhr.status, 0);
});
xhr.send(null);
}
const withoutCredentials = false;
const withCredentials = true;
const succeeds = true;
const fails = false;
// Test simple same origin requests that receive cross origin redirects.
// The redirect response passes the access check.
async_test(t => {
runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow-star.py",
withoutCredentials, succeeds)
}, "Request without credentials is redirected to a cross-origin response with Access-Control-Allow-Origin=* (with star)");
// The redirect response fails the access check because credentials were sent.
async_test(t => {
runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow-star.py",
withCredentials, fails)
}, "Request with credentials is redirected to a cross-origin response with Access-Control-Allow-Origin=* (with star)");
// The redirect response passes the access check.
async_test(t => {
runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow.py",
withoutCredentials, succeeds)
}, "Request without credentials is redirected to a cross-origin response with a specific Access-Control-Allow-Origin");
// The redirect response passes the access check.
async_test(t => {
runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow.py",
withCredentials, succeeds)
}, "Request with credentials is redirected to a cross-origin response with a specific Access-Control-Allow-Origin");
// forbidding credentials. The redirect response passes the access check.
async_test(t => {
runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow-no-credentials.py",
withoutCredentials, succeeds)
}, "Request without credentials is redirected to a cross-origin response with a specific Access-Control-Allow-Origin (no credentials)");
// forbidding credentials. The redirect response fails the access check.
async_test(t => {
runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow-no-credentials.py",
withCredentials, fails)
}, "Request with credentials is redirected to a cross-origin response with a specific Access-Control-Allow-Origin (no credentials)");
</script>
</body>
</html>

View file

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that asynchronous XMLHttpRequests handle redirects according to the CORS standard.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script>
function runTest(test, destination, parameters, customHeader, local, expectSuccess) {
const xhr = new XMLHttpRequest();
const url = (local ? get_host_info().HTTP_ORIGIN : get_host_info().HTTP_REMOTE_ORIGIN) +
"/XMLHttpRequest/resources/redirect-cors.py?location=" + destination + "&" + parameters;
xhr.open("GET", url, true);
if (customHeader)
xhr.setRequestHeader("x-test", "test");
xhr.onload = test.step_func_done(function() {
assert_true(expectSuccess);
assert_true(xhr.responseText.startsWith("PASS"));
});
xhr.onerror = test.step_func_done(function() {
assert_false(expectSuccess);
assert_equals(xhr.status, 0);
});
xhr.send();
}
const withCustomHeader = true;
const withoutCustomHeader = false;
const local = true;
const remote = false;
const succeeds = true;
const fails = false;
// Test simple cross origin requests that receive redirects.
// The redirect response fails the access check because the redirect lacks a CORS header.
async_test(t => {
runTest(t, get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow-star.py", "",
withoutCustomHeader, remote, fails)
}, "Request is redirected without CORS headers to a response with Access-Control-Allow-Origin=*");
// The redirect response passes the access check.
async_test(t => {
runTest(t, get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow-star.py", "allow_origin=true",
withoutCustomHeader, remote, succeeds)
}, "Request is redirected to a response with Access-Control-Allow-Origin=*");
// The redirect response fails the access check because user info was sent.
async_test(t => {
runTest(t, get_host_info().HTTP_REMOTE_ORIGIN.replace("http://", "http://username:password@") +
"/XMLHttpRequest/resources/access-control-basic-allow-star.py", "allow_origin=true",
withoutCustomHeader, remote, fails)
}, "Request with user info is redirected to a response with Access-Control-Allow-Origin=*");
// The redirect response fails the access check because the URL scheme is unsupported.
async_test(t => {
runTest(t, "foo://bar.cgi", "allow_origin=true", withoutCustomHeader, remote, fails)
}, "Request is redirect to a bad URL");
// The preflighted redirect response fails the access check because of preflighting.
async_test(t => {
runTest(t, get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow-star.py",
"allow_origin=true&redirect_preflight=true", withCustomHeader, remote, fails)
}, "Preflighted request is redirected to a response with Access-Control-Allow-Origin=*");
// The preflighted redirect response fails the access check after successful preflighting.
async_test(t => {
runTest(t, get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow-star.py",
"allow_origin=true&allow_header=x-test&redirect_preflight=true",
withCustomHeader, remote, fails)
}, "Preflighted request is redirected to a response with Access-Control-Allow-Origin=* and header allowed");
// The same-origin redirect response passes the access check.
async_test(t => {
runTest(t, get_host_info().HTTP_ORIGIN + "/XMLHttpRequest/resources/pass.txt",
"", withCustomHeader, local, succeeds)
}, "Request is redirected to a same-origin resource file");
</script>
</body>
</html>

View file

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that redirects between origins are allowed when access control is involved.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script>
function runSync(test, url)
{
const xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.send();
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.");
test.done();
}
function runAsync(test, url)
{
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onload = test.step_func_done(function() {
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.");
});
xhr.onerror = test.unreached_func("Network error");
xhr.send();
test.done();
}
test(t => {
runSync(t, "resources/redirect-cors.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow.py")
}, "Local sync redirect to remote origin");
async_test(t => {
runAsync(t, "resources/redirect-cors.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow.py")
}, "Local async redirect to remote origin");
test(t => {
runSync(t, get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/redirect-cors.py?location=" + get_host_info().HTTP_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow.py&allow_origin=true")
}, "Remote sync redirect to local origin");
async_test(t => {
runAsync(t, get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/redirect-cors.py?location=" + get_host_info().HTTP_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow.py&allow_origin=true")
}, "Remote async redirect to local origin");
test(t => {
runSync(t, get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/redirect-cors.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow.py&allow_origin=true")
}, "Remote sync redirect to same remote origin");
async_test(t => {
runAsync(t, get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/redirect-cors.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow.py&allow_origin=true")
}, "Remote async redirect to same remote origin");
</script>
</body>
</html>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that cross-origin access is granted to null-origin embedded iframe</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
const url = get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-origin-header.py";
async_test(function(test) {
window.addEventListener("message", test.step_func(function(evt) {
if (evt.data == "ready") {
document.getElementById("frame").contentWindow.postMessage(url, "*");
} else {
assert_equals(evt.data, "PASS: Cross-domain access allowed.\nHTTP_ORIGIN: null");
test.done();
}
}), false);
}, "Access granted to null-origin iframe");
</script>
<iframe id="frame" src='data:text/html,
<script>
(function() {
parent.postMessage("ready", "*");
window.addEventListener("message", function(evt) {
try {
const url = evt.data;
const xhr = new XMLHttpRequest;
xhr.open("GET", url, false);
xhr.send();
parent.postMessage(xhr.responseText, "*");
} catch(e) {
parent.postMessage(e.message, "*");
}
});
})();
</script>'>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test(function(test) {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-origin-header.py", false);
xhr.send();
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.\n" +
"HTTP_ORIGIN: " + get_host_info().HTTP_ORIGIN);
test.done();
}, "Access control test with origin header");
</script>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Testing a basic asynchronous CORS XHR request</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test(function(test) {
const xhr = new XMLHttpRequest;
xhr.onreadystatechange = test.step_func(function() {
if (xhr.readyState == xhr.DONE) {
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.");
test.done();
}
});
xhr.onerror = test.unreached_func("FAIL: Network error.");
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-allow.py", true);
xhr.send();
}, "Basic async cross-origin XHR request");
</script>
</body>
</html>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests cross-origin async request with non-CORS-safelisted method</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.\nPASS: PUT data received");
});
xhr.onerror = test.unreached_func("Unexpected error.");
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-put-allow.py");
xhr.setRequestHeader("Content-Type", "text/plain; charset=UTF-8");
xhr.send("PASS: PUT data received");
}, "Allow async PUT request");
</script>
</body>
</html>

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests cross-origin request with non-CORS-safelisted method</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-put-allow.py", false);
xhr.setRequestHeader("Content-Type", "text/plain; charset=UTF-8");
xhr.send("PASS: PUT data received");
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.\nPASS: PUT data received");
}, "Allow PUT request");
</script>
</body>
</html>

View file

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>Preflight cache should be invalidated in presence of custom header</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
const xhr = new XMLHttpRequest;
async_test(function(test) {
xhr.onerror = test.unreached_func("FAIL: Network error.");
xhr.onload = test.step_func(function() {
// Token reset. We can start the test now.
assert_equals(xhr.responseText, "PASS");
firstRequest();
});
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/reset-token.py?token=" + uuid, true);
xhr.send();
function firstRequest() {
xhr.onload = test.step_func(function() {
assert_equals(xhr.responseText, "PASS: First PUT request.");
secondRequest();
});
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py?token=" + uuid, true);
xhr.send();
}
function secondRequest() {
xhr.onload = test.step_func(function() {
assert_equals(xhr.responseText, "PASS: Second OPTIONS request was sent.");
test.done();
});
// Send a header not included in the inital cache.
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py?token=" + uuid, true);
xhr.setRequestHeader("x-test", "headerValue");
xhr.send();
}
}, "Preflight cache should be invalidated in presence of custom header");
</script>
</body>
</html>

View file

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>Preflight cache should be invalidated by changed method</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
const xhr = new XMLHttpRequest;
async_test(function(test) {
xhr.onerror = test.unreached_func("FAIL: Network error.");
xhr.onload = test.step_func(function() {
// Token reset. We can start the test now.
assert_equals(xhr.responseText, "PASS");
firstRequest();
});
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/reset-token.py?token=" + uuid, true);
xhr.send();
function firstRequest() {
xhr.onload = test.step_func(function() {
assert_equals(xhr.responseText, "PASS: First PUT request.");
secondRequest();
});
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py?token=" + uuid, true);
xhr.send();
}
function secondRequest() {
xhr.onload = test.step_func(function() {
assert_equals(xhr.responseText, "PASS: Second OPTIONS request was sent.");
test.done();
});
// Send a header not included in the inital cache.
xhr.open("XMETHOD", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py?token=" + uuid, true);
xhr.send();
}
}, "Preflight cache should be invalidated by changed method");
</script>
</body>
</html>

View file

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>Preflight cache should be invalidated on timeout</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
let xhr = new XMLHttpRequest;
async_test(function(test) {
xhr.onerror = test.unreached_func("FAIL: Network error.");
xhr.onload = test.step_func(function() {
// Token reset. We can start the test now.
assert_equals(xhr.responseText, "PASS");
firstRequest();
});
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/reset-token.py?token=" + uuid, true);
xhr.send();
function firstRequest() {
xhr.onload = test.step_func(function() {
assert_equals(xhr.responseText, "PASS: First PUT request.");
step_timeout(secondRequest, 3000); // 3 seconds
});
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache-timeout.py?token=" + uuid, true);
xhr.send();
}
function secondRequest() {
xhr.onload = test.step_func(function() {
assert_equals(xhr.responseText, "PASS: Second OPTIONS request was sent.");
test.done();
});
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache-timeout.py?token=" + uuid, true);
xhr.send();
}
}, "Preflight cache should be invalidated on timeout");
</script>
</body>
</html>

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<title>Preflight cache should allow second request without preflight OPTIONS request</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
async_test(function(test) {
const xhr = new XMLHttpRequest;
xhr.onerror = test.unreached_func("FAIL: Network error.");
xhr.onload = test.step_func(function() {
// Token reset. We can start the test now.
assert_equals(xhr.responseText, "PASS");
firstRequest();
});
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/reset-token.py?token=" + uuid, true);
xhr.send();
function firstRequest() {
xhr.onload = test.step_func(function() {
assert_equals(xhr.responseText, "PASS: First PUT request.");
secondRequest();
});
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache.py?token=" + uuid, true);
xhr.send();
}
function secondRequest() {
xhr.onload = test.step_func_done(function() {
assert_equals(xhr.responseText, "PASS: Second PUT request. Preflight worked.");
});
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache.py?token=" + uuid, true);
xhr.send();
}
}, "Preflight cache should allow second request");
</script>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests "*" setting for Access-Control-Allow-Origin header</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
const xhr = new XMLHttpRequest;
test(function(test) {
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-allow-star.py", false);
xhr.send();
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.");
}, "Allow star");
</script>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests CORS with Access-Control-Allow-Origin header</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-allow.py", false);
xhr.send();
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.");
}, "Allow basic");
</script>
</body>
</html>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that CORS-safelisted request headers are permitted in cross-origin request</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("POST", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-cors-safelisted-request-headers.py", false);
xhr.setRequestHeader("Accept", "*");
xhr.setRequestHeader("Accept-Language", "ru");
xhr.setRequestHeader("Content-Language", "ru");
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.setRequestHeader("Save-Data", "on");
xhr.send();
assert_equals(xhr.responseText,
"Accept: *\n" +
"Accept-Language: ru\n" +
"Content-Language: ru\n" +
"Content-Type: text/plain\n");
}, "Request with CORS-safelisted headers");
</script>
</body>
</html>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that CORS-safelisted response headers are permitted in cross-origin request</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-whitelist-response-headers.py", false);
xhr.send();
assert_not_equals(xhr.getResponseHeader("cache-control"), null);
assert_not_equals(xhr.getResponseHeader("content-language"), null);
assert_not_equals(xhr.getResponseHeader("content-type"), null);
assert_not_equals(xhr.getResponseHeader("expires"), null);
assert_not_equals(xhr.getResponseHeader("last-modified"), null);
assert_not_equals(xhr.getResponseHeader("pragma"), null);
assert_equals(xhr.getResponseHeader("x-webkit"), null);
assert_not_equals(xhr.getAllResponseHeaders().match("en"), null);
assert_equals(xhr.getAllResponseHeaders().match("foobar"), null);
}, "Response with CORS-safelisted headers");
</script>
</body>
</html>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests CORS denying resource without Access-Control-Allow-Origin header</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
const path = "/XMLHttpRequest/resources/access-control-basic-denied.py";
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_ORIGIN + path, false);
xhr.send();
assert_equals(xhr.status, 200);
}, "Same-origin request accepted");
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + path, false);
try {
xhr.send();
assert_unreached("Error should occur here");
} catch(e) {
assert_equals(xhr.status, 0);
}
}, "Cross-origin request denied");
</script>
</body>
</html>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests CORS denying preflighted request to resource without CORS headers for OPTIONS</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-options-not-supported.py", false);
// Non-CORS-safelisted header
xhr.setRequestHeader("x-test", "foobar");
// This fails because the server-side script is not prepared for an OPTIONS request
try {
xhr.send();
} catch(e) {
assert_equals(xhr.status, 0);
return;
}
assert_unreached("Preflighted request was not denied.");
}, "Preflighted cross-origin request denied");
</script>
</body>
</html>

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests cross-origin request with non-CORS-safelisted content type</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(() => {
const xhr = new XMLHttpRequest;
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-put-allow.py", false);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.send("PASS: PUT data received");
assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.\nPASS: PUT data received");
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-put-allow.py", false);
xhr.setRequestHeader("Content-Type", "application/xml");
try {
xhr.send("FAIL: PUT data received");
} catch(e) {
assert_equals(xhr.status, 0, "Cross-domain access was denied in 'send'.");
return;
}
assert_unreached("Cross-domain access was not denied in 'send'.");
}, "Deny cross-origin request with non-CORS-safelisted content type");
</script>
</body>
</html>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that POST requests with text content and no content-type set explicitly don't generate a preflight request.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test(function(test) {
const xhr = new XMLHttpRequest;
xhr.open("POST", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-options-not-supported.py");
xhr.onerror = test.unreached_func("Network error.");
xhr.onload = test.step_func_done(function() {
assert_equals(xhr.status, 200);
});
xhr.send("Test");
}, "POST request with text content and no Content-Type header");
</script>
</body>
</html>

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>Non-CORS-safelisted value in the Content-Type header results in a request preflight</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("POST", get_host_info().HTTP_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-options-not-supported.py", false);
xhr.setRequestHeader("Content-Type", "application/xml");
xhr.send();
assert_equals(xhr.status, 200, "Same-origin access doesn't issue preflight; not denied.");
}, "Same-origin request with non-safelisted content type succeeds");
test(function() {
const xhr = new XMLHttpRequest;
xhr.open("POST", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-options-not-supported.py", false);
xhr.setRequestHeader("Content-Type", "application/xml");
try {
xhr.send();
} catch(e) {
assert_equals(xhr.status, 0, "Cross-domain access was denied in 'send'.");
return;
}
assert_unreached("Cross-domain access was not denied in 'send'.");
}, "CORS request with non-safelisted content type sends preflight and fails");
</script>
</body>
</html>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests async XHR preflight denial due to lack of CORS headers</title>
<!--The original test addressed a more specific issue involving caching,
but that issue has since been resolved.
We maintain this test as a basic test of invalid preflight denial.
Please refer to the comment in the following link for more information:
https://chromium-review.googlesource.com/c/chromium/src/+/630338#message-0280542b95c9b0f82b121dc373320c04fcaece31
-->
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.onerror = test.step_func_done(() => {
assert_equals(xhr.status, 0);
});
xhr.onload = test.unreached_func("Request succeeded unexpectedly");
xhr.open("FOO", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-denied.py");
xhr.send();
});
</script>
</body>
</html>

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<title>Async request denied at preflight because of non-CORS-safelisted header</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
const url = get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-preflight-denied.py?token=" + uuid;
async_test((test) => {
let xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=reset", false);
xhr.send();
xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=header", true);
xhr.setRequestHeader("x-test", "foo");
xhr.onload = test.unreached_func(
"Cross-domain access with custom header allowed without throwing exception");
xhr.onerror = test.step_func_done(() => {
xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=complete", false);
xhr.send();
assert_equals(xhr.responseText, "Request successfully blocked.");
});
xhr.send();
}, "Async request denied at preflight");
</script>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Async request denied at preflight because of non-CORS-safelisted method</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
const url = get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-preflight-denied.py?token=" + uuid;
async_test((test) => {
let xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=reset", false);
xhr.send();
xhr = new XMLHttpRequest;
xhr.open("DELETE", url + "&command=method", true);
xhr.onload = test.unreached_func(
"Cross-domain access with non-CORS-safelisted method allowed without throwing exception");
xhr.onerror = test.step_func_done(() => {
xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=complete", false);
xhr.send();
assert_equals(xhr.responseText, "Request successfully blocked.");
});
xhr.send();
}, "Async request denied at preflight");
</script>
</body>
</html>

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Async PUT request denied at preflight</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
const url = get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-preflight-denied.py?token=" + uuid;
async_test((test) => {
let xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=reset", false);
xhr.send();
xhr = new XMLHttpRequest;
xhr.open("PUT", url, true);
xhr.onload = test.unreached_func("Cross-domain access allowed unexpectedly.");
xhr.onerror = test.step_func_done(() => {
xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=complete", false);
xhr.send();
assert_equals(xhr.responseText, "Request successfully blocked.");
});
xhr.send();
});
</script>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests proper handling of cross-origin async request with credentials</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-auth-basic.py?uid=fooUser",
true, "fooUser", "barPass");
xhr.withCredentials = true;
xhr.onerror = test.unreached_func("Unexpected error.");
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.status, 401, "Request raises HTTP 401: Unauthorized error.");
});
xhr.send();
}, "CORS async request with URL credentials");
</script>
</body>
</html>

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests proper handling of cross-origin sync request with credentials</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(() => {
const xhr = new XMLHttpRequest;
xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-auth-basic.py?uid=fooUser", false, "fooUser", "barPass");
xhr.withCredentials = true;
xhr.send();
assert_equals(xhr.status, 401, "Request raises HTTP 401: Unauthorized error.");
}, "CORS sync request with URL credentials");
</script>
</body>
</html>

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<title>Test that async CORS requests with custom headers are sent with OPTIONS preflight</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
let xhr = new XMLHttpRequest;
const uuid = token();
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/reset-token.py?token=" + uuid, false);
xhr.send();
xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/no-custom-header-on-preflight.py?token=" + uuid);
xhr.setRequestHeader("x-test", "foobar");
xhr.onerror = test.unreached_func("Unexpected error");
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.responseText, "PASS");
});
xhr.send();
}, "Preflighted async request with custom header");
</script>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Test that sync CORS requests with custom headers are not sent with OPTIONS preflight</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
test(function() {
let xhr = new XMLHttpRequest;
const uuid = token();
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/reset-token.py?token=" + uuid, false);
xhr.send();
xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/no-custom-header-on-preflight.py?token=" + uuid, false);
xhr.setRequestHeader("x-test", "foobar");
xhr.send();
assert_equals(xhr.responseText, "PASS");
}, "Preflighted sync request with custom header");
</script>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Access-Control-Request-Headers values should be lowercase</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test(function(test) {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-preflight-request-header-lowercase.py");
xhr.setRequestHeader("X-Test", "foobar");
xhr.onerror = test.unreached_func("Error occurred.");
xhr.onload = test.step_func_done(function() {
assert_equals(xhr.status, 200);
assert_equals(xhr.responseText, "PASS");
});
xhr.send();
}, "Request with uppercase header set");
</script>
</body>
</html>

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that Access-Control-Request-Headers are sorted.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script>
async_test((test) => {
const xhr = new XMLHttpRequest();
const url = get_host_info().HTTP_REMOTE_ORIGIN + '/XMLHttpRequest/resources/access-control-preflight-request-header-sorted.py';
xhr.open('GET', url);
xhr.setRequestHeader("X-Custom-Test", "foobar");
xhr.setRequestHeader("X-Custom-ua", "foobar");
xhr.setRequestHeader("X-Custom-V", "foobar");
xhr.setRequestHeader("X-Custom-s", "foobar");
xhr.setRequestHeader("X-Custom-U", "foobar");
xhr.onerror = test.unreached_func('xhr failure');
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.responseText, 'PASS');
});
xhr.send();
});
</script>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Test that 'Origin' is not included in Access-Control-Request-Headers in a preflight request</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
const url = get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-preflight-request-headers-origin.py";
xhr.open("GET", url);
xhr.setRequestHeader("x-pass", "PASS");
xhr.onerror = test.unreached_func("Unexpected error");
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.responseText, "PASS");
});
xhr.send();
}, "'Origin' should not be included in CORS Request-Headers");
</script>
</body>
</html>

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that preflight requests returning invalid 301 status code result in error.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-preflight-request-invalid-status.py?code=301");
xhr.setRequestHeader("x-pass", "pass");
xhr.onerror = test.step_func_done(function() {
assert_equals(xhr.status, 0);
});
xhr.onload = test.unreached_func("Invalid 301 response to preflight should result in error.");
xhr.send();
}, "Request with 301 preflight response");
</script>
</body>
</html>

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that preflight requests returning invalid 400 status code result in error.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-preflight-request-invalid-status.py?code=400");
xhr.setRequestHeader("x-pass", "pass");
xhr.onerror = test.step_func_done(function() {
assert_equals(xhr.status, 0);
});
xhr.onload = test.unreached_func("Invalid 400 response to preflight should result in error.");
xhr.send();
}, "Request with 400 preflight response");
</script>
</body>
</html>

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that preflight requests returning invalid 501 status code result in error.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-preflight-request-invalid-status.py?code=501");
xhr.setRequestHeader("x-pass", "pass");
xhr.onerror = test.step_func_done(function() {
assert_equals(xhr.status, 0);
});
xhr.onload = test.unreached_func("Invalid 501 response to preflight should result in error.");
xhr.send();
}, "Request with 501 preflight response");
</script>
</body>
</html>

View file

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<title>Preflight request must not contain any cookie header</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
function setupCookie() {
const xhr = new XMLHttpRequest;
// Delete all preexisting cookies and set a cookie named "foo"
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-cookie.py?cookie_name=foo");
xhr.withCredentials = true;
xhr.send();
xhr.onerror = test.unreached_func("Unexpected error.");
xhr.onload = test.step_func(() => {
assert_equals(xhr.status, 200);
sendPreflightedRequest();
});
}
function sendPreflightedRequest() {
const xhr = new XMLHttpRequest;
// Request to server-side file fails if cookie is included in preflight
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-preflight-request-must-not-contain-cookie.py");
xhr.withCredentials = true;
xhr.setRequestHeader("X-Proprietary-Header", "foo");
xhr.onerror = test.unreached_func("Unexpected error.");
xhr.onload = test.step_func(() => {
assert_equals(xhr.status, 200);
assert_equals(xhr.responseText, "COOKIE");
cleanupCookies();
});
xhr.send();
}
function cleanupCookies() {
const xhr = new XMLHttpRequest;
// Delete all cookies
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-cookie.py");
xhr.withCredentials = true;
xhr.send();
xhr.onerror = test.unreached_func("Unexpected error.");
xhr.onload = test.step_func_done(() => {});
}
setupCookie();
});
</script>
</body>
</html>

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<title>Sync request denied at preflight because of non-CORS-safelisted header</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
const url = get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-preflight-denied.py?token=" + uuid;
test(() => {
let xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=reset", false);
xhr.send();
xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=header", false);
xhr.setRequestHeader("x-test", "foo");
try {
xhr.send();
} catch(e) {
xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=complete", false);
xhr.send();
assert_equals(xhr.responseText, "Request successfully blocked.");
return;
}
assert_unreached("Cross-domain access with custom header allowed without throwing exception");
}, "Sync request denied at preflight");
</script>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Sync request denied at preflight because of non-CORS-safelisted method</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
const url = get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-preflight-denied.py?token=" + uuid;
test(() => {
let xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=reset", false);
xhr.send();
xhr = new XMLHttpRequest;
xhr.open("DELETE", url + "&command=method", false);
try {
xhr.send();
} catch(e) {
xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=complete", false);
xhr.send();
assert_equals(xhr.responseText, "Request successfully blocked.");
return;
}
assert_unreached("Cross-domain access with non-CORS-safelisted method allowed without throwing exception");
});
</script>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Sync PUT request denied at preflight</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script type="text/javascript">
const uuid = token();
const url = get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-preflight-denied.py?token=" + uuid;
test(() => {
let xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=reset", false);
xhr.send();
xhr = new XMLHttpRequest;
xhr.open("PUT", url, false);
try {
xhr.send("");
} catch(e) {
xhr = new XMLHttpRequest;
xhr.open("GET", url + "&command=complete", false);
xhr.send();
assert_equals(xhr.responseText, "Request successfully blocked.");
return;
}
assert_unreached("Cross-domain access allowed without throwing exception");
});
</script>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Recursively repeated CORS requests with failed preflights should never result in unexpected behavior</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
let requestCount = 0;
const requestMax = 10;
async_test((test) => {
function preflightRequest() {
const xhr = new XMLHttpRequest;
xhr.onload = test.unreached_func("Request succeeded unexpectedly.");
xhr.onerror = test.step_func(() => {
assert_equals(xhr.status, 0);
if (++requestCount >= requestMax) {
test.done();
return;
}
preflightRequest();
});
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-basic-denied.py");
xhr.send();
}
preflightRequest();
});
</script>
</body>
</html>

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests body from CORS preflight response and actual response with sync request</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
test(() => {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN+
"/XMLHttpRequest/resources/access-control-allow-with-body.py", false);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.send();
assert_equals(xhr.status, 200);
assert_equals(xhr.responseText, "PASS");
});
</script>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that XHR doesn't prepend the body from CORS preflight response to the actual response</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.onerror = test.unreached_func("Unexpected error.");
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.status, 200);
assert_equals(xhr.responseText, "PASS");
});
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/access-control-allow-with-body.py");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.send();
});
</script>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Test CORS response with 'Access-Control-Expose-Headers' header</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN +
"/XMLHttpRequest/resources/pass.txt?pipe=" +
"header(Cache-Control,no-cache)|" +
"header(Access-Control-Max-Age,0)|" +
"header(Access-Control-Allow-Origin,*)|" +
"header(X-foo,BAR)|" +
"header(x-test,TEST)|" +
"header(Access-Control-Expose-Headers,x-Foo)|",
"header(Content-Type,text/html)");
xhr.onerror = test.unreached_func("Unexpected error");
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.status, 200);
assert_equals(xhr.getResponseHeader("X-FOO"), "BAR");
assert_equals(xhr.getResponseHeader("x-foo"), "BAR");
assert_equals(xhr.getResponseHeader("x-test"), null);
assert_equals(xhr.responseText, "PASS\n");
});
xhr.send();
});
</script>
</body>
</html>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that sandboxed iframe has CORS XHR access to a server that accepts null domain</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
window.addEventListener("message", test.step_func((evt) => {
if (evt.data === "ready") {
document.getElementById("frame").contentWindow.postMessage(
get_host_info().HTTP_ORIGIN +
"/XMLHttpRequest/resources/pass.txt?pipe=" +
"header(Cache-Control,no-store)|" +
"header(Content-Type,text/plain)|" +
"header(Access-Control-Allow-Credentials,true)|" +
"header(Access-Control-Allow-External,true)|" +
"header(Access-Control-Allow-Origin,null)", "*");
} else {
assert_equals(evt.data.trim(), "PASS");
test.done();
}
}), false);
});
</script>
<iframe id="frame" sandbox="allow-scripts" src="/XMLHttpRequest/resources/access-control-sandboxed-iframe.html">
</iframe>
</body>
</html>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that sandboxed iframe has CORS XHR access to a server that accepts all domains</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test((test) => {
window.addEventListener("message", test.step_func((evt) => {
if (evt.data === "ready") {
document.getElementById("frame").contentWindow.postMessage(
get_host_info().HTTP_ORIGIN +
"/XMLHttpRequest/resources/pass.txt?pipe=" +
"header(Cache-Control,no-store)|" +
"header(Content-Type,text/plain)|" +
"header(Access-Control-Allow-Credentials,true)|" +
"header(Access-Control-Allow-External,true)|" +
"header(Access-Control-Allow-Origin,*)", "*");
} else {
assert_equals(evt.data.trim(), "PASS");
test.done();
}
}), false);
});
</script>
<iframe id="frame" sandbox="allow-scripts" src="/XMLHttpRequest/resources/access-control-sandboxed-iframe.html">
</iframe>
</body>
</html>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that sandboxed iframe does not have CORS XHR access to server with "Access-Control-Allow-Origin" set to the original origin</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
const path = "/XMLHttpRequest/resources/pass.txt?pipe=" +
"header(Cache-Control,no-store)|" +
"header(Content-Type,text/plain)" +
"header(Access-Control-Allow-Credentials,true)|" +
"header(Access-Control-Allow-Origin," + get_host_info().HTTP_ORIGIN + ")";
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + path);
xhr.send();
xhr.onerror = test.unreached_func("Unexpected error");
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.status, 200);
assert_equals(xhr.responseText.trim(), "PASS");
});
}, "Check that path exists and is accessible via CORS XHR request");
async_test((test) => {
window.addEventListener("message", test.step_func((evt) => {
if (evt.data === "ready") {
document.getElementById("frame").contentWindow.postMessage(
get_host_info().HTTP_REMOTE_ORIGIN + path, "*");
} else {
assert_equals(evt.data, "Exception thrown. Sandboxed iframe XHR access was denied in 'send'.");
test.done();
}
}), false);
}, "Sandboxed iframe is denied CORS access to server that allows parent origin");
</script>
<iframe id="frame" sandbox="allow-scripts" src="/XMLHttpRequest/resources/access-control-sandboxed-iframe.html">
</iframe>
</body>
</html>

View file

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests that sandboxed iframe does not have CORS XHR access to its server</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
const path = "/XMLHttpRequest/resources/pass.txt?pipe=" +
"header(Cache-Control,no-store)|" +
"header(Content-Type,text/plain)";
async_test((test) => {
const xhr = new XMLHttpRequest;
xhr.open("GET", get_host_info().HTTP_ORIGIN + path);
xhr.send();
xhr.onerror = test.unreached_func("Unexpected error");
xhr.onload = test.step_func_done(() => {
assert_equals(xhr.status, 200);
assert_equals(xhr.responseText.trim(), "PASS");
});
}, "Check that path exists and is accessible via local XHR request");
async_test((test) => {
window.addEventListener("message", test.step_func((evt) => {
if (evt.data === "ready") {
document.getElementById("frame").contentWindow.postMessage(
get_host_info().HTTP_ORIGIN + path, "*");
} else {
assert_equals(evt.data, "Exception thrown. Sandboxed iframe XHR access was denied in 'send'.");
test.done();
}
}), false);
}, "Sandboxed iframe is denied access to path");
</script>
<iframe id="frame" sandbox="allow-scripts" src="/XMLHttpRequest/resources/access-control-sandboxed-iframe.html">
</iframe>
</body>
</html>

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<title>Allow lists starting with a comma should be parsed correctly</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script type="text/javascript">
async_test(function(test) {
const client = new XMLHttpRequest();
let url = "XMLHttpRequest/resources/access-control-allow-lists.py?headers=,y-lol,x-print,%20,,,y-print&origin=" +
get_host_info().HTTP_ORIGIN;
client.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + '/' + url, false);
client.setRequestHeader('x-print', 'unicorn')
client.setRequestHeader('y-print', 'narwhal')
// Sending GET request with custom headers
assert_equals(client.send(null), undefined);
const response = JSON.parse(client.response);
assert_equals(response['x-print'], "unicorn");
assert_equals(response['y-print'], "narwhal");
url = "XMLHttpRequest/resources/access-control-allow-lists.py?methods=,,PUT,GET&origin=" +
get_host_info().HTTP_ORIGIN;
client.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + '/' + url, false);
// Sending PUT request
assert_equals(client.send(null), undefined);
test.done();
}, "Allow lists starting with a comma should be parsed correctly");
</script>
</body>
</html>

View file

@ -10,13 +10,13 @@
if (typeof mimeType === 'undefined' || mimeType === null) mimeType = 'text/plain';
var test = async_test("XHR method " + method + " with MIME type " + mimeType + (testNamePostfix||''));
test.step(function() {
var client = new XMLHttpRequest();
var client = new XMLHttpRequest(),
body = method === "HEAD" ? "" : "Hello, World!";
client.onreadystatechange = test.step_func(function () {
if (client.readyState !== 4) {
return;
}
assert_equals(client.responseText, "Hello, World!");
assert_equals(client.responseText, body);
assert_equals(client.status, 200);
assert_equals(client.getResponseHeader('Content-Type'), mimeType);
var allHeaders = client.getAllResponseHeaders();

View file

@ -4,23 +4,30 @@
<title>XMLHttpRequest: upload progress event for cross-origin requests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onprogress" data-tested-assertations="../.." />
<link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::*//a[contains(@href,'#make-upload-progress-notifications')] following::ol[1]/li[8]" />
<link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-upload" data-tested-assertations=".." />
<div id="log"></div>
<script src="/common/get-host-info.sub.js"></script>
<div id="log"></div>
<script>
var test = async_test();
test.step(function() {
var client = new XMLHttpRequest();
client.upload.onprogress = test.step_func(function() {
test.done();
});
client.onload = test.step_func(function() {
assert_unreached("onprogress not called.");
});
client.open("POST", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/corsenabled.py");
client.send("This is a test string.");
});
const remote = get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/corsenabled.py",
redirect = "resources/redirect.py?code=307&location=" + remote;
[remote, redirect].forEach(url => {
async_test(test => {
const client = new XMLHttpRequest();
client.upload.onprogress = test.step_func_done()
client.onload = test.unreached_func()
client.open("POST", url)
client.send("On time: " + url)
}, "Upload events registered on time (" + url + ")");
});
[remote, redirect].forEach(url => {
async_test(test => {
const client = new XMLHttpRequest();
client.onload = test.step_func_done();
client.open("POST", url);
client.send("Too late: " + url);
client.upload.onloadstart = test.unreached_func(); // registered too late
client.upload.onprogress = test.unreached_func(); // registered too late
}, "Upload events registered too late (" + url + ")");
});
</script>

View file

@ -12,8 +12,8 @@
<script type="text/javascript">
var test = async_test() // This "test" does not actually do any assertations. It's just there to have multiple, separate, asyncronous sub-tests.
var expectations = {
'Referer header': 'referer: '+(location.href.replace(/[^/]*$/, ''))+"resources/workerxhr-origin-referrer.js\n",
'Origin header': 'origin: '+location.protocol+'//'+location.hostname+((location.port === "")?"":":"+location.port)+'\n',
'Referer header': 'Referer: '+(location.href.replace(/[^/]*$/, ''))+"resources/workerxhr-origin-referrer.js\n",
'Origin header': 'Origin: '+location.protocol+'//'+location.hostname+((location.port === "")?"":":"+location.port)+'\n',
'Request URL test' : (location.href.replace(/[^/]*$/, ''))+'resources/requri.py?full'
}
// now start the worker

View file

@ -59,7 +59,7 @@ async_test(t => {
})
client.open("GET", "resources/status.py")
client.responseType = "blob"
client.overrideMimeType("HI/x;test")
client.overrideMimeType("HI/x;test=test")
client.send()
}, "Valid MIME types need to be normalized")
</script>

View file

@ -0,0 +1,20 @@
import json
def main(request, response):
if "origin" in request.GET:
response.headers.set("Access-Control-Allow-Origin", request.GET["origin"])
elif "origins" in request.GET:
for origin in request.GET["origins"].split(','):
response.headers.set("Access-Control-Allow-Origin", request.GET["origin"])
if "headers" in request.GET:
response.headers.set("Access-Control-Allow-Headers", request.GET["headers"])
if "methods" in request.GET:
response.headers.set("Access-Control-Allow-Methods", request.GET["methods"])
headers = dict(request.headers)
for header in headers:
headers[header] = headers[header][0]
return json.dumps(headers)

View file

@ -0,0 +1,15 @@
def main(request, response):
headers = {
"Cache-Control": "no-store",
"Access-Control-Allow-Headers": "X-Requested-With",
"Access-Control-Max-Age": 0,
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*",
"Vary": "Accept-Encoding",
"Content-Type": "text/plain"
}
for (name, value) in headers.items():
response.headers.set(name, value)
response.content = "PASS"

View file

@ -0,0 +1,17 @@
def main(request, response):
response.headers.set("Cache-Control", "no-store")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.headers.set("Access-Control-Allow-Credentials", "true")
uid = request.GET.first("uid", None)
if request.method == "OPTIONS":
response.headers.set("Access-Control-Allow-Methods", "PUT")
else:
username = request.auth.username
password = request.auth.password
if (not username) or (username != uid):
response.headers.set("WWW-Authenticate", "Basic realm='Test Realm/Cross Origin'")
response.status = 401
response.content = "Authentication cancelled"
else:
response.content = "User: " + username + ", Password: " + password

View file

@ -0,0 +1,6 @@
#!/usr/bin/env python
def main(request, response):
response.headers.set("Content-Type", "text/plain")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.content = "PASS: Cross-domain access allowed."

View file

@ -0,0 +1,6 @@
#!/usr/bin/env python
def main(request, response):
response.headers.set("Content-Type", "text/plain")
response.headers.set("Access-Control-Allow-Origin", "*")
response.content = "PASS: Cross-domain access allowed."

View file

@ -0,0 +1,7 @@
#!/usr/bin/env python
def main(request, response):
response.headers.set("Content-Type", "text/plain")
response.headers.set("Access-Control-Allow-Credentials", "true")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.content = "PASS: Cross-domain access allowed."

View file

@ -0,0 +1,14 @@
def main(request, response):
response.headers.set("Cache-Control", "no-store")
# This should be a simple request; deny preflight
if request.method != "POST":
response.status = 400
return
response.headers.set("Access-Control-Allow-Credentials", "true")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
for header in ["Accept", "Accept-Language", "Content-Language", "Content-Type"]:
value = request.headers.get(header)
response.content += header + ": " + (value if value else "<None>") + '\n'

View file

@ -0,0 +1,5 @@
def main(request, response):
response.headers.set("Cache-Control", "no-store")
response.headers.set("Content-Type", "text/plain")
response.text = "FAIL: Cross-domain access allowed."

View file

@ -0,0 +1,9 @@
def main(request, response):
response.headers.set("Cache-Control", "no-store")
# Allow simple requests, but deny preflight
if request.method != "OPTIONS":
response.headers.set("Access-Control-Allow-Credentials", "true")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
else:
response.status = 400

View file

@ -0,0 +1,47 @@
def main(request, response):
def fail(message):
response.content = "FAIL " + request.method + ": " + str(message)
def getState(token):
server_state = request.server.stash.take(token)
if not server_state:
return "Uninitialized"
return server_state
def setState(state, token):
request.server.stash.put(token, state)
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.headers.set("Access-Control-Allow-Credentials", "true")
token = request.GET.first("token", None)
state = getState(token)
if state == "Uninitialized":
if request.method == "OPTIONS":
response.headers.set("Access-Control-Allow-Methods", "PUT")
response.headers.set("Access-Control-Max-Age", 10)
setState("OPTIONSSent", token)
else:
fail(state)
elif state == "OPTIONSSent":
if request.method == "PUT":
response.content = "PASS: First PUT request."
setState("FirstPUTSent", token)
else:
fail(state)
elif state == "FirstPUTSent":
if request.method == "OPTIONS":
response.headers.set("Access-Control-Allow-Methods", "PUT, XMETHOD")
response.headers.set("Access-Control-Allow-Headers", "x-test")
setState("SecondOPTIONSSent", token)
elif request.method == "PUT":
fail("Second PUT request sent without preflight")
else:
fail(state)
elif state == "SecondOPTIONSSent":
if request.method == "PUT" or request.method == "XMETHOD":
response.content = "PASS: Second OPTIONS request was sent."
else:
fail(state)
else:
fail(state)

View file

@ -0,0 +1,48 @@
def main(request, response):
def fail(message):
response.content = "FAIL " + request.method + ": " + str(message)
def getState(token):
server_state = request.server.stash.take(token)
if not server_state:
return "Uninitialized"
return server_state
def setState(state, token):
request.server.stash.put(token, state)
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.headers.set("Access-Control-Allow-Credentials", "true")
token = request.GET.first("token", None)
state = getState(token)
if state == "Uninitialized":
if request.method == "OPTIONS":
response.headers.set("Access-Control-Allow-Methods", "PUT")
response.headers.set("Access-Control-Allow-Headers", "x-test")
response.headers.set("Access-Control-Max-Age", 1)
setState("OPTIONSSent", token)
else:
fail(state)
elif state == "OPTIONSSent":
if request.method == "PUT":
response.content = "PASS: First PUT request."
setState("FirstPUTSent", token)
else:
fail(state)
elif state == "FirstPUTSent":
if request.method == "OPTIONS":
response.headers.set("Access-Control-Allow-Methods", "PUT")
response.headers.set("Access-Control-Allow-Headers", "x-test")
setState("SecondOPTIONSSent", token)
elif request.method == "PUT":
fail("Second PUT request sent without preflight")
else:
fail(state)
elif state == "SecondOPTIONSSent":
if request.method == "PUT":
response.content = "PASS: Second OPTIONS request was sent."
else:
fail(state)
else:
fail(state)

View file

@ -0,0 +1,47 @@
def main(request, response):
def fail(message):
response.content = "FAIL " + request.method + ": " + str(message)
response.status = 400
def getState(token):
server_state = request.server.stash.take(token)
if not server_state:
return "Uninitialized"
return server_state
def setState(state, token):
request.server.stash.put(token, state)
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.headers.set("Access-Control-Allow-Credentials", "true")
token = request.GET.first("token", None)
state = getState(token)
if state == "Uninitialized":
if request.method == "OPTIONS":
response.headers.set("Access-Control-Allow-Methods", "PUT")
response.headers.set("Access-Control-Max-Age", 10)
setState("OPTIONSSent", token)
else:
fail(state)
elif state == "OPTIONSSent":
if request.method == "PUT":
response.content = "PASS: First PUT request."
setState("FirstPUTSent", token)
else:
fail(state)
elif state == "FirstPUTSent":
if request.method == "PUT":
response.content = "PASS: Second PUT request. Preflight worked."
elif request.method == "OPTIONS":
response.headers.set("Access-Control-Allow-Methods", "PUT")
setState("FAILSecondOPTIONSSent", token)
else:
fail(state)
elif state == "FAILSecondOPTIONSSent":
if request.method == "PUT":
fail("Second OPTIONS request was sent. Preflight failed.")
else:
fail(state)
else:
fail(state)

View file

@ -0,0 +1,20 @@
def main(request, response):
if request.method == "OPTIONS":
response.headers.set("Content-Type", "text/plain")
response.headers.set("Access-Control-Allow-Credentials", "true")
response.headers.set("Access-Control-Allow-Methods", "PUT")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
elif request.method == "PUT":
response.headers.set("Content-Type", "text/plain")
response.headers.set("Access-Control-Allow-Credentials", "true")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.content = "PASS: Cross-domain access allowed."
try:
response.content += "\n" + request.body
except:
response.content += "Could not read in content."
else:
response.headers.set("Content-Type", "text/plain")
response.content = "Wrong method: " + request.method

View file

@ -0,0 +1,19 @@
def main(request, response):
headers = {
# CORS-safelisted
"content-type": "text/plain",
"cache-control": "no cache",
"content-language": "en",
"expires": "Fri, 30 Oct 1998 14:19:41 GMT",
"last-modified": "Tue, 15 Nov 1994 12:45:26 GMT",
"pragma": "no-cache",
# Non-CORS-safelisted
"x-test": "foobar",
"Access-Control-Allow-Origin": "*"
}
for header in headers:
response.headers.set(header, headers[header])
response.content = "PASS: Cross-domain access allowed."

View file

@ -0,0 +1,16 @@
import datetime
def main(request, response):
cookie_name = request.GET.first("cookie_name", "")
response.headers.set("Cache-Control", "no-store")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.headers.set("Access-Control-Allow-Credentials", "true")
for cookie in request.cookies:
# Set cookie to expire yesterday
response.set_cookie(cookie, "deleted", expires=-datetime.timedelta(days=1))
if cookie_name:
# Set cookie to expire tomorrow
response.set_cookie(cookie_name, "COOKIE", expires=datetime.timedelta(days=1))

View file

@ -0,0 +1,9 @@
#!/usr/bin/env python
def main(request, response):
response.headers.set("Content-Type", "text/plain");
response.headers.set("Cache-Control", "no-cache, no-store");
response.headers.set("Access-Control-Allow-External", "true");
response.headers.set("Access-Control-Allow-Origin", "*");
response.content = "PASS: Cross-domain access allowed.\n"
response.content += "HTTP_ORIGIN: " + request.headers.get("origin");

View file

@ -0,0 +1,50 @@
def main(request, response):
def fail(message):
response.content = "FAIL: " + str(message)
response.status = 400
def getState(token):
server_state = request.server.stash.take(token)
if not server_state:
return "Uninitialized"
return server_state
def setState(token, state):
request.server.stash.put(token, state)
def resetState(token):
setState(token, "")
response.headers.set("Cache-Control", "no-store")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.headers.set("Access-Control-Max-Age", 1)
token = request.GET.first("token", None)
state = getState(token)
command = request.GET.first("command", None)
if command == "reset":
if request.method == "GET":
resetState(token)
response.content = "Server state reset"
else:
fail("Invalid Method.")
elif state == "Uninitialized":
if request.method == "OPTIONS":
response.content = "This request should not be displayed."
setState(token, "Denied")
else:
fail(state)
elif state == "Denied":
if request.method == "GET" and command == "complete":
resetState(token)
response.content = "Request successfully blocked."
else:
setState("Deny Ignored")
fail("The request was not denied.")
elif state == "Deny Ignored":
resetState(token)
fail(state)
else:
resetState(token)
fail("Unknown Error.")

View file

@ -0,0 +1,16 @@
def main(request, response):
response.headers.set("Cache-Control", "no-store")
response.headers.set("Access-Control-Allow-Origin", "*")
response.headers.set("Access-Control-Max-Age", 0)
if request.method == "OPTIONS":
if "x-test" in [header.strip(" ") for header in
request.headers.get("Access-Control-Request-Headers").split(",")]:
response.headers.set("Access-Control-Allow-Headers", "X-Test")
else:
response.status = 400
elif request.method == "GET":
if request.headers.get("X-Test"):
response.content = "PASS"
else:
response.status = 400

View file

@ -0,0 +1,18 @@
def main(request, response):
response.headers.set('Cache-Control', 'no-store')
response.headers.set('Access-Control-Allow-Origin',
request.headers.get('origin'))
headers = 'x-custom-s,x-custom-test,x-custom-u,x-custom-ua,x-custom-v'
if request.method == 'OPTIONS':
response.headers.set('Access-Control-Max-Age', '0')
response.headers.set('Access-Control-Allow-Headers', headers)
# Access-Control-Request-Headers should be sorted.
if headers != request.headers.get('Access-Control-Request-Headers'):
response.status = 400
else:
if request.headers.get('x-custom-s'):
response.content = 'PASS'
else:
response.status = 400
response.content = 'FAIL'

View file

@ -0,0 +1,12 @@
def main(request, response):
response.headers.set("Cache-Control", "no-store")
response.headers.set("Access-Control-Allow-Origin", "*")
if request.method == "OPTIONS":
if "origin" in request.headers.get("Access-Control-Request-Headers").lower():
response.status = 400
response.content = "Error: 'origin' included in Access-Control-Request-Headers"
else:
response.headers.set("Access-Control-Allow-Headers", "x-pass")
else:
response.content = request.headers.get("x-pass")

View file

@ -0,0 +1,16 @@
def main(request, response):
try:
code = int(request.GET.first("code", None))
except:
code = None
if request.method == "OPTIONS":
if code:
response.status = code
response.headers.set("Access-Control-Max-Age", 1)
response.headers.set("Access-Control-Allow-Headers", "x-pass")
else:
response.status = 200
response.headers.set("Cache-Control", "no-store")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))

View file

@ -0,0 +1,12 @@
def main(request, response):
if request.method == "OPTIONS" and request.cookies.get("foo"):
response.status = 400
else:
response.headers.set("Cache-Control", "no-store")
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
response.headers.set("Access-Control-Allow-Credentials", "true")
response.headers.set("Access-Control-Allow-Headers", "X-Proprietary-Header")
response.headers.set("Connection", "close")
if request.cookies.get("foo"):
response.content = request.cookies["foo"].value

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
window.addEventListener("message", (evt) => {
const url = evt.data;
const xhr = new XMLHttpRequest;
xhr.open("GET", url, false);
try {
xhr.send();
} catch(e) {
parent.postMessage("Exception thrown. Sandboxed iframe XHR access was denied in 'send'.", "*");
return;
}
parent.postMessage(xhr.responseText, "*");
}, false);
parent.postMessage("ready", "*");
</script>
</body>
</html>

View file

@ -5,10 +5,12 @@ def get_response(raw_headers, filter_value, filter_name):
return "Syntax error: missing CRLF: " + line
line = line[:-2]
if ': ' not in line:
return "Syntax error: no colon and space: " + line
if ':' not in line:
return "Syntax error: no colon found: " + line
name, value = line.split(':', 1)
if len(value) > 1 and value[0] == ' ':
value = value[1:]
name, value = line.split(': ', 1)
if filter_value:
if value == filter_value:
result += name + ","

View file

@ -0,0 +1,27 @@
def main(request, response):
def getState(token):
server_state = request.server.stash.take(token)
if not server_state:
return "Uninitialized"
return server_state
def setState(state, token):
request.server.stash.put(token, state)
response.headers.set("Access-Control-Allow-Origin", "*")
response.headers.set("Access-Control-Allow-Headers", "x-test")
response.headers.set("Access-Control-Max-Age", 0)
token = request.GET.first("token", None)
if request.method == "OPTIONS":
if request.headers.get("x-test"):
response.content = "FAIL: Invalid header in preflight request."
response.status = 400
else:
setState("PASS", token)
else:
if request.headers.get("x-test"):
response.content = getState(token)
else:
response.content = "FAIL: X-Test header missing in request"
response.status = 400

View file

@ -0,0 +1 @@
PASS

View file

@ -0,0 +1,20 @@
def main(request, response):
location = request.GET.first("location")
if request.method == "OPTIONS":
if "redirect_preflight" in request.GET:
response.status = 302
response.headers.set("Location", location)
else:
response.status = 200
response.headers.set("Access-Control-Allow-Methods", "GET")
response.headers.set("Access-Control-Max-Age", 1)
elif request.method == "GET":
response.status = 302
response.headers.set("Location", location)
if "allow_origin" in request.GET:
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
if "allow_header" in request.GET:
response.headers.set("Access-Control-Allow-Headers", request.GET.first("allow_header"))

View file

@ -0,0 +1,5 @@
def main(request, response):
response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
token = request.GET["token"]
request.server.stash.put(token, "")
response.content = "PASS"

View file

@ -0,0 +1,9 @@
self.importScripts('/resources/testharness.js');
test(function() {
let xhr = new XMLHttpRequest();
xhr.responseType = "document";
assert_not_equals(xhr.responseType, "document");
}, "Setting XMLHttpRequest responseType to 'document' in a worker should have no effect.");
done();

View file

@ -0,0 +1,9 @@
self.importScripts('/resources/testharness.js');
test(function() {
let xhr = new XMLHttpRequest();
assert_not_exists(xhr, "responseXML", "responseXML should not be available on instances.");
assert_not_exists(XMLHttpRequest.prototype, "responseXML", "responseXML should not be on the prototype.");
}, "XMLHttpRequest's responseXML property should not be exposed in workers.");
done();

View file

@ -0,0 +1,5 @@
def main(request, response):
headers = [("Content-type", "text/html;charset=windows-1252")]
content = chr(0xff)
return headers, content

View file

@ -0,0 +1,13 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
fetch_tests_from_worker(new Worker("resources/responseType-document-in-worker.js"));
</script>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
fetch_tests_from_worker(new Worker("resources/responseXML-unavailable-in-worker.js"));
</script>
</body>
</html>

View file

@ -0,0 +1,39 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>XMLHttpRequest: response document decoding</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
function request(type, input, expected) {
async_test((test) => {
const client = new XMLHttpRequest();
client.responseType = 'document';
client.open("GET", "resources/status.py?content=" + input + "&type=" + encodeURIComponent(type), true);
client.onload = test.step_func_done(() => {
assert_equals(client.responseXML.querySelector("x").textContent, expected);
})
client.send(null);
}, document.title + " (" + type + " " + input + ")");
}
const encoded_content = "%e6%a9%9f";
const encoded_xml =
encodeURIComponent("<?xml version='1.0' encoding='windows-1252'?><x>") + encoded_content + encodeURIComponent("<\/x>");
const encoded_html =
encodeURIComponent("<!doctype html><meta charset=windows-1252><x>") + encoded_content + encodeURIComponent("<\/x>");
const decoded_as_windows_1252 = "\u00e6\u00a9\u0178";
const decoded_as_utf_8 = "\u6a5f";
request("application/xml", encoded_xml, decoded_as_windows_1252);
request("application/xml;charset=utf-8", encoded_xml, decoded_as_utf_8);
request("application/xml;charset=windows-1252", encoded_xml, decoded_as_windows_1252);
request("text/html", encoded_html, decoded_as_windows_1252);
request("text/html;charset=utf-8", encoded_html, decoded_as_utf_8);
request("text/html;charset=windows-1252", encoded_html, decoded_as_windows_1252);
</script>
</body>
</html>

View file

@ -1,47 +1,92 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>XMLHttpRequest: responseText decoding</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol[1]/li[4]" />
<link rel="help" href="https://xhr.spec.whatwg.org/#text-response-entity-body" data-tested-assertations="following::ol[1]/li[2] following::ol[1]/li[3] following::ol[1]/li[4] following::ol[1]/li[5]" />
</head>
<body>
<div id="log"></div>
<script>
function request(type, input, output, responseType) {
var test = async_test(document.title + " (" + type + " " + input + ")");
test.step(function() {
var client = new XMLHttpRequest()
if (responseType !== undefined) {
client.responseType = responseType
}
client.open("GET", "resources/status.py?content=" + input + "&type=" + encodeURIComponent(type), true)
client.onload = test.step_func_done(() => {
assert_equals(client.responseText, output)
})
client.send(null)
})
function create_html(content) {
return "<!doctype html><meta charset=windows-1252><x>" + content + "</x>";
}
request("application/xml", encodeURIComponent("<?xml version='1.0' encoding='windows-1252'?><x>")+'%FF'+encodeURIComponent("<\/x>"), "<?xml version='1.0' encoding='windows-1252'?><x>\u00FF<\/x>")
request("text/html", encodeURIComponent("<!doctype html><meta charset=windows-1252>")+"%FF", "<!doctype html><meta charset=windows-1252>\uFFFD")
request("text/plain;charset=windows-1252", "%FF", "\u00FF")
request("text/plain", "%FF", "\uFFFD")
request("text/plain", "%FE%FF", "")
request("text/plain", "%FE%FF%FE%FF", "\uFEFF")
request("text/plain", "%EF%BB%BF", "")
request("text/plain", "%EF%BB%BF%EF%BB%BF", "\uFEFF")
request("text/plain", "%C2", "\uFFFD")
request("text/xml", "%FE%FF", "")
request("text/xml", "%FE%FF%FE%FF", "\uFEFF")
request("text/xml", "%EF%BB%BF", "")
request("text/xml", "%EF%BB%BF%EF%BB%BF", "\uFEFF")
request("text/plain", "%E3%81%B2", "\u3072", 'text')
// the point of the following test: setting responseType=text should (per spec #text-response-entity-body point 3)
// skip some of the charset detection even for XML resources. The test uses a wilfully mislabelled XMLish response
// and the pass condition is that the responseType = text makes the decoder fall back to UTF-8
request("text/xml", encodeURIComponent("<?xml version='1.0' encoding='windows-1252'?><x>")+"%E3%81%B2"+encodeURIComponent("<\/x>"), "<?xml version='1.0' encoding='windows-1252'?><x>\u3072<\/x>", 'text')
function create_encoded_html(encoded_content) {
return encodeURIComponent("<!doctype html><meta charset=windows-1252><x>") + encoded_content + encodeURIComponent("<\/x>");
}
function create_xml(content) {
return "<?xml version='1.0' encoding='windows-1252'?><x>" + content + "</x>";
}
function create_encoded_xml(encoded_content) {
return encodeURIComponent("<?xml version='1.0' encoding='windows-1252'?><x>") + encoded_content + encodeURIComponent("<\/x>");
}
function request(type, input, output, responseType) {
async_test((test) => {
const client = new XMLHttpRequest();
if (responseType !== undefined) {
client.responseType = responseType;
}
client.open("GET", "resources/status.py?content=" + input + "&type=" + encodeURIComponent(type), true);
client.onload = test.step_func_done(() => {
assert_equals(client.responseText, output);
})
client.send(null);
}, document.title + " (" + type + " " + input + " " + (responseType ? " " + responseType : "empty") + ")");
}
const encoded_content = "%e6%a9%9f";
const decoded_as_windows_1252 = "\u00e6\u00a9\u0178";
const decoded_as_utf_8 = "\u6a5f";
const encoded_xml = create_encoded_xml(encoded_content);
const encoded_html = create_encoded_html(encoded_content);
const xml_decoded_as_windows_1252 = create_xml(decoded_as_windows_1252);
const xml_decoded_as_utf_8 = create_xml(decoded_as_utf_8);
const html_decoded_as_windows_1252 = create_html(decoded_as_windows_1252);
const html_decoded_as_utf_8 = create_html(decoded_as_utf_8);
// "default" response type
// An XML-ish response is sniffed.
request("application/xml", encoded_xml, xml_decoded_as_windows_1252);
// An HTML-ish response isn't sniffed.
request("text/html", encoded_html, html_decoded_as_utf_8);
request("application/xml;charset=utf-8", encoded_xml, xml_decoded_as_utf_8);
request("application/xml;charset=windows-1252", encoded_xml, xml_decoded_as_windows_1252);
request("text/html;charset=utf-8", encoded_html, html_decoded_as_utf_8);
request("text/html;charset=windows-1252", encoded_html, html_decoded_as_windows_1252);
request("text/plain;charset=windows-1252", "%FF", "\u00FF");
request("text/plain", "%FF", "\uFFFD");
request("text/plain", "%FE%FF", "");
request("text/plain", "%FE%FF%FE%FF", "\uFEFF");
request("text/plain", "%EF%BB%BF", "");
request("text/plain", "%EF%BB%BF%EF%BB%BF", "\uFEFF");
request("text/plain", "%C2", "\uFFFD");
request("text/xml", "%FE%FF", "");
request("text/xml", "%FE%FF%FE%FF", "\uFEFF");
request("text/xml", "%EF%BB%BF", "");
request("text/xml", "%EF%BB%BF%EF%BB%BF", "\uFEFF");
request("text/plain", "%E3%81%B2", "\u3072");
// "text" response type
// An XML-ish response isn't sniffed.
request("application/xml", encoded_xml, xml_decoded_as_utf_8, "text");
// An HTML-ish response isn't sniffed.
request("text/html", encoded_html, html_decoded_as_utf_8, "text");
request("application/xml;charset=utf-8", encoded_xml, xml_decoded_as_utf_8, "text");
request("application/xml;charset=windows-1252", encoded_xml, xml_decoded_as_windows_1252, "text");
request("text/html;charset=utf-8", encoded_html, html_decoded_as_utf_8, "text");
request("text/html;charset=windows-1252", encoded_html, html_decoded_as_windows_1252, "text");
request("text/plain;charset=windows-1252", "%FF", "\u00FF", "text");
request("text/plain", "%FF", "\uFFFD", "text");
request("text/plain", "%FE%FF", "", "text");
request("text/plain", "%FE%FF%FE%FF", "\uFEFF", "text");
request("text/plain", "%EF%BB%BF", "", "text");
request("text/plain", "%EF%BB%BF%EF%BB%BF", "\uFEFF", "text");
request("text/plain", "%C2", "\uFFFD", "text");
request("text/xml", "%FE%FF", "", "text");
request("text/xml", "%FE%FF%FE%FF", "\uFEFF", "text");
request("text/xml", "%EF%BB%BF", "", "text");
request("text/xml", "%EF%BB%BF%EF%BB%BF", "\uFEFF", "text");
request("text/plain", "%E3%81%B2", "\u3072", "text");
</script>
</body>
</html>

View file

@ -20,7 +20,7 @@
request("TEST", "text/plain;charset=UTF-8")
function init(fr) { request(fr.contentDocument, fr.getAttribute("data-t")) }
</script>
<iframe src='data:text/xml;charset=windows-1252,<%FF/>' onload="init(this)" data-t="application/xml;charset=UTF-8"></iframe>
<iframe src='data:text/html;charset=windows-1252,%FF' onload="init(this)" data-t="text/html;charset=UTF-8"></iframe>
<iframe src="resources/win-1252-xml.py" onload="init(this)" data-t="application/xml;charset=UTF-8"></iframe>
<iframe src="resources/win-1252-html.py" onload="init(this)" data-t="text/html;charset=UTF-8"></iframe>
</body>
</html>

View file

@ -21,13 +21,13 @@
}
client.send(toSend)
const responseType = client.responseText
const actual = client.responseText
if (expectedType === undefined || expectedType === null) {
assert_equals(responseType, "");
assert_equals(actual, "");
} else if (expectedType instanceof RegExp) {
assert_regexp_match(responseType, expectedType);
assert_regexp_match(actual, expectedType);
} else {
assert_equals(responseType, "Content-Type: " + expectedType + "\n");
assert_equals(actual, "Content-Type: " + expectedType + "\n");
}
}, title)
}
@ -121,6 +121,12 @@
"application/xml;charset=ASCII",
"Blob request with unset type keeps setRequestHeader() Content-Type and charset"
)
request(
function _Blob() { return new Blob(["<xml/>"], {type : "application/xml;charset=ASCII"}); },
{"Content-Type": ""},
"",
'Blob request with set type respects setRequestHeader("") to be specified'
)
request(
function _Blob() { return new Blob(["<xml/>"], {type : "application/xml;charset=ASCII"}); },
{},