Reputation: 2177
I found this where and extension A is able to uninstall extension B: Uninstall/Remove Firefox Extension programmatically?
I wonder if the same method would also work for an extension to uninstall itself (e.g., if it senses a superior extension that supersedes it)? The following code is my simple adaption of the answer to the above linked question:
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID("supersedes-me@id", function(betteraddon) {
if (betteraddon) {
AddonManager.getAddonById("my-own@id", function(thisaddon) {
if (!thisaddon) {
// this Add-on not present? Should not happen ...
return;
}
if (!(thisaddon.permissions & AddonManager.PERM_CAN_UNINSTALL)) {
// Add-on cannot be uninstalled
return;
}
thisaddon.uninstall();
if (thisaddon.pendingOperations & AddonManager.PENDING_UNINSTALL) {
// Need to restart to finish the uninstall.
// Might ask the user to do just that. Or not ask and just do.
// Or just wait until the browser is restarted by the user.
}
});
}
});
This sounds dangerous as the self-uninstalling addon is at least waiting for the return to the call from its own uninstall ... But is this approach really so dangerous? After all, nowadays uninstall is even undo-able, which means that an uninstalled addon is "still there" for a while .. ?
Upvotes: 1
Views: 350
Reputation: 43
The AddonManager API is deprecated since it would be a security issue for add-ons to remove other add-ons. The new way for an extension to remove itself is using management.uninstallSelf()
browser.management.uninstallSelf({
showConfirmDialog: true,
dialogMessage: 'Please reconsider, since this is the best extension!'
}).then(() => alert('Extension uninstalled'))
.catch(() => alert('User cancelled extension uninstall'))
If showConfirmDiloag
is true, the user is prompted with a confirmation dialog.
If the user chooses to keep the extension, the Promise returned by uninstallSelf returns an error.
Both properties in the argument object are optional.
Upvotes: 0
Reputation: 33306
Yes, an extension can uninstall itself using AddonManager.jsm. You can get an Addon object, using getAddonByID()
, which has an uninstall()
method. In other words, more or less how you coded it in your question.
Below is an Add-on SDK extension that uninstalls itself. When installed, it briefly appears in about:addons
, but then disappears. It produces the following output in the console when installed from an .xpi file:
uninstallself:My ID=@uninstallself
uninstallself:This add-on is being loaded for reason= install
uninstallself:Going to uninstall myself
uninstallself:This add-on is being unloaded for reason= uninstall
uninstallself:Called uninstall on myself
If invoked using jpm run
it also outputs an additional two lines of errors which indicate that a file can not be removed. That file is the temporary .xpi file created by jpm run
.
package.json:
{
"title": "Test Self Uninstall",
"name": "uninstallself",
"version": "0.0.1",
"description": "Test an add-on uninstalling itself",
"main": "index.js",
"author": "Makyen",
"engines": {
"firefox": ">=38.0a1",
"fennec": ">=38.0a1"
},
"license": "MIT",
"keywords": [
"jetpack"
]
}
index.js:
/* Firefox Add-on SDK uninstall self */
const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
var self = require("sdk/self");
var myId = self.id;
var utils = require('sdk/window/utils');
activeWin = utils.getMostRecentBrowserWindow();
// Using activeWin.console.log() is needed to have output to the
// Browser Console when installed as an .xpi file. In that case,
// console is mapped to dump(), which does not output to the console.
// This is done to not polute the console from SDK add-ons that are
// logging information when they should not. Using jpm run,
// console.log outputs to the Browser Console.
activeWin.console.log('My ID=' +myId);
exports.main = function (options) {
activeWin = utils.getMostRecentBrowserWindow();
activeWin.console.log('This add-on is being loaded for reason=', options.loadReason);
};
exports.onUnload = function (reason) {
activeWin.console.log('This add-on is being unloaded for reason=',reason);
};
AddonManager.getAddonByID(myId,addon => {
if(addon && typeof addon.uninstall === 'function'){
activeWin.console.log('Going to uninstall myself');
addon.uninstall();
activeWin.console.log('Called uninstall on myself');
}
});
Upvotes: 2