morgan pushed to branch tor-browser-153.0a1-16.0-2 at The Tor Project / Applications / Tor Browser Commits: 36f1d1c6 by Henry Wilkes at 2026-07-14T15:24:00+00:00 fixup! TB 31286: Implementation of bridge, proxy, and firewall settings in about:preferences#connection TB 45029: Add the connection status pane to the connection settings config. - - - - - 8beb26de by Henry Wilkes at 2026-07-14T15:24:00+00:00 fixup! Tor Browser strings TB 45029: Add connection status strings. - - - - - 31a4963d by Henry Wilkes at 2026-07-14T15:24:00+00:00 fixup! Tor Browser localization migration scripts. TB 45029: Migrate connection status strings. - - - - - 10 changed files: - browser/components/preferences/preferences.js - browser/components/preferences/preferences.xhtml - + browser/components/torpreferences/config/connection.mjs - − browser/components/torpreferences/content/connectionCategory.inc.xhtml - browser/components/torpreferences/content/connectionPane.inc.xhtml - browser/components/torpreferences/jar.mn - + browser/components/torpreferences/widgets/tor-connection-status.css - + browser/components/torpreferences/widgets/tor-connection-status.mjs - toolkit/locales/en-US/toolkit/global/tor-browser.ftl - + tools/torbrowser/l10n/migrations/bug-45029-connection-status.py Changes: ===================================== browser/components/preferences/preferences.js ===================================== @@ -116,6 +116,7 @@ ChromeUtils.defineESModuleGetters(this, { "resource:///modules/SelectionChangedMenulist.sys.mjs", ShortcutUtils: "resource://gre/modules/ShortcutUtils.sys.mjs", SiteDataManager: "resource:///modules/SiteDataManager.sys.mjs", + TorConnect: "resource://gre/modules/TorConnect.sys.mjs", TransientPrefs: "resource:///modules/TransientPrefs.sys.mjs", UIState: "resource://services-sync/UIState.sys.mjs", UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs", @@ -267,6 +268,16 @@ const CONFIG_PANES = Object.freeze({ visible: () => Services.prefs.getBoolPref("browser.settings-redesign.enabled", false), }, + connection: { + l10nId: "tor-connection-settings-pane", + iconSrc: "chrome://browser/content/torconnect/tor-connect.svg", + groupIds: ["connectionStatus"], + module: "chrome://browser/content/torpreferences/config/connection.mjs", + visible: () => { + return TorConnect.enabled; + }, + replaces: "connection", + }, connectionSecurity: { parent: "privacy", l10nId: "preferences-connection-header", ===================================== browser/components/preferences/preferences.xhtml ===================================== @@ -108,6 +108,7 @@ <script type="module" src="chrome://browser/content/preferences/widgets/update-information.mjs"></script> <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-connection-status.mjs"></script> <script src="chrome://browser/content/torpreferences/bridgemoji/BridgeEmoji.js"/> </head> @@ -150,6 +151,11 @@ iconsrc="chrome://browser/skin/preferences/category-privacy-security.svg" data-l10n-id="pane-privacy-title3"> </html:moz-page-nav-button> + <html:moz-page-nav-button id="category-connection" + view="paneConnection" + iconsrc="chrome://browser/content/torconnect/tor-connect.svg" + data-l10n-id="tor-connection-settings-nav-button"> + </html:moz-page-nav-button> <html:moz-page-nav-button id="category-passwords-autofill" view="panePasswordsAutofill" iconsrc="chrome://browser/skin/login.svg" @@ -220,8 +226,6 @@ <!-- Hide the translations sub-pane. tor-browser#44710. --> <html:moz-page-nav-button hidden="true" class="hidden-category" view="paneTranslations"/> -#include ../torpreferences/content/connectionCategory.inc.xhtml - <!-- Footer links --> <html:moz-page-nav-button id="addonsButton" slot="secondary-nav" ===================================== browser/components/torpreferences/config/connection.mjs ===================================== @@ -0,0 +1,115 @@ +import { SettingGroupManager } from "chrome://browser/content/preferences/config/SettingGroupManager.mjs"; +import { Preferences } from "chrome://global/content/preferences/Preferences.mjs"; + +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + InternetStatus: "moz-src:///toolkit/modules/TorConnect.sys.mjs", + TorConnect: "moz-src:///toolkit/modules/TorConnect.sys.mjs", + TorConnectStage: "moz-src:///toolkit/modules/TorConnect.sys.mjs", + TorConnectTopics: "moz-src:///toolkit/modules/TorConnect.sys.mjs", +}); + +SettingGroupManager.registerGroups({ + connectionStatus: { + inProgress: true, + l10nId: "tor-connection-internet-status-group", + supportPage: "tor-manual:about", + headingLevel: 2, + items: [ + { + id: "connectionStatusGroup", + control: "moz-box-group", + items: [ + { + id: "internetStatus", + control: "tor-connection-status", + controlAttrs: { "status-type": "internet" }, + }, + { + id: "torStatus", + control: "tor-connection-status", + controlAttrs: { "status-type": "tor" }, + }, + ], + }, + { + id: "connectAutomatically", + l10nId: "tor-connection-quickstart-checkbox", + control: "moz-toggle", + }, + ], + }, +}); + +Preferences.addSetting({ + id: "connectionStatusGroup", +}); + +Preferences.addSetting({ + id: "internetStatus", + setup(emitChange) { + Services.obs.addObserver( + emitChange, + lazy.TorConnectTopics.InternetStatusChange + ); + return () => { + Services.obs.removeObserver( + emitChange, + lazy.TorConnectTopics.InternetStatusChange + ); + }; + }, + get() { + switch (lazy.TorConnect.internetStatus) { + case lazy.InternetStatus.Online: + return "online"; + case lazy.InternetStatus.Offline: + return "offline"; + } + return "unknown"; + }, +}); + +Preferences.addSetting({ + id: "torStatus", + setup(emitChange) { + Services.obs.addObserver(emitChange, lazy.TorConnectTopics.StageChange); + return () => { + Services.obs.removeObserver( + emitChange, + lazy.TorConnectTopics.StageChange + ); + }; + }, + get() { + if (lazy.TorConnect.stageName === lazy.TorConnectStage.Bootstrapped) { + return "connected"; + } + if (lazy.TorConnect.potentiallyBlocked) { + return "potentially-blocked"; + } + return "not-connected"; + }, +}); + +Preferences.addSetting({ + id: "connectAutomatically", + setup(emitChange) { + Services.obs.addObserver( + emitChange, + lazy.TorConnectTopics.QuickstartChange + ); + return () => { + Services.obs.removeObserver( + emitChange, + lazy.TorConnectTopics.QuickstartChange + ); + }; + }, + get() { + return lazy.TorConnect.quickstart; + }, + set(val) { + lazy.TorConnect.quickstart = val; + }, +}); ===================================== browser/components/torpreferences/content/connectionCategory.inc.xhtml deleted ===================================== @@ -1,6 +0,0 @@ -<html:moz-page-nav-button id="category-connection" - view="paneConnection" - iconsrc="chrome://browser/content/torconnect/tor-connect.svg" - data-l10n-id="tor-connection-settings-heading" - hidden="true"> -</html:moz-page-nav-button> ===================================== browser/components/torpreferences/content/connectionPane.inc.xhtml ===================================== @@ -10,6 +10,7 @@ class="subcategory" data-category="paneConnection" hidden="true" + data-srd-groupid="connectionStatus"
<html:h1 data-l10n-id="tor-connection-settings-heading"></html:h1> <description class="description-deemphasized" flex="1"> @@ -67,7 +68,11 @@ </vbox> <!-- Quickstart --> - <groupbox data-category="paneConnection" hidden="true"> + <groupbox + data-category="paneConnection" + hidden="true" + data-srd-groupid="connectionStatus" + > <label> <html:h2 data-l10n-id="tor-connection-automatic-heading"></html:h2> </label> @@ -85,7 +90,12 @@ </groupbox> <!-- Bridges --> - <hbox class="subcategory" data-category="paneConnection" hidden="true"> + <hbox + class="subcategory" + data-category="paneConnection" + hidden="true" + data-srd-groupid="connectionStatus" + > <html:h1 id="tor-bridges-subcategory-heading-non-search" class="tor-bridges-subcategory-heading tor-focusable-heading" @@ -98,6 +108,7 @@ data-category="paneConnection" hidden="true" aria-labelledby="tor-bridges-subcategory-heading-non-search" + data-srd-groupid="connectionStatus"
<!-- Add a search-header that only appears in search results as a substitute - for the hidden h1 element. See tor-browser#43320. @@ -580,7 +591,12 @@ </groupbox> <!-- Advanced --> - <hbox class="subcategory" data-category="paneConnection" hidden="true"> + <hbox + class="subcategory" + data-category="paneConnection" + hidden="true" + data-srd-groupid="connectionStatus" + > <html:h1 id="tor-advanced-subcategory-heading-non-search" data-l10n-id="tor-advanced-settings-heading" @@ -591,6 +607,7 @@ data-category="paneConnection" hidden="true" aria-labelledby="tor-advanced-subcategory-heading-non-search" + data-srd-groupid="connectionStatus"
<!-- Add a search-header that only appears in search results as a substitute - for the hidden h1 element. See tor-browser#43320. ===================================== browser/components/torpreferences/jar.mn ===================================== @@ -24,9 +24,11 @@ browser.jar: content/browser/torpreferences/provideBridgeDialog.js (content/provideBridgeDialog.js) content/browser/torpreferences/requestBridgeDialog.xhtml (content/requestBridgeDialog.xhtml) content/browser/torpreferences/requestBridgeDialog.js (content/requestBridgeDialog.js) - content/browser/torpreferences/connectionCategory.inc.xhtml (content/connectionCategory.inc.xhtml) content/browser/torpreferences/torLogDialog.js (content/torLogDialog.js) content/browser/torpreferences/torLogDialog.xhtml (content/torLogDialog.xhtml) + content/browser/torpreferences/config/connection.mjs (config/connection.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) content/browser/torpreferences/torPreferences.css (content/torPreferences.css) content/browser/torpreferences/bridgemoji/BridgeEmoji.js (content/bridgemoji/BridgeEmoji.js) ===================================== browser/components/torpreferences/widgets/tor-connection-status.css ===================================== @@ -0,0 +1,23 @@ +.tor-status-container { + padding: var(--box-padding); + + &.tor-status-icon-warning { + --box-icon-stroke: var(--icon-color-critical); + } +} + +.tor-status-label { + display: flex; + align-items: center; + gap: var(--space-medium); + & > * { + flex: 0 0 auto; + } + & > p { + margin: 0; + } +} + +.tor-status-name { + font-weight: var(--font-weight-semibold); +} ===================================== browser/components/torpreferences/widgets/tor-connection-status.mjs ===================================== @@ -0,0 +1,162 @@ +import { MozBoxBase } from "chrome://global/content/lit-utils.mjs"; +import { + classMap, + html, + ifDefined, +} from "chrome://global/content/vendor/lit.all.mjs"; + +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + TorConnectParent: + "moz-src:///browser/components/torconnect/TorConnectParent.sys.mjs", +}); + +/** + * Widget for displaying the current internet or Tor connection status. + * + * @tagname tor-connection-status + * @property {"internet" | "tor"} statusType - The type of status this widget is + * showing. + * @property {string} value - The current status value. + */ +class TorConnectionStatus extends MozBoxBase { + static properties = { + statusType: { type: String, attribute: "status-type" }, + value: { type: String }, + _nameL10nId: { type: String }, + _valueL10nId: { type: String }, + _iconWarning: { type: Boolean }, + _connectButton: { type: Boolean }, + }; + + /** + * A map from the status type to it's configuration. Each configuration is + * used to set the internal properties depending on the current value. + * + * @type {{[key: string]: object}} + */ + static #config = { + internet: { + nameL10nId: "tor-connection-internet-status-label", + values: { + online: { + iconSrc: "chrome://browser/content/torconnect/network.svg", + valueL10nId: "tor-connection-internet-status-online", + }, + offline: { + iconSrc: "chrome://browser/content/torconnect/network-broken.svg", + valueL10nId: "tor-connection-internet-status-offline", + }, + unknown: { + iconSrc: "chrome://browser/content/torconnect/network.svg", + valueL10nId: "tor-connection-internet-status-unknown", + }, + }, + }, + tor: { + nameL10nId: "tor-connection-network-status-label", + values: { + connected: { + iconSrc: "chrome://browser/content/torconnect/tor-connect.svg", + valueL10nId: "tor-connection-network-status-connected", + }, + "not-connected": { + iconSrc: "chrome://browser/content/torconnect/tor-connect-broken.svg", + valueL10nId: "tor-connection-network-status-not-connected", + connectButton: true, + }, + "potentially-blocked": { + iconSrc: "chrome://browser/content/torconnect/tor-connect-broken.svg", + valueL10nId: "tor-connection-network-status-blocked", + iconWarning: true, + connectButton: true, + }, + }, + }, + }; + + /** + * Whether we had focus prior to an update. + * + * @type {boolean} + */ + #hadFocus = false; + + willUpdate() { + const config = TorConnectionStatus.#config[this.statusType]; + const valueConfig = config?.values[this.value]; + this._nameL10nId = config?.nameL10nId; + this._valueL10nId = valueConfig?.valueL10nId; + this.iconSrc = valueConfig?.iconSrc; + this._iconWarning = valueConfig?.iconWarning ?? false; + this._connectButton = valueConfig?.connectButton ?? false; + this.#hadFocus = !!this.shadowRoot.activeElement; + } + + updated() { + if (this.#hadFocus && !this.shadowRoot.activeElement) { + // Focus is lost. We move focus to the search input. + window.gSearchResultsPane.searchInput.focus(); + } + this.#hadFocus = false; + } + + connectButtonClick() { + lazy.TorConnectParent.open({ beginBootstrapping: "soft" }); + } + + connectButtonTemplate() { + if (!this._connectButton) { + return ""; + } + return html` + <moz-button + data-l10n-id="tor-connection-status-connect-button" + @click=${this.connectButtonClick} + ></moz-button> + `; + } + + // override MozBoxBase.labelTemplate. + labelTemplate() { + if (!this._nameL10nId) { + return ""; + } + // NOTE: We purposefully include whitespace between the inner <span> + // elements so their text is separated. + return html`<div class="label tor-status-label"> + <p> + <span + class="tor-status-name" + data-l10n-id=${this._nameL10nId} + ></span> + <span data-l10n-id=${ifDefined(this._valueL10nId)}></span> + </p> + ${this.connectButtonTemplate()} + </span> `; + } + + render() { + if (!this._nameL10nId) { + return ""; + } + // NOTE: textTemplate comes from MozBoxBase, which will include an icon + // followed by our label. + return html` + ${this.stylesTemplate()} + <link + rel="stylesheet" + href="chrome://browser/content/torpreferences/widgets/tor-connection-status.css" + /> + <div + class=${classMap({ + "tor-status-container": true, + "tor-status-icon-warning": this._iconWarning, + })} + > + ${super.textTemplate()} + </div> + `; + } +} +customElements.define("tor-connection-status", TorConnectionStatus); ===================================== toolkit/locales/en-US/toolkit/global/tor-browser.ftl ===================================== @@ -55,10 +55,12 @@ home-mode-choice-tor = # "Connection" refers to the Tor Browser's connection to the Tor network. tor-connection-settings-heading = Connection -# The tooltip text for the "Connection" settings, shown in the preferences side bar. -# Likely should just be "{ tor-connection-settings-heading }", which will match the displayed text exactly. -tor-connection-settings-category = - .tooltiptext = { tor-connection-settings-heading } +# "Connection" refers to the Tor Browser's connection to the Tor network. +tor-connection-settings-pane = + .heading = Connection +# "Connection" refers to the Tor Browser's connection to the Tor network. +tor-connection-settings-nav-button = Connection + .title = Connection # -brand-short-name refers to 'Tor Browser', localized. tor-connection-overview = { -brand-short-name } routes your traffic over the Tor network, run by thousands of volunteers around the world. tor-connection-browser-learn-more-link = Learn more @@ -67,6 +69,10 @@ tor-connection-automatic-description = Automatically connect to the Tor network tor-connection-quickstart-checkbox = .label = Always connect automatically +# "{ -brand-short-name }" will be replaced with the localized name of the browser, e.g. "Tor Browser". +tor-connection-internet-status-group = + .label = Connection status + .description = { -brand-short-name } routes your traffic over the Tor network, run by thousands of volunteers around the world. # Prefix before the internet connection status. # "Internet" is not a proper noun, but is capitalized because it is the start of a sentence. tor-connection-internet-status-label = Internet: @@ -96,6 +102,10 @@ tor-connection-network-status-blocked = Potentially blocked # It will open a page to start connecting to the Tor network. # Uses sentence case in English (US). tor-connection-network-status-connect-button = Connect +# Here "Connect" refers to connecting to the Tor network. +# Uses sentence case in English (US). +tor-connection-status-connect-button = + .label = Connect ## Tor Bridges Settings. ===================================== tools/torbrowser/l10n/migrations/bug-45029-connection-status.py ===================================== @@ -0,0 +1,19 @@ +from fluent.migrate.helpers import transforms_from + + +def migrate(ctx): + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +tor-connection-settings-pane = + .heading = { COPY_PATTERN(path, "tor-connection-settings-heading") } +tor-connection-settings-nav-button = { COPY_PATTERN(path, "tor-connection-settings-heading") } + .title = { COPY_PATTERN(path, "tor-connection-settings-heading") } +tor-connection-status-connect-button = + .label = { COPY_PATTERN(path, "tor-connection-network-status-connect-button") } +""", + path="tor-browser.ftl", + ), + ) View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/437411d... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/437411d... 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
participants (1)
-
morgan (@morgan)