browser_etp_permission.js (5386B)
1 "use strict"; 2 3 const { PermissionTestUtils } = ChromeUtils.importESModule( 4 "resource://testing-common/PermissionTestUtils.sys.mjs" 5 ); 6 7 const BASE_URI = "http://mochi.test:8888/browser/dom/serviceworkers/test/"; 8 const PAGE_URI = BASE_URI + "empty.html"; 9 const SCOPE = PAGE_URI + "?etp_permission"; 10 const SW_SCRIPT = BASE_URI + "service_worker_etp.js"; 11 12 // Test that a service worker respects ETP permissions 13 // during ServiceWorkerPrivate::Initialize. 14 add_task(async function test_permission_during_init() { 15 await SpecialPowers.pushPrefEnv({ 16 set: [ 17 ["privacy.fingerprintingProtection", true], 18 [ 19 "privacy.fingerprintingProtection.overrides", 20 "+CanvasImageExtractionPrompt", 21 ], 22 ], 23 }); 24 25 let tab = BrowserTestUtils.addTab(gBrowser, SCOPE); 26 await BrowserTestUtils.browserLoaded(tab.linkedBrowser); 27 28 const checkAllowList = async expected => { 29 await SpecialPowers.spawn( 30 tab.linkedBrowser, 31 [{ script: SW_SCRIPT, scope: SCOPE, expected }], 32 async function (opts) { 33 const reg = await content.navigator.serviceWorker.register( 34 opts.script, 35 { 36 scope: opts.scope, 37 } 38 ); 39 const worker = reg.installing || reg.waiting || reg.active; 40 await new Promise(resolve => { 41 if (worker.state === "activated") { 42 resolve(); 43 return; 44 } 45 worker.addEventListener("statechange", function onStateChange() { 46 if (worker.state === "activated") { 47 worker.removeEventListener("statechange", onStateChange); 48 resolve(); 49 } 50 }); 51 }); 52 53 worker.postMessage("IsETPAllowListed"); 54 const response = await new Promise(resolve => { 55 content.navigator.serviceWorker.onmessage = function (e) { 56 resolve(e.data); 57 }; 58 }); 59 60 is( 61 response, 62 opts.expected, 63 `Service worker should ${!opts.expected ? "not" : ""} be allow-listed` 64 ); 65 66 await reg.unregister(); 67 } 68 ); 69 }; 70 71 await checkAllowList(false); 72 73 PermissionTestUtils.add( 74 SCOPE, 75 "trackingprotection", 76 Services.perms.ALLOW_ACTION 77 ); 78 79 await checkAllowList(true); 80 81 PermissionTestUtils.remove(SCOPE, "trackingprotection"); 82 83 BrowserTestUtils.removeTab(tab); 84 await SpecialPowers.popPrefEnv(); 85 }); 86 87 // Test that a service worker respects ETP permissions 88 // during service worker runtime. 89 add_task(async function test_permission_during_runtime() { 90 await SpecialPowers.pushPrefEnv({ 91 set: [ 92 ["privacy.fingerprintingProtection", true], 93 [ 94 "privacy.fingerprintingProtection.overrides", 95 "+CanvasImageExtractionPrompt", 96 ], 97 ], 98 }); 99 100 let tab = BrowserTestUtils.addTab(gBrowser, SCOPE); 101 await BrowserTestUtils.browserLoaded(tab.linkedBrowser); 102 103 // Define functions with nice names for easier understanding 104 const registerServiceWorker = async () => { 105 await SpecialPowers.spawn( 106 tab.linkedBrowser, 107 [{ script: SW_SCRIPT, scope: SCOPE }], 108 async function (opts) { 109 const reg = await content.navigator.serviceWorker.register( 110 opts.script, 111 { 112 scope: opts.scope, 113 } 114 ); 115 const worker = reg.installing || reg.waiting || reg.active; 116 await new Promise(resolve => { 117 if (worker.state === "activated") { 118 resolve(); 119 return; 120 } 121 worker.addEventListener("statechange", function onStateChange() { 122 if (worker.state === "activated") { 123 worker.removeEventListener("statechange", onStateChange); 124 resolve(); 125 } 126 }); 127 }); 128 } 129 ); 130 }; 131 132 const checkAllowList = async expected => { 133 await SpecialPowers.spawn( 134 tab.linkedBrowser, 135 [{ expected }], 136 async function (opts) { 137 content.navigator.serviceWorker.ready.then(registration => { 138 registration.active.postMessage("IsETPAllowListed"); 139 }); 140 141 const response = await new Promise(resolve => { 142 content.navigator.serviceWorker.onmessage = function (e) { 143 resolve(e.data); 144 }; 145 }); 146 147 is( 148 response, 149 opts.expected, 150 `Service worker should ${!opts.expected ? "not" : ""} be allow-listed` 151 ); 152 } 153 ); 154 }; 155 156 const unregisterServiceWorker = async () => { 157 await SpecialPowers.spawn( 158 tab.linkedBrowser, 159 [{ scope: SCOPE }], 160 async function (opts) { 161 const registrations = 162 await content.navigator.serviceWorker.getRegistrations(); 163 for (const registration of registrations) { 164 if (registration.scope === opts.scope) { 165 await registration.unregister(); 166 } 167 } 168 } 169 ); 170 }; 171 172 // Run the actual test 173 await registerServiceWorker(); 174 175 await checkAllowList(false); 176 177 PermissionTestUtils.add( 178 SCOPE, 179 "trackingprotection", 180 Services.perms.ALLOW_ACTION 181 ); 182 183 await checkAllowList(true); 184 185 PermissionTestUtils.add( 186 SCOPE, 187 "trackingprotection", 188 Services.perms.DENY_ACTION 189 ); 190 191 await checkAllowList(false); 192 193 await unregisterServiceWorker(); 194 195 PermissionTestUtils.remove(SCOPE, "trackingprotection"); 196 197 BrowserTestUtils.removeTab(tab); 198 await SpecialPowers.popPrefEnv(); 199 });