Bug 1888504 - Add a dry-run mode for Bounce Tracking Protection. r=bvandersloot,anti-tracking-reviewers

Adds a mode where if bounce tracking protection is enabled it classifies
but does not purge trackers. This mode is helpful for testing the feature
without risking data loss. Telemetry is still collected normally.

Differential Revision: https://phabricator.services.mozilla.com/D206518
This commit is contained in:
Paul Zuehlcke 2024-04-17 20:29:07 +00:00
Родитель 5583c689e9
Коммит 94e36ac7ae
5 изменённых файлов: 132 добавлений и 7 удалений

Просмотреть файл

@ -14215,7 +14215,15 @@
value: true
mirror: always
# To be used in test environments to enable observer messages.
# Enables a mode where if bounce tracking protection is enabled it classifies
# but does not purge trackers. This mode is helpful for testing the feature
# without risking data loss. Telemetry is still collected normally.
- name: privacy.bounceTrackingProtection.enableDryRunMode
type: bool
value: false
mirror: always
# To be used in automated test environments to enable observer messages.
- name: privacy.bounceTrackingProtection.enableTestMode
type: bool
value: false

Просмотреть файл

@ -587,11 +587,17 @@ nsresult BounceTrackingProtection::PurgeBounceTrackersForStateGlobal(
("%s: Purge state for host: %s", __FUNCTION__,
PromiseFlatCString(host).get()));
// TODO: Bug 1842067: Clear by site + OA.
rv = clearDataService->DeleteDataFromBaseDomain(host, false,
TRACKER_PURGE_FLAGS, cb);
if (NS_WARN_IF(NS_FAILED(rv))) {
clearPromise->Reject(0, __func__);
if (StaticPrefs::privacy_bounceTrackingProtection_enableDryRunMode()) {
// In dry-run mode, we don't actually clear the data, but we still want to
// resolve the promise to indicate that the data would have been cleared.
clearPromise->Resolve(host, __func__);
} else {
// TODO: Bug 1842067: Clear by site + OA.
rv = clearDataService->DeleteDataFromBaseDomain(host, false,
TRACKER_PURGE_FLAGS, cb);
if (NS_WARN_IF(NS_FAILED(rv))) {
clearPromise->Reject(0, __func__);
}
}
aClearPromises.AppendElement(clearPromise);

Просмотреть файл

@ -12,6 +12,8 @@ support-files = [
"file_web_worker.js",
]
["browser_bouncetracking_dry_run.js"]
["browser_bouncetracking_oa_isolation.js"]
["browser_bouncetracking_purge.js"]

Просмотреть файл

@ -0,0 +1,102 @@
/* Any copyright is dedicated to the Public Domain.
https://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { SiteDataTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/SiteDataTestUtils.sys.mjs"
);
const TEST_ORIGIN = "https://itisatracker.org";
const TEST_BASE_DOMAIN = "itisatracker.org";
async function runPurgeTest(expectPurge) {
ok(!SiteDataTestUtils.hasCookies(TEST_ORIGIN), "No cookies initially.");
// Adding a cookie that should later be purged.
info("Add a test cookie to be purged later.");
SiteDataTestUtils.addToCookies({ origin: TEST_ORIGIN });
ok(SiteDataTestUtils.hasCookies(TEST_ORIGIN), "Cookie added.");
// The bounce adds localStorage. Test that there is none initially.
ok(
!SiteDataTestUtils.hasLocalStorage(TEST_ORIGIN),
"No localStorage initially."
);
info("Test client bounce with cookie.");
await runTestBounce({
bounceType: "client",
setState: "localStorage",
postBounceCallback: () => {
info(
"Test that after the bounce but before purging cookies and localStorage are present."
);
ok(SiteDataTestUtils.hasCookies(TEST_ORIGIN), "Cookies not purged.");
ok(
SiteDataTestUtils.hasLocalStorage(TEST_ORIGIN),
"localStorage not purged."
);
Assert.deepEqual(
bounceTrackingProtection.testGetBounceTrackerCandidateHosts({}),
[TEST_BASE_DOMAIN],
`Bounce tracker candidate '${TEST_BASE_DOMAIN}' added`
);
},
});
if (expectPurge) {
info("After purging the site shouldn't have any data.");
ok(!SiteDataTestUtils.hasCookies(TEST_ORIGIN), "Cookies purged.");
ok(!SiteDataTestUtils.hasLocalStorage(TEST_ORIGIN), "localStorage purged.");
} else {
info("Purging did not run meaning the site should still have data.");
ok(SiteDataTestUtils.hasCookies(TEST_ORIGIN), "Cookies still set.");
ok(
SiteDataTestUtils.hasLocalStorage(TEST_ORIGIN),
"localStorage still set."
);
}
info(
"Candidates should have been removed after running the purging algorithm. This is true for both regular and dry-run mode where we pretend to purge."
);
Assert.deepEqual(
bounceTrackingProtection.testGetBounceTrackerCandidateHosts({}),
[],
"No bounce tracker candidates after purging."
);
// Cleanup.
bounceTrackingProtection.clearAll();
await SiteDataTestUtils.clear();
}
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.bounceTrackingProtection.requireStatefulBounces", true],
["privacy.bounceTrackingProtection.bounceTrackingGracePeriodSec", 0],
// Required to use SiteDataTestUtils localStorage helpers.
["dom.storage.client_validation", false],
],
});
});
add_task(async function test_purge_in_regular_mode() {
await SpecialPowers.pushPrefEnv({
set: [["privacy.bounceTrackingProtection.enableDryRunMode", false]],
});
await runPurgeTest(true);
});
add_task(async function test_purge_in_dry_run_mode() {
await SpecialPowers.pushPrefEnv({
set: [["privacy.bounceTrackingProtection.enableDryRunMode", true]],
});
await runPurgeTest(false);
});

Просмотреть файл

@ -114,7 +114,11 @@ export var SiteDataTestUtils = {
},
/**
* Adds a new localStorage entry for the specified origin, with the specified contents.
* Adds a new localStorage entry for the specified origin, with the specified
* contents.
*
* This method requires the pref dom.storage.client_validation=false in order
* to access LS without a window.
*
* @param {String} origin - the origin of the site to add test data for
* @param {String} [key] - the localStorage key
@ -139,6 +143,9 @@ export var SiteDataTestUtils = {
* @param {{key: String, value: String}[]} [testEntries] - An array of entries
* to test for.
*
* This method requires the pref dom.storage.client_validation=false in order
* to access LS without a window.
*
* @returns {Boolean} whether the origin has localStorage data
*/
hasLocalStorage(origin, testEntries) {