Dan Ballard pushed to branch tor-browser-128.8.0esr-14.5-1 at The Tor Project / Applications / Tor Browser
Commits: 6199983c by Dan Ballard at 2025-03-13T11:17:04-07:00 fixup! TB 42247: Android helpers for the TorProvider
Bug 41188: Add staging event wiring
- - - - - d9c0e220 by Dan Ballard at 2025-03-13T11:17:04-07:00 fixup! TB 41878: [android] Add standalone Tor Bootstrap
Bug 41188: Add staging event wiring
- - - - - f545b853 by Dan Ballard at 2025-03-13T11:17:04-07:00 fixup! [android] Implement Android-native Connection Assist UI
Bug 41188: Add staging event wiring
- - - - - da17f78c by Dan Ballard at 2025-03-13T11:17:05-07:00 fixup! TB 40597: Implement TorSettings module
Bug 41188: pt1 add android stages
- - - - -
9 changed files:
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt - mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapProgressViewModel.kt - mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorAndroidIntegration.java - + mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorBootstrappingStatus.java - + mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorConnectStage.java - + mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorConnectStageName.java - toolkit/modules/TorAndroidIntegration.sys.mjs - toolkit/modules/TorConnect.sys.mjs
Changes:
===================================== mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt ===================================== @@ -157,6 +157,7 @@ import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.home.HomeFragment import org.mozilla.fenix.tor.UrlQuickLoadViewModel import org.mozilla.geckoview.TorAndroidIntegration +import org.mozilla.geckoview.TorConnectStage
/** * The main activity of the application. The application is primarily a single Activity (this one) @@ -1453,6 +1454,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorAn }
override fun onBootstrapStateChange(state: String) = Unit + override fun onBootstrapStageChange(stage: TorConnectStage) = Unit override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) = Unit override fun onBootstrapComplete() { if (settings().useHtmlConnectionUi) {
===================================== mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapProgressViewModel.kt ===================================== @@ -5,6 +5,7 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData import org.mozilla.fenix.ext.components import org.mozilla.geckoview.TorAndroidIntegration.BootstrapStateChangeListener +import org.mozilla.geckoview.TorConnectStage
class TorBootstrapProgressViewModel( application: Application, @@ -27,6 +28,7 @@ class TorBootstrapProgressViewModel( }
override fun onBootstrapStateChange(state: String?) {} + override fun onBootstrapStageChange(stage: TorConnectStage) = Unit
override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) { this.progress.value = progress.toInt()
===================================== mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt ===================================== @@ -11,6 +11,7 @@ import org.mozilla.fenix.ext.components import org.mozilla.geckoview.TorAndroidIntegration import org.mozilla.geckoview.TorAndroidIntegration.BootstrapStateChangeListener import org.mozilla.geckoview.TorAndroidIntegration.TorLogListener +import org.mozilla.geckoview.TorConnectStage import org.mozilla.geckoview.TorSettings import org.mozilla.geckoview.TorSettings.BridgeBuiltinType import org.mozilla.geckoview.TorSettings.BridgeSource @@ -322,6 +323,8 @@ class TorControllerGV( onTorStatusUpdate(null, newStateVal, null) }
+ override fun onBootstrapStageChange(stage: TorConnectStage) = Unit + // TorEventsBootstrapStateChangeListener override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) { Log.d(TAG, "onBootstrapProgress(progress = $progress, hasWarnings = $hasWarnings)")
===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorAndroidIntegration.java ===================================== @@ -37,7 +37,8 @@ public class TorAndroidIntegration implements BundleEventListener { private static final String EVENT_TOR_STOP = "GeckoView:Tor:StopTor"; private static final String EVENT_MEEK_START = "GeckoView:Tor:StartMeek"; private static final String EVENT_MEEK_STOP = "GeckoView:Tor:StopMeek"; - private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged"; + private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged"; // deprecation path + private static final String EVENT_CONNECT_STAGE_CHANGED = "GeckoView:Tor:ConnectStageChanged"; // replacement path private static final String EVENT_CONNECT_ERROR = "GeckoView:Tor:ConnectError"; private static final String EVENT_BOOTSTRAP_PROGRESS = "GeckoView:Tor:BootstrapProgress"; private static final String EVENT_BOOTSTRAP_COMPLETE = "GeckoView:Tor:BootstrapComplete"; @@ -114,6 +115,7 @@ public class TorAndroidIntegration implements BundleEventListener { EVENT_SETTINGS_READY, EVENT_SETTINGS_CHANGED, EVENT_CONNECT_STATE_CHANGED, + EVENT_CONNECT_STAGE_CHANGED, EVENT_CONNECT_ERROR, EVENT_BOOTSTRAP_PROGRESS, EVENT_BOOTSTRAP_COMPLETE, @@ -150,6 +152,11 @@ public class TorAndroidIntegration implements BundleEventListener { for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { listener.onBootstrapStateChange(state); } + } else if (EVENT_CONNECT_STAGE_CHANGED.equals(event)) { + TorConnectStage stage = new TorConnectStage(message.getBundle("stage")); + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapStageChange(stage); + } } else if (EVENT_CONNECT_ERROR.equals(event)) { String code = message.getString("code"); String msg = message.getString("message"); @@ -629,7 +636,9 @@ public class TorAndroidIntegration implements BundleEventListener { }
public interface BootstrapStateChangeListener { - void onBootstrapStateChange(String state); + void onBootstrapStateChange(String state); // depreaction path + + void onBootstrapStageChange(TorConnectStage stage); // new upgrade
void onBootstrapProgress(double progress, boolean hasWarnings);
===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorBootstrappingStatus.java ===================================== @@ -0,0 +1,14 @@ +package org.mozilla.geckoview; + +import org.mozilla.gecko.util.GeckoBundle; + +// Class to receive BootstrappingStatus object from TorConnect.sys.mjs ~ln698 +public class TorBootstrappingStatus { + public int progress; // percent of bootstrap progress + public boolean hasWarning; // Whether this bootstrap has a warning in the tor log + + public TorBootstrappingStatus(GeckoBundle bundle) { + progress = bundle.getInt("progress"); + hasWarning = bundle.getBoolean("hasWarning"); + } +}
===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorConnectStage.java ===================================== @@ -0,0 +1,48 @@ +package org.mozilla.geckoview; + +import org.mozilla.gecko.util.GeckoBundle; + +// Class to receive ConnectStage object from TorConnect.sys.mjs ~ln677 +public class TorConnectStage { + + public class Error { + public String code; + public String message; + public String phase; + public String reason; + + public Error(GeckoBundle bundle) { + code = bundle.getString("code"); + message = bundle.getString("message"); + phase = bundle.getString("phase"); + reason = bundle.getString("reason"); + } + } + + public TorConnectStageName name; + // The TorConnectStage prior to this bootstrap attempt. Only set during the "Bootstrapping" stage. + public TorConnectStageName bootstrapTrigger; + public Error error; + public String defaultRegion; + public Boolean potentiallyBlocked; + public Boolean tryAgain; + public TorBootstrappingStatus bootstrappingStatus; + + public TorConnectStage(GeckoBundle bundle) { + name = TorConnectStageName.fromString(bundle.getString("name")); + if (bundle.getString("bootstrapTrigger") != null) { + bootstrapTrigger = TorConnectStageName.fromString(bundle.getString("bootstrapTrigger")); + } + defaultRegion = bundle.getString("defaultRegion"); + potentiallyBlocked = bundle.getBoolean("potentiallyBlocked"); + tryAgain = bundle.getBoolean("tryAgain"); + if (bundle.getBundle("error") != null) { + error = new Error(bundle.getBundle("error")); + } + bootstrappingStatus = new TorBootstrappingStatus(bundle.getBundle("bootstrappingStatus")); + } + + public Boolean isBootstrapped() { + return name.isBootstrapped(); + } +}
===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorConnectStageName.java ===================================== @@ -0,0 +1,43 @@ +package org.mozilla.geckoview; + +import java.security.InvalidParameterException; + +public enum TorConnectStageName { + // These names should match entries from TorConnectStage in TorConnect.sys.mjs at ~ln163. + Disabled("Disabled"), + Loading("Loading"), + Start("Start"), + Bootstrapping("Bootstrapping"), + Offline("Offline"), + ChooseRegion("ChooseRegion"), + RegionNotFound("RegionNotFound"), + ConfirmRegion("ConfirmRegion"), + FinalError("FinalError"), + Bootstrapped("Bootstrapped"); + + private String valueText; + + TorConnectStageName(String valueText) { + this.valueText = valueText; + } + + public Boolean isBootstrapped() { + return this == Bootstrapped; + } + + public String getString() { + return this.valueText; + } + + public static TorConnectStageName fromString(String text) { + for (TorConnectStageName tcs : TorConnectStageName.values()) { + if (tcs.valueText.equalsIgnoreCase(text)) { + return tcs; + } + } + if (BuildConfig.BUILD_TYPE == "debug") { + throw new InvalidParameterException("Unknown TorConnectStageName " + text); + } + return null; + } +}
===================================== toolkit/modules/TorAndroidIntegration.sys.mjs ===================================== @@ -25,7 +25,8 @@ const logger = console.createInstance({ const EmittedEvents = Object.freeze({ settingsReady: "GeckoView:Tor:SettingsReady", settingsChanged: "GeckoView:Tor:SettingsChanged", - connectStateChanged: "GeckoView:Tor:ConnectStateChanged", + connectStateChanged: "GeckoView:Tor:ConnectStateChanged", // deprecation path + connectStageChanged: "GeckoView:Tor:ConnectStageChanged", // new replacement path connectError: "GeckoView:Tor:ConnectError", bootstrapProgress: "GeckoView:Tor:BootstrapProgress", bootstrapComplete: "GeckoView:Tor:BootstrapComplete", @@ -106,6 +107,12 @@ class TorAndroidIntegrationImpl { state: subj.wrappedJSObject.state ?? "", }); break; + case lazy.TorConnectTopics.StageChange: + lazy.EventDispatcher.instance.sendRequest({ + type: EmittedEvents.connectStageChanged, + stage: subj.wrappedJSObject ?? "", + }); + break; case lazy.TorConnectTopics.BootstrapProgress: lazy.EventDispatcher.instance.sendRequest({ type: EmittedEvents.bootstrapProgress,
===================================== toolkit/modules/TorConnect.sys.mjs ===================================== @@ -660,6 +660,7 @@ export const InternetStatus = Object.freeze({ Online: 1, });
+// This enum is mirrored for Android in TorConnectStageName.java. Changes should be mirrored there export const TorConnectStage = Object.freeze({ Disabled: "Disabled", Loading: "Loading", @@ -677,6 +678,7 @@ export const TorConnectStage = Object.freeze({ * @typedef {object} ConnectStage * * A summary of the user stage. + * (This class is mirrored for Android in TorConnectStage.java. Changes should be mirrored there) * * @property {string} name - The name of the stage. * @property {string} defaultRegion - The default region to show in the UI. @@ -698,6 +700,7 @@ export const TorConnectStage = Object.freeze({ * @typedef {object} BootstrappingStatus * * The status of a bootstrap. + * (This class is mirrored for Android in TorBootstrapping.java. Changes should be mirrored there) * * @property {number} progress - The percent progress. * @property {boolean} hasWarning - Whether this bootstrap has a warning in the @@ -708,6 +711,7 @@ export const TorConnectStage = Object.freeze({ * @typedef {object} BootstrapError * * Details about the error that caused bootstrapping to fail. + * (This class is mirrored for Android in TorError.java. Changes should be mirrored there) * * @property {string} code - The error code type. * @property {string} message - The error message.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/8fec318...
tbb-commits@lists.torproject.org