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 --- .../test/xpcshell/test_ext_background_iframe.js | 349 +++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 toolkit/components/extensions/test/xpcshell/test_ext_background_iframe.js (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_background_iframe.js') diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_background_iframe.js b/toolkit/components/extensions/test/xpcshell/test_ext_background_iframe.js new file mode 100644 index 0000000000..827a2a8697 --- /dev/null +++ b/toolkit/components/extensions/test/xpcshell/test_ext_background_iframe.js @@ -0,0 +1,349 @@ +"use strict"; + +const { Management } = ChromeUtils.importESModule( + "resource://gre/modules/Extension.sys.mjs" +); + +const server = AddonTestUtils.createHttpServer({ + hosts: ["example.com"], +}); + +// One test below relies on a slow-loading stylesheet. This function and promise +// enables the script to control exactly when the stylesheet load should finish. +let allowStylesheetToLoad; +let stylesheetBlockerPromise = new Promise(resolve => { + allowStylesheetToLoad = resolve; +}); +server.registerPathHandler("/slow.css", (request, response) => { + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/css", false); + + response.processAsync(); + + stylesheetBlockerPromise.then(() => { + response.write("body { color: rgb(1, 2, 3); }"); + response.finish(); + }); +}); + +// Test helper to keep track of the number of background context loads, from +// any extension. +class BackgroundWatcher { + constructor() { + // Number of background page loads observed. + this.bgBrowserCount = 0; + // Number of top-level background context loads observed. + this.bgViewCount = 0; + this.observing = false; + + this.onBrowserInserted = this.onBrowserInserted.bind(this); + this.onBackgroundViewLoaded = this.onBackgroundViewLoaded.bind(this); + + this.startObserving(); + } + + startObserving() { + this.observing = true; + Management.on("extension-browser-inserted", this.onBrowserInserted); + } + + stopObserving() { + this.observing = false; + Management.off("extension-browser-inserted", this.onBrowserInserted); + // Note: onBrowserInserted adds message listeners to the message manager + // of background contexts, but we do not explicitly unregister these here + // because the caller should only stop observing after knowing for sure + // that there are no new or pending loads of background pages. + } + + onBrowserInserted(eventName, browser) { + Assert.equal(eventName, "extension-browser-inserted", "Seen bg browser"); + if (!browser.getAttribute("webextension-view-type") === "background") { + return; + } + this.bgBrowserCount++; + browser.messageManager.addMessageListener( + "Extension:BackgroundViewLoaded", + this.onBackgroundViewLoaded + ); + } + + onBackgroundViewLoaded({ data }) { + if (!this.observing) { + // We shouldn't receive this event - see comment in stopObserving. + Assert.ok(false, "Got onBackgroundViewLoaded while !observing"); + } + this.bgViewCount++; + Assert.ok(data.childId, "childId passed to Extension:BackgroundViewLoaded"); + } +} + +add_task(async function test_first_extension_api_call_in_iframe() { + // In this test we test what happens when an extension API call happens in + // an iframe before the top-level document observes DOMContentLoaded. + // + // 1. Because DOMContentLoaded is blocked on the execution on + + + + + + `, + "background-subframe.html": ` + + + body_of_iframe`, + "background.js": backgroundScript, + "background-deferred.js": backgroundScriptDeferred, + }, + }); + + const bgWatcher = new BackgroundWatcher(); + // No "await extension.startup();" because extension.startup() in tests is + // currently blocked on background startup (due to TEST_NO_DELAYED_STARTUP + // defaulting to true). Because the background startup completion is blocked + // on the DOMContentLoaded of the background, extension.startup() does not + // resolve until we've unblocked the DOMContentLoaded notification. + const startupPromise = extension.startup(); + await extension.awaitMessage("allowStylesheetToLoad"); + Assert.equal(bgWatcher.bgBrowserCount, 1, "Got background page"); + Assert.equal(bgWatcher.bgViewCount, 0, "Background view still loading"); + info("frame loaded; allowing slow.css to load to unblock DOMContentLoaded"); + allowStylesheetToLoad(); + + info("Waiting for extension.startup() to resolve (background completion)"); + await startupPromise; + info("extension.startup() resolved. Waiting for top_and_frame_done..."); + + await extension.awaitMessage("top_and_frame_done"); + Assert.equal( + extension.extension.backgroundContext?.uri?.spec, + `moz-extension://${extension.uuid}/background.html`, + `extension.backgroundContext should exist and point to the main background` + ); + Assert.equal(bgWatcher.bgViewCount, 1, "Background has loaded once"); + Assert.equal( + extension.extension.views.size, + 2, + "Got ProxyContextParent instances for background and iframe" + ); + + await extension.unload(); + bgWatcher.stopObserving(); +}); + +add_task(async function test_only_script_execution_in_iframe() { + function backgroundSubframeScript() { + // The exact API call does not matter, as any extension API call will + // ensure that ProxyContextParent is initialized if it was not before: + // https://searchfox.org/mozilla-central/rev/892475f3ba2b959aeaef19d1d8602494e3f2ae32/toolkit/components/extensions/ExtensionPageChild.sys.mjs#221,223,227-228 + browser.runtime.getPlatformInfo().then(info => { + browser.test.assertTrue("os" in info, "extension API called in iframe"); + browser.test.assertTrue( + browser.extension.getBackgroundPage() === top, + "extension.getBackgroundPage() returns the top context" + ); + browser.test.sendMessage("iframe_done"); + }); + } + const extension = ExtensionTestUtils.loadExtension({ + manifest: { + background: { + page: "background.html", + }, + }, + files: { + "background.html": ` + + + `, + "background-subframe.html": ` + + + `, + "background-subframe.js": backgroundSubframeScript, + }, + }); + const bgWatcher = new BackgroundWatcher(); + await extension.startup(); + await extension.awaitMessage("iframe_done"); + Assert.equal(bgWatcher.bgBrowserCount, 1, "Got background page"); + Assert.equal(bgWatcher.bgViewCount, 1, "Got background view"); + Assert.equal( + extension.extension.views.size, + 2, + "Got ProxyContextParent instances for background and iframe" + ); + + Assert.equal( + extension.extension.backgroundContext?.uri?.spec, + `moz-extension://${extension.uuid}/background.html`, + `extension.backgroundContext should exist and point to the main background` + ); + + await extension.unload(); + bgWatcher.stopObserving(); +}); -- cgit v1.2.3