Bug 1354590 - Add 'temporary' flag to runtime.onInstalled details. r?aswan, zombie draft
authorTushar Saini (:shatur) <tushar.saini1285@gmail.com>
Sun, 14 May 2017 10:54:11 +0530
changeset 577458 fea05b57fe2e8d17a357363481c1f066312a2460
parent 577456 73b3fc64525b6816842c737e104ef2ac5482d217
child 628499 9f403b77d4140c9ebdc2f90e653a8dd187741396
push id58689
push userbmo:tushar.saini1285@gmail.com
push dateSun, 14 May 2017 05:35:24 +0000
reviewersaswan, zombie
bugs1354590
milestone55.0a1
Bug 1354590 - Add 'temporary' flag to runtime.onInstalled details. r?aswan, zombie MozReview-Commit-ID: IbQno1ZL7KV
toolkit/components/extensions/ext-runtime.js
toolkit/components/extensions/schemas/runtime.json
toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled_and_onStartup.js
toolkit/mozapps/extensions/internal/XPIProvider.jsm
--- a/toolkit/components/extensions/ext-runtime.js
+++ b/toolkit/components/extensions/ext-runtime.js
@@ -28,28 +28,34 @@ this.runtime = class extends ExtensionAP
           };
           extension.on("startup", listener);
           return () => {
             extension.off("startup", listener);
           };
         }).api(),
 
         onInstalled: new SingletonEventManager(context, "runtime.onInstalled", fire => {
+          let temporary = !!extension.addonData.temporarilyInstalled;
+
           let listener = () => {
             switch (extension.startupReason) {
               case "APP_STARTUP":
                 if (AddonManagerPrivate.browserUpdated) {
-                  fire.sync({reason: "browser_update"});
+                  fire.sync({reason: "browser_update", temporary});
                 }
                 break;
               case "ADDON_INSTALL":
-                fire.sync({reason: "install"});
+                fire.sync({reason: "install", temporary});
                 break;
               case "ADDON_UPGRADE":
-                fire.sync({reason: "update", previousVersion: extension.addonData.oldVersion});
+                fire.sync({
+                  reason: "update",
+                  previousVersion: extension.addonData.oldVersion,
+                  temporary,
+                });
                 break;
             }
           };
           extension.on("startup", listener);
           return () => {
             extension.off("startup", listener);
           };
         }).api(),
--- a/toolkit/components/extensions/schemas/runtime.json
+++ b/toolkit/components/extensions/schemas/runtime.json
@@ -470,16 +470,20 @@
                 "$ref": "OnInstalledReason",
                 "description": "The reason that this event is being dispatched."
               },
               "previousVersion": {
                 "type": "string",
                 "optional": true,
                 "description": "Indicates the previous version of the extension, which has just been updated. This is present only if 'reason' is 'update'."
               },
+              "temporary": {
+                "type": "boolean",
+                "description": "Indicates whether the addon is installed as a temporary extension."
+              },
               "id": {
                 "type": "string",
                 "optional": true,
                 "unsupported": true,
                 "description": "Indicates the ID of the imported shared module extension which updated. This is present only if 'reason' is 'shared_module_update'."
               }
             }
           }
--- 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
@@ -52,21 +52,22 @@ function background() {
   });
 
   browser.runtime.onUpdateAvailable.addListener(details => {
     browser.test.sendMessage("reloading");
     browser.runtime.reload();
   });
 }
 
-async function expectEvents(extension, {onStartupFired, onInstalledFired, onInstalledReason, onInstalledPrevious}) {
+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");
@@ -132,16 +133,17 @@ add_task(async function test_should_fire
 
   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;
@@ -154,16 +156,17 @@ add_task(async function test_should_fire
   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();
 });
@@ -186,16 +189,17 @@ add_task(async function test_should_fire
     background,
   });
 
   await extension.startup();
 
   await expectEvents(extension, {
     onStartupFired: false,
     onInstalledFired: true,
+    onInstalledTemporary: false,
     onInstalledReason: "install",
   });
 
   await promiseRestartManager("1");
 
   await extension.awaitStartup();
 
   await expectEvents(extension, {
@@ -205,16 +209,17 @@ add_task(async function test_should_fire
 
   // Update the browser.
   await promiseRestartManager("2");
   await extension.awaitStartup();
 
   await expectEvents(extension, {
     onStartupFired: true,
     onInstalledFired: true,
+    onInstalledTemporary: false,
     onInstalledReason: "browser_update",
   });
 
   // Restart the browser.
   await promiseRestartManager("2");
   await extension.awaitStartup();
 
   await expectEvents(extension, {
@@ -224,16 +229,17 @@ add_task(async function test_should_fire
 
   // Update the browser again.
   await promiseRestartManager("3");
   await extension.awaitStartup();
 
   await expectEvents(extension, {
     onStartupFired: true,
     onInstalledFired: true,
+    onInstalledTemporary: false,
     onInstalledReason: "browser_update",
   });
 
   await extension.unload();
 
   await promiseShutdownManager();
 });
 
@@ -255,16 +261,17 @@ add_task(async function test_should_not_
     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, {
@@ -294,16 +301,17 @@ add_task(async function test_should_not_
     background,
   });
 
   await extension.startup();
 
   await expectEvents(extension, {
     onStartupFired: false,
     onInstalledFired: true,
+    onInstalledTemporary: false,
     onInstalledReason: "install",
   });
 
   let addon = await AddonManager.getAddonByID(EXTENSION_ID);
   addon.userDisabled = true;
 
   addon.userDisabled = false;
   await extension.awaitStartup();
@@ -311,8 +319,39 @@ add_task(async function test_should_not_
   await expectEvents(extension, {
     onStartupFired: false,
     onInstalledFired: false,
   });
 
   await extension.markUnloaded();
   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",
+      "applications": {
+        "gecko": {
+          "id": EXTENSION_ID,
+        },
+      },
+    },
+    background,
+  });
+
+  await extension.startup();
+
+  await expectEvents(extension, {
+    onStartupFired: false,
+    onInstalledFired: true,
+    onInstalledReason: "install",
+    onInstalledTemporary: true,
+  });
+
+  await extension.unload();
+  await promiseShutdownManager();
+});
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -4136,16 +4136,17 @@ this.XPIProvider = {
       throw new Error("Only restartless (bootstrap) add-ons"
                     + " can be installed from sources:", addon.id);
     }
     let installReason = BOOTSTRAP_REASONS.ADDON_INSTALL;
     let oldAddon = await new Promise(
                    resolve => XPIDatabase.getVisibleAddonForID(addon.id, resolve));
 
     let extraParams = {};
+    extraParams.temporarilyInstalled = aInstallLocation === TemporaryInstallLocation;
     if (oldAddon) {
       if (!oldAddon.bootstrap) {
         logger.warn("Non-restartless Add-on is already installed", addon.id);
         throw new Error("Non-restartless add-on with ID "
                         + oldAddon.id + " is already installed");
       } else {
         logger.warn("Addon with ID " + oldAddon.id + " already installed,"
                     + " older version will be disabled");