Bug 1458917 - Register dedicated timer for Remote Settings r=Gijs draft
authorMathieu Leplatre <mathieu@mozilla.com>
Thu, 14 Jun 2018 20:54:19 +0200
changeset 816409 f6932e5c3014ce0bb8e29e08468e4e533130273e
parent 815985 a675c5d7eb76887a3e4b24548d621c9cc05a1545
child 816422 eeb08cd7ce71c24dbe9bdafc07b5d0003715ac5f
push id115835
push usermleplatre@mozilla.com
push dateWed, 11 Jul 2018 07:10:41 +0000
reviewersGijs
bugs1458917
milestone63.0a1
Bug 1458917 - Register dedicated timer for Remote Settings r=Gijs MozReview-Commit-ID: K5Rf1McJUHy
browser/components/nsBrowserGlue.js
browser/installer/package-manifest.in
mobile/android/installer/package-manifest.in
modules/libpref/init/all.js
security/manager/ssl/tests/unit/test_cert_blocklist.js
services/common/blocklist-clients.js
services/common/docs/RemoteSettings.rst
services/settings/RemoteSettingsComponents.js
services/settings/moz.build
services/settings/remote-settings.js
services/settings/servicesSettings.manifest
services/settings/test/unit/test_remote_settings_poll.js
testing/profiles/common/user.js
testing/profiles/reftest/user.js
toolkit/mozapps/extensions/Blocklist.jsm
toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -124,16 +124,17 @@ XPCOMUtils.defineLazyModuleGetters(this,
   PingCentre: "resource:///modules/PingCentre.jsm",
   PlacesBackups: "resource://gre/modules/PlacesBackups.jsm",
   PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
   PluralForm: "resource://gre/modules/PluralForm.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
   ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
   ReaderParent: "resource:///modules/ReaderParent.jsm",
   RemotePrompt: "resource:///modules/RemotePrompt.jsm",
+  RemoteSettings: "resource://services-settings/remote-settings.js",
   SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
   SavantShieldStudy: "resource:///modules/SavantShieldStudy.jsm",
   SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
   ShellService: "resource:///modules/ShellService.jsm",
   TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
   UIState: "resource://services-sync/UIState.jsm",
   UITour: "resource:///modules/UITour.jsm",
@@ -1302,16 +1303,20 @@ BrowserGlue.prototype = {
     Services.tm.idleDispatchToMainThread(() => {
       let obj = {};
       ChromeUtils.import("resource://gre/modules/GMPInstallManager.jsm", obj);
       this._gmpInstallManager = new obj.GMPInstallManager();
       // We don't really care about the results, if someone is interested they
       // can check the log.
       this._gmpInstallManager.simpleCheckAndInstall().catch(() => {});
     });
+
+    Services.tm.idleDispatchToMainThread(() => {
+      RemoteSettings.init();
+    });
   },
 
   _createExtraDefaultProfile() {
     if (!AppConstants.MOZ_DEV_EDITION) {
       return;
     }
     // If Developer Edition is the only installed Firefox version and no other
     // profiles are present, create a second one for use by other versions.
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -293,16 +293,17 @@
 @RESPATH@/components/SyncComponents.manifest
 @RESPATH@/components/Weave.js
 @RESPATH@/components/FxAccountsComponents.manifest
 @RESPATH@/components/FxAccountsPush.js
 @RESPATH@/components/CaptivePortalDetectComponents.manifest
 @RESPATH@/components/captivedetect.js
 @RESPATH@/components/servicesComponents.manifest
 @RESPATH@/components/servicesSettings.manifest
+@RESPATH@/components/RemoteSettingsComponents.js
 @RESPATH@/components/cryptoComponents.manifest
 @RESPATH@/components/TelemetryStartup.js
 @RESPATH@/components/TelemetryStartup.manifest
 @RESPATH@/components/XULStore.js
 @RESPATH@/components/XULStore.manifest
 @RESPATH@/components/recording-cmdline.js
 @RESPATH@/components/recording-cmdline.manifest
 @RESPATH@/components/htmlMenuBuilder.js
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -183,16 +183,17 @@
 @BINPATH@/components/FormHistoryStartup.js
 @BINPATH@/components/nsInputListAutoComplete.js
 @BINPATH@/components/contentAreaDropListener.manifest
 @BINPATH@/components/contentAreaDropListener.js
 @BINPATH@/components/nsINIProcessor.manifest
 @BINPATH@/components/nsINIProcessor.js
 @BINPATH@/components/servicesComponents.manifest
 @BINPATH@/components/servicesSettings.manifest
+@BINPATH@/components/RemoteSettingsComponents.js
 
 #ifndef MOZ_GECKOVIEW_JAR
 @BINPATH@/components/TelemetryStartup.js
 @BINPATH@/components/TelemetryStartup.manifest
 #endif
 
 @BINPATH@/components/XULStore.js
 @BINPATH@/components/XULStore.manifest
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2557,17 +2557,18 @@ pref("security.cert_pinning.enforcement_
 // This is to prevent accidental pinning from MITM devices and is used
 // for tests.
 pref("security.cert_pinning.process_headers_from_non_builtin_roots", false);
 
 // If set to true, allow view-source URIs to be opened from URIs that share
 // their protocol with the inner URI of the view-source URI
 pref("security.view-source.reachable-from-inner-protocol", false);
 
-// Services security settings
+// Remote settings preferences
+pref("services.settings.poll_interval", 86400); // 24H
 pref("services.settings.server", "https://firefox.settings.services.mozilla.com/v1");
 pref("services.settings.changes.path", "/buckets/monitor/collections/changes/records");
 pref("services.settings.default_bucket", "main");
 pref("services.settings.default_signer", "remote-settings.content-signature.mozilla.org");
 
 // Blocklist preferences
 pref("extensions.blocklist.enabled", true);
 // OneCRL freshness checking depends on this value, so if you change it,
@@ -2596,18 +2597,16 @@ pref("services.blocklist.plugins.signer"
 pref("services.blocklist.pinning.enabled", true);
 pref("services.blocklist.pinning.bucket", "pinning");
 pref("services.blocklist.pinning.collection", "pins");
 pref("services.blocklist.pinning.checked", 0);
 pref("services.blocklist.pinning.signer", "pinning-preload.content-signature.mozilla.org");
 pref("services.blocklist.gfx.collection", "gfx");
 pref("services.blocklist.gfx.checked", 0);
 pref("services.blocklist.gfx.signer", "remote-settings.content-signature.mozilla.org");
-// Enable blocklists via the services settings mechanism
-pref("services.blocklist.update_enabled", true);
 
 // Modifier key prefs: default to Windows settings,
 // menu access key = alt, accelerator key = control.
 // Use 17 for Ctrl, 18 for Alt, 224 for Meta, 91 for Win, 0 for none. Mac settings in macprefs.js
 pref("ui.key.accelKey", 17);
 pref("ui.key.menuAccessKey", 18);
 pref("ui.key.generalAccessKey", -1);
 
--- a/security/manager/ssl/tests/unit/test_cert_blocklist.js
+++ b/security/manager/ssl/tests/unit/test_cert_blocklist.js
@@ -8,16 +8,18 @@
 // * it ensures that data loaded from revocations.txt on startup is present
 // * it ensures that data served from OneCRL are persisted correctly
 // * it ensures that items in the CertBlocklist are seen as revoked by the
 //   cert verifier
 // * it does a sanity check to ensure other cert verifier behavior is
 //   unmodified
 
 const { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm", {});
+const { RemoteSettings } = ChromeUtils.import("resource://services-settings/remote-settings.js", {});
+const BlocklistClients = ChromeUtils.import("resource://services-common/blocklist-clients.js", {});
 
 // First, we need to setup appInfo for the blocklist service to work
 var id = "xpcshell@tests.mozilla.org";
 var appName = "XPCShell";
 var version = "1";
 var platformVersion = "1.9.2";
 ChromeUtils.import("resource://testing-common/AppInfo.jsm", this);
 /* global updateAppInfo:false */ // Imported via AppInfo.jsm.
@@ -203,32 +205,20 @@ function test_is_revoked(certList, issue
                                 pubKeyString ? pubKeyString.length : 0);
 }
 
 function fetch_blocklist() {
   Services.prefs.setBoolPref("services.settings.load_dump", false);
   Services.prefs.setBoolPref("services.settings.verify_signature", false);
   Services.prefs.setCharPref("services.settings.server",
                              `http://localhost:${port}/v1`);
-  Services.prefs.setCharPref("extensions.blocklist.url",
-                              `http://localhost:${port}/blocklist.xml`);
-  let blocklist = Cc["@mozilla.org/extensions/blocklist;1"]
-                    .getService(Ci.nsITimerCallback);
 
-  return new Promise((resolve) => {
-    const e = "remote-settings-changes-polled";
-    const changesPolledObserver = {
-      observe(aSubject, aTopic, aData) {
-        Services.obs.removeObserver(this, e);
-        resolve();
-      }
-    };
-    Services.obs.addObserver(changesPolledObserver, e);
-    blocklist.notify(null);
-  });
+  BlocklistClients.initialize();
+
+  return RemoteSettings.pollChanges();
 }
 
 function* generate_revocations_txt_lines() {
   let profile = do_get_profile();
   let revocations = profile.clone();
   revocations.append("revocations.txt");
   ok(revocations.exists(), "the revocations file should exist");
   let inputStream = Cc["@mozilla.org/network/file-input-stream;1"]
--- a/services/common/blocklist-clients.js
+++ b/services/common/blocklist-clients.js
@@ -230,9 +230,17 @@ function initialize() {
   GfxBlocklistClient.on("sync", updateJSONBlocklist.bind(null, GfxBlocklistClient));
 
   PinningBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_COLLECTION), {
     bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_BUCKET),
     lastCheckTimePref: PREF_BLOCKLIST_PINNING_CHECKED_SECONDS,
     signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_SIGNER),
   });
   PinningBlocklistClient.on("sync", updatePinningList);
+
+  return {
+    OneCRLBlocklistClient,
+    AddonBlocklistClient,
+    PluginBlocklistClient,
+    GfxBlocklistClient,
+    PinningBlocklistClient
+  };
 }
--- a/services/common/docs/RemoteSettings.rst
+++ b/services/common/docs/RemoteSettings.rst
@@ -64,17 +64,18 @@ The ``sync`` event allows to be notified
       const { data: { current } } = event;
       for(const entry of current) {
         // Do something with entry...
         // await InternalAPI.reload(entry.id, entry.label, entry.weight);
       }
     });
 
 .. note::
