Bug 1947734 - Test, r=anti-tracking-reviewers,timhuang
Differential Revision: https://phabricator.services.mozilla.com/D237880
This commit is contained in:
@@ -16,6 +16,8 @@ support-files = [
|
||||
"file_web_worker.js",
|
||||
]
|
||||
|
||||
["browser_bouncetracking_clearingPurgeLogCrash.js"]
|
||||
|
||||
["browser_bouncetracking_cookie_behavior.js"]
|
||||
|
||||
["browser_bouncetracking_dry_run.js"]
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Verifies that clearing the purge log via nsIClearDataService does not lead to
|
||||
* a crash.
|
||||
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1947281#c2 for details.
|
||||
*/
|
||||
|
||||
async function bounceTwice() {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
await runTestBounce({
|
||||
bounceType: "client",
|
||||
setState: "cookie-client",
|
||||
// We don't want to clear the purge log here because we want to test that
|
||||
// clearing the purge log through nsIClearDataService does not lead to a
|
||||
// crash.
|
||||
skipBounceTrackingProtectionCleanup: true,
|
||||
// This also calls into BTP clearing.
|
||||
skipSiteDataCleanup: true,
|
||||
// Skip state checks on the second bounce. The second test run would
|
||||
// otherwise fail because it expects to start with clean BTP state.
|
||||
skipStateChecks: i == 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
add_setup(async function () {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["privacy.bounceTrackingProtection.requireStatefulBounces", true],
|
||||
["privacy.bounceTrackingProtection.bounceTrackingGracePeriodSec", 0],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_crash() {
|
||||
info("Bounce and purge twice so we get two entries in recent purges.");
|
||||
await bounceTwice();
|
||||
|
||||
info("Clear BTP state via nsIClearDataService which must not crash.");
|
||||
await new Promise(function (resolve) {
|
||||
Services.clearData.deleteDataInTimeRange(
|
||||
0,
|
||||
// In microseconds
|
||||
Date.now() * 1000,
|
||||
true,
|
||||
Ci.nsIClearDataService.CLEAR_BOUNCE_TRACKING_PROTECTION_STATE,
|
||||
failedFlags => {
|
||||
Assert.equal(failedFlags, 0, "Clearing should have succeeded");
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Cleanup
|
||||
await SiteDataTestUtils.clear();
|
||||
});
|
||||
@@ -281,6 +281,8 @@ async function waitForRecordBounces(browser) {
|
||||
* @param {boolean} [options.skipBounceTrackingProtectionCleanup=false] - Skip
|
||||
* the cleanup of BounceTrackingProtection state. When this is enabled the
|
||||
* caller is responsible for cleaning BTP state.
|
||||
* @param {boolean} [options.skipStateChecks=false] - Only run a bounce,
|
||||
* skipping BTP state checks.
|
||||
* @param {boolean} [options.closeTabAfterBounce=false] - Close the tab right
|
||||
* after the bounce completes before the extended navigation ends as the result
|
||||
* of a timeout or user interaction.
|
||||
@@ -299,6 +301,7 @@ async function runTestBounce(options = {}) {
|
||||
expectPurge = true,
|
||||
originAttributes = {},
|
||||
postBounceCallback = () => {},
|
||||
skipStateChecks = false,
|
||||
skipSiteDataCleanup = false,
|
||||
skipBounceTrackingProtectionCleanup = false,
|
||||
closeTabAfterBounce = false,
|
||||
@@ -322,34 +325,36 @@ async function runTestBounce(options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
if (btpIsDisabled) {
|
||||
Assert.ok(!expectCandidate, "Expect no classification in disabled mode.");
|
||||
Assert.ok(
|
||||
!expectRecordBounces,
|
||||
"Expect no record bounces in disabled mode."
|
||||
);
|
||||
Assert.ok(!expectPurge, "Expect no purge in disabled mode.");
|
||||
} else {
|
||||
Assert.ok(
|
||||
bounceTrackingProtection,
|
||||
"BTP singleton must be available in any of the 'enabled' modes."
|
||||
);
|
||||
}
|
||||
if (!skipStateChecks) {
|
||||
if (btpIsDisabled) {
|
||||
Assert.ok(!expectCandidate, "Expect no classification in disabled mode.");
|
||||
Assert.ok(
|
||||
!expectRecordBounces,
|
||||
"Expect no record bounces in disabled mode."
|
||||
);
|
||||
Assert.ok(!expectPurge, "Expect no purge in disabled mode.");
|
||||
} else {
|
||||
Assert.ok(
|
||||
bounceTrackingProtection,
|
||||
"BTP singleton must be available in any of the 'enabled' modes."
|
||||
);
|
||||
}
|
||||
|
||||
if (bounceTrackingProtection) {
|
||||
Assert.equal(
|
||||
bounceTrackingProtection.testGetBounceTrackerCandidateHosts(
|
||||
originAttributes
|
||||
).length,
|
||||
0,
|
||||
"No bounce tracker hosts initially."
|
||||
);
|
||||
Assert.equal(
|
||||
bounceTrackingProtection.testGetUserActivationHosts(originAttributes)
|
||||
.length,
|
||||
0,
|
||||
"No user activation hosts initially."
|
||||
);
|
||||
if (bounceTrackingProtection) {
|
||||
Assert.equal(
|
||||
bounceTrackingProtection.testGetBounceTrackerCandidateHosts(
|
||||
originAttributes
|
||||
).length,
|
||||
0,
|
||||
"No bounce tracker hosts initially."
|
||||
);
|
||||
Assert.equal(
|
||||
bounceTrackingProtection.testGetUserActivationHosts(originAttributes)
|
||||
.length,
|
||||
0,
|
||||
"No user activation hosts initially."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let win = window;
|
||||
@@ -448,55 +453,57 @@ async function runTestBounce(options = {}) {
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
}
|
||||
|
||||
if (btpIsDisabled) {
|
||||
// In MODE_DISABLED `bounceTrackingProtection` may still be defined if it
|
||||
// was previously accessed in an enabled state. In that case make sure
|
||||
// nothing is recorded.
|
||||
if (bounceTrackingProtection) {
|
||||
if (!skipStateChecks) {
|
||||
if (btpIsDisabled) {
|
||||
// In MODE_DISABLED `bounceTrackingProtection` may still be defined if it
|
||||
// was previously accessed in an enabled state. In that case make sure
|
||||
// nothing is recorded.
|
||||
if (bounceTrackingProtection) {
|
||||
Assert.deepEqual(
|
||||
bounceTrackingProtection
|
||||
.testGetBounceTrackerCandidateHosts(originAttributes)
|
||||
.map(entry => entry.siteHost),
|
||||
[],
|
||||
"Should not have identified any bounce trackers"
|
||||
);
|
||||
Assert.deepEqual(
|
||||
bounceTrackingProtection
|
||||
.testGetUserActivationHosts(originAttributes)
|
||||
.map(entry => entry.siteHost),
|
||||
[],
|
||||
"Should not have recorded any user activation"
|
||||
);
|
||||
} else {
|
||||
info("BTP singleton is unavailable because mode is MODE_DISABLED.");
|
||||
}
|
||||
} else {
|
||||
// Any of the "enabled" modes.
|
||||
Assert.deepEqual(
|
||||
bounceTrackingProtection
|
||||
.testGetBounceTrackerCandidateHosts(originAttributes)
|
||||
.map(entry => entry.siteHost),
|
||||
[],
|
||||
"Should not have identified any bounce trackers"
|
||||
expectCandidate ? [SITE_TRACKER] : [],
|
||||
`Should ${
|
||||
expectCandidate ? "" : "not "
|
||||
}have identified ${SITE_TRACKER} as a bounce tracker.`
|
||||
);
|
||||
|
||||
let expectedUserActivationHosts = [SITE_A];
|
||||
if (!closeTabAfterBounce) {
|
||||
// If we didn't close the tab early we should have user activation for the
|
||||
// destination site.
|
||||
expectedUserActivationHosts.push(SITE_B);
|
||||
}
|
||||
|
||||
Assert.deepEqual(
|
||||
bounceTrackingProtection
|
||||
.testGetUserActivationHosts(originAttributes)
|
||||
.map(entry => entry.siteHost),
|
||||
[],
|
||||
"Should not have recorded any user activation"
|
||||
.map(entry => entry.siteHost)
|
||||
.sort(),
|
||||
expectedUserActivationHosts.sort(),
|
||||
"Should only have user activation for sites where we clicked links."
|
||||
);
|
||||
} else {
|
||||
info("BTP singleton is unavailable because mode is MODE_DISABLED.");
|
||||
}
|
||||
} else {
|
||||
// Any of the "enabled" modes.
|
||||
Assert.deepEqual(
|
||||
bounceTrackingProtection
|
||||
.testGetBounceTrackerCandidateHosts(originAttributes)
|
||||
.map(entry => entry.siteHost),
|
||||
expectCandidate ? [SITE_TRACKER] : [],
|
||||
`Should ${
|
||||
expectCandidate ? "" : "not "
|
||||
}have identified ${SITE_TRACKER} as a bounce tracker.`
|
||||
);
|
||||
|
||||
let expectedUserActivationHosts = [SITE_A];
|
||||
if (!closeTabAfterBounce) {
|
||||
// If we didn't close the tab early we should have user activation for the
|
||||
// destination site.
|
||||
expectedUserActivationHosts.push(SITE_B);
|
||||
}
|
||||
|
||||
Assert.deepEqual(
|
||||
bounceTrackingProtection
|
||||
.testGetUserActivationHosts(originAttributes)
|
||||
.map(entry => entry.siteHost)
|
||||
.sort(),
|
||||
expectedUserActivationHosts.sort(),
|
||||
"Should only have user activation for sites where we clicked links."
|
||||
);
|
||||
}
|
||||
|
||||
// If the caller specified a function to run after the bounce, run it now.
|
||||
@@ -518,53 +525,61 @@ async function runTestBounce(options = {}) {
|
||||
"testRunPurgeBounceTrackers should reject when BTP is disabled."
|
||||
);
|
||||
} else {
|
||||
Assert.deepEqual(
|
||||
await bounceTrackingProtection.testRunPurgeBounceTrackers(),
|
||||
expectPurge ? [SITE_TRACKER] : [],
|
||||
`Should ${expectPurge ? "" : "not "}purge state for ${SITE_TRACKER}.`
|
||||
);
|
||||
let purgedHosts =
|
||||
await bounceTrackingProtection.testRunPurgeBounceTrackers();
|
||||
|
||||
info("Testing the purge log.");
|
||||
let purgeLog =
|
||||
bounceTrackingProtection.testGetRecentlyPurgedTrackers(
|
||||
originAttributes
|
||||
if (!skipStateChecks) {
|
||||
Assert.deepEqual(
|
||||
purgedHosts,
|
||||
expectPurge ? [SITE_TRACKER] : [],
|
||||
`Should ${expectPurge ? "" : "not "}purge state for ${SITE_TRACKER}.`
|
||||
);
|
||||
// Purges are only logged in (fully) enabled mode. Dry-run mode does not
|
||||
// log purges.
|
||||
if (expectPurge && mode == Ci.nsIBounceTrackingProtection.MODE_ENABLED) {
|
||||
Assert.equal(
|
||||
purgeLog.length,
|
||||
1,
|
||||
"Should have one tracker in purge log."
|
||||
);
|
||||
let { siteHost, timeStamp, purgeTime } = purgeLog[0];
|
||||
|
||||
Assert.equal(
|
||||
siteHost,
|
||||
SITE_TRACKER,
|
||||
`The purge log entry should be for site host '${SITE_TRACKER}'`
|
||||
);
|
||||
Assert.greater(
|
||||
timeStamp,
|
||||
0,
|
||||
"The purge log entry should have a valid timestamp for bounce time."
|
||||
);
|
||||
Assert.greater(
|
||||
purgeTime,
|
||||
0,
|
||||
"The purge log entry should have a valid timestamp for purge time."
|
||||
);
|
||||
Assert.greaterOrEqual(
|
||||
purgeTime,
|
||||
timeStamp,
|
||||
"The purge time should be greater or equal to bounce time."
|
||||
);
|
||||
} else {
|
||||
Assert.equal(
|
||||
purgeLog.length,
|
||||
0,
|
||||
"Should have no trackers in purge log."
|
||||
);
|
||||
info("Testing the purge log.");
|
||||
let purgeLog =
|
||||
bounceTrackingProtection.testGetRecentlyPurgedTrackers(
|
||||
originAttributes
|
||||
);
|
||||
// Purges are only logged in (fully) enabled mode. Dry-run mode does not
|
||||
// log purges.
|
||||
if (
|
||||
expectPurge &&
|
||||
mode == Ci.nsIBounceTrackingProtection.MODE_ENABLED
|
||||
) {
|
||||
Assert.equal(
|
||||
purgeLog.length,
|
||||
1,
|
||||
"Should have one tracker in purge log."
|
||||
);
|
||||
let { siteHost, timeStamp, purgeTime } = purgeLog[0];
|
||||
|
||||
Assert.equal(
|
||||
siteHost,
|
||||
SITE_TRACKER,
|
||||
`The purge log entry should be for site host '${SITE_TRACKER}'`
|
||||
);
|
||||
Assert.greater(
|
||||
timeStamp,
|
||||
0,
|
||||
"The purge log entry should have a valid timestamp for bounce time."
|
||||
);
|
||||
Assert.greater(
|
||||
purgeTime,
|
||||
0,
|
||||
"The purge log entry should have a valid timestamp for purge time."
|
||||
);
|
||||
Assert.greaterOrEqual(
|
||||
purgeTime,
|
||||
timeStamp,
|
||||
"The purge time should be greater or equal to bounce time."
|
||||
);
|
||||
} else {
|
||||
Assert.equal(
|
||||
purgeLog.length,
|
||||
0,
|
||||
"Should have no trackers in purge log."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user