Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
// Bug 2060310: the sibling of the same-tab gap covered by
// browser_bouncetracking_iframe_initiated_load.js. Bug 1843308 / privacycg#50
// made a popup inherit its opener's site as the extended navigation's
// initialHost, so a tracker opened in a new tab can no longer exempt itself.
// When the popup is opened from a cross-site iframe though, the opener is the
// frame, so the tracker became its own initialHost again through a different
// door.
//
// The bounces here return the popup to SITE_A, so finalHost is SITE_A and the
// tracker can only be caught by resolving the opener frame to its top level
// document.
let bounceTrackingProtection = Cc[
"@mozilla.org/bounce-tracking-protection;1"
].getService(Ci.nsIBounceTrackingProtection);
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [
[
"privacy.bounceTrackingProtection.mode",
Ci.nsIBounceTrackingProtection.MODE_ENABLED,
],
["privacy.bounceTrackingProtection.bounceTrackingGracePeriodSec", 0],
],
});
});
function getStartURL(origin) {
return getBaseUrl(origin) + "file_start.html";
}
/**
* Opens a popup from the given context which bounces through the tracker and
* ends on SITE_A, then ends the popup's extended navigation.
*
* @param {MozBrowser|BrowsingContext} opener - Context which opens the popup.
* @returns {Promise} Resolves once the popup's extended navigation has ended.
*/
async function runPopupBounce(opener) {
let targetURL = new URL(getStartURL(ORIGIN_A));
let bounceURL = getBounceURL({
bounceType: "server",
bounceOrigin: ORIGIN_TRACKER,
targetURL,
});
// Resolves once the new tab has opened and finished loading targetURL.
let openPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
targetURL.href,
true
);
await navigateLinkClick(opener, bounceURL, { spawnWindow: "newTab" });
let popupTab = await openPromise;
let popupBrowser = popupTab.linkedBrowser;
// End the popup's extended navigation with a user activated navigation, and
// wait for it to commit before tearing the context down.
//
// Same-site with initialHost: ending elsewhere starts a second extended
// navigation holding that site, and closing the context finalizes it
// (Bug 1921464) possibly before finalHost is set.
let endURL = new URL(getStartURL(ORIGIN_A) + "?end");
let endLoaded = BrowserTestUtils.browserLoaded(
popupBrowser,
false,
endURL.href
);
let recordedBounces = waitForRecordBounces(popupBrowser, 0);
await navigateLinkClick(popupBrowser, endURL);
await endLoaded;
await recordedBounces;
await BrowserTestUtils.removeTab(popupTab);
}
// runPopupBounce has already awaited the finalization run, so this only reads a
// settled state.
function assertTrackerClassified() {
Assert.ok(
bounceTrackingProtection
.testGetBounceTrackerCandidateHosts({})
.some(entry => entry.siteHost == SITE_TRACKER),
`${SITE_TRACKER} should be classified as a bounce tracker.`
);
}
// A popup opened by a cross-site frame must attribute the frame's embedder, via the
// opener, so the tracker is not its own initialHost.
add_task(async function test_frame_opens_new_tab() {
bounceTrackingProtection.clearAll();
await BrowserTestUtils.withNewTab(getStartURL(ORIGIN_A), async browser => {
let frameBC = await insertIframeAndWaitForLoad(
browser,
getStartURL(ORIGIN_TRACKER)
);
await runPopupBounce(frameBC);
});
assertTrackerClassified();
let purgedHosts = await bounceTrackingProtection.testRunPurgeBounceTrackers();
Assert.ok(
purgedHosts.includes(SITE_TRACKER),
`Should purge ${SITE_TRACKER}. Got: ${JSON.stringify(purgedHosts)}`
);
let purgeLog = bounceTrackingProtection.testGetRecentlyPurgedTrackers({});
Assert.equal(
purgeLog.length,
1,
`Should have one tracker in purge log. Got: ${JSON.stringify(
purgeLog.map(e => ({
siteHost: e.siteHost,
initialHost: e.bounceTrackingRecord?.initialHost,
finalHost: e.bounceTrackingRecord?.finalHost,
bounceHosts: e.bounceTrackingRecord?.bounceHosts,
}))
)}`
);
Assert.equal(
purgeLog[0].bounceTrackingRecord.initialHost,
SITE_A,
"initialHost should be the opener frame's top level site, not the frame's."
);
});
// A popup window rather than a tab resolves through the same opener, so it adds no
// coverage here; browser_bouncetracking_popup.js covers that shape.
// Regression guard for Bug 1843308 / privacycg#50: a popup opened from the top
// level document still inherits that document's site as initialHost, so the
// tracker in the popup's chain is still classified and SITE_A is still exempt.
add_task(async function test_top_level_opens_new_tab_unchanged() {
bounceTrackingProtection.clearAll();
await BrowserTestUtils.withNewTab(getStartURL(ORIGIN_A), async browser => {
await runPopupBounce(browser);
});
assertTrackerClassified();
await bounceTrackingProtection.testRunPurgeBounceTrackers();
let purgeLog = bounceTrackingProtection.testGetRecentlyPurgedTrackers({});
Assert.equal(
purgeLog.length,
1,
`Should have one tracker in purge log. Got: ${JSON.stringify(
purgeLog.map(e => ({
siteHost: e.siteHost,
initialHost: e.bounceTrackingRecord?.initialHost,
finalHost: e.bounceTrackingRecord?.finalHost,
bounceHosts: e.bounceTrackingRecord?.bounceHosts,
}))
)}`
);
Assert.equal(
purgeLog[0].bounceTrackingRecord.initialHost,
SITE_A,
"initialHost for a top level opener is unchanged."
);
});