-    Currently, the update of remote settings is triggered by the `nsBlocklistService <https://dxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/nsBlocklistService.js>`_ (~ every 24H).
+
+    Currently, the synchronization of remote settings is triggered by its own timer every 24H (see the preference ``services.settings.poll_interval`` ).
 
 File attachments
 ----------------
 
 When an entry has a file attached to it, it has an ``attachment`` attribute, which contains the file related information (url, hash, size, mimetype, etc.). Remote files are not downloaded automatically.
 
 .. code-block:: js
 
new file mode 100644
--- /dev/null
+++ b/services/settings/RemoteSettingsComponents.js
@@ -0,0 +1,29 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ "use strict";
+
+var EXPORTED_SYMBOLS = [
+  "RemoteSettingsTimer",
+];
+
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "RemoteSettings",
+  "resource://services-settings/remote-settings.js");
+
+
+var RemoteSettingsTimer = function() {};
+RemoteSettingsTimer.prototype = {
+  QueryInterface: ChromeUtils.generateQI([Ci.nsITimerCallback]),
+  classID: Components.ID("{5e756573-234a-49ea-bbe4-59ec7a70657d}"),
+  contractID: "@mozilla.org/services/settings;1",
+
+  // By default, this timer fires once every 24 hours. See the "services.settings.poll_interval" pref.
+  notify(timer) {
+    RemoteSettings.pollChanges()
+      .catch(e => Cu.reportError(e));
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RemoteSettingsTimer]);
--- a/services/settings/moz.build
+++ b/services/settings/moz.build
@@ -5,16 +5,17 @@
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'Remote Settings Client')
 
 DIRS += [
     'dumps',
 ]
 
 EXTRA_COMPONENTS += [
+    'RemoteSettingsComponents.js',
     'servicesSettings.manifest',
 ]
 
 EXTRA_JS_MODULES['services-settings'] += [
     'remote-settings.js',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
--- a/services/settings/remote-settings.js
+++ b/services/settings/remote-settings.js
@@ -155,21 +155,23 @@ async function fetchLatestChanges(url, l
   const response = await fetch(url, {headers});
 
   let changes = [];
   // If no changes since last time, go on with empty list of changes.
   if (response.status != 304) {
     let payload;
     try {
       payload = await response.json();
-    } catch (e) {}
+    } catch (e) {
+      payload = e.message;
+    }
     if (!payload.hasOwnProperty("data")) {
       // If the server is failing, the JSON response might not contain the
       // expected data (e.g. error response - Bug 1259145)
-      throw new Error(`Server error response ${JSON.stringify(payload)}`);
+      throw new Error(`Server error ${response.status} ${response.statusText}: ${JSON.stringify(payload)}`);
     }
     changes = payload.data;
   }
   // The server should always return ETag. But we've had situations where the CDN
   // was interfering.
   const currentEtag = response.headers.has("ETag") ? response.headers.get("ETag") : undefined;
   let serverTimeMillis = Date.parse(response.headers.get("Date"));
   // Since the response is served via a CDN, the Date header value could have been cached.
@@ -799,29 +801,34 @@ function remoteSettingsFunction() {
       localTimestamp: Services.prefs.getCharPref(PREF_SETTINGS_LAST_ETAG, null),
       lastCheck: Services.prefs.getIntPref(PREF_SETTINGS_LAST_UPDATE, 0),
       mainBucket,
       defaultSigner,
       collections: collections.filter(c => !!c)
     };
   };
 
