summaryrefslogtreecommitdiffstats
path: root/toolkit/components/resistfingerprinting
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/resistfingerprinting')
-rw-r--r--toolkit/components/resistfingerprinting/FingerprintingWebCompatService.sys.mjs2
-rw-r--r--toolkit/components/resistfingerprinting/KeyCodeConsensus_En_US.h2
-rw-r--r--toolkit/components/resistfingerprinting/RFPHelper.sys.mjs42
-rw-r--r--toolkit/components/resistfingerprinting/RFPTargetIPCUtils.h2
-rw-r--r--toolkit/components/resistfingerprinting/RFPTargets.inc2
-rw-r--r--toolkit/components/resistfingerprinting/RelativeTimeline.cpp2
-rw-r--r--toolkit/components/resistfingerprinting/RelativeTimeline.h2
-rw-r--r--toolkit/components/resistfingerprinting/UserCharacteristicsPageService.sys.mjs209
-rw-r--r--toolkit/components/resistfingerprinting/components.conf9
-rw-r--r--toolkit/components/resistfingerprinting/content/usercharacteristics.html18
-rw-r--r--toolkit/components/resistfingerprinting/content/usercharacteristics.js41
-rw-r--r--toolkit/components/resistfingerprinting/jar.mn7
-rw-r--r--toolkit/components/resistfingerprinting/metrics.yaml121
-rw-r--r--toolkit/components/resistfingerprinting/moz.build6
-rw-r--r--toolkit/components/resistfingerprinting/nsIFingerprintingWebCompatService.idl2
-rw-r--r--toolkit/components/resistfingerprinting/nsIRFPService.idl2
-rw-r--r--toolkit/components/resistfingerprinting/nsIUserCharacteristicsPageService.idl23
-rw-r--r--toolkit/components/resistfingerprinting/nsRFPService.cpp126
-rw-r--r--toolkit/components/resistfingerprinting/nsRFPService.h2
-rw-r--r--toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp319
-rw-r--r--toolkit/components/resistfingerprinting/nsUserCharacteristics.h14
-rw-r--r--toolkit/components/resistfingerprinting/pings.yaml2
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser.toml2
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_canvas_fingerprinter_telemetry.js2
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization.js2
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization_worker.js2
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingRemoteOverrides.js60
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js2
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_font_fingerprinter_telemetry.js2
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_fpiServiceWorkers_fingerprinting.js2
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_serviceWorker_fingerprinting_webcompat.js4
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics.js51
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/head.js2
-rw-r--r--toolkit/components/resistfingerprinting/tests/gtest/test_reduceprecision.cpp2
-rw-r--r--toolkit/components/resistfingerprinting/tests/gtest/test_usercharping.cpp11
35 files changed, 930 insertions, 169 deletions
diff --git a/toolkit/components/resistfingerprinting/FingerprintingWebCompatService.sys.mjs b/toolkit/components/resistfingerprinting/FingerprintingWebCompatService.sys.mjs
index b6d5bed59c..56f6435e47 100644
--- a/toolkit/components/resistfingerprinting/FingerprintingWebCompatService.sys.mjs
+++ b/toolkit/components/resistfingerprinting/FingerprintingWebCompatService.sys.mjs
@@ -1,7 +1,7 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* 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/. */
+ * You can obtain one at https://mozilla.org/MPL/2.0/. */
const lazy = {};
diff --git a/toolkit/components/resistfingerprinting/KeyCodeConsensus_En_US.h b/toolkit/components/resistfingerprinting/KeyCodeConsensus_En_US.h
index c8fafcf22e..6558bcdc29 100644
--- a/toolkit/components/resistfingerprinting/KeyCodeConsensus_En_US.h
+++ b/toolkit/components/resistfingerprinting/KeyCodeConsensus_En_US.h
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/**
* This file contains the spoofed keycodes of en-US for fingerprinting
diff --git a/toolkit/components/resistfingerprinting/RFPHelper.sys.mjs b/toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
index 223c0259b7..c586873a74 100644
--- a/toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
+++ b/toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
@@ -1,7 +1,7 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* 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/. */
+ * You can obtain one at https://mozilla.org/MPL/2.0/. */
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
@@ -43,6 +43,8 @@ class _RFPHelper {
this._initialized = true;
// Add unconditional observers
+ Services.obs.addObserver(this, "user-characteristics-populating-data");
+ Services.obs.addObserver(this, "user-characteristics-populating-data-done");
Services.prefs.addObserver(kPrefResistFingerprinting, this);
Services.prefs.addObserver(kPrefLetterboxing, this);
XPCOMUtils.defineLazyPreferenceGetter(
@@ -80,6 +82,12 @@ class _RFPHelper {
observe(subject, topic, data) {
switch (topic) {
+ case "user-characteristics-populating-data":
+ this._registerUserCharacteristicsActor();
+ break;
+ case "user-characteristics-populating-data-done":
+ this._unregisterUserCharacteristicsActor();
+ break;
case "nsPref:changed":
this._handlePrefChanged(data);
break;
@@ -97,6 +105,28 @@ class _RFPHelper {
}
}
+ _registerUserCharacteristicsActor() {
+ log("_registerUserCharacteristicsActor()");
+ ChromeUtils.registerWindowActor("UserCharacteristics", {
+ parent: {
+ esModuleURI: "resource://gre/actors/UserCharacteristicsParent.sys.mjs",
+ },
+ child: {
+ esModuleURI: "resource://gre/actors/UserCharacteristicsChild.sys.mjs",
+ events: {
+ UserCharacteristicsDataDone: { wantUntrusted: true },
+ },
+ },
+ matches: ["about:fingerprinting"],
+ remoteTypes: ["privilegedabout"],
+ });
+ }
+
+ _unregisterUserCharacteristicsActor() {
+ log("_unregisterUserCharacteristicsActor()");
+ ChromeUtils.unregisterWindowActor("UserCharacteristics");
+ }
+
handleEvent(aMessage) {
switch (aMessage.type) {
case "TabOpen": {
@@ -186,7 +216,7 @@ class _RFPHelper {
);
}
- _handleHttpOnModifyRequest(subject, data) {
+ _handleHttpOnModifyRequest(subject) {
// If we are loading an HTTP page from content, show the
// "request English language web pages?" prompt.
let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
@@ -283,16 +313,16 @@ class _RFPHelper {
_handleLetterboxingPrefChanged() {
if (Services.prefs.getBoolPref(kPrefLetterboxing, false)) {
Services.ww.registerNotification(this);
- this._registerActor();
+ this._registerLetterboxingActor();
this._attachAllWindows();
} else {
- this._unregisterActor();
+ this._unregisterLetterboxingActor();
this._detachAllWindows();
Services.ww.unregisterNotification(this);
}
}
- _registerActor() {
+ _registerLetterboxingActor() {
ChromeUtils.registerWindowActor("RFPHelper", {
parent: {
esModuleURI: "resource:///actors/RFPHelperParent.sys.mjs",
@@ -307,7 +337,7 @@ class _RFPHelper {
});
}
- _unregisterActor() {
+ _unregisterLetterboxingActor() {
ChromeUtils.unregisterWindowActor("RFPHelper");
}
diff --git a/toolkit/components/resistfingerprinting/RFPTargetIPCUtils.h b/toolkit/components/resistfingerprinting/RFPTargetIPCUtils.h
index 198332e3f6..414aa94905 100644
--- a/toolkit/components/resistfingerprinting/RFPTargetIPCUtils.h
+++ b/toolkit/components/resistfingerprinting/RFPTargetIPCUtils.h
@@ -2,7 +2,7 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
+ * You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef __RFPTargetIPCUtils_h__
#define __RFPTargetIPCUtils_h__
diff --git a/toolkit/components/resistfingerprinting/RFPTargets.inc b/toolkit/components/resistfingerprinting/RFPTargets.inc
index d2327ffbfe..9bc9dcbb8e 100644
--- a/toolkit/components/resistfingerprinting/RFPTargets.inc
+++ b/toolkit/components/resistfingerprinting/RFPTargets.inc
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
// Names should not be re-used.
diff --git a/toolkit/components/resistfingerprinting/RelativeTimeline.cpp b/toolkit/components/resistfingerprinting/RelativeTimeline.cpp
index dd2d304adb..84fdeb93f8 100644
--- a/toolkit/components/resistfingerprinting/RelativeTimeline.cpp
+++ b/toolkit/components/resistfingerprinting/RelativeTimeline.cpp
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "nsCOMPtr.h"
#include "nsIRandomGenerator.h"
diff --git a/toolkit/components/resistfingerprinting/RelativeTimeline.h b/toolkit/components/resistfingerprinting/RelativeTimeline.h
index bf23de904d..c8ad1c7aad 100644
--- a/toolkit/components/resistfingerprinting/RelativeTimeline.h
+++ b/toolkit/components/resistfingerprinting/RelativeTimeline.h
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef __RelativeTimeline_h__
#define __RelativeTimeline_h__
diff --git a/toolkit/components/resistfingerprinting/UserCharacteristicsPageService.sys.mjs b/toolkit/components/resistfingerprinting/UserCharacteristicsPageService.sys.mjs
new file mode 100644
index 0000000000..d24a2eae33
--- /dev/null
+++ b/toolkit/components/resistfingerprinting/UserCharacteristicsPageService.sys.mjs
@@ -0,0 +1,209 @@
+// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ HiddenFrame: "resource://gre/modules/HiddenFrame.sys.mjs",
+});
+
+ChromeUtils.defineLazyGetter(lazy, "console", () => {
+ return console.createInstance({
+ prefix: "UserCharacteristicsPage",
+ maxLogLevelPref: "toolkit.telemetry.user_characteristics_ping.logLevel",
+ });
+});
+
+const BACKGROUND_WIDTH = 1024;
+const BACKGROUND_HEIGHT = 768;
+
+/**
+ * A manager for hidden browsers. Responsible for creating and destroying a
+ * hidden frame to hold them.
+ * All of this is copied from PageDataService.sys.mjs
+ */
+class HiddenBrowserManager {
+ /**
+ * The hidden frame if one has been created.
+ *
+ * @type {HiddenFrame | null}
+ */
+ #frame = null;
+ /**
+ * The number of hidden browser elements currently in use.
+ *
+ * @type {number}
+ */
+ #browsers = 0;
+
+ /**
+ * Creates and returns a new hidden browser.
+ *
+ * @returns {Browser}
+ */
+ async #acquireBrowser() {
+ this.#browsers++;
+ if (!this.#frame) {
+ this.#frame = new lazy.HiddenFrame();
+ }
+
+ let frame = await this.#frame.get();
+ let doc = frame.document;
+ let browser = doc.createXULElement("browser");
+ browser.setAttribute("remote", "true");
+ browser.setAttribute("type", "content");
+ browser.setAttribute(
+ "style",
+ `
+ width: ${BACKGROUND_WIDTH}px;
+ min-width: ${BACKGROUND_WIDTH}px;
+ height: ${BACKGROUND_HEIGHT}px;
+ min-height: ${BACKGROUND_HEIGHT}px;
+ `
+ );
+ browser.setAttribute("maychangeremoteness", "true");
+ doc.documentElement.appendChild(browser);
+
+ return browser;
+ }
+
+ /**
+ * Releases the given hidden browser.
+ *
+ * @param {Browser} browser
+ * The hidden browser element.
+ */
+ #releaseBrowser(browser) {
+ browser.remove();
+
+ this.#browsers--;
+ if (this.#browsers == 0) {
+ this.#frame.destroy();
+ this.#frame = null;
+ }
+ }
+
+ /**
+ * Calls a callback function with a new hidden browser.
+ * This function will return whatever the callback function returns.
+ *
+ * @param {Callback} callback
+ * The callback function will be called with the browser element and may
+ * be asynchronous.
+ * @returns {T}
+ */
+ async withHiddenBrowser(callback) {
+ let browser = await this.#acquireBrowser();
+ try {
+ return await callback(browser);
+ } finally {
+ this.#releaseBrowser(browser);
+ }
+ }
+}
+
+export class UserCharacteristicsPageService {
+ classId = Components.ID("{ce3e9659-e311-49fb-b18b-7f27c6659b23}");
+ QueryInterface = ChromeUtils.generateQI([
+ "nsIUserCharacteristicsPageService",
+ ]);
+
+ _initialized = false;
+ _isParentProcess = false;
+
+ /**
+ * A manager for hidden browsers.
+ *
+ * @type {HiddenBrowserManager}
+ */
+ _browserManager = new HiddenBrowserManager();
+
+ /**
+ * A map of hidden browsers to a resolve function that should be passed the
+ * actor that was created for the browser.
+ *
+ * @type {WeakMap<Browser, function(PageDataParent): void>}
+ */
+ _backgroundBrowsers = new WeakMap();
+
+ constructor() {
+ lazy.console.debug("Init");
+
+ if (
+ Services.appinfo.processType !== Services.appinfo.PROCESS_TYPE_DEFAULT
+ ) {
+ throw new Error(
+ "Shouldn't init UserCharacteristicsPage in content processes."
+ );
+ }
+
+ // Return if we have initiated.
+ if (this._initialized) {
+ lazy.console.warn("preventing re-initilization...");
+ return;
+ }
+ this._initialized = true;
+ }
+
+ shutdown() {}
+
+ createContentPage() {
+ lazy.console.debug("called createContentPage");
+ return this._browserManager.withHiddenBrowser(async browser => {
+ lazy.console.debug(`In withHiddenBrowser`);
+ try {
+ let { promise, resolve } = Promise.withResolvers();
+ this._backgroundBrowsers.set(browser, resolve);
+
+ let principal = Services.scriptSecurityManager.getSystemPrincipal();
+ let loadURIOptions = {
+ triggeringPrincipal: principal,
+ };
+
+ let userCharacteristicsPageURI = Services.io.newURI(
+ "about:fingerprinting"
+ );
+
+ browser.loadURI(userCharacteristicsPageURI, loadURIOptions);
+
+ let data = await promise;
+ if (data.debug) {
+ lazy.console.debug(`Debugging Output:`);
+ for (let line of data.debug) {
+ lazy.console.debug(line);
+ }
+ lazy.console.debug(`(debugging output done)`);
+ }
+ lazy.console.debug(`Data:`, data.output);
+
+ lazy.console.debug("Populating Glean metrics...");
+ Glean.characteristics.timezone.set(data.output.foo);
+
+ lazy.console.debug("Unregistering actor");
+ Services.obs.notifyObservers(
+ null,
+ "user-characteristics-populating-data-done"
+ );
+ } finally {
+ this._backgroundBrowsers.delete(browser);
+ }
+ });
+ }
+
+ async pageLoaded(browsingContext, data) {
+ lazy.console.debug(
+ `pageLoaded browsingContext=${browsingContext} data=${data}`
+ );
+
+ let browser = browsingContext.embedderElement;
+
+ let backgroundResolve = this._backgroundBrowsers.get(browser);
+ if (backgroundResolve) {
+ backgroundResolve(data);
+ return;
+ }
+ throw new Error(`No backround resolve for ${browser} found`);
+ }
+}
diff --git a/toolkit/components/resistfingerprinting/components.conf b/toolkit/components/resistfingerprinting/components.conf
index aae29becf4..d7a5f71578 100644
--- a/toolkit/components/resistfingerprinting/components.conf
+++ b/toolkit/components/resistfingerprinting/components.conf
@@ -2,7 +2,7 @@
# vim: set filetype=python:
# 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/.
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
Classes = [
{
@@ -34,4 +34,11 @@ Classes = [
'constructor': 'FingerprintingWebCompatService',
'processes': ProcessSelector.MAIN_PROCESS_ONLY,
},
+ {
+ 'cid': '{ce3e9659-e311-49fb-b18b-7f27c6659b23}',
+ 'contract_ids': ['@mozilla.org/user-characteristics-page;1'],
+ 'esModule': 'resource://gre/modules/UserCharacteristicsPageService.sys.mjs',
+ 'constructor': 'UserCharacteristicsPageService',
+ 'processes': ProcessSelector.MAIN_PROCESS_ONLY,
+ },
]
diff --git a/toolkit/components/resistfingerprinting/content/usercharacteristics.html b/toolkit/components/resistfingerprinting/content/usercharacteristics.html
new file mode 100644
index 0000000000..50071bb21e
--- /dev/null
+++ b/toolkit/components/resistfingerprinting/content/usercharacteristics.html
@@ -0,0 +1,18 @@
+<!-- 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 https://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <meta
+ http-equiv="Content-Security-Policy"
+ content="default-src 'none'; object-src 'none'; script-src chrome:"
+ />
+ <title>about:fingerprinting</title>
+ </head>
+ <body>
+ <script src="chrome://global/content/usercharacteristics/usercharacteristics.js"></script>
+ </body>
+</html>
diff --git a/toolkit/components/resistfingerprinting/content/usercharacteristics.js b/toolkit/components/resistfingerprinting/content/usercharacteristics.js
new file mode 100644
index 0000000000..1f10ba9cbb
--- /dev/null
+++ b/toolkit/components/resistfingerprinting/content/usercharacteristics.js
@@ -0,0 +1,41 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+var debugMsgs = [];
+function debug(...args) {
+ let msg = "";
+ if (!args.length) {
+ debugMsgs.push("");
+ return;
+ }
+
+ let stringify = o => {
+ if (typeof o == "string") {
+ return o;
+ }
+ return JSON.stringify(o);
+ };
+
+ let stringifiedArgs = args.map(stringify);
+ msg += stringifiedArgs.join(" ");
+ debugMsgs.push(msg);
+}
+
+debug("Debug Line");
+debug("Another debug line, with", { an: "object" });
+
+// The first time we put a real value in here, please update browser_usercharacteristics.js
+let output = {
+ foo: "Hello World",
+};
+
+document.dispatchEvent(
+ new CustomEvent("UserCharacteristicsDataDone", {
+ bubbles: true,
+ detail: {
+ debug: debugMsgs,
+ output,
+ },
+ })
+);
diff --git a/toolkit/components/resistfingerprinting/jar.mn b/toolkit/components/resistfingerprinting/jar.mn
new file mode 100644
index 0000000000..657797b6d0
--- /dev/null
+++ b/toolkit/components/resistfingerprinting/jar.mn
@@ -0,0 +1,7 @@
+# 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 https://mozilla.org/MPL/2.0/.
+
+toolkit.jar:
+ content/global/usercharacteristics/usercharacteristics.html (content/usercharacteristics.html)
+ content/global/usercharacteristics/usercharacteristics.js (content/usercharacteristics.js)
diff --git a/toolkit/components/resistfingerprinting/metrics.yaml b/toolkit/components/resistfingerprinting/metrics.yaml
index 3c706d20fa..51b251508c 100644
--- a/toolkit/components/resistfingerprinting/metrics.yaml
+++ b/toolkit/components/resistfingerprinting/metrics.yaml
@@ -1,6 +1,6 @@
# 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/.
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# Adding a new metric? We have docs for that!
# https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/new_definitions_file.html
@@ -337,6 +337,23 @@ characteristics:
data_sensitivity:
- interaction
+ system_locale:
+ type: string
+ description: >
+ The locale used by the host OS for localization.
+ lifetime: application
+ send_in_pings:
+ - user-characteristics
+ notification_emails:
+ - tom@mozilla.com
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881744
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881744#c7
+ expires: never
+ data_sensitivity:
+ - technical
+
target_frame_rate:
type: quantity
unit: int
@@ -409,3 +426,105 @@ characteristics:
expires: never
data_sensitivity:
- interaction
+
+ prefs_privacy_donottrackheader_enabled:
+ type: boolean
+ description: >
+ Sending "do not track" HTTP header
+ lifetime: application
+ send_in_pings:
+ - user-characteristics
+ notification_emails:
+ - tom@mozilla.com
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693#c5
+ expires: never
+ data_sensitivity:
+ - interaction
+
+ prefs_privacy_globalprivacycontrol_enabled:
+ type: boolean
+ description: >
+ Sending "global privacy control" HTTP header
+ lifetime: application
+ send_in_pings:
+ - user-characteristics
+ notification_emails:
+ - tom@mozilla.com
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693#c5
+ expires: never
+ data_sensitivity:
+ - interaction
+
+ prefs_general_autoscroll: # general.autoScroll
+ type: boolean
+ description: >
+ Use autoscrolling
+ lifetime: application
+ send_in_pings:
+ - user-characteristics
+ notification_emails:
+ - tom@mozilla.com
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693#c5
+ expires: never
+ data_sensitivity:
+ - interaction
+
+ prefs_general_smoothscroll: # general.smoothScroll
+ type: boolean
+ description: >
+ Use smooth scrolling
+ lifetime: application
+ send_in_pings:
+ - user-characteristics
+ notification_emails:
+ - tom@mozilla.com
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693#c5
+ expires: never
+ data_sensitivity:
+ - interaction
+
+ prefs_overlay_scrollbars: # widget.gtk.overlay-scrollbars.enabled
+ type: boolean
+ description: >
+ Use overlay scrollbars (or otherwise "Always show scrollbars")
+ lifetime: application
+ send_in_pings:
+ - user-characteristics
+ notification_emails:
+ - tom@mozilla.com
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693#c5
+ expires: never
+ data_sensitivity:
+ - interaction
+
+ prefs_block_popups: # dom.disable_open_during_load
+ type: boolean
+ description: >
+ Block pop-up windows (The dom.disable_open_during_load pref)
+ lifetime: application
+ send_in_pings:
+ - user-characteristics
+ notification_emails:
+ - tom@mozilla.com
+ bugs:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693
+ data_reviews:
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1884693#c5
+ expires: never
+ data_sensitivity:
+ - interaction
diff --git a/toolkit/components/resistfingerprinting/moz.build b/toolkit/components/resistfingerprinting/moz.build
index 9b4e9cc8ed..4b71617b9b 100644
--- a/toolkit/components/resistfingerprinting/moz.build
+++ b/toolkit/components/resistfingerprinting/moz.build
@@ -2,13 +2,15 @@
# vim: set filetype=python:
# 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/.
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
with Files("**"):
BUG_COMPONENT = ("Core", "Privacy: Anti-Tracking")
TEST_DIRS += ["tests"]
+JAR_MANIFESTS += ["jar.mn"]
+
UNIFIED_SOURCES += [
"nsRFPService.cpp",
"RelativeTimeline.cpp",
@@ -39,6 +41,7 @@ EXPORTS.mozilla.gtest += ["nsUserCharacteristics.h"]
EXTRA_JS_MODULES += [
"FingerprintingWebCompatService.sys.mjs",
"RFPHelper.sys.mjs",
+ "UserCharacteristicsPageService.sys.mjs",
]
XPIDL_MODULE = "toolkit_resistfingerprinting"
@@ -50,6 +53,7 @@ XPCOM_MANIFESTS += [
XPIDL_SOURCES += [
"nsIFingerprintingWebCompatService.idl",
"nsIRFPService.idl",
+ "nsIUserCharacteristicsPageService.idl",
]
include("/ipc/chromium/chromium-config.mozbuild")
diff --git a/toolkit/components/resistfingerprinting/nsIFingerprintingWebCompatService.idl b/toolkit/components/resistfingerprinting/nsIFingerprintingWebCompatService.idl
index 01b1379e44..e8c7195a0e 100644
--- a/toolkit/components/resistfingerprinting/nsIFingerprintingWebCompatService.idl
+++ b/toolkit/components/resistfingerprinting/nsIFingerprintingWebCompatService.idl
@@ -1,6 +1,6 @@
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
diff --git a/toolkit/components/resistfingerprinting/nsIRFPService.idl b/toolkit/components/resistfingerprinting/nsIRFPService.idl
index b81868d202..8c83cc7e6e 100644
--- a/toolkit/components/resistfingerprinting/nsIRFPService.idl
+++ b/toolkit/components/resistfingerprinting/nsIRFPService.idl
@@ -1,6 +1,6 @@
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "nsIFingerprintingWebCompatService.idl"
diff --git a/toolkit/components/resistfingerprinting/nsIUserCharacteristicsPageService.idl b/toolkit/components/resistfingerprinting/nsIUserCharacteristicsPageService.idl
new file mode 100644
index 0000000000..ce58c1a14a
--- /dev/null
+++ b/toolkit/components/resistfingerprinting/nsIUserCharacteristicsPageService.idl
@@ -0,0 +1,23 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+webidl BrowsingContext;
+
+[scriptable, uuid(ce3e9659-e311-49fb-b18b-7f27c6659b23)]
+interface nsIUserCharacteristicsPageService : nsISupports {
+
+ /*
+ * Create the UserCharacteristics about: page as a HiddenFrame
+ * and begin the data collection.
+ */
+ Promise createContentPage();
+
+ /*
+ * Called when the UserCharacteristics about: page has been loaded
+ * and supplied data back to the actor, which is passed as `data`
+ */
+ void pageLoaded(in BrowsingContext browsingContext, in jsval data);
+};
diff --git a/toolkit/components/resistfingerprinting/nsRFPService.cpp b/toolkit/components/resistfingerprinting/nsRFPService.cpp
index 643cc2cb7a..f39deb3283 100644
--- a/toolkit/components/resistfingerprinting/nsRFPService.cpp
+++ b/toolkit/components/resistfingerprinting/nsRFPService.cpp
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "nsRFPService.h"
@@ -19,6 +19,7 @@
#include "MainThreadUtils.h"
#include "ScopedNSSTypes.h"
+#include "mozilla/AntiTrackingUtils.h"
#include "mozilla/ArrayIterator.h"
#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
@@ -109,6 +110,8 @@ static mozilla::LazyLogModule gFingerprinterDetection("FingerprinterDetection");
#define LAST_PB_SESSION_EXITED_TOPIC "last-pb-context-exited"
#define IDLE_TOPIC "browser-idle-startup-tasks-finished"
#define GFX_FEATURES "gfx-features-ready"
+#define USER_CHARACTERISTICS_TEST_REQUEST \
+ "user-characteristics-testing-please-populate-data"
static constexpr uint32_t kVideoFramesPerSec = 30;
static constexpr uint32_t kVideoDroppedRatio = 5;
@@ -190,6 +193,9 @@ nsresult nsRFPService::Init() {
rv = obs->AddObserver(this, GFX_FEATURES, false);
NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = obs->AddObserver(this, USER_CHARACTERISTICS_TEST_REQUEST, false);
+ NS_ENSURE_SUCCESS(rv, rv);
}
Preferences::RegisterCallbacks(nsRFPService::PrefChanged, gCallbackPrefs,
@@ -289,6 +295,7 @@ void nsRFPService::StartShutdown() {
obs->RemoveObserver(this, OBSERVER_TOPIC_IDLE_DAILY);
obs->RemoveObserver(this, IDLE_TOPIC);
obs->RemoveObserver(this, GFX_FEATURES);
+ obs->RemoveObserver(this, USER_CHARACTERISTICS_TEST_REQUEST);
}
}
@@ -350,6 +357,12 @@ nsRFPService::Observe(nsISupports* aObject, const char* aTopic,
}
}
+ if (!strcmp(USER_CHARACTERISTICS_TEST_REQUEST, aTopic) &&
+ xpc::IsInAutomation()) {
+ nsUserCharacteristics::PopulateDataAndEventuallySubmit(
+ /* aUpdatePref = */ false, /* aTesting = */ true);
+ }
+
if (!strcmp(OBSERVER_TOPIC_IDLE_DAILY, aTopic)) {
if (StaticPrefs::
privacy_resistFingerprinting_randomization_daily_reset_enabled()) {
@@ -1267,7 +1280,10 @@ Maybe<nsTArray<uint8_t>> nsRFPService::GenerateKey(nsIChannel* aChannel) {
// Set the partitionKey using the top level URI to ensure that the key is
// specific to the top level site.
- attrs.SetPartitionKey(topLevelURI);
+ bool foreignByAncestorContext =
+ AntiTrackingUtils::IsThirdPartyChannel(aChannel) &&
+ loadInfo->GetIsThirdPartyContextToTopWindow();
+ attrs.SetPartitionKey(topLevelURI, foreignByAncestorContext);
nsAutoCString oaSuffix;
attrs.CreateSuffix(oaSuffix);
@@ -1337,8 +1353,14 @@ nsRFPService::CleanRandomKeyByPrincipal(nsIPrincipal* aPrincipal) {
OriginAttributes attrs = aPrincipal->OriginAttributesRef();
nsCOMPtr<nsIURI> uri = aPrincipal->GetURI();
- attrs.SetPartitionKey(uri);
+ attrs.SetPartitionKey(uri, false);
+ ClearBrowsingSessionKey(attrs);
+
+ // We must also include the cross-site embeds of this principal that end up
+ // re-embedded back into the same principal's top level, otherwise state will
+ // persist for this target
+ attrs.SetPartitionKey(uri, true);
ClearBrowsingSessionKey(attrs);
return NS_OK;
}
@@ -1354,14 +1376,21 @@ nsRFPService::CleanRandomKeyByDomain(const nsACString& aDomain) {
// Use the originAttributes to get the partitionKey.
OriginAttributes attrs;
- attrs.SetPartitionKey(httpURI);
+ attrs.SetPartitionKey(httpURI, false);
// Create a originAttributesPattern and set the http partitionKey to the
// pattern.
OriginAttributesPattern pattern;
pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey);
+ ClearBrowsingSessionKey(pattern);
+ // We must also include the cross-site embeds of this principal that end up
+ // re-embedded back into the same principal's top level, otherwise state will
+ // persist for this target
+ attrs.SetPartitionKey(httpURI, true);
+ pattern.mPartitionKey.Reset();
+ pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern);
// Get https URI from the domain.
@@ -1370,10 +1399,17 @@ nsRFPService::CleanRandomKeyByDomain(const nsACString& aDomain) {
NS_ENSURE_SUCCESS(rv, rv);
// Use the originAttributes to get the partitionKey and set to the pattern.
- attrs.SetPartitionKey(httpsURI);
+ attrs.SetPartitionKey(httpsURI, false);
pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey);
+ ClearBrowsingSessionKey(pattern);
+ // We must also include the cross-site embeds of this principal that end up
+ // re-embedded back into the same principal's top level, otherwise state will
+ // persist for this target
+ attrs.SetPartitionKey(httpsURI, true);
+ pattern.mPartitionKey.Reset();
+ pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern);
return NS_OK;
}
@@ -1395,7 +1431,7 @@ nsRFPService::CleanRandomKeyByHost(const nsACString& aHost,
// Use the originAttributes to get the partitionKey.
OriginAttributes attrs;
- attrs.SetPartitionKey(httpURI);
+ attrs.SetPartitionKey(httpURI, false);
// Set the partitionKey to the pattern.
pattern.mPartitionKey.Reset();
@@ -1403,16 +1439,31 @@ nsRFPService::CleanRandomKeyByHost(const nsACString& aHost,
ClearBrowsingSessionKey(pattern);
+ // We must also include the cross-site embeds of this principal that end up
+ // re-embedded back into the same principal's top level, otherwise state will
+ // persist for this target
+ attrs.SetPartitionKey(httpURI, true);
+ pattern.mPartitionKey.Reset();
+ pattern.mPartitionKey.Construct(attrs.mPartitionKey);
+ ClearBrowsingSessionKey(pattern);
+
// Get https URI from the host.
nsCOMPtr<nsIURI> httpsURI;
rv = NS_NewURI(getter_AddRefs(httpsURI), "https://"_ns + aHost);
NS_ENSURE_SUCCESS(rv, rv);
// Use the originAttributes to get the partitionKey and set to the pattern.
- attrs.SetPartitionKey(httpsURI);
+ attrs.SetPartitionKey(httpsURI, false);
pattern.mPartitionKey.Reset();
pattern.mPartitionKey.Construct(attrs.mPartitionKey);
+ ClearBrowsingSessionKey(pattern);
+ // We must also include the cross-site embeds of this principal that end up
+ // re-embedded back into the same principal's top level, otherwise state will
+ // persist for this target
+ attrs.SetPartitionKey(httpsURI, true);
+ pattern.mPartitionKey.Reset();
+ pattern.mPartitionKey.Construct(attrs.mPartitionKey);
ClearBrowsingSessionKey(pattern);
return NS_OK;
}
@@ -2011,19 +2062,63 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
}
// The channel is for the first-party load.
- if (!loadInfo->GetIsThirdPartyContextToTopWindow()) {
+ if (!AntiTrackingUtils::IsThirdPartyChannel(aChannel)) {
return GetOverriddenFingerprintingSettingsForURI(uri, nullptr);
}
// The channel is for the third-party load. We get the first-party URI from
// the top-level window global parent.
- RefPtr<dom::WindowGlobalParent> topWGP =
- bc->Top()->Canonical()->GetCurrentWindowGlobal();
+ RefPtr<dom::CanonicalBrowsingContext> topBC = bc->Top()->Canonical();
+ RefPtr<dom::WindowGlobalParent> topWGP = topBC->GetCurrentWindowGlobal();
if (NS_WARN_IF(!topWGP)) {
return Nothing();
}
+ nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
+ DebugOnly<nsresult> rv =
+ loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ MOZ_ASSERT(cookieJarSettings);
+
+ uint64_t topWindowContextIdFromCJS =
+ net::CookieJarSettings::Cast(cookieJarSettings)
+ ->GetTopLevelWindowContextId();
+
+ // The top-level window could be navigated away when we get the fingerprinting
+ // override here. For example, the beacon requests. In this case, the
+ // top-level windowContext id won't match the inner window id of the top-level
+ // windowGlobalParent. So, we cannot rely on the URI from the top-level
+ // windowGlobalParent because it could be different from the one that creates
+ // the channel. Instead, we fallback to use the partitionKey in the
+ // cookieJarSettings to get the top-level URI.
+ if (topWGP->InnerWindowId() != topWindowContextIdFromCJS) {
+ nsAutoString partitionKey;
+ rv = cookieJarSettings->GetPartitionKey(partitionKey);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+
+ // Bail out early if the partitionKey is empty.
+ if (partitionKey.IsEmpty()) {
+ return Nothing();
+ }
+
+ nsAutoString scheme;
+ nsAutoString domain;
+ int32_t unused;
+ bool unused2;
+ if (!OriginAttributes::ParsePartitionKey(partitionKey, scheme, domain,
+ unused, unused2)) {
+ MOZ_ASSERT(false);
+ return Nothing();
+ }
+
+ nsCOMPtr<nsIURI> topURI;
+ rv = NS_NewURI(getter_AddRefs(topURI), scheme + u"://"_ns + domain);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+
+ return GetOverriddenFingerprintingSettingsForURI(topURI, uri);
+ }
+
nsCOMPtr<nsIPrincipal> topPrincipal = topWGP->DocumentPrincipal();
if (NS_WARN_IF(!topPrincipal)) {
return Nothing();
@@ -2049,19 +2144,20 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
#ifdef DEBUG
// Verify if the top URI matches the partitionKey of the channel.
- nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
- Unused << loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
-
nsAutoString partitionKey;
cookieJarSettings->GetPartitionKey(partitionKey);
OriginAttributes attrs;
- attrs.SetPartitionKey(topURI);
+ attrs.SetPartitionKey(topURI, false);
+
+ OriginAttributes attrsForeignByAncestor;
+ attrsForeignByAncestor.SetPartitionKey(topURI, true);
// The partitionKey of the channel could haven't been set here if the loading
// channel is top-level.
MOZ_ASSERT_IF(!partitionKey.IsEmpty(),
- attrs.mPartitionKey.Equals(partitionKey));
+ attrs.mPartitionKey.Equals(partitionKey) ||
+ attrsForeignByAncestor.mPartitionKey.Equals(partitionKey));
#endif
return GetOverriddenFingerprintingSettingsForURI(topURI, uri);
diff --git a/toolkit/components/resistfingerprinting/nsRFPService.h b/toolkit/components/resistfingerprinting/nsRFPService.h
index 9e0ae9b6af..d45f4172c9 100644
--- a/toolkit/components/resistfingerprinting/nsRFPService.h
+++ b/toolkit/components/resistfingerprinting/nsRFPService.h
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef __nsRFPService_h__
#define __nsRFPService_h__
diff --git a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp
index 9bce616f81..86de7d61a7 100644
--- a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp
+++ b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp
@@ -1,25 +1,34 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "nsUserCharacteristics.h"
#include "nsID.h"
#include "nsIUUIDGenerator.h"
+#include "nsIUserCharacteristicsPageService.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/Logging.h"
#include "mozilla/glean/GleanPings.h"
#include "mozilla/glean/GleanMetrics.h"
+#include "jsapi.h"
+#include "mozilla/Components.h"
+#include "mozilla/dom/Promise-inl.h"
+
+#include "mozilla/StaticPrefs_dom.h"
+#include "mozilla/StaticPrefs_general.h"
#include "mozilla/StaticPrefs_media.h"
+#include "mozilla/StaticPrefs_widget.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/PreferenceSheet.h"
#include "mozilla/RelativeLuminanceUtils.h"
#include "mozilla/ServoStyleConsts.h"
#include "mozilla/dom/ScreenBinding.h"
+#include "mozilla/intl/OSPreferences.h"
#include "mozilla/intl/TimeZone.h"
#include "mozilla/widget/ScreenManager.h"
@@ -33,7 +42,9 @@
# include "nsMacUtilsImpl.h"
#endif
-static mozilla::LazyLogModule gUserCharacteristicsLog("UserCharacteristics");
+using namespace mozilla;
+
+static LazyLogModule gUserCharacteristicsLog("UserCharacteristics");
// ==================================================================
namespace testing {
@@ -41,9 +52,9 @@ extern "C" {
int MaxTouchPoints() {
#if defined(XP_WIN)
- return mozilla::widget::WinUtils::GetMaxTouchPoints();
+ return widget::WinUtils::GetMaxTouchPoints();
#elif defined(MOZ_WIDGET_ANDROID)
- return mozilla::java::GeckoAppShell::GetMaxTouchPoints();
+ return java::GeckoAppShell::GetMaxTouchPoints();
#else
return 0;
#endif
@@ -53,84 +64,113 @@ int MaxTouchPoints() {
}; // namespace testing
// ==================================================================
+// ==================================================================
+already_AddRefed<mozilla::dom::Promise> ContentPageStuff() {
+ nsCOMPtr<nsIUserCharacteristicsPageService> ucp =
+ do_GetService("@mozilla.org/user-characteristics-page;1");
+ MOZ_ASSERT(ucp);
+
+ RefPtr<mozilla::dom::Promise> promise;
+ nsresult rv = ucp->CreateContentPage(getter_AddRefs(promise));
+ if (NS_FAILED(rv)) {
+ MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Error,
+ ("Could not create Content Page"));
+ return nullptr;
+ }
+ MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Debug,
+ ("Created Content Page"));
+
+ return promise.forget();
+}
+
void PopulateCSSProperties() {
- mozilla::glean::characteristics::video_dynamic_range.Set(
- mozilla::LookAndFeel::GetInt(
- mozilla::LookAndFeel::IntID::VideoDynamicRange));
- mozilla::glean::characteristics::prefers_reduced_transparency.Set(
- mozilla::LookAndFeel::GetInt(
- mozilla::LookAndFeel::IntID::PrefersReducedTransparency));
- mozilla::glean::characteristics::prefers_reduced_motion.Set(
- mozilla::LookAndFeel::GetInt(
- mozilla::LookAndFeel::IntID::PrefersReducedMotion));
- mozilla::glean::characteristics::inverted_colors.Set(
- mozilla::LookAndFeel::GetInt(
- mozilla::LookAndFeel::IntID::InvertedColors));
- mozilla::glean::characteristics::color_scheme.Set(
- (int)mozilla::PreferenceSheet::ContentPrefs().mColorScheme);
-
- mozilla::StylePrefersContrast prefersContrast = [] {
+ glean::characteristics::prefers_reduced_transparency.Set(
+ LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedTransparency));
+ glean::characteristics::prefers_reduced_motion.Set(
+ LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion));
+ glean::characteristics::inverted_colors.Set(
+ LookAndFeel::GetInt(LookAndFeel::IntID::InvertedColors));
+ glean::characteristics::color_scheme.Set(
+ (int)PreferenceSheet::ContentPrefs().mColorScheme);
+
+ StylePrefersContrast prefersContrast = [] {
// Replicates Gecko_MediaFeatures_PrefersContrast but without a Document
- if (!mozilla::PreferenceSheet::ContentPrefs().mUseAccessibilityTheme &&
- mozilla::PreferenceSheet::ContentPrefs().mUseDocumentColors) {
- return mozilla::StylePrefersContrast::NoPreference;
+ if (!PreferenceSheet::ContentPrefs().mUseAccessibilityTheme &&
+ PreferenceSheet::ContentPrefs().mUseDocumentColors) {
+ return StylePrefersContrast::NoPreference;
}
- const auto& colors = mozilla::PreferenceSheet::ContentPrefs().ColorsFor(
- mozilla::ColorScheme::Light);
- float ratio = mozilla::RelativeLuminanceUtils::ContrastRatio(
+ const auto& colors =
+ PreferenceSheet::ContentPrefs().ColorsFor(ColorScheme::Light);
+ float ratio = RelativeLuminanceUtils::ContrastRatio(
colors.mDefaultBackground, colors.mDefault);
// https://www.w3.org/TR/WCAG21/#contrast-minimum
if (ratio < 4.5f) {
- return mozilla::StylePrefersContrast::Less;
+ return StylePrefersContrast::Less;
}
// https://www.w3.org/TR/WCAG21/#contrast-enhanced
if (ratio >= 7.0f) {
- return mozilla::StylePrefersContrast::More;
+ return StylePrefersContrast::More;
}
- return mozilla::StylePrefersContrast::Custom;
+ return StylePrefersContrast::Custom;
}();
- mozilla::glean::characteristics::prefers_contrast.Set((int)prefersContrast);
+ glean::characteristics::prefers_contrast.Set((int)prefersContrast);
}
void PopulateScreenProperties() {
- auto& screenManager = mozilla::widget::ScreenManager::GetSingleton();
- RefPtr<mozilla::widget::Screen> screen = screenManager.GetPrimaryScreen();
+ auto& screenManager = widget::ScreenManager::GetSingleton();
+ RefPtr<widget::Screen> screen = screenManager.GetPrimaryScreen();
MOZ_ASSERT(screen);
- mozilla::dom::ScreenColorGamut colorGamut;
+ dom::ScreenColorGamut colorGamut;
screen->GetColorGamut(&colorGamut);
- mozilla::glean::characteristics::color_gamut.Set((int)colorGamut);
+ glean::characteristics::color_gamut.Set((int)colorGamut);
int32_t colorDepth;
screen->GetColorDepth(&colorDepth);
- mozilla::glean::characteristics::color_depth.Set(colorDepth);
+ glean::characteristics::color_depth.Set(colorDepth);
+
+ glean::characteristics::color_gamut.Set((int)colorGamut);
+ glean::characteristics::color_depth.Set(colorDepth);
+ const LayoutDeviceIntRect rect = screen->GetRect();
+ glean::characteristics::screen_height.Set(rect.Height());
+ glean::characteristics::screen_width.Set(rect.Width());
- mozilla::glean::characteristics::color_gamut.Set((int)colorGamut);
- mozilla::glean::characteristics::color_depth.Set(colorDepth);
- const mozilla::LayoutDeviceIntRect rect = screen->GetRect();
- mozilla::glean::characteristics::screen_height.Set(rect.Height());
- mozilla::glean::characteristics::screen_width.Set(rect.Width());
+ glean::characteristics::video_dynamic_range.Set(screen->GetIsHDR());
}
void PopulateMissingFonts() {
nsCString aMissingFonts;
gfxPlatformFontList::PlatformFontList()->GetMissingFonts(aMissingFonts);
- mozilla::glean::characteristics::missing_fonts.Set(aMissingFonts);
+ glean::characteristics::missing_fonts.Set(aMissingFonts);
}
void PopulatePrefs() {
nsAutoCString acceptLang;
- mozilla::Preferences::GetLocalizedCString("intl.accept_languages",
- acceptLang);
- mozilla::glean::characteristics::prefs_intl_accept_languages.Set(acceptLang);
+ Preferences::GetLocalizedCString("intl.accept_languages", acceptLang);
+ glean::characteristics::prefs_intl_accept_languages.Set(acceptLang);
+
+ glean::characteristics::prefs_media_eme_enabled.Set(
+ StaticPrefs::media_eme_enabled());
+
+ glean::characteristics::prefs_zoom_text_only.Set(
+ !Preferences::GetBool("browser.zoom.full"));
+
+ glean::characteristics::prefs_privacy_donottrackheader_enabled.Set(
+ StaticPrefs::privacy_donottrackheader_enabled());
+ glean::characteristics::prefs_privacy_globalprivacycontrol_enabled.Set(
+ StaticPrefs::privacy_globalprivacycontrol_enabled());
- mozilla::glean::characteristics::prefs_media_eme_enabled.Set(
- mozilla::StaticPrefs::media_eme_enabled());
+ glean::characteristics::prefs_general_autoscroll.Set(
+ Preferences::GetBool("general.autoScroll"));
+ glean::characteristics::prefs_general_smoothscroll.Set(
+ StaticPrefs::general_smoothScroll());
+ glean::characteristics::prefs_overlay_scrollbars.Set(
+ StaticPrefs::widget_gtk_overlay_scrollbars_enabled());
- mozilla::glean::characteristics::prefs_zoom_text_only.Set(
- !mozilla::Preferences::GetBool("browser.zoom.full"));
+ glean::characteristics::prefs_block_popups.Set(
+ StaticPrefs::dom_disable_open_during_load());
}
// ==================================================================
@@ -138,12 +178,16 @@ void PopulatePrefs() {
// metric is set, this variable should be incremented. It'll be a lot. It's
// okay. We're going to need it to know (including during development) what is
// the source of the data we are looking at.
-const int kSubmissionSchema = 0;
+const int kSubmissionSchema = 1;
+
+const auto* const kLastVersionPref =
+ "toolkit.telemetry.user_characteristics_ping.last_version_sent";
+const auto* const kCurrentVersionPref =
+ "toolkit.telemetry.user_characteristics_ping.current_version";
/* static */
void nsUserCharacteristics::MaybeSubmitPing() {
- MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Debug,
- ("In MaybeSubmitPing()"));
+ MOZ_LOG(gUserCharacteristicsLog, LogLevel::Debug, ("In MaybeSubmitPing()"));
MOZ_ASSERT(XRE_IsParentProcess());
/**
@@ -161,14 +205,8 @@ void nsUserCharacteristics::MaybeSubmitPing() {
* Sent = Current Version.
*
*/
- const auto* const kLastVersionPref =
- "toolkit.telemetry.user_characteristics_ping.last_version_sent";
- const auto* const kCurrentVersionPref =
- "toolkit.telemetry.user_characteristics_ping.current_version";
-
- auto lastSubmissionVersion =
- mozilla::Preferences::GetInt(kLastVersionPref, 0);
- auto currentVersion = mozilla::Preferences::GetInt(kCurrentVersionPref, 0);
+ auto lastSubmissionVersion = Preferences::GetInt(kLastVersionPref, 0);
+ auto currentVersion = Preferences::GetInt(kCurrentVersionPref, 0);
MOZ_ASSERT(currentVersion == -1 || lastSubmissionVersion <= currentVersion,
"lastSubmissionVersion is somehow greater than currentVersion "
@@ -176,46 +214,40 @@ void nsUserCharacteristics::MaybeSubmitPing() {
if (lastSubmissionVersion < 0) {
// This is a way for users to opt out of this ping specifically.
- MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Debug,
+ MOZ_LOG(gUserCharacteristicsLog, LogLevel::Debug,
("Returning, User Opt-out"));
return;
}
if (currentVersion == 0) {
// Do nothing. We do not want any pings.
- MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Debug,
+ MOZ_LOG(gUserCharacteristicsLog, LogLevel::Debug,
("Returning, currentVersion == 0"));
return;
}
if (currentVersion == -1) {
// currentVersion = -1 is a development value to force a ping submission
- MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Debug,
+ MOZ_LOG(gUserCharacteristicsLog, LogLevel::Debug,
("Force-Submitting Ping"));
- if (NS_SUCCEEDED(PopulateData())) {
- SubmitPing();
- }
+ PopulateDataAndEventuallySubmit(false);
return;
}
if (lastSubmissionVersion > currentVersion) {
// This is an unexpected scneario that indicates something is wrong. We
// asserted against it (in debug, above) We will try to sanity-correct
// ourselves by setting it to the current version.
- mozilla::Preferences::SetInt(kLastVersionPref, currentVersion);
- MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Warning,
+ Preferences::SetInt(kLastVersionPref, currentVersion);
+ MOZ_LOG(gUserCharacteristicsLog, LogLevel::Warning,
("Returning, lastSubmissionVersion > currentVersion"));
return;
}
if (lastSubmissionVersion == currentVersion) {
// We are okay, we've already submitted the most recent ping
- MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Warning,
+ MOZ_LOG(gUserCharacteristicsLog, LogLevel::Warning,
("Returning, lastSubmissionVersion == currentVersion"));
return;
}
if (lastSubmissionVersion < currentVersion) {
- if (NS_SUCCEEDED(PopulateData())) {
- if (NS_SUCCEEDED(SubmitPing())) {
- mozilla::Preferences::SetInt(kLastVersionPref, currentVersion);
- }
- }
+ PopulateDataAndEventuallySubmit(false);
} else {
MOZ_ASSERT_UNREACHABLE("Should never reach here");
}
@@ -225,73 +257,128 @@ const auto* const kUUIDPref =
"toolkit.telemetry.user_characteristics_ping.uuid";
/* static */
-nsresult nsUserCharacteristics::PopulateData(bool aTesting /* = false */) {
- MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Warning,
- ("Populating Data"));
+void nsUserCharacteristics::PopulateDataAndEventuallySubmit(
+ bool aUpdatePref /* = true */, bool aTesting /* = false */
+) {
+ MOZ_LOG(gUserCharacteristicsLog, LogLevel::Warning, ("Populating Data"));
MOZ_ASSERT(XRE_IsParentProcess());
- mozilla::glean::characteristics::submission_schema.Set(kSubmissionSchema);
+
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (!obs) {
+ return;
+ }
+
+ // This notification tells us to register the actor
+ obs->NotifyObservers(nullptr, "user-characteristics-populating-data",
+ nullptr);
+
+ glean::characteristics::submission_schema.Set(kSubmissionSchema);
nsAutoCString uuidString;
- nsresult rv = mozilla::Preferences::GetCString(kUUIDPref, uuidString);
+ nsresult rv = Preferences::GetCString(kUUIDPref, uuidString);
if (NS_FAILED(rv) || uuidString.Length() == 0) {
nsCOMPtr<nsIUUIDGenerator> uuidgen =
do_GetService("@mozilla.org/uuid-generator;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_FAILED(rv)) {
+ return;
+ }
nsIDToCString id(nsID::GenerateUUID());
uuidString = id.get();
- mozilla::Preferences::SetCString(kUUIDPref, uuidString);
+ Preferences::SetCString(kUUIDPref, uuidString);
}
- mozilla::glean::characteristics::client_identifier.Set(uuidString);
- mozilla::glean::characteristics::max_touch_points.Set(
- testing::MaxTouchPoints());
+ glean::characteristics::client_identifier.Set(uuidString);
+
+ glean::characteristics::max_touch_points.Set(testing::MaxTouchPoints());
+
+ // ------------------------------------------------------------------------
- if (aTesting) {
+ if (!aTesting) {
// Many of the later peices of data do not work in a gtest
- // so just populate something, and return
- return NS_OK;
- }
+ // so skip populating them
+
+ // ------------------------------------------------------------------------
- PopulateMissingFonts();
- PopulateCSSProperties();
- PopulateScreenProperties();
- PopulatePrefs();
+ PopulateMissingFonts();
+ PopulateCSSProperties();
+ PopulateScreenProperties();
+ PopulatePrefs();
- mozilla::glean::characteristics::target_frame_rate.Set(
- gfxPlatform::TargetFrameRate());
+ glean::characteristics::target_frame_rate.Set(
+ gfxPlatform::TargetFrameRate());
- int32_t processorCount = 0;
+ int32_t processorCount = 0;
#if defined(XP_MACOSX)
- if (nsMacUtilsImpl::IsTCSMAvailable()) {
- // On failure, zero is returned from GetPhysicalCPUCount()
- // and we fallback to PR_GetNumberOfProcessors below.
- processorCount = nsMacUtilsImpl::GetPhysicalCPUCount();
- }
+ if (nsMacUtilsImpl::IsTCSMAvailable()) {
+ // On failure, zero is returned from GetPhysicalCPUCount()
+ // and we fallback to PR_GetNumberOfProcessors below.
+ processorCount = nsMacUtilsImpl::GetPhysicalCPUCount();
+ }
#endif
- if (processorCount == 0) {
- processorCount = PR_GetNumberOfProcessors();
+ if (processorCount == 0) {
+ processorCount = PR_GetNumberOfProcessors();
+ }
+ glean::characteristics::processor_count.Set(processorCount);
+
+ AutoTArray<char16_t, 128> tzBuffer;
+ auto result = intl::TimeZone::GetDefaultTimeZone(tzBuffer);
+ if (result.isOk()) {
+ NS_ConvertUTF16toUTF8 timeZone(
+ nsDependentString(tzBuffer.Elements(), tzBuffer.Length()));
+ glean::characteristics::timezone.Set(timeZone);
+ } else {
+ glean::characteristics::timezone.Set("<error>"_ns);
+ }
+
+ nsAutoCString locale;
+ intl::OSPreferences::GetInstance()->GetSystemLocale(locale);
+ glean::characteristics::system_locale.Set(locale);
}
- mozilla::glean::characteristics::processor_count.Set(processorCount);
-
- AutoTArray<char16_t, 128> tzBuffer;
- auto result = mozilla::intl::TimeZone::GetDefaultTimeZone(tzBuffer);
- if (result.isOk()) {
- NS_ConvertUTF16toUTF8 timeZone(
- nsDependentString(tzBuffer.Elements(), tzBuffer.Length()));
- mozilla::glean::characteristics::timezone.Set(timeZone);
+
+ // When this promise resolves, everything succeeded and we can submit.
+ RefPtr<mozilla::dom::Promise> promise = ContentPageStuff();
+
+ // ------------------------------------------------------------------------
+
+ auto fulfillSteps = [aUpdatePref, aTesting](
+ JSContext* aCx, JS::Handle<JS::Value> aPromiseResult,
+ mozilla::ErrorResult& aRv) {
+ MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Debug,
+ ("ContentPageStuff Promise Resolved"));
+
+ if (!aTesting) {
+ nsUserCharacteristics::SubmitPing();
+ }
+
+ if (aUpdatePref) {
+ MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Debug,
+ ("Updating preference"));
+ auto current_version =
+ mozilla::Preferences::GetInt(kCurrentVersionPref, 0);
+ mozilla::Preferences::SetInt(kLastVersionPref, current_version);
+ }
+ };
+
+ // Something failed in the Content Page...
+ auto rejectSteps = [](JSContext* aCx, JS::Handle<JS::Value> aReason,
+ mozilla::ErrorResult& aRv) {
+ MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Error,
+ ("ContentPageStuff Promise Rejected"));
+ };
+
+ if (promise) {
+ promise->AddCallbacksWithCycleCollectedArgs(std::move(fulfillSteps),
+ std::move(rejectSteps));
} else {
- mozilla::glean::characteristics::timezone.Set("<error>"_ns);
+ MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Error,
+ ("Did not get a Promise back from ContentPageStuff"));
}
-
- return NS_OK;
}
/* static */
-nsresult nsUserCharacteristics::SubmitPing() {
+void nsUserCharacteristics::SubmitPing() {
MOZ_LOG(gUserCharacteristicsLog, mozilla::LogLevel::Warning,
("Submitting Ping"));
- mozilla::glean_pings::UserCharacteristics.Submit();
-
- return NS_OK;
+ glean_pings::UserCharacteristics.Submit();
}
diff --git a/toolkit/components/resistfingerprinting/nsUserCharacteristics.h b/toolkit/components/resistfingerprinting/nsUserCharacteristics.h
index a52bc9aea7..7d78dcd965 100644
--- a/toolkit/components/resistfingerprinting/nsUserCharacteristics.h
+++ b/toolkit/components/resistfingerprinting/nsUserCharacteristics.h
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef __nsUserCharacteristics_h__
#define __nsUserCharacteristics_h__
@@ -12,9 +12,15 @@ class nsUserCharacteristics {
public:
static void MaybeSubmitPing();
- // Public For testing
- static nsresult PopulateData(bool aTesting = false);
- static nsresult SubmitPing();
+ /*
+ * These APIs are public only for testing using the gtest
+ * When PopulateDataAndEventuallySubmit is called with aTesting = true
+ * it will not submit the data, and SubmitPing must be called explicitly.
+ * This is perfect because that's what we want for the gtest.
+ */
+ static void PopulateDataAndEventuallySubmit(bool aUpdatePref = true,
+ bool aTesting = false);
+ static void SubmitPing();
};
namespace testing {
diff --git a/toolkit/components/resistfingerprinting/pings.yaml b/toolkit/components/resistfingerprinting/pings.yaml
index 46a4b2da19..ddbd48d1d1 100644
--- a/toolkit/components/resistfingerprinting/pings.yaml
+++ b/toolkit/components/resistfingerprinting/pings.yaml
@@ -1,6 +1,6 @@
# 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/.
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
---
$schema: moz://mozilla.org/schemas/glean/pings/2-0-0
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser.toml b/toolkit/components/resistfingerprinting/tests/browser/browser.toml
index 213d6d4287..527e39ad89 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser.toml
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser.toml
@@ -31,3 +31,5 @@ support-files = [
support-files = ["file_pdf.pdf"]
["browser_serviceWorker_fingerprinting_webcompat.js"]
+
+["browser_usercharacteristics.js"]
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_fingerprinter_telemetry.js b/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_fingerprinter_telemetry.js
index d2a33a4347..1098d91138 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_fingerprinter_telemetry.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_fingerprinter_telemetry.js
@@ -1,7 +1,7 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
"use strict";
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization.js b/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization.js
index 8b4be78d53..e526f7fff1 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization.js
@@ -1,6 +1,6 @@
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/**
* Bug 1816189 - Testing canvas randomization on canvas data extraction.
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization_worker.js b/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization_worker.js
index dd7c292fa4..723d7382f8 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization_worker.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_canvas_randomization_worker.js
@@ -1,6 +1,6 @@
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
const emptyPage =
getRootDirectory(gTestPath).replace(
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingRemoteOverrides.js b/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingRemoteOverrides.js
index 29c7c9170b..ac4722fd84 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingRemoteOverrides.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingRemoteOverrides.js
@@ -1,6 +1,6 @@
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
"use strict";
@@ -20,6 +20,18 @@ const TARGET_CanvasRandomization = 0x000000100;
const TARGET_WindowOuterSize = 0x002000000;
const TARGET_Gamepad = 0x00800000;
+const TEST_PAGE =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.com"
+ ) + "empty.html";
+
+const TEST_ANOTHER_PAGE =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.net"
+ ) + "empty.html";
+
// A helper function to filter high 32 bits.
function extractLow32Bits(value) {
return value & 0xffffffff;
@@ -404,3 +416,49 @@ add_task(async function test_pref_override_remote_settings() {
db.clear();
});
+
+// Bug 1873682 - Verify that a third-party beacon request won't hit the
+// assertion in nsRFPService::GetOverriddenFingerprintingSettingsForChannel().
+add_task(async function test_beacon_request() {
+ // Open an empty page.
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE);
+
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [TEST_ANOTHER_PAGE],
+ async url => {
+ // Create a third-party iframe
+ let ifr = content.document.createElement("iframe");
+
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ ifr.src = url;
+ });
+
+ await SpecialPowers.spawn(ifr, [url], url => {
+ // Sending the beacon request right before the tab navigates away.
+ content.addEventListener("unload", _ => {
+ let value = ["text"];
+ let blob = new Blob(value, {
+ type: "application/x-www-form-urlencoded",
+ });
+ content.navigator.sendBeacon(url, blob);
+ });
+ });
+
+ // Navigate the tab to another page.
+ content.location = url;
+ }
+ );
+
+ await BrowserTestUtils.browserLoaded(
+ tab.linkedBrowser,
+ false,
+ TEST_ANOTHER_PAGE
+ );
+
+ ok(true, "Successfully navigates away.");
+
+ BrowserTestUtils.removeTab(tab);
+});
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js b/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
index 1a882fc63d..62335b2fe7 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
@@ -1,6 +1,6 @@
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
"use strict";
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_font_fingerprinter_telemetry.js b/toolkit/components/resistfingerprinting/tests/browser/browser_font_fingerprinter_telemetry.js
index 2231197eed..0cccf0c5f3 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser_font_fingerprinter_telemetry.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_font_fingerprinter_telemetry.js
@@ -1,7 +1,7 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
"use strict";
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_fpiServiceWorkers_fingerprinting.js b/toolkit/components/resistfingerprinting/tests/browser/browser_fpiServiceWorkers_fingerprinting.js
index 64279ae442..aaa40a7928 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser_fpiServiceWorkers_fingerprinting.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_fpiServiceWorkers_fingerprinting.js
@@ -68,7 +68,7 @@ runTestInFirstAndThirdPartyContexts(
},
async _ => {
await new Promise(resolve => {
- Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
+ Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
resolve()
);
});
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_serviceWorker_fingerprinting_webcompat.js b/toolkit/components/resistfingerprinting/tests/browser/browser_serviceWorker_fingerprinting_webcompat.js
index a9bab38e61..eb1ab8d795 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/browser_serviceWorker_fingerprinting_webcompat.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_serviceWorker_fingerprinting_webcompat.js
@@ -59,7 +59,7 @@ runTestInFirstAndThirdPartyContexts(
async _ => {
await new Promise(resolve => {
- Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
+ Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
resolve()
);
});
@@ -142,7 +142,7 @@ runTestInFirstAndThirdPartyContexts(
async _ => {
await new Promise(resolve => {
- Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
+ Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
resolve()
);
});
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics.js b/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics.js
new file mode 100644
index 0000000000..9896948311
--- /dev/null
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const emptyPage =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.com"
+ ) + "empty.html";
+
+function promiseObserverNotification() {
+ return TestUtils.topicObserved(
+ "user-characteristics-populating-data-done",
+ _ => {
+ var submitted = false;
+ GleanPings.userCharacteristics.testBeforeNextSubmit(_ => {
+ submitted = true;
+
+ // Did we assign a value we got out of about:fingerprinting?
+ // For now, we are sticking the test value in a random telemetry
+ // metric, but once we have a real metric, we'll update this
+ Assert.equal(
+ "Hello World",
+ Glean.characteristics.timezone.testGetValue()
+ );
+ });
+ GleanPings.userCharacteristics.submit();
+
+ return submitted;
+ }
+ );
+}
+
+add_task(async function run_test() {
+ info("Starting test...");
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: emptyPage },
+ async function tabTask(_) {
+ let promise = promiseObserverNotification();
+
+ Services.obs.notifyObservers(
+ null,
+ "user-characteristics-testing-please-populate-data"
+ );
+
+ let submitted = await promise;
+ Assert.ok(submitted);
+ }
+ );
+});
diff --git a/toolkit/components/resistfingerprinting/tests/browser/head.js b/toolkit/components/resistfingerprinting/tests/browser/head.js
index 9d8ec19956..e2fddaecc6 100644
--- a/toolkit/components/resistfingerprinting/tests/browser/head.js
+++ b/toolkit/components/resistfingerprinting/tests/browser/head.js
@@ -54,7 +54,7 @@ function countDifferencesInArrayBuffers(buffer1, buffer2) {
function promiseObserver(topic) {
return new Promise(resolve => {
- let obs = (aSubject, aTopic, aData) => {
+ let obs = (aSubject, aTopic) => {
Services.obs.removeObserver(obs, aTopic);
resolve(aSubject);
};
diff --git a/toolkit/components/resistfingerprinting/tests/gtest/test_reduceprecision.cpp b/toolkit/components/resistfingerprinting/tests/gtest/test_reduceprecision.cpp
index 5d8b598ff0..a36b819d8f 100644
--- a/toolkit/components/resistfingerprinting/tests/gtest/test_reduceprecision.cpp
+++ b/toolkit/components/resistfingerprinting/tests/gtest/test_reduceprecision.cpp
@@ -2,7 +2,7 @@
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include <math.h>
diff --git a/toolkit/components/resistfingerprinting/tests/gtest/test_usercharping.cpp b/toolkit/components/resistfingerprinting/tests/gtest/test_usercharping.cpp
index dd1cbe7d46..2eefa8e7fe 100644
--- a/toolkit/components/resistfingerprinting/tests/gtest/test_usercharping.cpp
+++ b/toolkit/components/resistfingerprinting/tests/gtest/test_usercharping.cpp
@@ -2,7 +2,7 @@
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/gtest/nsUserCharacteristics.h"
@@ -35,7 +35,8 @@ TEST(ResistFingerprinting, UserCharacteristics_Simple)
TEST(ResistFingerprinting, UserCharacteristics_Complex)
{
- nsUserCharacteristics::PopulateData(true);
+ nsUserCharacteristics::PopulateDataAndEventuallySubmit(
+ /* aUpdatePref = */ false, /* aTesting = */ true);
bool submitted = false;
mozilla::glean_pings::UserCharacteristics.TestBeforeNextSubmit(
@@ -102,7 +103,8 @@ TEST(ResistFingerprinting, UserCharacteristics_ClearPref)
.value()
.get());
});
- nsUserCharacteristics::PopulateData(true);
+ nsUserCharacteristics::PopulateDataAndEventuallySubmit(
+ /* aUpdatePref = */ false, /* aTesting = */ true);
nsUserCharacteristics::SubmitPing();
auto original_value =
@@ -135,7 +137,8 @@ TEST(ResistFingerprinting, UserCharacteristics_ClearPref)
Preferences::GetCString(kUUIDPref, uuidValue);
ASSERT_STRNE("", uuidValue.get());
});
- nsUserCharacteristics::PopulateData(true);
+ nsUserCharacteristics::PopulateDataAndEventuallySubmit(
+ /* aUpdatePref = */ false, /* aTesting = */ true);
nsUserCharacteristics::SubmitPing();
Preferences::SetBool("datareporting.healthreport.uploadEnabled",