Bug 1336208 - Part 3: Adding a new BlocklistClient for font fingerprinting. r?leplatrem,arthuredelstein draft
authorTim Huang <tihuang@mozilla.com>
Thu, 17 Aug 2017 11:58:29 +0800
changeset 707551 09b887290a860055e22c9cfd31f0f9dbca2057d2
parent 707550 08f68cd96832095042ee4b12b3f5e8579e2fb619
child 707552 9dd463e88bc34a71bff0a2d931e4b60e41b42070
push id92156
push userbmo:tihuang@mozilla.com
push dateTue, 05 Dec 2017 14:33:57 +0000
reviewersleplatrem, arthuredelstein
bugs1336208
milestone59.0a1
Bug 1336208 - Part 3: Adding a new BlocklistClient for font fingerprinting. r?leplatrem,arthuredelstein This patch adds a new BlocklistClient 'FontsRFPClient' for synchronizing fonts list with Kinto server. After it syncs up with Kinto, it will write the fonts list into the profile folder and notify an observer 'resist-fingerprinting:download-fonts' to issue that fonts list is ready and kick off the downloading process if fingerprinting resistance is enabled. MozReview-Commit-ID: 2laVDd4uhjQ
modules/libpref/init/all.js
services/common/blocklist-clients.js
services/common/blocklist-updater.js
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2616,16 +2616,21 @@ pref("services.blocklist.plugins.collect
 pref("services.blocklist.plugins.checked", 0);
 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.gfx.collection", "gfx");
 pref("services.blocklist.gfx.checked", 0);
 
+// Fonts downloading for fingerprinting resistance via settings server (Kinto)
+pref("privacy.resistFingerprinting.fonts.bucket", "fingerprinting-defenses");
+pref("privacy.resistFingerprinting.fonts.collection", "fonts");
+pref("privacy.resistFingerprinting.fonts.checked", 0);
+
 // Controls whether signing should be enforced on signature-capable blocklist
 // collections.
 pref("services.blocklist.signing.enforced", true);
 
 // Enable blocklists via the services settings mechanism
 pref("services.blocklist.update_enabled", true);
 
 
--- a/services/common/blocklist-clients.js
+++ b/services/common/blocklist-clients.js
@@ -3,17 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["AddonBlocklistClient",
                          "GfxBlocklistClient",
                          "OneCRLBlocklistClient",
                          "PinningBlocklistClient",
-                         "PluginBlocklistClient"];
+                         "PluginBlocklistClient",
+                         "FontsRFPClient"];
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
 Cu.importGlobalProperties(["fetch"]);
 
@@ -42,16 +43,21 @@ const PREF_BLOCKLIST_PLUGINS_CHECKED_SEC
 const PREF_BLOCKLIST_PINNING_ENABLED         = "services.blocklist.pinning.enabled";
 const PREF_BLOCKLIST_PINNING_BUCKET          = "services.blocklist.pinning.bucket";
 const PREF_BLOCKLIST_PINNING_COLLECTION      = "services.blocklist.pinning.collection";
 const PREF_BLOCKLIST_PINNING_CHECKED_SECONDS = "services.blocklist.pinning.checked";
 const PREF_BLOCKLIST_GFX_COLLECTION          = "services.blocklist.gfx.collection";
 const PREF_BLOCKLIST_GFX_CHECKED_SECONDS     = "services.blocklist.gfx.checked";
 const PREF_BLOCKLIST_ENFORCE_SIGNING         = "services.blocklist.signing.enforced";
 
+// Prefs for font fingerprinting resistance.
+const PREF_RFP_FONTS_BUCKET          = "privacy.resistFingerprinting.fonts.bucket";
+const PREF_RFP_FONTS_CHECKED_SECONDS = "privacy.resistFingerprinting.fonts.checked";
+const PREF_RFP_FONTS_COLLECTION      = "privacy.resistFingerprinting.fonts.collection";
+
 const INVALID_SIGNATURE = "Invalid content/signature";
 
 // This was the default path in earlier versions of
 // FirefoxAdapter, so for backwards compatibility we maintain this
 // filename, even though it isn't descriptive of who is using it.
 const KINTO_STORAGE_PATH = "kinto.sqlite";
 
 
