diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /devtools/server/tests/xpcshell/webextension-helpers.js | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/server/tests/xpcshell/webextension-helpers.js')
-rw-r--r-- | devtools/server/tests/xpcshell/webextension-helpers.js | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/devtools/server/tests/xpcshell/webextension-helpers.js b/devtools/server/tests/xpcshell/webextension-helpers.js new file mode 100644 index 0000000000..46968f09e7 --- /dev/null +++ b/devtools/server/tests/xpcshell/webextension-helpers.js @@ -0,0 +1,197 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* globals browser */ + +"use strict"; + +/** + * Test helpers shared by the devtools server xpcshell tests related to webextensions. + */ + +const { FileUtils } = ChromeUtils.importESModule( + "resource://gre/modules/FileUtils.sys.mjs" +); +const { ExtensionTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/ExtensionXPCShellUtils.sys.mjs" +); + +const { + CommandsFactory, +} = require("resource://devtools/shared/commands/commands-factory.js"); + +/** + * Loads and starts up a test extension given the provided extension configuration. + * + * @param {Object} extConfig - The extension configuration object + * @return {ExtensionWrapper} extension - Resolves with an extension object once the + * extension has started up. + */ +async function startupExtension(extConfig) { + const extension = ExtensionTestUtils.loadExtension(extConfig); + + await extension.startup(); + + return extension; +} +exports.startupExtension = startupExtension; + +/** + * Initializes the extensionStorage actor for a given extension. This is effectively + * what happens when the addon storage panel is opened in the browser. + * + * @param {String} - id, The addon id + * @return {Object} - Resolves with the DevTools "commands" objact and the extensionStorage + * resource/front. + */ +async function openAddonStoragePanel(id) { + const commands = await CommandsFactory.forAddon(id); + await commands.targetCommand.startListening(); + + // Fetch the EXTENSION_STORAGE resource. + // Unfortunately, we can't use resourceCommand.waitForNextResource as it would destroy + // the actor by immediately unwatching for the resource type. + const extensionStorage = await new Promise(resolve => { + commands.resourceCommand.watchResources( + [commands.resourceCommand.TYPES.EXTENSION_STORAGE], + { + onAvailable(resources) { + resolve(resources[0]); + }, + } + ); + }); + + return { commands, extensionStorage }; +} +exports.openAddonStoragePanel = openAddonStoragePanel; + +/** + * Builds the extension configuration object passed into ExtensionTestUtils.loadExtension + * + * @param {Object} options - Options, if any, to add to the configuration + * @param {Function} options.background - A function comprising the test extension's + * background script if provided + * @param {Object} options.files - An object whose keys correspond to file names and + * values map to the file contents + * @param {Object} options.manifest - An object representing the extension's manifest + * @return {Object} - The extension configuration object + */ +function getExtensionConfig(options = {}) { + const { manifest, ...otherOptions } = options; + const baseConfig = { + manifest: { + ...manifest, + permissions: ["storage"], + }, + useAddonManager: "temporary", + }; + return { + ...baseConfig, + ...otherOptions, + }; +} +exports.getExtensionConfig = getExtensionConfig; + +/** + * Shared files for a test extension that has no background page but adds storage + * items via a transient extension page in a tab + */ +const ext_no_bg = { + files: { + "extension_page_in_tab.html": `<!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + </head> + <body> + <h1>Extension Page in a Tab</h1> + <script src="extension_page_in_tab.js"></script> + </body> + </html>`, + "extension_page_in_tab.js": extensionScriptWithMessageListener, + }, +}; +exports.ext_no_bg = ext_no_bg; + +/** + * An extension script that can be used in any extension context (e.g. as a background + * script or as an extension page script loaded in a tab). + */ +async function extensionScriptWithMessageListener() { + let fireOnChanged = false; + browser.storage.onChanged.addListener(() => { + if (fireOnChanged) { + // Do not fire it again until explicitly requested again using the "storage-local-fireOnChanged" test message. + fireOnChanged = false; + browser.test.sendMessage("storage-local-onChanged"); + } + }); + + browser.test.onMessage.addListener(async (msg, ...args) => { + let item = null; + switch (msg) { + case "storage-local-set": + await browser.storage.local.set(args[0]); + break; + case "storage-local-get": + item = await browser.storage.local.get(args[0]); + break; + case "storage-local-remove": + await browser.storage.local.remove(args[0]); + break; + case "storage-local-clear": + await browser.storage.local.clear(); + break; + case "storage-local-fireOnChanged": { + // Allow the storage.onChanged listener to send a test event + // message when onChanged is being fired. + fireOnChanged = true; + // Do not fire fireOnChanged:done. + return; + } + default: + browser.test.fail(`Unexpected test message: ${msg}`); + } + + browser.test.sendMessage(`${msg}:done`, item); + }); + // window is available in background scripts + // eslint-disable-next-line no-undef + browser.test.sendMessage("extension-origin", window.location.origin); +} +exports.extensionScriptWithMessageListener = extensionScriptWithMessageListener; + +/** + * Shutdown procedure common to all tasks. + * + * @param {Object} extension - The test extension + * @param {Object} commands - The web extension commands used by the DevTools to interact with the backend + */ +async function shutdown(extension, commands) { + if (commands) { + await commands.destroy(); + } + await extension.unload(); +} +exports.shutdown = shutdown; + +/** + * Mocks the missing 'storage/permanent' directory needed by the "indexedDB" + * storage actor's 'populateStoresForHosts' method. This + * directory exists in a full browser i.e. mochitest. + */ +function createMissingIndexedDBDirs() { + const dir = Services.dirsvc.get("ProfD", Ci.nsIFile).clone(); + dir.append("storage"); + if (!dir.exists()) { + dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + } + dir.append("permanent"); + if (!dir.exists()) { + dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + } + + return dir; +} +exports.createMissingIndexedDBDirs = createMissingIndexedDBDirs; |