Bug 1454202: Part 3a - Promisify more internal add-on manager methods. r?aswan draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 15 Apr 2018 13:54:07 -0700
changeset 782443 793fdda3efb4d9935be55478eeae39c69e19e236
parent 782442 823dcf8466a773161add1c3a1eb28aab110ce578
child 782444 548449a0a83cc11b6e1f11f381e7827a8456084f
push id106537
push usermaglione.k@gmail.com
push dateMon, 16 Apr 2018 03:19:09 +0000
reviewersaswan
bugs1454202
milestone61.0a1
Bug 1454202: Part 3a - Promisify more internal add-on manager methods. r?aswan MozReview-Commit-ID: G91c0RGcSty
toolkit/mozapps/extensions/internal/XPIInstall.jsm
toolkit/mozapps/extensions/internal/XPIProviderUtils.js
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -1888,19 +1888,17 @@ var LocalAddonInstall = class extends Ad
       XPIProvider.removeActiveInstall(this);
       AddonManagerPrivate.callInstallListeners("onNewInstall",
                                                this.listeners,
                                                this.wrapper);
       flushJarCache(this.file);
       return;
     }
 
-    let addon = await new Promise(resolve => {
-      XPIDatabase.getVisibleAddonForID(this.addon.id, resolve);
-    });
+    let addon = await XPIDatabase.getVisibleAddonForID(this.addon.id);
 
     this.existingAddon = addon;
     this.addon.updateBlocklistState({oldAddon: this.existingAddon});
     this.addon.updateDate = Date.now();
     this.addon.installDate = addon ? addon.installDate : this.addon.updateDate;
 
     if (!this.addon.isCompatible) {
       this.state = AddonManager.STATE_CHECKING;
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -66,68 +66,42 @@ const PROP_JSON_FIELDS = ["id", "syncGUI
                           "blocklistState", "blocklistURL", "startupData"];
 
 // Time to wait before async save of XPI JSON database, in milliseconds
 const ASYNC_SAVE_DELAY_MS = 20;
 
 /**
  * Asynchronously fill in the _repositoryAddon field for one addon
  */
-function getRepositoryAddon(aAddon, aCallback) {
-  if (!aAddon) {
-    aCallback(aAddon);
-    return;
+async function getRepositoryAddon(aAddon, aCallback) {
+  let addon;
+  if (aAddon) {
+    addon = await AddonRepository.getCachedAddonByID(aAddon.id);
+    aAddon._repositoryAddon = addon;
   }
-  AddonRepository.getCachedAddonByID(aAddon.id, repoAddon => {
-    aAddon._repositoryAddon = repoAddon;
-    aCallback(aAddon);
-  });
+  if (aCallback) {
+    aCallback(addon);
+  }
+  return addon;
 }
 
 /**
  * Wrap an API-supplied function in an exception handler to make it safe to call
  */
 function makeSafe(aCallback) {
   return function(...aArgs) {
     try {
       aCallback(...aArgs);
     } catch (ex) {
       logger.warn("XPI Database callback failed", ex);
     }
   };
 }
 
 /**
- * A helper method to asynchronously call a function on an array of objects.
- * Returns a promise that resolves with the results for each function call in
- * the same order as the aObjects array.
- * WARNING: not currently error-safe; if the async function does not call its
- * callback for any of the array elements, asyncMap will never resolve.
- *
- * @param  aObjects
- *         The array of objects to process asynchronously
- * @param  aMethod
- *         Function with signature function(object, function(f_of_object))
- */
-function asyncMap(aObjects, aMethod) {
-  let methodCalls = aObjects.map(obj => {
-    return new Promise(resolve => {
-      try {
-        aMethod(obj, resolve);
-      } catch (e) {
-        logger.error("Async map function failed", e);
-        resolve(undefined);
-      }
-    });
-  });
-
-  return Promise.all(methodCalls);
-}
-
-/**
  * Copies properties from one object to another. If no target object is passed
  * a new object will be created and returned.
  *
  * @param  aObject
  *         An object to copy from
  * @param  aProperties
  *         An array of properties to be copied
  * @param  aTarget
@@ -658,17 +632,17 @@ this.XPIDatabase = {
    *         aFilter or an empty array if none match.
    * @return a Promise that resolves to the list of add-ons matching aFilter or
    *         an empty array if none match
    */
   async getAddonList(aFilter, aCallback) {
     try {
       let addonDB = await this.asyncLoadDB();
       let addonList = _filterDB(addonDB, aFilter);
-      let addons = await asyncMap(addonList, getRepositoryAddon);
+      let addons = await Promise.all(addonList.map(addon => getRepositoryAddon(addon)));
       if (aCallback) {
         makeSafe(aCallback)(addons);
       }
       return addons;
     } catch (error) {
       logger.error("getAddonList failed", error);
       if (aCallback) {
         makeSafe(aCallback)([]);
@@ -683,17 +657,17 @@ this.XPIDatabase = {
    *         Function that takes an addon instance and returns
    *         true if that addon should be selected
    * @param  aCallback
    *         Called back with the addon, or null if no matching addon is found
    */
   getAddon(aFilter, aCallback) {
     return this.asyncLoadDB().then(
       addonDB => {
-        getRepositoryAddon(_findAddon(addonDB, aFilter), makeSafe(aCallback));
+        return getRepositoryAddon(_findAddon(addonDB, aFilter));
       })
     .catch(
         error => {
           logger.error("getAddon failed", error);
           makeSafe(aCallback)(null);
         });
   },
 
@@ -704,59 +678,59 @@ this.XPIDatabase = {
    * @param  aId
    *         The ID of the add-on to retrieve
    * @param  aLocation
    *         The name of the install location
    * @param  aCallback
    *         A callback to pass the DBAddonInternal to
    */
   getAddonInLocation(aId, aLocation, aCallback) {
-    this.asyncLoadDB().then(
+    return this.asyncLoadDB().then(
         addonDB => getRepositoryAddon(addonDB.get(aLocation + ":" + aId),
                                       makeSafe(aCallback)));
   },
 
   /**
    * Asynchronously get all the add-ons in a particular install location.
    *
    * @param  aLocation
    *         The name of the install location
    * @param  aCallback
    *         A callback to pass the array of DBAddonInternals to
    */
   getAddonsInLocation(aLocation, aCallback) {
-    this.getAddonList(aAddon => aAddon._installLocation.name == aLocation, aCallback);
+    return this.getAddonList(aAddon => aAddon._installLocation.name == aLocation, aCallback);
   },
 
   /**
    * Asynchronously gets the add-on with the specified ID that is visible.
    *
    * @param  aId
    *         The ID of the add-on to retrieve
    * @param  aCallback
    *         A callback to pass the DBAddonInternal to
    */
   getVisibleAddonForID(aId, aCallback) {
-    this.getAddon(aAddon => ((aAddon.id == aId) && aAddon.visible),
-                  aCallback);
+    return this.getAddon(aAddon => ((aAddon.id == aId) && aAddon.visible),
+                         aCallback);
   },
 
   /**
    * Asynchronously gets the visible add-ons, optionally restricting by type.
    *
    * @param  aTypes
    *         An array of types to include or null to include all types
    * @param  aCallback
    *         A callback to pass the array of DBAddonInternals to
    */
   getVisibleAddons(aTypes, aCallback) {
-    this.getAddonList(aAddon => (aAddon.visible &&
-                                 (!aTypes || (aTypes.length == 0) ||
-                                  (aTypes.indexOf(aAddon.type) > -1))),
-                      aCallback);
+    return this.getAddonList(aAddon => (aAddon.visible &&
+                                        (!aTypes || (aTypes.length == 0) ||
+                                         (aTypes.indexOf(aAddon.type) > -1))),
+                             aCallback);
   },
 
   /**
    * Synchronously gets all add-ons of a particular type(s).
    *
    * @param  aType, aType2, ...
    *         The type(s) of add-on to retrieve
    * @return an array of DBAddonInternals
@@ -802,17 +776,17 @@ this.XPIDatabase = {
    * Asynchronously gets all add-ons with pending operations.
    *
    * @param  aTypes
    *         The types of add-ons to retrieve or null to get all types
    * @param  aCallback
    *         A callback to pass the array of DBAddonInternal to
    */
   getVisibleAddonsWithPendingOperations(aTypes, aCallback) {
-    this.getAddonList(
+    return this.getAddonList(
         aAddon => (aAddon.visible &&
                    aAddon.pendingUninstall &&
                    (!aTypes || (aTypes.length == 0) || (aTypes.indexOf(aAddon.type) > -1))),
         aCallback);
   },
 
   /**
    * Asynchronously get an add-on by its Sync GUID.
@@ -820,18 +794,18 @@ this.XPIDatabase = {
    * @param  aGUID
    *         Sync GUID of add-on to fetch
    * @param  aCallback
    *         A callback to pass the DBAddonInternal record to. Receives null
    *         if no add-on with that GUID is found.
    *
    */
   getAddonBySyncGUID(aGUID, aCallback) {
-    this.getAddon(aAddon => aAddon.syncGUID == aGUID,
-                  aCallback);
+    return this.getAddon(aAddon => aAddon.syncGUID == aGUID,
+                         aCallback);
   },
 
   /**
    * Synchronously gets all add-ons in the database.
    * This is only called from the preference observer for the default
    * compatibility version preference, so we can return an empty list if
    * we haven't loaded the database yet.
    *