diff options
Diffstat (limited to 'toolkit/components/cookiebanners/test/browser/browser_cookieinjector.js')
-rw-r--r-- | toolkit/components/cookiebanners/test/browser/browser_cookieinjector.js | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/toolkit/components/cookiebanners/test/browser/browser_cookieinjector.js b/toolkit/components/cookiebanners/test/browser/browser_cookieinjector.js new file mode 100644 index 0000000000..58fdab7114 --- /dev/null +++ b/toolkit/components/cookiebanners/test/browser/browser_cookieinjector.js @@ -0,0 +1,625 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { SiteDataTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/SiteDataTestUtils.sys.mjs" +); + +const DOMAIN_A = "example.com"; +const DOMAIN_B = "example.org"; +const DOMAIN_C = "example.net"; + +const ORIGIN_A = "https://" + DOMAIN_A; +const ORIGIN_A_SUB = `https://test1.${DOMAIN_A}`; +const ORIGIN_B = "https://" + DOMAIN_B; +const ORIGIN_C = "https://" + DOMAIN_C; + +const TEST_COOKIE_HEADER_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "testCookieHeader.sjs"; + +/** + * Tests that the test domains have no cookies set. + */ +function assertNoCookies() { + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_A), + "Should not set any cookies for ORIGIN_A" + ); + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_B), + "Should not set any cookies for ORIGIN_B" + ); + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_C), + "Should not set any cookies for ORIGIN_C" + ); +} + +/** + * Loads a list of urls consecutively from the same tab. + * @param {string[]} urls - List of urls to load. + */ +async function visitTestSites(urls = [ORIGIN_A, ORIGIN_B, ORIGIN_C]) { + let tab = BrowserTestUtils.addTab(gBrowser, "about:blank"); + + for (let url of urls) { + await BrowserTestUtils.loadURIString(tab.linkedBrowser, url); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + } + + BrowserTestUtils.removeTab(tab); +} + +add_setup(cookieInjectorTestSetup); + +/** + * Tests that no cookies are set if the cookie injection component is disabled + * by pref, but the cookie banner service is enabled. + */ +add_task(async function test_cookie_injector_disabled() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["cookiebanners.service.mode", Ci.nsICookieBannerService.MODE_REJECT], + ["cookiebanners.cookieInjector.enabled", false], + ], + }); + + insertTestCookieRules(); + + await visitTestSites(); + assertNoCookies(); + + await SiteDataTestUtils.clear(); +}); + +/** + * Tests that no cookies are set if the cookie injection component is enabled + * by pref, but the cookie banner service is disabled or in detect-only mode. + */ +add_task(async function test_cookie_banner_service_disabled() { + // Enable in PBM so the service is always initialized. + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "cookiebanners.service.mode.privateBrowsing", + Ci.nsICookieBannerService.MODE_REJECT, + ], + ], + }); + + for (let [serviceMode, detectOnly] of [ + [Ci.nsICookieBannerService.MODE_DISABLED, false], + [Ci.nsICookieBannerService.MODE_DISABLED, true], + [Ci.nsICookieBannerService.MODE_REJECT, true], + [Ci.nsICookieBannerService.MODE_REJECT_OR_ACCEPT, true], + ]) { + info(`Testing with serviceMode=${serviceMode}; detectOnly=${detectOnly}`); + await SpecialPowers.pushPrefEnv({ + set: [ + ["cookiebanners.service.mode", serviceMode], + ["cookiebanners.cookieInjector.enabled", true], + ["cookiebanners.service.detectOnly", detectOnly], + ], + }); + + await visitTestSites(); + assertNoCookies(); + + await SiteDataTestUtils.clear(); + await SpecialPowers.popPrefEnv(); + } +}); + +/** + * Tests that we don't inject cookies if there are no matching rules. + */ +add_task(async function test_no_rules() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["cookiebanners.service.mode", Ci.nsICookieBannerService.MODE_REJECT], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + + info("Clearing existing rules"); + Services.cookieBanners.resetRules(false); + + await visitTestSites(); + assertNoCookies(); + + await SiteDataTestUtils.clear(); +}); + +/** + * Tests that inject the correct cookies for matching rules and MODE_REJECT. + */ +add_task(async function test_mode_reject() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["cookiebanners.service.mode", Ci.nsICookieBannerService.MODE_REJECT], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + + insertTestCookieRules(); + + await visitTestSites(); + + ok( + SiteDataTestUtils.hasCookies(ORIGIN_A, [ + { + key: `cookieConsent_${DOMAIN_A}_1`, + value: "optOut1", + }, + { + key: `cookieConsent_${DOMAIN_A}_2`, + value: "optOut2", + }, + ]), + "Should set opt-out cookies for ORIGIN_A" + ); + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_B), + "Should not set any cookies for ORIGIN_B" + ); + // RULE_A also includes DOMAIN_C. + ok( + SiteDataTestUtils.hasCookies(ORIGIN_C, [ + { + key: `cookieConsent_${DOMAIN_A}_1`, + value: "optOut1", + }, + { + key: `cookieConsent_${DOMAIN_A}_2`, + value: "optOut2", + }, + ]), + "Should set opt-out cookies for ORIGIN_C" + ); + + await SiteDataTestUtils.clear(); +}); + +/** + * Tests that inject the correct cookies for matching rules and + * MODE_REJECT_OR_ACCEPT. + */ +add_task(async function test_mode_reject_or_accept() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "cookiebanners.service.mode", + Ci.nsICookieBannerService.MODE_REJECT_OR_ACCEPT, + ], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + + insertTestCookieRules(); + + await visitTestSites(); + + ok( + SiteDataTestUtils.hasCookies(ORIGIN_A, [ + { + key: `cookieConsent_${DOMAIN_A}_1`, + value: "optOut1", + }, + { + key: `cookieConsent_${DOMAIN_A}_2`, + value: "optOut2", + }, + ]), + "Should set opt-out cookies for ORIGIN_A" + ); + ok( + SiteDataTestUtils.hasCookies(ORIGIN_B, [ + { + key: `cookieConsent_${DOMAIN_B}_1`, + value: "optIn1", + }, + ]), + "Should set opt-in cookies for ORIGIN_B" + ); + // Rule a also includes DOMAIN_C + ok( + SiteDataTestUtils.hasCookies(ORIGIN_C, [ + { + key: `cookieConsent_${DOMAIN_A}_1`, + value: "optOut1", + }, + { + key: `cookieConsent_${DOMAIN_A}_2`, + value: "optOut2", + }, + ]), + "Should set opt-out cookies for ORIGIN_C" + ); + + await SiteDataTestUtils.clear(); +}); + +/** + * Test that embedded third-parties do not trigger cookie injection. + */ +add_task(async function test_embedded_third_party() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "cookiebanners.service.mode", + Ci.nsICookieBannerService.MODE_REJECT_OR_ACCEPT, + ], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + + insertTestCookieRules(); + + info("Loading example.com with an iframe for example.org."); + await BrowserTestUtils.withNewTab("https://example.com", async browser => { + await SpecialPowers.spawn(browser, [], async () => { + let iframe = content.document.createElement("iframe"); + iframe.src = "https://example.org"; + content.document.body.appendChild(iframe); + await ContentTaskUtils.waitForEvent(iframe, "load"); + }); + }); + + ok( + SiteDataTestUtils.hasCookies(ORIGIN_A, [ + { + key: `cookieConsent_${DOMAIN_A}_1`, + value: "optOut1", + }, + { + key: `cookieConsent_${DOMAIN_A}_2`, + value: "optOut2", + }, + ]), + "Should set opt-out cookies for top-level ORIGIN_A" + ); + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_B), + "Should not set any cookies for embedded ORIGIN_B" + ); + + await SiteDataTestUtils.clear(); +}); + +/** + * Test that the injected cookies are present in the cookie header for the + * initial top level document request. + */ +add_task(async function test_cookie_header_and_document() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["cookiebanners.service.mode", Ci.nsICookieBannerService.MODE_REJECT], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + insertTestCookieRules(); + + await BrowserTestUtils.withNewTab(TEST_COOKIE_HEADER_URL, async browser => { + await SpecialPowers.spawn(browser, [], async () => { + const EXPECTED_COOKIE_STR = + "cookieConsent_example.com_1=optOut1; cookieConsent_example.com_2=optOut2"; + is( + content.document.body.innerText, + EXPECTED_COOKIE_STR, + "Sent the correct cookie header." + ); + is( + content.document.cookie, + EXPECTED_COOKIE_STR, + "document.cookie has the correct cookie string." + ); + }); + }); + + await SiteDataTestUtils.clear(); +}); + +/** + * Test that cookies get properly injected for private browsing mode. + */ +add_task(async function test_pbm() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "cookiebanners.service.mode.privateBrowsing", + Ci.nsICookieBannerService.MODE_REJECT, + ], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + insertTestCookieRules(); + + let pbmWindow = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + let tab = BrowserTestUtils.addTab(pbmWindow.gBrowser, "about:blank"); + await BrowserTestUtils.loadURIString(tab.linkedBrowser, ORIGIN_A); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + + ok( + SiteDataTestUtils.hasCookies( + tab.linkedBrowser.contentPrincipal.origin, + [ + { + key: `cookieConsent_${DOMAIN_A}_1`, + value: "optOut1", + }, + { + key: `cookieConsent_${DOMAIN_A}_2`, + value: "optOut2", + }, + ], + true + ), + "Should set opt-out cookies for top-level ORIGIN_A in private browsing." + ); + + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_A), + "Should not set any cookies for ORIGIN_A without PBM origin attribute." + ); + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_B), + "Should not set any cookies for ORIGIN_B" + ); + + await BrowserTestUtils.closeWindow(pbmWindow); + await SiteDataTestUtils.clear(); +}); + +/** + * Test that cookies get properly injected for container tabs. + */ +add_task(async function test_container_tab() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "cookiebanners.service.mode", + Ci.nsICookieBannerService.MODE_REJECT_OR_ACCEPT, + ], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + insertTestCookieRules(); + + info("Loading ORIGIN_B in a container tab."); + let tab = BrowserTestUtils.addTab(gBrowser, ORIGIN_B, { + userContextId: 1, + }); + await BrowserTestUtils.loadURIString(tab.linkedBrowser, ORIGIN_B); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_A), + "Should not set any cookies for ORIGIN_A" + ); + ok( + SiteDataTestUtils.hasCookies(tab.linkedBrowser.contentPrincipal.origin, [ + { + key: `cookieConsent_${DOMAIN_B}_1`, + value: "optIn1", + }, + ]), + "Should set opt-out cookies for top-level ORIGIN_B in user context 1." + ); + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_B), + "Should not set any cookies for ORIGIN_B in default user context" + ); + + BrowserTestUtils.removeTab(tab); + await SiteDataTestUtils.clear(); +}); + +/** + * Test that if there is already a cookie with the given key, we don't overwrite + * it. If the rule sets the unsetValue field, this cookie may be overwritten if + * the value matches. + */ +add_task(async function test_no_overwrite() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "cookiebanners.service.mode", + Ci.nsICookieBannerService.MODE_REJECT_OR_ACCEPT, + ], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + + insertTestCookieRules(); + + info("Pre-setting a cookie that should not be overwritten."); + SiteDataTestUtils.addToCookies({ + origin: ORIGIN_A, + host: `.${DOMAIN_A}`, + path: "/", + name: `cookieConsent_${DOMAIN_A}_1`, + value: "KEEPME", + }); + + info("Pre-setting a cookie that should be overwritten, based on its value"); + SiteDataTestUtils.addToCookies({ + origin: ORIGIN_B, + host: `.${DOMAIN_B}`, + path: "/", + name: `cookieConsent_${DOMAIN_B}_1`, + value: "UNSET", + }); + + await visitTestSites(); + + ok( + SiteDataTestUtils.hasCookies(ORIGIN_A, [ + { + key: `cookieConsent_${DOMAIN_A}_1`, + value: "KEEPME", + }, + { + key: `cookieConsent_${DOMAIN_A}_2`, + value: "optOut2", + }, + ]), + "Should retain pre-set opt-in cookies for ORIGIN_A, but write new secondary cookie from rules." + ); + ok( + SiteDataTestUtils.hasCookies(ORIGIN_B, [ + { + key: `cookieConsent_${DOMAIN_B}_1`, + value: "optIn1", + }, + ]), + "Should have overwritten cookie for ORIGIN_B, based on its value and the unsetValue rule property." + ); + + await SiteDataTestUtils.clear(); +}); + +/** + * Tests that cookies are injected for the base domain when visiting a + * subdomain. + */ +add_task(async function test_subdomain() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["cookiebanners.service.mode", Ci.nsICookieBannerService.MODE_REJECT], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + + insertTestCookieRules(); + + await visitTestSites([ORIGIN_A_SUB, ORIGIN_B]); + + ok( + SiteDataTestUtils.hasCookies(ORIGIN_A, [ + { + key: `cookieConsent_${DOMAIN_A}_1`, + value: "optOut1", + }, + { + key: `cookieConsent_${DOMAIN_A}_2`, + value: "optOut2", + }, + ]), + "Should set opt-out cookies for ORIGIN_A when visiting subdomain." + ); + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_B), + "Should not set any cookies for ORIGIN_B" + ); + + await SiteDataTestUtils.clear(); +}); + +add_task(async function test_site_preference() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["cookiebanners.service.mode", Ci.nsICookieBannerService.MODE_REJECT], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + + insertTestCookieRules(); + + await visitTestSites(); + + ok( + !SiteDataTestUtils.hasCookies(ORIGIN_B), + "Should not set any cookies for ORIGIN_B" + ); + + info("Set the site preference of example.org to MODE_REJECT_OR_ACCEPT."); + let uri = Services.io.newURI(ORIGIN_B); + Services.cookieBanners.setDomainPref( + uri, + Ci.nsICookieBannerService.MODE_REJECT_OR_ACCEPT, + false + ); + + await visitTestSites(); + ok( + SiteDataTestUtils.hasCookies(ORIGIN_B, [ + { + key: `cookieConsent_${DOMAIN_B}_1`, + value: "optIn1", + }, + ]), + "Should set opt-in cookies for ORIGIN_B" + ); + + Services.cookieBanners.removeAllDomainPrefs(false); + await SiteDataTestUtils.clear(); +}); + +add_task(async function test_site_preference_pbm() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "cookiebanners.service.mode.privateBrowsing", + Ci.nsICookieBannerService.MODE_REJECT, + ], + ["cookiebanners.cookieInjector.enabled", true], + ], + }); + + insertTestCookieRules(); + + let pbmWindow = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + let tab = BrowserTestUtils.addTab(pbmWindow.gBrowser, "about:blank"); + await BrowserTestUtils.loadURIString(tab.linkedBrowser, ORIGIN_B); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + + ok( + !SiteDataTestUtils.hasCookies( + tab.linkedBrowser.contentPrincipal.origin, + null, + true + ), + "Should not set any cookies for ORIGIN_B in the private window" + ); + + info( + "Set the site preference of example.org to MODE_REJECT_OR_ACCEPT. in the private window." + ); + let uri = Services.io.newURI(ORIGIN_B); + Services.cookieBanners.setDomainPref( + uri, + Ci.nsICookieBannerService.MODE_REJECT_OR_ACCEPT, + true + ); + + await BrowserTestUtils.loadURIString(tab.linkedBrowser, ORIGIN_B); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + + ok( + SiteDataTestUtils.hasCookies( + tab.linkedBrowser.contentPrincipal.origin, + [ + { + key: `cookieConsent_${DOMAIN_B}_1`, + value: "optIn1", + }, + ], + true + ), + "Should set opt-in cookies for ORIGIN_B" + ); + + Services.cookieBanners.removeAllDomainPrefs(true); + BrowserTestUtils.removeTab(tab); + await BrowserTestUtils.closeWindow(pbmWindow); + await SiteDataTestUtils.clear(); +}); |