--- a/toolkit/mozapps/extensions/.eslintrc.js
+++ b/toolkit/mozapps/extensions/.eslintrc.js
@@ -1,8 +1,11 @@
"use strict";
module.exports = { // eslint-disable-line no-undef
+ "parserOptions": {
+ "ecmaVersion": 8,
+ },
"rules": {
// No using undeclared variables
"no-undef": 2,
}
};
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -74,18 +74,16 @@ const WEBAPI_TEST_INSTALL_HOSTS = [
"testpilot.stage.mozaws.net", "testpilot.dev.mozaws.net",
"example.com",
];
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AsyncShutdown.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository",
"resource://gre/modules/addons/AddonRepository.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Extension",
"resource://gre/modules/Extension.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
@@ -1177,17 +1175,17 @@ var AddonManagerInternal = {
},
/**
* Shuts down the addon manager and all registered providers, this must clean
* up everything in order for automated tests to fake restarts.
* @return Promise{null} that resolves when all providers and dependent modules
* have finished shutting down
*/
- shutdownManager: Task.async(function*() {
+ shutdownManager: async function() {
logger.debug("shutdown");
this.callManagerListeners("onShutdown");
gRepoShutdownState = "pending";
gShutdownInProgress = true;
// Clean up listeners
Services.prefs.removeObserver(PREF_EM_CHECK_COMPATIBILITY, this);
Services.prefs.removeObserver(PREF_EM_STRICT_COMPATIBILITY, this);
@@ -1197,29 +1195,29 @@ var AddonManagerInternal = {
Services.prefs.removeObserver(PREF_EM_HOTFIX_ID, this);
gPluginPageListener.destroy();
gPluginPageListener = null;
let savedError = null;
// Only shut down providers if they've been started.
if (gStarted) {
try {
- yield gShutdownBarrier.wait();
+ await gShutdownBarrier.wait();
}
catch (err) {
savedError = err;
logger.error("Failure during wait for shutdown barrier", err);
AddonManagerPrivate.recordException("AMI", "Async shutdown of AddonManager providers", err);
}
}
// Shut down AddonRepository after providers (if any).
try {
gRepoShutdownState = "in progress";
- yield AddonRepository.shutdown();
+ await AddonRepository.shutdown();
gRepoShutdownState = "done";
}
catch (err) {
savedError = err;
logger.error("Failure during AddonRepository shutdown", err);
AddonManagerPrivate.recordException("AMI", "Async shutdown of AddonRepository", err);
}
@@ -1233,17 +1231,17 @@ var AddonManagerInternal = {
delete this.startupChanges[type];
gStarted = false;
gStartupComplete = false;
gShutdownBarrier = null;
gShutdownInProgress = false;
if (savedError) {
throw savedError;
}
- }),
+ },
requestPlugins: function({ target: port }) {
// Lists all the properties that plugins.html needs
const NEEDED_PROPS = ["name", "pluginLibraries", "pluginFullpath", "version",
"isActive", "blocklistState", "description",
"pluginMimeTypes"];
function filterProperties(plugin) {
let filtered = {};
@@ -1430,37 +1428,37 @@ var AddonManagerInternal = {
* @return Promise{null} Resolves when the background update check is complete
* (the resulting addon installations may still be in progress).
*/
backgroundUpdateCheck: function() {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
- let buPromise = Task.spawn(function*() {
+ let buPromise = new Promise(resolve => async function() {
let hotfixID = this.hotfixID;
let appUpdateEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
let checkHotfix = hotfixID && appUpdateEnabled;
logger.debug("Background update check beginning");
Services.obs.notifyObservers(null, "addons-background-update-start", null);
if (this.updateEnabled) {
let scope = {};
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
scope.LightweightThemeManager.updateCurrentTheme();
- let allAddons = yield new Promise((resolve, reject) => this.getAllAddons(resolve));
+ let allAddons = await new Promise((resolve, reject) => this.getAllAddons(resolve));
// Repopulate repository cache first, to ensure compatibility overrides
// are up to date before checking for addon updates.
- yield AddonRepository.backgroundUpdateCheck();
+ await AddonRepository.backgroundUpdateCheck();
// Keep track of all the async add-on updates happening in parallel
let updates = [];
for (let addon of allAddons) {
if (addon.id == hotfixID) {
continue;
}
@@ -1481,17 +1479,17 @@ var AddonManagerInternal = {
aInstall.install();
}
},
onUpdateFinished: aAddon => { logger.debug("onUpdateFinished for ${id}", aAddon); resolve(); }
}, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
}));
}
- yield Promise.all(updates);
+ await Promise.all(updates);
}
if (checkHotfix) {
var hotfixVersion = "";
try {
hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION);
}
catch (e) { }
@@ -1508,33 +1506,33 @@ var AddonManagerInternal = {
version: hotfixVersion,
userDisabled: false,
appDisabled: false
}, url);
Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm");
let update = null;
try {
- let foundUpdates = yield new Promise((resolve, reject) => {
+ let foundUpdates = await new Promise((resolve, reject) => {
AddonUpdateChecker.checkForUpdates(hotfixID, null, url, {
onUpdateCheckComplete: resolve,
onUpdateCheckError: reject
});
});
update = AddonUpdateChecker.getNewestCompatibleUpdate(foundUpdates);
} catch (e) {
// AUC.checkForUpdates already logged the error
}
// Check that we have a hotfix update, and it's newer than the one we already
// have installed (if any)
if (update) {
if (Services.vc.compare(hotfixVersion, update.version) < 0) {
logger.debug("Downloading hotfix version " + update.version);
- let aInstall = yield new Promise((resolve, reject) =>
+ let aInstall = await new Promise((resolve, reject) =>
AddonManager.getInstallForURL(update.updateURL, resolve,
"application/x-xpinstall", update.updateHash, null,
null, update.version));
aInstall.addListener({
onDownloadEnded: function(aInstall) {
if (aInstall.addon.id != hotfixID) {
logger.warn("The downloaded hotfix add-on did not have the " +
@@ -1584,17 +1582,17 @@ var AddonManagerInternal = {
aInstall.install();
}
}
}
if (appUpdateEnabled) {
try {
- yield AddonManagerInternal._getProviderByName("XPIProvider").updateSystemAddons();
+ await AddonManagerInternal._getProviderByName("XPIProvider").updateSystemAddons();
}
catch (e) {
logger.warn("Failed to update system addons", e);
}
}
logger.debug("Background update check complete");
Services.obs.notifyObservers(null,
--- a/toolkit/mozapps/extensions/amWebAPI.js
+++ b/toolkit/mozapps/extensions/amWebAPI.js
@@ -3,17 +3,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
const MSG_PROMISE_REQUEST = "WebAPIPromiseRequest";
const MSG_PROMISE_RESULT = "WebAPIPromiseResult";
const MSG_INSTALL_EVENT = "WebAPIInstallEvent";
const MSG_INSTALL_CLEANUP = "WebAPICleanup";
const MSG_ADDON_EVENT_REQ = "WebAPIAddonEventRequest";
const MSG_ADDON_EVENT = "WebAPIAddonEvent";
@@ -124,18 +123,18 @@ class APIObject {
* argument. Used to convert the result
* into something appropriate for content.
* @returns {Promise<any>} A Promise suitable for passing directly to content.
*/
_apiTask(apiRequest, apiArgs, resultConverter) {
let win = this.window;
let broker = this.broker;
return new win.Promise((resolve, reject) => {
- Task.spawn(function*() {
- let result = yield broker.sendRequest(apiRequest, ...apiArgs);
+ new Promise(async function() {
+ let result = await broker.sendRequest(apiRequest, ...apiArgs);
if ("reject" in result) {
let err = new win.Error(result.reject.message);
// We don't currently put any other properties onto Errors
// generated by mozAddonManager. If/when we do, they will
// need to get copied here.
reject(err);
return;
}
--- a/toolkit/mozapps/extensions/content/update.js
+++ b/toolkit/mozapps/extensions/content/update.js
@@ -14,17 +14,16 @@ const PREF_XPINSTALL_ENABLED
// timeout (in milliseconds) to wait for response to the metadata ping
const METADATA_TIMEOUT = 30000;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManagerPrivate", "resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository", "resource://gre/modules/addons/AddonRepository.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Log", "resource://gre/modules/Log.jsm");
var logger = null;
var gUpdateWizard = {
// When synchronizing app compatibility info this contains all installed
// add-ons. When checking for compatible versions this contains only
// incompatible add-ons.
@@ -174,59 +173,59 @@ var listener = {
gUpdateWizard.metadataEnabled++;
}
};
var gVersionInfoPage = {
_completeCount: 0,
_totalCount: 0,
_versionInfoDone: false,
- onPageShow: Task.async(function*() {
+ onPageShow: async function() {
gUpdateWizard.setButtonLabels(null, true,
"nextButtonText", true,
"cancelButtonText", false);
gUpdateWizard.disabled = gUpdateWizard.affectedAddonIDs.size;
// Ensure compatibility overrides are up to date before checking for
// individual addon updates.
AddonManager.addAddonListener(listener);
if (AddonRepository.isMetadataStale()) {
// Do the metadata ping, listening for any newly enabled/disabled add-ons.
- yield AddonRepository.repopulateCache(METADATA_TIMEOUT);
+ await AddonRepository.repopulateCache(METADATA_TIMEOUT);
if (gUpdateWizard.shuttingDown) {
logger.debug("repopulateCache completed after dialog closed");
}
}
// Fetch the add-ons that are still affected by this update,
// excluding the hotfix add-on.
let idlist = Array.from(gUpdateWizard.affectedAddonIDs).filter(
a => a.id != AddonManager.hotfixID);
if (idlist.length < 1) {
gVersionInfoPage.onAllUpdatesFinished();
return;
}
logger.debug("Fetching affected addons " + idlist.toSource());
- let fetchedAddons = yield new Promise((resolve, reject) =>
+ let fetchedAddons = await new Promise((resolve, reject) =>
AddonManager.getAddonsByIDs(idlist, resolve));
// We shouldn't get nulls here, but let's be paranoid...
gUpdateWizard.addons = fetchedAddons.filter(a => a);
if (gUpdateWizard.addons.length < 1) {
gVersionInfoPage.onAllUpdatesFinished();
return;
}
gVersionInfoPage._totalCount = gUpdateWizard.addons.length;
for (let addon of gUpdateWizard.addons) {
logger.debug("VersionInfo Finding updates for ${id}", addon);
addon.findUpdates(gVersionInfoPage, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
}
- }),
+ },
onAllUpdatesFinished: function() {
AddonManager.removeAddonListener(listener);
AddonManagerPrivate.recordSimpleMeasure("appUpdate_disabled",
gUpdateWizard.disabled);
AddonManagerPrivate.recordSimpleMeasure("appUpdate_metadata_enabled",
gUpdateWizard.metadataEnabled);
AddonManagerPrivate.recordSimpleMeasure("appUpdate_metadata_disabled",
--- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm
@@ -19,18 +19,16 @@ XPCOMUtils.defineLazyModuleGetter(this,
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DeferredSave",
"resource://gre/modules/DeferredSave.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository_SQLiteMigrator",
"resource://gre/modules/addons/AddonRepository_SQLiteMigrator.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
this.EXPORTED_SYMBOLS = [ "AddonRepository" ];
const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
const PREF_GETADDONS_CACHE_TYPES = "extensions.getAddons.cache.types";
const PREF_GETADDONS_CACHE_ID_ENABLED = "extensions.%ID%.getAddons.cache.enabled"
const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons";
@@ -561,17 +559,17 @@ this.AddonRepository = {
* add-on is not found) is passed to the specified callback. If caching is
* disabled, null is passed to the specified callback.
*
* @param aId
* The id of the add-on to get
* @param aCallback
* The callback to pass the result back to
*/
- getCachedAddonByID: Task.async(function*(aId, aCallback) {
+ getCachedAddonByID: async function(aId, aCallback) {
if (!aId || !this.cacheEnabled) {
aCallback(null);
return;
}
function getAddon(aAddons) {
aCallback(aAddons.get(aId) || null);
}
@@ -581,17 +579,17 @@ this.AddonRepository = {
this._addons = aAddons;
getAddon(aAddons);
});
return;
}
getAddon(this._addons);
- }),
+ },
/**
* Asynchronously repopulate cache so it only contains the add-ons
* corresponding to the specified ids. If caching is disabled,
* the cache is completely removed.
*
* @param aTimeout
* (Optional) timeout in milliseconds to abandon the XHR request
@@ -610,62 +608,62 @@ this.AddonRepository = {
_clearCache: function() {
this._addons = null;
return AddonDatabase.delete().then(() =>
new Promise((resolve, reject) =>
AddonManagerPrivate.updateAddonRepositoryData(resolve))
);
},
- _repopulateCacheInternal: Task.async(function*(aSendPerformance, aTimeout) {
- let allAddons = yield new Promise((resolve, reject) =>
+ _repopulateCacheInternal: async function(aSendPerformance, aTimeout) {
+ let allAddons = await new Promise((resolve, reject) =>
AddonManager.getAllAddons(resolve));
// Filter the hotfix out of our list of add-ons
allAddons = allAddons.filter(a => a.id != AddonManager.hotfixID);
// Completely remove cache if caching is not enabled
if (!this.cacheEnabled) {
logger.debug("Clearing cache because it is disabled");
- yield this._clearCache();
+ await this._clearCache();
return;
}
let ids = allAddons.map(a => a.id);
logger.debug("Repopulate add-on cache with " + ids.toSource());
- let addonsToCache = yield new Promise((resolve, reject) =>
+ let addonsToCache = await new Promise((resolve, reject) =>
getAddonsToCache(ids, resolve));
// Completely remove cache if there are no add-ons to cache
if (addonsToCache.length == 0) {
logger.debug("Clearing cache because 0 add-ons were requested");
- yield this._clearCache();
+ await this._clearCache();
return;
}
- yield new Promise((resolve, reject) =>
+ await new Promise((resolve, reject) =>
this._beginGetAddons(addonsToCache, {
searchSucceeded: aAddons => {
this._addons = new Map();
for (let addon of aAddons) {
this._addons.set(addon.id, addon);
}
AddonDatabase.repopulate(aAddons, resolve);
},
searchFailed: () => {
logger.warn("Search failed when repopulating cache");
resolve();
}
}, aSendPerformance, aTimeout));
// Always call AddonManager updateAddonRepositoryData after we refill the cache
- yield new Promise((resolve, reject) =>
+ await new Promise((resolve, reject) =>
AddonManagerPrivate.updateAddonRepositoryData(resolve));
- }),
+ },
/**
* Asynchronously add add-ons to the cache corresponding to the specified
* ids. If caching is disabled, the cache is unchanged and the callback is
* immediately called if it is defined.
*
* @param aIds
* The array of add-on ids to add to the cache
@@ -1567,23 +1565,23 @@ var AddonDatabase = {
/**
* Asynchronously opens a new connection to the database file.
*
* @return {Promise} a promise that resolves to the database.
*/
openConnection: function() {
if (!this.connectionPromise) {
- this.connectionPromise = Task.spawn(function*() {
+ this.connectionPromise = new Promise(async function() {
this.DB = BLANK_DB();
let inputDB, schema;
try {
- let data = yield OS.File.read(this.jsonFile, { encoding: "utf-8"})
+ let data = await OS.File.read(this.jsonFile, { encoding: "utf-8"})
inputDB = JSON.parse(data);
if (!inputDB.hasOwnProperty("addons") ||
!Array.isArray(inputDB.addons)) {
throw new Error("No addons array.");
}
if (!inputDB.hasOwnProperty("schema")) {
@@ -1607,22 +1605,22 @@ var AddonDatabase = {
this._saveDBToDisk();
let dbSchema = 0;
try {
dbSchema = Services.prefs.getIntPref(PREF_GETADDONS_DB_SCHEMA);
} catch (e) {}
if (dbSchema < DB_MIN_JSON_SCHEMA) {
- let results = yield new Promise((resolve, reject) => {
+ let results = await new Promise((resolve, reject) => {
AddonRepository_SQLiteMigrator.migrate(resolve);
});
if (results.length) {
- yield this._insertAddons(results);
+ await this._insertAddons(results);
}
}
Services.prefs.setIntPref(PREF_GETADDONS_DB_SCHEMA, DB_SCHEMA);
return this.DB;
}
@@ -1767,29 +1765,29 @@ var AddonDatabase = {
/**
* Asynchronously inserts an array of add-ons into the database
*
* @param aAddons
* The array of add-ons to insert
* @param aCallback
* An optional callback to call once complete
*/
- insertAddons: Task.async(function*(aAddons, aCallback) {
- yield this.openConnection();
- yield this._insertAddons(aAddons, aCallback);
- }),
+ insertAddons: async function(aAddons, aCallback) {
+ await this.openConnection();
+ await this._insertAddons(aAddons, aCallback);
+ },
- _insertAddons: Task.async(function*(aAddons, aCallback) {
+ _insertAddons: async function(aAddons, aCallback) {
for (let addon of aAddons) {
this._insertAddon(addon);
}
- yield this._saveDBToDisk();
+ await this._saveDBToDisk();
aCallback && aCallback();
- }),
+ },
/**
* Inserts an individual add-on into the database. If the add-on already
* exists in the database (by id), then the specified add-on will not be
* inserted.
*
* @param aAddon
* The add-on to insert into the database
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
@@ -16,17 +16,16 @@ const CERTDB_CID = Components.ID("{fb0bb
Cu.importGlobalProperties(["fetch", "TextEncoder"]);
Cu.import("resource://gre/modules/AsyncShutdown.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const {EventEmitter} = Cu.import("resource://devtools/shared/event-emitter.js", {});
const {OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "Extension",
"resource://gre/modules/Extension.jsm");
@@ -383,77 +382,77 @@ var AddonTestUtils = {
}
throw new Error("No manifest file present");
} finally {
zip.close();
}
},
- getIDFromManifest: Task.async(function*(manifestURI) {
- let body = yield fetch(manifestURI.spec);
+ getIDFromManifest: async function(manifestURI) {
+ let body = await fetch(manifestURI.spec);
if (manifestURI.spec.endsWith(".rdf")) {
- let data = yield body.text();
+ let data = await body.text();
let ds = new RDFDataSource();
new RDFXMLParser(ds, manifestURI, data);
let rdfID = ds.GetTarget(rdfService.GetResource("urn:mozilla:install-manifest"),
rdfService.GetResource("http://www.mozilla.org/2004/em-rdf#id"),
true);
return rdfID.QueryInterface(Ci.nsIRDFLiteral).Value;
}
- let manifest = yield body.json();
+ let manifest = await body.json();
try {
return manifest.applications.gecko.id;
} catch (e) {
// IDs for WebExtensions are extracted from the certificate when
// not present in the manifest, so just generate a random one.
return uuidGen.generateUUID().number;
}
- }),
+ },
overrideCertDB() {
// Unregister the real database. This only works because the add-ons manager
// hasn't started up and grabbed the certificate database yet.
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
let factory = registrar.getClassObject(CERTDB_CID, Ci.nsIFactory);
registrar.unregisterFactory(CERTDB_CID, factory);
// Get the real DB
let realCertDB = factory.createInstance(null, Ci.nsIX509CertDB);
- let verifyCert = Task.async(function*(file, result, cert, callback) {
+ let verifyCert = async function(file, result, cert, callback) {
if (result == Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED &&
!this.useRealCertChecks && callback.wrappedJSObject) {
// Bypassing XPConnect allows us to create a fake x509 certificate from JS
callback = callback.wrappedJSObject;
try {
let manifestURI = this.getManifestURI(file);
- let id = yield this.getIDFromManifest(manifestURI);
+ let id = await this.getIDFromManifest(manifestURI);
let fakeCert = {commonName: id};
return [callback, Cr.NS_OK, fakeCert];
} catch (e) {
// If there is any error then just pass along the original results
} finally {
// Make sure to close the open zip file or it will be locked.
if (file.isFile())
Services.obs.notifyObservers(file, "flush-cache-entry", "cert-override");
}
}
return [callback, result, cert];
- }).bind(this);
+ };
function FakeCertDB() {
for (let property of Object.keys(realCertDB)) {
if (property in this)
continue;
if (typeof realCertDB[property] == "function")
@@ -712,46 +711,46 @@ var AddonTestUtils = {
// Note these files are being created in the XPI archive with date "0" which is 1970-01-01.
zipW.addEntryStream(path, 0, Ci.nsIZipWriter.COMPRESSION_NONE,
stream, false);
}
zipW.close();
},
- promiseWriteFilesToZip: Task.async(function*(zip, files, flags) {
- yield this.recursiveMakeDir(OS.Path.dirname(zip));
+ promiseWriteFilesToZip: async function(zip, files, flags) {
+ await this.recursiveMakeDir(OS.Path.dirname(zip));
this.writeFilesToZip(zip, files, flags);
return Promise.resolve(nsFile(zip));
- }),
+ },
- promiseWriteFilesToDir: Task.async(function*(dir, files) {
- yield this.recursiveMakeDir(dir);
+ promiseWriteFilesToDir: async function(dir, files) {
+ await this.recursiveMakeDir(dir);
for (let [path, data] of Object.entries(files)) {
path = path.split("/");
let leafName = path.pop();
// Create parent directories, if necessary.
let dirPath = dir;
for (let subDir of path) {
dirPath = OS.Path.join(dirPath, subDir);
- yield OS.Path.makeDir(dirPath, {ignoreExisting: true});
+ await OS.Path.makeDir(dirPath, {ignoreExisting: true});
}
if (typeof data == "string")
data = new TextEncoder("utf-8").encode(data);
- yield OS.File.writeAtomic(OS.Path.join(dirPath, leafName), data);
+ await OS.File.writeAtomic(OS.Path.join(dirPath, leafName), data);
}
return nsFile(dir);
- }),
+ },
promiseWriteFilesToExtension(dir, id, files, unpacked = this.testUnpacked) {
if (typeof files["install.rdf"] === "object")
files["install.rdf"] = this.createInstallRDF(files["install.rdf"]);
if (unpacked) {
let path = OS.Path.join(dir, id);
@@ -928,32 +927,32 @@ var AddonTestUtils = {
let entries = ext.directoryEntries
.QueryInterface(Ci.nsIDirectoryEnumerator);
while (entries.hasMoreElements())
this.setExtensionModifiedTime(entries.nextFile, time);
entries.close();
}
},
- promiseSetExtensionModifiedTime: Task.async(function*(path, time) {
- yield OS.File.setDates(path, time, time);
+ promiseSetExtensionModifiedTime: async function(path, time) {
+ await OS.File.setDates(path, time, time);
let iterator = new OS.File.DirectoryIterator(path);
try {
- yield iterator.forEach(entry => {
+ await iterator.forEach(entry => {
return this.promiseSetExtensionModifiedTime(entry.path, time);
});
} catch (ex) {
if (ex instanceof OS.File.Error)
return;
throw ex;
} finally {
iterator.close().catch(() => {});
}
- }),
+ },
registerDirectory(key, dir) {
var dirProvider = {
getFile(prop, persistent) {
persistent.value = false;
if (prop == key)
return dir.clone();
return null;
@@ -1169,43 +1168,43 @@ var AddonTestUtils = {
* either a generator function, per Task.jsm, or an ordinary
* function which returns promose.
* @return {Promise<[Array<nsIConsoleMessage>, *]>}
* Resolves to an object containing a `messages` property, with
* the array of console messages emitted during the execution
* of the task, and a `result` property, containing the task's
* return value.
*/
- promiseConsoleOutput: Task.async(function*(task) {
+ promiseConsoleOutput: async function(task) {
const DONE = "=== xpcshell test console listener done ===";
let listener, messages = [];
let awaitListener = new Promise(resolve => {
listener = msg => {
if (msg == DONE) {
resolve();
} else {
msg instanceof Ci.nsIScriptError;
messages.push(msg);
}
};
});
Services.console.registerListener(listener);
try {
- let result = yield task();
+ let result = await task();
Services.console.logStringMessage(DONE);
- yield awaitListener;
+ await awaitListener;
return {messages, result};
} finally {
Services.console.unregisterListener(listener);
}
- }),
+ },
};
for (let [key, val] of Object.entries(AddonTestUtils)) {
if (typeof val == "function")
AddonTestUtils[key] = val.bind(AddonTestUtils);
}
EventEmitter.decorate(AddonTestUtils);
--- a/toolkit/mozapps/extensions/internal/GMPProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/GMPProvider.jsm
@@ -13,17 +13,16 @@ this.EXPORTED_SYMBOLS = [];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AddonManager.jsm");
/* globals AddonManagerPrivate*/
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
/* globals OS*/
Cu.import("resource://gre/modules/Log.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/GMPUtils.jsm");
/* globals EME_ADOBE_ID, GMP_PLUGIN_IDS, GMPPrefs, GMPUtils, OPEN_H264_ID, WIDEVINE_ID */
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource://gre/modules/UpdateUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(
this, "GMPInstallManager", "resource://gre/modules/GMPInstallManager.jsm");
XPCOMUtils.defineLazyModuleGetter(
@@ -282,40 +281,40 @@ GMPWrapper.prototype = {
}
if (this._updateTask !== null) {
this._log.trace("findUpdates() - " + this._plugin.id +
" - update task already running");
return this._updateTask;
}
- this._updateTask = Task.spawn(function*() {
+ this._updateTask = async function() {
this._log.trace("findUpdates() - updateTask");
try {
let installManager = new GMPInstallManager();
- let res = yield installManager.checkForAddons();
+ let res = await installManager.checkForAddons();
let update = res.gmpAddons.find(addon => addon.id === this._plugin.id);
if (update && update.isValid && !update.isInstalled) {
this._log.trace("findUpdates() - found update for " +
this._plugin.id + ", installing");
- yield installManager.installAddon(update);
+ await installManager.installAddon(update);
} else {
this._log.trace("findUpdates() - no updates for " + this._plugin.id);
}
this._log.info("findUpdates() - updateTask succeeded for " +
this._plugin.id);
} catch (e) {
this._log.error("findUpdates() - updateTask for " + this._plugin.id +
" threw", e);
throw e;
} finally {
this._updateTask = null;
return true;
}
- }.bind(this));
+ }
return this._updateTask;
},
get pluginMimeTypes() { return []; },
get pluginLibraries() {
if (this.isInstalled) {
let path = this.version;
@@ -589,34 +588,34 @@ var GMPProvider = {
this._log.warn("startup - adding clearkey CDM failed", e);
}
},
shutdown: function() {
this._log.trace("shutdown");
Preferences.ignore(GMPPrefs.KEY_LOG_BASE, configureLogging);
- let shutdownTask = Task.spawn(function*() {
+ let shutdownTask = async function() {
this._log.trace("shutdown - shutdownTask");
let shutdownSucceeded = true;
for (let plugin of this._plugins.values()) {
try {
- yield plugin.wrapper.shutdown();
+ await plugin.wrapper.shutdown();
} catch (e) {
shutdownSucceeded = false;
}
}
this._plugins = null;
if (!shutdownSucceeded) {
throw new Error("Shutdown failed");
}
- }.bind(this));
+ }
return shutdownTask;
},
getAddonByID: function(aId, aCallback) {
if (!this.isEnabled) {
aCallback(null);
return;
--- a/toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm
+++ b/toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm
@@ -18,17 +18,16 @@ const LOCAL_EME_SOURCES = [{
}];
this.EXPORTED_SYMBOLS = [ "ProductAddonChecker" ];
Cu.importGlobalProperties(["XMLHttpRequest"]);
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/CertUtils.jsm");
/* globals checkCert, BadCertHandler*/
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
/* globals GMPPrefs */
@@ -295,22 +294,22 @@ function downloadFile(url) {
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
createInstance(Ci.nsISupports);
xhr.onload = function(response) {
logger.info("downloadXHR File download. status=" + xhr.status);
if (xhr.status != 200 && xhr.status != 206) {
reject(Components.Exception("File download failed", xhr.status));
return;
}
- Task.spawn(function* () {
- let f = yield OS.File.openUnique(OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon"));
+ new Promise(async function() {
+ let f = await OS.File.openUnique(OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon"));
let path = f.path;
logger.info(`Downloaded file will be saved to ${path}`);
- yield f.file.close();
- yield OS.File.writeAtomic(path, new Uint8Array(xhr.response));
+ await f.file.close();
+ await OS.File.writeAtomic(path, new Uint8Array(xhr.response));
return path;
}).then(resolve, reject);
};
let fail = (event) => {
let request = event.target;
let status = getRequestStatus(request);
let message = "Failed downloading via XHR, status: " + status + ", reason: " + event.type;
@@ -352,63 +351,63 @@ function binaryToHex(input) {
*
* @param hashFunction
* The type of hash function to use, must be supported by nsICryptoHash.
* @param path
* The path of the file to hash.
* @return a promise that resolves to hash of the file or rejects with a JS
* exception in case of error.
*/
-var computeHash = Task.async(function*(hashFunction, path) {
- let file = yield OS.File.open(path, { existing: true, read: true });
+var computeHash = async function(hashFunction, path) {
+ let file = await OS.File.open(path, { existing: true, read: true });
try {
let hasher = Cc["@mozilla.org/security/hash;1"].
createInstance(Ci.nsICryptoHash);
hasher.initWithString(hashFunction);
let bytes;
do {
- bytes = yield file.read(HASH_CHUNK_SIZE);
+ bytes = await file.read(HASH_CHUNK_SIZE);
hasher.update(bytes, bytes.length);
} while (bytes.length == HASH_CHUNK_SIZE);
return binaryToHex(hasher.finish(false));
}
finally {
- yield file.close();
+ await file.close();
}
-});
+};
/**
* Verifies that a downloaded file matches what was expected.
*
* @param properties
* The properties to check, `size` and `hashFunction` with `hashValue`
* are supported. Any properties missing won't be checked.
* @param path
* The path of the file to check.
* @return a promise that resolves if the file matched or rejects with a JS
* exception in case of error.
*/
-var verifyFile = Task.async(function*(properties, path) {
+var verifyFile = async function(properties, path) {
if (properties.size !== undefined) {
- let stat = yield OS.File.stat(path);
+ let stat = await OS.File.stat(path);
if (stat.size != properties.size) {
throw new Error("Downloaded file was " + stat.size + " bytes but expected " + properties.size + " bytes.");
}
}
if (properties.hashFunction !== undefined) {
let expectedDigest = properties.hashValue.toLowerCase();
- let digest = yield computeHash(properties.hashFunction, path);
+ let digest = await computeHash(properties.hashFunction, path);
if (digest != expectedDigest) {
throw new Error("Hash was `" + digest + "` but expected `" + expectedDigest + "`.");
}
}
-});
+};
const ProductAddonChecker = {
/**
* Downloads a list of add-ons from a URL optionally testing the SSL
* certificate for certain attributes.
*
* @param url
* The url to download from.
@@ -431,20 +430,20 @@ const ProductAddonChecker = {
* Downloads an add-on to a local file and checks that it matches the expected
* file. The caller is responsible for deleting the temporary file returned.
*
* @param addon
* The addon to download.
* @return a promise that resolves to the temporary file downloaded or rejects
* with a JS exception in case of error.
*/
- downloadAddon: Task.async(function*(addon) {
- let path = yield downloadFile(addon.URL);
+ downloadAddon: async function(addon) {
+ let path = await downloadFile(addon.URL);
try {
- yield verifyFile(addon, path);
+ await verifyFile(addon, path);
return path;
}
catch (e) {
- yield OS.File.remove(path);
+ await OS.File.remove(path);
throw e;
}
- })
+ }
}
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -38,18 +38,16 @@ XPCOMUtils.defineLazyModuleGetter(this,
XPCOMUtils.defineLazyModuleGetter(this, "ZipUtils",
"resource://gre/modules/ZipUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PermissionsUtils",
"resource://gre/modules/PermissionsUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserToolboxProcess",
"resource://devtools/client/framework/ToolboxProcess.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPI",
"resource://gre/modules/Console.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ProductAddonChecker",
"resource://gre/modules/addons/ProductAddonChecker.jsm");
@@ -931,28 +929,28 @@ function getRDFProperty(aDs, aResource,
* Reads an AddonInternal object from a manifest stream.
*
* @param aUri
* A |file:| or |jar:| URL for the manifest
* @return an AddonInternal object
* @throws if the install manifest in the stream is corrupt or could not
* be read
*/
-var loadManifestFromWebManifest = Task.async(function*(aUri) {
+async function loadManifestFromWebManifest(aUri) {
// We're passed the URI for the manifest file. Get the URI for its
// parent directory.
let uri = NetUtil.newURI("./", null, aUri);
let extension = new ExtensionData(uri);
- let manifest = yield extension.readManifest();
+ let manifest = await extension.readManifest();
// Read the list of available locales, and pre-load messages for
// all locales.
- let locales = yield extension.initAllLocales();
+ let locales = await extension.initAllLocales();
// If there were any errors loading the extension, bail out now.
if (extension.errors.length)
throw new Error("Extension is invalid");
let bss = (manifest.browser_specific_settings && manifest.browser_specific_settings.gecko)
|| (manifest.applications && manifest.applications.gecko) || {};
if (manifest.browser_specific_settings && manifest.applications) {
@@ -1041,30 +1039,30 @@ var loadManifestFromWebManifest = Task.a
maxVersion: bss.strict_max_version,
}];
addon.targetPlatforms = [];
addon.userDisabled = false;
addon.softDisabled = addon.blocklistState == Blocklist.STATE_SOFTBLOCKED;
return addon;
-});
+}
/**
* Reads an AddonInternal object from an RDF stream.
*
* @param aUri
* The URI that the manifest is being read from
* @param aStream
* An open stream to read the RDF from
* @return an AddonInternal object
* @throws if the install manifest in the RDF stream is corrupt or could not
* be read
*/
-let loadManifestFromRDF = Task.async(function*(aUri, aStream) {
+async function loadManifestFromRDF(aUri, aStream) {
function getPropertyArray(aDs, aSource, aProperty) {
let values = [];
let targets = aDs.GetTargets(aSource, EM_R(aProperty), true);
while (targets.hasMoreElements())
values.push(getRDFValue(targets.getNext()));
return values;
}
@@ -1202,17 +1200,17 @@ let loadManifestFromRDF = Task.async(fun
addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE &&
addon.optionsType != AddonManager.OPTIONS_TYPE_TAB &&
addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE_INFO) {
throw new Error("Install manifest specifies unknown type: " + addon.optionsType);
}
if (addon.hasEmbeddedWebExtension) {
let uri = NetUtil.newURI("webextension/manifest.json", null, aUri);
- let embeddedAddon = yield loadManifestFromWebManifest(uri);
+ let embeddedAddon = await loadManifestFromWebManifest(uri);
if (embeddedAddon.optionsURL) {
if (addon.optionsType || addon.optionsURL)
logger.warn(`Addon ${addon.id} specifies optionsType or optionsURL ` +
`in both install.rdf and manifest.json`);
addon.optionsURL = embeddedAddon.optionsURL;
addon.optionsType = embeddedAddon.optionsType;
}
@@ -1329,17 +1327,17 @@ let loadManifestFromRDF = Task.async(fun
addon.updateURL = null;
addon.updateKey = null;
}
// icons will be filled by the calling function
addon.icons = {};
return addon;
-});
+}
function defineSyncGUID(aAddon) {
// Define .syncGUID as a lazy property which is also settable
Object.defineProperty(aAddon, "syncGUID", {
get: () => {
// Generate random GUID used for Sync.
let guid = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator)
@@ -1376,42 +1374,42 @@ function generateTemporaryInstallID(aFil
/**
* Loads an AddonInternal object from an add-on extracted in a directory.
*
* @param aDir
* The nsIFile directory holding the add-on
* @return an AddonInternal object
* @throws if the directory does not contain a valid install manifest
*/
-var loadManifestFromDir = Task.async(function*(aDir, aInstallLocation) {
+async function loadManifestFromDir(aDir, aInstallLocation) {
function getFileSize(aFile) {
if (aFile.isSymlink())
return 0;
if (!aFile.isDirectory())
return aFile.fileSize;
let size = 0;
let entries = aFile.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator);
let entry;
while ((entry = entries.nextFile))
size += getFileSize(entry);
entries.close();
return size;
}
- function* loadFromRDF(aUri) {
+ async function loadFromRDF(aUri) {
let fis = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
fis.init(aUri.file, -1, -1, false);
let bis = Cc["@mozilla.org/network/buffered-input-stream;1"].
createInstance(Ci.nsIBufferedInputStream);
bis.init(fis, 4096);
try {
- var addon = yield loadManifestFromRDF(aUri, bis);
+ var addon = await loadManifestFromRDF(aUri, bis);
} finally {
bis.close();
fis.close();
}
let iconFile = aDir.clone();
iconFile.append("icon.png");
@@ -1440,56 +1438,56 @@ var loadManifestFromDir = Task.async(fun
throw new Error("Directory " + aDir.path + " does not contain a valid " +
"install manifest");
}
let uri = Services.io.newFileURI(file).QueryInterface(Ci.nsIFileURL);
let addon;
if (file.leafName == FILE_WEB_MANIFEST) {
- addon = yield loadManifestFromWebManifest(uri);
+ addon = await loadManifestFromWebManifest(uri);
if (!addon.id) {
if (aInstallLocation == TemporaryInstallLocation) {
addon.id = generateTemporaryInstallID(aDir);
} else {
addon.id = aDir.leafName;
}
}
} else {
- addon = yield loadFromRDF(uri);
+ addon = await loadFromRDF(uri);
}
addon._sourceBundle = aDir.clone();
addon._installLocation = aInstallLocation;
addon.size = getFileSize(aDir);
- addon.signedState = yield verifyDirSignedState(aDir, addon)
+ addon.signedState = await verifyDirSignedState(aDir, addon)
.then(({signedState}) => signedState);
addon.appDisabled = !isUsableAddon(addon);
defineSyncGUID(addon);
return addon;
-});
+}
/**
* Loads an AddonInternal object from an nsIZipReader for an add-on.
*
* @param aZipReader
* An open nsIZipReader for the add-on's files
* @return an AddonInternal object
* @throws if the XPI file does not contain a valid install manifest
*/
-var loadManifestFromZipReader = Task.async(function*(aZipReader, aInstallLocation) {
- function* loadFromRDF(aUri) {
+async function loadManifestFromZipReader(aZipReader, aInstallLocation) {
+ async function loadFromRDF(aUri) {
let zis = aZipReader.getInputStream(entry);
let bis = Cc["@mozilla.org/network/buffered-input-stream;1"].
createInstance(Ci.nsIBufferedInputStream);
bis.init(zis, 4096);
try {
- var addon = yield loadManifestFromRDF(aUri, bis);
+ var addon = await loadManifestFromRDF(aUri, bis);
} finally {
bis.close();
zis.close();
}
if (aZipReader.hasEntry("icon.png")) {
addon.icons[32] = "icon.png";
addon.icons[48] = "icon.png";
@@ -1518,28 +1516,28 @@ var loadManifestFromZipReader = Task.asy
"install manifest");
}
let uri = buildJarURI(aZipReader.file, entry);
let isWebExtension = (entry == FILE_WEB_MANIFEST);
let addon = isWebExtension ?
- yield loadManifestFromWebManifest(uri) :
- yield loadFromRDF(uri);
+ await loadManifestFromWebManifest(uri) :
+ await loadFromRDF(uri);
addon._sourceBundle = aZipReader.file;
addon._installLocation = aInstallLocation;
addon.size = 0;
let entries = aZipReader.findEntries(null);
while (entries.hasMore())
addon.size += aZipReader.getEntry(entries.getNext()).realSize;
- let {signedState, cert} = yield verifyZipSignedState(aZipReader.file, addon);
+ let {signedState, cert} = await verifyZipSignedState(aZipReader.file, addon);
addon.signedState = signedState;
if (isWebExtension && !addon.id) {
if (cert) {
addon.id = cert.commonName;
if (!gIDTest.test(addon.id)) {
throw new Error(`Webextension is signed with an invalid id (${addon.id})`);
}
}
@@ -1547,42 +1545,42 @@ var loadManifestFromZipReader = Task.asy
addon.id = generateTemporaryInstallID(aZipReader.file);
}
}
addon.appDisabled = !isUsableAddon(addon);
defineSyncGUID(addon);
return addon;
-});
+}
/**
* Loads an AddonInternal object from an add-on in an XPI file.
*
* @param aXPIFile
* An nsIFile pointing to the add-on's XPI file
* @return an AddonInternal object
* @throws if the XPI file does not contain a valid install manifest
*/
-var loadManifestFromZipFile = Task.async(function*(aXPIFile, aInstallLocation) {
+async function loadManifestFromZipFile(aXPIFile, aInstallLocation) {
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(Ci.nsIZipReader);
try {
zipReader.open(aXPIFile);
// Can't return this promise because that will make us close the zip reader
// before it has finished loading the manifest. Wait for the result and then
// return.
- let manifest = yield loadManifestFromZipReader(zipReader, aInstallLocation);
+ let manifest = await loadManifestFromZipReader(zipReader, aInstallLocation);
return manifest;
}
finally {
zipReader.close();
}
-});
+}
function loadManifestFromFile(aFile, aInstallLocation) {
if (aFile.isFile())
return loadManifestFromZipFile(aFile, aInstallLocation);
return loadManifestFromDir(aFile, aInstallLocation);
}
/**
@@ -1940,33 +1938,31 @@ function escapeAddonURI(aAddon, aUri, aU
compatMode = "ignore";
else if (AddonManager.strictCompatibility)
compatMode = "strict";
uri = uri.replace(/%COMPATIBILITY_MODE%/g, compatMode);
return uri;
}
-function removeAsync(aFile) {
- return Task.spawn(function*() {
- let info = null;
- try {
- info = yield OS.File.stat(aFile.path);
- if (info.isDir)
- yield OS.File.removeDir(aFile.path);
- else
- yield OS.File.remove(aFile.path);
- }
- catch (e) {
- if (!(e instanceof OS.File.Error) || ! e.becauseNoSuchFile)
- throw e;
- // The file has already gone away
- return;
- }
- });
+async function removeAsync(aFile) {
+ let info = null;
+ try {
+ info = await OS.File.stat(aFile.path);
+ if (info.isDir)
+ await OS.File.removeDir(aFile.path);
+ else
+ await OS.File.remove(aFile.path);
+ }
+ catch (e) {
+ if (!(e instanceof OS.File.Error) || ! e.becauseNoSuchFile)
+ throw e;
+ // The file has already gone away
+ return;
+ }
}
/**
* Recursively removes a directory or file fixing permissions when necessary.
*
* @param aFile
* The nsIFile to remove
*/
@@ -3113,41 +3109,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*() {
+ updateSystemAddons: async function() {
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 => {
@@ -3167,66 +3163,66 @@ 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;
}
@@ -3245,77 +3241,75 @@ this.XPIProvider = {
try {
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));
// Bug 1204156: Switch to the new system add-ons without requiring a restart
}
finally {
// Delete the temporary files
logger.info("Deleting temporary files");
for (let item of addonList.values()) {
// If this item downloaded delete the temporary file.
if (item.path) {
try {
- yield OS.File.remove(item.path);
+ await OS.File.remove(item.path);
}
catch (e) {
logger.warn(`Failed to remove temporary file ${item.path}.`, e);
}
}
}
- yield systemAddonLocation.cleanDirectories();
- }
- }),
+ await systemAddonLocation.cleanDirectories();
+ }
+ },
/**
* Verifies that all installed add-ons are still correctly signed.
*/
- verifySignatures: function() {
- XPIDatabase.getAddonList(a => true, (addons) => {
- Task.spawn(function*() {
- let changes = {
- enabled: [],
- disabled: []
- };
-
- for (let addon of addons) {
- // The add-on might have vanished, we'll catch that on the next startup
- if (!addon._sourceBundle.exists())
- continue;
-
- let signedState = yield verifyBundleSignedState(addon._sourceBundle, addon);
-
- if (signedState != addon.signedState) {
- addon.signedState = signedState;
- AddonManagerPrivate.callAddonListeners("onPropertyChanged",
- addon.wrapper,
- ["signedState"]);
- }
-
- let disabled = XPIProvider.updateAddonDisabledState(addon);
- if (disabled !== undefined)
- changes[disabled ? "disabled" : "enabled"].push(addon.id);
- }
-
- XPIDatabase.saveChanges();
-
- Services.obs.notifyObservers(null, "xpi-signature-changed", JSON.stringify(changes));
- }).then(null, err => {
- logger.error("XPI_verifySignature: " + err);
- })
- });
+ verifySignatures: async function() {
+ let addons = await new Promise(
+ resolve => XPIDatabase.getAddonList(a => true, resolve),
+ ).catch(err => logger.error("XPI_verifySignature: " + err));
+
+ let changes = {
+ enabled: [],
+ disabled: []
+ };
+
+ for (let addon of addons) {
+ // The add-on might have vanished, we'll catch that on the next startup
+ if (!addon._sourceBundle.exists())
+ continue;
+
+ let signedState = await verifyBundleSignedState(addon._sourceBundle, addon);
+
+ if (signedState != addon.signedState) {
+ addon.signedState = signedState;
+ AddonManagerPrivate.callAddonListeners("onPropertyChanged",
+ addon.wrapper,
+ ["signedState"]);
+ }
+
+ let disabled = XPIProvider.updateAddonDisabledState(addon);
+ if (disabled !== undefined)
+ changes[disabled ? "disabled" : "enabled"].push(addon.id);
+ }
+
+ XPIDatabase.saveChanges();
+
+ Services.obs.notifyObservers(null, "xpi-signature-changed", JSON.stringify(changes));
},
/**
* Persists changes to XPIProvider.bootstrappedAddons to its store (a pref).
*/
persistBootstrappedAddons: function() {
// Experiments are disabled upon app load, so don't persist references.
let filtered = {};
@@ -4067,41 +4061,41 @@ this.XPIProvider = {
* Permanently installs add-on from a local XPI file or directory.
* The signature is checked but the add-on persist on application restart.
*
* @param aFile
* An nsIFile for the unpacked add-on directory or XPI file.
*
* @return See installAddonFromLocation return value.
*/
- installAddonFromSources: Task.async(function*(aFile) {
+ installAddonFromSources: async function(aFile) {
let location = XPIProvider.installLocationsByName[KEY_APP_PROFILE];
return this.installAddonFromLocation(aFile, location, "proxy");
- }),
+ },
/**
* Installs add-on from a local XPI file or directory.
*
* @param aFile
* An nsIFile for the unpacked add-on directory or XPI file.
* @param aInstallLocation
* Define a custom install location object to use for the install.
* @param aInstallAction
* Optional action mode to use when installing the addon
* (see MutableDirectoryInstallLocation.installAddon)
*
* @return a Promise that resolves to an Addon object on success, or rejects
* if the add-on is not a valid restartless add-on or if the
* same ID is already installed.
*/
- installAddonFromLocation: Task.async(function*(aFile, aInstallLocation, aInstallAction) {
+ installAddonFromLocation: async function(aFile, aInstallLocation, aInstallAction) {
if (aFile.exists() && aFile.isFile()) {
flushJarCache(aFile);
}
- let addon = yield loadManifestFromFile(aFile, aInstallLocation);
+ let addon = await loadManifestFromFile(aFile, aInstallLocation);
aInstallLocation.installAddon({ id: addon.id, source: aFile, action: aInstallAction });
if (addon.appDisabled) {
let message = `Add-on ${addon.id} is not compatible with application version.`;
let app = addon.matchingTargetApplication;
if (app) {
@@ -4115,17 +4109,17 @@ this.XPIProvider = {
throw new Error(message);
}
if (!addon.bootstrap) {
throw new Error("Only restartless (bootstrap) add-ons"
+ " can be installed from sources:", addon.id);
}
let installReason = BOOTSTRAP_REASONS.ADDON_INSTALL;
- let oldAddon = yield new Promise(
+ let oldAddon = await new Promise(
resolve => XPIDatabase.getVisibleAddonForID(addon.id, resolve));
if (oldAddon) {
if (!oldAddon.bootstrap) {
logger.warn("Non-restartless Add-on is already installed", addon.id);
throw new Error("Non-restartless add-on with ID "
+ oldAddon.id + " is already installed");
}
else {
@@ -4180,17 +4174,17 @@ this.XPIProvider = {
BOOTSTRAP_REASONS.ADDON_ENABLE);
AddonManagerPrivate.callInstallListeners("onExternalInstall",
null, addon.wrapper,
oldAddon ? oldAddon.wrapper : null,
false);
AddonManagerPrivate.callAddonListeners("onInstalled", addon.wrapper);
return addon.wrapper;
- }),
+ },
/**
* Returns an Addon corresponding to an instance ID.
* @param aInstanceID
* An Addon Instance ID
* @return {Promise}
* @resolves The found Addon or null if no such add-on exists.
* @rejects Never
@@ -5773,27 +5767,27 @@ AddonInstall.prototype = {
/**
* Fills out linkedInstalls with AddonInstall instances for the other files
* in a multi-package XPI.
*
* @param aFiles
* An array of { entryName, file } for each remaining file from the
* multi-package XPI.
*/
- _createLinkedInstalls: Task.async(function*(aFiles) {
+ _createLinkedInstalls: async function(aFiles) {
if (aFiles.length == 0)
return;
// Create new AddonInstall instances for every remaining file
if (!this.linkedInstalls)
this.linkedInstalls = [];
for (let { entryName, file } of aFiles) {
logger.debug("Creating linked install from " + entryName);
- let install = yield new Promise(resolve => AddonInstall.createInstall(resolve, file));
+ let install = await new Promise(resolve => AddonInstall.createInstall(resolve, file));
// Make the new install own its temporary file
install.ownsTempFile = true;
this.linkedInstalls.push(install);
// If one of the internal XPIs was multipackage then move its linked
// installs to the outer install
@@ -5802,30 +5796,30 @@ AddonInstall.prototype = {
install.linkedInstalls = null;
}
install.sourceURI = this.sourceURI;
install.releaseNotesURI = this.releaseNotesURI;
if (install.state != AddonManager.STATE_DOWNLOAD_FAILED)
install.updateAddonURIs();
}
- }),
+ },
/**
* Loads add-on manifests from a multi-package XPI file. Each of the
* XPI and JAR files contained in the XPI will be extracted. Any that
* do not contain valid add-ons will be ignored. The first valid add-on will
* be installed by this AddonInstall instance, the rest will have new
* AddonInstall instances created for them.
*
* @param aZipReader
* An open nsIZipReader for the multi-package XPI's files. This will
* be closed before this method returns.
*/
- _loadMultipackageManifests: Task.async(function*(aZipReader) {
+ _loadMultipackageManifests: async function(aZipReader) {
let files = [];
let entries = aZipReader.findEntries("(*.[Xx][Pp][Ii]|*.[Jj][Aa][Rr])");
while (entries.hasMore()) {
let entryName = entries.getNext();
let file = getTemporaryFile();
try {
aZipReader.extract(entryName, file);
files.push({ entryName, file });
@@ -5846,22 +5840,22 @@ AddonInstall.prototype = {
let addon = null;
// Find the first file that is a valid install and use it for
// the add-on that this AddonInstall instance will install.
for (let { entryName, file } of files) {
this.removeTemporaryFile();
try {
- yield this.loadManifest(file);
+ await this.loadManifest(file);
logger.debug("Base multi-package XPI install came from " + entryName);
this.file = file;
this.ownsTempFile = true;
- yield this._createLinkedInstalls(files.filter(f => f.file != file));
+ await this._createLinkedInstalls(files.filter(f => f.file != file));
return undefined;
}
catch (e) {
// _createLinkedInstalls will log errors when it tries to process this
// file
}
}
@@ -5871,41 +5865,41 @@ AddonInstall.prototype = {
file.remove(true);
} catch (e) {
this.logger.warn("Could not remove temp file " + file.path);
}
}
return Promise.reject([AddonManager.ERROR_CORRUPT_FILE,
"Multi-package XPI does not contain any valid packages to install"]);
- }),
+ },
/**
* Called after the add-on is a local file and the signature and install
* manifest can be read.
*
* @param aCallback
* A function to call when the manifest has been loaded
* @throws if the add-on does not contain a valid install manifest or the
* XPI is incorrectly signed
*/
- loadManifest: Task.async(function*(file) {
+ loadManifest: async function(file) {
let zipreader = Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(Ci.nsIZipReader);
try {
zipreader.open(file);
}
catch (e) {
zipreader.close();
return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, e]);
}
try {
// loadManifestFromZipReader performs the certificate verification for us
- this.addon = yield loadManifestFromZipReader(zipreader, this.installLocation);
+ this.addon = await loadManifestFromZipReader(zipreader, this.installLocation);
}
catch (e) {
zipreader.close();
return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, e]);
}
// A multi-package XPI is a container, the add-ons it holds each
// have their own id. Everything else had better have an id here.
@@ -5983,32 +5977,32 @@ AddonInstall.prototype = {
this.name = this.addon.selectedLocale.name;
this.type = this.addon.type;
this.version = this.addon.version;
// Setting the iconURL to something inside the XPI locks the XPI and
// makes it impossible to delete on Windows.
// Try to load from the existing cache first
- let repoAddon = yield new Promise(resolve => AddonRepository.getCachedAddonByID(this.addon.id, resolve));
+ let repoAddon = await new Promise(resolve => AddonRepository.getCachedAddonByID(this.addon.id, resolve));
// It wasn't there so try to re-download it
if (!repoAddon) {
- yield new Promise(resolve => AddonRepository.cacheAddons([this.addon.id], resolve));
- repoAddon = yield new Promise(resolve => AddonRepository.getCachedAddonByID(this.addon.id, resolve));
+ await new Promise(resolve => AddonRepository.cacheAddons([this.addon.id], resolve));
+ repoAddon = await new Promise(resolve => AddonRepository.getCachedAddonByID(this.addon.id, resolve));
}
this.addon._repositoryAddon = repoAddon;
this.name = this.name || this.addon._repositoryAddon.name;
this.addon.compatibilityOverrides = repoAddon ?
repoAddon.compatibilityOverrides :
null;
this.addon.appDisabled = !isUsableAddon(this.addon);
return undefined;
- }),
+ },
observe: function(aSubject, aTopic, aData) {
// Network is going offline
this.cancel();
},
/**
* Starts downloading the add-on's XPI file.
@@ -6290,107 +6284,107 @@ AddonInstall.prototype = {
else
logger.debug("downloadFailed: listener changed AddonInstall state for " +
this.sourceURI.spec + " to " + this.state);
},
/**
* Notify listeners that the download completed.
*/
- downloadCompleted: function() {
- XPIDatabase.getVisibleAddonForID(this.addon.id, aAddon => {
- if (aAddon)
- this.existingAddon = aAddon;
-
- this.state = AddonManager.STATE_DOWNLOADED;
- this.addon.updateDate = Date.now();
-
- if (this.existingAddon) {
- this.addon.existingAddonID = this.existingAddon.id;
- this.addon.installDate = this.existingAddon.installDate;
- applyBlocklistChanges(this.existingAddon, this.addon);
- }
- else {
- this.addon.installDate = this.addon.updateDate;
- }
-
- if (AddonManagerPrivate.callInstallListeners("onDownloadEnded",
- this.listeners,
- this.wrapper)) {
- // If a listener changed our state then do not proceed with the install
- if (this.state != AddonManager.STATE_DOWNLOADED)
- return;
-
- // If an upgrade listener is registered for this add-on, pass control
- // over the upgrade to the add-on.
- if (AddonManagerPrivate.hasUpgradeListener(this.addon.id)) {
- logger.info(`${this.addon.id} has an upgrade listener, postponing until restart`);
- this.state = AddonManager.STATE_POSTPONED;
-
- let stagingDir = this.installLocation.getStagingDir();
- let stagedAddon = stagingDir.clone();
-
- Task.spawn((function*() {
- yield this.installLocation.requestStagingDir();
-
- yield this.unstageInstall(stagedAddon);
-
- stagedAddon.append(this.addon.id);
- stagedAddon.leafName = this.addon.id + ".xpi";
-
- yield this.stageInstall(true, stagedAddon, true);
-
- AddonManagerPrivate.callInstallListeners("onInstallPostponed",
- this.listeners, this.wrapper)
-
- // upgrade has been staged for restart, notify the add-on and give
- // it a way to resume.
- let callback = AddonManagerPrivate.getUpgradeListener(this.addon.id);
- callback({
- version: this.version,
- install: () => {
- switch (this.state) {
- case AddonManager.STATE_INSTALLED:
- // this addon has already been installed, nothing to do
- logger.warn(`${this.addon.id} tried to resume postponed upgrade, but it's already installed`);
- break;
- case AddonManager.STATE_POSTPONED:
- logger.info(`${this.addon.id} has resumed a previously postponed upgrade`);
- this.state = AddonManager.STATE_DOWNLOADED;
- this.installLocation.releaseStagingDir();
- this.install();
- break;
- default:
- logger.warn(`${this.addon.id} cannot resume postponed upgrade from state (${this.state})`);
- break;
- }
- },
- });
- }).bind(this));
- } else {
- // no upgrade listener present, so proceed with normal install
- this.install();
- if (this.linkedInstalls) {
- for (let install of this.linkedInstalls) {
- if (install.state == AddonManager.STATE_DOWNLOADED)
- install.install();
+ downloadCompleted: async function() {
+ let aAddon = await new Promise(
+ resolve => XPIDatabase.getVisibleAddonForID(this.addon.id, resolve)
+ );
+ if (aAddon) {
+ this.existingAddon = aAddon;
+ }
+
+ this.state = AddonManager.STATE_DOWNLOADED;
+ this.addon.updateDate = Date.now();
+
+ if (this.existingAddon) {
+ this.addon.existingAddonID = this.existingAddon.id;
+ this.addon.installDate = this.existingAddon.installDate;
+ applyBlocklistChanges(this.existingAddon, this.addon);
+ }
+ else {
+ this.addon.installDate = this.addon.updateDate;
+ }
+
+ if (AddonManagerPrivate.callInstallListeners("onDownloadEnded",
+ this.listeners,
+ this.wrapper)) {
+ // If a listener changed our state then do not proceed with the install
+ if (this.state != AddonManager.STATE_DOWNLOADED)
+ return;
+
+ // If an upgrade listener is registered for this add-on, pass control
+ // over the upgrade to the add-on.
+ if (AddonManagerPrivate.hasUpgradeListener(this.addon.id)) {
+ logger.info(`${this.addon.id} has an upgrade listener, postponing until restart`);
+ this.state = AddonManager.STATE_POSTPONED;
+
+ let stagingDir = this.installLocation.getStagingDir();
+ let stagedAddon = stagingDir.clone();
+
+ await this.installLocation.requestStagingDir();
+
+ await this.unstageInstall(stagedAddon);
+
+ stagedAddon.append(this.addon.id);
+ stagedAddon.leafName = this.addon.id + ".xpi";
+
+ await this.stageInstall(true, stagedAddon, true);
+
+ AddonManagerPrivate.callInstallListeners("onInstallPostponed",
+ this.listeners, this.wrapper)
+
+ // upgrade has been staged for restart, notify the add-on and give
+ // it a way to resume.
+ let callback = AddonManagerPrivate.getUpgradeListener(this.addon.id);
+ callback({
+ version: this.version,
+ install: () => {
+ switch (this.state) {
+ case AddonManager.STATE_INSTALLED:
+ // this addon has already been installed, nothing to do
+ logger.warn(`${this.addon.id} tried to resume postponed upgrade, but it's already installed`);
+ break;
+ case AddonManager.STATE_POSTPONED:
+ logger.info(`${this.addon.id} has resumed a previously postponed upgrade`);
+ this.state = AddonManager.STATE_DOWNLOADED;
+ this.installLocation.releaseStagingDir();
+ this.install();
+ break;
+ default:
+ logger.warn(`${this.addon.id} cannot resume postponed upgrade from state (${this.state})`);
+ break;
}
+ },
+ });
+ } else {
+ // no upgrade listener present, so proceed with normal install
+ this.install();
+ if (this.linkedInstalls) {
+ for (let install of this.linkedInstalls) {
+ if (install.state == AddonManager.STATE_DOWNLOADED)
+ install.install();
}
}
}
- });
+ }
},
// TODO This relies on the assumption that we are always installing into the
// highest priority install location so the resulting add-on will be visible
// overriding any existing copy in another install location (bug 557710).
/**
* Installs the add-on into the install location.
*/
- startInstall: function() {
+ startInstall: async function() {
this.state = AddonManager.STATE_INSTALLING;
if (!AddonManagerPrivate.callInstallListeners("onInstallStarted",
this.listeners, this.wrapper)) {
this.state = AddonManager.STATE_DOWNLOADED;
XPIProvider.removeActiveInstall(this);
AddonManagerPrivate.callInstallListeners("onInstallCancelled",
this.listeners, this.wrapper)
return;
@@ -6414,28 +6408,28 @@ AddonInstall.prototype = {
logger.debug("Starting install of " + this.addon.id + " from " + this.sourceURI.spec);
AddonManagerPrivate.callAddonListeners("onInstalling",
this.addon.wrapper,
requiresRestart);
let stagingDir = this.installLocation.getStagingDir();
let stagedAddon = stagingDir.clone();
- Task.spawn((function*() {
+ let install = new Promise(async function() {
let installedUnpacked = 0;
- yield this.installLocation.requestStagingDir();
+ await this.installLocation.requestStagingDir();
// remove any previously staged files
- yield this.unstageInstall(stagedAddon);
+ await this.unstageInstall(stagedAddon);
stagedAddon.append(this.addon.id);
stagedAddon.leafName = this.addon.id + ".xpi";
- installedUnpacked = yield this.stageInstall(requiresRestart, stagedAddon, isUpgrade);
+ installedUnpacked = await this.stageInstall(requiresRestart, stagedAddon, isUpgrade);
if (requiresRestart) {
this.state = AddonManager.STATE_INSTALLED;
AddonManagerPrivate.callInstallListeners("onInstallEnded",
this.listeners, this.wrapper,
this.addon.wrapper);
}
else {
@@ -6533,57 +6527,59 @@ AddonInstall.prototype = {
// XXX this makes it dangerous to do some things in onInstallEnded
// listeners because important cleanup hasn't been done yet
XPIProvider.unloadBootstrapScope(this.addon.id);
}
}
XPIProvider.setTelemetry(this.addon.id, "unpacked", installedUnpacked);
recordAddonTelemetry(this.addon);
}
- }).bind(this)).then(null, (e) => {
+ }).then(null, (e) => {
logger.warn("Failed to install " + this.file.path + " from " + this.sourceURI.spec + " to " + stagedAddon.path, e);
if (stagedAddon.exists())
recursiveRemove(stagedAddon);
this.state = AddonManager.STATE_INSTALL_FAILED;
this.error = AddonManager.ERROR_FILE_ACCESS;
XPIProvider.removeActiveInstall(this);
AddonManagerPrivate.callAddonListeners("onOperationCancelled",
this.addon.wrapper);
AddonManagerPrivate.callInstallListeners("onInstallFailed",
this.listeners,
this.wrapper);
}).then(() => {
this.removeTemporaryFile();
return this.installLocation.releaseStagingDir();
});
+
+ await install();
},
/**
* Stages an upgrade for next application restart.
*/
- stageInstall: function*(restartRequired, stagedAddon, isUpgrade) {
+ stageInstall: async function(restartRequired, stagedAddon, isUpgrade) {
let stagedJSON = stagedAddon.clone();
stagedJSON.leafName = this.addon.id + ".json";
let installedUnpacked = 0;
// First stage the file regardless of whether restarting is necessary
if (this.addon.unpack || Preferences.get(PREF_XPI_UNPACK, false)) {
logger.debug("Addon " + this.addon.id + " will be installed as " +
"an unpacked directory");
stagedAddon.leafName = this.addon.id;
- yield OS.File.makeDir(stagedAddon.path);
- yield ZipUtils.extractFilesAsync(this.file, stagedAddon);
+ await OS.File.makeDir(stagedAddon.path);
+ await ZipUtils.extractFilesAsync(this.file, stagedAddon);
installedUnpacked = 1;
}
else {
logger.debug("Addon " + this.addon.id + " will be installed as " +
"a packed xpi");
stagedAddon.leafName = this.addon.id + ".xpi";
- yield OS.File.copy(this.file.path, stagedAddon.path);
+ await OS.File.copy(this.file.path, stagedAddon.path);
}
if (restartRequired) {
// Point the add-on to its extracted files as the xpi may get deleted
this.addon._sourceBundle = stagedAddon;
// Cache the AddonInternal as it may have updated compatibility info
writeStringToFile(stagedJSON, JSON.stringify(this.addon));
@@ -6596,30 +6592,30 @@ AddonInstall.prototype = {
}
return installedUnpacked;
},
/**
* Removes any previously staged upgrade.
*/
- unstageInstall: function*(stagedAddon) {
+ unstageInstall: async function(stagedAddon) {
let stagedJSON = stagedAddon.clone();
let removedAddon = stagedAddon.clone();
stagedJSON.append(this.addon.id + ".json");
if (stagedJSON.exists()) {
stagedJSON.remove(true);
}
removedAddon.append(this.addon.id);
- yield removeAsync(removedAddon);
+ await removeAsync(removedAddon);
removedAddon.leafName = this.addon.id + ".xpi";
- yield removeAsync(removedAddon);
+ await removeAsync(removedAddon);
},
getInterface: function(iid) {
if (iid.equals(Ci.nsIAuthPrompt2)) {
let win = this.window;
if (!win && this.browser)
win = this.browser.ownerDocument.defaultView;
@@ -7250,25 +7246,22 @@ AddonInternal.prototype = {
this.appDisabled = !isUsableAddon(this);
},
/**
* getDataDirectory tries to execute the callback with two arguments:
* 1) the path of the data directory within the profile,
* 2) any exception generated from trying to build it.
*/
- getDataDirectory: function(callback) {
+ getDataDirectory: async function(callback) {
let parentPath = OS.Path.join(OS.Constants.Path.profileDir, "extension-data");
let dirPath = OS.Path.join(parentPath, this.id);
- Task.spawn(function*() {
- yield OS.File.makeDir(parentPath, {ignoreExisting: true});
- yield OS.File.makeDir(dirPath, {ignoreExisting: true});
- }).then(() => callback(dirPath, null),
- e => callback(dirPath, e));
+ await OS.File.makeDir(parentPath, {ignoreExisting: true});
+ await OS.File.makeDir(dirPath, {ignoreExisting: true});
},
/**
* toJSON is called by JSON.stringify in order to create a filtered version
* of this object to be serialized to a JSON file. A new object is returned
* with copies of all non-private properties. Functions, getters and setters
* are not copied.
*
@@ -8694,114 +8687,114 @@ Object.assign(SystemAddonInstallLocation
this._saveAddonSet({ schema: 1, addons: {} });
},
/**
* 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*() {
+ cleanDirectories: async function() {
// 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 => {
+ await iterator.forEach(entry => {
// Skip the directory currently in use
if (this._directory && this._directory.path == entry.path)
return;
// Skip the next directory
if (this._nextDir && this._nextDir.path == entry.path)
return;
entries.push(entry);
});
for (let entry of entries) {
if (entry.isDir) {
- yield OS.File.removeDir(entry.path, {
+ await OS.File.removeDir(entry.path, {
ignoreAbsent: true,
ignorePermissions: true,
});
}
else {
- yield OS.File.remove(entry.path, {
+ 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. We wait to switch state until a restart.
*/
- installAddonSet: Task.async(function*(aAddons) {
+ installAddonSet: async function(aAddons) {
// Make sure the base dir exists
- yield OS.File.makeDir(this._baseDir.path, { ignoreExisting: true });
+ await OS.File.makeDir(this._baseDir.path, { ignoreExisting: true });
let newDir = this._baseDir.clone();
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) {
// Directory already exists, pick another
}
}
- let copyAddon = Task.async(function*(addon) {
+ let copyAddon = async function(addon) {
let target = OS.Path.join(newDir.path, addon.id + ".xpi");
logger.info(`Copying ${addon.id} from ${addon._sourceBundle.path} to ${target}.`);
try {
- yield OS.File.copy(addon._sourceBundle.path, target);
+ await OS.File.copy(addon._sourceBundle.path, target);
}
catch (e) {
logger.error(`Failed to copy ${addon.id} from ${addon._sourceBundle.path} to ${target}.`, e);
throw e;
}
addon._sourceBundle = new nsIFile(target);
- });
+ };
try {
- yield waitForAllPromises(aAddons.map(copyAddon));
+ await waitForAllPromises(aAddons.map(copyAddon));
}
catch (e) {
try {
- yield OS.File.removeDir(newDir.path, { ignorePermissions: true });
+ await OS.File.removeDir(newDir.path, { ignorePermissions: true });
}
catch (e) {
logger.warn(`Failed to remove new system add-on directory ${newDir.path}.`, e);
}
throw e;
}
// All add-ons in position, create the new state and store it in prefs
@@ -8809,17 +8802,17 @@ Object.assign(SystemAddonInstallLocation
for (let addon of aAddons) {
state.addons[addon.id] = {
version: addon.version
}
}
this._saveAddonSet(state);
this._nextDir = newDir;
- }),
+ },
});
/**
* An object which identifies an install location for temporary add-ons.
*/
const TemporaryInstallLocation = {
locked: false,
name: KEY_APP_TEMPORARY,
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -219,20 +219,20 @@ function asyncMap(aObjects, aMethod, aCa
}
/**
* A generator to synchronously return result rows from an mozIStorageStatement.
*
* @param aStatement
* The statement to execute
*/
-function* resultRows(aStatement) {
+async function resultRows(aStatement) {
try {
while (stepStatement(aStatement))
- yield aStatement.row;
+ await aStatement.row;
}
finally {
aStatement.reset();
}
}
/**
* A helper function to log an SQL error.
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -24,18 +24,16 @@ try {
}
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
- "resource://gre/modules/Task.jsm");
const TOOLKIT_ID = "toolkit@mozilla.org";
const KEY_PROFILEDIR = "ProfD";
const KEY_APPDIR = "XCurProcD";
const FILE_BLOCKLIST = "blocklist.xml";
const PREF_BLOCKLIST_LASTUPDATETIME = "app.update.lastUpdateTime.blocklist-background-update-timer";
const PREF_BLOCKLIST_URL = "extensions.blocklist.url";
const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL";
@@ -634,17 +632,17 @@ Blocklist.prototype = {
{});
updater.checkVersions().catch(() => {
// Before we enable this in release, we want to collect telemetry on
// failed kinto updates - see bug 1254099
});
}
},
- onXMLLoad: Task.async(function*(aEvent) {
+ onXMLLoad: async function(aEvent) {
let request = aEvent.target;
try {
gCertUtils.checkCert(request.channel);
}
catch (e) {
LOG("Blocklist::onXMLLoad: " + e);
return;
}
@@ -663,21 +661,21 @@ Blocklist.prototype = {
this._loadBlocklistFromString(request.responseText);
// We don't inform the users when the graphics blocklist changed at runtime.
// However addons and plugins blocking status is refreshed.
this._blocklistUpdated(oldAddonEntries, oldPluginEntries);
try {
let path = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST);
- yield OS.File.writeAtomic(path, request.responseText, {tmpPath: path + ".tmp"});
+ await OS.File.writeAtomic(path, request.responseText, {tmpPath: path + ".tmp"});
} catch (e) {
LOG("Blocklist::onXMLLoad: " + e);
}
- }),
+ },
onXMLError: function(aEvent) {
try {
var request = aEvent.target;
// the following may throw (e.g. a local file or timeout)
var status = request.status;
}
catch (e) {
@@ -849,54 +847,54 @@ Blocklist.prototype = {
/* Used for testing */
_clear: function() {
this._addonEntries = null;
this._gfxEntries = null;
this._pluginEntries = null;
this._preloadedBlocklistContent = null;
},
- _preloadBlocklist: Task.async(function*() {
+ _preloadBlocklist: async function() {
let profPath = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST);
try {
- yield this._preloadBlocklistFile(profPath);
+ await this._preloadBlocklistFile(profPath);
return;
} catch (e) {
LOG("Blocklist::_preloadBlocklist: Failed to load XML file " + e)
}
var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]);
try {
- yield this._preloadBlocklistFile(appFile.path);
+ await this._preloadBlocklistFile(appFile.path);
return;
} catch (e) {
LOG("Blocklist::_preloadBlocklist: Failed to load XML file " + e)
}
LOG("Blocklist::_preloadBlocklist: no XML File found");
- }),
+ },
- _preloadBlocklistFile: Task.async(function*(path) {
+ _preloadBlocklistFile: async function(path) {
if (this._addonEntries) {
// The file has been already loaded.
return;
}
if (!gBlocklistEnabled) {
LOG("Blocklist::_preloadBlocklistFile: blocklist is disabled");
return;
}
- let text = yield OS.File.read(path, { encoding: "utf-8" });
+ let text = await OS.File.read(path, { encoding: "utf-8" });
if (!this._addonEntries) {
// Store the content only if a sync load has not been performed in the meantime.
this._preloadedBlocklistContent = text;
}
- }),
+ },
_loadBlocklistFromString : function(text) {
try {
var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
createInstance(Ci.nsIDOMParser);
var doc = parser.parseFromString(text, "text/xml");
if (doc.documentElement.namespaceURI != XMLURI_BLOCKLIST) {
LOG("Blocklist::_loadBlocklistFromFile: aborting due to incorrect " +