summaryrefslogtreecommitdiffstats
path: root/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprinting_randomization_key.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/resistfingerprinting/tests/browser/browser_fingerprinting_randomization_key.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/resistfingerprinting/tests/browser/browser_fingerprinting_randomization_key.js')
-rw-r--r--toolkit/components/resistfingerprinting/tests/browser/browser_fingerprinting_randomization_key.js490
1 files changed, 490 insertions, 0 deletions
diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprinting_randomization_key.js b/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprinting_randomization_key.js
new file mode 100644
index 0000000000..f2d037491d
--- /dev/null
+++ b/toolkit/components/resistfingerprinting/tests/browser/browser_fingerprinting_randomization_key.js
@@ -0,0 +1,490 @@
+let { ForgetAboutSite } = ChromeUtils.importESModule(
+ "resource://gre/modules/ForgetAboutSite.sys.mjs"
+);
+
+requestLongerTimeout(2);
+
+const TEST_DOMAIN = "https://example.com";
+const TEST_DOMAIN_ANOTHER = "https://example.org";
+const TEST_DOMAIN_THIRD = "https://example.net";
+
+const TEST_PAGE =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ TEST_DOMAIN
+ ) + "testPage.html";
+const TEST_DOMAIN_ANOTHER_PAGE =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ TEST_DOMAIN_ANOTHER
+ ) + "testPage.html";
+const TEST_DOMAIN_THIRD_PAGE =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ TEST_DOMAIN_THIRD
+ ) + "testPage.html";
+
+/**
+ * A helper function to get the random key in a hex string format and test if
+ * the random key works properly.
+ *
+ * @param {Browser} browser The browser element of the testing tab.
+ * @param {string} firstPartyDomain The first-party domain loaded on the tab
+ * @param {string} thirdPartyDomain The third-party domain to test
+ * @returns {string} The random key hex string
+ */
+async function getRandomKeyHexFromBrowser(
+ browser,
+ firstPartyDomain,
+ thirdPartyDomain
+) {
+ // Get the key from the cookieJarSettings of the browser element.
+ let key = browser.cookieJarSettings.fingerprintingRandomizationKey;
+ let keyHex = key.map(bytes => bytes.toString(16).padStart(2, "0")).join("");
+
+ // Get the key from the cookieJarSettings of the top-level document.
+ let keyTop = await SpecialPowers.spawn(browser, [], _ => {
+ return content.document.cookieJarSettings.fingerprintingRandomizationKey;
+ });
+ let keyTopHex = keyTop
+ .map(bytes => bytes.toString(16).padStart(2, "0"))
+ .join("");
+
+ is(
+ keyTopHex,
+ keyHex,
+ "The fingerprinting random key should match between the browser element and the top-level document."
+ );
+
+ // Get the key from the cookieJarSettings of an about:blank iframe.
+ let keyAboutBlank = await SpecialPowers.spawn(browser, [], async _ => {
+ let ifr = content.document.createElement("iframe");
+
+ let loaded = new content.Promise(resolve => {
+ ifr.onload = resolve;
+ });
+ content.document.body.appendChild(ifr);
+ ifr.src = "about:blank";
+
+ await loaded;
+
+ return SpecialPowers.spawn(ifr, [], _ => {
+ return content.document.cookieJarSettings.fingerprintingRandomizationKey;
+ });
+ });
+
+ let keyAboutBlankHex = keyAboutBlank
+ .map(bytes => bytes.toString(16).padStart(2, "0"))
+ .join("");
+ is(
+ keyAboutBlankHex,
+ keyHex,
+ "The fingerprinting random key should match between the browser element and the about:blank iframe document."
+ );
+
+ // Get the key from the cookieJarSettings of the javascript URL iframe
+ // document.
+ let keyJavascriptURL = await SpecialPowers.spawn(browser, [], async _ => {
+ let ifr = content.document.getElementById("testFrame");
+
+ return ifr.contentDocument.cookieJarSettings.fingerprintingRandomizationKey;
+ });
+
+ let keyJavascriptURLHex = keyJavascriptURL
+ .map(bytes => bytes.toString(16).padStart(2, "0"))
+ .join("");
+ is(
+ keyJavascriptURLHex,
+ keyHex,
+ "The fingerprinting random key should match between the browser element and the javascript URL iframe document."
+ );
+
+ // Get the key from the cookieJarSettings of an first-party iframe.
+ let keyFirstPartyFrame = await SpecialPowers.spawn(
+ browser,
+ [firstPartyDomain],
+ async domain => {
+ let ifr = content.document.createElement("iframe");
+
+ let loaded = new content.Promise(resolve => {
+ ifr.onload = resolve;
+ });
+ content.document.body.appendChild(ifr);
+ ifr.src = domain;
+
+ await loaded;
+
+ return SpecialPowers.spawn(ifr, [], _ => {
+ return content.document.cookieJarSettings
+ .fingerprintingRandomizationKey;
+ });
+ }
+ );
+
+ let keyFirstPartyFrameHex = keyFirstPartyFrame
+ .map(bytes => bytes.toString(16).padStart(2, "0"))
+ .join("");
+ is(
+ keyFirstPartyFrameHex,
+ keyHex,
+ "The fingerprinting random key should match between the browser element and the first-party iframe document."
+ );
+
+ // Get the key from the cookieJarSettings of an third-party iframe
+ let keyThirdPartyFrame = await SpecialPowers.spawn(
+ browser,
+ [thirdPartyDomain],
+ async domain => {
+ let ifr = content.document.createElement("iframe");
+
+ let loaded = new content.Promise(resolve => {
+ ifr.onload = resolve;
+ });
+ content.document.body.appendChild(ifr);
+ ifr.src = domain;
+
+ await loaded;
+
+ return SpecialPowers.spawn(ifr, [], _ => {
+ return content.document.cookieJarSettings
+ .fingerprintingRandomizationKey;
+ });
+ }
+ );
+
+ let keyThirdPartyFrameHex = keyThirdPartyFrame
+ .map(bytes => bytes.toString(16).padStart(2, "0"))
+ .join("");
+ is(
+ keyThirdPartyFrameHex,
+ keyHex,
+ "The fingerprinting random key should match between the browser element and the third-party iframe document."
+ );
+
+ return keyHex;
+}
+
+// Test accessing the fingerprinting randomization key will throw if
+// fingerprinting resistance is disabled.
+add_task(async function test_randomization_disabled_with_rfp_disabled() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["privacy.resistFingerprinting", false],
+ ["privacy.resistFingerprinting.pbmode", false],
+ ["privacy.fingerprintingProtection", false],
+ ["privacy.fingerprintingProtection.pbmode", false],
+ ],
+ });
+
+ // Ensure accessing the fingerprinting randomization key of the browser
+ // element will throw if fingerprinting randomization is disabled.
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE);
+
+ try {
+ let key =
+ tab.linkedBrowser.cookieJarSettings.fingerprintingRandomizationKey;
+ ok(
+ false,
+ `Accessing the fingerprinting randomization key should throw when fingerprinting resistance is disabled. ${key}`
+ );
+ } catch (e) {
+ ok(
+ true,
+ "It should throw when getting the key when fingerprinting resistance is disabled."
+ );
+ }
+
+ // Ensure accessing the fingerprinting randomization key of the top-level
+ // document will throw if fingerprinting randomization is disabled.
+ try {
+ await SpecialPowers.spawn(tab.linkedBrowser, [], _ => {
+ return content.document.cookieJarSettings.fingerprintingRandomizationKey;
+ });
+ } catch (e) {
+ ok(
+ true,
+ "It should throw when getting the key when fingerprinting resistance is disabled."
+ );
+ }
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+// Test the fingerprinting randomization key generation.
+add_task(async function test_generate_randomization_key() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["privacy.resistFingerprinting", true]],
+ });
+
+ for (let testPrivateWin of [true, false]) {
+ let win = window;
+
+ if (testPrivateWin) {
+ win = await BrowserTestUtils.openNewBrowserWindow({
+ private: true,
+ });
+ }
+
+ let tabOne = await BrowserTestUtils.openNewForegroundTab(
+ win.gBrowser,
+ TEST_PAGE
+ );
+ let keyHexOne;
+
+ try {
+ keyHexOne = await getRandomKeyHexFromBrowser(
+ tabOne.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+ ok(true, `The fingerprinting random key: ${keyHexOne}`);
+ } catch (e) {
+ ok(
+ false,
+ "Shouldn't fail when getting the random key from the cookieJarSettings"
+ );
+ }
+
+ // Open the test domain again and check if the key remains the same.
+ let tabTwo = await BrowserTestUtils.openNewForegroundTab(
+ win.gBrowser,
+ TEST_PAGE
+ );
+ try {
+ let keyHexTwo = await getRandomKeyHexFromBrowser(
+ tabTwo.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+ is(
+ keyHexTwo,
+ keyHexOne,
+ `The key should remain the same after reopening the tab.`
+ );
+ } catch (e) {
+ ok(
+ false,
+ "Shouldn't fail when getting the random key from the cookieJarSettings"
+ );
+ }
+
+ // Open a tab with a different domain to see if the key changes.
+ let tabAnother = await BrowserTestUtils.openNewForegroundTab(
+ win.gBrowser,
+ TEST_DOMAIN_ANOTHER_PAGE
+ );
+ try {
+ let keyHexAnother = await getRandomKeyHexFromBrowser(
+ tabAnother.linkedBrowser,
+ TEST_DOMAIN_ANOTHER_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+ isnot(
+ keyHexAnother,
+ keyHexOne,
+ `The key should be different when loading a different domain`
+ );
+ } catch (e) {
+ ok(
+ false,
+ "Shouldn't fail when getting the random key from the cookieJarSettings"
+ );
+ }
+
+ BrowserTestUtils.removeTab(tabOne);
+ BrowserTestUtils.removeTab(tabTwo);
+ BrowserTestUtils.removeTab(tabAnother);
+ if (testPrivateWin) {
+ await BrowserTestUtils.closeWindow(win);
+ }
+ }
+});
+
+// Test the fingerprinting randomization key will change after private session
+// ends.
+add_task(async function test_reset_key_after_pbm_session_ends() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["privacy.resistFingerprinting", true]],
+ });
+
+ let privateWin = await BrowserTestUtils.openNewBrowserWindow({
+ private: true,
+ });
+
+ // Open a tab in the private window.
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ privateWin.gBrowser,
+ TEST_PAGE
+ );
+
+ let keyHex = await getRandomKeyHexFromBrowser(
+ tab.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+
+ // Close the window and open another private window.
+ BrowserTestUtils.removeTab(tab);
+
+ let promisePBExit = TestUtils.topicObserved("last-pb-context-exited");
+ await BrowserTestUtils.closeWindow(privateWin);
+ await promisePBExit;
+
+ privateWin = await BrowserTestUtils.openNewBrowserWindow({
+ private: true,
+ });
+
+ // Open a tab again in the new private window.
+ tab = await BrowserTestUtils.openNewForegroundTab(
+ privateWin.gBrowser,
+ TEST_PAGE
+ );
+
+ let keyHexNew = await getRandomKeyHexFromBrowser(
+ tab.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+
+ // Ensure the keys are different.
+ isnot(keyHexNew, keyHex, "Ensure the new key is different from the old one.");
+
+ BrowserTestUtils.removeTab(tab);
+ await BrowserTestUtils.closeWindow(privateWin);
+});
+
+// Test accessing the fingerprinting randomization key will throw in normal
+// windows if we exempt fingerprinting protection in normal windows.
+add_task(async function test_randomization_with_exempted_normal_window() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["privacy.resistFingerprinting", false],
+ ["privacy.resistFingerprinting.pbmode", true],
+ ["privacy.fingerprintingProtection", false],
+ ["privacy.fingerprintingProtection.pbmode", false],
+ ],
+ });
+
+ // Ensure accessing the fingerprinting randomization key of the browser
+ // element will throw if fingerprinting randomization is exempted from normal
+ // windows.
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE);
+
+ try {
+ let key =
+ tab.linkedBrowser.cookieJarSettings.fingerprintingRandomizationKey;
+ ok(
+ false,
+ `Accessing the fingerprinting randomization key should throw when fingerprinting resistance is exempted in normal windows. ${key}`
+ );
+ } catch (e) {
+ ok(
+ true,
+ "It should throw when getting the key when fingerprinting resistance is exempted in normal windows."
+ );
+ }
+
+ // Ensure accessing the fingerprinting randomization key of the top-level
+ // document will throw if fingerprinting randomization is exempted from normal
+ // windows.
+ try {
+ await SpecialPowers.spawn(tab.linkedBrowser, [], _ => {
+ return content.document.cookieJarSettings.fingerprintingRandomizationKey;
+ });
+ } catch (e) {
+ ok(
+ true,
+ "It should throw when getting the key when fingerprinting resistance is exempted in normal windows."
+ );
+ }
+
+ BrowserTestUtils.removeTab(tab);
+
+ // Open a private window and check the key can be accessed there.
+ let privateWin = await BrowserTestUtils.openNewBrowserWindow({
+ private: true,
+ });
+
+ // Open a tab in the private window.
+ tab = await BrowserTestUtils.openNewForegroundTab(
+ privateWin.gBrowser,
+ TEST_PAGE
+ );
+
+ // Access the key, this shouldn't throw an error.
+ await getRandomKeyHexFromBrowser(
+ tab.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+
+ BrowserTestUtils.removeTab(tab);
+ await BrowserTestUtils.closeWindow(privateWin);
+});
+
+// Test that the random key gets reset when the site data gets cleared.
+add_task(async function test_reset_random_key_when_clear_site_data() {
+ // Enable fingerprinting randomization key generation.
+ await SpecialPowers.pushPrefEnv({
+ set: [["privacy.resistFingerprinting", true]],
+ });
+
+ // Open a tab and get randomization key from the test domain.
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE);
+
+ let keyHex = await getRandomKeyHexFromBrowser(
+ tab.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+
+ // Open another tab and get randomization key from another domain.
+ let anotherTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_DOMAIN_ANOTHER_PAGE
+ );
+
+ let keyHexAnother = await getRandomKeyHexFromBrowser(
+ anotherTab.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+
+ BrowserTestUtils.removeTab(tab);
+ BrowserTestUtils.removeTab(anotherTab);
+
+ // Call ForgetAboutSite for the test domain.
+ await ForgetAboutSite.removeDataFromDomain("example.com");
+
+ // Open the tab for the test domain again and verify the key is reset.
+ tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE);
+ let keyHexNew = await getRandomKeyHexFromBrowser(
+ tab.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+
+ // Open the tab for another domain again and verify the key is intact.
+ anotherTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_DOMAIN_ANOTHER_PAGE
+ );
+ let keyHexAnotherNew = await getRandomKeyHexFromBrowser(
+ anotherTab.linkedBrowser,
+ TEST_PAGE,
+ TEST_DOMAIN_THIRD_PAGE
+ );
+
+ // Ensure the keys are different for the test domain.
+ isnot(keyHexNew, keyHex, "Ensure the new key is different from the old one.");
+
+ // Ensure the key for another domain isn't changed.
+ is(
+ keyHexAnother,
+ keyHexAnotherNew,
+ "Ensure the key of another domain isn't reset."
+ );
+
+ BrowserTestUtils.removeTab(tab);
+ BrowserTestUtils.removeTab(anotherTab);
+});