Bug 1557790 - fix initialization of blocklist clients, r=aswan, a=jcristau
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Tue, 11 Jun 2019 18:39:45 +0000
changeset 536928 f8429b9c6790161fa215e5d340ba05eae544c6de
parent 536927 4ff3f4af050df6110825067eef38240126c2274a
child 536929 807e9d8f83dc8b87a5e1c76061f63fac179010d0
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan, jcristau
bugs1557790
milestone68.0
Bug 1557790 - fix initialization of blocklist clients, r=aswan, a=jcristau In order for the remote settings blocklist to sync, we need to ensure that the corresponding remote settings clients are created (see also https://bugzilla.mozilla.org/show_bug.cgi?id=1557790#c2 ). This is necessary because the blocklist clients are not in the `main` bucket. This would otherwise happen as soon as any consumer asked the blocklist for any block data, but that's not going to happen unless the list of add-ons or plugins changes. Even if there are no changes to the local lists of installed things, we do need blocklist updates because otherwise already-installed items would never get blocked even if/when they are added to the blocklist. The client initialization should have no other side effects (in terms of performance/cost) beyond ensuring they get included in things we ask for when the update-timer fires. Differential Revision: https://phabricator.services.mozilla.com/D34550
browser/base/content/test/plugins/head.js
toolkit/mozapps/extensions/Blocklist.jsm
toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_clients.js
toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_targetapp_filter.js
--- a/browser/base/content/test/plugins/head.js
+++ b/browser/base/content/test/plugins/head.js
@@ -267,17 +267,17 @@ let JSONBlocklistWrapper = {
       for (let item of newData) {
         if (!item.id) {
           item.id = uuidGen.generateUUID().number.slice(1, -1);
         }
         if (!item.last_modified) {
           item.last_modified = Date.now();
         }
       }
-      await blocklistObj._ensureInitialized();
+      await blocklistObj.ensureInitialized();
       let collection = await blocklistObj._client.openCollection();
       await collection.clear();
       await collection.loadDump(newData);
       // We manually call _onUpdate... which is evil, but at the moment kinto doesn't have
       // a better abstraction unless you want to mock your own http server to do the update.
       await blocklistObj._onUpdate();
     }
   },
