summaryrefslogtreecommitdiffstats
path: root/toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js')
-rw-r--r--toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js174
1 files changed, 136 insertions, 38 deletions
diff --git a/toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js b/toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js
index f5857b6919..71d9acedc6 100644
--- a/toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js
+++ b/toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js
@@ -3,6 +3,17 @@
"use strict";
+const { SiteDataTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/SiteDataTestUtils.sys.mjs"
+);
+
+XPCOMUtils.defineLazyServiceGetter(
+ this,
+ "bounceTrackingProtection",
+ "@mozilla.org/bounce-tracking-protection;1",
+ "nsIBounceTrackingProtection"
+);
+
const SITE_A = "example.com";
const ORIGIN_A = `https://${SITE_A}`;
@@ -25,13 +36,6 @@ const OBSERVER_MSG_RECORD_BOUNCES_FINISHED = "test-record-bounces-finished";
const ROOT_DIR = getRootDirectory(gTestPath);
-XPCOMUtils.defineLazyServiceGetter(
- this,
- "bounceTrackingProtection",
- "@mozilla.org/bounce-tracking-protection;1",
- "nsIBounceTrackingProtection"
-);
-
/**
* Get the base url for the current test directory using the given origin.
* @param {string} origin - Origin to use in URL.
@@ -48,8 +52,14 @@ function getBaseUrl(origin) {
* the bounce.
* @param {string} [options.bounceOrigin] - The origin of the bounce URL.
* @param {string} [options.targetURL] - URL to redirect to after the bounce.
- * @param {("cookie"|null)} [options.setState] - What type of state should be set during
- * the bounce. No state by default.
+ * @param {('cookie-server'|'cookie-client'|'localStorage')} [options.setState]
+ * Type of state to set during the redirect. Defaults to non stateful redirect.
+ * @param {boolean} [options.setStateSameSiteFrame=false] - Whether to set the
+ * state in a sub frame that is same site to the top window.
+ * @param {boolean} [options.setStateInWebWorker=false] - Whether to set the
+ * state in a web worker. This only supports setState == "indexedDB".
+ * @param {boolean} [options.setStateInWebWorker=false] - Whether to set the
+ * state in a nested web worker. Otherwise the same as setStateInWebWorker.
* @param {number} [options.statusCode] - HTTP status code to use for server
* side redirect. Only applies to bounceType == "server".
* @param {number} [options.redirectDelayMS] - How long to wait before
@@ -62,6 +72,9 @@ function getBounceURL({
bounceOrigin = ORIGIN_TRACKER,
targetURL = new URL(getBaseUrl(ORIGIN_B) + "file_start.html"),
setState = null,
+ setStateSameSiteFrame = false,
+ setStateInWebWorker = false,
+ setStateInNestedWebWorker = false,
statusCode = 302,
redirectDelayMS = 50,
}) {
@@ -79,6 +92,25 @@ function getBounceURL({
if (setState) {
searchParams.set("setState", setState);
}
+ if (setStateSameSiteFrame) {
+ searchParams.set("setStateSameSiteFrame", setStateSameSiteFrame);
+ }
+ if (setStateInWebWorker) {
+ if (setState != "indexedDB") {
+ throw new Error(
+ "setStateInWebWorker only supports setState == 'indexedDB'"
+ );
+ }
+ searchParams.set("setStateInWebWorker", setStateInWebWorker);
+ }
+ if (setStateInNestedWebWorker) {
+ if (setState != "indexedDB") {
+ throw new Error(
+ "setStateInNestedWebWorker only supports setState == 'indexedDB'"
+ );
+ }
+ searchParams.set("setStateInNestedWebWorker", setStateInNestedWebWorker);
+ }
if (bounceType == "server") {
searchParams.set("statusCode", statusCode);
@@ -94,23 +126,58 @@ function getBounceURL({
* click on it.
* @param {MozBrowser} browser - Browser to insert the link in.
* @param {URL} targetURL - Destination for navigation.
+ * @param {Object} options - Additional options.
+ * @param {string} [options.spawnWindow] - If set to "newTab" or "popup" the
+ * link will be opened in a new tab or popup window respectively. If unset the
+ * link is opened in the given browser.
* @returns {Promise} Resolves once the click is done. Does not wait for
* navigation or load.
*/
-async function navigateLinkClick(browser, targetURL) {
- await SpecialPowers.spawn(browser, [targetURL.href], targetURL => {
- let link = content.document.createElement("a");
-
- link.href = targetURL;
- link.textContent = targetURL;
- // The link needs display: block, otherwise synthesizeMouseAtCenter doesn't
- // hit it.
- link.style.display = "block";
-
- content.document.body.appendChild(link);
- });
+async function navigateLinkClick(
+ browser,
+ targetURL,
+ { spawnWindow = null } = {}
+) {
+ if (spawnWindow && !["newTab", "popup"].includes(spawnWindow)) {
+ throw new Error(`Invalid option '${spawnWindow}' for spawnWindow`);
+ }
- await BrowserTestUtils.synthesizeMouseAtCenter("a[href]", {}, browser);
+ await SpecialPowers.spawn(
+ browser,
+ [targetURL.href, spawnWindow],
+ async (targetURL, spawnWindow) => {
+ let link = content.document.createElement("a");
+ link.id = "link";
+ link.textContent = "Click Me";
+ link.style.display = "block";
+ link.style.fontSize = "40px";
+
+ // For opening a popup we attach an event listener to trigger via click.
+ if (spawnWindow) {
+ link.href = "#";
+ link.addEventListener("click", event => {
+ event.preventDefault();
+ if (spawnWindow == "newTab") {
+ // Open a new tab.
+ content.window.open(targetURL, "bounce");
+ } else {
+ // Open a popup window.
+ content.window.open(targetURL, "bounce", "height=200,width=200");
+ }
+ });
+ } else {
+ // For regular navigation add href and click.
+ link.href = targetURL;
+ }
+
+ content.document.body.appendChild(link);
+
+ // TODO: Bug 1892091: Use EventUtils.synthesizeMouse instead for a real click.
+ SpecialPowers.wrap(content.document).notifyUserGestureActivation();
+ content.document.userInteractionForTesting();
+ link.click();
+ }
+ );
}
/**
@@ -141,25 +208,38 @@ async function waitForRecordBounces(browser) {
* or server side redirect.
* @param {('cookie-server'|'cookie-client'|'localStorage')} [options.setState]
* Type of state to set during the redirect. Defaults to non stateful redirect.
- * @param {boolean} [options.expectCandidate=true] - Expect the redirecting site to be
- * identified as a bounce tracker (candidate).
- * @param {boolean} [options.expectPurge=true] - Expect the redirecting site to have
- * its storage purged.
+ * @param {boolean} [options.setStateSameSiteFrame=false] - Whether to set the
+ * state in a sub frame that is same site to the top window.
+ * @param {boolean} [options.setStateInWebWorker=false] - Whether to set the
+ * state in a web worker. This only supports setState == "indexedDB".
+ * @param {boolean} [options.setStateInWebWorker=false] - Whether to set the
+ * state in a nested web worker. Otherwise the same as setStateInWebWorker.
+ * @param {boolean} [options.expectCandidate=true] - Expect the redirecting site
+ * to be identified as a bounce tracker (candidate).
+ * @param {boolean} [options.expectPurge=true] - Expect the redirecting site to
+ * have its storage purged.
* @param {OriginAttributes} [options.originAttributes={}] - Origin attributes
* to use for the test. This determines whether the test is run in normal
- * browsing, a private window or a container tab. By default the test is run
- * in normal browsing.
- * @param {function} [options.postBounceCallback] - Optional function to run after the
- * bounce has completed.
+ * browsing, a private window or a container tab. By default the test is run in
+ * normal browsing.
+ * @param {function} [options.postBounceCallback] - Optional function to run
+ * after the bounce has completed.
+ * @param {boolean} [options.skipSiteDataCleanup=false] - Skip the cleanup of
+ * site data after the test. When this is enabled the caller is responsible for
+ * cleaning up site data.
*/
async function runTestBounce(options = {}) {
let {
bounceType,
setState = null,
+ setStateSameSiteFrame = false,
+ setStateInWebWorker = false,
+ setStateInNestedWebWorker = false,
expectCandidate = true,
expectPurge = true,
originAttributes = {},
postBounceCallback = () => {},
+ skipSiteDataCleanup = false,
} = options;
info(`runTestBounce ${JSON.stringify(options)}`);
@@ -191,28 +271,42 @@ async function runTestBounce(options = {}) {
win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
}
- let tab = win.gBrowser.addTab(getBaseUrl(ORIGIN_A) + "file_start.html", {
+ let initialURL = getBaseUrl(ORIGIN_A) + "file_start.html";
+ let tab = win.gBrowser.addTab(initialURL, {
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
userContextId,
});
win.gBrowser.selectedTab = tab;
let browser = tab.linkedBrowser;
- await BrowserTestUtils.browserLoaded(browser);
+ await BrowserTestUtils.browserLoaded(browser, true, initialURL);
let promiseRecordBounces = waitForRecordBounces(browser);
// The final destination after the bounce.
let targetURL = new URL(getBaseUrl(ORIGIN_B) + "file_start.html");
+ // Wait for the final site to be loaded which complete the BounceTrackingRecord.
+ let targetURLLoadedPromise = BrowserTestUtils.browserLoaded(
+ browser,
+ false,
+ targetURL
+ );
+
// Navigate through the bounce chain.
await navigateLinkClick(
browser,
- getBounceURL({ bounceType, targetURL, setState })
+ getBounceURL({
+ bounceType,
+ targetURL,
+ setState,
+ setStateSameSiteFrame,
+ setStateInWebWorker,
+ setStateInNestedWebWorker,
+ })
);
- // Wait for the final site to be loaded which complete the BounceTrackingRecord.
- await BrowserTestUtils.browserLoaded(browser, false, targetURL);
+ await targetURLLoadedPromise;
// Navigate again with user gesture which triggers
// BounceTrackingProtection::RecordStatefulBounces. We could rely on the
@@ -226,9 +320,9 @@ async function runTestBounce(options = {}) {
await promiseRecordBounces;
Assert.deepEqual(
- bounceTrackingProtection.testGetBounceTrackerCandidateHosts(
- originAttributes
- ),
+ bounceTrackingProtection
+ .testGetBounceTrackerCandidateHosts(originAttributes)
+ .map(entry => entry.siteHost),
expectCandidate ? [SITE_TRACKER] : [],
`Should ${
expectCandidate ? "" : "not "
@@ -237,6 +331,7 @@ async function runTestBounce(options = {}) {
Assert.deepEqual(
bounceTrackingProtection
.testGetUserActivationHosts(originAttributes)
+ .map(entry => entry.siteHost)
.sort(),
[SITE_A, SITE_B].sort(),
"Should only have user activation for sites where we clicked links."
@@ -272,4 +367,7 @@ async function runTestBounce(options = {}) {
);
}
bounceTrackingProtection.clearAll();
+ if (!skipSiteDataCleanup) {
+ await SiteDataTestUtils.clear();
+ }
}