summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled_and_onStartup.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled_and_onStartup.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled_and_onStartup.js599
1 files changed, 599 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled_and_onStartup.js b/toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled_and_onStartup.js
new file mode 100644
index 0000000000..c330aaafde
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled_and_onStartup.js
@@ -0,0 +1,599 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+const { AddonManager } = ChromeUtils.importESModule(
+ "resource://gre/modules/AddonManager.sys.mjs"
+);
+const { Preferences } = ChromeUtils.importESModule(
+ "resource://gre/modules/Preferences.sys.mjs"
+);
+
+const {
+ createAppInfo,
+ createTempWebExtensionFile,
+ promiseAddonEvent,
+ promiseCompleteAllInstalls,
+ promiseFindAddonUpdates,
+ promiseRestartManager,
+ promiseShutdownManager,
+ promiseStartupManager,
+} = AddonTestUtils;
+
+AddonTestUtils.init(this);
+
+// Allow for unsigned addons.
+AddonTestUtils.overrideCertDB();
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "42", "42");
+
+function background() {
+ let onInstalledDetails = null;
+ let onStartupFired = false;
+ let eventPage = browser.runtime.getManifest().background.persistent === false;
+
+ browser.runtime.onInstalled.addListener(details => {
+ onInstalledDetails = details;
+ });
+
+ browser.runtime.onStartup.addListener(() => {
+ onStartupFired = true;
+ });
+
+ browser.test.onMessage.addListener(message => {
+ if (message === "get-on-installed-details") {
+ onInstalledDetails = onInstalledDetails || { fired: false };
+ browser.test.sendMessage("on-installed-details", onInstalledDetails);
+ } else if (message === "did-on-startup-fire") {
+ browser.test.sendMessage("on-startup-fired", onStartupFired);
+ } else if (message === "reload-extension") {
+ browser.runtime.reload();
+ }
+ });
+
+ browser.runtime.onUpdateAvailable.addListener(details => {
+ browser.test.sendMessage("reloading");
+ browser.runtime.reload();
+ });
+
+ if (eventPage) {
+ browser.runtime.onSuspend.addListener(() => {
+ browser.test.sendMessage("suspended");
+ });
+ // an event we use to restart the background
+ browser.browserSettings.homepageOverride.onChange.addListener(() => {
+ browser.test.sendMessage("homepageOverride");
+ });
+ }
+}
+
+async function expectEvents(
+ extension,
+ {
+ onStartupFired,
+ onInstalledFired,
+ onInstalledReason,
+ onInstalledTemporary,
+ onInstalledPrevious,
+ }
+) {
+ extension.sendMessage("get-on-installed-details");
+ let details = await extension.awaitMessage("on-installed-details");
+ if (onInstalledFired) {
+ equal(
+ details.reason,
+ onInstalledReason,
+ "runtime.onInstalled fired with the correct reason"
+ );
+ equal(
+ details.temporary,
+ onInstalledTemporary,
+ "runtime.onInstalled fired with the correct temporary flag"
+ );
+ if (onInstalledPrevious) {
+ equal(
+ details.previousVersion,
+ onInstalledPrevious,
+ "runtime.onInstalled after update with correct previousVersion"
+ );
+ }
+ } else {
+ equal(
+ details.fired,
+ onInstalledFired,
+ "runtime.onInstalled should not have fired"
+ );
+ }
+
+ extension.sendMessage("did-on-startup-fire");
+ let fired = await extension.awaitMessage("on-startup-fired");
+ equal(
+ fired,
+ onStartupFired,
+ `Expected runtime.onStartup to ${onStartupFired ? "" : "not "} fire`
+ );
+}
+
+add_task(async function test_should_fire_on_addon_update() {
+ Preferences.set("extensions.logging.enabled", false);
+
+ await promiseStartupManager();
+
+ const EXTENSION_ID =
+ "test_runtime_on_installed_addon_update@tests.mozilla.org";
+
+ const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
+
+ // The test extension uses an insecure update url.
+ Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+
+ const testServer = createHttpServer();
+ const port = testServer.identity.primaryPort;
+
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "permanent",
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION_ID,
+ update_url: `http://localhost:${port}/test_update.json`,
+ },
+ },
+ },
+ background,
+ });
+
+ testServer.registerPathHandler("/test_update.json", (request, response) => {
+ response.write(`{
+ "addons": {
+ "${EXTENSION_ID}": {
+ "updates": [
+ {
+ "version": "2.0",
+ "update_link": "http://localhost:${port}/addons/test_runtime_on_installed-2.0.xpi"
+ }
+ ]
+ }
+ }
+ }`);
+ });
+
+ let webExtensionFile = createTempWebExtensionFile({
+ manifest: {
+ version: "2.0",
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION_ID,
+ },
+ },
+ },
+ background,
+ });
+
+ testServer.registerFile(
+ "/addons/test_runtime_on_installed-2.0.xpi",
+ webExtensionFile
+ );
+
+ await extension.startup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: true,
+ onInstalledTemporary: false,
+ onInstalledReason: "install",
+ });
+
+ let addon = await AddonManager.getAddonByID(EXTENSION_ID);
+ equal(addon.version, "1.0", "The installed addon has the correct version");
+
+ let update = await promiseFindAddonUpdates(addon);
+ let install = update.updateAvailable;
+
+ let promiseInstalled = promiseAddonEvent("onInstalled");
+ await promiseCompleteAllInstalls([install]);
+
+ await extension.awaitMessage("reloading");
+
+ let [updated_addon] = await promiseInstalled;
+ equal(
+ updated_addon.version,
+ "2.0",
+ "The updated addon has the correct version"
+ );
+
+ await extension.awaitStartup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: true,
+ onInstalledTemporary: false,
+ onInstalledReason: "update",
+ onInstalledPrevious: "1.0",
+ });
+
+ await extension.unload();
+
+ await promiseShutdownManager();
+});
+
+add_task(async function test_should_fire_on_browser_update() {
+ const EXTENSION_ID =
+ "test_runtime_on_installed_browser_update@tests.mozilla.org";
+
+ await promiseStartupManager("1");
+
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "permanent",
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION_ID,
+ },
+ },
+ },
+ background,
+ });
+
+ await extension.startup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: true,
+ onInstalledTemporary: false,
+ onInstalledReason: "install",
+ });
+
+ // Restart the browser.
+ await promiseRestartManager("1");
+ await extension.awaitBackgroundStarted();
+
+ await expectEvents(extension, {
+ onStartupFired: true,
+ onInstalledFired: false,
+ });
+
+ // Update the browser.
+ await promiseRestartManager("2");
+ await extension.awaitBackgroundStarted();
+
+ await expectEvents(extension, {
+ onStartupFired: true,
+ onInstalledFired: true,
+ onInstalledTemporary: false,
+ onInstalledReason: "browser_update",
+ });
+
+ // Restart the browser.
+ await promiseRestartManager("2");
+ await extension.awaitBackgroundStarted();
+
+ await expectEvents(extension, {
+ onStartupFired: true,
+ onInstalledFired: false,
+ });
+
+ // Update the browser again.
+ await promiseRestartManager("3");
+ await extension.awaitBackgroundStarted();
+
+ await expectEvents(extension, {
+ onStartupFired: true,
+ onInstalledFired: true,
+ onInstalledTemporary: false,
+ onInstalledReason: "browser_update",
+ });
+
+ await extension.unload();
+
+ await promiseShutdownManager();
+});
+
+add_task(async function test_should_not_fire_on_reload() {
+ const EXTENSION_ID = "test_runtime_on_installed_reload@tests.mozilla.org";
+
+ await promiseStartupManager();
+
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "permanent",
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION_ID,
+ },
+ },
+ },
+ background,
+ });
+
+ await extension.startup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: true,
+ onInstalledTemporary: false,
+ onInstalledReason: "install",
+ });
+
+ extension.sendMessage("reload-extension");
+ extension.setRestarting();
+ await extension.awaitStartup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: false,
+ });
+
+ await extension.unload();
+ await promiseShutdownManager();
+});
+
+add_task(async function test_should_not_fire_on_restart() {
+ const EXTENSION_ID = "test_runtime_on_installed_restart@tests.mozilla.org";
+
+ await promiseStartupManager();
+
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "permanent",
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION_ID,
+ },
+ },
+ },
+ background,
+ });
+
+ await extension.startup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: true,
+ onInstalledTemporary: false,
+ onInstalledReason: "install",
+ });
+
+ let addon = await AddonManager.getAddonByID(EXTENSION_ID);
+ await addon.disable();
+ await addon.enable();
+ await extension.awaitStartup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: false,
+ });
+
+ await extension.unload();
+ await promiseShutdownManager();
+});
+
+add_task(async function test_temporary_installation() {
+ const EXTENSION_ID =
+ "test_runtime_on_installed_addon_temporary@tests.mozilla.org";
+
+ await promiseStartupManager();
+
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION_ID,
+ },
+ },
+ },
+ background,
+ });
+
+ await extension.startup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: true,
+ onInstalledReason: "install",
+ onInstalledTemporary: true,
+ });
+
+ await extension.unload();
+ await promiseShutdownManager();
+});
+
+add_task(
+ {
+ pref_set: [["extensions.eventPages.enabled", true]],
+ },
+ async function test_runtime_eventpage() {
+ const EXTENSION_ID = "test_runtime_eventpage@tests.mozilla.org";
+
+ await promiseStartupManager("1");
+
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "permanent",
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION_ID,
+ },
+ },
+ permissions: ["browserSettings"],
+ background: {
+ persistent: false,
+ },
+ },
+ background,
+ });
+
+ await extension.startup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: true,
+ onInstalledReason: "install",
+ onInstalledTemporary: false,
+ });
+
+ info(`test onInstall does not fire after suspend`);
+ // we do enough here that idle timeout causes intermittent failure.
+ // using terminateBackground results in the same code path tested.
+ extension.terminateBackground();
+ await extension.awaitMessage("suspended");
+ await promiseExtensionEvent(extension, "shutdown-background-script");
+
+ Services.prefs.setStringPref(
+ "browser.startup.homepage",
+ "http://test.example.com"
+ );
+ await extension.awaitMessage("homepageOverride");
+ // onStartup remains persisted, but not primed
+ assertPersistentListeners(extension, "runtime", "onStartup", {
+ primed: false,
+ persisted: true,
+ });
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: false,
+ });
+
+ info("test onStartup is not primed but background starts automatically");
+ await promiseRestartManager();
+ // onStartup is a bit special. During APP_STARTUP we do not
+ // prime this, we just start since it needs to.
+ assertPersistentListeners(extension, "runtime", "onStartup", {
+ primed: false,
+ persisted: true,
+ });
+ await extension.awaitBackgroundStarted();
+
+ info("test expectEvents");
+ await expectEvents(extension, {
+ onStartupFired: true,
+ onInstalledFired: false,
+ });
+
+ info("test onInstalled fired during browser update");
+ await promiseRestartManager("2");
+ assertPersistentListeners(extension, "runtime", "onStartup", {
+ primed: false,
+ persisted: true,
+ });
+ await extension.awaitBackgroundStarted();
+
+ await expectEvents(extension, {
+ onStartupFired: true,
+ onInstalledFired: true,
+ onInstalledReason: "browser_update",
+ onInstalledTemporary: false,
+ });
+
+ info(`test onStarted does not fire after suspend`);
+ extension.terminateBackground();
+ await extension.awaitMessage("suspended");
+ await promiseExtensionEvent(extension, "shutdown-background-script");
+
+ Services.prefs.setStringPref(
+ "browser.startup.homepage",
+ "http://homepage.example.com"
+ );
+ await extension.awaitMessage("homepageOverride");
+ // onStartup remains persisted, but not primed
+ assertPersistentListeners(extension, "runtime", "onStartup", {
+ primed: false,
+ persisted: true,
+ });
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: false,
+ });
+
+ await extension.unload();
+ await promiseShutdownManager();
+ }
+);
+
+// Verify we don't regress the issue related to runtime.onStartup persistent
+// listener being cleared from the startup data as part of priming all listeners
+// while terminating the event page on idle timeout (Bug 1796586).
+add_task(
+ {
+ pref_set: [["extensions.eventPages.enabled", true]],
+ },
+ async function test_runtime_onStartup_eventpage() {
+ const EXTENSION_ID = "test_eventpage_onStartup@tests.mozilla.org";
+
+ await promiseStartupManager();
+
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "permanent",
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: {
+ id: EXTENSION_ID,
+ },
+ },
+ permissions: ["browserSettings"],
+ background: {
+ persistent: false,
+ },
+ },
+ background,
+ });
+
+ await extension.startup();
+
+ await expectEvents(extension, {
+ onStartupFired: false,
+ onInstalledFired: true,
+ onInstalledReason: "install",
+ onInstalledTemporary: false,
+ });
+
+ info("Simulated idle timeout");
+ extension.terminateBackground();
+ await extension.awaitMessage("suspended");
+ await promiseExtensionEvent(extension, "shutdown-background-script");
+
+ // onStartup remains persisted, but not primed
+ assertPersistentListeners(extension, "runtime", "onStartup", {
+ primed: false,
+ persisted: true,
+ });
+
+ info(`test onStartup after restart`);
+ await promiseRestartManager();
+
+ // onStartup is a bit special. During APP_STARTUP we do not
+ // prime this, we just start since it needs to.
+ assertPersistentListeners(extension, "runtime", "onStartup", {
+ primed: false,
+ persisted: true,
+ });
+ await extension.awaitBackgroundStarted();
+
+ info("test expectEvents");
+ await expectEvents(extension, {
+ onStartupFired: true,
+ onInstalledFired: false,
+ });
+
+ extension.terminateBackground();
+ await extension.awaitMessage("suspended");
+ await promiseExtensionEvent(extension, "shutdown-background-script");
+ assertPersistentListeners(extension, "runtime", "onStartup", {
+ primed: false,
+ persisted: true,
+ });
+
+ await extension.unload();
+ await promiseShutdownManager();
+ }
+);