diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /toolkit/components/resistfingerprinting/tests/browser/head.js | |
parent | Initial commit. (diff) | |
download | firefox-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/head.js')
-rw-r--r-- | toolkit/components/resistfingerprinting/tests/browser/head.js | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/toolkit/components/resistfingerprinting/tests/browser/head.js b/toolkit/components/resistfingerprinting/tests/browser/head.js new file mode 100644 index 0000000000..9d8ec19956 --- /dev/null +++ b/toolkit/components/resistfingerprinting/tests/browser/head.js @@ -0,0 +1,227 @@ +// Number of bits in the canvas that we randomize when canvas randomization is +// enabled. +const NUM_RANDOMIZED_CANVAS_BITS = 256; + +/** + * Compares two Uint8Arrays and returns the number of bits that are different. + * + * @param {Uint8ClampedArray} arr1 - The first Uint8ClampedArray to compare. + * @param {Uint8ClampedArray} arr2 - The second Uint8ClampedArray to compare. + * @returns {number} - The number of bits that are different between the two + * arrays. + */ +function countDifferencesInUint8Arrays(arr1, arr2) { + let count = 0; + for (let i = 0; i < arr1.length; i++) { + let diff = arr1[i] ^ arr2[i]; + while (diff > 0) { + count += diff & 1; + diff >>= 1; + } + } + return count; +} + +/** + * Compares two ArrayBuffer objects to see if they are different. + * + * @param {ArrayBuffer} buffer1 - The first buffer to compare. + * @param {ArrayBuffer} buffer2 - The second buffer to compare. + * @returns {boolean} True if the buffers are different, false if they are the + * same. + */ +function countDifferencesInArrayBuffers(buffer1, buffer2) { + // compare the byte lengths of the two buffers + if (buffer1.byteLength !== buffer2.byteLength) { + return true; + } + + // create typed arrays to represent the two buffers + const view1 = new DataView(buffer1); + const view2 = new DataView(buffer2); + + let differences = 0; + // compare the byte values of the two typed arrays + for (let i = 0; i < buffer1.byteLength; i++) { + if (view1.getUint8(i) !== view2.getUint8(i)) { + differences += 1; + } + } + + // the two buffers are the same + return differences; +} + +function promiseObserver(topic) { + return new Promise(resolve => { + let obs = (aSubject, aTopic, aData) => { + Services.obs.removeObserver(obs, aTopic); + resolve(aSubject); + }; + Services.obs.addObserver(obs, topic); + }); +} + +/** + * + * Spawns a worker in the given browser and sends a callback function to it. + * The result of the callback function is returned as a Promise. + * + * @param {object} browser - The browser context to spawn the worker in. + * @param {Function} fn - The callback function to send to the worker. + * @returns {Promise} A Promise that resolves to the result of the callback function. + */ +function runFunctionInWorker(browser, fn) { + return SpecialPowers.spawn(browser, [fn.toString()], async callback => { + // Create a worker. + let worker = new content.Worker("worker.js"); + + // Send the callback to the worker. + return new content.Promise(resolve => { + worker.onmessage = e => { + resolve(e.data.result); + }; + + worker.postMessage({ + callback, + }); + }); + }); +} + +const TEST_FIRST_PARTY_CONTEXT_PAGE = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.net" + ) + "testPage.html"; +const TEST_THIRD_PARTY_CONTEXT_PAGE = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "scriptExecPage.html"; + +/** + * Executes provided callbacks in both first and third party contexts. + * + * @param {string} name - Name of the test. + * @param {Function} firstPartyCallback - The callback to be executed in the first-party context. + * @param {Function} thirdPartyCallback - The callback to be executed in the third-party context. + * @param {Function} [cleanupFunction] - A cleanup function to be called after the tests. + * @param {Array} [extraPrefs] - Optional. An array of preferences to be set before running the test. + */ +function runTestInFirstAndThirdPartyContexts( + name, + firstPartyCallback, + thirdPartyCallback, + cleanupFunction, + extraPrefs +) { + add_task(async _ => { + info("Starting test `" + name + "' in first and third party contexts"); + + await SpecialPowers.flushPrefEnv(); + + if (extraPrefs && Array.isArray(extraPrefs) && extraPrefs.length) { + await SpecialPowers.pushPrefEnv({ set: extraPrefs }); + } + + info("Creating a new tab"); + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + TEST_FIRST_PARTY_CONTEXT_PAGE + ); + + info("Creating a 3rd party content and a 1st party popup"); + let firstPartyPopupPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + TEST_THIRD_PARTY_CONTEXT_PAGE, + true + ); + + let thirdPartyBC = await SpecialPowers.spawn( + tab.linkedBrowser, + [TEST_THIRD_PARTY_CONTEXT_PAGE], + async url => { + let ifr = content.document.createElement("iframe"); + + await new content.Promise(resolve => { + ifr.onload = resolve; + + content.document.body.appendChild(ifr); + ifr.src = url; + }); + + content.open(url); + + return ifr.browsingContext; + } + ); + let firstPartyTab = await firstPartyPopupPromise; + let firstPartyBrowser = firstPartyTab.linkedBrowser; + + info("Sending code to the 3rd party content and the 1st party popup"); + let runningCallbackTask = async obj => { + return new content.Promise(resolve => { + content.postMessage({ callback: obj.callback }, "*"); + + content.addEventListener("message", function msg(event) { + // This is the event from above postMessage. + if (event.data.callback) { + return; + } + + if (event.data.type == "finish") { + content.removeEventListener("message", msg); + resolve(); + return; + } + + if (event.data.type == "ok") { + ok(event.data.what, event.data.msg); + return; + } + + if (event.data.type == "info") { + info(event.data.msg); + return; + } + + ok(false, "Unknown message"); + }); + }); + }; + + let firstPartyTask = SpecialPowers.spawn( + firstPartyBrowser, + [ + { + callback: firstPartyCallback.toString(), + }, + ], + runningCallbackTask + ); + + let thirdPartyTask = SpecialPowers.spawn( + thirdPartyBC, + [ + { + callback: thirdPartyCallback.toString(), + }, + ], + runningCallbackTask + ); + + await Promise.all([firstPartyTask, thirdPartyTask]); + + info("Removing the tab"); + BrowserTestUtils.removeTab(tab); + BrowserTestUtils.removeTab(firstPartyTab); + }); + + add_task(async _ => { + info("Cleaning up."); + if (cleanupFunction) { + await cleanupFunction(); + } + }); +} |