tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 6fa68a53285b7f553114cda4030f51ffab3d1efb
parent 23626800f0305e47f1d3d67df93007d2653ea443
Author: Tim Huang <tihuang@mozilla.com>
Date:   Mon, 24 Nov 2025 16:59:14 +0000

Bug 2000486 - Reset the IsThirdPartyContextToTopWindow flag for the redirect channel. r=bvandersloot,necko-reviewers,cookie-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D273835

Diffstat:
Mnetwerk/cookie/test/browser/browser.toml | 9+++++++++
Anetwerk/cookie/test/browser/browser_redirect_ABA_chips.js | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anetwerk/cookie/test/browser/redirect_301.sjs | 25+++++++++++++++++++++++++
Anetwerk/cookie/test/browser/set_cookie_cors.html | 2++
Anetwerk/cookie/test/browser/set_cookie_cors.html^headers^ | 3+++
Anetwerk/cookie/test/browser/sw_fetch.js | 15+++++++++++++++
Mnetwerk/protocol/http/HttpBaseChannel.cpp | 15+++++++++++++++
7 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/netwerk/cookie/test/browser/browser.toml b/netwerk/cookie/test/browser/browser.toml @@ -46,6 +46,15 @@ support-files = ["oversize.sjs"] ["browser_partitionedConsole.js"] support-files = ["partitioned.sjs"] +["browser_redirect_ABA_chips.js"] +support-files = [ + "redirect_301.sjs", + "serviceWorker.js", + "set_cookie_cors.html", + "set_cookie_cors.html^headers^", + "sw_fetch.js" +] + ["browser_sameSiteConsole.js"] support-files = ["sameSite.sjs"] diff --git a/netwerk/cookie/test/browser/browser_redirect_ABA_chips.js b/netwerk/cookie/test/browser/browser_redirect_ABA_chips.js @@ -0,0 +1,80 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const FIRST_PARTY_DOMAIN = "https://example.com/"; +const THIRD_PARTY_DOMAIN = "https://example.org/"; + +const FIRST_PARTY_PAGE = FIRST_PARTY_DOMAIN + TEST_PATH + "file_empty.html"; +const THIRD_PARTY_PAGE = THIRD_PARTY_DOMAIN + TEST_PATH + "file_empty.html"; +const FIRST_PARTY_PAGE_CORS = + FIRST_PARTY_DOMAIN + TEST_PATH + "set_cookie_cors.html"; + +add_setup(async () => { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "network.cookie.cookieBehavior", + Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN, + ], + ["network.cookie.CHIPS.enabled", true], + ], + }); + + registerCleanupFunction(async () => { + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () => + resolve() + ); + }); + }); +}); + +add_task(async () => { + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + FIRST_PARTY_PAGE + ); + + const browser = tab.linkedBrowser; + + // Load a third-party iframe. + let iframeBC = await SpecialPowers.spawn( + browser, + [THIRD_PARTY_PAGE], + async src => { + const iframe = content.document.createElement("iframe"); + + await new content.Promise(resolve => { + iframe.onload = resolve; + + iframe.src = src; + content.document.body.appendChild(iframe); + }); + + return iframe.browsingContext; + } + ); + + // Register a service worker in the third-party iframe. + await SpecialPowers.spawn(iframeBC, [FIRST_PARTY_PAGE_CORS], async src => { + let reg = await content.navigator.serviceWorker.register("sw_fetch.js"); + + await ContentTaskUtils.waitForCondition(() => { + return reg.active && reg.active.state === "activated"; + }, "The service worker is activated"); + + // Trigger a fetch which should be intercepted by the service worker. The + // fetch will be redirected to the first-party page to set a cookie. + await content.fetch("redirect_301.sjs?src=" + src); + + ok(true, "The fetch is completed without a crash."); + + // Clean up the service worker to avoid leaking control into later tests. + await reg.unregister(); + }); + + BrowserTestUtils.removeTab(tab); +}); diff --git a/netwerk/cookie/test/browser/redirect_301.sjs b/netwerk/cookie/test/browser/redirect_301.sjs @@ -0,0 +1,25 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * A page that performs 301 redirection to the given 'src'. + */ + +"use strict"; + +function handleRequest(request, response) { + let query = new URLSearchParams(request.queryString); + + // The 'src' must be included. + if (!query.has("src")) { + throw Error("No 'src' in the query string"); + } + + response.setStatusLine(request.httpVersion, 301, "Moved Permanently"); + response.setHeader("Location", query.get("src")); + response.setHeader("Cache-Control", "no-cache", false); + + // Optional body for 301 response + response.write("Redirecting..."); +} diff --git a/netwerk/cookie/test/browser/set_cookie_cors.html b/netwerk/cookie/test/browser/set_cookie_cors.html @@ -0,0 +1,2 @@ +<html><body> +</body></html> diff --git a/netwerk/cookie/test/browser/set_cookie_cors.html^headers^ b/netwerk/cookie/test/browser/set_cookie_cors.html^headers^ @@ -0,0 +1,3 @@ +Access-Control-Allow-Origin: https://example.org +Access-Control-Allow-Credentials: true +set-cookie: foo=bar; Secure; HttpOnly diff --git a/netwerk/cookie/test/browser/sw_fetch.js b/netwerk/cookie/test/browser/sw_fetch.js @@ -0,0 +1,15 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +self.oninstall = _ => { + self.skipWaiting(); +}; + +self.onactivate = event => { + event.waitUntil(self.clients.claim()); +}; + +self.onfetch = event => { + event.respondWith(fetch(event.request, { credentials: "include" })); +}; diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -4569,6 +4569,21 @@ already_AddRefed<nsILoadInfo> HttpBaseChannel::CloneLoadInfoForRedirect( } } + // Clone a new cookieJarSettings from the old one for the new channel. + // Otherwise, updating the new cookieJarSettings will affect the old one. + nsCOMPtr<nsICookieJarSettings> oldCookieJarSettings; + mLoadInfo->GetCookieJarSettings(getter_AddRefs(oldCookieJarSettings)); + + RefPtr<CookieJarSettings> newCookieJarSettings; + newCookieJarSettings = CookieJarSettings::Cast(oldCookieJarSettings)->Clone(); + + newLoadInfo->SetCookieJarSettings(newCookieJarSettings); + + // Clear the isThirdPartyContextToTopWindow flag for the new channel so that + // it will be computed again when the new channel is opened. + static_cast<net::LoadInfo*>(newLoadInfo.get()) + ->ClearIsThirdPartyContextToTopWindow(); + // Leave empty, we want a 'clean ground' when creating the new channel. // This will be ensured to be either set by the protocol handler or set // to the redirect target URI properly after the channel creation.