browser_storage_permission.js (9961B)
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 + "?storage_permission"; 10 const SW_SCRIPT = BASE_URI + "empty.js"; 11 12 add_setup(async function () { 13 await SpecialPowers.pushPrefEnv({ 14 set: [ 15 // Until the e10s refactor is complete, use a single process to avoid 16 // service worker propagation race. 17 ["dom.ipc.processCount", 1], 18 ["dom.serviceWorkers.enabled", true], 19 ["dom.serviceWorkers.testing.enabled", true], 20 ], 21 }); 22 23 let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI); 24 let browser = gBrowser.getBrowserForTab(tab); 25 await BrowserTestUtils.browserLoaded(browser); 26 27 await SpecialPowers.spawn( 28 browser, 29 [{ script: SW_SCRIPT, scope: SCOPE }], 30 async function (opts) { 31 let reg = await content.navigator.serviceWorker.register(opts.script, { 32 scope: opts.scope, 33 }); 34 let worker = reg.installing || reg.waiting || reg.active; 35 await new Promise(resolve => { 36 if (worker.state === "activated") { 37 resolve(); 38 return; 39 } 40 worker.addEventListener("statechange", function onStateChange() { 41 if (worker.state === "activated") { 42 worker.removeEventListener("statechange", onStateChange); 43 resolve(); 44 } 45 }); 46 }); 47 } 48 ); 49 50 BrowserTestUtils.removeTab(tab); 51 }); 52 53 add_task(async function test_allow_permission() { 54 PermissionTestUtils.add( 55 PAGE_URI, 56 "cookie", 57 Ci.nsICookiePermission.ACCESS_ALLOW 58 ); 59 60 let tab = BrowserTestUtils.addTab(gBrowser, SCOPE); 61 let browser = gBrowser.getBrowserForTab(tab); 62 await BrowserTestUtils.browserLoaded(browser); 63 64 let controller = await SpecialPowers.spawn(browser, [], async function () { 65 return content.navigator.serviceWorker.controller; 66 }); 67 68 ok(!!controller, "page should be controlled with storage allowed"); 69 70 BrowserTestUtils.removeTab(tab); 71 }); 72 73 add_task(async function test_deny_permission() { 74 PermissionTestUtils.add( 75 PAGE_URI, 76 "cookie", 77 Ci.nsICookiePermission.ACCESS_DENY 78 ); 79 80 let tab = BrowserTestUtils.addTab(gBrowser, SCOPE); 81 let browser = gBrowser.getBrowserForTab(tab); 82 await BrowserTestUtils.browserLoaded(browser); 83 84 let controller = await SpecialPowers.spawn(browser, [], async function () { 85 return content.navigator.serviceWorker.controller; 86 }); 87 88 is(controller, null, "page should be not controlled with storage denied"); 89 90 BrowserTestUtils.removeTab(tab); 91 PermissionTestUtils.remove(PAGE_URI, "cookie"); 92 }); 93 94 add_task(async function test_session_permission() { 95 PermissionTestUtils.add( 96 PAGE_URI, 97 "cookie", 98 Ci.nsICookiePermission.ACCESS_SESSION 99 ); 100 101 let tab = BrowserTestUtils.addTab(gBrowser, SCOPE); 102 let browser = gBrowser.getBrowserForTab(tab); 103 await BrowserTestUtils.browserLoaded(browser); 104 105 let controller = await SpecialPowers.spawn(browser, [], async function () { 106 return content.navigator.serviceWorker.controller; 107 }); 108 109 is(controller, null, "page should be not controlled with session storage"); 110 111 BrowserTestUtils.removeTab(tab); 112 PermissionTestUtils.remove(PAGE_URI, "cookie"); 113 }); 114 115 // Test to verify an about:blank iframe successfully inherits the 116 // parent's controller when storage is blocked between opening the 117 // parent page and creating the iframe. 118 add_task(async function test_block_storage_before_blank_iframe() { 119 PermissionTestUtils.remove(PAGE_URI, "cookie"); 120 121 let tab = BrowserTestUtils.addTab(gBrowser, SCOPE); 122 let browser = gBrowser.getBrowserForTab(tab); 123 await BrowserTestUtils.browserLoaded(browser); 124 125 let controller = await SpecialPowers.spawn(browser, [], async function () { 126 return content.navigator.serviceWorker.controller; 127 }); 128 129 ok(!!controller, "page should be controlled with storage allowed"); 130 131 let controller2 = await SpecialPowers.spawn(browser, [], async function () { 132 let f = content.document.createElement("iframe"); 133 content.document.body.appendChild(f); 134 await new Promise(resolve => (f.onload = resolve)); 135 return !!f.contentWindow.navigator.serviceWorker.controller; 136 }); 137 138 ok(!!controller2, "page should be controlled with storage allowed"); 139 140 await SpecialPowers.pushPrefEnv({ 141 set: [ 142 ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT], 143 ], 144 }); 145 146 let controller3 = await SpecialPowers.spawn(browser, [], async function () { 147 let f = content.document.createElement("iframe"); 148 content.document.body.appendChild(f); 149 await new Promise(resolve => (f.onload = resolve)); 150 return !!f.contentWindow.navigator.serviceWorker.controller; 151 }); 152 153 ok(!!controller3, "page should be controlled with storage allowed"); 154 155 await SpecialPowers.popPrefEnv(); 156 BrowserTestUtils.removeTab(tab); 157 }); 158 159 // Test to verify a blob URL iframe successfully inherits the 160 // parent's controller when storage is blocked between opening the 161 // parent page and creating the iframe. 162 add_task(async function test_block_storage_before_blob_iframe() { 163 PermissionTestUtils.remove(PAGE_URI, "cookie"); 164 165 let tab = BrowserTestUtils.addTab(gBrowser, SCOPE); 166 let browser = gBrowser.getBrowserForTab(tab); 167 await BrowserTestUtils.browserLoaded(browser); 168 169 let controller = await SpecialPowers.spawn(browser, [], async function () { 170 return content.navigator.serviceWorker.controller; 171 }); 172 173 ok(!!controller, "page should be controlled with storage allowed"); 174 175 let controller2 = await SpecialPowers.spawn(browser, [], async function () { 176 let b = new content.Blob(["<!DOCTYPE html><html></html>"], { 177 type: "text/html", 178 }); 179 let f = content.document.createElement("iframe"); 180 // No need to call revokeObjectURL() since the window will be closed shortly. 181 f.src = content.URL.createObjectURL(b); 182 content.document.body.appendChild(f); 183 await new Promise(resolve => (f.onload = resolve)); 184 return !!f.contentWindow.navigator.serviceWorker.controller; 185 }); 186 187 ok(!!controller2, "page should be controlled with storage allowed"); 188 189 await SpecialPowers.pushPrefEnv({ 190 set: [ 191 ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT], 192 ], 193 }); 194 195 let controller3 = await SpecialPowers.spawn(browser, [], async function () { 196 let b = new content.Blob(["<!DOCTYPE html><html></html>"], { 197 type: "text/html", 198 }); 199 let f = content.document.createElement("iframe"); 200 // No need to call revokeObjectURL() since the window will be closed shortly. 201 f.src = content.URL.createObjectURL(b); 202 content.document.body.appendChild(f); 203 await new Promise(resolve => (f.onload = resolve)); 204 return !!f.contentWindow.navigator.serviceWorker.controller; 205 }); 206 207 ok(!!controller3, "page should be controlled with storage allowed"); 208 209 await SpecialPowers.popPrefEnv(); 210 BrowserTestUtils.removeTab(tab); 211 }); 212 213 // Test to verify a blob worker script does not hit our service 214 // worker storage assertions when storage is blocked between opening 215 // the parent page and creating the worker. Note, we cannot 216 // explicitly check if the worker is controlled since we don't expose 217 // WorkerNavigator.serviceWorkers.controller yet. 218 add_task(async function test_block_storage_before_blob_worker() { 219 PermissionTestUtils.remove(PAGE_URI, "cookie"); 220 221 let tab = BrowserTestUtils.addTab(gBrowser, SCOPE); 222 let browser = gBrowser.getBrowserForTab(tab); 223 await BrowserTestUtils.browserLoaded(browser); 224 225 let controller = await SpecialPowers.spawn(browser, [], async function () { 226 return content.navigator.serviceWorker.controller; 227 }); 228 229 ok(!!controller, "page should be controlled with storage allowed"); 230 231 let scriptURL = await SpecialPowers.spawn(browser, [], async function () { 232 let b = new content.Blob( 233 ["self.postMessage(self.location.href);self.close()"], 234 { type: "application/javascript" } 235 ); 236 // No need to call revokeObjectURL() since the window will be closed shortly. 237 let u = content.URL.createObjectURL(b); 238 let w = new content.Worker(u); 239 return await new Promise(resolve => { 240 w.onmessage = e => resolve(e.data); 241 }); 242 }); 243 244 ok(scriptURL.startsWith("blob:"), "blob URL worker should run"); 245 246 await SpecialPowers.pushPrefEnv({ 247 set: [ 248 ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT], 249 ], 250 }); 251 252 let scriptURL2 = await SpecialPowers.spawn(browser, [], async function () { 253 let b = new content.Blob( 254 ["self.postMessage(self.location.href);self.close()"], 255 { type: "application/javascript" } 256 ); 257 // No need to call revokeObjectURL() since the window will be closed shortly. 258 let u = content.URL.createObjectURL(b); 259 let w = new content.Worker(u); 260 return await new Promise(resolve => { 261 w.onmessage = e => resolve(e.data); 262 }); 263 }); 264 265 ok(scriptURL2.startsWith("blob:"), "blob URL worker should run"); 266 267 await SpecialPowers.popPrefEnv(); 268 BrowserTestUtils.removeTab(tab); 269 }); 270 271 add_task(async function cleanup() { 272 PermissionTestUtils.remove(PAGE_URI, "cookie"); 273 274 let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI); 275 let browser = gBrowser.getBrowserForTab(tab); 276 await BrowserTestUtils.browserLoaded(browser); 277 278 await SpecialPowers.spawn(browser, [SCOPE], async function (uri) { 279 let reg = await content.navigator.serviceWorker.getRegistration(uri); 280 let worker = reg.active; 281 await reg.unregister(); 282 await new Promise(resolve => { 283 if (worker.state === "redundant") { 284 resolve(); 285 return; 286 } 287 worker.addEventListener("statechange", function onStateChange() { 288 if (worker.state === "redundant") { 289 worker.removeEventListener("statechange", onStateChange); 290 resolve(); 291 } 292 }); 293 }); 294 }); 295 296 BrowserTestUtils.removeTab(tab); 297 });