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
 - 
d9c0e220
by Dan Ballard at 2025-03-13T11:17:04-07:00
 - 
f545b853
by Dan Ballard at 2025-03-13T11:17:04-07:00
 - 
da17f78c
by Dan Ballard at 2025-03-13T11:17:05-07:00
 
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:
| ... | ... | @@ -157,6 +157,7 @@ import org.mozilla.fenix.components.FenixSnackbar | 
| 157 | 157 |  import org.mozilla.fenix.home.HomeFragment
 | 
| 158 | 158 |  import org.mozilla.fenix.tor.UrlQuickLoadViewModel
 | 
| 159 | 159 |  import org.mozilla.geckoview.TorAndroidIntegration
 | 
| 160 | +import org.mozilla.geckoview.TorConnectStage
 | 
|
| 160 | 161 | |
| 161 | 162 |  /**
 | 
| 162 | 163 |   * 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 | 
| 1453 | 1454 |      }
 | 
| 1454 | 1455 | |
| 1455 | 1456 |      override fun onBootstrapStateChange(state: String) = Unit
 | 
| 1457 | +    override fun onBootstrapStageChange(stage: TorConnectStage) = Unit
 | 
|
| 1456 | 1458 |      override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) = Unit
 | 
| 1457 | 1459 |      override fun onBootstrapComplete() {
 | 
| 1458 | 1460 |          if (settings().useHtmlConnectionUi) {
 | 
| ... | ... | @@ -5,6 +5,7 @@ import androidx.lifecycle.AndroidViewModel | 
| 5 | 5 |  import androidx.lifecycle.MutableLiveData
 | 
| 6 | 6 |  import org.mozilla.fenix.ext.components
 | 
| 7 | 7 |  import org.mozilla.geckoview.TorAndroidIntegration.BootstrapStateChangeListener
 | 
| 8 | +import org.mozilla.geckoview.TorConnectStage
 | 
|
| 8 | 9 | |
| 9 | 10 |  class TorBootstrapProgressViewModel(
 | 
| 10 | 11 |      application: Application,
 | 
| ... | ... | @@ -27,6 +28,7 @@ class TorBootstrapProgressViewModel( | 
| 27 | 28 |      }
 | 
| 28 | 29 | |
| 29 | 30 |      override fun onBootstrapStateChange(state: String?) {}
 | 
| 31 | +    override fun onBootstrapStageChange(stage: TorConnectStage) = Unit
 | 
|
| 30 | 32 | |
| 31 | 33 |      override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) {
 | 
| 32 | 34 |          this.progress.value = progress.toInt()
 | 
| ... | ... | @@ -11,6 +11,7 @@ import org.mozilla.fenix.ext.components | 
| 11 | 11 |  import org.mozilla.geckoview.TorAndroidIntegration
 | 
| 12 | 12 |  import org.mozilla.geckoview.TorAndroidIntegration.BootstrapStateChangeListener
 | 
| 13 | 13 |  import org.mozilla.geckoview.TorAndroidIntegration.TorLogListener
 | 
| 14 | +import org.mozilla.geckoview.TorConnectStage
 | 
|
| 14 | 15 |  import org.mozilla.geckoview.TorSettings
 | 
| 15 | 16 |  import org.mozilla.geckoview.TorSettings.BridgeBuiltinType
 | 
| 16 | 17 |  import org.mozilla.geckoview.TorSettings.BridgeSource
 | 
| ... | ... | @@ -322,6 +323,8 @@ class TorControllerGV( | 
| 322 | 323 |          onTorStatusUpdate(null, newStateVal, null)
 | 
| 323 | 324 |      }
 | 
| 324 | 325 | |
| 326 | +    override fun onBootstrapStageChange(stage: TorConnectStage) = Unit
 | 
|
| 327 | +  | 
|
| 325 | 328 |      // TorEventsBootstrapStateChangeListener
 | 
| 326 | 329 |      override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) {
 | 
| 327 | 330 |          Log.d(TAG, "onBootstrapProgress(progress = $progress, hasWarnings = $hasWarnings)")
 | 
| ... | ... | @@ -37,7 +37,8 @@ public class TorAndroidIntegration implements BundleEventListener { | 
| 37 | 37 |    private static final String EVENT_TOR_STOP = "GeckoView:Tor:StopTor";
 | 
| 38 | 38 |    private static final String EVENT_MEEK_START = "GeckoView:Tor:StartMeek";
 | 
| 39 | 39 |    private static final String EVENT_MEEK_STOP = "GeckoView:Tor:StopMeek";
 | 
| 40 | -  private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged";
 | 
|
| 40 | +  private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged"; // deprecation path
 | 
|
| 41 | +  private static final String EVENT_CONNECT_STAGE_CHANGED = "GeckoView:Tor:ConnectStageChanged"; // replacement path
 | 
|
| 41 | 42 |    private static final String EVENT_CONNECT_ERROR = "GeckoView:Tor:ConnectError";
 | 
| 42 | 43 |    private static final String EVENT_BOOTSTRAP_PROGRESS = "GeckoView:Tor:BootstrapProgress";
 | 
| 43 | 44 |    private static final String EVENT_BOOTSTRAP_COMPLETE = "GeckoView:Tor:BootstrapComplete";
 | 
| ... | ... | @@ -114,6 +115,7 @@ public class TorAndroidIntegration implements BundleEventListener { | 
| 114 | 115 |              EVENT_SETTINGS_READY,
 | 
| 115 | 116 |              EVENT_SETTINGS_CHANGED,
 | 
| 116 | 117 |              EVENT_CONNECT_STATE_CHANGED,
 | 
| 118 | +            EVENT_CONNECT_STAGE_CHANGED,
 | 
|
| 117 | 119 |              EVENT_CONNECT_ERROR,
 | 
| 118 | 120 |              EVENT_BOOTSTRAP_PROGRESS,
 | 
| 119 | 121 |              EVENT_BOOTSTRAP_COMPLETE,
 | 
| ... | ... | @@ -150,6 +152,11 @@ public class TorAndroidIntegration implements BundleEventListener { | 
| 150 | 152 |        for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
 | 
| 151 | 153 |          listener.onBootstrapStateChange(state);
 | 
| 152 | 154 |        }
 | 
| 155 | +    } else if (EVENT_CONNECT_STAGE_CHANGED.equals(event)) {
 | 
|
| 156 | +      TorConnectStage stage = new TorConnectStage(message.getBundle("stage"));
 | 
|
| 157 | +      for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
 | 
|
| 158 | +        listener.onBootstrapStageChange(stage);
 | 
|
| 159 | +      }
 | 
|
| 153 | 160 |      } else if (EVENT_CONNECT_ERROR.equals(event)) {
 | 
| 154 | 161 |        String code = message.getString("code");
 | 
| 155 | 162 |        String msg = message.getString("message");
 | 
| ... | ... | @@ -629,7 +636,9 @@ public class TorAndroidIntegration implements BundleEventListener { | 
| 629 | 636 |    }
 | 
| 630 | 637 | |
| 631 | 638 |    public interface BootstrapStateChangeListener {
 | 
| 632 | -    void onBootstrapStateChange(String state);
 | 
|
| 639 | +    void onBootstrapStateChange(String state); // depreaction path
 | 
|
| 640 | +  | 
|
| 641 | +    void onBootstrapStageChange(TorConnectStage stage); // new upgrade
 | 
|
| 633 | 642 | |
| 634 | 643 |      void onBootstrapProgress(double progress, boolean hasWarnings);
 | 
| 635 | 644 | 
| 1 | +package org.mozilla.geckoview;
 | 
|
| 2 | +  | 
|
| 3 | +import org.mozilla.gecko.util.GeckoBundle;
 | 
|
| 4 | +  | 
|
| 5 | +// Class to receive BootstrappingStatus object from TorConnect.sys.mjs ~ln698
 | 
|
| 6 | +public class TorBootstrappingStatus {
 | 
|
| 7 | +    public int progress; // percent of bootstrap progress
 | 
|
| 8 | +    public boolean hasWarning; //  Whether this bootstrap has a warning in the tor log
 | 
|
| 9 | +  | 
|
| 10 | +    public TorBootstrappingStatus(GeckoBundle bundle) {
 | 
|
| 11 | +        progress = bundle.getInt("progress");
 | 
|
| 12 | +        hasWarning = bundle.getBoolean("hasWarning");
 | 
|
| 13 | +    }
 | 
|
| 14 | +} | 
| 1 | +package org.mozilla.geckoview;
 | 
|
| 2 | +  | 
|
| 3 | +import org.mozilla.gecko.util.GeckoBundle;
 | 
|
| 4 | +  | 
|
| 5 | +// Class to receive ConnectStage object from TorConnect.sys.mjs ~ln677
 | 
|
| 6 | +public class TorConnectStage {
 | 
|
| 7 | +  | 
|
| 8 | +    public class Error {
 | 
|
| 9 | +        public String code;
 | 
|
| 10 | +        public String message;
 | 
|
| 11 | +        public String phase;
 | 
|
| 12 | +        public String reason;
 | 
|
| 13 | +  | 
|
| 14 | +        public Error(GeckoBundle bundle) {
 | 
|
| 15 | +            code = bundle.getString("code");
 | 
|
| 16 | +            message = bundle.getString("message");
 | 
|
| 17 | +            phase = bundle.getString("phase");
 | 
|
| 18 | +            reason = bundle.getString("reason");
 | 
|
| 19 | +        }
 | 
|
| 20 | +    }
 | 
|
| 21 | +  | 
|
| 22 | +    public TorConnectStageName name;
 | 
|
| 23 | +    // The TorConnectStage prior to this bootstrap attempt. Only set during the "Bootstrapping" stage.
 | 
|
| 24 | +    public TorConnectStageName bootstrapTrigger;
 | 
|
| 25 | +    public Error error;
 | 
|
| 26 | +    public String defaultRegion;
 | 
|
| 27 | +    public Boolean potentiallyBlocked;
 | 
|
| 28 | +    public Boolean tryAgain;
 | 
|
| 29 | +    public TorBootstrappingStatus bootstrappingStatus;
 | 
|
| 30 | +  | 
|
| 31 | +    public TorConnectStage(GeckoBundle bundle) {
 | 
|
| 32 | +        name = TorConnectStageName.fromString(bundle.getString("name"));
 | 
|
| 33 | +        if (bundle.getString("bootstrapTrigger") != null) {
 | 
|
| 34 | +            bootstrapTrigger = TorConnectStageName.fromString(bundle.getString("bootstrapTrigger"));
 | 
|
| 35 | +        }
 | 
|
| 36 | +        defaultRegion = bundle.getString("defaultRegion");
 | 
|
| 37 | +        potentiallyBlocked = bundle.getBoolean("potentiallyBlocked");
 | 
|
| 38 | +        tryAgain = bundle.getBoolean("tryAgain");
 | 
|
| 39 | +        if (bundle.getBundle("error") != null) {
 | 
|
| 40 | +            error = new Error(bundle.getBundle("error"));
 | 
|
| 41 | +        }
 | 
|
| 42 | +        bootstrappingStatus = new TorBootstrappingStatus(bundle.getBundle("bootstrappingStatus"));
 | 
|
| 43 | +    }
 | 
|
| 44 | +  | 
|
| 45 | +    public Boolean isBootstrapped() {
 | 
|
| 46 | +        return name.isBootstrapped();
 | 
|
| 47 | +    }
 | 
|
| 48 | +} | 
| 1 | +package org.mozilla.geckoview;
 | 
|
| 2 | +  | 
|
| 3 | +import java.security.InvalidParameterException;
 | 
|
| 4 | +  | 
|
| 5 | +public enum TorConnectStageName {
 | 
|
| 6 | +    // These names should match entries from TorConnectStage in TorConnect.sys.mjs at ~ln163.
 | 
|
| 7 | +    Disabled("Disabled"),
 | 
|
| 8 | +    Loading("Loading"),
 | 
|
| 9 | +    Start("Start"),
 | 
|
| 10 | +    Bootstrapping("Bootstrapping"),
 | 
|
| 11 | +    Offline("Offline"),
 | 
|
| 12 | +    ChooseRegion("ChooseRegion"),
 | 
|
| 13 | +    RegionNotFound("RegionNotFound"),
 | 
|
| 14 | +    ConfirmRegion("ConfirmRegion"),
 | 
|
| 15 | +    FinalError("FinalError"),
 | 
|
| 16 | +    Bootstrapped("Bootstrapped");
 | 
|
| 17 | +  | 
|
| 18 | +    private String valueText;
 | 
|
| 19 | +  | 
|
| 20 | +    TorConnectStageName(String valueText) {
 | 
|
| 21 | +        this.valueText = valueText;
 | 
|
| 22 | +    }
 | 
|
| 23 | +  | 
|
| 24 | +    public Boolean isBootstrapped() {
 | 
|
| 25 | +        return this == Bootstrapped;
 | 
|
| 26 | +    }
 | 
|
| 27 | +  | 
|
| 28 | +    public String getString() {
 | 
|
| 29 | +        return this.valueText;
 | 
|
| 30 | +    }
 | 
|
| 31 | +  | 
|
| 32 | +    public static TorConnectStageName fromString(String text) {
 | 
|
| 33 | +        for (TorConnectStageName tcs : TorConnectStageName.values()) {
 | 
|
| 34 | +            if (tcs.valueText.equalsIgnoreCase(text)) {
 | 
|
| 35 | +                return tcs;
 | 
|
| 36 | +            }
 | 
|
| 37 | +        }
 | 
|
| 38 | +        if (BuildConfig.BUILD_TYPE == "debug") {
 | 
|
| 39 | +            throw new InvalidParameterException("Unknown TorConnectStageName " + text);
 | 
|
| 40 | +        }
 | 
|
| 41 | +        return null;
 | 
|
| 42 | +    }
 | 
|
| 43 | +} | 
| ... | ... | @@ -25,7 +25,8 @@ const logger = console.createInstance({ | 
| 25 | 25 |  const EmittedEvents = Object.freeze({
 | 
| 26 | 26 |    settingsReady: "GeckoView:Tor:SettingsReady",
 | 
| 27 | 27 |    settingsChanged: "GeckoView:Tor:SettingsChanged",
 | 
| 28 | -  connectStateChanged: "GeckoView:Tor:ConnectStateChanged",
 | 
|
| 28 | +  connectStateChanged: "GeckoView:Tor:ConnectStateChanged", // deprecation path
 | 
|
| 29 | +  connectStageChanged: "GeckoView:Tor:ConnectStageChanged", // new replacement path
 | 
|
| 29 | 30 |    connectError: "GeckoView:Tor:ConnectError",
 | 
| 30 | 31 |    bootstrapProgress: "GeckoView:Tor:BootstrapProgress",
 | 
| 31 | 32 |    bootstrapComplete: "GeckoView:Tor:BootstrapComplete",
 | 
| ... | ... | @@ -106,6 +107,12 @@ class TorAndroidIntegrationImpl { | 
| 106 | 107 |            state: subj.wrappedJSObject.state ?? "",
 | 
| 107 | 108 |          });
 | 
| 108 | 109 |          break;
 | 
| 110 | +      case lazy.TorConnectTopics.StageChange:
 | 
|
| 111 | +        lazy.EventDispatcher.instance.sendRequest({
 | 
|
| 112 | +          type: EmittedEvents.connectStageChanged,
 | 
|
| 113 | +          stage: subj.wrappedJSObject ?? "",
 | 
|
| 114 | +        });
 | 
|
| 115 | +        break;
 | 
|
| 109 | 116 |        case lazy.TorConnectTopics.BootstrapProgress:
 | 
| 110 | 117 |          lazy.EventDispatcher.instance.sendRequest({
 | 
| 111 | 118 |            type: EmittedEvents.bootstrapProgress,
 | 
| ... | ... | @@ -660,6 +660,7 @@ export const InternetStatus = Object.freeze({ | 
| 660 | 660 |    Online: 1,
 | 
| 661 | 661 |  });
 | 
| 662 | 662 | |
| 663 | +// This enum is mirrored for Android in TorConnectStageName.java. Changes should be mirrored there
 | 
|
| 663 | 664 |  export const TorConnectStage = Object.freeze({
 | 
| 664 | 665 |    Disabled: "Disabled",
 | 
| 665 | 666 |    Loading: "Loading",
 | 
| ... | ... | @@ -677,6 +678,7 @@ export const TorConnectStage = Object.freeze({ | 
| 677 | 678 |   * @typedef {object} ConnectStage
 | 
| 678 | 679 |   *
 | 
| 679 | 680 |   * A summary of the user stage.
 | 
| 681 | + * (This class is mirrored for Android in TorConnectStage.java. Changes should be mirrored there)
 | 
|
| 680 | 682 |   *
 | 
| 681 | 683 |   * @property {string} name - The name of the stage.
 | 
| 682 | 684 |   * @property {string} defaultRegion - The default region to show in the UI.
 | 
| ... | ... | @@ -698,6 +700,7 @@ export const TorConnectStage = Object.freeze({ | 
| 698 | 700 |   * @typedef {object} BootstrappingStatus
 | 
| 699 | 701 |   *
 | 
| 700 | 702 |   * The status of a bootstrap.
 | 
| 703 | + * (This class is mirrored for Android in TorBootstrapping.java. Changes should be mirrored there)
 | 
|
| 701 | 704 |   *
 | 
| 702 | 705 |   * @property {number} progress - The percent progress.
 | 
| 703 | 706 |   * @property {boolean} hasWarning - Whether this bootstrap has a warning in the
 | 
| ... | ... | @@ -708,6 +711,7 @@ export const TorConnectStage = Object.freeze({ | 
| 708 | 711 |   * @typedef {object} BootstrapError
 | 
| 709 | 712 |   *
 | 
| 710 | 713 |   * Details about the error that caused bootstrapping to fail.
 | 
| 714 | + * (This class is mirrored for Android in TorError.java. Changes should be mirrored there)
 | 
|
| 711 | 715 |   *
 | 
| 712 | 716 |   * @property {string} code - The error code type.
 | 
| 713 | 717 |   * @property {string} message - The error message.
 |