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
--- 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) {