tor-browser

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

commit 66986d27c3494b653ceeab63fc46d4076774840f
parent 13a9f1cc1ae8b2261605979912eaa95c34d16e8b
Author: Pier Angelo Vendrame <pierov@torproject.org>
Date:   Tue, 17 Feb 2026 09:21:16 +0100

fixup! TB 3455: Add DomainIsolator, for isolating circuit by domain.

TB 44635: Gather conflux information on circuits.

Relay information collection now happens at the tor provider level.
So, adapt the code of TorDomainIsolator to take the data alrady
prepared.

Diffstat:
Mtoolkit/components/tor-launcher/TorDomainIsolator.sys.mjs | 64+++++++++++++++++++++++++++++++---------------------------------
1 file changed, 31 insertions(+), 33 deletions(-)

diff --git a/toolkit/components/tor-launcher/TorDomainIsolator.sys.mjs b/toolkit/components/tor-launcher/TorDomainIsolator.sys.mjs @@ -12,6 +12,7 @@ import { const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { + ObjectUtils: "resource://gre/modules/ObjectUtils.sys.mjs", TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs", }); @@ -59,10 +60,6 @@ const CLEAR_TIMEOUT = 600_000; * @typedef {number} BrowserId */ /** - * @typedef {NodeData[]} CircuitData The data about the nodes, ordered from - * guard (or bridge) to exit. - */ -/** * @typedef BrowserCircuits Circuits related to a certain combination of * isolators (first-party domain and user context ID, currently). * @property {IsolationKey} current The last isolation key for which circuit @@ -113,7 +110,14 @@ class TorDomainIsolatorImpl { /** * A map that associates an isolation context to its circuits. * - * @type {Map<IsolationKey, CircuitData>} + * The circuits are represented with a multidimensional array. + * The outer layer contains an array for each circuit of the isolation context + * (when conflux is in use, a certain isolation context might use more than a + * circuit). + * The inner layer contains the data about a certain circuit, ordered from + * guard/bridge to exit. + * + * @type {Map<IsolationKey, NodeData[][]>} */ #knownCircuits = new Map(); @@ -190,8 +194,11 @@ class TorDomainIsolatorImpl { } /** - * Get the last circuit used in a certain browser. - * The returned data is created when the circuit is first seen, therefore it + * Get the circuits being used for a certain browser. There may be multiple + * if conflux is being used. + * + * Note, this returns the last known circuits for the browser. In particular, + * the returned data is created when the circuit is first seen, therefore it * could be stale (i.e., the circuit might not be available anymore). * * @param {MozBrowser} browser The browser to get data for @@ -199,10 +206,12 @@ class TorDomainIsolatorImpl { * for * @param {number} userContextId The user context domain we want to get the * circuit for - * @returns {NodeData[]} The node data, or an empty array if we do not have - * data for the requested key. + * @returns {NodeData[][]} An array of all the circuits being used for this + * context. Each circuit is represented by an array of nodes, ordered from + * the guard/bridge to the exit. If the context has no known circuits, then + * this will be an empty array. */ - getCircuit(browser, domain, userContextId) { + getCircuits(browser, domain, userContextId) { const username = this.#makeUsername(domain, userContextId); const circuits = this.#browsers.get(browser.browserId)?.get(username); // This is the only place where circuit data can go out, so the only place @@ -277,8 +286,8 @@ class TorDomainIsolatorImpl { // TODO: What UX to use here? See tor-browser#41708 } } else if (topic === lazy.TorProviderTopics.CircuitCredentialsMatched) { - const { username, password, circuit } = subject.wrappedJSObject; - this.#updateCircuit(username, password, circuit); + const { username, password, circuits } = subject.wrappedJSObject; + this.#updateCircuits(username, password, circuits); } } @@ -579,36 +588,25 @@ class TorDomainIsolatorImpl { } /** - * Update a circuit, and notify the related circuit displays if it changed. + * Update the circuits associated to a certain isolation context, and notify + * the related circuit displays if they changed. * * This function is called when a certain stream has succeeded and so we can - * associate its SOCKS credential to the circuit it is using. - * We receive only the fingerprints of the circuit nodes, but they are enough - * to check if the circuit has changed. If it has, we also get the nodes' - * information through the control port. + * associate its SOCKS credentials to the circuit it is using. * * @param {string} username The SOCKS username * @param {string} password The SOCKS password - * @param {NodeFingerprint[]} circuit The fingerprints of the nodes that - * compose the circuit + * @param {NodeData[][]} circuits The circuits being used for this isolation + * context. Each is represented by an array of nodes. */ - async #updateCircuit(username, password, circuit) { + async #updateCircuits(username, password, circuits) { const key = this.#credentialsToKey(username, password); - let data = this.#knownCircuits.get(key) ?? []; - // Should we modify the lower layer to send a circuit identifier, instead? - if ( - circuit.length === data.length && - circuit.every((fp, index) => fp === data[index].fingerprint) - ) { + let current = this.#knownCircuits.get(key); + if (lazy.ObjectUtils.deepEqual(current, circuits)) { return; } - - const provider = await lazy.TorProviderBuilder.build(); - data = await Promise.all( - circuit.map(fingerprint => provider.getNodeInfo(fingerprint)) - ); - logger.debug(`Updating circuit ${id}`, data); - this.#knownCircuits.set(id, data); + logger.info(`Updating circuits for ${key}`, circuits); + this.#knownCircuits.set(key, circuits); // We know that something changed, but we cannot know if anyone is // interested in this change. So, we have to notify all the possible // consumers of the data in any case.