From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../browser_ext_background_serviceworker.js | 285 +++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 toolkit/components/extensions/test/browser/browser_ext_background_serviceworker.js (limited to 'toolkit/components/extensions/test/browser/browser_ext_background_serviceworker.js') diff --git a/toolkit/components/extensions/test/browser/browser_ext_background_serviceworker.js b/toolkit/components/extensions/test/browser/browser_ext_background_serviceworker.js new file mode 100644 index 0000000000..153818f4de --- /dev/null +++ b/toolkit/components/extensions/test/browser/browser_ext_background_serviceworker.js @@ -0,0 +1,285 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +/* globals getBackgroundServiceWorkerRegistration, waitForServiceWorkerTerminated */ + +Services.scriptloader.loadSubScript( + new URL("head_serviceworker.js", gTestPath).href, + this +); + +add_task(assert_background_serviceworker_pref_enabled); + +add_task(async function test_serviceWorker_register_guarded_by_pref() { + // Test with backgroundServiceWorkeEnable set to true and the + // extensions.serviceWorkerRegist.allowed pref set to false. + // NOTE: the scenario with backgroundServiceWorkeEnable set to false + // is part of "browser_ext_background_serviceworker_pref_disabled.js". + + await SpecialPowers.pushPrefEnv({ + set: [["extensions.serviceWorkerRegister.allowed", false]], + }); + + let extensionData = { + files: { + "page.html": "", + "page.js": async function () { + browser.test.assertEq( + undefined, + navigator.serviceWorker, + "navigator.serviceWorker should be undefined" + ); + browser.test.sendMessage("test-serviceWorker-register-disallowed"); + }, + "sw.js": "", + }, + }; + + let extension = ExtensionTestUtils.loadExtension(extensionData); + await extension.startup(); + + // Verify that an extension page can't register a moz-extension url + // as a service worker. + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: `moz-extension://${extension.uuid}/page.html`, + }, + async () => { + await extension.awaitMessage("test-serviceWorker-register-disallowed"); + } + ); + + await extension.unload(); + + await SpecialPowers.popPrefEnv(); + + // Test again with the pref set to true. + + await SpecialPowers.pushPrefEnv({ + set: [["extensions.serviceWorkerRegister.allowed", true]], + }); + + extension = ExtensionTestUtils.loadExtension({ + files: { + ...extensionData.files, + "page.js": async function () { + try { + await navigator.serviceWorker.register("sw.js"); + } catch (err) { + browser.test.fail( + `Unexpected error on registering a service worker: ${err}` + ); + throw err; + } finally { + browser.test.sendMessage("test-serviceworker-register-allowed"); + } + }, + }, + }); + await extension.startup(); + + // Verify that an extension page can register a moz-extension url + // as a service worker if enabled by the related pref. + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: `moz-extension://${extension.uuid}/page.html`, + }, + async () => { + await extension.awaitMessage("test-serviceworker-register-allowed"); + } + ); + + await extension.unload(); + + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function test_cache_api_allowed() { + // Verify that Cache API support for moz-extension url availability is + // conditioned only by the extensions.backgroundServiceWorker.enabled pref. + // NOTE: the scenario with backgroundServiceWorkeEnable set to false + // is part of "browser_ext_background_serviceworker_pref_disabled.js". + const extension = ExtensionTestUtils.loadExtension({ + async background() { + try { + let cache = await window.caches.open("test-cache-api"); + browser.test.assertTrue( + await window.caches.has("test-cache-api"), + "CacheStorage.has should resolve to true" + ); + + // Test that adding and requesting cached moz-extension urls + // works as well. + let url = browser.runtime.getURL("file.txt"); + await cache.add(url); + const content = await cache.match(url).then(res => res.text()); + browser.test.assertEq( + "file content", + content, + "Got the expected content from the cached moz-extension url" + ); + + // Test that deleting the cache storage works as expected. + browser.test.assertTrue( + await window.caches.delete("test-cache-api"), + "Cache deleted successfully" + ); + browser.test.assertTrue( + !(await window.caches.has("test-cache-api")), + "CacheStorage.has should resolve to false" + ); + } catch (err) { + browser.test.fail(`Unexpected error on using Cache API: ${err}`); + throw err; + } finally { + browser.test.sendMessage("test-cache-api-allowed"); + } + }, + files: { + "file.txt": "file content", + }, + }); + + await extension.startup(); + await extension.awaitMessage("test-cache-api-allowed"); + await extension.unload(); +}); + +function createTestSWScript({ postMessageReply }) { + return ` + self.onmessage = msg => { + dump("Background ServiceWorker - onmessage handler\\n"); + msg.ports[0].postMessage("${postMessageReply}"); + dump("Background ServiceWorker - postMessage\\n"); + }; + dump("Background ServiceWorker - executed\\n"); + `; +} + +async function testServiceWorker({ extension, expectMessageReply }) { + // Verify that the WebExtensions framework has successfully registered the + // background service worker declared in the extension manifest. + const swRegInfo = getBackgroundServiceWorkerRegistration(extension); + + // Activate the background service worker by exchanging a message + // with it. + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: `moz-extension://${extension.uuid}/page.html`, + }, + async browser => { + let msgFromV1 = await SpecialPowers.spawn( + browser, + [swRegInfo.scriptURL], + async url => { + const { active } = await content.navigator.serviceWorker.ready; + const { port1, port2 } = new content.MessageChannel(); + + return new Promise(resolve => { + port1.onmessage = msg => resolve(msg.data); + active.postMessage("test", [port2]); + }); + } + ); + + Assert.deepEqual( + msgFromV1, + expectMessageReply, + "Got the expected reply from the extension service worker" + ); + } + ); +} + +function loadTestExtension({ version }) { + const postMessageReply = `reply:sw-v${version}`; + + return ExtensionTestUtils.loadExtension({ + useAddonManager: "temporary", + manifest: { + version, + background: { + service_worker: "sw.js", + }, + browser_specific_settings: { gecko: { id: "test-bg-sw@mochi.test" } }, + }, + files: { + "page.html": "", + "sw.js": createTestSWScript({ postMessageReply }), + }, + }); +} + +async function assertWorkerIsRunningInExtensionProcess(extension) { + // Activate the background service worker by exchanging a message + // with it. + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: `moz-extension://${extension.uuid}/page.html`, + }, + async browser => { + const workerScriptURL = `moz-extension://${extension.uuid}/sw.js`; + const workerDebuggerURLs = await SpecialPowers.spawn( + browser, + [workerScriptURL], + async url => { + await content.navigator.serviceWorker.ready; + const wdm = Cc[ + "@mozilla.org/dom/workers/workerdebuggermanager;1" + ].getService(Ci.nsIWorkerDebuggerManager); + + return Array.from(wdm.getWorkerDebuggerEnumerator()) + .map(wd => { + return wd.url; + }) + .filter(swURL => swURL == url); + } + ); + + Assert.deepEqual( + workerDebuggerURLs, + [workerScriptURL], + "The worker should be running in the extension child process" + ); + } + ); +} + +add_task(async function test_background_serviceworker_with_no_ext_apis() { + const extensionV1 = loadTestExtension({ version: "1" }); + await extensionV1.startup(); + + const swRegInfo = getBackgroundServiceWorkerRegistration(extensionV1); + const { uuid } = extensionV1; + + await assertWorkerIsRunningInExtensionProcess(extensionV1); + await testServiceWorker({ + extension: extensionV1, + expectMessageReply: "reply:sw-v1", + }); + + // Load a new version of the same addon and verify that the + // expected worker script is being executed. + const extensionV2 = loadTestExtension({ version: "2" }); + await extensionV2.startup(); + is(extensionV2.uuid, uuid, "The extension uuid did not change as expected"); + + await testServiceWorker({ + extension: extensionV2, + expectMessageReply: "reply:sw-v2", + }); + + await Promise.all([ + extensionV2.unload(), + // test extension v1 wrapper has to be unloaded explicitly, otherwise + // will be detected as a failure by the test harness. + extensionV1.unload(), + ]); + await waitForServiceWorkerTerminated(swRegInfo); + await waitForServiceWorkerRegistrationsRemoved(extensionV2); +}); -- cgit v1.2.3