dangling-markup-mitigation-allowed-apis.https.html (3455B)
1 <!DOCTYPE html> 2 <meta name="timeout" content="long"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <body> 6 <script> 7 const blank = 'about:blank'; 8 const dangling_url = 'resources/empty.html?\n<'; 9 const navigation_api_calls = [ 10 `window.open(\`${dangling_url}\`,'_self')`, 11 `location.replace(\`${dangling_url}\`)`, 12 ]; 13 14 function get_requests(test, worker, expected) { 15 return new Promise((resolve, reject) => { 16 let didTimeout = false; 17 test.step_timeout(() => { 18 didTimeout = true; 19 reject("get_requests timed out"); 20 }, 1000); 21 navigator.serviceWorker.addEventListener('message', function onMsg(evt) { 22 if (evt.data.size >= expected) { 23 navigator.serviceWorker.removeEventListener('message', onMsg); 24 resolve(evt.data); 25 } else if (!didTimeout) { 26 worker.postMessage(""); 27 } 28 }); 29 worker.postMessage(""); 30 }); 31 } 32 33 navigation_api_calls.forEach(call => { 34 async_test(t => { 35 const iframe = 36 document.body.appendChild(document.createElement('iframe')); 37 t.step(() => { 38 iframe.contentWindow.eval(call); 39 t.step_timeout(() => { 40 assert_false(iframe.contentWindow.location.href.endsWith(blank)); 41 t.done(); 42 }, 500); 43 }); 44 }, `Does not block ${call}`); 45 }); 46 47 const dangling_resource = "404?type=text/javascript&\n<" 48 const dangling_resource_expected = "404?type=text/javascript&%3C" 49 const api_calls = [ 50 [`const xhr = new XMLHttpRequest(); 51 xhr.open("GET", \`${"xhr" + dangling_resource}\`); 52 xhr.send(null);`, "xhr"], 53 [`new EventSource(\`${"EventSource" + dangling_resource}\`)`,"EventSource"], 54 [`fetch(\`${"fetch" + dangling_resource}\`).catch(()=>{})`, "fetch"], 55 [`new Worker(\`${"Worker" + dangling_resource}\`)`, "Worker"], 56 [`let text = \`try{importScripts(\\\`${location.href + "/../importScripts" + dangling_resource}\\\`)}catch(e){}\`; 57 let blob = new Blob([text], {type : 'text/javascript'}); 58 let url = URL.createObjectURL(blob); 59 new Worker(url)`, "importScripts"], 60 61 ]; 62 63 let iframe, registration; 64 promise_test(async t => { 65 iframe = document.createElement('iframe'); 66 iframe.src = "resources/empty.html"; 67 document.body.appendChild(iframe); 68 await new Promise(resolve => iframe.onload = resolve); 69 registration = await navigator.serviceWorker.register('service-worker.js'); 70 if (!iframe.contentWindow.navigator.serviceWorker.controller) 71 await new Promise(resolve => iframe.contentWindow.navigator.serviceWorker.oncontrollerchange = resolve); 72 }, "Setup controlled frame"); 73 74 let number_api_calls = 0; 75 api_calls.forEach(call => { 76 promise_test(async t => { 77 iframe.contentWindow.eval(call[0]); 78 const requests = await get_requests(t, registration.active, number_api_calls + 1); 79 assert_equals(Array.from(requests)[number_api_calls], call[1] + dangling_resource_expected); 80 number_api_calls++; 81 }, `Does not block ${call[1]}`); 82 }); 83 promise_test(async () => { 84 iframe.remove(); 85 registration.unregister(); 86 }, "Clean up iframe"); 87 88 async_test(t => { 89 let url = new URL(location.origin + "/" + dangling_url); 90 // Newlines are removed by the URL parser. 91 assert_true(url.href.endsWith(encodeURI(dangling_url.replace("\n","")))); 92 t.done(); 93 }, `Does not block new URL()`); 94 </script>