| <!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> |