/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; /** * Note: this test used to be in test_extension_storage_actor.js, but seems to * fail frequently as soon as we start auto-attaching targets. * See Bug 1618059. */ const { ExtensionTestUtils } = ChromeUtils.importESModule( "resource://testing-common/ExtensionXPCShellUtils.sys.mjs" ); const { createMissingIndexedDBDirs, extensionScriptWithMessageListener, getExtensionConfig, openAddonStoragePanel, shutdown, startupExtension, } = require("resource://test/webextension-helpers.js"); const l10n = new Localization(["devtools/client/storage.ftl"], true); const sessionString = l10n.formatValueSync("storage-expires-session"); // Ignore rejection related to the storage.onChanged listener being removed while the extension context is being closed. const { PromiseTestUtils } = ChromeUtils.importESModule( "resource://testing-common/PromiseTestUtils.sys.mjs" ); PromiseTestUtils.allowMatchingRejectionsGlobally( /Message manager disconnected/ ); const { createAppInfo, promiseStartupManager } = AddonTestUtils; AddonTestUtils.init(this); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); ExtensionTestUtils.init(this); add_task(async function setup() { await promiseStartupManager(); const dir = createMissingIndexedDBDirs(); Assert.ok( dir.exists(), "Should have a 'storage/permanent' dir in the profile dir" ); }); /** * Test case: Bg page adds an item to storage. With storage panel open, reload extension. * - Load extension with background page that adds a storage item on message. * - Open the add-on storage panel. * - With the storage panel still open, reload the extension. * - The data in the storage panel should match the item added prior to reloading. */ add_task(async function test_panel_live_reload() { const EXTENSION_ID = "test_panel_live_reload@xpcshell.mozilla.org"; let manifest = { version: "1.0", browser_specific_settings: { gecko: { id: EXTENSION_ID, }, }, }; info("Loading extension version 1.0"); const extension = await startupExtension( getExtensionConfig({ manifest, background: extensionScriptWithMessageListener, }) ); info("Waiting for message from test extension"); const host = await extension.awaitMessage("extension-origin"); info("Adding storage item"); extension.sendMessage("storage-local-set", { a: 123 }); await extension.awaitMessage("storage-local-set:done"); const { commands, extensionStorage } = await openAddonStoragePanel( extension.id ); manifest = { ...manifest, version: "2.0", }; // "Reload" is most similar to an upgrade, as e.g. storage data is preserved info("Update to version 2.0"); // Wait for the storage front to receive an event for the storage panel refresh // when the extension has been reloaded. const promiseStoragePanelUpdated = new Promise(resolve => { extensionStorage.on( "single-store-update", function updateListener(updates) { info(`Got stores-update event: ${JSON.stringify(updates)}`); const extStorageAdded = updates.added?.extensionStorage; if (host in extStorageAdded && extStorageAdded[host].length) { extensionStorage.off("single-store-update", updateListener); resolve(); } } ); }); await extension.upgrade( getExtensionConfig({ manifest, background: extensionScriptWithMessageListener, }) ); await Promise.all([ extension.awaitMessage("extension-origin"), promiseStoragePanelUpdated, ]); const { data } = await extensionStorage.getStoreObjects(host, null, { sessionString, }); Assert.deepEqual( data, [ { area: "local", name: "a", value: { str: "123" }, isValueEditable: true, }, ], "Got the expected results on populated storage.local" ); await shutdown(extension, commands); });