morgan pushed to branch tor-browser-153.0esr-16.0-1 at The Tor Project / Applications / Tor Browser Commits: 4983f698 by Henry Wilkes at 2026-08-06T15:48:25+00:00 fixup! TB 31286: Implementation of bridge, proxy, and firewall settings in about:preferences#connection TB 43939: Add a connection assist banner. - - - - - b825b06d by Henry Wilkes at 2026-08-06T15:48:25+00:00 fixup! Tor Browser strings TB 43939: Add connection assist banner string. - - - - - 09269559 by Henry Wilkes at 2026-08-06T15:48:25+00:00 fixup! TB 40597: Implement TorSettings module TB 43939: Add a method to determine whether the user is in a "Connection Assist" stage. - - - - - 6 changed files: - browser/components/preferences/preferences.xhtml - browser/components/torpreferences/config/connection.mjs - browser/components/torpreferences/jar.mn - + browser/components/torpreferences/widgets/tor-connection-assist-banner.mjs - toolkit/locales/en-US/toolkit/global/tor-browser.ftl - toolkit/modules/TorConnect.sys.mjs Changes: ===================================== browser/components/preferences/preferences.xhtml ===================================== @@ -109,6 +109,7 @@ <script type="module" src="chrome://browser/content/preferences/widgets/update-state.mjs"></script> <script type="module" src="chrome://browser/content/ipprotection/bandwidth-usage.mjs"></script> <script type="module" src="chrome://browser/content/torpreferences/widgets/tor-bridges-display.mjs"></script> + <script type="module" src="chrome://browser/content/torpreferences/widgets/tor-connection-assist-banner.mjs"></script> <script type="module" src="chrome://browser/content/torpreferences/widgets/tor-connection-status.mjs"></script> <script src="chrome://browser/content/torpreferences/bridgemoji/BridgeEmoji.js"/> </head> ===================================== browser/components/torpreferences/config/connection.mjs ===================================== @@ -4,6 +4,8 @@ import { Preferences } from "chrome://global/content/preferences/Preferences.mjs const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { InternetStatus: "moz-src:///toolkit/modules/TorConnect.sys.mjs", + moveFocusToBridgeHeading: + "chrome://browser/content/torpreferences/config/helpers.mjs", openBridgeDialog: "chrome://browser/content/torpreferences/config/helpers.mjs", openUserProvideBridgeDialog: @@ -68,6 +70,18 @@ SettingGroupManager.registerGroups({ headingLevel: 2, controlAttrs: { "focusable-heading": true }, items: [ + { + id: "connectionAssistBanner", + // NOTE: Instead of using a custom widget for this one banner, we could + // use moz-message-bar and populate it's children. However, we want to + // intercept the "click" event for the "Connection Assist" link within + // the banner text. As of ESR 153, onUserClick would not allow us to + // intercept the event because the `<a>` would need to be wrapped in a + // `<setting-control>`. But Fluent would not allow wrapping the + // `<setting-control>` element as part of a wider string (unlike + // `<a data-l10n-name="link">`, which is allowed). tor-browser#43939. + control: "tor-connection-assist-banner", + }, { id: "bridgesEnabled", l10nId: "tor-bridges-use-bridges", @@ -253,6 +267,27 @@ Preferences.addSetting({ }, }); +Preferences.addSetting({ + id: "connectionAssistBanner", + deps: ["torStatus"], + _wasVisible: false, + visible({ torStatus }) { + const visible = torStatus.value === "potentially-blocked"; + if ( + !visible && + this._wasVisible && + document + .getElementById("connectionAssistBanner") + ?.contains(document.activeElement) + ) { + // About to loose focus, move focus to the bridge heading. + lazy.moveFocusToBridgeHeading(window, true); + } + this._wasVisible = visible; + return visible; + }, +}); + Preferences.addSetting({ id: "torSettingsReady", _ready: false, ===================================== browser/components/torpreferences/jar.mn ===================================== @@ -27,6 +27,7 @@ browser.jar: content/browser/torpreferences/config/connection.mjs (config/connection.mjs) content/browser/torpreferences/config/helpers.mjs (config/helpers.mjs) content/browser/torpreferences/widgets/tor-bridges-display.mjs (widgets/tor-bridges-display.mjs) + content/browser/torpreferences/widgets/tor-connection-assist-banner.mjs (widgets/tor-connection-assist-banner.mjs) content/browser/torpreferences/widgets/tor-connection-status.mjs (widgets/tor-connection-status.mjs) content/browser/torpreferences/widgets/tor-connection-status.css (widgets/tor-connection-status.css) content/browser/torpreferences/connectionPane.js (content/connectionPane.js) ===================================== browser/components/torpreferences/widgets/tor-connection-assist-banner.mjs ===================================== @@ -0,0 +1,56 @@ +import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; +import { html } from "chrome://global/content/vendor/lit.all.mjs"; + +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + TorConnect: "moz-src:///toolkit/modules/TorConnect.sys.mjs", + TorConnectParent: + "moz-src:///browser/components/torconnect/TorConnectParent.sys.mjs", +}); + +const TOR_CONNECT_HREF = "about:torconnect"; + +/** + * Widget for displaying a Connection Assist banner. + * + * @tagname tor-connection-status + */ +class TorConnectionAssistBanner extends MozLitElement { + render() { + return html` + <moz-message-bar + role="complementary" + type="warning" + @click=${this.#handleClick} + > + <span + slot="message" + data-l10n-id="tor-bridges-connection-assist-message" + > + <a + id="link" + data-l10n-name="link" + href=${TOR_CONNECT_HREF} + target="_blank" + ></a> + </span> + </moz-message-bar> + `; + } + + #handleClick(event) { + if (!this.shadowRoot.getElementById("link")?.contains(event.target)) { + return; + } + event.preventDefault(); + if (!lazy.TorConnect.inConnectionAssistStage) { + // Switch to the "ChooseRegion" stage to reflect "Connection Assist". + lazy.TorConnect.chooseRegion(); + } + lazy.TorConnectParent.open(); + } +} +customElements.define( + "tor-connection-assist-banner", + TorConnectionAssistBanner +); ===================================== toolkit/locales/en-US/toolkit/global/tor-browser.ftl ===================================== @@ -156,6 +156,11 @@ tor-bridges-group = .label = Bridges .description = Bridges help you securely access the Tor network in places where Tor is blocked. Depending on where you are, one bridge may work better than another. +# "{ -brand-product-name }" will be replaced with the localized name of the browser, e.g. "Tor Browser". +# "Connection Assist" is the name of a Tor Browser feature, and is therefore capitalised in English. For translations, it should similarly be treated as a feature/product name. It should also be wrapped by the tags '<a data-l10n-name="link">' and '</a>'. +tor-bridges-connection-assist-message = { -brand-short-name } could not connect to the Tor network. You may want to change your bridge settings below, or use <a data-l10n-name="link">Connection Assist</a> to find bridges for you. + + # Toggle button for enabling and disabling the use of bridges. tor-bridges-use-bridges = .label = Use bridges ===================================== toolkit/modules/TorConnect.sys.mjs ===================================== @@ -305,6 +305,8 @@ class BootstrapAttempt { /** * Each instance can be used to attempt one auto-bootstrapping sequence. + * + * AKA Connection Assist bootstrap. */ class AutoBootstrapAttempt { /** @@ -811,6 +813,12 @@ export const TorConnect = { */ _bootstrapAttempt: null, + /** + * Whether the current or last bootstrap attempt was a "normal" bootstrap (not + * Connection Assist). + */ + _wasNormalBootstrap: false, + /** * The bootstrap error that was last generated. * @@ -1048,7 +1056,7 @@ export const TorConnect = { // No change. return; } - if (this._stageName === "Bootstrapping") { + if (this._stageName === TorConnectStage.Bootstrapping) { this._bootstrappingStatus.hasWarning = true; this._notifyBootstrapProgress(); } @@ -1197,6 +1205,19 @@ export const TorConnect = { ); }, + /** + * Whether we are in a stage that is considered part of "Connection Assist". + * + * @type {boolean} + */ + get inConnectionAssistStage() { + return ( + this.canBeginAutoBootstrap || + (this._stageName === TorConnectStage.Bootstrapping && + !this._wasNormalBootstrap) + ); + }, + /** * Get a map of all region codes and their localized names. * @@ -1377,9 +1398,10 @@ export const TorConnect = { const beginStage = this._stageName; const bootstrapOptions = { regionCode }; - const bootstrapAttempt = regionCode - ? new AutoBootstrapAttempt() - : new BootstrapAttempt(); + const normalBootstrap = !regionCode; + const bootstrapAttempt = normalBootstrap + ? new BootstrapAttempt() + : new AutoBootstrapAttempt(); this._addSimulateOptions(bootstrapOptions, regionCode); @@ -1398,6 +1420,7 @@ export const TorConnect = { this._requestedStage = null; this._bootstrapTrigger = beginStage; this._isQuickstart = isQuickstart; + this._wasNormalBootstrap = normalBootstrap; this._setStage(TorConnectStage.Bootstrapping); this._bootstrapAttempt = bootstrapAttempt; View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/e97309c... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/e97309c... You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help