From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../browser/browser_partitionedServiceWorkers.js | 625 +++++++++++++++++++++ 1 file changed, 625 insertions(+) create mode 100644 toolkit/components/antitracking/test/browser/browser_partitionedServiceWorkers.js (limited to 'toolkit/components/antitracking/test/browser/browser_partitionedServiceWorkers.js') diff --git a/toolkit/components/antitracking/test/browser/browser_partitionedServiceWorkers.js b/toolkit/components/antitracking/test/browser/browser_partitionedServiceWorkers.js new file mode 100644 index 0000000000..f45caba43a --- /dev/null +++ b/toolkit/components/antitracking/test/browser/browser_partitionedServiceWorkers.js @@ -0,0 +1,625 @@ +/* import-globals-from storageAccessAPIHelpers.js */ + +PartitionedStorageHelper.runTest( + "ServiceWorkers - disable partitioning", + async (win3rdParty, win1stParty, allowed) => { + // Partitioned serviceWorkers are disabled in third-party context. + await win3rdParty.navigator.serviceWorker.register("empty.js").then( + _ => { + ok(allowed, "Success: ServiceWorker cannot be used!"); + }, + _ => { + ok(!allowed, "Failed: ServiceWorker cannot be used!"); + } + ); + + await win1stParty.navigator.serviceWorker.register("empty.js").then( + _ => { + ok(true, "Success: ServiceWorker should be available!"); + }, + _ => { + ok(false, "Failed: ServiceWorker should be available!"); + } + ); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", false], + ] +); + +PartitionedStorageHelper.runTest( + "ServiceWorkers - enable partitioning", + async (win3rdParty, win1stParty, allowed) => { + // Partitioned serviceWorkers are enabled in third-party context. + await win3rdParty.navigator.serviceWorker.register("empty.js").then( + _ => { + ok( + true, + "Success: ServiceWorker should be available in third parties." + ); + }, + _ => { + ok( + false, + "Failed: ServiceWorker should be available in third parties." + ); + } + ); + + await win1stParty.navigator.serviceWorker.register("empty.js").then( + _ => { + ok(true, "Success: ServiceWorker should be available!"); + }, + _ => { + ok(false, "Failed: ServiceWorker should be available!"); + } + ); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", true], + ] +); + +PartitionedStorageHelper.runTest( + "ServiceWorkers - MatchAll", + async (win3rdParty, win1stParty, allowed) => { + if (!win1stParty.sw) { + win1stParty.sw = await registerServiceWorker(win1stParty, "matchAll.js"); + } + + let msgPromise = new Promise(resolve => { + win1stParty.navigator.serviceWorker.addEventListener("message", msg => { + resolve(msg.data); + }); + }); + + win1stParty.sw.postMessage(win3rdParty.location.href); + let msg = await msgPromise; + + // The service worker will always be partitioned. So, the first party window + // won't have control on the third-party window. + is( + false, + msg, + "We won't have the 3rd party window controlled regardless of StorageAccess." + ); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", true], + ] +); + +PartitionedStorageHelper.runTest( + "ServiceWorkers - Partition ScriptContext", + async (win3rdParty, win1stParty, allowed) => { + // Register service worker for the first-party window. + if (!win1stParty.sw) { + win1stParty.sw = await registerServiceWorker( + win1stParty, + "serviceWorker.js" + ); + } + + // Register service worker for the third-party window. + if (!win3rdParty.sw) { + win3rdParty.sw = await registerServiceWorker( + win3rdParty, + "serviceWorker.js" + ); + } + + // Set a script value to first-party service worker. + let res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { + type: "SetScriptValue", + value: "1stParty", + } + ); + ok(res.result, "OK", "Set script value to first-party service worker."); + + // Set a script value to third-party service worker. + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { + type: "SetScriptValue", + value: "3rdParty", + } + ); + ok(res.result, "OK", "Set script value to third-party service worker."); + + // Get and check script value from the first-party service worker. + res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { type: "GetScriptValue" } + ); + is( + res.value, + "1stParty", + "The script value in first party window is correct" + ); + + // Get and check script value from the third-party service worker. + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { type: "GetScriptValue" } + ); + + is( + res.value, + "3rdParty", + "The script value in third party window is correct" + ); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", true], + ] +); + +PartitionedStorageHelper.runTest( + "ServiceWorkers - Partition DOM Cache", + async (win3rdParty, win1stParty, allowed) => { + // Register service worker for the first-party window. + if (!win1stParty.sw) { + win1stParty.sw = await registerServiceWorker( + win1stParty, + "serviceWorker.js" + ); + } + + // Register service worker for the third-party window. + if (!win3rdParty.sw) { + win3rdParty.sw = await registerServiceWorker( + win3rdParty, + "serviceWorker.js" + ); + } + + // Set DOM cache to first-party service worker. + let res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { + type: "SetCache", + value: "1stParty", + } + ); + ok(res.result, "OK", "Set cache to first-party service worker."); + + // Set DOM cache to third-party service worker. + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { + type: "SetCache", + value: "3rdParty", + } + ); + ok(res.result, "OK", "Set cache to third-party service worker."); + + // Check DOM cache from the first-party service worker. + res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { type: "HasCache", value: "1stParty" } + ); + ok( + res.value, + "The '1stParty' cache storage should exist for the first-party window." + ); + res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { type: "HasCache", value: "3rdParty" } + ); + ok( + !res.value, + "The '3rdParty' cache storage should not exist for the first-party window." + ); + + // Check DOM cache from the third-party service worker. + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { type: "HasCache", value: "1stParty" } + ); + + ok( + !res.value, + "The '1stParty' cache storage should not exist for the third-party window." + ); + + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { type: "HasCache", value: "3rdParty" } + ); + + ok( + res.value, + "The '3rdParty' cache storage should exist for the third-party window." + ); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", true], + ] +); + +PartitionedStorageHelper.runTest( + "ServiceWorkers - Partition IndexedDB", + async (win3rdParty, win1stParty, allowed) => { + // Register service worker for the first-party window. + if (!win1stParty.sw) { + win1stParty.sw = await registerServiceWorker( + win1stParty, + "serviceWorker.js" + ); + } + + // Register service worker for the third-party window. + if (!win3rdParty.sw) { + win3rdParty.sw = await registerServiceWorker( + win3rdParty, + "serviceWorker.js" + ); + } + + // Set indexedDB value to first-party service worker. + let res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { + type: "SetIndexedDB", + value: "1stParty", + } + ); + ok(res.result, "OK", "Set cache to first-party service worker."); + + // Set indexedDB value to third-party service worker. + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { + type: "SetIndexedDB", + value: "3rdParty", + } + ); + ok(res.result, "OK", "Set cache to third-party service worker."); + + // Get and check indexedDB value from the first-party service worker. + res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { type: "GetIndexedDB" } + ); + is( + res.value, + "1stParty", + "The indexedDB value in first party window is correct" + ); + + // Get and check indexedDB from the third-party service worker. + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { type: "GetIndexedDB" } + ); + + is( + res.value, + "3rdParty", + "The indexedDB value in third party window is correct" + ); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", true], + ] +); + +PartitionedStorageHelper.runTest( + "ServiceWorkers - Partition Intercept", + async (win3rdParty, win1stParty, allowed) => { + // Register service worker for the first-party window. + if (!win1stParty.sw) { + win1stParty.sw = await registerServiceWorker( + win1stParty, + "serviceWorker.js" + ); + } + + // Register service worker for the third-party window. + if (!win3rdParty.sw) { + win3rdParty.sw = await registerServiceWorker( + win3rdParty, + "serviceWorker.js" + ); + } + + // Fetch a resource in the first-party window. + await win1stParty.fetch("empty.js"); + + // Check that only the first-party service worker gets fetch event. + let res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { type: "GetFetchURL" } + ); + is( + res.value, + "http://not-tracking.example.com/browser/toolkit/components/antitracking/test/browser/empty.js", + "The first-party service worker received fetch event." + ); + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { type: "GetFetchURL" } + ); + is( + res.value, + "", + "The third-party service worker received no fetch event." + ); + + // Fetch a resource in the third-party window. + await win3rdParty.fetch("empty.js"); + + // Check if the fetch event only happens in third-party service worker. + res = await sendAndWaitWorkerMessage( + win1stParty.sw, + win1stParty.navigator.serviceWorker, + { type: "GetFetchURL" } + ); + is( + res.value, + "", + "The first-party service worker received no fetch event." + ); + res = await sendAndWaitWorkerMessage( + win3rdParty.sw, + win3rdParty.navigator.serviceWorker, + { type: "GetFetchURL" } + ); + is( + res.value, + "http://not-tracking.example.com/browser/toolkit/components/antitracking/test/browser/empty.js", + "The third-party service worker received fetch event." + ); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", true], + ] +); + +// Bug1743236 - Verify the content process won't crash if we create a dedicated +// worker in a service worker controlled third-party page with Storage Access. +PartitionedStorageHelper.runTest( + "ServiceWorkers - Create Dedicated Worker", + async (win3rdParty, win1stParty, allowed) => { + // We only do this test when the storage access is granted. + if (!allowed) { + return; + } + + // Register service worker for the first-party window. + if (!win1stParty.sw) { + win1stParty.sw = await registerServiceWorker( + win1stParty, + "serviceWorker.js" + ); + } + + // Register service worker for the third-party window. + if (!win3rdParty.sw) { + win3rdParty.sw = await registerServiceWorker( + win3rdParty, + "serviceWorker.js" + ); + } + + // Create a dedicated worker in first-party window. + let firstPartyWorker = new win1stParty.Worker("dedicatedWorker.js"); + + // Post a message to the dedicated worker and wait until the message circles + // back. + await new Promise(resolve => { + firstPartyWorker.addEventListener("message", msg => { + if (msg.data == "1stParty") { + resolve(); + } + }); + + firstPartyWorker.postMessage("1stParty"); + }); + + // Create a dedicated worker in third-party window. + let thirdPartyWorker = new win3rdParty.Worker("dedicatedWorker.js"); + + // Post a message to the dedicated worker and wait until the message circles + // back. + await new Promise(resolve => { + thirdPartyWorker.addEventListener("message", msg => { + if (msg.data == "3rdParty") { + resolve(); + } + }); + + thirdPartyWorker.postMessage("3rdParty"); + }); + + firstPartyWorker.terminate(); + thirdPartyWorker.terminate(); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", true], + ] +); + +// Bug1768193 - Verify the parent process won't crash if we create a shared +// worker in a service worker controlled third-party page with Storage Access. +PartitionedStorageHelper.runTest( + "ServiceWorkers - Create Shared Worker", + async (win3rdParty, win1stParty, allowed) => { + // We only do this test when the storage access is granted. + if (!allowed) { + return; + } + + // Register service worker for the first-party window. + if (!win1stParty.sw) { + win1stParty.sw = await registerServiceWorker( + win1stParty, + "serviceWorker.js" + ); + } + + // Register service worker for the third-party window. + if (!win3rdParty.sw) { + win3rdParty.sw = await registerServiceWorker( + win3rdParty, + "serviceWorker.js" + ); + } + + // Create a shared worker in third-party window. + let thirdPartyWorker = new win3rdParty.SharedWorker("sharedWorker.js"); + + // Post a message to the dedicated worker and wait until the message circles + // back. + await new Promise(resolve => { + thirdPartyWorker.port.onmessage = msg => { + resolve(); + }; + thirdPartyWorker.onerror = _ => { + ok(false, "We should not be here"); + resolve(); + }; + thirdPartyWorker.port.postMessage("count"); + }); + + thirdPartyWorker.port.postMessage("close"); + }, + + async _ => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + }, + + [ + ["dom.serviceWorkers.exemptFromPerDomainMax", true], + ["dom.ipc.processCount", 1], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ["privacy.partition.serviceWorkers", true], + ] +); -- cgit v1.2.3