diff options
Diffstat (limited to 'toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js')
-rw-r--r-- | toolkit/components/antitracking/bouncetrackingprotection/test/browser/head.js | 174 |
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(); + } } |