-
-  const broadcastID = "remote-settings/monitor_changes";
-  // When we start on a new profile there will be no ETag stored.
-  // Use an arbitrary ETag that is guaranteed not to occur.
-  // This will trigger a broadcast message but that's fine because we
-  // will check the changes on each collection and retrieve only the
-  // changes (e.g. nothing if we have a dump with the same data).
-  const currentVersion = Services.prefs.getStringPref(PREF_SETTINGS_LAST_ETAG, "\"0\"");
-  const moduleInfo = {
-    moduleURI: __URI__,
-    symbolName: "remoteSettingsBroadcastHandler",
+  /**
+   * Startup function called from nsBrowserGlue.
+   */
+  remoteSettings.init = () => {
+    // Hook the Push broadcast and RemoteSettings polling.
+    const broadcastID = "remote-settings/monitor_changes";
+    // When we start on a new profile there will be no ETag stored.
+    // Use an arbitrary ETag that is guaranteed not to occur.
+    // This will trigger a broadcast message but that's fine because we
+    // will check the changes on each collection and retrieve only the
+    // changes (e.g. nothing if we have a dump with the same data).
+    const currentVersion = Services.prefs.getStringPref(PREF_SETTINGS_LAST_ETAG, "\"0\"");
+    const moduleInfo = {
+      moduleURI: __URI__,
+      symbolName: "remoteSettingsBroadcastHandler",
+    };
+    pushBroadcastService.addListener(broadcastID, currentVersion, moduleInfo);
   };
-  pushBroadcastService.addListener(broadcastID, currentVersion, moduleInfo);
 
   return remoteSettings;
 }
 
 var RemoteSettings = remoteSettingsFunction();
 
 var remoteSettingsBroadcastHandler = {
   async receivedBroadcastMessage(data, broadcastID) {
--- a/services/settings/servicesSettings.manifest
+++ b/services/settings/servicesSettings.manifest
@@ -1,2 +1,7 @@
 # Register resource aliases
 resource services-settings resource://gre/modules/services-settings/
+
+# Schedule polling of remote settings changes
+component {5e756573-234a-49ea-bbe4-59ec7a70657d} RemoteSettingsComponents.js
+contract @mozilla.org/services/settings;1 {5e756573-234a-49ea-bbe4-59ec7a70657d}
+category update-timer RemoteSettingsComponents @mozilla.org/services/settings;1,getService,services-settings-poll-changes,services.settings.poll_interval,86400
--- a/services/settings/test/unit/test_remote_settings_poll.js
+++ b/services/settings/test/unit/test_remote_settings_poll.js
@@ -111,16 +111,48 @@ add_task(async function test_check_succe
   const expectedIncrements = {
     [UptakeTelemetry.STATUS.SUCCESS]: 1,
   };
   checkUptakeTelemetry(startHistogram, endHistogram, expectedIncrements);
 });
 add_task(clear_state);
 
 
+add_task(async function test_update_timer_interface() {
+  const remoteSettings = Cc["@mozilla.org/services/settings;1"]
+    .getService(Ci.nsITimerCallback);
+
+  const serverTime = 8000;
+  server.registerPathHandler(CHANGES_PATH, serveChangesEntries(serverTime, [{
+    id: "028261ad-16d4-40c2-a96a-66f72914d125",
+    last_modified: 42,
+    host: "localhost",
+    bucket: "main",
+    collection: "whatever-collection"
+  }]));
+
+  await new Promise((resolve) => {
+    const e = "remote-settings-changes-polled";
+    const changesPolledObserver = {
+      observe(aSubject, aTopic, aData) {
+        Services.obs.removeObserver(this, e);
+        resolve();
+      }
+    };
+    Services.obs.addObserver(changesPolledObserver, e);
+    remoteSettings.notify(null);
+  });
+
+  // Everything went fine.
+  Assert.equal(Services.prefs.getCharPref(PREF_LAST_ETAG), "\"42\"");
+  Assert.equal(Services.prefs.getIntPref(PREF_LAST_UPDATE), serverTime / 1000);
+});
+add_task(clear_state);
+
+
 add_task(async function test_check_up_to_date() {
   // Simulate a poll with up-to-date collection.
   const startHistogram = getUptakeTelemetrySnapshot(TELEMETRY_HISTOGRAM_KEY);
 
   const serverTime = 4000;
   function server304(request, response) {
     if (request.hasHeader("if-none-match") && request.getHeader("if-none-match") == "\"1100\"") {
       response.setHeader("Date", (new Date(serverTime)).toUTCString());
@@ -204,16 +236,36 @@ add_task(async function test_success_wit
   await RemoteSettings.pollChanges();
 
   // On the second call, the server does not mention the test-collection
   // and maybeSync() is not called.
   Assert.equal(maybeSyncCount, 1, "maybeSync should not be called twice");
 });
 add_task(clear_state);
 
+
+add_task(async function test_server_bad_json() {
+  function simulateBadJSON(request, response) {
+    response.setHeader("Content-Type", "application/json; charset=UTF-8");
+    response.write("<html></html>");
+    response.setStatusLine(null, 200, "OK");
+  }
+  server.registerPathHandler(CHANGES_PATH, simulateBadJSON);
+
+  let error;
+  try {
+    await RemoteSettings.pollChanges();
+  } catch (e) {
+    error = e;
+  }
+  Assert.ok(/JSON.parse: unexpected character/.test(error.message));
+});
+add_task(clear_state);
+
+
 add_task(async function test_server_error() {
   const startHistogram = getUptakeTelemetrySnapshot(TELEMETRY_HISTOGRAM_KEY);
 
   // Simulate a server error.
   function simulateErrorResponse(request, response) {
     response.setHeader("Date", (new Date(3000)).toUTCString());
     response.setHeader("Content-Type", "application/json; charset=UTF-8");
     response.write(JSON.stringify({
--- a/testing/profiles/common/user.js
+++ b/testing/profiles/common/user.js
@@ -33,8 +33,10 @@ user_pref("extensions.legacy.enabled", t
 user_pref("extensions.update.enabled", false);
 // Disable useragent updates.
 user_pref("general.useragent.updates.enabled", false);
 user_pref("hangmonitor.timeout", 0); // no hang monitor
 user_pref("media.gmp-manager.updateEnabled", false);
 // Make enablePrivilege continue to work for test code. :-(
 user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_computer", true);
 user_pref("xpinstall.signatures.required", false);
+// Prevent Remote Settings to issue non local connections.
+user_pref("services.settings.server", "http://localhost/remote-settings-dummy/v1");
--- a/testing/profiles/reftest/user.js
+++ b/testing/profiles/reftest/user.js
@@ -97,8 +97,10 @@ user_pref("startup.homepage_welcome_url.
 // A fake bool pref for "@supports -moz-bool-pref" sanify test.
 user_pref("testing.supports.moz-bool-pref", false);
 // Ensure that telemetry is disabled, so we don't connect to the telemetry
 // server in the middle of the tests.
 user_pref("toolkit.telemetry.enabled", false);
 user_pref("toolkit.telemetry.server", "https://%(server)s/telemetry-dummy/");
 user_pref("ui.caretBlinkTime", -1);
 user_pref("ui.caretWidth", 1);
+// Turn off the Push service.
+user_pref("dom.push.serverURL", "");
--- a/toolkit/mozapps/extensions/Blocklist.jsm
+++ b/toolkit/mozapps/extensions/Blocklist.jsm
@@ -90,38 +90,30 @@ ChromeUtils.defineModuleGetter(this, "Se
    */
 
 // The remote settings updater is the new system in charge of fetching remote data
 // securely and efficiently. It will replace the current XML-based system.
 // See Bug 1257565 and Bug 1252456.
 const BlocklistClients = {};
 ChromeUtils.defineModuleGetter(BlocklistClients, "initialize",
                                "resource://services-common/blocklist-clients.js");
-XPCOMUtils.defineLazyGetter(this, "RemoteSettings", function() {
-  // Instantiate blocklist clients.
-  BlocklistClients.initialize();
-  // Import RemoteSettings for ``pollChanges()``
-  const { RemoteSettings } = ChromeUtils.import("resource://services-settings/remote-settings.js", {});
-  return RemoteSettings;
-});
 
 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";
 const PREF_BLOCKLIST_ENABLED          = "extensions.blocklist.enabled";
 const PREF_BLOCKLIST_LAST_MODIFIED    = "extensions.blocklist.lastModified";
 const PREF_BLOCKLIST_LEVEL            = "extensions.blocklist.level";
 const PREF_BLOCKLIST_PINGCOUNTTOTAL   = "extensions.blocklist.pingCountTotal";
 const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion";
 const PREF_BLOCKLIST_SUPPRESSUI       = "extensions.blocklist.suppressUI";
-const PREF_BLOCKLIST_UPDATE_ENABLED   = "services.blocklist.update_enabled";
 const PREF_APP_DISTRIBUTION           = "distribution.id";
 const PREF_APP_DISTRIBUTION_VERSION   = "distribution.version";
 const PREF_EM_LOGGING_ENABLED         = "extensions.logging.enabled";
 const XMLURI_BLOCKLIST                = "http://www.mozilla.org/2006/addons-blocklist";
 const XMLURI_PARSE_ERROR              = "http://www.mozilla.org/newlayout/xml/parsererror.xml";
 const URI_BLOCKLIST_DIALOG            = "chrome://mozapps/content/extensions/blocklist.xul";
 const DEFAULT_SEVERITY                = 3;
 const DEFAULT_LEVEL                   = 2;
@@ -301,16 +293,23 @@ var Blocklist = {
 
     gLoggingEnabled = Services.prefs.getBoolPref(PREF_EM_LOGGING_ENABLED, false);
     gBlocklistEnabled = Services.prefs.getBoolPref(PREF_BLOCKLIST_ENABLED, true);
     gBlocklistLevel = Math.min(Services.prefs.getIntPref(PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL),
                                MAX_BLOCK_LEVEL);
     Services.prefs.addObserver("extensions.blocklist.", this);
     Services.prefs.addObserver(PREF_EM_LOGGING_ENABLED, this);
 
+    // Instantiate Remote Settings clients for blocklists.
+    // Their initialization right here serves two purposes:
+    // - Make sure they are instantiated (it's cheap) in order to be included in the synchronization process;
+    // - Pave the way for Bug 1257565 which will leverage remote settings instead of the XML file
+    //   to manage the blocklists state.
+    BlocklistClients.initialize();
+
     // If the stub blocklist service deferred any queries because we
     // weren't loaded yet, execute them now.
     for (let entry of Services.blocklist.pluginQueries.splice(0)) {
       entry.resolve(this.getPluginBlocklistState(entry.plugin,
                                                  entry.appVersion,
                                                  entry.toolkitVersion));
     }
   },
@@ -680,24 +679,16 @@ var Blocklist = {
       request.setRequestHeader("If-Modified-Since", lastModified);
     } else {
       request.setRequestHeader("Cache-Control", "no-cache");
     }
 
     request.addEventListener("error", event => this.onXMLError(event));
     request.addEventListener("load", event => this.onXMLLoad(event));
     request.send(null);
-
-    // If blocklist update via Kinto is enabled, poll for changes and sync.
-    // Currently certificates blocklist relies on it by default.
-    if (Services.prefs.getBoolPref(PREF_BLOCKLIST_UPDATE_ENABLED)) {
-      RemoteSettings.pollChanges().catch(() => {
-        // Bug 1254099 - Telemetry (success or errors) will be collected during this process.
-      });
-    }
   },
 
   async onXMLLoad(aEvent) {
     let request = aEvent.target;
     try {
       CertUtils.checkCert(request.channel);
     } catch (e) {
       LOG("Blocklist::onXMLLoad: " + e);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js
@@ -48,18 +48,16 @@ function load_blocklist(aFile, aCallback
 
     executeSoon(aCallback);
   }, "blocklist-updated");
 
   Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" +
                              gPort + "/data/" + aFile);
   var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
                   getService(Ci.nsITimerCallback);
-  ok(Services.prefs.getBoolPref("services.blocklist.update_enabled"),
-                                "Kinto update should be enabled");
   blocklist.notify(null);
 }
 
 
 function end_test() {
   do_test_finished();
 }