Bug 1471522 - Move blocklist target app filter to Blocklist module r=Gijs
authorMathieu Leplatre <mathieu@mozilla.com>
Wed, 15 May 2019 22:22:50 +0000
changeset 532831 bf04bcac450c62314cd6d4deed2b3629651c54e4
parent 532830 afaf68ba6e54f8309317b3d346396178fde23fb7
child 532832 e1080b62268c73c6b920dd1a826310d12c55127b
push id11272
push userapavel@mozilla.com
push dateThu, 16 May 2019 15:28:22 +0000
treeherdermozilla-beta@2265bfc5920d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1471522
milestone68.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 1471522 - Move blocklist target app filter to Blocklist module r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D31222
services/common/blocklist-clients.js
toolkit/mozapps/extensions/Blocklist.jsm
--- a/services/common/blocklist-clients.js
+++ b/services/common/blocklist-clients.js
@@ -177,81 +177,16 @@ async function updatePinningList({ data:
     } catch (e) {
       // prevent errors relating to individual preload entries from causing
       // sync to fail. We will accumulate telemetry for such failures in bug
       // 1254099.
     }
   }
 }
 
-/**
- * This custom filter function is used to limit the entries returned
- * by `RemoteSettings("...").get()` depending on the target app information
- * defined on entries.
- *
- * Note that this is async because `jexlFilterFunc` is async.
- */
-async function targetAppFilter(entry, environment) {
-  // If the entry has a JEXL filter expression, it should prevail.
-  // The legacy target app mechanism will be kept in place for old entries.
-  // See https://bugzilla.mozilla.org/show_bug.cgi?id=1463377
-  const { filter_expression } = entry;
-  if (filter_expression) {
-    return jexlFilterFunc(entry, environment);
-  }
-
-  // Keep entries without target information.
-  if (!("versionRange" in entry)) {
-    return entry;
-  }
-
-  const { appID, version: appVersion, toolkitVersion } = environment;
-  const { versionRange } = entry;
-
-  // Everywhere in this method, we avoid checking the minVersion, because
-  // we want to retain items whose minVersion is higher than the current
-  // app version, so that we have the items around for app updates.
-
-  // Gfx blocklist has a specific versionRange object, which is not a list.
-  if (!Array.isArray(versionRange)) {
-    const { maxVersion = "*" } = versionRange;
-    const matchesRange = (Services.vc.compare(appVersion, maxVersion) <= 0);
-    return matchesRange ? entry : null;
-  }
-
-  // Iterate the targeted applications, at least one of them must match.
-  // If no target application, keep the entry.
-  if (versionRange.length == 0) {
-    return entry;
-  }
-  for (const vr of versionRange) {
-    const { targetApplication = [] } = vr;
-    if (targetApplication.length == 0) {
-      return entry;
-    }
-    for (const ta of targetApplication) {
-      const { guid } = ta;
-      if (!guid) {
-        return entry;
-      }
-      const { maxVersion = "*" } = ta;
-      if (guid == appID &&
-          Services.vc.compare(appVersion, maxVersion) <= 0) {
-        return entry;
-      }
-      if (guid == "toolkit@mozilla.org" &&
-          Services.vc.compare(toolkitVersion, maxVersion) <= 0) {
-        return entry;
-      }
-    }
-  }
-  // Skip this entry.
-  return null;
-}
-
 var OneCRLBlocklistClient;
 var PinningBlocklistClient;
 var RemoteSecuritySettingsClient;
 
 function initialize(options = {}) {
   const { verifySignature = true } = options;
 
   OneCRLBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_SECURITY_SETTINGS_ONECRL_COLLECTION), {
@@ -286,10 +221,10 @@ function initialize(options = {}) {
   }
 
   return {
     OneCRLBlocklistClient,
     PinningBlocklistClient,
   };
 }
 
-let BlocklistClients = {initialize, targetAppFilter};
+let BlocklistClients = {initialize};
 
