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_ext_eventpage_messaging_wakeup.js | 329 +++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 toolkit/components/extensions/test/xpcshell/test_ext_eventpage_messaging_wakeup.js (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_eventpage_messaging_wakeup.js') diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_eventpage_messaging_wakeup.js b/toolkit/components/extensions/test/xpcshell/test_ext_eventpage_messaging_wakeup.js new file mode 100644 index 0000000000..dc0c9d051a --- /dev/null +++ b/toolkit/components/extensions/test/xpcshell/test_ext_eventpage_messaging_wakeup.js @@ -0,0 +1,329 @@ +"use strict"; + +// This test checks that the event page is awakened as expected when a +// extension messaging event is triggered. +// - onMessage / onConnect: triggered by the extension's own extension page. +// - onMessage / onConnect: triggered by the extension's own content script. +// - onMessageExternal / onConnectExternal: triggered by another extension. +// +// Note: the behavior in persistent background scripts (at browser startup) is +// covered by test_ext_messaging_startup.js. +// +// These events delay suspend of the event page, which is partially verified by +// test_ext_eventpage_messaging.js. + +const { ExtensionTestCommon } = ChromeUtils.importESModule( + "resource://testing-common/ExtensionTestCommon.sys.mjs" +); + +const server = createHttpServer({ hosts: ["example.com"] }); +server.registerPathHandler("/dummy", (request, response) => { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html", false); +}); + +async function testEventPageWakeup({ + backgroundScript, + triggerScript, + triggerFromContentScript = false, // default to calling from extension page. + triggerFromOtherExtension = false, // default to calling from own extension. + skipInitialPriming = false, // default to start+suspend before starting test. +}) { + function loadExtension(id, withBackground, withTrigger) { + let extensionData = { + manifest: { browser_specific_settings: { gecko: { id } } }, + }; + if (withBackground) { + extensionData.manifest.background = { persistent: false }; + extensionData.background = backgroundScript; + if (skipInitialPriming) { + // Delay event page startup until an explicit event. + extensionData.startupReason = "APP_STARTUP"; + // APP_STARTUP is not enough, delayedStartup is needed (bug 1756225). + extensionData.delayedStartup = true; + } + } + if (withTrigger) { + extensionData.files = { + "trigger.html": ``, + "trigger.js": triggerScript, + }; + if (triggerFromContentScript) { + // trigger.html unused, use content script instead: + extensionData.manifest.content_scripts = [ + { + js: ["trigger.js"], + run_at: "document_end", + matches: ["http://example.com/dummy"], + }, + ]; + } + } + return ExtensionTestUtils.loadExtension(extensionData); + } + + await ExtensionTestCommon.resetStartupPromises(); + // Event-triggered wakeup is blocked on browserPaintedPromise, so unblock it: + await ExtensionTestCommon.notifyEarlyStartup(); + + let extension = loadExtension("@ext", true, !triggerFromOtherExtension); + await extension.startup(); + if (!skipInitialPriming) { + // Default test behavior is ADDON_INSTALL, which starts up the background. + Assert.equal(extension.extension.backgroundState, "running", "Bg started"); + // Not strictly needed because the background has already started. But to + // more closely match reality, flag as fully started. + await ExtensionTestCommon.notifyLateStartup(); + // Suspend event page so we can verify that it wakes up by triggerScript. + await extension.terminateBackground(); + Assert.equal(extension.extension.backgroundState, "stopped", "Bg closed"); + } else { + // Event page initially suspended, waiting for event. + Assert.equal(extension.extension.backgroundState, "stopped", "Bg inactive"); + } + + let extension2; + if (triggerFromOtherExtension) { + extension2 = loadExtension("@other-ext", false, true); + await extension2.startup(); + } + + let url; + if (triggerFromContentScript) { + url = "http://example.com/dummy"; + } else if (triggerFromOtherExtension) { + url = `moz-extension://${extension2.uuid}/trigger.html`; + } else { + url = `moz-extension://${extension.uuid}/trigger.html`; + } + let contentPage = await ExtensionTestUtils.loadContentPage(url); + info("Waiting for event page to be awakened by event"); + await extension.awaitMessage("TRIGGER_TEST_DONE"); + // Unload test extensions first to avoid an issue on Windows platforms. + await extension.unload(); + if (triggerFromOtherExtension) { + await extension2.unload(); + } + await contentPage.close(); +} + +add_task(async function test_sendMessage_without_onMessage() { + await testEventPageWakeup({ + backgroundScript() { + // No runtime.onMessage listener here. + }, + async triggerScript() { + browser.test.assertTrue( + !browser.extension.getBackgroundPage(), + "Event page suspended before sendMessage()" + ); + await browser.test.assertRejects( + browser.runtime.sendMessage(""), + "Could not establish connection. Receiving end does not exist.", + "sendMessage without onMessage should reject" + ); + browser.test.assertTrue( + // TODO bug 1852317: This should be "!" instead of "!!", i.e. the event + // page should not wake up. + !!browser.extension.getBackgroundPage(), + "Existence of event page after sendMessage()" + ); + browser.test.sendMessage("TRIGGER_TEST_DONE"); + }, + // For completeness, start background before suspending. This makes sure + // that if the persistent listener mechanism is used for runtime.onMessage, + // that we have started the background at least once to enable the + // framework to detect (the lack of) persistent listeners, so that it can + // know that waking the event page doesn't make a difference. + // (note: persistent listeners are currently not used here: bug 1852317) + skipInitialPriming: false, + }); +}); + +add_task(async function test_connect_without_onConnect() { + await testEventPageWakeup({ + backgroundScript() { + // No runtime.onConnect listener here. + }, + triggerScript() { + browser.test.assertTrue( + !browser.extension.getBackgroundPage(), + "Event page suspended before sendMessage()" + ); + let port = browser.runtime.connect({}); + port.onDisconnect.addListener(() => { + browser.test.assertEq( + "Could not establish connection. Receiving end does not exist.", + port.error?.message, + "connect() without onConnect should disconnect port with an error" + ); + browser.test.assertTrue( + // TODO bug 1852317: This should be "!" instead of "!!", i.e. the + // event page should not wake up. + !!browser.extension.getBackgroundPage(), + "Existence of event page after connect()" + ); + browser.test.sendMessage("TRIGGER_TEST_DONE"); + }); + }, + // For completeness, start background before suspending. This makes sure + // that if the persistent listener mechanism is used for runtime.onConnect, + // that we have started the background at least once to enable the + // framework to detect (the lack of) persistent listeners, so that it can + // know that waking the event page doesn't make a difference. + // (note: persistent listeners are currently not used here: bug 1852317) + skipInitialPriming: false, + }); +}); + +async function testEventPageWakeupWithSendMessage({ + triggerFromContentScript, + triggerFromOtherExtension, + skipInitialPriming, +}) { + let backgroundScript, triggerScript; + // Note: using dump() instead of browser.test.log for logging, to rule out + // any side effects from extension API calls. + if (triggerFromOtherExtension) { + backgroundScript = () => { + dump("Event page started, listening to onMessageExternal\n"); + browser.runtime.onMessageExternal.addListener(() => { + browser.test.sendMessage("TRIGGER_TEST_DONE"); + }); + }; + triggerScript = () => { + dump("Calling sendMessage, expecting onMessageExternal\n"); + browser.runtime.sendMessage("@ext", "msg"); + }; + } else { + backgroundScript = () => { + dump("Event page started, listening to onMessage\n"); + browser.runtime.onMessage.addListener(() => { + browser.test.sendMessage("TRIGGER_TEST_DONE"); + }); + }; + triggerScript = () => { + dump("Calling sendMessage, expecting onMessage\n"); + browser.runtime.sendMessage("msg"); + }; + } + await testEventPageWakeup({ + backgroundScript, + triggerScript, + triggerFromContentScript, + triggerFromOtherExtension, + skipInitialPriming, + }); +} + +add_task(async function test_wakeup_onMessage() { + await testEventPageWakeupWithSendMessage({ + triggerFromContentScript: false, + triggerFromOtherExtension: false, + }); +}); + +add_task(async function test_wakeup_onMessage_on_first_run() { + await testEventPageWakeupWithSendMessage({ + triggerFromContentScript: false, + triggerFromOtherExtension: false, + skipInitialPriming: true, + }); +}); + +add_task(async function test_wakeup_onMessage_by_content_script() { + await testEventPageWakeupWithSendMessage({ + triggerFromContentScript: true, + triggerFromOtherExtension: false, + }); +}); + +add_task(async function test_wakeup_onMessageExternal() { + await testEventPageWakeupWithSendMessage({ + triggerFromContentScript: false, + triggerFromOtherExtension: true, + }); +}); + +add_task(async function test_wakeup_onMessageExternal_by_content_script() { + await testEventPageWakeupWithSendMessage({ + triggerFromContentScript: true, + triggerFromOtherExtension: true, + }); +}); + +async function testEventPageWakeupWithConnect({ + triggerFromContentScript, + triggerFromOtherExtension, + skipInitialPriming, +}) { + let backgroundScript, triggerScript; + // Note: using dump() instead of browser.test.log for logging, to rule out + // any side effects from extension API calls. + if (triggerFromOtherExtension) { + backgroundScript = () => { + dump("Event page started, listening to onConnectExternal\n"); + browser.runtime.onConnectExternal.addListener(() => { + browser.test.sendMessage("TRIGGER_TEST_DONE"); + }); + }; + triggerScript = () => { + dump("Calling connect, expecting onConnectExternal\n"); + browser.runtime.connect("@ext", {}); + }; + } else { + backgroundScript = () => { + dump("Event page started, listening to onConnect\n"); + browser.runtime.onConnect.addListener(() => { + browser.test.sendMessage("TRIGGER_TEST_DONE"); + }); + }; + triggerScript = () => { + dump("Calling connect, expecting onConnect\n"); + browser.runtime.connect({}); + }; + } + await testEventPageWakeup({ + backgroundScript, + triggerScript, + triggerFromContentScript, + triggerFromOtherExtension, + skipInitialPriming, + }); +} + +add_task(async function test_wakeup_onConnect() { + await testEventPageWakeupWithConnect({ + triggerFromContentScript: false, + triggerFromOtherExtension: false, + }); +}); + +add_task(async function test_wakeup_onConnect_on_first_run() { + await testEventPageWakeupWithConnect({ + triggerFromContentScript: false, + triggerFromOtherExtension: false, + skipInitialPriming: true, + }); +}); + +add_task(async function test_wakeup_onConnect_by_content_script() { + await testEventPageWakeupWithConnect({ + triggerFromContentScript: true, + triggerFromOtherExtension: false, + }); +}); + +add_task(async function test_wakeup_onConnectExternal() { + await testEventPageWakeupWithConnect({ + triggerFromContentScript: false, + triggerFromOtherExtension: true, + }); +}); + +add_task(async function test_wakeup_onConnectExternal_by_content_script() { + await testEventPageWakeupWithConnect({ + triggerFromContentScript: true, + triggerFromOtherExtension: true, + }); +}); -- cgit v1.2.3