Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
const blank = 'about:blank';
const dangling_url = 'resources/empty.html?\n<';
const navigation_api_calls = [
`window.open(\`${dangling_url}\`,'_self')`,
`location.replace(\`${dangling_url}\`)`,
];
function get_requests(test, worker, expected) {
return new Promise((resolve, reject) => {
let didTimeout = false;
test.step_timeout(() => {
didTimeout = true;
reject("get_requests timed out");
}, 1000);
navigator.serviceWorker.addEventListener('message', function onMsg(evt) {
if (evt.data.size >= expected) {
navigator.serviceWorker.removeEventListener('message', onMsg);
resolve(evt.data);
} else if (!didTimeout) {
worker.postMessage("");
}
});
worker.postMessage("");
});
}
navigation_api_calls.forEach(call => {
async_test(t => {
const iframe =
document.body.appendChild(document.createElement('iframe'));
t.step(() => {
iframe.contentWindow.eval(call);
t.step_timeout(() => {
assert_false(iframe.contentWindow.location.href.endsWith(blank));
t.done();
}, 500);
});
}, `Does not block ${call}`);
});
const dangling_resource = "404?type=text/javascript&\n<"
const dangling_resource_expected = "404?type=text/javascript&%3C"
const api_calls = [
[`const xhr = new XMLHttpRequest();
xhr.open("GET", \`${"xhr" + dangling_resource}\`);
xhr.send(null);`, "xhr"],
[`new EventSource(\`${"EventSource" + dangling_resource}\`)`,"EventSource"],
[`fetch(\`${"fetch" + dangling_resource}\`).catch(()=>{})`, "fetch"],
[`new Worker(\`${"Worker" + dangling_resource}\`)`, "Worker"],
[`let text = \`try{importScripts(\\\`${location.href + "/../importScripts" + dangling_resource}\\\`)}catch(e){}\`;
let blob = new Blob([text], {type : 'text/javascript'});
let url = URL.createObjectURL(blob);
new Worker(url)`, "importScripts"],
];
let iframe, registration;
promise_test(async t => {
iframe = document.createElement('iframe');
iframe.src = "resources/empty.html";
document.body.appendChild(iframe);
await new Promise(resolve => iframe.onload = resolve);
registration = await navigator.serviceWorker.register('service-worker.js');
if (!iframe.contentWindow.navigator.serviceWorker.controller)
await new Promise(resolve => iframe.contentWindow.navigator.serviceWorker.oncontrollerchange = resolve);
}, "Setup controlled frame");
let number_api_calls = 0;
api_calls.forEach(call => {
promise_test(async t => {
iframe.contentWindow.eval(call[0]);
const requests = await get_requests(t, registration.active, number_api_calls + 1);
assert_equals(Array.from(requests)[number_api_calls], call[1] + dangling_resource_expected);
number_api_calls++;
}, `Does not block ${call[1]}`);
});
promise_test(async () => {
iframe.remove();
registration.unregister();
}, "Clean up iframe");
async_test(t => {
let url = new URL(location.origin + "/" + dangling_url);
// Newlines are removed by the URL parser.
assert_true(url.href.endsWith(encodeURI(dangling_url.replace("\n",""))));
t.done();
}, `Does not block new URL()`);
</script>