gecko-dev/browser/extensions/shield-recipe-client/lib/Addons.jsm
Mike Cooper 3f60b088ef Bug 1388823 - Sync shield-recipe-client v65 from GitHub (commit ff1b680c) r=Gijs
MozReview-Commit-ID: F8uuFRyS4li

--HG--
extra : rebase_source : 87670f9d0d219a21f544952785b30991fee61b68
2017-08-10 10:22:32 -07:00

136 lines
4.1 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/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Extension", "resource://gre/modules/Extension.jsm");
XPCOMUtils.defineLazyModuleGetter(
this, "CleanupManager", "resource://shield-recipe-client/lib/CleanupManager.jsm"
);
this.EXPORTED_SYMBOLS = ["Addons"];
/**
* SafeAddons store info about an add-on. They are single-depth
* objects to simplify cloning, and have no methods so they are safe
* to pass to sandboxes and filter expressions.
*
* @typedef {Object} SafeAddon
* @property {string} id
* Add-on id, such as "shield-recipe-client@mozilla.com" or "{4ea51ac2-adf2-4af8-a69d-17b48c558a12}"
* @property {Date} installDate
* @property {boolean} isActive
* @property {string} name
* @property {string} type
* "extension", "theme", etc.
* @property {string} version
*/
this.Addons = {
/**
* Get information about an installed add-on by ID.
*
* @param {string} addonId
* @returns {SafeAddon?} Add-on with given ID, or null if not found.
* @throws If addonId is not specified or not a string.
*/
async get(addonId) {
const addon = await AddonManager.getAddonByID(addonId);
if (!addon) {
return null;
}
return this.serializeForSandbox(addon);
},
/**
* Get information about all installed add-ons.
* @async
* @returns {Array<SafeAddon>}
*/
async getAll(addonId) {
const addons = await AddonManager.getAllAddons();
return addons.map(this.serializeForSandbox.bind(this));
},
/**
* Installs an add-on
*
* @param {string} addonUrl
* Url to download the .xpi for the add-on from.
* @param {object} options
* @param {boolean} options.update=false
* If true, will update an existing installed add-on with the same ID.
* @async
* @returns {string}
* Add-on ID that was installed
* @throws {string}
* If the add-on can not be installed, or overwriting is disabled and an
* add-on with a matching ID is already installed.
*/
async install(addonUrl, options) {
const installObj = await AddonManager.getInstallForURL(addonUrl, null, "application/x-xpinstall");
return this.applyInstall(installObj, options);
},
async applyInstall(addonInstall, {update = false} = {}) {
const result = new Promise((resolve, reject) => addonInstall.addListener({
onInstallStarted(cbInstall) {
if (cbInstall.existingAddon && !update) {
reject(new Error(`
Cannot install add-on ${cbInstall.addon.id}; an existing add-on
with the same ID exists and updating is disabled.
`));
return false;
}
return true;
},
onInstallEnded(cbInstall, addon) {
resolve(addon.id);
},
onInstallFailed(cbInstall) {
reject(new Error(`AddonInstall error code: [${cbInstall.error}]`));
},
onDownloadFailed(cbInstall) {
reject(new Error(`Download failed: [${cbInstall.sourceURI.spec}]`));
},
}));
addonInstall.install();
return result;
},
/**
* Uninstalls an add-on by ID.
* @param addonId {string} Add-on ID to uninstall.
* @async
* @throws If no add-on with `addonId` is installed.
*/
async uninstall(addonId) {
const addon = await AddonManager.getAddonByID(addonId);
if (addon === null) {
throw new Error(`No addon with ID [${addonId}] found.`);
}
addon.uninstall();
return null;
},
/**
* Make a safe serialization of an add-on
* @param addon {Object} An add-on object as returned from AddonManager.
*/
serializeForSandbox(addon) {
return {
id: addon.id,
installDate: new Date(addon.installDate),
isActive: addon.isActive,
name: addon.name,
type: addon.type,
version: addon.version,
};
},
};