--- a/toolkit/mozapps/extensions/Blocklist.jsm
+++ b/toolkit/mozapps/extensions/Blocklist.jsm
@@ -27,16 +27,18 @@ ChromeUtils.defineModuleGetter(this, "Bl
 ChromeUtils.defineModuleGetter(this, "CertUtils",
                                "resource://gre/modules/CertUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "FileUtils",
                                "resource://gre/modules/FileUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "OS",
                                "resource://gre/modules/osfile.jsm");
 ChromeUtils.defineModuleGetter(this, "RemoteSettings",
                                "resource://services-settings/remote-settings.js");
+ChromeUtils.defineModuleGetter(this, "jexlFilterFunc",
+                               "resource://services-settings/remote-settings.js");
 ChromeUtils.defineModuleGetter(this, "ServiceRequest",
                                "resource://gre/modules/ServiceRequest.jsm");
 ChromeUtils.defineModuleGetter(this, "UpdateUtils",
                                "resource://gre/modules/UpdateUtils.jsm");
 
   /**
 #    The blocklist XML file looks something like this:
 #
@@ -271,16 +273,85 @@ const Utils = {
   _createBlocklistURL(id) {
     let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL);
     return url.replace(/%blockID%/g, id);
   },
 
 };
 
 /**
+ * This custom filter function is used to limit the entries returned
+ * by `RemoteSettings("...").get()` depending on the target app information
+ * defined on entries.
+ *
+ * Note that this is async because `jexlFilterFunc` is async.
+ *
+ * @param {Object} entry a Remote Settings record
+ * @param {Object} environment the JEXL environment object.
+ * @returns {Object} The entry if it matches, `null` otherwise.
+ */
+async function targetAppFilter(entry, environment) {
+  // If the entry has a JEXL filter expression, it should prevail.
+  // The legacy target app mechanism will be kept in place for old entries.
+  // See https://bugzilla.mozilla.org/show_bug.cgi?id=1463377
+  const { filter_expression } = entry;
+  if (filter_expression) {
+    return jexlFilterFunc(entry, environment);
+  }
+
+  // Keep entries without target information.
+  if (!("versionRange" in entry)) {
+    return entry;
+  }
+
+  const { appID, version: appVersion, toolkitVersion } = environment;
+  const { versionRange } = entry;
+
+  // Everywhere in this method, we avoid checking the minVersion, because
+  // we want to retain items whose minVersion is higher than the current
+  // app version, so that we have the items around for app updates.
+
+  // Gfx blocklist has a specific versionRange object, which is not a list.
+  if (!Array.isArray(versionRange)) {
+    const { maxVersion = "*" } = versionRange;
+    const matchesRange = (Services.vc.compare(appVersion, maxVersion) <= 0);
+    return matchesRange ? entry : null;
+  }
+
+  // Iterate the targeted applications, at least one of them must match.
+  // If no target application, keep the entry.
+  if (versionRange.length == 0) {
+    return entry;
+  }
+  for (const vr of versionRange) {
+    const { targetApplication = [] } = vr;
+    if (targetApplication.length == 0) {
+      return entry;
+    }
+    for (const ta of targetApplication) {
+      const { guid } = ta;
+      if (!guid) {
+        return entry;
+      }
+      const { maxVersion = "*" } = ta;
+      if (guid == appID &&
+        Services.vc.compare(appVersion, maxVersion) <= 0) {
+        return entry;
+      }
+      if (guid == "toolkit@mozilla.org" &&
+        Services.vc.compare(toolkitVersion, maxVersion) <= 0) {
+        return entry;
+      }
+    }
+  }
+  // Skip this entry.
+  return null;
+}
+
+/**
  * The Graphics blocklist implementation. The JSON objects for graphics blocks look
  * something like:
  *
  * {
  *  "blockID": "g35",
  *  "os": "WINNT 6.1",
  *  "vendor": "0xabcd",
  *  "devices": [
@@ -305,17 +376,17 @@ this.GfxBlocklistRS = {
     if (this._initialized || !gBlocklistEnabled) {
       return;
     }
     this._initialized = true;
     this._client = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_GFX_COLLECTION), {
       bucketNamePref: PREF_BLOCKLIST_BUCKET,
       lastCheckTimePref: PREF_BLOCKLIST_GFX_CHECKED_SECONDS,
       signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_GFX_SIGNER),
-      filterFunc: BlocklistClients.targetAppFilter,
+      filterFunc: targetAppFilter,
     });
     this.checkForEntries = this.checkForEntries.bind(this);
     this._client.on("sync", this.checkForEntries);
   },
 
   shutdown() {
     if (this._client) {
       this._client.off("sync", this.checkForEntries);
@@ -480,17 +551,17 @@ this.PluginBlocklistRS = {
           } catch (ex) { /* Ignore invalid regexes */ }
         }
       }
       Utils.ensureVersionRangeIsSane(entry);
     });
   },
 
   async _filterItem(entry) {
-    if (!(await BlocklistClients.targetAppFilter(entry, {appID: gAppID, version: gApp.version}))) {
+    if (!(await targetAppFilter(entry, {appID: gAppID, version: gApp.version}))) {
       return null;
     }
     if (!Utils.matchesOSABI(entry)) {
       return null;
     }
     if (!entry.matchFilename && !entry.matchName && !entry.matchDescription) {
       Cu.reportError(new Error("Nothing to filter plugin item " + entry.blockID + " on"));
       return null;
@@ -855,17 +926,17 @@ this.ExtensionBlocklistRS = {
         }
         entry.matches[key] = getCriteria(entry[key]);
       }
       Utils.ensureVersionRangeIsSane(entry);
     });
   },
 
   async _filterItem(entry) {
-    if (!(await BlocklistClients.targetAppFilter(entry, {appID: gAppID, version: gApp.version}))) {
+    if (!(await targetAppFilter(entry, {appID: gAppID, version: gApp.version}))) {
       return null;
     }
     if (!Utils.matchesOSABI(entry)) {
       return null;
     }
     // Need something to filter on - at least a guid or name (either could be a regex):
     if (!entry.guid && !entry.name) {
       Cu.reportError(new Error("Nothing to filter add-on item " + entry.blockID + " on"));