Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

let { ForgetAboutSite } = ChromeUtils.importESModule(
);
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(
TEST_DOMAIN
) + "testPage.html";
const TEST_DOMAIN_ANOTHER_PAGE =
getRootDirectory(gTestPath).replace(
TEST_DOMAIN_ANOTHER
) + "testPage.html";
const TEST_DOMAIN_THIRD_PAGE =
getRootDirectory(gTestPath).replace(
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);
});