tor-commits
Threads by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 215537 discussions
[Git][tpo/applications/mullvad-browser][mullvad-browser-153.0esr-16.0-1] fixup! MB 97: Remove UI cues to install new extensions.
by Pier Angelo Vendrame (@pierov) 29 Jul '26
by Pier Angelo Vendrame (@pierov) 29 Jul '26
29 Jul '26
Pier Angelo Vendrame pushed to branch mullvad-browser-153.0esr-16.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
da45097b by Pier Angelo Vendrame at 2026-07-29T15:58:52+02:00
fixup! MB 97: Remove UI cues to install new extensions.
MB 565: Update the selector to hide the help button in about:addons.
- - - - -
1 changed file:
- toolkit/mozapps/extensions/content/aboutaddons.css
Changes:
=====================================
toolkit/mozapps/extensions/content/aboutaddons.css
=====================================
@@ -739,7 +739,7 @@ addon-page-header .main-search {
visibility: hidden;
}
-#help-button,
+[support-page="addons-help"],
#empty-addons-message {
display: none;
}
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/da4…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/da4…
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
1
0
[Git][tpo/applications/tor-browser-build][main] Bug 41843: Avoid storing unused universal apks
by boklm (@boklm) 29 Jul '26
by boklm (@boklm) 29 Jul '26
29 Jul '26
boklm pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits:
777d1539 by Nicolas Vigier at 2026-07-29T15:51:51+02:00
Bug 41843: Avoid storing unused universal apks
- - - - -
1 changed file:
- projects/geckoview/build_ac_fenix.sh
Changes:
=====================================
projects/geckoview/build_ac_fenix.sh
=====================================
@@ -63,3 +63,6 @@ mv $objdir/gradle/build/mobile/android/fenix/app/outputs/apk/$variant/*.apk $out
mv $objdir/gradle/build/mobile/android/fenix/app/outputs/apk/androidTest/$variant/*.apk $outdir/[% project %]/tests
popd
+
+# Remove universal apk files, since we don't use them (tor-browser-build#41843)
+find $outdir/[% project %] -name 'app-universal-*.apk' -delete
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/7…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/7…
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
1
0
[Git][tpo/applications/mullvad-browser][mullvad-browser-153.0esr-16.0-1] 3 commits: fixup! BB 44711: Hide unwanted setting controls in Base Browser.
by Pier Angelo Vendrame (@pierov) 29 Jul '26
by Pier Angelo Vendrame (@pierov) 29 Jul '26
29 Jul '26
Pier Angelo Vendrame pushed to branch mullvad-browser-153.0esr-16.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
72648d16 by Henry Wilkes at 2026-07-29T15:33:53+02:00
fixup! BB 44711: Hide unwanted setting controls in Base Browser.
BB 45156: Hide "Customize Firefox Home" in appearance settings.
- - - - -
81f0f262 by Henry Wilkes at 2026-07-29T15:34:02+02:00
fixup! BB 41916: Letterboxing preferences UI
BB 44959: Swap about:manual link.
- - - - -
6b39a131 by Henry Wilkes at 2026-07-29T15:34:17+02:00
fixup! BB 40925: Implemented the Security Level component
BB 44959: Swap about:manual link.
- - - - -
4 changed files:
- browser/components/preferences/config/appearance.mjs
- browser/components/preferences/letterboxing.inc.xhtml
- browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
- browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
Changes:
=====================================
browser/components/preferences/config/appearance.mjs
=====================================
@@ -90,6 +90,8 @@ Preferences.addSetting({
Preferences.addSetting({
id: "related-settings-home-link",
+ // Hide the "Customize Firefox Home" link. tor-browser#45156.
+ visible: () => false,
onUserClick: e => {
e.preventDefault();
window.gotoPref("paneHome");
=====================================
browser/components/preferences/letterboxing.inc.xhtml
=====================================
@@ -10,7 +10,7 @@
<html:span data-l10n-id="letterboxing-overview"></html:span>
<html:a
is="moz-support-link"
- support-page="tor-manual:anti-fingerprinting_letterboxing"
+ support-page="tor-manual:features__fingerprinting-protections___letterboxing"
data-l10n-id="letterboxing-learn-more"
></html:a>
</description>
=====================================
browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
=====================================
@@ -18,7 +18,7 @@
<html:a
is="moz-support-link"
id="securityLevel-learnMore"
- support-page="tor-manual:security-settings"
+ support-page="tor-manual:features__security-levels"
data-l10n-id="security-level-panel-learn-more-link"
></html:a>
<html:img id="securityLevel-background-image" alt="" />
=====================================
browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
=====================================
@@ -13,7 +13,7 @@
></html:span>
<html:a
is="moz-support-link"
- support-page="tor-manual:security-settings"
+ support-page="tor-manual:features__security-levels"
data-l10n-id="security-level-preferences-learn-more-link"
></html:a>
</description>
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/7e…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/7e…
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
1
0
[Git][tpo/applications/tor-browser][tor-browser-153.0esr-16.0-1] 4 commits: fixup! TB 40933: Add tor-launcher functionality
by henry (@henry) 29 Jul '26
by henry (@henry) 29 Jul '26
29 Jul '26
henry pushed to branch tor-browser-153.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
e6adf55b by Henry Wilkes at 2026-07-29T11:02:33+01:00
fixup! TB 40933: Add tor-launcher functionality
TB 43186: Stop using `TorProviderBuilder` to prompt users on desktop.
Also replace `settledState` with `currentState` and `settled`.
- - - - -
dda5c0f2 by Henry Wilkes at 2026-07-29T11:05:04+01:00
fixup! TB 40597: Implement TorSettings module
TB 43186: TorConnect handles TorProvider initialisation errors.
+ Add the `"ProviderStopped"` stage, which we enter whenever the
current `TorProvider` needs replacing.
+ In the `init` method we check `TorProvider.settledState` to see if the
current provider is still running at startup. After this, we listen
for the `ProviderStateChanged` event to see if it stops running later
on.
+ We expose a `restartProvider` method to request a new provider. The
`ProviderStatusChange` event allow consumers to update the UI.
- - - - -
3d9e8cbc by Henry Wilkes at 2026-07-29T11:05:05+01:00
fixup! TB 27476: Implement about:torconnect captive portal within Tor Browser
TB 43186: Add a `"ProviderStopped"` page to about:torconnect.
- - - - -
3dbd891f by Henry Wilkes at 2026-07-29T11:05:06+01:00
fixup! Tor Browser strings
TB 43186 - Add strings for the new `"ProviderStopped"` stage.
- - - - -
9 changed files:
- browser/components/torconnect/TorConnectParent.sys.mjs
- browser/components/torconnect/content/aboutTorConnect.css
- browser/components/torconnect/content/aboutTorConnect.html
- browser/components/torconnect/content/aboutTorConnect.js
- toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs
- toolkit/components/tor-launcher/tor-launcher.manifest
- toolkit/locales/en-US/toolkit/global/tor-browser.ftl
- toolkit/modules/RemotePageAccessManager.sys.mjs
- toolkit/modules/TorConnect.sys.mjs
Changes:
=====================================
browser/components/torconnect/TorConnectParent.sys.mjs
=====================================
@@ -3,6 +3,7 @@
import { TorStrings } from "moz-src:///toolkit/modules/TorStrings.sys.mjs";
import {
TorConnect,
+ TorConnectStage,
TorConnectTopics,
} from "moz-src:///toolkit/modules/TorConnect.sys.mjs";
@@ -26,9 +27,7 @@ and a particular about:torconnect page
* It adapts and relays the messages from and to the TorConnect module.
*/
export class TorConnectParent extends JSWindowActorParent {
- constructor(...args) {
- super(...args);
-
+ actorCreated() {
const self = this;
// JSWindowActiveParent derived objects cannot observe directly, so create a
@@ -44,6 +43,9 @@ export class TorConnectParent extends JSWindowActorParent {
case TorConnectTopics.StageChange:
self.sendAsyncMessage("torconnect:stage-change", obj);
break;
+ case TorConnectTopics.ProviderStatusChange:
+ self.sendAsyncMessage("torconnect:provider-status-change", obj);
+ break;
case TorConnectTopics.BootstrapProgress:
self.sendAsyncMessage("torconnect:bootstrap-progress", obj);
break;
@@ -64,6 +66,10 @@ export class TorConnectParent extends JSWindowActorParent {
this.torConnectObserver,
TorConnectTopics.StageChange
);
+ Services.obs.addObserver(
+ this.torConnectObserver,
+ TorConnectTopics.ProviderStatusChange
+ );
Services.obs.addObserver(
this.torConnectObserver,
TorConnectTopics.BootstrapProgress
@@ -124,6 +130,9 @@ export class TorConnectParent extends JSWindowActorParent {
Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit
);
break;
+ case "torconnect:restart-provider":
+ TorConnect.restartProvider();
+ break;
case "torconnect:start-again":
TorConnect.startAgain();
break;
@@ -267,3 +276,13 @@ export class TorConnectParent extends JSWindowActorParent {
);
}
}
+
+Services.obs.addObserver((_subject, topic) => {
+ if (topic !== TorConnectTopics.StageChange) {
+ return;
+ }
+ if (TorConnect.stageName === TorConnectStage.ProviderStopped) {
+ // Make sure we have an open tab to show the ProviderStopped stage.
+ TorConnectParent.open();
+ }
+}, TorConnectTopics.StageChange);
=====================================
browser/components/torconnect/content/aboutTorConnect.css
=====================================
@@ -235,40 +235,57 @@ form#locationDropdown select {
stroke: var(--icon-color);
/* Make non-interactive (non-draggable). */
pointer-events: none;
-}
-.torconnect-icon.offline-icon {
- content: url("chrome://browser/content/torconnect/network-broken.svg");
-}
+ &.offline-icon {
+ content: url("chrome://browser/content/torconnect/network-broken.svg");
+ }
-.torconnect-icon.assist-icon {
- content: url("chrome://browser/content/torconnect/tor-connect-broken.svg");
-}
+ &.assist-icon {
+ content: url("chrome://browser/content/torconnect/tor-connect-broken.svg");
+ }
-.torconnect-icon.location-icon {
- content: url("chrome://browser/content/torconnect/connection-location.svg");
- stroke: var(--icon-color-warning);
+ &.location-icon {
+ content: url("chrome://browser/content/torconnect/connection-location.svg");
+ stroke: var(--icon-color-warning);
+ }
}
.torconnect-heading {
grid-area: heading;
/* Do not show the focus outline. */
outline: none;
- font-size: var(--font-size-xxxlarge);
+ font-size: var(--font-size-xxlarge);
margin: 0;
margin-block-end: var(--space-xxlarge);
}
.torconnect-text-container {
grid-area: text-container;
+
+ & > *:not(:last-child) {
+ margin-block-end: var(--space-large);
+ }
+
+ & :is(p, ul) {
+ margin: 0;
+ }
+
+ & ul {
+ padding-inline-start: var(--space-xxlarge);
+ }
+
+ & li:not(:last-child) {
+ margin-block-end: var(--space-medium);
+ }
}
-.torconnect-text-container p {
- margin: 0;
+.torconnect-list-intro {
+ font-weight: var(--font-weight-semibold);
}
-.torconnect-text-container > *:not(:last-child) {
- margin-block-end: var(--space-large);
+body.hide-provider-config-debugging .provider-config-debugging,
+body:not(.hide-provider-config-debugging) .provider-generic-debugging {
+ display: none;
}
.torconnect-controls-container {
@@ -281,11 +298,33 @@ form#locationDropdown select {
align-items: center;
/* Gap between children and rows. */
gap: var(--space-small) var(--space-small);
+
+ & > * {
+ flex: 0 0 max-content;
+ margin: 0;
+ }
}
-.torconnect-controls-container > * {
- flex: 0 0 max-content;
- margin: 0;
+#restart-provider-failed {
+ color: var(--text-color-error);
+ align-items: center;
+ gap: var(--space-xxsmall);
+
+ &:not([hidden]) {
+ display: flex;
+ }
+
+ & > * {
+ flex: 0 0 max-content;
+ }
+}
+
+#restart-provider-failed-icon {
+ width: var(--icon-size);
+ height: var(--icon-size);
+ -moz-context-properties: fill;
+ fill: var(--icon-color-critical);
+ content: url("chrome://global/skin/icons/error.svg");
}
/* Temporary hacks for the connectPageContainer. */
=====================================
browser/components/torconnect/content/aboutTorConnect.html
=====================================
@@ -15,12 +15,22 @@
href="chrome://browser/content/torconnect/aboutTorConnect.css"
/>
+ <link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="toolkit/global/tor-browser.ftl" />
+ <link rel="localization" href="toolkit/global/mozSupportLink.ftl" />
+ <script
+ type="module"
+ src="chrome://global/content/elements/moz-button.mjs"
+ ></script>
<script
type="module"
src="chrome://global/content/elements/moz-toggle.mjs"
></script>
+ <script
+ type="module"
+ src="chrome://global/content/elements/moz-support-link.mjs"
+ ></script>
</head>
<body class="onion-pattern-background">
<div id="progressBar" hidden="hidden">
@@ -50,6 +60,86 @@
<span class="breadcrumb-label"></span>
</span>
</div>
+ <div class="torconnect-stage-content" data-stage-name="ProviderStopped">
+ <img class="torconnect-icon assist-icon" alt="" />
+ <h1
+ class="torconnect-heading"
+ tabindex="-1"
+ data-l10n-id="tor-connect-tor-not-working-heading"
+ ></h1>
+ <div class="torconnect-text-container">
+ <p data-l10n-id="tor-connect-tor-not-working-intro"></p>
+ <p
+ class="torconnect-list-intro"
+ data-l10n-id="tor-connect-tor-not-working-cause-intro"
+ ></p>
+ <ul>
+ <li
+ class="provider-config-debugging"
+ data-l10n-id="tor-connect-tor-not-working-cause-applications"
+ ></li>
+ <li
+ class="provider-config-debugging"
+ data-l10n-id="tor-connect-tor-not-working-cause-files"
+ ></li>
+ <li
+ class="provider-config-debugging"
+ data-l10n-id="tor-connect-tor-not-working-cause-other"
+ ></li>
+ <li
+ class="provider-generic-debugging"
+ data-l10n-id="tor-connect-tor-not-working-cause-generic"
+ ></li>
+ </ul>
+ <p
+ class="torconnect-list-intro"
+ data-l10n-id="tor-connect-tor-not-working-resolve-intro"
+ ></p>
+ <ul>
+ <li
+ class="provider-config-debugging"
+ data-l10n-id="tor-connect-tor-not-working-resolve-applications"
+ ></li>
+ <li
+ class="provider-config-debugging"
+ data-l10n-id="tor-connect-tor-not-working-resolve-files"
+ ></li>
+ <li
+ class="provider-config-debugging"
+ data-l10n-id="tor-connect-tor-not-working-resolve-restart-long"
+ ></li>
+ <li
+ class="provider-generic-debugging"
+ data-l10n-id="tor-connect-tor-not-working-resolve-restart-short"
+ ></li>
+ </ul>
+ <p data-l10n-id="tor-connect-tor-not-working-support">
+ <a
+ is="moz-support-link"
+ data-l10n-name="support-link"
+ support-page="tor-manual:get-in-touch__bug-or-feedback"
+ >
+ </a>
+ </p>
+ <a
+ is="moz-support-link"
+ support-page="tor-manual:encountering-issues__troubleshooting"
+ ></a>
+ </div>
+ <div class="torconnect-controls-container">
+ <div id="restart-provider-failed" role="alert">
+ <img id="restart-provider-failed-icon" alt="" />
+ <span
+ data-l10n-id="tor-connect-tor-not-working-restarting-failed"
+ ></span>
+ </div>
+ <moz-button
+ id="restart-provider-button"
+ type="primary"
+ data-l10n-id="tor-connect-tor-not-working-restart-button"
+ ></moz-button>
+ </div>
+ </div>
<div id="connectPageContainer" class="torconnect-stage-content">
<img id="tor-connect-icon" class="torconnect-icon" alt="" />
<h1
=====================================
browser/components/torconnect/content/aboutTorConnect.js
=====================================
@@ -134,6 +134,8 @@ class AboutTorConnect {
"full-regions-option-group"
),
tryBridgeButton: document.querySelector(this.selectors.buttons.tryBridge),
+ restartProviderButton: document.getElementById("restart-provider-button"),
+ restartProviderFailed: document.getElementById("restart-provider-failed"),
});
/**
@@ -418,6 +420,10 @@ class AboutTorConnect {
console.warn("Page opened whilst loading");
isLoaded = false;
break;
+ case "ProviderStopped":
+ this.hideBreadcrumbs();
+ this.updateProviderStatus(stage.providerStatus, true);
+ break;
case "Start":
this.showStart(stage.tryAgain, stage.potentiallyBlocked);
if (focusConnect) {
@@ -479,6 +485,157 @@ class AboutTorConnect {
moveFocus.focus();
}
+ /**
+ * The stored data for the `ProviderStopped` page content. `null` whilst
+ * uninitialized.
+ *
+ * @type {object}
+ */
+ _providerStoppedData = null;
+
+ /**
+ * Called whenever the tor provider status may have changed. Only relevant in
+ * the `ProviderStopped` stage.
+ *
+ * @param {ProviderStatus} providerStatus - The latest provider status.
+ * @param {boolean} enteringStage - Whether this is being called because we
+ * have just entered the `ProviderStopped` stage as the initial stage of the
+ * page, or transitioning from another stage.
+ */
+ updateProviderStatus(providerStatus, enteringStage) {
+ if (this.shownStage !== "ProviderStopped") {
+ // Ignore.
+ return;
+ }
+ if (enteringStage) {
+ // Reset the data:
+ // + When entering the stage.
+ // + When opening the page in this initial stage.
+ this._providerStoppedData = {
+ // Set to `null` to make sure we don't early exit below.
+ isRestarting: null,
+ forceShowRestarting: false,
+ canShowFailedAlert: false,
+ // We set the maybeConfigIssue when entering the stage, but do not attempt
+ // to update it between failed attempts.
+ maybeConfigIssue: providerStatus.maybeConfigIssue,
+ };
+ }
+
+ // We show the UI as restarting if the state is not "Stopped", which
+ // includes both "Starting" and "Running". In the latter case (which is
+ // unexpected) we still want to show the state as loading before we enter a
+ // different shownStage.
+ const restarting = providerStatus.state !== "Stopped";
+
+ const data = this._providerStoppedData;
+
+ if (restarting === data.isRestarting) {
+ // No change in the recorded state. Don't change the UI or adjust any
+ // timeouts.
+ return;
+ }
+
+ data.isRestarting = restarting;
+ if (restarting) {
+ // Whilst we remain in this `ProviderStopped` stage, we will now show the
+ // failed alert when we re-enter the "Stopped" state.
+ data.canShowFailedAlert = true;
+
+ if (!data.forceShowRestarting) {
+ // Force the restarting UI to show for at least a certain amount of
+ // time. Even if we fail early, we continue to show the restarting UI
+ // for a short time to make sure the user has enough time to visually
+ // see the restarting UI before we return to the error state.
+ data.forceShowRestarting = true;
+ setTimeout(() => {
+ if (
+ data !== this._providerStoppedData ||
+ this.shownStage !== "ProviderStopped"
+ ) {
+ // We left or re-entered this stage whilst waiting. Do nothing.
+ return;
+ }
+ data.forceShowRestarting = false;
+ this.updateProviderStoppedContent();
+ }, 1000);
+ }
+ // Else, we already have a pending timeout.
+ // E.g., consider the following timeline, where "R" represents entering
+ // the "Starting" state, "S" represents entering the "Stopped" state,
+ // "T0" represents the start of the forcedShowRestarting timeout, and "T1"
+ // represents the completion:
+ //
+ // |--------------+-----+-----+-----+----+------------------>
+ // S0 R0 S1 R1 S2
+ // T0 T1
+ // |--stopped UI--|--restarting UI-------|--stopped UI-------
+ //
+ //
+ // Similarly with S2 delayed:
+ //
+ // |--------------+-----+-----+----------+----+------------->
+ // S0 R0 S1 R1 S2
+ // T0 T1
+ // |--stopped UI--|--restarting UI------------|--stopped UI--
+ //
+ //
+ // I.e. we restart once (R0) which starts the timeout. Then we stop (S1) and
+ // restart (R1) again (though unlikely, this could happen if the user
+ // opens another `about:torconnect` tab after S1 and presses the restart
+ // button). Rather than create a new timeout, which would delay the
+ // restart display for even longer, we maintain the current one.
+ }
+
+ this.updateProviderStoppedContent();
+ }
+
+ /**
+ * Whether we are currently *showing* the tor provider as restarting in the
+ * UI.
+ *
+ * @type {boolean}
+ */
+ restartingProvider = false;
+
+ /**
+ * Called to update the page content for the `ProviderStopped` stage.
+ */
+ updateProviderStoppedContent() {
+ const {
+ isRestarting,
+ forceShowRestarting,
+ canShowFailedAlert,
+ maybeConfigIssue,
+ } = this._providerStoppedData;
+
+ // Hide any of the debugging information related to configuration issues if
+ // we do not suspect that this could be the cause.
+ document.body.classList.toggle(
+ "hide-provider-config-debugging",
+ !maybeConfigIssue
+ );
+
+ const showRestarting = isRestarting || forceShowRestarting;
+ this.elements.restartProviderFailed.hidden =
+ showRestarting || !canShowFailedAlert;
+
+ this.restartingProvider = showRestarting;
+ // The button is functionally disabled, but can still keep focus.
+ // TODO: tor-browser#45050. Disabled attribute is waiting on bugzilla bug
+ // 1927727.
+ // this.elements.restartProviderButton.disabled = showRestarting;
+ this.elements.restartProviderButton.iconSrc = showRestarting
+ ? "chrome://global/skin/icons/loading.svg"
+ : null;
+ document.l10n.setAttributes(
+ this.elements.restartProviderButton,
+ showRestarting
+ ? "tor-connect-tor-not-working-restarting-button"
+ : "tor-connect-tor-not-working-restart-button"
+ );
+ }
+
updateBootstrappingStatus(data) {
this.elements.progressMeter.style.setProperty(
"--progress-percent",
@@ -816,6 +973,14 @@ class AboutTorConnect {
RPMSendAsyncMessage("torconnect:restart");
});
+ this.elements.restartProviderButton.addEventListener("click", () => {
+ if (this.restartingProvider) {
+ // Ignore clicks whilst the button is shown as "Restarting".
+ return;
+ }
+ RPMSendAsyncMessage("torconnect:restart-provider");
+ });
+
this.elements.configureButton.textContent =
TorStrings.torConnect.torConfigure;
this.elements.configureButton.addEventListener("click", () => {
@@ -896,6 +1061,9 @@ class AboutTorConnect {
RPMAddMessageListener("torconnect:stage-change", ({ data }) => {
this.updateStage(data);
});
+ RPMAddMessageListener("torconnect:provider-status-change", ({ data }) => {
+ this.updateProviderStatus(data, false);
+ });
RPMAddMessageListener("torconnect:bootstrap-progress", ({ data }) => {
this.updateBootstrappingStatus(data);
});
=====================================
toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs
=====================================
@@ -204,13 +204,13 @@ export class TorProviderBuilder {
// I.e. it should be safe to call
// TorProviderBuilder.init();
// TorProviderBuilder.build();
- // TorProviderBuilder.settledState();
+ // TorProviderBuilder.settled();
// // etc
// without any await.
//
// In particular, this is needed by `TorConnect.init`, which will call
- // `settledState`. It will also call `build` immediately if quickstart is
- // set. See tor-browser#41921.
+ // `settled`. It will also call `build` immediately if quickstart is set.
+ // See tor-browser#41921.
if (this.#providerData) {
lazy.logger.info(
`Replacing the provider with a "${this.providerType}" provider.`
@@ -372,21 +372,24 @@ export class TorProviderBuilder {
}
/**
- * Get the state of the current provider instance. Waits until the provider
- * has finished initialisation first.
+ * Get the state of the current provider instance.
*
- * If the provider has been replaced, the Stopped state will be returned.
- *
- * @returns {string} - The `TorProviderState` state for the provider that
- * existed when this method was called.
+ * @returns {string} - The `TorProviderState` state for the current provider.
*/
- static async settledState() {
+ static currentState() {
+ this.#checkActive();
+ return this.#providerData.provider.state;
+ }
+
+ /**
+ * Wait until the current provider instance has finished initializing, so it
+ * is no longer in the `Starting` state.
+ */
+ static async settled() {
this.#checkActive();
- const { provider, initPromise } = this.#providerData;
try {
- await initPromise;
+ await this.#providerData.initPromise;
} catch {}
- return this.#checkProviderState(provider);
}
/**
=====================================
toolkit/components/tor-launcher/tor-launcher.manifest
=====================================
@@ -1,2 +1 @@
category profile-after-change TorStartupService @torproject.org/tor-startup-service;1
-category browser-first-window-ready moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs TorProviderBuilder.firstWindowLoaded
=====================================
toolkit/locales/en-US/toolkit/global/tor-browser.ftl
=====================================
@@ -15,6 +15,37 @@ appmenu-open-tor-manual =
# Here "Tor" refers to the Tor network.
tor-connect-page-title = Connect to Tor
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-heading = The Tor process has stopped working
+# Here "process" is a noun, referring to the execution of a computer program.
+tor-connect-tor-not-working-intro = The underlying process that controls your connection to the Tor network has stopped working.
+tor-connect-tor-not-working-cause-intro = What could be causing this?
+# "-brand-short-name" will be substituted with the localized name for "Tor Browser".
+tor-connect-tor-not-working-cause-applications = Another application that uses the Tor network is conflicting with { -brand-short-name }.
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-cause-files = The files used by the Tor process have been modified or removed.
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-cause-other = The Tor process has stopped working due to a different technical issue.
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-cause-generic = The Tor process has stopped working due to a technical issue.
+tor-connect-tor-not-working-resolve-intro = What can you do about it?
+tor-connect-tor-not-working-resolve-applications = Quit any other applications that use the Tor network, or reconfigure them.
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-resolve-files = If you have modified the files used by the Tor process, undo these changes.
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-resolve-restart-long = Once you have followed these steps, or made any other change, try restarting the Tor process (this won’t close your browser tabs).
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-resolve-restart-short = Try restarting the Tor process (this won’t close your browser tabs).
+# The translation of "support channels" should also be wrapped in '<a data-l10n-name="support-link">' and '</a>', which will link to the corresponding support page.
+tor-connect-tor-not-working-support = If the problem remains, get in contact with us through one of our <a data-l10n-name="support-link">support channels</a>.
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-restart-button =
+ .label = Restart Tor process
+# Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network".
+tor-connect-tor-not-working-restarting-button =
+ .label = Restarting Tor process…
+tor-connect-tor-not-working-restarting-failed = Restarting failed
+
## Tor Browser home page.
tor-browser-home-heading-stable = Explore. Privately.
=====================================
toolkit/modules/RemotePageAccessManager.sys.mjs
=====================================
@@ -296,6 +296,7 @@ export let RemotePageAccessManager = {
"about:torconnect": {
RPMAddMessageListener: [
"torconnect:stage-change",
+ "torconnect:provider-status-change",
"torconnect:bootstrap-progress",
"torconnect:quickstart-change",
"torconnect:region-names-change",
@@ -307,10 +308,12 @@ export let RemotePageAccessManager = {
"torconnect:set-quickstart",
"torconnect:view-tor-logs",
"torconnect:restart",
+ "torconnect:restart-provider",
"torconnect:start-again",
"torconnect:choose-region",
],
RPMSendQuery: ["torconnect:get-init-args", "torconnect:get-regions"],
+ RPMGetFormatURLPref: ["app.support.baseURL"],
},
"about:welcome": {
RPMSendAsyncMessage: ["ActivityStream:ContentToMain"],
=====================================
toolkit/modules/TorConnect.sys.mjs
=====================================
@@ -10,6 +10,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
MoatRPC: "moz-src:///toolkit/modules/Moat.sys.mjs",
TorBootstrapRequest:
"moz-src:///toolkit/components/tor-launcher/TorBootstrapRequest.sys.mjs",
+ TorProviderBuilder:
+ "moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs",
TorProviderState:
"moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs",
TorProviderTopics:
@@ -81,11 +83,28 @@ ChromeUtils.defineLazyGetter(lazy, "logger", () =>
/* Topics Notified by the TorConnect module */
export const TorConnectTopics = Object.freeze({
+ // Fired when the stage changes.
+ // The stage name from `TorConnectStage` is passed as the event subject.
StageChange: "torconnect:stage-change",
+ // Fired when the `TorConnect.quickstart` value changes.
QuickstartChange: "torconnect:quickstart-change",
+ // Fired when the `TorConnect.internetStatus` changes.
InternetStatusChange: "torconnect:internet-status-change",
+ // Fired when the `TorConnect.stage.providerStatus` changes.
+ // NOTE: The state of the provider may switch to `TorProviderState.Stopped`
+ // prior to `TorConnect` entering the stage `TorConnectStage.ProviderStopped`
+ // because a stage switch can be delayed. A consumer should always show the
+ // current `TorConnect` stage as the highest priority, and only react to this
+ // event when we are already in the `TorConnectStage.ProviderStopped` stage.
+ // The `ProviderStatus` object is passed as the event subject.
+ ProviderStatusChange: "torconnect:provider-status-change",
+ // Fired when the list of region names returned by `TorConnect.getRegionNames`
+ // may have changed.
RegionNamesChange: "torconnect:region-names-change",
+ // Fired when the `TorConnect.stage.bootstrapStatus` may have changed.
+ // The `BootstrapStatus` object is passed as the event subject.
BootstrapProgress: "torconnect:bootstrap-progress",
+ // Fired when we enter the `TorConnectStage.Bootstrapped` stage.
BootstrapComplete: "torconnect:bootstrap-complete",
});
@@ -655,6 +674,7 @@ export const InternetStatus = Object.freeze({
export const TorConnectStage = Object.freeze({
Disabled: "Disabled",
Loading: "Loading",
+ ProviderStopped: "ProviderStopped",
Start: "Start",
Bootstrapping: "Bootstrapping",
Offline: "Offline",
@@ -689,6 +709,8 @@ export const TorConnectStage = Object.freeze({
* have reached an error stage at some point before being bootstrapped.
* @property {BootstrappingStatus} bootstrappingStatus - The current
* bootstrapping status.
+ * @property {ProviderStatus} providerStatus - The current status of the Tor
+ * provider.
*/
/**
@@ -714,6 +736,19 @@ export const TorConnectStage = Object.freeze({
* @property {?string} reason - The bootstrapping failure reason.
*/
+/**
+ * @typedef {object} ProviderStatus
+ *
+ * The status of the current Tor provider.
+ *
+ * @property {string} state - The current `TorProviderState` state of the
+ * provider.
+ * @property {boolean} maybeConfigIssue - Whether we suspect that a
+ * configuration issue (conflicting tor process or a mis-config) *may* have
+ * caused the provider to be stopped. This is a *soft* indicator for UI
+ * purposes to show additional debugging advice that might resolve the issue.
+ */
+
export const TorConnect = {
/**
* Default bootstrap options for simulation.
@@ -800,6 +835,52 @@ export const TorConnect = {
*/
_potentiallyBlocked: false,
+ /**
+ * The current `TorProviderState` state. `null` whilst we wait for
+ * `TorProviderBuilder.settled` to return.
+ *
+ * @type {?string}
+ */
+ _providerKnownState: null,
+
+ /**
+ * The current `TorProviderState` state. Whilst we wait for
+ * `TorProviderBuilder.settled` to return with the true state, we will assume
+ * that the provider is in the `TorProviderState.Running` state, as would be
+ * expected under normal circumstances.
+ */
+ get _providerState() {
+ return this._providerKnownState ?? lazy.TorProviderState.Running;
+ },
+
+ /**
+ * Convenience property for detecting when a provider is running.
+ *
+ * @type {boolean}
+ */
+ get _providerRunning() {
+ return this._providerState === lazy.TorProviderState.Running;
+ },
+
+ /**
+ * Whether we suspect a config issue cause the provider to fail.
+ *
+ * @type {boolean}
+ */
+ _maybeConfigIssue: false,
+
+ /**
+ * The latest provider status information for consumers.
+ *
+ * @returns {ProviderStatus} - The provider status.
+ */
+ _providerStatus() {
+ return {
+ state: this._providerState,
+ maybeConfigIssue: this._maybeConfigIssue,
+ };
+ },
+
/**
* Get a summary of the current user stage.
*
@@ -822,6 +903,7 @@ export const TorConnect = {
tryAgain: this._tryAgain,
potentiallyBlocked: this._potentiallyBlocked,
bootstrappingStatus: structuredClone(this._bootstrappingStatus),
+ providerStatus: this._providerStatus(),
};
},
@@ -928,6 +1010,23 @@ export const TorConnect = {
this._updateInternetStatus();
+ // Do not await the `TorProviderBuilder` initialisation before we move to
+ // the Start stage so that the UI can load quickly. We presume it will not
+ // fail, but will switch to `ProviderStopped` if necessary.
+ lazy.TorProviderBuilder.settled().then(() => {
+ // NOTE: Assuming `TorConnect` is the only consumer of
+ // `TorProviderBuilder` that will replace the provider, then the current
+ // provider should be the *first* provider.
+ const state = lazy.TorProviderBuilder.currentState();
+ lazy.logger.debug(`Init state: ${state}`);
+ this._setProviderState(state, true);
+ });
+
+ if (!this._providerRunning) {
+ // Promise resolved immediately, and failed. Should have already requested
+ // the ProviderStopped stage.
+ return;
+ }
// NOTE: At this point, _requestedStage should still be `null`.
this._setStage(TorConnectStage.Start);
if (
@@ -955,19 +1054,13 @@ export const TorConnect = {
}
break;
case lazy.TorProviderTopics.ProviderStateChanged:
- if (data !== lazy.TorProviderState.Stopped) {
- break;
- }
- lazy.logger.info("Starting again since the tor process exited");
- // Treat a failure as a possibly broken configuration.
- // So, prevent quickstart at the next start.
- Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, true);
- this._makeStageRequest(TorConnectStage.Start, true);
+ this._setProviderState(data, false);
break;
case lazy.TorSettingsTopics.SettingsChanged:
if (
this._stageName !== TorConnectStage.Bootstrapped &&
this._stageName !== TorConnectStage.Loading &&
+ this._stageName !== TorConnectStage.ProviderStopped &&
this._stageName !== TorConnectStage.Start &&
subject.wrappedJSObject.changes.some(propertyName =>
propertyName.startsWith("bridges.")
@@ -1009,9 +1102,20 @@ export const TorConnect = {
* @param {string} name - The name of the stage to move to.
*/
_setStage(name) {
+ if (this._stageName === TorConnectStage.Disabled) {
+ throw new Error(`Trying to set the stage to ${name} when disabled`);
+ }
if (this._bootstrapAttempt) {
throw new Error(`Trying to set the stage to ${name} during a bootstrap`);
}
+ if (!this._providerRunning && name !== TorConnectStage.ProviderStopped) {
+ if (!lazy.TorLauncherUtil.isAndroid) {
+ // TODO: Remove Android exception.
+ throw new Error(
+ `Trying to set the stage to ${name} when provider is not running`
+ );
+ }
+ }
lazy.logger.info(`Entering stage ${name}`);
this._stageName = name;
@@ -1211,6 +1315,13 @@ export const TorConnect = {
return false;
}
+ if (!this._providerRunning) {
+ lazy.logger.warn(
+ `Tor provider is not running. Ignoring request with ${regionCode}.`
+ );
+ return false;
+ }
+
const currentStage = this._stageName;
if (regionCode) {
@@ -1315,7 +1426,7 @@ export const TorConnect = {
this._defaultRegion = bootstrapAttempt.detectedRegion;
}
- if (result === "complete") {
+ if (result === "complete" && this._providerRunning) {
// Reset tryAgain, potentiallyBlocked and errorDetails in case the tor
// process exists later on.
this._tryAgain = false;
@@ -1351,15 +1462,10 @@ export const TorConnect = {
this._tryAgain = true;
if (error instanceof lazy.TorProviderInitError) {
- // Treat like TorProviderTopics.ProviderStateChanged. We expect a user
- // notification when this happens.
- // Treat a failure as a possibly broken configuration.
- // So, prevent quickstart at the next start.
- Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, true);
- lazy.logger.info(
- "Starting again since the tor provider failed to initialise"
- );
- this._setStage(TorConnectStage.Start);
+ // Unexpected. We expect TorProviderTopics.ProviderStateChanged to have
+ // already been called. I.e. the requestStage should be set.
+ lazy.logger.error("Unexpected TorProviderInitError");
+ this._setProviderState(lazy.TorProviderBuilder.currentState(), false);
return;
}
@@ -1489,14 +1595,27 @@ export const TorConnect = {
lazy.logger.warn(`Cannot move to ${stage} when bootstrapped`);
return;
}
+ if (!this._providerRunning && stage !== TorConnectStage.ProviderStopped) {
+ if (!lazy.TorLauncherUtil.isAndroid) {
+ // TODO: Remove Android exception.
+ lazy.logger.warn(
+ `Cannot move to ${stage} when provider is not running`
+ );
+ return;
+ }
+ }
if (this._stageName === TorConnectStage.Loading) {
- if (stage === TorConnectStage.Start) {
- // Will transition to "Start" stage when loading completes.
- lazy.logger.info("Still in the Loading stage");
+ if (stage === TorConnectStage.ProviderStopped) {
+ lazy.logger.info("Skipping straight from Loading to ProviderStopped");
} else {
- lazy.logger.warn(`Cannot move to ${stage} when Loading`);
+ if (stage === TorConnectStage.Start) {
+ // Will transition to "Start" stage when loading completes.
+ lazy.logger.info("Still in the Loading stage");
+ } else {
+ lazy.logger.warn(`Cannot move to ${stage} when Loading`);
+ }
+ return;
}
- return;
}
if (!this._bootstrapAttempt) {
@@ -1519,6 +1638,116 @@ export const TorConnect = {
this._bootstrapAttempt?.cancel();
},
+ /**
+ * Called when the current Tor provider's state changes.
+ *
+ * @param {string} state - The `TorProviderState` we are now in.
+ * @param {boolean} initialState - Whether this is the initial provider's
+ * state.
+ */
+ _setProviderState(state, initialState) {
+ if (this._providerKnownState === null && !initialState) {
+ // Wait for `TorProviderBuilder.settled` to return first.
+ // We stick to the assumed status for the time being.
+ return;
+ }
+
+ const wasRunning = this._providerRunning;
+ const prevState = this._providerState;
+ this._providerKnownState = state;
+
+ if (prevState === state) {
+ // No change in state.
+ // NOTE: If this is the initial state, then `prevState` will be
+ // `TorProviderState.Running`, in which case this will *not* notify
+ // consumers if the initial state is also `Running`.
+ return;
+ }
+
+ if (this._providerRunning) {
+ // As soon as we get a provider that is running (has not immediately
+ // exited), from now on we will no longer *suspect* that a configuration
+ // issue (conflicting tor process, or a mis-config) *could* cause a tor
+ // provider to stop. I.e. if we ever re-enter the "Stopped" or "Starting"
+ // state, `maybeConfigIssue` will remain `false`.
+ //
+ // This is because we assume that the browser's established tor process
+ // can not be killed by the spawning of a new conflicting non-browser tor
+ // process, and any changes in the configuration (via files or otherwise)
+ // mid session won't be read by the existing process.
+ //
+ // NOTE: In principle, if the browser tor process is killed for some other
+ // reason, in the interim there is a time period where the configuration
+ // could change or a new non-browser tor process is spawned that could
+ // conflict, which may prevent any *new* browser tor process from
+ // starting. I.e. the cause of failure switches from non-config issue to
+ // a config issue. However, such a scenario is deemed unlikely, and the
+ // consequences of not accounting for it are very mild since
+ // `maybeConfigIssue` is only soft hint for the debugging UI.
+ this._maybeConfigIssue = false;
+ if (!wasRunning) {
+ // Return to the Start stage to re-try a bootstrap.
+ this._makeStageRequest(TorConnectStage.Start);
+ }
+ } else {
+ if (initialState) {
+ // This is the first time we learn the provider state. If the first
+ // provider is not running after initialisation, then we *suspect* that
+ // there *could* be a conflict with another tor process. E.g. an
+ // existing tor process is already using the ports we want to use, so
+ // the browser's tor provider will fail at initialisation.
+ this._maybeConfigIssue = true;
+ }
+ if (wasRunning) {
+ // Transitioning from the Running state to a non-Running state.
+
+ // Prevent quickstart firing at the next startup until we have another
+ // successful bootstrap.
+ Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, true);
+ // We request the ProviderStopped stage, which may take some time to
+ // reach if we need to cancel the current bootstrap first.
+ // But other methods should take into account that _providerRunning is now
+ // `false` to early return and guarantee that we enter this
+ // ProviderStopped stage.
+ if (lazy.TorLauncherUtil.isAndroid) {
+ // TODO: Remove this Android path when android supports the
+ // `ProviderStopped` stage.
+ this._makeStageRequest(TorConnectStage.Start, true);
+ } else {
+ this._makeStageRequest(TorConnectStage.ProviderStopped, true);
+ }
+ }
+ }
+
+ const providerStatus = this._providerStatus();
+ lazy.logger.debug("New provider status", providerStatus);
+ Services.obs.notifyObservers(
+ providerStatus,
+ TorConnectTopics.ProviderStatusChange
+ );
+ },
+
+ /**
+ * Restart the Tor provider after it has stopped.
+ */
+ restartProvider() {
+ lazy.logger.debug("Request to restart Tor provider");
+ this._ensureEnabled();
+
+ if (this._stageName !== TorConnectStage.ProviderStopped) {
+ lazy.logger.warn(
+ `Cannot restart the provider in stage ${this._stageName}`
+ );
+ return;
+ }
+ if (this._providerState === lazy.TorProviderState.Starting) {
+ lazy.logger.warn("Already restarting the Tor provider");
+ return;
+ }
+
+ lazy.TorProviderBuilder.replace();
+ },
+
/**
* Restart the TorConnect stage to the start.
*/
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/3867e5…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/3867e5…
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
1
0
[Git][tpo/applications/tor-browser][tor-browser-153.0esr-16.0-1] fixup! [android] Delete unused media
by Dan Ballard (@dan) 28 Jul '26
by Dan Ballard (@dan) 28 Jul '26
28 Jul '26
Dan Ballard pushed to branch tor-browser-153.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
3867e54e by clairehurst at 2026-07-28T13:33:44-06:00
fixup! [android] Delete unused media
Bug 44448: P1 trivialize assets
- - - - -
63 changed files:
- mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_logo_firefox_24.xml
- mobile/android/fenix/app/src/debug/res/drawable/ic_firefox.xml
- mobile/android/fenix/app/src/debug/res/drawable/ic_launcher_foreground.xml
- mobile/android/fenix/app/src/main/res/drawable-nodpi/firefox_as_default_banner_illustration.xml
- mobile/android/fenix/app/src/main/res/drawable-xxhdpi/firefox_sport.webp
- mobile/android/fenix/app/src/main/res/drawable/bookmarks_folder_illustration.xml
- mobile/android/fenix/app/src/main/res/drawable/expressive_firefox.xml
- mobile/android/fenix/app/src/main/res/drawable/fox_ai_on_state.xml
- mobile/android/fenix/app/src/main/res/drawable/fox_alert_crash_dark.xml
- mobile/android/fenix/app/src/main/res/drawable/fox_alert_crash_light.xml
- mobile/android/fenix/app/src/main/res/drawable/fox_exclamation_alert.xml
- mobile/android/fenix/app/src/main/res/drawable/fox_expressive_face_tail.xml
- mobile/android/fenix/app/src/main/res/drawable/fox_hand_over_eyes.xml
- mobile/android/fenix/app/src/main/res/drawable/fox_sitting_looking_up.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_cool.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_cuddling.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_flaming.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_high_five.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_japan_onboarding_favicon.webp
- mobile/android/fenix/app/src/main/res/drawable/ic_kit_bookmarks_empty_state.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_kit_heart.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_kit_shield_off_state.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_kit_shield_on_state.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground_cool.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground_cuddling.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground_flaming.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground_minimal.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground_momo.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground_pixelated.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground_pride.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_foreground_retro_2004.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_launcher_monochrome.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_minimal.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_momo.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_pixelated.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_pride.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_retro_2004.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_sport_logo.webp
- mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_text_normal.xml
- mobile/android/fenix/app/src/main/res/drawable/ic_wordmark_text_private.xml
- mobile/android/fenix/app/src/main/res/drawable/illustration_fox_box_inside_light.xml
- mobile/android/fenix/app/src/main/res/drawable/kit_expressive_full.xml
- mobile/android/fenix/app/src/main/res/drawable/kit_head_protection_blocker_banner.xml
- mobile/android/fenix/app/src/main/res/drawable/kit_sleeping_under_laptop.webp
- mobile/android/fenix/app/src/main/res/drawable/mozac_ic_kit_tab_groups.xml
- mobile/android/fenix/app/src/main/res/drawable/mozac_ic_kit_tab_groups_list_view.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_marketing.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_notifications.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_set_to_default.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_sync.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_sync_qr.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_toolbar_bottom_active.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_toolbar_bottom_inactive.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_toolbar_top_active.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_toolbar_top_inactive.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_tou.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_tou_2.xml
- mobile/android/fenix/app/src/main/res/drawable/nova_onboarding_widget.xml
- mobile/android/fenix/app/src/main/res/drawable/protection_panel_not_protected.xml
- mobile/android/fenix/app/src/main/res/drawable/protection_panel_not_secure.xml
- mobile/android/fenix/app/src/main/res/drawable/review_prompt_negative_button.xml
- mobile/android/fenix/app/src/main/res/drawable/review_prompt_positive_button.xml
- mobile/android/fenix/app/src/main/res/drawable/sports_widget_celebration.xml
The diff was not included because it is too large.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/3867e54…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/3867e54…
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
1
0
[Git][tpo/applications/tor-browser][tor-browser-153.0esr-16.0-1] fixup! TB 40015: [android] Port padlock states for .onion services
by Dan Ballard (@dan) 28 Jul '26
by Dan Ballard (@dan) 28 Jul '26
28 Jul '26
Dan Ballard pushed to branch tor-browser-153.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
323fa639 by clairehurst at 2026-07-28T12:28:57-07:00
fixup! TB 40015: [android] Port padlock states for .onion services
Bug 45115: Fix site security icon for new toolbar
- - - - -
1 changed file:
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddleware.kt
Changes:
=====================================
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddleware.kt
=====================================
@@ -76,6 +76,7 @@ import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.kotlin.applyRegistrableDomainSpan
import mozilla.components.support.ktx.kotlin.getOrigin
import mozilla.components.support.ktx.kotlin.isContentUrl
+import mozilla.components.support.ktx.kotlin.isOnionUrl
import mozilla.components.support.ktx.kotlin.isUrl
import mozilla.components.support.ktx.util.URLStringUtils
import mozilla.components.support.utils.ClipboardHandler
@@ -1273,19 +1274,26 @@ class BrowserToolbarMiddleware(
onClick = object : BrowserToolbarEvent {},
)
} else if (
- selectedTab.content.securityInfo.isSecure &&
- selectedTab.trackingProtection.enabled &&
- !selectedTab.trackingProtection.ignoredOnTrackingProtection
+ selectedTab.content.securityInfo.isSecure
) {
- buildSiteInfoAction(
- drawableResId = iconsR.drawable.mozac_ic_shield_checkmark_24,
- contentDescription = toolbarR.string.mozac_browser_toolbar_content_description_site_info,
- highlighted = highlight,
- onClick = StartPageActions.SiteInfoClicked,
- )
+ if (selectedTab.content.url.isOnionUrl()) {
+ buildSiteInfoAction(
+ drawableResId = iconsR.drawable.mozac_ic_onion,
+ contentDescription = toolbarR.string.mozac_browser_toolbar_content_description_site_info,
+ highlighted = highlight,
+ onClick = StartPageActions.SiteInfoClicked,
+ )
+ } else {
+ buildSiteInfoAction(
+ drawableResId = iconsR.drawable.mozac_ic_lock_24,
+ contentDescription = toolbarR.string.mozac_browser_toolbar_content_description_site_info,
+ highlighted = highlight,
+ onClick = StartPageActions.SiteInfoClicked,
+ )
+ }
} else {
buildSiteInfoAction(
- drawableResId = iconsR.drawable.mozac_ic_shield_slash_24,
+ drawableResId = iconsR.drawable.mozac_ic_lock_slash_critical_24,
contentDescription = toolbarR.string.mozac_browser_toolbar_content_description_site_info,
highlighted = highlight,
onClick = StartPageActions.SiteInfoClicked,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/323fa63…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/323fa63…
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
1
0
[Git][tpo/applications/tor-browser-build][main] Bug 41711: Update our manual machinery for its new home
by boklm (@boklm) 28 Jul '26
by boklm (@boklm) 28 Jul '26
28 Jul '26
boklm pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits:
8b8abf69 by Nicolas Vigier at 2026-07-28T13:41:58+02:00
Bug 41711: Update our manual machinery for its new home
- - - - -
7 changed files:
- doc/how-to-update-the-manual.txt
- projects/browser/build
- projects/manual/README.md
- projects/manual/build
- projects/manual/config
- − projects/manual/packagemanual.py
- tools/update_manual.py
Changes:
=====================================
doc/how-to-update-the-manual.txt
=====================================
@@ -1,9 +1,3 @@
-1. Go to https://gitlab.torproject.org/tpo/web/manual/-/jobs/
-2. Open the latest build stage
-3. Download the artifacts (they come in a .zip file).
-4. Rename it to manual_$PIPELINEID.zip
-5. Upload it to people.tpo
-6. Update projects/manual/config
- 6.1 Change the version to $PIPELINEID
- 6.2 Update the hash in the input_files section
- 6.3 Update the URL if it was different from the previous uploader
+1. Run ./tools/update_manual.py
+2. Upload the new file to tb-build-02.torproject.org:~tb-builder/public_html/
+3. Commit the changes made by the script to projects/manual/config
=====================================
projects/browser/build
=====================================
@@ -184,7 +184,7 @@ tar -C "${TB_STAGE_DIR}" -xf [% c('input_files_by_name/firefox') %]/browser.tar.
find . -exec [% c("touch") %] {} \;
for tbdir in "${TBDIRS[@]}"
do
- find chrome/ | sort | zip -X -@ "$tbdir[% IF c('var/macos') %]/Contents/Resources[% END %]/browser/omni.ja"
+ find chrome/ defaults/preferences/tor-browser-manual.js | sort | zip -X -@ "$tbdir[% IF c('var/macos') %]/Contents/Resources[% END %]/browser/omni.ja"
done
popd
rm -rf $TMP_MANUAL_PATH
=====================================
projects/manual/README.md
=====================================
@@ -10,7 +10,11 @@ So, since the manual doesn't contain binary executables, we decided not to build
it, but to mirror the latest result of the CI to make sure a build stays
reproducible (otherwise, CI artifacts would be deleted after a week).
-However, the CI artifacts include a lot of files used by other Tor sites but not
-from the manual, so we delete them in our build script to save space in the
-builds. Also, the paths to resources need to be updated, because we serve the
-manual as an about page, so we need to convert them to full `chrome://` URIs.
+The download of the latest CI artifacts can be done by the script
+`tools/update_manual.py`.
+
+However, the CI artifacts include a lot of files used by other Tor sites
+but not from the manual, so they need to be deleted, and some of the
+files need to be adapted for offline use. This is done by the script
+`package_marble_build_artifacts.py` (which has tests in
+`test_package_marble_build_artifacts.py`).
=====================================
projects/manual/build
=====================================
@@ -1,19 +1,26 @@
#!/bin/bash
[% c("var/set_default_env") -%]
-mkdir -p chrome/browser/content/browser/manual
-unzip $rootdir/[% c('input_files_by_name/manual') %]
-python3 $rootdir/[% c('input_files_by_name/package_script') %] public chrome/browser/content/browser/manual
+manual_dir='chrome/browser/content/browser/aboutmanual'
+mkdir -p "$manual_dir" manual-src
+unzip -d manual-src $rootdir/[% c('input_files_by_name/manual') %]
+python3 $rootdir/[% c('input_files_by_name/package_script') %] \
+ --in-dir manual-src/public --out-dir "$manual_dir" \
+ --out-locales "$rootdir/supported-locales.txt"
-pushd chrome/browser/content/browser/manual/static
-find -name '*.map' -delete
-rm -rf fonts
-rm -rf css/digital-climate-strike css/images
-# We prune unused images in the Python script, but empty directories remain
-find images -type d -empty -delete
-popd
+# Check for the expected characters, which will also ensure this can
+# form a valid javascript string literal.
+# Note that $() will strip any trailing newlines, if any.
+supported_locales="$(cat "$rootdir/supported-locales.txt")"
+if [[ ! "$supported_locales" =~ ^[a-zA-Z,-]*$ ]]; then
+ echo 'Error: unexpected characters in supported-locales.txt' >&2
+ exit 1
+fi
+
+mkdir -p defaults/preferences
+echo 'pref("torbrowser.manual.available-locales", "'"$supported_locales"'");' > defaults/preferences/tor-browser-manual.js
[% c('tar', {
- tar_src => [ 'chrome' ],
+ tar_src => [ 'chrome', 'defaults' ],
tar_args => '-caf ' _ dest_dir _ '/' _ c('filename'),
}) %]
=====================================
projects/manual/config
=====================================
@@ -1,7 +1,7 @@
# vim: filetype=yaml sw=2
# To update, see doc/how-to-update-the-manual.txt
# Remember to update also the package's hash, with the version!
-version: 321660
+version: 402523
filename: 'manual-[% c("version") %]-[% c("var/build_id") %].tar.[% c("compress_tar") %]'
container:
use_container: 1
@@ -21,8 +21,8 @@ var:
input_files:
- project: container-image
- - URL: 'https://build-sources.tbb.torproject.org/manual_[% c("version") %].zip'
+ - URL: 'https://build-sources.tbb.torproject.org/marble-support_[% c("version") %].zip'
name: manual
- sha256sum: 9adb7d8ca2c9cb7dbd8d13d46135ea9f42636eafd053192fc5e233f2426cd8a3
- - filename: packagemanual.py
+ sha256sum: e0f09c869719bf9dc0ae2761f121cae7cd9b5324f817f2cc0a5861c58442f3ff
+ - filename: package_marble_build_artifacts.py
name: package_script
=====================================
projects/manual/packagemanual.py deleted
=====================================
@@ -1,69 +0,0 @@
-#!/usr/bin/env python3
-from pathlib import Path
-import re
-import sys
-import shutil
-
-
-PAGE_NAME = 'offline-docs'
-STATIC_PATH = 'chrome://browser/content/manual/static'
-
-if len(sys.argv) < 3:
- print(f'Usage: {sys.argv[0]} lektor-out-directory target-directory')
- sys.exit(1)
-
-source = Path(sys.argv[1])
-target = Path(sys.argv[2])
-if not target.exists():
- target.mkdir(exist_ok=True)
-
-static_re = re.compile('"(?:../)*static/([^"]+)"')
-link_re = re.compile('href="../([^"]+)"')
-
-
-def clean_urls(match):
- m = re.match(r'(?:../)?([^/#]+)[/]?[#]?(.*)', match.group(1))
- slug = m.group(1)
- if m.group(2):
- anchor = '_' + m.group(2)
- else:
- anchor = ''
- return f'href="#{slug}{anchor}"'
-
-
-remove_images = []
-for p in (source / 'static/images').glob('**/*'):
- if p.is_file():
- rel = p.relative_to(source)
- remove_images.append(rel)
-
-htmls = source.rglob(f'{PAGE_NAME}/index.html')
-for page in htmls:
- with page.open(encoding='utf8') as f:
- contents = f.read()
-
- remove_images = list(filter(
- lambda im: contents.find(str(im)) == -1, remove_images))
-
- contents = static_re.sub(f'"{STATIC_PATH}/\\1"', contents)
- contents = link_re.sub(clean_urls, contents)
-
- rel = page.relative_to(source)
- dest_name = str(list(rel.parents)[-2].name)
- if dest_name == PAGE_NAME:
- dest_name = 'en'
- dest_name += '.html'
- with (target / dest_name).open('w', encoding='utf8') as f:
- f.write(contents)
-
-
-def ignore_images(path, names):
- return [
- n
- for n in names
- if Path(path, n).relative_to(source) in remove_images
- ]
-
-
-shutil.rmtree(target / 'static', ignore_errors=True)
-shutil.copytree(source / 'static', target / 'static', ignore=ignore_images)
=====================================
tools/update_manual.py
=====================================
@@ -10,7 +10,7 @@ from fetch_changelogs import load_token, AUTH_HEADER
GITLAB = "https://gitlab.torproject.org"
API_URL = f"{GITLAB}/api/v4"
-PROJECT_ID = 23
+PROJECT_ID = 3354
REF_NAME = "main"
@@ -66,7 +66,7 @@ def update_manual(auth_token, base_path):
raise RuntimeError("No usable job found")
pipeline_id = int(job["pipeline"]["id"])
- manual_fname = f"manual_{pipeline_id}.zip"
+ manual_fname = f"marble-support_{pipeline_id}.zip"
url = f"https://build-sources.tbb.torproject.org/{manual_fname}"
r = requests.head(url)
needs_upload = r.status_code != 200
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/8…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/8…
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
1
0
[Git][tpo/applications/tor-browser][tor-browser-153.0esr-16.0-1] 6 commits: fixup! TB 44694: [android] Remove new Tab bar feature
by brizental (@brizental) 28 Jul '26
by brizental (@brizental) 28 Jul '26
28 Jul '26
brizental pushed to branch tor-browser-153.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
eac41a90 by Beatriz Rizental at 2026-07-28T16:18:31+02:00
fixup! TB 44694: [android] Remove new Tab bar feature
Bug 45147: Enable android unit test builds.
- - - - -
94f970fe by Beatriz Rizental at 2026-07-28T16:18:31+02:00
fixup! TB 44098: [android] Disable sync
Bug 45147: Enable android unit test builds.
- - - - -
5202d68f by Beatriz Rizental at 2026-07-28T16:18:31+02:00
fixup! TB 42655: [android] Implement "New circuit for this site" on Android
Bug 45147: Enable android unit test builds.
- - - - -
de1a09f1 by Beatriz Rizental at 2026-07-28T16:18:31+02:00
fixup! [android] Disable features and functionality
Bug 45147: Enable android unit test builds.
- - - - -
092ce022 by Beatriz Rizental at 2026-07-28T16:18:31+02:00
fixup! [android] Delete unused media
Bug 45147: Enable android unit test builds.
- - - - -
a054fea8 by Beatriz Rizental at 2026-07-28T16:18:31+02:00
fixup! [android] Modify UI/UX
Bug 45147: Enable android unit test builds.
- - - - -
7 changed files:
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/bookmarks/BookmarksMiddlewareTest.kt
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/menu/compose/MainMenuTest.kt
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/MetricsUtilsTest.kt
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddlewareTest.kt
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/setup/store/ChecklistItemTest.kt
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/DefaultCookieBannerDetailsControllerTest.kt
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/tabstray/TabManagerCfrControllerTest.kt
Changes:
=====================================
mobile/android/fenix/app/src/test/java/org/mozilla/fenix/bookmarks/BookmarksMiddlewareTest.kt
=====================================
@@ -1230,31 +1230,8 @@ class BookmarksMiddlewareTest {
assertFalse(exited)
}
- @Test
- fun `GIVEN current screen is an empty list and the top-level is loaded WHEN sign into sync is clicked THEN navigate to sign into sync `() =
- runTest {
- coEvery {
- bookmarksStorage.countBookmarksInTrees(
- listOf(
- BookmarkRoot.Menu.id,
- BookmarkRoot.Toolbar.id,
- BookmarkRoot.Unfiled.id,
- ),
- )
- } returns 0u
- coEvery { bookmarksStorage.getTree(BookmarkRoot.Mobile.id) } returns Result.success(
- generateBookmarkTree(),
- )
- var navigated = false
- navigateToSignIntoSync = { navigated = true }
- val middleware = buildMiddleware(this)
- val store = middleware.makeStore()
- testScheduler.advanceUntilIdle()
-
- store.dispatch(SignIntoSyncClicked)
-
- assertTrue(navigated)
- }
+ // tor-browser#44098: sign-into-sync from bookmarks was removed, along with the
+ // SignIntoSyncClicked action this test used to dispatch.
@Test
fun `GIVEN current screen is a subfolder WHEN close is clicked THEN exit bookmarks `() =
=====================================
mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/menu/compose/MainMenuTest.kt
=====================================
@@ -94,6 +94,7 @@ class MainMenuTest {
onIPProtectionClick = {},
onIPProtectionNavigate = {},
onShareButtonClick = {},
+ onNewCircuitButtonClick = {},
extensionsMenuItemDescription = null,
moreSettingsSubmenu = {},
extensionSubmenu = {},
=====================================
mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/metrics/MetricsUtilsTest.kt
=====================================
@@ -4,7 +4,6 @@
package org.mozilla.fenix.components.metrics
-import com.google.android.gms.ads.identifier.AdvertisingIdClient
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
import com.google.android.gms.common.GooglePlayServicesRepairableException
import io.mockk.every
@@ -13,6 +12,7 @@ import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
+import org.junit.Ignore
import org.junit.Test
import java.io.IOException
@@ -34,21 +34,18 @@ class MetricsUtilsTest {
@Test
fun `getAdvertisingID() returns null if the API returns null info`() {
- val mockInfo: AdvertisingIdClient.Info = mockk()
- every { mockInfo.id } returns null
-
- assertNull(MetricsUtils.getAdvertisingID { mockInfo.id })
+ assertNull(MetricsUtils.getAdvertisingID { null })
}
+ @Ignore("tor-browser#40014: the Google Advertising ID is neutered, so getAdvertisingID() always returns null")
@Test
fun `getAdvertisingID() returns a valid string if the API returns a valid ID`() {
val testId = "test-value-id"
- val mockInfo: AdvertisingIdClient.Info = mockk()
- every { mockInfo.id } returns testId
- assertEquals(testId, MetricsUtils.getAdvertisingID({ mockInfo.id }))
+ assertEquals(testId, MetricsUtils.getAdvertisingID({ testId }))
}
+ @Ignore("tor-browser#40014: getHashedIdentifier() derives from getAdvertisingID(), which always returns null")
@Test
fun `getHashedIdentifier() returns a hashed identifier`() = runTest {
val testId = "test-value-id"
=====================================
mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddlewareTest.kt
=====================================
@@ -224,7 +224,7 @@ class BrowserToolbarMiddlewareTest {
coEvery { bookmarksStorage.getBookmarksWithUrl(any()) } returns Result.success(listOf(mockk()))
settings.shouldUseBottomToolbar = false
settings.shouldUseExpandedToolbar = false
- settings.isTabStripEnabled = false
+ // settings.isTabStripEnabled = false
}
@Test
@@ -1266,7 +1266,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN on a small screen with tabstrip is disabled and not using the extended layout THEN don't show a share button as page end action`() {
- settings.isTabStripEnabled = false
+ // settings.isTabStripEnabled = false
settings.shouldUseExpandedToolbar = false
val browserScreenStore = buildBrowserScreenStore()
@@ -1278,7 +1278,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN on a wide screen with tabstrip is disabled THEN show a share button as page end action`() {
- settings.isTabStripEnabled = false
+ // settings.isTabStripEnabled = false
val browserScreenStore = buildBrowserScreenStore()
val middleware = buildMiddleware(
browserScreenStore = browserScreenStore,
@@ -1292,7 +1292,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN on a large screen with tabstrip is enabled THEN don't show a share button as page end action`() {
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
val browserScreenStore = buildBrowserScreenStore()
val middleware = buildMiddleware(appStore, browserScreenStore)
val toolbarStore = buildStore(middleware)
@@ -1302,7 +1302,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN the current tab shows a content page WHEN the share shortcut is clicked THEN record telemetry and start sharing the local resource`() = runTest(testDispatcher) {
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
settings.shouldUseExpandedToolbar = false
settings.toolbarSimpleShortcutKey = ShortcutType.SHARE.value
val browserScreenStore = buildBrowserScreenStore()
@@ -1337,7 +1337,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN the current tab shows a remote PDF WHEN the share shortcut is clicked THEN record telemetry and start sharing the remote resource`() {
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
settings.shouldUseExpandedToolbar = false
settings.toolbarSimpleShortcutKey = ShortcutType.SHARE.value
val browserScreenStore = buildBrowserScreenStore()
@@ -1382,7 +1382,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN the current tab shows a normal webpage WHEN the share shortcut is clicked THEN record telemetry and open the share dialog`() {
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
settings.shouldUseExpandedToolbar = false
settings.toolbarSimpleShortcutKey = ShortcutType.SHARE.value
settings.nativeShareSheetEnabled = false
@@ -1430,7 +1430,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `WHEN the share shortcut is clicked THEN the share use case is invoked with the current tab's details`() {
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
settings.shouldUseExpandedToolbar = false
settings.toolbarSimpleShortcutKey = ShortcutType.SHARE.value
@@ -1471,7 +1471,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN on a small width with tabstrip is enabled and not using the extended layout THEN don't show a share button as browser end action`() {
settings.shouldUseExpandedToolbar = false
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
val browserScreenStore = buildBrowserScreenStore()
val middleware = buildMiddleware(
browserScreenStore = browserScreenStore,
@@ -1491,7 +1491,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN expanded toolbar with tabstrip and tall window WHEN changing to short window THEN show new tab, tab counter and menu`() = runTest(testDispatcher) {
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
settings.shouldUseExpandedToolbar = true
val browserScreenStore = buildBrowserScreenStore()
var isWideScreen = false
@@ -1526,7 +1526,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN on a wide window with tabstrip and extended layout enabled THEN don't show a share button as browser end action`() {
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
settings.shouldUseExpandedToolbar = true
val browserScreenStore = buildBrowserScreenStore()
@@ -1539,7 +1539,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `WHEN cycling through tall window and wide window THEN update what end page actions should be shown`() {
val appStore = AppStore()
- settings.isTabStripEnabled = false
+ // settings.isTabStripEnabled = false
settings.shouldUseExpandedToolbar = false
val readerModeStatus: ReaderModeStatus = mockk(relaxed = true) {
every { isAvailable } returns true
@@ -3156,7 +3156,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN share shortcut is selected THEN update end page actions without share action`() = runTest(testDispatcher) {
- settings.isTabStripEnabled = false
+ // settings.isTabStripEnabled = false
settings.toolbarSimpleShortcutKey = ShortcutType.SHARE.value
val browserScreenStore = buildBrowserScreenStore()
val middleware = buildMiddleware(
@@ -3353,7 +3353,7 @@ class BrowserToolbarMiddlewareTest {
@Test
fun `GIVEN simple toolbar use share shortcut AND wide window with tabstrip enabled WHEN initializing toolbar THEN only show one Share in end browser actions`() {
- settings.isTabStripEnabled = true
+ // settings.isTabStripEnabled = true
settings.toolbarSimpleShortcutKey = ShortcutType.SHARE.value
val middleware = buildMiddleware(
=====================================
mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/setup/store/ChecklistItemTest.kt
=====================================
@@ -7,6 +7,7 @@ package org.mozilla.fenix.home.setup.store
import androidx.annotation.StringRes
import io.mockk.every
import io.mockk.mockk
+import mozilla.components.lib.crash.R as crashR
import org.junit.Assert.assertEquals
import org.junit.Test
import org.mozilla.fenix.R
@@ -149,7 +150,7 @@ class ChecklistItemTest {
ChecklistItem.Task(
type = ChecklistItem.Task.Type.SIGN_IN,
title = R.string.setup_checklist_task_account_sync,
- icon = R.drawable.ic_fx_accounts_avatar,
+ icon = crashR.drawable.mozac_lib_crash_notification,
isCompleted = isCompleted,
),
)
@@ -185,7 +186,7 @@ class ChecklistItemTest {
ChecklistItem.Task(
type = ChecklistItem.Task.Type.SIGN_IN,
title = R.string.setup_checklist_task_account_sync,
- icon = R.drawable.ic_fx_accounts_avatar,
+ icon = crashR.drawable.mozac_lib_crash_notification,
isCompleted = isCompleted,
),
),
@@ -258,7 +259,7 @@ class ChecklistItemTest {
ChecklistItem.Task(
type = ChecklistItem.Task.Type.SIGN_IN,
title = R.string.setup_checklist_task_account_sync,
- icon = R.drawable.ic_fx_accounts_avatar,
+ icon = crashR.drawable.mozac_lib_crash_notification,
isCompleted = isCompleted,
),
),
=====================================
mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/quicksettings/protections/cookiebanners/DefaultCookieBannerDetailsControllerTest.kt
=====================================
@@ -220,46 +220,7 @@ internal class DefaultCookieBannerDetailsControllerTest {
}
}
- @Test
- fun `GIVEN cookie banner mode is site not supported WHEN handleRequestSiteSupportPressed THEN request report site domain`() =
- runTest(testDispatcher) {
- val store = BrowserStore(
- BrowserState(
- customTabs = listOf(
- createCustomTab(
- url = "https://www.mozilla.org",
- id = "mozilla",
- ),
- ),
- ),
- )
- every { testContext.components.core.store } returns store
- coEvery { controller.getTabDomain(any()) } returns "mozilla.org"
- every { protectionsStore.dispatch(any()) } returns mockk()
-
- val job = Pings.cookieBannerReportSite.testBeforeNextSubmit {
- assertNotNull(CookieBanners.reportSiteDomain.testGetValue())
- assertEquals("mozilla.org", CookieBanners.reportSiteDomain.testGetValue())
- }
- controller.handleRequestSiteSupportPressed()
- testScheduler.advanceUntilIdle()
-
- job.join()
-
- assertNotNull(CookieBanners.reportDomainSiteButton.testGetValue())
- testScheduler.advanceUntilIdle()
- coVerifyOrder {
- protectionsStore.dispatch(
- ProtectionsAction.RequestReportSiteDomain(
- "mozilla.org",
- ),
- )
- protectionsStore.dispatch(
- ProtectionsAction.UpdateCookieBannerMode(
- cookieBannerUIMode = CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED,
- ),
- )
- cookieBannersStorage.saveSiteDomain("mozilla.org")
- }
- }
+ // tor-browser#42089: the ability to submit site support requests was removed, along with
+ // handleRequestSiteSupportPressed(), ProtectionsAction.RequestReportSiteDomain and
+ // CookieBannerUIMode.REQUEST_UNSUPPORTED_SITE_SUBMITTED this test used to exercise.
}
=====================================
mobile/android/fenix/app/src/test/java/org/mozilla/fenix/tabstray/TabManagerCfrControllerTest.kt
=====================================
@@ -100,7 +100,7 @@ class TabManagerCfrControllerTest {
@Test
fun `GIVEN an adjacent tab WHEN maybeMarkTabSwipeCfrReady is called THEN shouldShowTabSwipeCfr is set`() {
settings.hasShownTabSwipeCFR = false
- settings.isTabStripEnabled = false
+ // settings.isTabStripEnabled = false
settings.isSwipeToolbarToSwitchTabsEnabled = true
settings.shouldShowTabSwipeCFR = false
val adjacentTab = createTab(id = "tab2", url = "")
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/51b776…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/51b776…
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
1
0
[Git][tpo/applications/mullvad-browser][mullvad-browser-153.0esr-16.0-1] BB 45085: [android] Confine GooglePlayIntegrityClient to Components.kt
by brizental (@brizental) 28 Jul '26
by brizental (@brizental) 28 Jul '26
28 Jul '26
brizental pushed to branch mullvad-browser-153.0esr-16.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
7e4d093f by Beatriz Rizental at 2026-07-28T11:20:40-03:00
BB 45085: [android] Confine GooglePlayIntegrityClient to Components.kt
Uplifting: https://phabricator.services.mozilla.com/D313912
- - - - -
4 changed files:
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/ClientUUID.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/llm/Llm.kt
Changes:
=====================================
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt
=====================================
@@ -583,7 +583,7 @@ open class FenixApplication : Application(), Provider, ThemeProvider {
}
runOnVisualCompleteness(queue) {
GlobalScope.launch(IO) {
- components.integrityClient.warmUp()
+ components.warmUpIntegrityClient()
}
}
}
=====================================
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/ClientUUID.kt
=====================================
@@ -7,7 +7,6 @@ package org.mozilla.fenix.components
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
-import mozilla.components.lib.integrity.googleplay.RequestHashProvider
import mozilla.components.lib.llm.mlpa.UserIdProvider
import mozilla.components.lib.llm.mlpa.service.UserId
import mozilla.components.support.ktx.kotlin.toHexString
@@ -39,9 +38,15 @@ fun interface Hasher {
/**
* Generates and persists a stable per-install UUID, used to identify this client
- * consistently across [UserIdProvider] and [RequestHashProvider] consumers.
+ * consistently across [UserIdProvider] consumers and other callers that need a
+ * stable per-request hash derived from that UUID.
*/
-interface ClientUUID : UserIdProvider, RequestHashProvider {
+interface ClientUUID : UserIdProvider {
+ /**
+ * Generates a hash derived from the client's stable UUID.
+ */
+ fun generateHash(): String
+
companion object {
/**
* Convenience initializer that creates a [SharedPreferences] to be used by [ClientUUID].
=====================================
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
=====================================
@@ -19,6 +19,7 @@ import kotlinx.coroutines.MainScope
import kotlinx.coroutines.SupervisorJob
import mozilla.components.concept.ai.controls.AIFeatureBlock
import mozilla.components.concept.ai.controls.AIFeatureRegistry
+import mozilla.components.concept.integrity.IntegrityClient
import mozilla.components.feature.addons.AddonManager
import mozilla.components.feature.addons.amo.AMOAddonsProvider
import mozilla.components.feature.addons.migration.DefaultSupportedAddonsChecker
@@ -32,6 +33,8 @@ import mozilla.components.lib.ai.controls.default
import mozilla.components.lib.crash.store.CrashAction
import mozilla.components.lib.crash.store.CrashMiddleware
import mozilla.components.lib.integrity.googleplay.GooglePlayIntegrityClient
+import mozilla.components.lib.integrity.googleplay.IntegrityConsumer
+import mozilla.components.lib.integrity.googleplay.RequestHashProvider
import mozilla.components.lib.llm.mlpa.MlpaTokenStorage
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import mozilla.components.service.fxrelay.eligibility.RelayEligibilityStore
@@ -434,14 +437,25 @@ class Components(private val context: Context) {
)
}
- val integrityClient by lazyMonitored {
+ private val googlePlayIntegrityClient by lazyMonitored {
GooglePlayIntegrityClient.create(
context = context,
projectNumberToken = BuildConfig.GPS_INTEGRITY_TOKEN,
- requestHashProvider = clientUUID,
+ requestHashProvider = RequestHashProvider { clientUUID.generateHash() },
)
}
+ val integrityClient: IntegrityClient by lazyMonitored {
+ googlePlayIntegrityClient.forConsumer(IntegrityConsumer.Summarize)
+ }
+
+ /**
+ * Eagerly initializes the underlying Play Integrity token provider. This is exposed
+ * separately from [integrityClient] because warm-up is specific to the Google
+ * Play-backed implementation and isn't part of the [IntegrityClient] concept.
+ */
+ suspend fun warmUpIntegrityClient(): Boolean = googlePlayIntegrityClient.warmUp()
+
val termsOfUsePromptRepository by lazyMonitored {
DefaultTermsOfUsePromptRepository(settings)
}
=====================================
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/llm/Llm.kt
=====================================
@@ -5,8 +5,7 @@
package org.mozilla.fenix.components.llm
import mozilla.components.concept.fetch.Client
-import mozilla.components.lib.integrity.googleplay.GooglePlayIntegrityClient
-import mozilla.components.lib.integrity.googleplay.IntegrityConsumer
+import mozilla.components.concept.integrity.IntegrityClient
import mozilla.components.lib.llm.mlpa.MlpaLlmProvider
import mozilla.components.lib.llm.mlpa.MlpaTokenProvider
import mozilla.components.lib.llm.mlpa.MlpaTokenStorage
@@ -25,7 +24,7 @@ class Llm(
private val client: Client,
private val storage: MlpaTokenStorage,
private val fxaTokenProvider: FxaAccessTokenProvider,
- private val integrityClient: GooglePlayIntegrityClient,
+ private val integrityClient: IntegrityClient,
private val userIdProvider: UserIdProvider,
) {
@@ -36,7 +35,7 @@ class Llm(
MlpaTokenProvider.choose(
MlpaTokenProvider.fxaTokenProvider(fxaTokenProvider),
MlpaTokenProvider.mlpaIntegrityHandshake(
- integrityClient = integrityClient.forConsumer(IntegrityConsumer.Summarize),
+ integrityClient = integrityClient,
authenticationService = fenixMlpaService,
userIdProvider = userIdProvider,
storage = storage,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/7e4…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/7e4…
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
1
0
[Git][tpo/applications/mullvad-browser][mullvad-browser-153.0esr-16.0-1] BB 44908: Do not read AutoConfig from /etc/firefox when --disable-system-preferences
by brizental (@brizental) 28 Jul '26
by brizental (@brizental) 28 Jul '26
28 Jul '26
brizental pushed to branch mullvad-browser-153.0esr-16.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
16c34621 by Beatriz Rizental at 2026-07-28T11:19:42-03:00
BB 44908: Do not read AutoConfig from /etc/firefox when --disable-system-preferences
Uplifting: https://phabricator.services.mozilla.com/D314532
- - - - -
1 changed file:
- extensions/pref/autoconfig/src/nsReadConfig.cpp
Changes:
=====================================
extensions/pref/autoconfig/src/nsReadConfig.cpp
=====================================
@@ -243,7 +243,7 @@ nsresult nsReadConfig::openAndEvaluateJSFile(const char* aFileName,
nsCOMPtr<nsIInputStream> inStr;
if (isBinDir) {
nsCOMPtr<nsIFile> jsFile;
-#if defined(MOZ_WIDGET_GTK)
+#if defined(MOZ_WIDGET_GTK) && defined(MOZ_SYSTEM_PREFERENCES)
bool exists;
rv =
@@ -257,15 +257,15 @@ nsresult nsReadConfig::openAndEvaluateJSFile(const char* aFileName,
if (NS_FAILED(rv)) return rv;
if (!exists) {
-#endif // defined(MOZ_WIDGET_GTK)
+#endif // defined(MOZ_WIDGET_GTK) && defined(MOZ_SYSTEM_PREFERENCES)
rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(jsFile));
if (NS_FAILED(rv)) return rv;
rv = jsFile->AppendNative(nsDependentCString(aFileName));
if (NS_FAILED(rv)) return rv;
-#if defined(MOZ_WIDGET_GTK)
+#if defined(MOZ_WIDGET_GTK) && defined(MOZ_SYSTEM_PREFERENCES)
}
-#endif // defined(MOZ_WIDGET_GTK)
+#endif // defined(MOZ_WIDGET_GTK) && defined(MOZ_SYSTEM_PREFERENCES)
rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), jsFile);
if (NS_FAILED(rv)) return rv;
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/16c…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/16c…
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
1
0