Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

"use strict";
const TEST_PAGE = TEST_DOMAIN + TEST_PATH + "page.html";
const TEST_REDIRECT_PAGE = TEST_DOMAIN + TEST_PATH + "redirect.sjs";
const TEST_TRACKING_PAGE = TEST_3RD_PARTY_DOMAIN + TEST_PATH + "page.html";
const TEST_TRACKING_REDIRECT_PAGE =
TEST_3RD_PARTY_DOMAIN + TEST_PATH + "redirect.sjs";
const TEST_ANOTHER_TRACKING_REDIRECT_PAGE =
TEST_ANOTHER_3RD_PARTY_DOMAIN_HTTPS + TEST_PATH + "redirect.sjs";
const TEST_CASES = [
// Tracker(Interacted) -> Non-Tracker
{
trackersHasUserInteraction: [TEST_3RD_PARTY_DOMAIN],
redirects: [TEST_TRACKING_REDIRECT_PAGE, TEST_PAGE],
expectedPermissionNumber: 1,
expects: [
[
TEST_DOMAIN,
TEST_3RD_PARTY_DOMAIN,
Ci.nsIPermissionManager.ALLOW_ACTION,
],
],
},
// Tracker(No interaction) -> Non-Tracker
{
trackersHasUserInteraction: [],
redirects: [TEST_TRACKING_REDIRECT_PAGE, TEST_PAGE],
expectedPermissionNumber: 0,
expects: [
[
TEST_DOMAIN,
TEST_3RD_PARTY_DOMAIN,
Ci.nsIPermissionManager.UNKNOWN_ACTION,
],
],
},
// Non-Tracker -> Tracker(Interacted) -> Non-Tracker
{
trackersHasUserInteraction: [TEST_3RD_PARTY_DOMAIN],
redirects: [TEST_REDIRECT_PAGE, TEST_TRACKING_REDIRECT_PAGE, TEST_PAGE],
expectedPermissionNumber: 1,
expects: [
[
TEST_DOMAIN,
TEST_3RD_PARTY_DOMAIN,
Ci.nsIPermissionManager.ALLOW_ACTION,
],
],
},
// Tracker(Interacted) -> Tracker(Interacted) -> Tracker(Interacted)
{
trackersHasUserInteraction: [TEST_3RD_PARTY_DOMAIN],
redirects: [
TEST_TRACKING_REDIRECT_PAGE,
TEST_TRACKING_REDIRECT_PAGE,
TEST_TRACKING_PAGE,
],
expectedPermissionNumber: 0,
expects: [
[
TEST_3RD_PARTY_DOMAIN,
TEST_3RD_PARTY_DOMAIN,
Ci.nsIPermissionManager.UNKNOWN_ACTION,
],
],
},
// Tracker1(Interacted) -> Tracker2(Interacted) -> Non-Tracker
{
trackersHasUserInteraction: [
TEST_3RD_PARTY_DOMAIN,
TEST_ANOTHER_3RD_PARTY_DOMAIN_HTTPS,
],
redirects: [
TEST_TRACKING_REDIRECT_PAGE,
TEST_ANOTHER_TRACKING_REDIRECT_PAGE,
TEST_PAGE,
],
expectedPermissionNumber: 1,
expects: [
[
TEST_DOMAIN,
TEST_ANOTHER_3RD_PARTY_DOMAIN_HTTPS,
Ci.nsIPermissionManager.ALLOW_ACTION,
],
],
},
// Tracker1(Interacted) -> Non-Tracker -> Tracker2(No interaction) -> Non-Tracker
{
trackersHasUserInteraction: [TEST_3RD_PARTY_DOMAIN],
redirects: [
TEST_TRACKING_REDIRECT_PAGE,
TEST_REDIRECT_PAGE,
TEST_ANOTHER_TRACKING_REDIRECT_PAGE,
TEST_PAGE,
],
expectedPermissionNumber: 1,
expects: [
[
TEST_DOMAIN,
TEST_3RD_PARTY_DOMAIN,
Ci.nsIPermissionManager.ALLOW_ACTION,
],
],
},
// Tracker1(Interacted) -> Non-Tracker -> Tracker2(Interacted) -> Non-Tracker
// Note that the result is not quite correct in this case. We are supposed to
// grant access to the least tracker instead of the first one. But, this is
// the behavior how we act so far. We would fix this in another bug.
{
trackersHasUserInteraction: [
TEST_3RD_PARTY_DOMAIN,
TEST_ANOTHER_3RD_PARTY_DOMAIN_HTTPS,
],
redirects: [
TEST_TRACKING_REDIRECT_PAGE,
TEST_REDIRECT_PAGE,
TEST_ANOTHER_TRACKING_REDIRECT_PAGE,
TEST_PAGE,
],
expectedPermissionNumber: 1,
expects: [
[
TEST_DOMAIN,
TEST_3RD_PARTY_DOMAIN,
Ci.nsIPermissionManager.ALLOW_ACTION,
],
],
},
// Tracker(Interacted) -> Non-Tracker (heuristic disabled)
{
trackersHasUserInteraction: [TEST_3RD_PARTY_DOMAIN],
redirects: [TEST_TRACKING_REDIRECT_PAGE, TEST_PAGE],
expectedPermissionNumber: 0,
expects: [
[
TEST_DOMAIN,
TEST_3RD_PARTY_DOMAIN,
Ci.nsIPermissionManager.UNKNOWN_ACTION,
],
],
extraPrefs: [["privacy.antitracking.enableWebcompat", false]],
},
];
async function interactWithSpecificTracker(aTracker) {
let win = await BrowserTestUtils.openNewBrowserWindow();
await BrowserTestUtils.withNewTab(
{ gBrowser: win.gBrowser, url: aTracker },
async function (browser) {
info("Let's interact with the tracker");
await SpecialPowers.spawn(browser, [], async function () {
SpecialPowers.wrap(content.document).userInteractionForTesting();
});
}
);
await BrowserTestUtils.closeWindow(win);
}
function getNumberOfStorageAccessPermissions() {
let num = 0;
for (let perm of Services.perms.all) {
if (perm.type.startsWith("3rdPartyStorage^")) {
num++;
}
}
return num;
}
async function verifyStorageAccessPermission(aExpects) {
for (let expect of aExpects) {
let uri = Services.io.newURI(expect[0]);
let principal = Services.scriptSecurityManager.createContentPrincipal(
uri,
{}
);
let access = Services.perms.testPermissionFromPrincipal(
principal,
`3rdPartyStorage^${expect[1].slice(0, -1)}`
);
is(access, expect[2], "The storage access is set correctly");
}
}
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [
["network.cookie.cookieBehavior", BEHAVIOR_REJECT_TRACKER],
["privacy.trackingprotection.annotate_channels", true],
[
"privacy.restrict3rdpartystorage.userInteractionRequiredForHosts",
"tracking.example.com,tracking.example.org",
],
["privacy.restrict3rdpartystorage.heuristic.redirect", true],
],
});
await UrlClassifierTestUtils.addTestTrackers();
registerCleanupFunction(_ => {
Services.perms.removeAll();
});
});
add_task(async function testETPRedirectHeuristic() {
info("Starting testing ETP redirect heuristic ...");
for (const test of TEST_CASES) {
let { extraPrefs } = test;
if (extraPrefs) {
await SpecialPowers.pushPrefEnv({
set: extraPrefs,
});
}
// First, clear all permissions.
Services.perms.removeAll();
for (const tracker of test.trackersHasUserInteraction) {
info(`Interact with ${tracker} in top-level.`);
await interactWithSpecificTracker(tracker);
}
info("Creating a new tab");
let tab = BrowserTestUtils.addTab(gBrowser, TEST_PAGE);
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
info("Loading the tracking page and trigger the top-level redirect.");
SpecialPowers.spawn(browser, [test.redirects], async redirects => {
let link = content.document.createElement("a");
link.appendChild(content.document.createTextNode("click me!"));
link.href = redirects.shift() + "?" + redirects.join("|");
content.document.body.appendChild(link);
link.click();
});
let finalRedirectDest = test.redirects[test.redirects.length - 1];
await BrowserTestUtils.browserLoaded(browser, false, finalRedirectDest);
is(
getNumberOfStorageAccessPermissions(),
test.expectedPermissionNumber,
"The number of storage permissions is correct."
);
await verifyStorageAccessPermission(test.expects);
info("Removing the tab");
BrowserTestUtils.removeTab(tab);
if (extraPrefs) {
await SpecialPowers.popPrefEnv();
}
}
});