Bug 1009332: Present certain internal add-on types as other types through the API. r=billm
authorDave Townsend <dtownsend@oxymoronical.com>
Fri, 07 Aug 2015 13:13:59 -0700
changeset 288642 1e52038911911ee778fc2837a21a658a7dcd621b
parent 288600 9dccd6cceff0ae5963ece393805b5c9f67312c4d
child 288643 bce7e1052bff5199b37c9d9f75dae4092b928adb
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1009332
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1009332: Present certain internal add-on types as other types through the API. r=billm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -193,23 +193,31 @@ const TYPES = {
   extension: 2,
   theme: 4,
   locale: 8,
   multipackage: 32,
   dictionary: 64,
   experiment: 128,
 };
 
+// Some add-on types that we track internally are presented as other types
+// externally
+const TYPE_ALIASES = {
+  "webextension": "extension",
+};
+
 const RESTARTLESS_TYPES = new Set([
+  "webextension",
   "dictionary",
   "experiment",
   "locale",
 ]);
 
 const SIGNED_TYPES = new Set([
+  "webextension",
   "extension",
   "experiment",
 ]);
 
 // Whether add-on signing is required.
 function mustSign(aType) {
   if (!SIGNED_TYPES.has(aType))
     return false;
@@ -633,16 +641,56 @@ function createAddonDetails(id, aAddon) 
     id: id || aAddon.id,
     type: aAddon.type,
     version: aAddon.version,
     multiprocessCompatible: aAddon.multiprocessCompatible
   };
 }
 
 /**
+ * Converts an internal add-on type to the type presented through the API.
+ *
+ * @param  aType
+ *         The internal add-on type
+ * @return an external add-on type
+ */
+function getExternalType(aType) {
+  if (aType in TYPE_ALIASES)
+    return TYPE_ALIASES[aType];
+  return aType;
+}
+
+/**
+ * Converts a list of API types to a list of API types and any aliases for those
+ * types.
+ *
+ * @param  aTypes
+ *         An array of types or null for all types
+ * @return an array of types or null for all types
+ */
+function getAllAliasesForTypes(aTypes) {
+  if (!aTypes)
+    return null;
+
+  // Build a set of all requested types and their aliases
+  let typeset = new Set(aTypes);
+
+  for (let alias of Object.keys(TYPE_ALIASES)) {
+    // Ignore any requested internal types
+    typeset.delete(alias);
+
+    // Add any alias for the internal type
+    if (typeset.has(TYPE_ALIASES[alias]))
+      typeset.add(alias);
+  }
+
+  return [...typeset];
+}
+
+/**
  * Converts an RDF literal, resource or integer into a string.
  *
  * @param  aLiteral
  *         The RDF object to convert
  * @return a string if the object could be converted or null
  */
 function getRDFValue(aLiteral) {
   if (aLiteral instanceof Ci.nsIRDFLiteral)
@@ -3950,17 +3998,19 @@ this.XPIProvider = {
    * Called to get Addons of a particular type.
    *
    * @param  aTypes
    *         An array of types to fetch. Can be null to get all types.
    * @param  aCallback
    *         A callback to pass an array of Addons to
    */
   getAddonsByTypes: function XPI_getAddonsByTypes(aTypes, aCallback) {
-    XPIDatabase.getVisibleAddons(aTypes, function getAddonsByTypes_getVisibleAddons(aAddons) {
+    let typesToGet = getAllAliasesForTypes(aTypes);
+
+    XPIDatabase.getVisibleAddons(typesToGet, function getAddonsByTypes_getVisibleAddons(aAddons) {
       aCallback([createWrapper(a) for each (a in aAddons)]);
     });
   },
 
   /**
    * Obtain an Addon having the specified Sync GUID.
    *
    * @param  aGUID
@@ -3979,17 +4029,19 @@ this.XPIProvider = {
    *
    * @param  aTypes
    *         An array of types to fetch. Can be null to get all types
    * @param  aCallback
    *         A callback to pass an array of Addons to
    */
   getAddonsWithOperationsByTypes:
   function XPI_getAddonsWithOperationsByTypes(aTypes, aCallback) {
-    XPIDatabase.getVisibleAddonsWithPendingOperations(aTypes,
+    let typesToGet = getAllAliasesForTypes(aTypes);
+
+    XPIDatabase.getVisibleAddonsWithPendingOperations(typesToGet,
       function getAddonsWithOpsByTypes_getVisibleAddonsWithPendingOps(aAddons) {
       let results = [createWrapper(a) for each (a in aAddons)];
       XPIProvider.installs.forEach(function(aInstall) {
         if (aInstall.state == AddonManager.STATE_INSTALLED &&
             !(aInstall.addon.inDatabase))
           results.push(createWrapper(aInstall.addon));
       });
       aCallback(results);
@@ -4003,17 +4055,17 @@ this.XPIProvider = {
    * @param  aTypes
    *         An array of types or null to get all types
    * @param  aCallback
    *         A callback to pass the array of AddonInstalls to
    */
   getInstallsByTypes: function XPI_getInstallsByTypes(aTypes, aCallback) {
     let results = [];
     this.installs.forEach(function(aInstall) {
-      if (!aTypes || aTypes.indexOf(aInstall.type) >= 0)
+      if (!aTypes || aTypes.indexOf(getExternalType(aInstall.type)) >= 0)
         results.push(aInstall.wrapper);
     });
     aCallback(results);
   },
 
   /**
    * Synchronously map a URI to the corresponding Addon ID.
    *
@@ -6142,21 +6194,23 @@ AddonInstall.createUpdate = function AI_
  */
 function AddonInstallWrapper(aInstall) {
 #ifdef MOZ_EM_DEBUG
   this.__defineGetter__("__AddonInstallInternal__", function AIW_debugGetter() {
     return aInstall;
   });
 #endif
 
-  ["name", "type", "version", "icons", "releaseNotesURI", "file", "state", "error",
+  ["name", "version", "icons", "releaseNotesURI", "file", "state", "error",
    "progress", "maxProgress", "certificate", "certName"].forEach(function(aProp) {
     this.__defineGetter__(aProp, function AIW_propertyGetter() aInstall[aProp]);
   }, this);
 
+  this.__defineGetter__("type", () => getExternalType(aInstall.type));
+
   this.__defineGetter__("iconURL", function AIW_iconURL() aInstall.icons[32]);
 
   this.__defineGetter__("existingAddon", function AIW_existingAddonGetter() {
     return createWrapper(aInstall.existingAddon);
   });
   this.__defineGetter__("addon", function AIW_addonGetter() createWrapper(aInstall.addon));
   this.__defineGetter__("sourceURI", function AIW_sourceURIGetter() aInstall.sourceURI);
 
@@ -6729,24 +6783,26 @@ function AddonWrapper(aAddon) {
     if (repositoryAddon && (aProp in repositoryAddon) &&
         (objValue === undefined || objValue === null)) {
       return [repositoryAddon[aProp], true];
     }
 
     return [objValue, false];
   }
 
-  ["id", "syncGUID", "version", "type", "isCompatible", "isPlatformCompatible",
+  ["id", "syncGUID", "version", "isCompatible", "isPlatformCompatible",
    "providesUpdatesSecurely", "blocklistState", "blocklistURL", "appDisabled",
    "softDisabled", "skinnable", "size", "foreignInstall", "hasBinaryComponents",
    "strictCompatibility", "compatibilityOverrides", "updateURL",
    "getDataDirectory", "multiprocessCompatible", "signedState"].forEach(function(aProp) {
      this.__defineGetter__(aProp, function AddonWrapper_propertyGetter() aAddon[aProp]);
   }, this);
 
+  this.__defineGetter__("type", () => getExternalType(aAddon.type));
+
   ["fullDescription", "developerComments", "eula", "supportURL",
    "contributionURL", "contributionAmount", "averageRating", "reviewCount",
    "reviewURL", "totalDownloads", "weeklyDownloads", "dailyUsers",
    "repositoryStatus"].forEach(function(aProp) {
     this.__defineGetter__(aProp, function AddonWrapper_repoPropertyGetter() {
       if (aAddon._repositoryAddon)
         return aAddon._repositoryAddon[aProp];