test_block_script_wrong_mime.html (5466B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Bug 1288361 - Block scripts with incorrect MIME type</title> 5 <!-- Including SimpleTest.js so we can use waitForExplicitFinish !--> 6 <script src="/tests/SimpleTest/SimpleTest.js"></script> 7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 8 </head> 9 <body> 10 11 <script class="testbody" type="text/javascript"> 12 13 const MIMETypes = [ 14 ["application/javascript", true], 15 ["text/javascript", true], 16 17 ["audio/mpeg", false], 18 ["audio/", false], 19 ["image/jpeg", false], 20 ["image/", false], 21 ["video/mpeg", false], 22 ["video/", false], 23 ["text/csv", false], 24 ]; 25 26 // <script src=""> 27 function testScript([mime, shouldLoad]) { 28 return new Promise((resolve) => { 29 let script = document.createElement("script"); 30 script.onload = () => { 31 document.body.removeChild(script); 32 ok(shouldLoad, `script with mime '${mime}' should ${shouldLoad ? "" : "NOT "}load`); 33 resolve(); 34 }; 35 script.onerror = () => { 36 document.body.removeChild(script); 37 ok(!shouldLoad, `script with wrong mime '${mime}' should be blocked`); 38 resolve(); 39 }; 40 script.src = "file_block_script_wrong_mime_server.sjs?type=script&mime="+mime; 41 document.body.appendChild(script); 42 }); 43 } 44 45 // new Worker() 46 function testWorker([mime, shouldLoad]) { 47 return new Promise((resolve) => { 48 let worker = new Worker("file_block_script_wrong_mime_server.sjs?type=worker&mime="+mime); 49 worker.onmessage = (event) => { 50 ok(shouldLoad, `worker with mime '${mime}' should ${shouldLoad ? "" : "NOT "}load`); 51 is(event.data, "worker-loaded", "worker should send correct message"); 52 resolve(); 53 }; 54 worker.onerror = (error) => { 55 ok(!shouldLoad, `worker with wrong mime '${mime}' should be blocked`); 56 error.preventDefault(); 57 resolve(); 58 } 59 worker.postMessage("dummy"); 60 }); 61 } 62 63 // new Worker() with importScripts() 64 function testWorkerImportScripts([mime, shouldLoad]) { 65 return new Promise((resolve) => { 66 let worker = new Worker("file_block_script_wrong_mime_server.sjs?type=worker-import&mime="+mime); 67 worker.onmessage = (event) => { 68 ok(shouldLoad, `worker/importScripts with mime '${mime}' should ${shouldLoad ? "" : "NOT "}load`); 69 is(event.data, "worker-loaded", "worker should send correct message"); 70 resolve(); 71 }; 72 worker.onerror = (error) => { 73 ok(!shouldLoad, `worker/importScripts with wrong mime '${mime}' should be blocked`); 74 error.preventDefault(); 75 resolve(); 76 // The worker doesn't self-terminate via close, so let's do it. 77 worker.terminate(); 78 } 79 worker.postMessage("dummy"); 80 }); 81 } 82 83 async function runMimeTypePermutations() { 84 info("### Running document script MIME checks."); 85 for (const mimeType of MIMETypes) { 86 await testScript(mimeType); 87 } 88 89 info("### Running worker top-level script MIME checks."); 90 for (const mimeType of MIMETypes) { 91 await testWorker(mimeType); 92 } 93 94 info("### Running worker importScripts MIME checks."); 95 for (const mimeType of MIMETypes) { 96 await testWorkerImportScripts(mimeType); 97 } 98 } 99 100 let gRegistration; 101 102 /** 103 * Register and wait for the helper ServiceWorker to be active in the given 104 * mode. 105 */ 106 async function useServiceWorker({ fetchMode }) { 107 info(`### Registering ServiceWorker with mode '${fetchMode}'`); 108 const activePromise = new Promise((resolve, reject) => { 109 navigator.serviceWorker.addEventListener( 110 "message", 111 event => { 112 if (event.data.fetchMode === fetchMode) { 113 resolve(); 114 } else { 115 reject(`wrong fetchMode: ${fetchMode}`); 116 } 117 is(fetchMode, event.data.fetchMode, "right fetch mode"); 118 }, 119 { once: true }); 120 }); 121 122 const reg = gRegistration = await navigator.serviceWorker.register( 123 `file_block_script_wrong_mime_sw.js?fetchMode=${fetchMode}`); 124 info("register resolved. " + 125 `installing: ${!!reg.installing} ` + 126 `waiting: ${!!reg.waiting} ` + 127 `active: ${!!reg.active}`); 128 129 await activePromise; 130 } 131 132 /** 133 * Unregister the ServiceWorker, with the caveat that the ServiceWorker will 134 * still be controlling us until this window goes away. 135 */ 136 async function cleanupServiceWorkerWithCaveat() { 137 await gRegistration.unregister(); 138 } 139 140 /** 141 * Top-level test that runs the MIME type checks in different ServiceWorker/ 142 * network configurations. 143 * 144 * We use the ServiceWorker mechanism that allows ServiceWorkers to claim 145 * existing scope-matching clients in order to make this window controlled and 146 * then run the tests. When changing the SW behavior the SW also needs to 147 * skipWaiting in order to advance to active. 148 */ 149 async function runNetworkPermutations() { 150 await SpecialPowers.pushPrefEnv({ 151 set: [ 152 ["dom.serviceWorkers.enabled", true], 153 ["dom.serviceWorkers.exemptFromPerDomainMax", true], 154 ["dom.serviceWorkers.testing.enabled", true], 155 ], 156 }); 157 158 info("## Run tests without a ServiceWorker involved."); 159 await runMimeTypePermutations(); 160 161 info("## Run tests with a pass-through fetch(event.request) handler."); 162 await useServiceWorker({ fetchMode: "direct" }); 163 await runMimeTypePermutations(); 164 165 info("## Run tests with a naive URL propagating fetch(event.request.url) handler."); 166 await useServiceWorker({ fetchMode: "indirect" }); 167 await runMimeTypePermutations(); 168 169 await cleanupServiceWorkerWithCaveat(); 170 } 171 172 add_task(runNetworkPermutations); 173 </script> 174 </body> 175 </html>