--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -3093,41 +3093,41 @@ this.XPIProvider = {
getService(Ci.nsIWindowWatcher);
ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant);
// Ensure any changes to the add-ons list are flushed to disk
Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS,
!XPIDatabase.writeAddonsList());
},
- updateSystemAddons: Task.async(function*() {
+ async updateSystemAddons() {
let systemAddonLocation = XPIProvider.installLocationsByName[KEY_APP_SYSTEM_ADDONS];
if (!systemAddonLocation)
return;
// Don't do anything in safe mode
if (Services.appinfo.inSafeMode)
return;
// Download the list of system add-ons
let url = Preferences.get(PREF_SYSTEM_ADDON_UPDATE_URL, null);
if (!url) {
- yield systemAddonLocation.cleanDirectories();
+ await systemAddonLocation.cleanDirectories();
return;
}
url = UpdateUtils.formatUpdateURL(url);
logger.info(`Starting system add-on update check from ${url}.`);
- let res = yield ProductAddonChecker.getProductAddonList(url);
+ let res = await ProductAddonChecker.getProductAddonList(url);
// If there was no list then do nothing.
if (!res || !res.gmpAddons) {
logger.info("No system add-ons list was returned.");
- yield systemAddonLocation.cleanDirectories();
+ await systemAddonLocation.cleanDirectories();
return;
}
let addonList = new Map(
res.gmpAddons.map(spec => [spec.id, { spec, path: null, addon: null }]));
let getAddonsInLocation = (location) => {
return new Promise(resolve => {
@@ -3147,64 +3147,64 @@ this.XPIProvider = {
if (wantedInfo.spec.version != addon.version)
return false;
}
return true;
};
// If this matches the current set in the profile location then do nothing.
- let updatedAddons = addonMap(yield getAddonsInLocation(KEY_APP_SYSTEM_ADDONS));
+ let updatedAddons = addonMap(await getAddonsInLocation(KEY_APP_SYSTEM_ADDONS));
if (setMatches(addonList, updatedAddons)) {
logger.info("Retaining existing updated system add-ons.");
- yield systemAddonLocation.cleanDirectories();
+ await systemAddonLocation.cleanDirectories();
return;
}
// If this matches the current set in the default location then reset the
// updated set.
- let defaultAddons = addonMap(yield getAddonsInLocation(KEY_APP_SYSTEM_DEFAULTS));
+ let defaultAddons = addonMap(await getAddonsInLocation(KEY_APP_SYSTEM_DEFAULTS));
if (setMatches(addonList, defaultAddons)) {
logger.info("Resetting system add-ons.");
systemAddonLocation.resetAddonSet();
- yield systemAddonLocation.cleanDirectories();
+ await systemAddonLocation.cleanDirectories();
return;
}
// Download all the add-ons
- let downloadAddon = Task.async(function*(item) {
+ async function downloadAddon(item) {
try {
let sourceAddon = updatedAddons.get(item.spec.id);
if (sourceAddon && sourceAddon.version == item.spec.version) {
// Copying the file to a temporary location has some benefits. If the
// file is locked and cannot be read then we'll fall back to
// downloading a fresh copy. It also means we don't have to remember
// whether to delete the temporary copy later.
try {
let path = OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon");
- let unique = yield OS.File.openUnique(path);
+ let unique = await OS.File.openUnique(path);
unique.file.close();
- yield OS.File.copy(sourceAddon._sourceBundle.path, unique.path);
+ await OS.File.copy(sourceAddon._sourceBundle.path, unique.path);
// Make sure to update file modification times so this is detected
// as a new add-on.
- yield OS.File.setDates(unique.path);
+ await OS.File.setDates(unique.path);
item.path = unique.path;
} catch (e) {
logger.warn(`Failed make temporary copy of ${sourceAddon._sourceBundle.path}.`, e);
}
}
if (!item.path) {
- item.path = yield ProductAddonChecker.downloadAddon(item.spec);
+ item.path = await ProductAddonChecker.downloadAddon(item.spec);
}
- item.addon = yield loadManifestFromFile(nsIFile(item.path), systemAddonLocation);
+ item.addon = await loadManifestFromFile(nsIFile(item.path), systemAddonLocation);
} catch (e) {
logger.error(`Failed to download system add-on ${item.spec.id}`, e);
}
- });
- yield Promise.all(Array.from(addonList.values()).map(downloadAddon));
+ }
+ await Promise.all(Array.from(addonList.values()).map(downloadAddon));
// The download promises all resolve regardless, now check if they all
// succeeded
let validateAddon = (item) => {
if (item.spec.id != item.addon.id) {
logger.warn(`Downloaded system add-on expected to be ${item.spec.id} but was ${item.addon.id}.`);
return false;
}
@@ -3222,19 +3222,19 @@ this.XPIProvider = {
if (!Array.from(addonList.values()).every(item => item.path && item.addon && validateAddon(item))) {
throw new Error("Rejecting updated system add-on set that either could not " +
"be downloaded or contained unusable add-ons.");
}
// Install into the install location
logger.info("Installing new system add-on set");
- yield systemAddonLocation.installAddonSet(Array.from(addonList.values())
+ await systemAddonLocation.installAddonSet(Array.from(addonList.values())
.map(a => a.addon));
- }),
+ },
/**
* Verifies that all installed add-ons are still correctly signed.
*/
verifySignatures() {
XPIDatabase.getAddonList(a => true, (addons) => {
Task.spawn(function*() {
let changes = {
@@ -7965,48 +7965,46 @@ PROP_LOCALE_MULTI.forEach(function(aProp
});
});
/**
* An object which identifies a directory install location for add-ons. The
* location consists of a directory which contains the add-ons installed in the
* location.
*
- * Each add-on installed in the location is either a directory containing the
- * add-on's files or a text file containing an absolute path to the directory
- * containing the add-ons files. The directory or text file must have the same
- * name as the add-on's ID.
- *
- * @param aName
- * The string identifier for the install location
- * @param aDirectory
- * The nsIFile directory for the install location
- * @param aScope
- * The scope of add-ons installed in this location
*/
-function DirectoryInstallLocation(aName, aDirectory, aScope) {
- this._name = aName;
- this.locked = true;
- this._directory = aDirectory;
- this._scope = aScope
- this._IDToFileMap = {};
- this._linkedAddons = [];
-
- if (!aDirectory || !aDirectory.exists())
- return;
- if (!aDirectory.isDirectory())
- throw new Error("Location must be a directory.");
-
- this._readAddons();
-}
-
-DirectoryInstallLocation.prototype = {
- _name: "",
- _directory: null,
- _IDToFileMap: null, // mapping from add-on ID to nsIFile
+class DirectoryInstallLocation {
+ /**
+ * Each add-on installed in the location is either a directory containing the
+ * add-on's files or a text file containing an absolute path to the directory
+ * containing the add-ons files. The directory or text file must have the same
+ * name as the add-on's ID.
+ *
+ * @param aName
+ * The string identifier for the install location
+ * @param aDirectory
+ * The nsIFile directory for the install location
+ * @param aScope
+ * The scope of add-ons installed in this location
+ */
+ constructor(aName, aDirectory, aScope) {
+ this._name = aName;
+ this.locked = true;
+ this._directory = aDirectory;
+ this._scope = aScope
+ this._IDToFileMap = {};
+ this._linkedAddons = [];
+
+ if (!aDirectory || !aDirectory.exists())
+ return;
+ if (!aDirectory.isDirectory())
+ throw new Error("Location must be a directory.");
+
+ this._readAddons();
+ }
/**
* Reads a directory linked to in a file.
*
* @param file
* The file containing the directory path
* @return An nsIFile object representing the linked directory.
*/
@@ -8054,17 +8052,17 @@ DirectoryInstallLocation.prototype = {
return null;
}
return linkedDirectory;
}
logger.warn("File pointer " + aFile.path + " does not contain a path");
return null;
- },
+ }
/**
* Finds all the add-ons installed in this location.
*/
_readAddons() {
// Use a snapshot of the directory contents to avoid possible issues with
// iterating over a directory while removing files from it (the YAFFS2
// embedded filesystem has this issue, see bug 772238).
@@ -8103,126 +8101,127 @@ DirectoryInstallLocation.prototype = {
entry = newEntry;
this._linkedAddons.push(id);
}
this._IDToFileMap[id] = entry;
XPIProvider._addURIMapping(id, entry);
}
- },
+ }
/**
* Gets the name of this install location.
*/
get name() {
return this._name;
- },
+ }
/**
* Gets the scope of this install location.
*/
get scope() {
return this._scope;
- },
+ }
/**
* Gets an array of nsIFiles for add-ons installed in this location.
*/
getAddonLocations() {
let locations = new Map();
for (let id in this._IDToFileMap) {
locations.set(id, this._IDToFileMap[id].clone());
}
return locations;
- },
+ }
/**
* Gets the directory that the add-on with the given ID is installed in.
*
* @param aId
* The ID of the add-on
* @return The nsIFile
* @throws if the ID does not match any of the add-ons installed
*/
getLocationForID(aId) {
if (aId in this._IDToFileMap)
return this._IDToFileMap[aId].clone();
throw new Error("Unknown add-on ID " + aId);
- },
+ }
/**
* Returns true if the given addon was installed in this location by a text
* file pointing to its real path.
*
* @param aId
* The ID of the addon
*/
isLinkedAddon(aId) {
return this._linkedAddons.indexOf(aId) != -1;
}
-};
+}
/**
* An extension of DirectoryInstallLocation which adds methods to installing
* and removing add-ons from the directory at runtime.
- *
- * @param aName
- * The string identifier for the install location
- * @param aDirectory
- * The nsIFile directory for the install location
- * @param aScope
- * The scope of add-ons installed in this location
*/
-function MutableDirectoryInstallLocation(aName, aDirectory, aScope) {
- DirectoryInstallLocation.call(this, aName, aDirectory, aScope);
- this.locked = false;
- this._stagingDirLock = 0;
-}
-
-MutableDirectoryInstallLocation.prototype = Object.create(DirectoryInstallLocation.prototype);
-Object.assign(MutableDirectoryInstallLocation.prototype, {
+class MutableDirectoryInstallLocation extends DirectoryInstallLocation {
+ /**
+ * @param aName
+ * The string identifier for the install location
+ * @param aDirectory
+ * The nsIFile directory for the install location
+ * @param aScope
+ * The scope of add-ons installed in this location
+ */
+ constructor(aName, aDirectory, aScope) {
+ super(aName, aDirectory, aScope);
+
+ this.locked = false;
+ this._stagingDirLock = 0;
+ }
+
/**
* Gets the staging directory to put add-ons that are pending install and
* uninstall into.
*
* @return an nsIFile
*/
getStagingDir() {
let dir = this._directory.clone();
dir.append(DIR_STAGE);
return dir;
- },
+ }
requestStagingDir() {
this._stagingDirLock++;
if (this._stagingDirPromise)
return this._stagingDirPromise;
OS.File.makeDir(this._directory.path);
let stagepath = OS.Path.join(this._directory.path, DIR_STAGE);
return this._stagingDirPromise = OS.File.makeDir(stagepath).then(null, (e) => {
if (e instanceof OS.File.Error && e.becauseExists)
return;
logger.error("Failed to create staging directory", e);
throw e;
});
- },
+ }
releaseStagingDir() {
this._stagingDirLock--;
if (this._stagingDirLock == 0) {
this._stagingDirPromise = null;
this.cleanStagingDir();
}
return Promise.resolve();
- },
+ }
/**
* Removes the specified files or directories in the staging directory and
* then if the staging directory is empty attempts to remove it.
*
* @param aLeafNames
* An array of file or directory to remove from the directory, the
* array may be empty
@@ -8249,17 +8248,17 @@ Object.assign(MutableDirectoryInstallLoc
try {
setFilePermissions(dir, FileUtils.PERMS_DIRECTORY);
dir.remove(false);
} catch (e) {
logger.warn("Failed to remove staging dir", e);
// Failing to remove the staging directory is ignorable
}
- },
+ }
/**
* Returns a directory that is normally on the same filesystem as the rest of
* the install location and can be used for temporarily storing files during
* safe move operations. Calling this method will delete the existing trash
* directory and its contents.
*
* @return an nsIFile
@@ -8274,17 +8273,17 @@ Object.assign(MutableDirectoryInstallLoc
trashDirExists = false;
} catch (e) {
logger.warn("Failed to remove trash directory", e);
}
if (!trashDirExists)
trashDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
return trashDir;
- },
+ }
/**
* Installs an add-on into the install location.
*
* @param id
* The ID of the add-on to install
* @param source
* The source nsIFile to install from
@@ -8393,17 +8392,17 @@ Object.assign(MutableDirectoryInstallLoc
XPIProvider._addURIMapping(id, newFile);
if (existingAddonID && existingAddonID != id &&
existingAddonID in this._IDToFileMap) {
delete this._IDToFileMap[existingAddonID];
}
return newFile;
- },
+ }
/**
* Uninstalls an add-on from this location.
*
* @param aId
* The ID of the add-on to uninstall
* @throws if the ID does not match any of the add-ons installed
*/
@@ -8445,60 +8444,67 @@ Object.assign(MutableDirectoryInstallLoc
try {
recursiveRemove(trashDir);
} catch (e) {
logger.warn("Failed to remove trash directory when uninstalling " + aId, e);
}
}
delete this._IDToFileMap[aId];
- },
-});
+ }
+}
/**
* An object which identifies a directory install location for system add-ons
- * upgrades.
- *
- * The location consists of a directory which contains the add-ons installed.
- *
- * @param aName
- * The string identifier for the install location
- * @param aDirectory
- * The nsIFile directory for the install location
- * @param aScope
- * The scope of add-ons installed in this location
- * @param aResetSet
- * True to throw away the current add-on set
+ * updates.
*/
-function SystemAddonInstallLocation(aName, aDirectory, aScope, aResetSet) {
- this._baseDir = aDirectory;
- this._nextDir = null;
-
- this._stagingDirLock = 0;
-
- if (aResetSet)
- this.resetAddonSet();
-
- this._addonSet = this._loadAddonSet();
-
- this._directory = null;
- if (this._addonSet.directory) {
- this._directory = aDirectory.clone();
- this._directory.append(this._addonSet.directory);
- logger.info("SystemAddonInstallLocation scanning directory " + this._directory.path);
- } else {
- logger.info("SystemAddonInstallLocation directory is missing");
- }
-
- DirectoryInstallLocation.call(this, aName, this._directory, aScope);
- this.locked = false;
-}
-
-SystemAddonInstallLocation.prototype = Object.create(DirectoryInstallLocation.prototype);
-Object.assign(SystemAddonInstallLocation.prototype, {
+class SystemAddonInstallLocation extends MutableDirectoryInstallLocation {
+ /**
+ * The location consists of a directory which contains the add-ons installed.
+ *
+ * @param aName
+ * The string identifier for the install location
+ * @param aDirectory
+ * The nsIFile directory for the install location
+ * @param aScope
+ * The scope of add-ons installed in this location
+ * @param aResetSet
+ * True to throw away the current add-on set
+ */
+ constructor(aName, aDirectory, aScope, aResetSet) {
+ let addonSet = SystemAddonInstallLocation._loadAddonSet();
+ let directory = null;
+
+ // The system add-on update directory is stored in a pref.
+ // Therefore, this is looked up before calling the
+ // constructor on the superclass.
+ if (addonSet.directory) {
+ directory = aDirectory.clone();
+ directory.append(addonSet.directory);
+ logger.info("SystemAddonInstallLocation scanning directory " + directory.path);
+ } else {
+ logger.info("SystemAddonInstallLocation directory is missing");
+ }
+
+ super(aName, directory, aScope);
+
+ this._addonSet = addonSet;
+ this._baseDir = aDirectory;
+ this._nextDir = null;
+ this._directory = directory;
+
+ this._stagingDirLock = 0;
+
+ if (aResetSet) {
+ this.resetAddonSet();
+ }
+
+ this.locked = false;
+ }
+
/**
* Removes the specified files or directories in the staging directory and
* then if the staging directory is empty attempts to remove it.
*
* @param aLeafNames
* An array of file or directory to remove from the directory, the
* array may be empty
*/
@@ -8524,121 +8530,124 @@ Object.assign(SystemAddonInstallLocation
try {
setFilePermissions(dir, FileUtils.PERMS_DIRECTORY);
dir.remove(false);
} catch (e) {
logger.warn("Failed to remove staging dir", e);
// Failing to remove the staging directory is ignorable
}
- },
+ }
/**
* Gets the staging directory to put add-ons that are pending install and
* uninstall into.
*
* @return {nsIFile} - staging directory for system add-on upgrades.
*/
getStagingDir() {
- this._addonSet = this._loadAddonSet();
+ this._addonSet = SystemAddonInstallLocation._loadAddonSet();
let dir = null;
if (this._addonSet.directory) {
this._directory = this._baseDir.clone();
this._directory.append(this._addonSet.directory);
dir = this._directory.clone();
dir.append(DIR_STAGE);
} else {
logger.info("SystemAddonInstallLocation directory is missing");
}
return dir;
- },
+ }
requestStagingDir() {
this._stagingDirLock++;
if (this._stagingDirPromise)
return this._stagingDirPromise;
- this._addonSet = this._loadAddonSet();
+ this._addonSet = SystemAddonInstallLocation._loadAddonSet();
if (this._addonSet.directory) {
this._directory = this._baseDir.clone();
this._directory.append(this._addonSet.directory);
}
OS.File.makeDir(this._directory.path);
let stagepath = OS.Path.join(this._directory.path, DIR_STAGE);
return this._stagingDirPromise = OS.File.makeDir(stagepath).then(null, (e) => {
if (e instanceof OS.File.Error && e.becauseExists)
return;
logger.error("Failed to create staging directory", e);
throw e;
});
- },
+ }
releaseStagingDir() {
this._stagingDirLock--;
if (this._stagingDirLock == 0) {
this._stagingDirPromise = null;
this.cleanStagingDir();
}
return Promise.resolve();
- },
+ }
/**
* Reads the current set of system add-ons
*/
- _loadAddonSet() {
+ static _loadAddonSet() {
try {
let setStr = Preferences.get(PREF_SYSTEM_ADDON_SET, null);
if (setStr) {
let addonSet = JSON.parse(setStr);
- if ((typeof addonSet == "object") && addonSet.schema == 1)
+ if ((typeof addonSet == "object") && addonSet.schema == 1) {
return addonSet;
+ }
}
} catch (e) {
logger.error("Malformed system add-on set, resetting.");
}
return { schema: 1, addons: {} };
- },
+ }
/**
* Saves the current set of system add-ons
*
* @param {Object} aAddonSet - object containing schema, directory and set
* of system add-on IDs and versions.
*/
_saveAddonSet(aAddonSet) {
Preferences.set(PREF_SYSTEM_ADDON_SET, JSON.stringify(aAddonSet));
- },
+ }
getAddonLocations() {
// Updated system add-ons are ignored in safe mode
- if (Services.appinfo.inSafeMode)
+ if (Services.appinfo.inSafeMode) {
return new Map();
-
- let addons = DirectoryInstallLocation.prototype.getAddonLocations.call(this);
+ }
+
+ let addons = super.getAddonLocations();
// Strip out any unexpected add-ons from the list
for (let id of addons.keys()) {
- if (!(id in this._addonSet.addons))
+ if (!(id in this._addonSet.addons)) {
addons.delete(id);
+ }
}
return addons;
- },
+ }
/**
* Tests whether updated system add-ons are expected.
*/
isActive() {
return this._directory != null;
- },
+ }
isValidAddon(aAddon) {
if (aAddon.appDisabled) {
logger.warn(`System add-on ${aAddon.id} isn't compatible with the application.`);
return false;
}
if (aAddon.unpack) {
@@ -8652,17 +8661,17 @@ Object.assign(SystemAddonInstallLocation
}
if (!aAddon.multiprocessCompatible) {
logger.warn(`System add-on ${aAddon.id} isn't multiprocess compatible.`);
return false;
}
return true;
- },
+ }
/**
* Tests whether the loaded add-on information matches what is expected.
*/
isValid(aAddons) {
for (let id of Object.keys(this._addonSet.addons)) {
if (!aAddons.has(id)) {
logger.warn(`Expected add-on ${id} is missing from the system add-on location.`);
@@ -8675,17 +8684,17 @@ Object.assign(SystemAddonInstallLocation
return false;
}
if (!this.isValidAddon(addon))
return false;
}
return true;
- },
+ }
/**
* Resets the add-on set so on the next startup the default set will be used.
*/
resetAddonSet() {
logger.info("Removing all system add-on upgrades.");
// remove everything from the pref first, if uninstall
@@ -8704,83 +8713,81 @@ Object.assign(SystemAddonInstallLocation
for (let id of Object.keys(this._addonSet.addons)) {
AddonManager.getAddonByID(id, addon => {
if (addon) {
addon.uninstall();
}
});
}
}
- },
+ }
/**
* Removes any directories not currently in use or pending use after a
* restart. Any errors that happen here don't really matter as we'll attempt
* to cleanup again next time.
*/
- cleanDirectories: Task.async(function*() {
-
+ async cleanDirectories() {
// System add-ons directory does not exist
- if (!(yield OS.File.exists(this._baseDir.path))) {
+ if (!(await OS.File.exists(this._baseDir.path))) {
return;
}
let iterator;
try {
iterator = new OS.File.DirectoryIterator(this._baseDir.path);
} catch (e) {
logger.error("Failed to clean updated system add-ons directories.", e);
return;
}
try {
- let entries = [];
-
- yield iterator.forEach(entry => {
+ for (let promise in iterator) {
+ let entry = await promise;
+
// Skip the directory currently in use
- if (this._directory && this._directory.path == entry.path)
- return;
+ if (this._directory && this._directory.path == entry.path) {
+ continue;
+ }
// Skip the next directory
- if (this._nextDir && this._nextDir.path == entry.path)
- return;
-
- entries.push(entry);
- });
-
- for (let entry of entries) {
+ if (this._nextDir && this._nextDir.path == entry.path) {
+ continue;
+ }
+
if (entry.isDir) {
- yield OS.File.removeDir(entry.path, {
- ignoreAbsent: true,
- ignorePermissions: true,
- });
- } else {
- yield OS.File.remove(entry.path, {
- ignoreAbsent: true,
- });
- }
- }
+ await OS.File.removeDir(entry.path, {
+ ignoreAbsent: true,
+ ignorePermissions: true,
+ });
+ } else {
+ await OS.File.remove(entry.path, {
+ ignoreAbsent: true,
+ });
+ }
+ }
+
} catch (e) {
logger.error("Failed to clean updated system add-ons directories.", e);
} finally {
iterator.close();
}
- }),
+ }
/**
* Installs a new set of system add-ons into the location and updates the
* add-on set in prefs.
*
* @param {Array} aAddons - An array of addons to install.
*/
- installAddonSet: Task.async(function*(aAddons) {
+ async installAddonSet(aAddons) {
// Make sure the base dir exists
- yield OS.File.makeDir(this._baseDir.path, { ignoreExisting: true });
-
- let addonSet = this._loadAddonSet();
+ await OS.File.makeDir(this._baseDir.path, { ignoreExisting: true });
+
+ let addonSet = SystemAddonInstallLocation._loadAddonSet();
// Remove any add-ons that are no longer part of the set.
for (let addonID of Object.keys(addonSet.addons)) {
if (!aAddons.includes(addonID)) {
AddonManager.getAddonByID(addonID, a => a.uninstall());
}
}
@@ -8789,115 +8796,115 @@ Object.assign(SystemAddonInstallLocation
let uuidGen = Cc["@mozilla.org/uuid-generator;1"].
getService(Ci.nsIUUIDGenerator);
newDir.append("blank");
while (true) {
newDir.leafName = uuidGen.generateUUID().toString();
try {
- yield OS.File.makeDir(newDir.path, { ignoreExisting: false });
+ await OS.File.makeDir(newDir.path, { ignoreExisting: false });
break;
} catch (e) {
logger.debug("Could not create new system add-on updates dir, retrying", e);
}
}
// Record the new upgrade directory.
let state = { schema: 1, directory: newDir.leafName, addons: {} };
this._saveAddonSet(state);
this._nextDir = newDir;
let location = this;
let installs = [];
for (let addon of aAddons) {
- let install = yield createLocalInstall(addon._sourceBundle, location);
+ let install = await createLocalInstall(addon._sourceBundle, location);
installs.push(install);
}
- let installAddon = Task.async(function*(install) {
+ async function installAddon(install) {
// Make the new install own its temporary file.
install.ownsTempFile = true;
install.install();
- });
-
- let postponeAddon = Task.async(function*(install) {
+ }
+
+ async function postponeAddon(install) {
let resumeFn;
if (AddonManagerPrivate.hasUpgradeListener(install.addon.id)) {
logger.info(`system add-on ${install.addon.id} has an upgrade listener, postponing upgrade set until restart`);
resumeFn = () => {
logger.info(`${install.addon.id} has resumed a previously postponed addon set`);
install.installLocation.resumeAddonSet(installs);
}
}
- yield install.postpone(resumeFn);
- });
+ await install.postpone(resumeFn);
+ }
let previousState;
try {
// All add-ons in position, create the new state and store it in prefs
state = { schema: 1, directory: newDir.leafName, addons: {} };
for (let addon of aAddons) {
state.addons[addon.id] = {
version: addon.version
}
}
- previousState = this._loadAddonSet();
+ previousState = SystemAddonInstallLocation._loadAddonSet();
this._saveAddonSet(state);
let blockers = aAddons.filter(
addon => AddonManagerPrivate.hasUpgradeListener(addon.id)
);
if (blockers.length > 0) {
- yield waitForAllPromises(installs.map(postponeAddon));
+ await waitForAllPromises(installs.map(postponeAddon));
} else {
- yield waitForAllPromises(installs.map(installAddon));
+ await waitForAllPromises(installs.map(installAddon));
}
} catch (e) {
// Roll back to previous upgrade set (if present) on restart.
if (previousState) {
this._saveAddonSet(previousState);
}
// Otherwise, roll back to built-in set on restart.
// TODO try to do these restartlessly
this.resetAddonSet();
try {
- yield OS.File.removeDir(newDir.path, { ignorePermissions: true });
+ await OS.File.removeDir(newDir.path, { ignorePermissions: true });
} catch (e) {
logger.warn(`Failed to remove failed system add-on directory ${newDir.path}.`, e);
}
throw e;
}
- }),
+ }
/**
* Resumes upgrade of a previously-delayed add-on set.
*/
- resumeAddonSet: Task.async(function*(installs) {
- let resumeAddon = Task.async(function*(install) {
+ async resumeAddonSet(installs) {
+ function resumeAddon(install) {
install.state = AddonManager.STATE_DOWNLOADED;
install.installLocation.releaseStagingDir();
install.install();
- });
+ }
let blockers = installs.filter(
install => AddonManagerPrivate.hasUpgradeListener(install.addon.id)
);
if (blockers.length > 1) {
logger.warn("Attempted to resume system add-on install but upgrade blockers are still present");
} else {
- yield waitForAllPromises(installs.map(resumeAddon));
- }
- }),
+ await waitForAllPromises(installs.map(resumeAddon));
+ }
+ }
/**
* Returns a directory that is normally on the same filesystem as the rest of
* the install location and can be used for temporarily storing files during
* safe move operations. Calling this method will delete the existing trash
* directory and its contents.
*
* @return an nsIFile
@@ -8912,17 +8919,17 @@ Object.assign(SystemAddonInstallLocation
trashDirExists = false;
} catch (e) {
logger.warn("Failed to remove trash directory", e);
}
if (!trashDirExists)
trashDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
return trashDir;
- },
+ }
/**
* Installs an add-on into the install location.
*
* @param id
* The ID of the add-on to install
* @param source
* The source nsIFile to install from
@@ -8957,21 +8964,21 @@ Object.assign(SystemAddonInstallLocation
newFile.lastModifiedTime = Date.now();
} catch (e) {
logger.warn("failed to set lastModifiedTime on " + newFile.path, e);
}
this._IDToFileMap[id] = newFile;
XPIProvider._addURIMapping(id, newFile);
return newFile;
- },
+ }
// old system add-on upgrade dirs get automatically removed
- uninstallAddon: (aAddon) => {},
-});
+ uninstallAddon(aAddon) {}
+}
/**
* An object which identifies an install location for temporary add-ons.
*/
const TemporaryInstallLocation = {
locked: false,
name: KEY_APP_TEMPORARY,
scope: AddonManager.SCOPE_TEMPORARY,
@@ -8982,51 +8989,48 @@ const TemporaryInstallLocation = {
getStagingDir: () => {},
}
/**
* An object that identifies a registry install location for add-ons. The location
* consists of a registry key which contains string values mapping ID to the
* path where an add-on is installed
*
- * @param aName
- * The string identifier of this Install Location.
- * @param aRootKey
- * The root key (one of the ROOT_KEY_ values from nsIWindowsRegKey).
- * @param scope
- * The scope of add-ons installed in this location
*/
-function WinRegInstallLocation(aName, aRootKey, aScope) {
- this.locked = true;
- this._name = aName;
- this._rootKey = aRootKey;
- this._scope = aScope;
- this._IDToFileMap = {};
-
- let path = this._appKeyPath + "\\Extensions";
- let key = Cc["@mozilla.org/windows-registry-key;1"].
- createInstance(Ci.nsIWindowsRegKey);
-
- // Reading the registry may throw an exception, and that's ok. In error
- // cases, we just leave ourselves in the empty state.
- try {
- key.open(this._rootKey, path, Ci.nsIWindowsRegKey.ACCESS_READ);
- } catch (e) {
- return;
- }
-
- this._readAddons(key);
- key.close();
-}
-
-WinRegInstallLocation.prototype = {
- _name: "",
- _rootKey: null,
- _scope: null,
- _IDToFileMap: null, // mapping from ID to nsIFile
+class WinRegInstallLocation extends DirectoryInstallLocation {
+ /**
+ * @param aName
+ * The string identifier of this Install Location.
+ * @param aRootKey
+ * The root key (one of the ROOT_KEY_ values from nsIWindowsRegKey).
+ * @param scope
+ * The scope of add-ons installed in this location
+ */
+ constructor(aName, aRootKey, aScope) {
+ this.locked = true;
+ this._name = aName;
+ this._rootKey = aRootKey;
+ this._scope = aScope;
+ this._IDToFileMap = {};
+
+ let path = this._appKeyPath + "\\Extensions";
+ let key = Cc["@mozilla.org/windows-registry-key;1"].
+ createInstance(Ci.nsIWindowsRegKey);
+
+ // Reading the registry may throw an exception, and that's ok. In error
+ // cases, we just leave ourselves in the empty state.
+ try {
+ key.open(this._rootKey, path, Ci.nsIWindowsRegKey.ACCESS_READ);
+ } catch (e) {
+ return;
+ }
+
+ this._readAddons(key);
+ key.close();
+ }
/**
* Retrieves the path of this Application's data key in the registry.
*/
get _appKeyPath() {
let appVendor = Services.appinfo.vendor;
let appName = Services.appinfo.name;
@@ -9034,17 +9038,17 @@ WinRegInstallLocation.prototype = {
if (AppConstants.MOZ_APP_NAME == "thunderbird" && appVendor == "")
appVendor = "Mozilla";
// XULRunner-based apps may intentionally not specify a vendor
if (appVendor != "")
appVendor += "\\";
return "SOFTWARE\\" + appVendor + appName;
- },
+ }
/**
* Read the registry and build a mapping between ID and path for each
* installed add-on.
*
* @param key
* The key that contains the ID to path mapping
*/
@@ -9058,50 +9062,50 @@ WinRegInstallLocation.prototype = {
if (!file.exists()) {
logger.warn("Ignoring missing add-on in " + file.path);
continue;
}
this._IDToFileMap[id] = file;
XPIProvider._addURIMapping(id, file);
}
- },
+ }
/**
* Gets the name of this install location.
*/
get name() {
return this._name;
- },
+ }
/**
* Gets the scope of this install location.
*/
get scope() {
return this._scope;
- },
+ }
/**
* Gets an array of nsIFiles for add-ons installed in this location.
*/
getAddonLocations() {
let locations = new Map();
for (let id in this._IDToFileMap) {
locations.set(id, this._IDToFileMap[id].clone());
}
return locations;
- },
+ }
/**
* @see DirectoryInstallLocation
*/
isLinkedAddon(aId) {
return true;
}
-};
+}
var addonTypes = [
new AddonManagerPrivate.AddonType("extension", URI_EXTENSION_STRINGS,
STRING_TYPE_NAME,
AddonManager.VIEW_TYPE_LIST, 4000,
AddonManager.TYPE_SUPPORTS_UNDO_RESTARTLESS_UNINSTALL),
new AddonManagerPrivate.AddonType("theme", URI_EXTENSION_STRINGS,
STRING_TYPE_NAME,