|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 module.metadata = { |
|
6 "stability": "experimental" |
|
7 }; |
|
8 |
|
9 const { Cc, Ci, Cu } = require("chrome"); |
|
10 const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm"); |
|
11 const { defer } = require("../core/promise"); |
|
12 const { setTimeout } = require("../timers"); |
|
13 |
|
14 /** |
|
15 * `install` method error codes: |
|
16 * |
|
17 * https://developer.mozilla.org/en/Addons/Add-on_Manager/AddonManager#AddonInstall_errors |
|
18 */ |
|
19 exports.ERROR_NETWORK_FAILURE = AddonManager.ERROR_NETWORK_FAILURE; |
|
20 exports.ERROR_INCORRECT_HASH = AddonManager.ERROR_INCORRECT_HASH; |
|
21 exports.ERROR_CORRUPT_FILE = AddonManager.ERROR_CORRUPT_FILE; |
|
22 exports.ERROR_FILE_ACCESS = AddonManager.ERROR_FILE_ACCESS; |
|
23 |
|
24 /** |
|
25 * Immediatly install an addon. |
|
26 * |
|
27 * @param {String} xpiPath |
|
28 * file path to an xpi file to install |
|
29 * @return {Promise} |
|
30 * A promise resolved when the addon is finally installed. |
|
31 * Resolved with addon id as value or rejected with an error code. |
|
32 */ |
|
33 exports.install = function install(xpiPath) { |
|
34 let { promise, resolve, reject } = defer(); |
|
35 |
|
36 // Create nsIFile for the xpi file |
|
37 let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile); |
|
38 try { |
|
39 file.initWithPath(xpiPath); |
|
40 } |
|
41 catch(e) { |
|
42 reject(exports.ERROR_FILE_ACCESS); |
|
43 return promise; |
|
44 } |
|
45 |
|
46 // Listen for installation end |
|
47 let listener = { |
|
48 onInstallEnded: function(aInstall, aAddon) { |
|
49 aInstall.removeListener(listener); |
|
50 // Bug 749745: on FF14+, onInstallEnded is called just before `startup()` |
|
51 // is called, but we expect to resolve the promise only after it. |
|
52 // As startup is called synchronously just after onInstallEnded, |
|
53 // a simple setTimeout(0) is enough |
|
54 setTimeout(resolve, 0, aAddon.id); |
|
55 }, |
|
56 onInstallFailed: function (aInstall) { |
|
57 console.log("failed"); |
|
58 aInstall.removeListener(listener); |
|
59 reject(aInstall.error); |
|
60 }, |
|
61 onDownloadFailed: function(aInstall) { |
|
62 this.onInstallFailed(aInstall); |
|
63 } |
|
64 }; |
|
65 |
|
66 // Order AddonManager to install the addon |
|
67 AddonManager.getInstallForFile(file, function(install) { |
|
68 if (install.error != null) { |
|
69 install.addListener(listener); |
|
70 install.install(); |
|
71 } else { |
|
72 reject(install.error); |
|
73 } |
|
74 }); |
|
75 |
|
76 return promise; |
|
77 }; |
|
78 |
|
79 exports.uninstall = function uninstall(addonId) { |
|
80 let { promise, resolve, reject } = defer(); |
|
81 |
|
82 // Listen for uninstallation end |
|
83 let listener = { |
|
84 onUninstalled: function onUninstalled(aAddon) { |
|
85 if (aAddon.id != addonId) |
|
86 return; |
|
87 AddonManager.removeAddonListener(listener); |
|
88 resolve(); |
|
89 } |
|
90 }; |
|
91 AddonManager.addAddonListener(listener); |
|
92 |
|
93 // Order Addonmanager to uninstall the addon |
|
94 getAddon(addonId).then(addon => addon.uninstall(), reject); |
|
95 |
|
96 return promise; |
|
97 }; |
|
98 |
|
99 exports.disable = function disable(addonId) { |
|
100 return getAddon(addonId).then(addon => { |
|
101 addon.userDisabled = true; |
|
102 return addonId; |
|
103 }); |
|
104 }; |
|
105 |
|
106 exports.enable = function enabled(addonId) { |
|
107 return getAddon(addonId).then(addon => { |
|
108 addon.userDisabled = false; |
|
109 return addonId; |
|
110 }); |
|
111 }; |
|
112 |
|
113 exports.isActive = function isActive(addonId) { |
|
114 return getAddon(addonId).then(addon => addon.isActive && !addon.appDisabled); |
|
115 }; |
|
116 |
|
117 function getAddon (id) { |
|
118 let { promise, resolve, reject } = defer(); |
|
119 AddonManager.getAddonByID(id, addon => addon ? resolve(addon) : reject()); |
|
120 return promise; |
|
121 } |