From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../resistfingerprinting/test/browser/head.js | 1063 ++++++++++++++++++++ 1 file changed, 1063 insertions(+) create mode 100644 browser/components/resistfingerprinting/test/browser/head.js (limited to 'browser/components/resistfingerprinting/test/browser/head.js') diff --git a/browser/components/resistfingerprinting/test/browser/head.js b/browser/components/resistfingerprinting/test/browser/head.js new file mode 100644 index 0000000000..244bd578ef --- /dev/null +++ b/browser/components/resistfingerprinting/test/browser/head.js @@ -0,0 +1,1063 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +ChromeUtils.defineESModuleGetters(this, { + ContentBlockingAllowList: + "resource://gre/modules/ContentBlockingAllowList.sys.mjs", +}); + +const TEST_PATH = + "http://example.net/browser/browser/" + + "components/resistfingerprinting/test/browser/"; + +const PERFORMANCE_TIMINGS = [ + "navigationStart", + "unloadEventStart", + "unloadEventEnd", + "redirectStart", + "redirectEnd", + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "secureConnectionStart", + "requestStart", + "responseStart", + "responseEnd", + "domLoading", + "domInteractive", + "domContentLoadedEventStart", + "domContentLoadedEventEnd", + "domComplete", + "loadEventStart", + "loadEventEnd", +]; + +/** + * Sets up tests for making sure that performance APIs have been correctly + * spoofed or disabled. + */ +let setupPerformanceAPISpoofAndDisableTest = async function ( + resistFingerprinting, + reduceTimerPrecision, + crossOriginIsolated, + expectedPrecision, + runTests, + workerCall +) { + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", resistFingerprinting], + ["privacy.reduceTimerPrecision", reduceTimerPrecision], + [ + "privacy.resistFingerprinting.reduceTimerPrecision.microseconds", + expectedPrecision * 1000, + ], + ["browser.tabs.remote.useCrossOriginOpenerPolicy", crossOriginIsolated], + ["browser.tabs.remote.useCrossOriginEmbedderPolicy", crossOriginIsolated], + ], + }); + + let url = crossOriginIsolated + ? `https://example.com/browser/browser/components/resistfingerprinting` + + `/test/browser/coop_header.sjs?crossOriginIsolated=${crossOriginIsolated}` + : TEST_PATH + "file_dummy.html"; + + let win = await BrowserTestUtils.openNewBrowserWindow(); + let tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, url); + + // No matter what we set the precision to, if we're in ResistFingerprinting + // mode we use the larger of the precision pref and the RFP time-atom constant + if (resistFingerprinting) { + const RFP_TIME_ATOM_MS = 16.667; + expectedPrecision = Math.max(RFP_TIME_ATOM_MS, expectedPrecision); + } + await SpecialPowers.spawn( + tab.linkedBrowser, + [ + { + list: PERFORMANCE_TIMINGS, + resistFingerprinting, + precision: expectedPrecision, + isRoundedFunc: isTimeValueRounded.toString(), + workerCall, + }, + ], + runTests + ); + + if (crossOriginIsolated) { + let remoteType = tab.linkedBrowser.remoteType; + ok( + remoteType.startsWith(E10SUtils.WEB_REMOTE_COOP_COEP_TYPE_PREFIX), + `${remoteType} expected to be coop+coep` + ); + } + + await BrowserTestUtils.closeWindow(win); +}; + +let isTimeValueRounded = (x, expectedPrecision, console) => { + const nearestExpected = Math.round(x / expectedPrecision) * expectedPrecision; + // First we do the perfectly normal check that should work just fine + if (x === nearestExpected) { + return true; + } + + // When we're dividing by non-whole numbers, we may not get perfect + // multiplication/division because of floating points. + // When dealing with ms since epoch, a double's precision is on the order + // of 1/5 of a microsecond, so we use a value a little higher than that as + // our epsilon. + // To be clear, this error is introduced in our re-calculation of 'rounded' + // above in JavaScript. + const error = Math.abs(x - nearestExpected); + + if (console) { + console.log( + "Additional Debugging Info: Expected Precision: " + + expectedPrecision + + " Measured Value: " + + x + + " Nearest Expected Vaue: " + + nearestExpected + + " Error: " + + error + ); + } + + if (Math.abs(error) < 0.0005) { + return true; + } + + // Then we handle the case where you're sub-millisecond and the timer is not + // We check that the timer is not sub-millisecond by assuming it is not if it + // returns an even number of milliseconds + if ( + Math.round(expectedPrecision) != expectedPrecision && + Math.round(x) == x + ) { + let acceptableIntRounding = false; + acceptableIntRounding |= Math.floor(nearestExpected) == x; + acceptableIntRounding |= Math.ceil(nearestExpected) == x; + if (acceptableIntRounding) { + return true; + } + } + + return false; +}; + +let setupAndRunCrossOriginIsolatedTest = async function ( + options, + expectedPrecision, + runTests, + workerCall +) { + let prefsToSet = [ + [ + "privacy.resistFingerprinting.reduceTimerPrecision.microseconds", + expectedPrecision * 1000, + ], + ]; + + if (options.resistFingerprinting !== undefined) { + prefsToSet = prefsToSet.concat([ + ["privacy.resistFingerprinting", options.resistFingerprinting], + ]); + } else { + options.resistFingerprinting = false; + } + + if (options.resistFingerprintingPBMOnly !== undefined) { + prefsToSet = prefsToSet.concat([ + [ + "privacy.resistFingerprinting.pbmode", + options.resistFingerprintingPBMOnly, + ], + ]); + } else { + options.resistFingerprintingPBMOnly = false; + } + + if (options.reduceTimerPrecision !== undefined) { + prefsToSet = prefsToSet.concat([ + ["privacy.reduceTimerPrecision", options.reduceTimerPrecision], + ]); + } else { + options.reduceTimerPrecision = false; + } + + if (options.crossOriginIsolated !== undefined) { + prefsToSet = prefsToSet.concat([ + [ + "browser.tabs.remote.useCrossOriginOpenerPolicy", + options.crossOriginIsolated, + ], + [ + "browser.tabs.remote.useCrossOriginEmbedderPolicy", + options.crossOriginIsolated, + ], + ]); + } else { + options.crossOriginIsolated = false; + } + + if (options.openPrivateWindow === undefined) { + options.openPrivateWindow = false; + } + if (options.shouldBeRounded === undefined) { + options.shouldBeRounded = true; + } + + console.log(prefsToSet); + await SpecialPowers.pushPrefEnv({ set: prefsToSet }); + + let win = await BrowserTestUtils.openNewBrowserWindow({ + private: options.openPrivateWindow, + }); + let tab = await BrowserTestUtils.openNewForegroundTab( + win.gBrowser, + `https://example.com/browser/browser/components/resistfingerprinting` + + `/test/browser/coop_header.sjs?crossOriginIsolated=${options.crossOriginIsolated}` + ); + + // No matter what we set the precision to, if we're in ResistFingerprinting + // mode we use the larger of the precision pref and the RFP time-atom constant + if ( + options.resistFingerprinting || + (options.resistFingerprintingPBMOnly && options.openPrivateWindow) + ) { + const RFP_TIME_ATOM_MS = 16.667; + expectedPrecision = Math.max(RFP_TIME_ATOM_MS, expectedPrecision); + } + await SpecialPowers.spawn( + tab.linkedBrowser, + [ + { + precision: expectedPrecision, + isRoundedFunc: isTimeValueRounded.toString(), + workerCall, + options, + }, + ], + runTests + ); + + if (options.crossOriginIsolated) { + let remoteType = tab.linkedBrowser.remoteType; + ok( + remoteType.startsWith(E10SUtils.WEB_REMOTE_COOP_COEP_TYPE_PREFIX), + `${remoteType} expected to be coop+coep` + ); + } + + await BrowserTestUtils.closeWindow(win); + await SpecialPowers.popPrefEnv(); +}; + +// This function calculates the maximum available window dimensions and returns +// them as an object. +async function calcMaximumAvailSize(aChromeWidth, aChromeHeight) { + let chromeUIWidth; + let chromeUIHeight; + let testPath = + "http://example.net/browser/browser/" + + "components/resistfingerprinting/test/browser/"; + + // If the chrome UI dimensions is not given, we will calculate it. + if (!aChromeWidth || !aChromeHeight) { + let win = await BrowserTestUtils.openNewBrowserWindow(); + + let tab = await BrowserTestUtils.openNewForegroundTab( + win.gBrowser, + testPath + "file_dummy.html" + ); + + let contentSize = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + async function () { + let result = { + width: content.innerWidth, + height: content.innerHeight, + }; + + return result; + } + ); + + // Calculate the maximum available window size which is depending on the + // available screen space. + chromeUIWidth = win.outerWidth - contentSize.width; + chromeUIHeight = win.outerHeight - contentSize.height; + + BrowserTestUtils.removeTab(tab); + await BrowserTestUtils.closeWindow(win); + } else { + chromeUIWidth = aChromeWidth; + chromeUIHeight = aChromeHeight; + } + + let availWidth = window.screen.availWidth; + let availHeight = window.screen.availHeight; + + // Ideally, we would round the window size as 1000x1000. But the available + // screen space might not suffice. So, we decide the size according to the + // available screen size. + let availContentWidth = Math.min(1000, availWidth - chromeUIWidth); + let availContentHeight; + + // If it is GTK window, we would consider the system decorations when we + // calculating avail content height since the system decorations won't be + // reported when we get available screen dimensions. + if (AppConstants.MOZ_WIDGET_GTK) { + availContentHeight = Math.min(1000, -40 + availHeight - chromeUIHeight); + } else { + availContentHeight = Math.min(1000, availHeight - chromeUIHeight); + } + + // Rounded the desire size to the nearest 200x100. + let maxAvailWidth = availContentWidth - (availContentWidth % 200); + let maxAvailHeight = availContentHeight - (availContentHeight % 100); + + return { maxAvailWidth, maxAvailHeight }; +} + +async function calcPopUpWindowChromeUISize() { + let testPath = + "http://example.net/browser/browser/" + + "components/resistFingerprinting/test/browser/"; + // open a popup window to acquire the chrome UI size of it. + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + testPath + "file_dummy.html" + ); + + let result = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + async function () { + let win; + + await new Promise(resolve => { + win = content.open("about:blank", "", "width=1000,height=1000"); + win.onload = () => resolve(); + }); + + let res = { + chromeWidth: win.outerWidth - win.innerWidth, + chromeHeight: win.outerHeight - win.innerHeight, + }; + + win.close(); + + return res; + } + ); + + BrowserTestUtils.removeTab(tab); + + return result; +} + +async function testWindowOpen( + aBrowser, + aSettingWidth, + aSettingHeight, + aTargetWidth, + aTargetHeight, + aMaxAvailWidth, + aMaxAvailHeight, + aPopupChromeUIWidth, + aPopupChromeUIHeight +) { + // If the target size is greater than the maximum available content size, + // we set the target size to it. + if (aTargetWidth > aMaxAvailWidth) { + aTargetWidth = aMaxAvailWidth; + } + + if (aTargetHeight > aMaxAvailHeight) { + aTargetHeight = aMaxAvailHeight; + } + + // Create the testing window features. + let winFeatures = "width=" + aSettingWidth + ",height=" + aSettingHeight; + + let testParams = { + winFeatures, + targetWidth: aTargetWidth, + targetHeight: aTargetHeight, + }; + + await SpecialPowers.spawn(aBrowser, [testParams], async function (input) { + // Call window.open() with window features. + await new Promise(resolve => { + let win = content.open("http://example.net/", "", input.winFeatures); + + win.onload = () => { + is( + win.screen.width, + input.targetWidth, + "The screen.width has a correct rounded value" + ); + is( + win.screen.height, + input.targetHeight, + "The screen.height has a correct rounded value" + ); + is( + win.innerWidth, + input.targetWidth, + "The window.innerWidth has a correct rounded value" + ); + is( + win.innerHeight, + input.targetHeight, + "The window.innerHeight has a correct rounded value" + ); + + win.close(); + resolve(); + }; + }); + }); +} + +async function testWindowSizeSetting( + aBrowser, + aSettingWidth, + aSettingHeight, + aTargetWidth, + aTargetHeight, + aInitWidth, + aInitHeight, + aTestOuter, + aMaxAvailWidth, + aMaxAvailHeight, + aPopupChromeUIWidth, + aPopupChromeUIHeight +) { + // If the target size is greater than the maximum available content size, + // we set the target size to it. + if (aTargetWidth > aMaxAvailWidth) { + aTargetWidth = aMaxAvailWidth; + } + + if (aTargetHeight > aMaxAvailHeight) { + aTargetHeight = aMaxAvailHeight; + } + + let testParams = { + initWidth: aInitWidth, + initHeight: aInitHeight, + settingWidth: aSettingWidth + (aTestOuter ? aPopupChromeUIWidth : 0), + settingHeight: aSettingHeight + (aTestOuter ? aPopupChromeUIHeight : 0), + targetWidth: aTargetWidth, + targetHeight: aTargetHeight, + testOuter: aTestOuter, + }; + + await SpecialPowers.spawn(aBrowser, [testParams], async function (input) { + let win; + // Open a new window and wait until it loads. + await new Promise(resolve => { + // Given a initial window size which should be different from target + // size. We need this to trigger 'onresize' event. + let initWinFeatures = + "width=" + input.initWidth + ",height=" + input.initHeight; + win = content.open("http://example.net/", "", initWinFeatures); + win.onload = () => resolve(); + }); + + // Test inner/outerWidth. + await new Promise(resolve => { + win.addEventListener( + "resize", + () => { + is( + win.screen.width, + input.targetWidth, + "The screen.width has a correct rounded value" + ); + is( + win.innerWidth, + input.targetWidth, + "The window.innerWidth has a correct rounded value" + ); + + resolve(); + }, + { once: true } + ); + + if (input.testOuter) { + win.outerWidth = input.settingWidth; + } else { + win.innerWidth = input.settingWidth; + } + }); + + win.close(); + // Open a new window and wait until it loads. + await new Promise(resolve => { + // Given a initial window size which should be different from target + // size. We need this to trigger 'onresize' event. + let initWinFeatures = + "width=" + input.initWidth + ",height=" + input.initHeight; + win = content.open("http://example.net/", "", initWinFeatures); + win.onload = () => resolve(); + }); + + // Test inner/outerHeight. + await new Promise(resolve => { + win.addEventListener( + "resize", + () => { + is( + win.screen.height, + input.targetHeight, + "The screen.height has a correct rounded value" + ); + is( + win.innerHeight, + input.targetHeight, + "The window.innerHeight has a correct rounded value" + ); + + resolve(); + }, + { once: true } + ); + + if (input.testOuter) { + win.outerHeight = input.settingHeight; + } else { + win.innerHeight = input.settingHeight; + } + }); + + win.close(); + }); +} + +class RoundedWindowTest { + // testOuter is optional. run() can be invoked with only 1 parameter. + static run(testCases, testOuter) { + // "this" is the calling class itself. + // e.g. when invoked by RoundedWindowTest.run(), "this" is "class RoundedWindowTest". + let test = new this(testCases); + add_task(async () => test.setup()); + add_task(async () => { + if (testOuter == undefined) { + // If testOuter is not given, do tests for both inner and outer. + await test.doTests(false); + await test.doTests(true); + } else { + await test.doTests(testOuter); + } + }); + } + + constructor(testCases) { + this.testCases = testCases; + } + + async setup() { + await SpecialPowers.pushPrefEnv({ + set: [["privacy.resistFingerprinting", true]], + }); + + // Calculate the popup window's chrome UI size for tests of outerWidth/Height. + let popUpChromeUISize = await calcPopUpWindowChromeUISize(); + + this.popupChromeUIWidth = popUpChromeUISize.chromeWidth; + this.popupChromeUIHeight = popUpChromeUISize.chromeHeight; + + // Calculate the maximum available size. + let maxAvailSize = await calcMaximumAvailSize( + this.popupChromeUIWidth, + this.popupChromeUIHeight + ); + + this.maxAvailWidth = maxAvailSize.maxAvailWidth; + this.maxAvailHeight = maxAvailSize.maxAvailHeight; + } + + async doTests(testOuter) { + // Open a tab to test. + this.tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + TEST_PATH + "file_dummy.html" + ); + + for (let test of this.testCases) { + await this.doTest(test, testOuter); + } + + BrowserTestUtils.removeTab(this.tab); + } + + async doTest() { + throw new Error("RoundedWindowTest.doTest must be overridden."); + } +} + +class WindowSettingTest extends RoundedWindowTest { + async doTest(test, testOuter) { + await testWindowSizeSetting( + this.tab.linkedBrowser, + test.settingWidth, + test.settingHeight, + test.targetWidth, + test.targetHeight, + test.initWidth, + test.initHeight, + testOuter, + this.maxAvailWidth, + this.maxAvailHeight, + this.popupChromeUIWidth, + this.popupChromeUIHeight + ); + } +} + +class OpenTest extends RoundedWindowTest { + async doTest(test) { + await testWindowOpen( + this.tab.linkedBrowser, + test.settingWidth, + test.settingHeight, + test.targetWidth, + test.targetHeight, + this.maxAvailWidth, + this.maxAvailHeight, + this.popupChromeUIWidth, + this.popupChromeUIHeight + ); + } +} + +// ============================================================ +const FRAMER_DOMAIN = "example.com"; +const IFRAME_DOMAIN = "example.org"; +const CROSS_ORIGIN_DOMAIN = "example.net"; + +async function runActualTest(uri, testFunction, expectedResults, extraData) { + let browserWin = gBrowser; + let openedWin = null; + + if ("private_window" in extraData) { + openedWin = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + browserWin = openedWin.gBrowser; + } + + let tab = await BrowserTestUtils.openNewForegroundTab(browserWin, uri); + + if ("etp_reload" in extraData) { + ContentBlockingAllowList.add(tab.linkedBrowser); + await BrowserTestUtils.reloadTab(tab); + } + + /* + * We expect that `runTheTest` is going to be able to communicate with the iframe + * or tab that it opens, but if it cannot (because we are using noopener), we kind + * of hack around and get the data directly. + */ + if ("noopener" in extraData) { + var popupTabPromise = BrowserTestUtils.waitForNewTab( + browserWin, + extraData.await_uri + ); + } + + // In SpecialPowers.spawn, extraData goes through a structuredClone, which cannot clone + // functions. await_uri is sometimes a function. This filters out keys that are used by + // this function (runActualTest) and not by runTheTest or testFunction. It avoids the + // cloning issue, and avoids polluting the object in those called functions. + let filterExtraData = function (x) { + let banned_keys = ["private_window", "etp_reload", "noopener", "await_uri"]; + return Object.fromEntries( + Object.entries(x).filter(([k, v]) => !banned_keys.includes(k)) + ); + }; + + let result = await SpecialPowers.spawn( + tab.linkedBrowser, + [IFRAME_DOMAIN, CROSS_ORIGIN_DOMAIN, filterExtraData(extraData)], + async function (iframe_domain_, cross_origin_domain_, extraData_) { + return content.wrappedJSObject.runTheTest( + iframe_domain_, + cross_origin_domain_, + extraData_ + ); + } + ); + + if ("noopener" in extraData) { + await popupTabPromise; + if (Services.appinfo.OS === "WINNT") { + await new Promise(r => setTimeout(r, 1000)); + } + + let popup_tab = browserWin.tabs[browserWin.tabs.length - 1]; + result = await SpecialPowers.spawn( + popup_tab.linkedBrowser, + [], + async function () { + let r = content.wrappedJSObject.give_result(); + return r; + } + ); + BrowserTestUtils.removeTab(popup_tab); + } + + testFunction(result, expectedResults, extraData); + + if ("etp_reload" in extraData) { + ContentBlockingAllowList.remove(tab.linkedBrowser); + } + BrowserTestUtils.removeTab(tab); + if ("private_window" in extraData) { + await BrowserTestUtils.closeWindow(openedWin); + } +} + +async function defaultsTest( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "default"; + expectedResults.shouldRFPApply = false; + if (extraPrefs != undefined) { + await SpecialPowers.pushPrefEnv({ + set: extraPrefs, + }); + } + await runActualTest(uri, testFunction, expectedResults, extraData); + if (extraPrefs != undefined) { + await SpecialPowers.popPrefEnv(); + } +} + +async function simpleRFPTest( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "simple RFP enabled"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [["privacy.resistFingerprinting", true]].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +async function simplePBMRFPTest( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.private_window = true; + extraData.testDesc = extraData.testDesc || "simple RFP in PBM enabled"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [["privacy.resistFingerprinting.pbmode", true]].concat( + extraPrefs || [] + ), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +async function simpleFPPTest( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "simple FPP enabled"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.fingerprintingProtection", true], + ["privacy.fingerprintingProtection.overrides", "+NavigatorHWConcurrency"], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +async function simplePBMFPPTest( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.private_window = true; + extraData.testDesc = extraData.testDesc || "simple FPP in PBM enabled"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.fingerprintingProtection.pbmode", true], + ["privacy.fingerprintingProtection.overrides", "+HardwareConcurrency"], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +// (A) RFP is exempted on the framer and framee and (if needed) on another cross-origin domain +async function testA( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "test (A)"; + expectedResults.shouldRFPApply = false; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true], + [ + "privacy.resistFingerprinting.exemptedDomains", + `${FRAMER_DOMAIN}, ${IFRAME_DOMAIN}, ${CROSS_ORIGIN_DOMAIN}`, + ], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +// (B) RFP is exempted on the framer and framee but is not on another (if needed) cross-origin domain +async function testB( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "test (B)"; + expectedResults.shouldRFPApply = false; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true], + [ + "privacy.resistFingerprinting.exemptedDomains", + `${FRAMER_DOMAIN}, ${IFRAME_DOMAIN}`, + ], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +// (C) RFP is exempted on the framer and (if needed) on another cross-origin domain, but not the framee +async function testC( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "test (C)"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true], + [ + "privacy.resistFingerprinting.exemptedDomains", + `${FRAMER_DOMAIN}, ${CROSS_ORIGIN_DOMAIN}`, + ], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +// (D) RFP is exempted on the framer but not the framee nor another (if needed) cross-origin domain +async function testD( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "test (D)"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true], + ["privacy.resistFingerprinting.exemptedDomains", `${FRAMER_DOMAIN}`], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +// (E) RFP is not exempted on the framer nor the framee but (if needed) is exempted on another cross-origin domain +async function testE( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "test (E)"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true], + [ + "privacy.resistFingerprinting.exemptedDomains", + `${CROSS_ORIGIN_DOMAIN}`, + ], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +// (F) RFP is not exempted on the framer nor the framee nor another (if needed) cross-origin domain +async function testF( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "test (F)"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true], + ["privacy.resistFingerprinting.exemptedDomains", ""], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +// (G) RFP is not exempted on the framer but is on the framee and (if needed) on another cross-origin domain +async function testG( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "test (G)"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true], + [ + "privacy.resistFingerprinting.exemptedDomains", + `${IFRAME_DOMAIN}, ${CROSS_ORIGIN_DOMAIN}`, + ], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} + +// (H) RFP is not exempted on the framer nor another (if needed) cross-origin domain but is on the framee +async function testH( + uri, + testFunction, + expectedResults, + extraData, + extraPrefs +) { + if (extraData == undefined) { + extraData = {}; + } + extraData.testDesc = extraData.testDesc || "test (H)"; + expectedResults.shouldRFPApply = true; + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true], + ["privacy.resistFingerprinting.exemptedDomains", `${IFRAME_DOMAIN}`], + ].concat(extraPrefs || []), + }); + + await runActualTest(uri, testFunction, expectedResults, extraData); + + await SpecialPowers.popPrefEnv(); +} -- cgit v1.2.3