gecko/addon-sdk/source/lib/sdk/addon/installer.js

107 lines
3.0 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module.metadata = {
"stability": "experimental"
};
const { Cc, Ci, Cu } = require("chrome");
const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
const { defer } = require("../core/promise");
const { setTimeout } = require("../timers");
/**
* `install` method error codes:
*
* https://developer.mozilla.org/en/Addons/Add-on_Manager/AddonManager#AddonInstall_errors
*/
exports.ERROR_NETWORK_FAILURE = AddonManager.ERROR_NETWORK_FAILURE;
exports.ERROR_INCORRECT_HASH = AddonManager.ERROR_INCORRECT_HASH;
exports.ERROR_CORRUPT_FILE = AddonManager.ERROR_CORRUPT_FILE;
exports.ERROR_FILE_ACCESS = AddonManager.ERROR_FILE_ACCESS;
/**
* Immediatly install an addon.
*
* @param {String} xpiPath
* file path to an xpi file to install
* @return {Promise}
* A promise resolved when the addon is finally installed.
* Resolved with addon id as value or rejected with an error code.
*/
exports.install = function install(xpiPath) {
let { promise, resolve, reject } = defer();
// Create nsIFile for the xpi file
let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
try {
file.initWithPath(xpiPath);
}
catch(e) {
reject(exports.ERROR_FILE_ACCESS);
return promise;
}
// Listen for installation end
let listener = {
onInstallEnded: function(aInstall, aAddon) {
aInstall.removeListener(listener);
// Bug 749745: on FF14+, onInstallEnded is called just before `startup()`
// is called, but we expect to resolve the promise only after it.
// As startup is called synchronously just after onInstallEnded,
// a simple setTimeout(0) is enough
setTimeout(resolve, 0, aAddon.id);
},
onInstallFailed: function (aInstall) {
console.log("failed");
aInstall.removeListener(listener);
reject(aInstall.error);
},
onDownloadFailed: function(aInstall) {
this.onInstallFailed(aInstall);
}
};
// Order AddonManager to install the addon
AddonManager.getInstallForFile(file, function(install) {
install.addListener(listener);
install.install();
});
return promise;
};
exports.uninstall = function uninstall(addonId) {
let { promise, resolve, reject } = defer();
// Listen for uninstallation end
let listener = {
onUninstalled: function onUninstalled(aAddon) {
if (aAddon.id != addonId)
return;
AddonManager.removeAddonListener(listener);
resolve();
}
};
AddonManager.addAddonListener(listener);
// Order Addonmanager to uninstall the addon
AddonManager.getAddonByID(addonId, function (addon) {
addon.uninstall();
});
return promise;
};
exports.disable = function disable(addonId) {
let { promise, resolve, reject } = defer();
AddonManager.getAddonByID(addonId, function (addon) {
addon.userDisabled = true;
resolve();
});
return promise;
};