--- 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();
+});