1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/addon/installer.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,121 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +module.metadata = { 1.9 + "stability": "experimental" 1.10 +}; 1.11 + 1.12 +const { Cc, Ci, Cu } = require("chrome"); 1.13 +const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm"); 1.14 +const { defer } = require("../core/promise"); 1.15 +const { setTimeout } = require("../timers"); 1.16 + 1.17 +/** 1.18 + * `install` method error codes: 1.19 + * 1.20 + * https://developer.mozilla.org/en/Addons/Add-on_Manager/AddonManager#AddonInstall_errors 1.21 + */ 1.22 +exports.ERROR_NETWORK_FAILURE = AddonManager.ERROR_NETWORK_FAILURE; 1.23 +exports.ERROR_INCORRECT_HASH = AddonManager.ERROR_INCORRECT_HASH; 1.24 +exports.ERROR_CORRUPT_FILE = AddonManager.ERROR_CORRUPT_FILE; 1.25 +exports.ERROR_FILE_ACCESS = AddonManager.ERROR_FILE_ACCESS; 1.26 + 1.27 +/** 1.28 + * Immediatly install an addon. 1.29 + * 1.30 + * @param {String} xpiPath 1.31 + * file path to an xpi file to install 1.32 + * @return {Promise} 1.33 + * A promise resolved when the addon is finally installed. 1.34 + * Resolved with addon id as value or rejected with an error code. 1.35 + */ 1.36 +exports.install = function install(xpiPath) { 1.37 + let { promise, resolve, reject } = defer(); 1.38 + 1.39 + // Create nsIFile for the xpi file 1.40 + let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile); 1.41 + try { 1.42 + file.initWithPath(xpiPath); 1.43 + } 1.44 + catch(e) { 1.45 + reject(exports.ERROR_FILE_ACCESS); 1.46 + return promise; 1.47 + } 1.48 + 1.49 + // Listen for installation end 1.50 + let listener = { 1.51 + onInstallEnded: function(aInstall, aAddon) { 1.52 + aInstall.removeListener(listener); 1.53 + // Bug 749745: on FF14+, onInstallEnded is called just before `startup()` 1.54 + // is called, but we expect to resolve the promise only after it. 1.55 + // As startup is called synchronously just after onInstallEnded, 1.56 + // a simple setTimeout(0) is enough 1.57 + setTimeout(resolve, 0, aAddon.id); 1.58 + }, 1.59 + onInstallFailed: function (aInstall) { 1.60 + console.log("failed"); 1.61 + aInstall.removeListener(listener); 1.62 + reject(aInstall.error); 1.63 + }, 1.64 + onDownloadFailed: function(aInstall) { 1.65 + this.onInstallFailed(aInstall); 1.66 + } 1.67 + }; 1.68 + 1.69 + // Order AddonManager to install the addon 1.70 + AddonManager.getInstallForFile(file, function(install) { 1.71 + if (install.error != null) { 1.72 + install.addListener(listener); 1.73 + install.install(); 1.74 + } else { 1.75 + reject(install.error); 1.76 + } 1.77 + }); 1.78 + 1.79 + return promise; 1.80 +}; 1.81 + 1.82 +exports.uninstall = function uninstall(addonId) { 1.83 + let { promise, resolve, reject } = defer(); 1.84 + 1.85 + // Listen for uninstallation end 1.86 + let listener = { 1.87 + onUninstalled: function onUninstalled(aAddon) { 1.88 + if (aAddon.id != addonId) 1.89 + return; 1.90 + AddonManager.removeAddonListener(listener); 1.91 + resolve(); 1.92 + } 1.93 + }; 1.94 + AddonManager.addAddonListener(listener); 1.95 + 1.96 + // Order Addonmanager to uninstall the addon 1.97 + getAddon(addonId).then(addon => addon.uninstall(), reject); 1.98 + 1.99 + return promise; 1.100 +}; 1.101 + 1.102 +exports.disable = function disable(addonId) { 1.103 + return getAddon(addonId).then(addon => { 1.104 + addon.userDisabled = true; 1.105 + return addonId; 1.106 + }); 1.107 +}; 1.108 + 1.109 +exports.enable = function enabled(addonId) { 1.110 + return getAddon(addonId).then(addon => { 1.111 + addon.userDisabled = false; 1.112 + return addonId; 1.113 + }); 1.114 +}; 1.115 + 1.116 +exports.isActive = function isActive(addonId) { 1.117 + return getAddon(addonId).then(addon => addon.isActive && !addon.appDisabled); 1.118 +}; 1.119 + 1.120 +function getAddon (id) { 1.121 + let { promise, resolve, reject } = defer(); 1.122 + AddonManager.getAddonByID(id, addon => addon ? resolve(addon) : reject()); 1.123 + return promise; 1.124 +}