261 lines
7.2 KiB
JavaScript
261 lines
7.2 KiB
JavaScript
"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();
|
|
}
|
|
}
|
|
});
|