browser_cookies_serviceWorker.js (14838B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const TEST_CROSS_SITE_DOMAIN = "https://example.net/"; 7 const TEST_CROSS_SITE_PAGE = 8 TEST_CROSS_SITE_DOMAIN + TEST_PATH + "file_empty.html"; 9 10 add_setup(async function () { 11 await SpecialPowers.pushPrefEnv({ 12 set: [ 13 ["dom.serviceWorkers.enabled", true], 14 ["dom.serviceWorkers.testing.enabled", true], 15 ], 16 }); 17 18 Services.cookies.removeAll(); 19 }); 20 21 function registerSW(browser) { 22 return SpecialPowers.spawn(browser, [], async _ => { 23 let reg = 24 await content.navigator.serviceWorker.register("serviceWorker.js"); 25 26 await ContentTaskUtils.waitForCondition(() => { 27 return reg.active && reg.active.state === "activated"; 28 }, "The service worker is activated"); 29 30 ok( 31 content.navigator.serviceWorker.controller, 32 "The service worker controls the document successfully." 33 ); 34 }); 35 } 36 37 function fetchCookiesFromSW(browser) { 38 return SpecialPowers.spawn(browser, [], async _ => { 39 return new content.Promise(resolve => { 40 content.navigator.serviceWorker.addEventListener("message", event => { 41 resolve(event.data.content); 42 }); 43 44 content.navigator.serviceWorker.controller.postMessage({ 45 action: "fetch", 46 url: `cookies.sjs`, 47 }); 48 }); 49 }); 50 } 51 52 function setCookiesFromSW(browser, cookies) { 53 let setCookieQuery = ""; 54 55 for (let cookie of cookies) { 56 setCookieQuery += `Set-Cookie=${cookie}&`; 57 } 58 59 return SpecialPowers.spawn(browser, [setCookieQuery], async query => { 60 return new content.Promise(resolve => { 61 content.navigator.serviceWorker.addEventListener("message", event => { 62 resolve(event.data.content); 63 }); 64 65 content.navigator.serviceWorker.controller.postMessage({ 66 action: "fetch", 67 url: `cookies.sjs?${query}`, 68 }); 69 }); 70 }); 71 } 72 73 function unregisterSW(browser) { 74 return SpecialPowers.spawn(browser, [], async _ => { 75 const regs = await content.navigator.serviceWorker.getRegistrations(); 76 for (const reg of regs) { 77 await reg.unregister(); 78 } 79 }); 80 } 81 82 /** 83 * Verify a first-party service worker can access both SameSite=None and 84 * SameSite=Lax cookies set in the first-party context. 85 */ 86 add_task(async function testCookiesWithFirstPartyServiceWorker() { 87 info("Open a tab"); 88 let tab = await BrowserTestUtils.openNewForegroundTab( 89 gBrowser, 90 TEST_TOP_PAGE 91 ); 92 93 info("Writing cookies to the first-party context."); 94 await SpecialPowers.spawn(tab.linkedBrowser, [], async _ => { 95 const cookies = [ 96 "foo=bar; SameSite=None; Secure", 97 "fooLax=barLax; SameSite=Lax; Secure", 98 ]; 99 100 let query = ""; 101 102 for (let cookie of cookies) { 103 query += `Set-Cookie=${cookie}&`; 104 } 105 106 await content.fetch(`cookies.sjs?${query}`); 107 }); 108 109 info("Register a service worker and trigger a fetch request to get cookies."); 110 await registerSW(tab.linkedBrowser); 111 let cookieStr = await fetchCookiesFromSW(tab.linkedBrowser); 112 113 is(cookieStr, "foo=bar; fooLax=barLax", "The cookies are expected"); 114 115 info("Set cookies from the service worker."); 116 await setCookiesFromSW(tab.linkedBrowser, [ 117 "foo=barSW; SameSite=None; Secure", 118 "fooLax=barLaxSW; SameSite=Lax; Secure", 119 ]); 120 121 info("Get cookies from the service worker."); 122 cookieStr = await fetchCookiesFromSW(tab.linkedBrowser); 123 124 is(cookieStr, "foo=barSW; fooLax=barLaxSW", "The cookies are expected"); 125 126 await unregisterSW(tab.linkedBrowser); 127 BrowserTestUtils.removeTab(tab); 128 Services.cookies.removeAll(); 129 }); 130 131 /** 132 * Verify a cross-site service worker can only access cookies set in the 133 * same cross-site context. 134 */ 135 add_task(async function testCookiesWithCrossSiteServiceWorker() { 136 // Disable blocking third-party cookies. 137 await SpecialPowers.pushPrefEnv({ 138 set: [["network.cookie.cookieBehavior.optInPartitioning", false]], 139 }); 140 141 info("Open a cross-site tab"); 142 let crossSiteTab = await BrowserTestUtils.openNewForegroundTab( 143 gBrowser, 144 TEST_CROSS_SITE_PAGE 145 ); 146 147 info("Writing cookies to the cross site in the first-party context."); 148 await SpecialPowers.spawn(crossSiteTab.linkedBrowser, [], async _ => { 149 const cookies = [ 150 "foo=bar; SameSite=None; Secure", 151 "fooLax=barLax; SameSite=Lax; Secure", 152 ]; 153 154 let query = ""; 155 156 for (let cookie of cookies) { 157 query += `Set-Cookie=${cookie}&`; 158 } 159 160 await content.fetch(`cookies.sjs?${query}`); 161 }); 162 163 info("Open a tab"); 164 let tab = await BrowserTestUtils.openNewForegroundTab( 165 gBrowser, 166 TEST_TOP_PAGE 167 ); 168 169 info("Load a cross-site iframe"); 170 let crossSiteBc = await SpecialPowers.spawn( 171 tab.linkedBrowser, 172 [TEST_CROSS_SITE_PAGE], 173 async url => { 174 let ifr = content.document.createElement("iframe"); 175 176 await new content.Promise(resolve => { 177 ifr.onload = resolve; 178 ifr.src = url; 179 content.document.body.appendChild(ifr); 180 }); 181 182 return ifr.browsingContext; 183 } 184 ); 185 186 info("Write cookies in the cross-site iframe"); 187 await SpecialPowers.spawn(crossSiteBc, [], async _ => { 188 const cookies = [ 189 "foo=crossBar; SameSite=None; Secure", 190 "fooLax=crossBarLax; SameSite=Lax; Secure", 191 ]; 192 193 let query = ""; 194 195 for (let cookie of cookies) { 196 query += `Set-Cookie=${cookie}&`; 197 } 198 199 await content.fetch(`cookies.sjs?${query}`); 200 }); 201 202 info( 203 "Register a service worker and trigger a fetch request to get cookies in cross-site context." 204 ); 205 await registerSW(crossSiteBc); 206 let cookieStr = await fetchCookiesFromSW(crossSiteBc); 207 208 is( 209 cookieStr, 210 "foo=crossBar", 211 "Only the SameSite=None cookie set in the third-party iframe is available." 212 ); 213 214 info("Set cookies from the third-party service worker."); 215 await setCookiesFromSW(crossSiteBc, [ 216 "foo=crossBarSW; SameSite=None; Secure", 217 "fooLax=crossBarLaxSW; SameSite=Lax; Secure", 218 ]); 219 220 info("Get cookies from the third-party service worker."); 221 cookieStr = await fetchCookiesFromSW(crossSiteBc); 222 223 is( 224 cookieStr, 225 "foo=crossBarSW", 226 "Only the SameSite=None cookie set in the third-party service worker is available." 227 ); 228 229 await unregisterSW(crossSiteBc); 230 BrowserTestUtils.removeTab(crossSiteTab); 231 BrowserTestUtils.removeTab(tab); 232 Services.cookies.removeAll(); 233 }); 234 235 /** 236 * Verify a cross-site service worker can only access partitioned cookies set in 237 * the same cross-site context if third-party cookies are blocked. 238 */ 239 add_task(async function testPartitionedCookiesWithCrossSiteServiceWorker() { 240 // Enable blocking third-party cookies. 241 await SpecialPowers.pushPrefEnv({ 242 set: [ 243 ["network.cookie.cookieBehavior.optInPartitioning", true], 244 ["network.cookie.CHIPS.enabled", true], 245 ], 246 }); 247 248 info("Open a tab"); 249 let tab = await BrowserTestUtils.openNewForegroundTab( 250 gBrowser, 251 TEST_TOP_PAGE 252 ); 253 254 info("Load a cross-site iframe"); 255 let crossSiteBc = await SpecialPowers.spawn( 256 tab.linkedBrowser, 257 [TEST_CROSS_SITE_PAGE], 258 async url => { 259 let ifr = content.document.createElement("iframe"); 260 261 await new content.Promise(resolve => { 262 ifr.onload = resolve; 263 ifr.src = url; 264 content.document.body.appendChild(ifr); 265 }); 266 267 return ifr.browsingContext; 268 } 269 ); 270 271 info("Write cookies in the cross-site iframe"); 272 await SpecialPowers.spawn(crossSiteBc, [], async _ => { 273 const cookies = [ 274 "foo=crossBar; SameSite=None; Secure", 275 "fooLax=crossBarLax; SameSite=Lax; Secure", 276 "fooPartitioned=crossBar; SameSite=None; Secure; Partitioned;", 277 "fooLaxPartitioned=crossBarLax; SameSite=Lax; Secure; Partitioned;", 278 ]; 279 280 let query = ""; 281 282 for (let cookie of cookies) { 283 query += `Set-Cookie=${cookie}&`; 284 } 285 286 await content.fetch(`cookies.sjs?${query}`); 287 }); 288 289 info( 290 "Register a service worker and trigger a fetch request to get cookies in cross-site context." 291 ); 292 await registerSW(crossSiteBc); 293 let cookieStr = await fetchCookiesFromSW(crossSiteBc); 294 295 is( 296 cookieStr, 297 "fooPartitioned=crossBar", 298 "Only the SameSite=None partitioned cookie set in the third-party iframe is available." 299 ); 300 301 info("Set cookies from the third-party service worker."); 302 await setCookiesFromSW(crossSiteBc, [ 303 "foo=crossBarSW; SameSite=None; Secure", 304 "fooLax=crossBarLaxSW; SameSite=Lax; Secure", 305 "fooPartitioned=crossBarSW; SameSite=None; Secure; Partitioned;", 306 "fooLaxPartitioned=crossBarLaxSW; SameSite=Lax; Secure; Partitioned;", 307 ]); 308 309 info("Get cookies from the third-party service worker."); 310 cookieStr = await fetchCookiesFromSW(crossSiteBc); 311 312 is( 313 cookieStr, 314 "fooPartitioned=crossBarSW", 315 "Only the SameSite=None partitioned cookie set in the third-party service worker is available." 316 ); 317 318 await unregisterSW(crossSiteBc); 319 BrowserTestUtils.removeTab(tab); 320 Services.cookies.removeAll(); 321 }); 322 323 /** 324 * Verify a ABA service worker can only access cookies set in the ABA context. 325 */ 326 add_task(async function testCookiesWithABAServiceWorker() { 327 // Disable blocking third-party cookies. 328 await SpecialPowers.pushPrefEnv({ 329 set: [["network.cookie.cookieBehavior.optInPartitioning", false]], 330 }); 331 332 info("Open a tab"); 333 let tab = await BrowserTestUtils.openNewForegroundTab( 334 gBrowser, 335 TEST_TOP_PAGE 336 ); 337 338 info("Writing cookies to the first-party context."); 339 await SpecialPowers.spawn(tab.linkedBrowser, [], async _ => { 340 const cookies = [ 341 "foo=bar; SameSite=None; Secure", 342 "fooLax=barLax; SameSite=Lax; Secure", 343 ]; 344 345 let query = ""; 346 347 for (let cookie of cookies) { 348 query += `Set-Cookie=${cookie}&`; 349 } 350 351 await content.fetch(`cookies.sjs?${query}`); 352 }); 353 354 info("Load a ABA iframe"); 355 let crossSiteBc = await SpecialPowers.spawn( 356 tab.linkedBrowser, 357 [TEST_CROSS_SITE_PAGE], 358 async url => { 359 let ifr = content.document.createElement("iframe"); 360 361 await new content.Promise(resolve => { 362 ifr.onload = resolve; 363 ifr.src = url; 364 content.document.body.appendChild(ifr); 365 }); 366 367 return ifr.browsingContext; 368 } 369 ); 370 371 let ABABc = await SpecialPowers.spawn( 372 crossSiteBc, 373 [TEST_TOP_PAGE], 374 async url => { 375 let ifr = content.document.createElement("iframe"); 376 377 await new content.Promise(resolve => { 378 ifr.onload = resolve; 379 ifr.src = url; 380 content.document.body.appendChild(ifr); 381 }); 382 383 return ifr.browsingContext; 384 } 385 ); 386 387 info( 388 "Register a service worker and trigger a fetch request to get cookies in the ABA context." 389 ); 390 391 await registerSW(ABABc); 392 let cookieStr = await fetchCookiesFromSW(ABABc); 393 is(cookieStr, "", "No cookie should be available in ABA context."); 394 395 info("Set cookies in the ABA iframe"); 396 await SpecialPowers.spawn(ABABc, [], async _ => { 397 const cookies = [ 398 "fooABA=barABA; SameSite=None; Secure", 399 "fooABALax=BarABALax; SameSite=Lax; Secure", 400 ]; 401 402 let query = ""; 403 404 for (let cookie of cookies) { 405 query += `Set-Cookie=${cookie}&`; 406 } 407 408 await content.fetch(`cookies.sjs?${query}`); 409 }); 410 411 info("Get cookies in the ABA service worker."); 412 cookieStr = await fetchCookiesFromSW(ABABc); 413 414 is( 415 cookieStr, 416 "fooABA=barABA", 417 "Only the SameSite=None cookie set in ABA iframe is available." 418 ); 419 420 info("Set cookies from the service worker in ABA context"); 421 await setCookiesFromSW(ABABc, [ 422 "fooABA=barABASW; SameSite=None; Secure", 423 "fooABALax=BarABALaxSW; SameSite=Lax; Secure", 424 ]); 425 426 info("Get cookies from the service worker in the ABA context."); 427 cookieStr = await fetchCookiesFromSW(ABABc); 428 429 is( 430 cookieStr, 431 "fooABA=barABASW", 432 "Only the SameSite=None cookie set in ABA service worker is available." 433 ); 434 435 await unregisterSW(ABABc); 436 BrowserTestUtils.removeTab(tab); 437 Services.cookies.removeAll(); 438 }); 439 440 /** 441 * Verify a ABA service worker can only access partitioned cookies set in the 442 * ABA context if third-party cookies are blocked. 443 */ 444 add_task(async function testCookiesWithABAServiceWorker() { 445 // Disable blocking third-party cookies. 446 await SpecialPowers.pushPrefEnv({ 447 set: [ 448 ["network.cookie.cookieBehavior.optInPartitioning", true], 449 ["network.cookie.CHIPS.enabled", true], 450 ], 451 }); 452 453 info("Open a tab"); 454 let tab = await BrowserTestUtils.openNewForegroundTab( 455 gBrowser, 456 TEST_TOP_PAGE 457 ); 458 459 info("Load a ABA iframe"); 460 let crossSiteBc = await SpecialPowers.spawn( 461 tab.linkedBrowser, 462 [TEST_CROSS_SITE_PAGE], 463 async url => { 464 let ifr = content.document.createElement("iframe"); 465 466 await new content.Promise(resolve => { 467 ifr.onload = resolve; 468 ifr.src = url; 469 content.document.body.appendChild(ifr); 470 }); 471 472 return ifr.browsingContext; 473 } 474 ); 475 476 let ABABc = await SpecialPowers.spawn( 477 crossSiteBc, 478 [TEST_TOP_PAGE], 479 async url => { 480 let ifr = content.document.createElement("iframe"); 481 482 await new content.Promise(resolve => { 483 ifr.onload = resolve; 484 ifr.src = url; 485 content.document.body.appendChild(ifr); 486 }); 487 488 return ifr.browsingContext; 489 } 490 ); 491 492 info("Set cookies in the ABA iframe"); 493 await SpecialPowers.spawn(ABABc, [], async _ => { 494 const cookies = [ 495 "fooABA=barABA; SameSite=None; Secure", 496 "fooABALax=BarABALax; SameSite=Lax; Secure", 497 "fooABAPartitioned=barABA; SameSite=None; Secure; Partitioned;", 498 "fooABALaxPartitioned=BarABALax; SameSite=Lax; Secure; Partitioned;", 499 ]; 500 501 let query = ""; 502 503 for (let cookie of cookies) { 504 query += `Set-Cookie=${cookie}&`; 505 } 506 507 await content.fetch(`cookies.sjs?${query}`); 508 }); 509 510 info( 511 "Register a service worker and trigger a fetch request to get cookies in the ABA context." 512 ); 513 514 await registerSW(ABABc); 515 516 info("Get cookies in the ABA service worker."); 517 let cookieStr = await fetchCookiesFromSW(ABABc); 518 519 is( 520 cookieStr, 521 "fooABAPartitioned=barABA", 522 "Only the SameSite=None partitioned cookie set in ABA iframe is available." 523 ); 524 525 info("Set cookies from the service worker in ABA context"); 526 await setCookiesFromSW(ABABc, [ 527 "fooABA=barABASW; SameSite=None; Secure", 528 "fooABALax=BarABALaxSW; SameSite=Lax; Secure", 529 "fooABAPartitioned=barABASW; SameSite=None; Secure; Partitioned;", 530 "fooABALaxPartitioned=BarABALaxSW; SameSite=Lax; Secure; Partitioned;", 531 ]); 532 533 info("Get cookies from the service worker in the ABA context."); 534 cookieStr = await fetchCookiesFromSW(ABABc); 535 536 is( 537 cookieStr, 538 "fooABAPartitioned=barABASW", 539 "Only the SameSite=None partitioned cookie set in ABA service worker is available." 540 ); 541 542 await unregisterSW(ABABc); 543 BrowserTestUtils.removeTab(tab); 544 Services.cookies.removeAll(); 545 });