@@ -433,16 +439,39 @@ async function updateJSONBlocklist(filen
     // Notify change to `nsBlocklistService`
     const eventData = {filename};
     Services.cpmm.sendAsyncMessage("Blocklist:reload-from-disk", eventData);
   } catch (e) {
     Cu.reportError(e);
   }
 }
 
+/**
+ * Write the list of fonts for fingerprinting resistance into a JSON file and
+ * notify nsRFPService to download fonts if necessary.
+ *
+ * @param {String} filename  path relative to profile dir.
+ * @param {Object} records   current records in the local db.
+ */
+async function updateFontList(filename, records) {
+  const path = OS.Path.join(OS.Constants.Path.profileDir, filename);
+  const blocklistFolder = OS.Path.dirname(path);
+
+  await OS.File.makeDir(blocklistFolder, {from: OS.Constants.Path.profileDir});
+
+  const serialized = JSON.stringify({data: records}, null, 2);
+
+  try {
+    await OS.File.writeAtomic(path, serialized, {tmpPath: path + ".tmp"});
+    Services.obs.notifyObservers(null, "resist-fingerprinting:download-fonts");
+  } catch (e) {
+    Cu.reportError(e);
+  }
+}
+
 this.OneCRLBlocklistClient = new BlocklistClient(
   Services.prefs.getCharPref(PREF_BLOCKLIST_ONECRL_COLLECTION),
   PREF_BLOCKLIST_ONECRL_CHECKED_SECONDS,
   updateCertBlocklist,
   Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
   "onecrl.content-signature.mozilla.org"
 );
 
@@ -469,8 +498,16 @@ this.PluginBlocklistClient = new Blockli
 
 this.PinningPreloadClient = new BlocklistClient(
   Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_COLLECTION),
   PREF_BLOCKLIST_PINNING_CHECKED_SECONDS,
   updatePinningList,
   Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_BUCKET),
   "pinning-preload.content-signature.mozilla.org"
 );
+
+this.FontsRFPClient = new BlocklistClient(
+  Services.prefs.getCharPref(PREF_RFP_FONTS_COLLECTION),
+  PREF_RFP_FONTS_CHECKED_SECONDS,
+  (records) => updateFontList(this.FontsRFPClient.filename, records),
+  Services.prefs.getCharPref(PREF_RFP_FONTS_BUCKET),
+  "fingerprinting-defenses.content-signature.mozilla.org"
+);
--- a/services/common/blocklist-updater.js
+++ b/services/common/blocklist-updater.js
@@ -27,16 +27,17 @@ const TELEMETRY_HISTOGRAM_KEY = "setting
 XPCOMUtils.defineLazyGetter(this, "gBlocklistClients", function() {
   const BlocklistClients = Cu.import("resource://services-common/blocklist-clients.js", {});
   return {
     [BlocklistClients.OneCRLBlocklistClient.collectionName]: BlocklistClients.OneCRLBlocklistClient,
     [BlocklistClients.AddonBlocklistClient.collectionName]: BlocklistClients.AddonBlocklistClient,
     [BlocklistClients.GfxBlocklistClient.collectionName]: BlocklistClients.GfxBlocklistClient,
     [BlocklistClients.PluginBlocklistClient.collectionName]: BlocklistClients.PluginBlocklistClient,
     [BlocklistClients.PinningPreloadClient.collectionName]: BlocklistClients.PinningPreloadClient,
+    [BlocklistClients.FontsRFPClient.collectionName]: BlocklistClients.FontsRFPClient,
   };
 });
 
 // Add a blocklist client for testing purposes. Do not use for any other purpose
 this.addTestBlocklistClient = (name, client) => { gBlocklistClients[name] = client; };
 
 
 async function pollChanges(url, lastEtag) {