--- a/toolkit/mozapps/extensions/Blocklist.jsm
+++ b/toolkit/mozapps/extensions/Blocklist.jsm
@@ -512,17 +512,17 @@ this.GfxBlocklistRS = {
 this.PluginBlocklistRS = {
   _matchProps: {
     "matchDescription": "description",
     "matchFilename": "filename",
     "matchName": "name",
   },
 
   async _ensureEntries() {
-    await this._ensureInitialized();
+    await this.ensureInitialized();
     if (!this._entries && gBlocklistEnabled) {
       await this._updateEntries();
 
       // Dispatch to mainthread because consumers may try to construct nsIPluginHost
       // again based on this notification, while we were called from nsIPluginHost
       // anyway, leading to re-entrancy.
       Services.tm.dispatchToMainThread(function() {
         Services.obs.notifyObservers(null, "plugin-blocklist-loaded");
@@ -564,17 +564,17 @@ this.PluginBlocklistRS = {
     }
     if (!entry.matchFilename && !entry.matchName && !entry.matchDescription) {
       Cu.reportError(new Error("Nothing to filter plugin item " + entry.blockID + " on"));
       return null;
     }
     return entry;
   },
 
-  async _ensureInitialized() {
+  async ensureInitialized() {
     if (!gBlocklistEnabled || this._initialized) {
       return;
     }
     this._initialized = true;
     this._client = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_COLLECTION), {
       bucketNamePref: PREF_BLOCKLIST_BUCKET,
       lastCheckTimePref: PREF_BLOCKLIST_PLUGINS_CHECKED_SECONDS,
       signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_SIGNER),
@@ -587,17 +587,17 @@ this.PluginBlocklistRS = {
   shutdown() {
     if (this._client) {
       this._client.off("sync", this._onUpdate);
     }
   },
 
   async _onUpdate() {
     let oldEntries = this._entries || [];
-    await this._ensureInitialized();
+    await this.ensureInitialized();
     await this._updateEntries();
     const pluginHost = Cc["@mozilla.org/plugin/host;1"].
                          getService(Ci.nsIPluginHost);
     const plugins = pluginHost.getPluginTags();
 
     let blockedItems = [];
 
     for (let plugin of plugins) {
@@ -883,17 +883,17 @@ this.PluginBlocklistRS = {
  *   "id": "<unique guid>",
  *   "last_modified": 1480349215672,
  * }
  *
  * Note: we assign to the global to allow tests to reach the object directly.
  */
 this.ExtensionBlocklistRS = {
   async _ensureEntries() {
-    await this._ensureInitialized();
+    await this.ensureInitialized();
     if (!this._entries && gBlocklistEnabled) {
       await this._updateEntries();
     }
   },
 
   async _updateEntries() {
     if (!gBlocklistEnabled) {
       this._entries = [];
@@ -940,17 +940,17 @@ this.ExtensionBlocklistRS = {
     // 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"));
       return null;
     }
     return entry;
   },
 
-  async _ensureInitialized() {
+  async ensureInitialized() {
     if (!gBlocklistEnabled || this._initialized) {
       return;
     }
     this._initialized = true;
     this._client = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_COLLECTION), {
       bucketNamePref: PREF_BLOCKLIST_BUCKET,
       lastCheckTimePref: PREF_BLOCKLIST_ADDONS_CHECKED_SECONDS,
       signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_SIGNER),
@@ -963,17 +963,17 @@ this.ExtensionBlocklistRS = {
   shutdown() {
     if (this._client) {
       this._client.off("sync", this._onUpdate);
     }
   },
 
   async _onUpdate() {
     let oldEntries = this._entries || [];
-    await this._ensureInitialized();
+    await this.ensureInitialized();
     await this._updateEntries();
 
     const types = ["extension", "theme", "locale", "dictionary", "service"];
     let addons = await AddonManager.getAddonsByTypes(types);
     for (let addon of addons) {
       let oldState = addon.blocklistState;
       if (addon.updateBlocklistState) {
         await addon.updateBlocklistState(false);
@@ -2531,16 +2531,18 @@ let BlocklistRS = {
   notify() {
     // ignore. We might miss a timer notification once if the XML impl. is disabled
     // when the timer fires and subsequently gets enabled. That seems OK.
   },
 
   loadBlocklistAsync() {
     // Need to ensure we notify gfx of new stuff.
     GfxBlocklistRS.checkForEntries();
+    ExtensionBlocklistRS.ensureInitialized();
+    PluginBlocklistRS.ensureInitialized();
     // Also ensure that if we start the other service after this, we
     // initialize it straight away.
     gLoadingWasTriggered = true;
   },
 
   getPluginBlocklistState(plugin, appVersion, toolkitVersion) {
     return PluginBlocklistRS.getState(plugin, appVersion, toolkitVersion);
   },
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
@@ -765,17 +765,17 @@ var AddonTestUtils = {
       for (let item of newData) {
         if (!item.id) {
           item.id = uuidGen.generateUUID().number.slice(1, -1);
         }
         if (!item.last_modified) {
           item.last_modified = Date.now();
         }
       }
-      await blocklistObj._ensureInitialized();
+      await blocklistObj.ensureInitialized();
       let collection = await blocklistObj._client.openCollection();
       await collection.clear();
       await collection.loadDump(newData);
       // We manually call _onUpdate... which is evil, but at the moment kinto doesn't have
       // a better abstraction unless you want to mock your own http server to do the update.
       await blocklistObj._onUpdate();
     }
   },
--- a/toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_clients.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_clients.js
@@ -30,18 +30,18 @@ function run_test() {
 
   // Unfortunately security settings are coupled with blocklists clients,
   // this will be fixed in Bug 1526018
   // We disable intermediate preloading because it runs when polling ends, and
   // interferes with `clear_state()` from this test suite.
   Services.prefs.setBoolPref("security.remote_settings.intermediates.enabled", false);
 
   // This will initialize the remote settings clients for blocklists.
-  BlocklistGlobal.ExtensionBlocklistRS._ensureInitialized();
-  BlocklistGlobal.PluginBlocklistRS._ensureInitialized();
+  BlocklistGlobal.ExtensionBlocklistRS.ensureInitialized();
+  BlocklistGlobal.PluginBlocklistRS.ensureInitialized();
   BlocklistGlobal.GfxBlocklistRS._ensureInitialized();
 
   gBlocklistClients = [
     {client: BlocklistGlobal.ExtensionBlocklistRS._client, testData: ["i808", "i720", "i539"]},
     {client: BlocklistGlobal.PluginBlocklistRS._client, testData: ["p1044", "p32", "p28"]},
     {client: BlocklistGlobal.GfxBlocklistRS._client, testData: ["g204", "g200", "g36"]},
   ];
   // Disable signature verification in these tests.
--- a/toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_targetapp_filter.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_targetapp_filter.js
@@ -20,17 +20,17 @@ async function createRecords(records) {
   collection.db.saveLastModified(42); // Simulate sync (and prevent load dump).
 }
 
 
 function run_test() {
   AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "58", "");
   // This will initialize the remote settings clients for blocklists,
   // with their specific options etc.
-  BlocklistGlobal.PluginBlocklistRS._ensureInitialized();
+  BlocklistGlobal.PluginBlocklistRS.ensureInitialized();
   // Obtain one of the instantiated client for our tests.
   client = RemoteSettings("plugins", { bucketName: "blocklists" });
 
   run_next_test();
 }
 
 add_task(async function test_returns_all_without_target() {
   await createRecords([{