[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-115.6.0esr-13.5-1] 2 commits: fixup! Bug 42247: Android helpers for the TorProvider

Pier Angelo Vendrame (@pierov) git at gitlab.torproject.org
Wed Dec 20 17:50:59 UTC 2023



Pier Angelo Vendrame pushed to branch tor-browser-115.6.0esr-13.5-1 at The Tor Project / Applications / Tor Browser


Commits:
1edf6cd0 by Pier Angelo Vendrame at 2023-12-20T17:50:17+00:00
fixup! Bug 42247: Android helpers for the TorProvider

Some wiring for TorSettings and TorConnect stuff and fixes to the one I
created previously.

- - - - -
e9cc4840 by Dan Ballard at 2023-12-20T17:50:17+00:00
fixup! Bug 42247: Android helpers for the TorProvider

Bug 42301: fix and implement loading settings and saving them to TorSettings.sys.mjs from Java

- - - - -


6 changed files:

- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
- + mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java
- + mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java
- + mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java
- toolkit/modules/TorAndroidIntegration.sys.mjs


Changes:

=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
=====================================
@@ -1008,6 +1008,14 @@ public final class GeckoRuntime implements Parcelable {
     return mPushController;
   }
 
+  /**
+   * Get the Tor integration controller for this runtime.
+   */
+  @UiThread
+  public @NonNull TorIntegrationAndroid getTorIntegrationController() {
+    return mTorIntegration;
+  }
+
   /**
    * Appends notes to crash report.
    *


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
=====================================
@@ -9,6 +9,10 @@ package org.mozilla.geckoview;
 import android.content.Context;
 import android.util.Log;
 
+import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
@@ -22,9 +26,9 @@ import java.nio.file.attribute.PosixFilePermission;
 import java.nio.file.attribute.PosixFilePermissions;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
@@ -32,13 +36,27 @@ import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 
-/* package */ class TorIntegrationAndroid implements BundleEventListener {
+import org.mozilla.geckoview.androidlegacysettings.TorLegacyAndroidSettings;
+
+public class TorIntegrationAndroid implements BundleEventListener {
     private static final String TAG = "TorIntegrationAndroid";
 
-    private static final String TOR_EVENT_START = "GeckoView:Tor:StartTor";
-    private static final String TOR_EVENT_STOP = "GeckoView:Tor:StopTor";
-    private static final String MEEK_EVENT_START = "GeckoView:Tor:StartMeek";
-    private static final String MEEK_EVENT_STOP = "GeckoView:Tor:StopMeek";
+    // Events we listen to
+    private static final String EVENT_TOR_START = "GeckoView:Tor:StartTor";
+    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";
+
+    // Events we emit
+    private static final String EVENT_SETTINGS_GET = "GeckoView:Tor:SettingsGet";
+    private static final String EVENT_SETTINGS_SET = "GeckoView:Tor:SettingsSet";
+    private static final String EVENT_SETTINGS_APPLY = "GeckoView:Tor:SettingsApply";
+    private static final String EVENT_SETTINGS_SAVE = "GeckoView:Tor:SettingsSave";
+    private static final String EVENT_BOOTSTRAP_BEGIN = "GeckoView:Tor:BootstrapBegin";
+    private static final String EVENT_BOOTSTRAP_BEGIN_AUTO = "GeckoView:Tor:BootstrapBeginAuto";
+    private static final String EVENT_BOOTSTRAP_CANCEL = "GeckoView:Tor:BootstrapCancel";
+    private static final String EVENT_BOOTSTRAP_GET_STATE = "GeckoView:Tor:BootstrapGetState";
+    private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady";
 
     private static final String CONTROL_PORT_FILE = "/control-ipc";
     private static final String SOCKS_FILE = "/socks-ipc";
@@ -63,7 +81,9 @@ import org.mozilla.gecko.util.GeckoBundle;
     private final HashMap<Integer, MeekTransport> mMeeks = new HashMap<>();
     private int mMeekCounter;
 
-    public TorIntegrationAndroid(Context context) {
+    private TorSettings mSettings = null;
+
+    /* package */ TorIntegrationAndroid(Context context) {
         mLibraryDir = context.getApplicationInfo().nativeLibraryDir;
         mCacheDir = context.getCacheDir().toPath();
         mIpcDirectory = mCacheDir + "/tor-private";
@@ -71,7 +91,7 @@ import org.mozilla.gecko.util.GeckoBundle;
         registerListener();
     }
 
-    public synchronized void shutdown() {
+    /* package */ synchronized void shutdown() {
         // FIXME: It seems this never gets called
         if (mTorProcess != null) {
             mTorProcess.shutdown();
@@ -83,22 +103,36 @@ import org.mozilla.gecko.util.GeckoBundle;
         EventDispatcher.getInstance()
                 .registerUiThreadListener(
                         this,
-                        TOR_EVENT_START,
-                        MEEK_EVENT_START,
-                        MEEK_EVENT_STOP);
+                        EVENT_TOR_START,
+                        EVENT_MEEK_START,
+                        EVENT_MEEK_STOP,
+                        EVENT_SETTINGS_READY);
     }
 
     @Override // BundleEventListener
     public synchronized void handleMessage(
             final String event, final GeckoBundle message, final EventCallback callback) {
-        if (TOR_EVENT_START.equals(event)) {
+        if (EVENT_TOR_START.equals(event)) {
             startDaemon(message, callback);
-        } else if (TOR_EVENT_STOP.equals(event)) {
+        } else if (EVENT_TOR_STOP.equals(event)) {
             stopDaemon(message, callback);
-        } else if (MEEK_EVENT_START.equals(event)) {
+        } else if (EVENT_MEEK_START.equals(event)) {
             startMeek(message, callback);
-        } else if (MEEK_EVENT_STOP.equals(event)) {
+        } else if (EVENT_MEEK_STOP.equals(event)) {
             stopMeek(message, callback);
+        } else if (EVENT_SETTINGS_READY.equals(event)) {
+            loadSettings(message);
+        }
+    }
+
+    private void loadSettings(GeckoBundle message) {
+        if (TorLegacyAndroidSettings.unmigrated()) {
+            mSettings = TorLegacyAndroidSettings.loadTorSettings();
+            setSettings(mSettings);
+            TorLegacyAndroidSettings.setMigrated();
+        } else {
+            GeckoBundle bundle = message.getBundle("settings");
+            mSettings = new TorSettings(bundle);
         }
     }
 
@@ -145,9 +179,9 @@ import org.mozilla.gecko.util.GeckoBundle;
     }
 
     class TorProcess extends Thread {
-        private static final String TOR_EVENT_STARTED = "GeckoView:Tor:TorStarted";
-        private static final String TOR_EVENT_START_FAILED = "GeckoView:Tor:TorStartFailed";
-        private static final String TOR_EVENT_EXITED = "GeckoView:Tor:TorExited";
+        private static final String EVENT_TOR_STARTED = "GeckoView:Tor:TorStarted";
+        private static final String EVENT_TOR_START_FAILED = "GeckoView:Tor:TorStartFailed";
+        private static final String EVENT_TOR_EXITED = "GeckoView:Tor:TorExited";
         private final String mHandle;
         private Process mProcess = null;
 
@@ -202,14 +236,14 @@ import org.mozilla.gecko.util.GeckoBundle;
                 final GeckoBundle data = new GeckoBundle(2);
                 data.putString("handle", mHandle);
                 data.putString("error", e.getMessage());
-                EventDispatcher.getInstance().dispatch(TOR_EVENT_START_FAILED, data);
+                EventDispatcher.getInstance().dispatch(EVENT_TOR_START_FAILED, data);
                 return;
             }
             Log.i(TAG, "Tor process " + mHandle + " started.");
             {
                 final GeckoBundle data = new GeckoBundle(1);
                 data.putString("handle", mHandle);
-                EventDispatcher.getInstance().dispatch(TOR_EVENT_STARTED, data);
+                EventDispatcher.getInstance().dispatch(EVENT_TOR_STARTED, data);
             }
             try {
                 BufferedReader reader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
@@ -232,7 +266,7 @@ import org.mozilla.gecko.util.GeckoBundle;
             // FIXME: We usually don't reach this when the application is killed!
             // So, we don't do our cleanup.
             Log.i(TAG, "Tor process " + mHandle + " has exited.");
-            EventDispatcher.getInstance().dispatch(TOR_EVENT_EXITED, data);
+            EventDispatcher.getInstance().dispatch(EVENT_TOR_EXITED, data);
         }
 
         private void cleanIpcDirectory() {
@@ -432,4 +466,71 @@ import org.mozilla.gecko.util.GeckoBundle;
             }
         }
     }
+
+    public static class BootstrapState {
+        // FIXME: We can do better than this :)
+        public GeckoBundle mBundle;
+
+        BootstrapState(GeckoBundle bundle) {
+            mBundle = bundle;
+        }
+    }
+
+    public interface BootstrapStateChangeListener {
+        void onBootstrapStateChange(BootstrapState state);
+    }
+
+    public @NonNull GeckoResult<GeckoBundle> getSettings() {
+        return EventDispatcher.getInstance().queryBundle(EVENT_SETTINGS_GET);
+    }
+
+    public @NonNull GeckoResult<Void> setSettings(final TorSettings settings) {
+        return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SET, settings.asGeckoBundle());
+    }
+
+    public @NonNull GeckoResult<Void> applySettings() {
+        return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_APPLY);
+    }
+
+    public @NonNull GeckoResult<Void> saveSettings() {
+        return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SAVE);
+    }
+
+    public @NonNull GeckoResult<Void> beginBootstrap() {
+        return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN);
+    }
+
+    public @NonNull GeckoResult<Void> beginAutoBootstrap(final String countryCode) {
+        final GeckoBundle bundle = new GeckoBundle(1);
+        bundle.putString("countryCode", countryCode);
+        return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN_AUTO, bundle);
+    }
+
+    public @NonNull GeckoResult<Void> beginAutoBootstrap() {
+        return beginAutoBootstrap(null);
+    }
+
+    public @NonNull GeckoResult<Void> cancelBootstrap() {
+        return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_CANCEL);
+    }
+
+    public @NonNull GeckoResult<BootstrapState> getBootstrapState() {
+        return EventDispatcher.getInstance().queryBundle(EVENT_BOOTSTRAP_GET_STATE).map(new GeckoResult.OnValueMapper<>() {
+            @AnyThread
+            @Nullable
+            public BootstrapState onValue(@Nullable GeckoBundle value) throws Throwable {
+                return new BootstrapState(value);
+            }
+        });
+    }
+
+    public void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
+        mBootstrapStateListeners.add(listener);
+    }
+
+    public void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
+        mBootstrapStateListeners.remove(listener);
+    }
+
+    private final HashSet<BootstrapStateChangeListener> mBootstrapStateListeners = new HashSet<>();
 }


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java
=====================================
@@ -0,0 +1,172 @@
+package org.mozilla.geckoview;
+
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.mozilla.gecko.util.GeckoBundle;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.SequenceInputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+public class TorSettings {
+
+    public enum BridgeSource {
+        Invalid(-1),
+        BuiltIn(0),
+        BridgeDB(1),
+        UserProvided(2);
+
+        private int source;
+
+        BridgeSource(final int source) {
+            this.source = source;
+        }
+
+        public static BridgeSource fromInt(int i) {
+            switch (i) {
+                case -1: return Invalid;
+                case 0: return BuiltIn;
+                case 1: return BridgeDB;
+                case 2: return UserProvided;
+            }
+            return Invalid;
+        }
+
+        public int toInt() {
+            return this.source;
+        }
+    }
+
+    public enum ProxyType {
+        Invalid(-1),
+        Socks4(0),
+        Socks5(1),
+        HTTPS(2);
+
+        private int type;
+
+        ProxyType(final int type) {
+            this.type = type;
+        }
+
+        public int toInt() {
+            return type;
+        }
+
+        public static ProxyType fromInt(int i) {
+            switch (i) {
+                case -1: return Invalid;
+                case 0: return Socks4;
+                case 1: return Socks5;
+                case 2: return HTTPS;
+            }
+            return Invalid;
+        }
+    }
+
+    private boolean loaded = false;
+
+    public boolean enabled = true;
+
+    public boolean quickstart = false;
+
+    // bridges section
+    public boolean bridgesEnabled = false;
+    public BridgeSource bridgesSource = BridgeSource.Invalid;
+    public String bridgesBuiltinType = "";
+    public String[] bridgeBridgeStrings;
+
+    // proxy section
+    public boolean proxyEnabled = false;
+    public ProxyType proxyType = ProxyType.Invalid;
+    public String proxyAddress = "";
+    public int proxyPort = 0;
+    public String proxyUsername = "";
+    public String proxyPassword = "";
+
+    // firewall section
+    public boolean firewallEnabled = false;
+    public int[] firewallAllowedPorts;
+
+    public TorSettings() {
+    }
+
+    public TorSettings(GeckoBundle bundle) {
+        try {
+            GeckoBundle qs = bundle.getBundle("quickstart");
+            GeckoBundle bridges = bundle.getBundle("bridges");
+            GeckoBundle proxy = bundle.getBundle("proxy");
+            GeckoBundle firewall = bundle.getBundle("firewall");
+
+            bridgesEnabled = bridges.getBoolean("enabled");
+            bridgesSource = BridgeSource.fromInt(bridges.getInt("source"));
+            bridgesBuiltinType = bridges.getString("builtin_type");
+            bridgeBridgeStrings = bridges.getStringArray("bridge_strings");
+
+            quickstart = qs.getBoolean("enabled");
+
+            firewallEnabled = firewall.getBoolean("enabled");
+            firewallAllowedPorts = firewall.getIntArray("allowed_ports");
+
+            proxyEnabled = proxy.getBoolean("enabled");
+            proxyAddress = proxy.getString("address");
+            proxyUsername = proxy.getString("username");
+            proxyPassword = proxy.getString("password");
+            proxyPort = proxy.getInt("port");
+            proxyType = ProxyType.fromInt(proxy.getInt("type"));
+
+            loaded = true;
+        } catch (Exception e) {
+            Log.e("TorSettings", "bundle access error: " + e.toString(), e);
+        }
+    }
+
+    public GeckoBundle asGeckoBundle() {
+        GeckoBundle bundle = new GeckoBundle();
+
+        GeckoBundle qs = new GeckoBundle();
+        GeckoBundle bridges = new GeckoBundle();
+        GeckoBundle proxy = new GeckoBundle();
+        GeckoBundle firewall = new GeckoBundle();
+
+        bridges.putBoolean("enabled", bridgesEnabled);
+        bridges.putInt("source", bridgesSource.toInt());
+        bridges.putString("builtin_type", bridgesBuiltinType);
+        bridges.putStringArray("bridge_strings", bridgeBridgeStrings);
+
+        qs.putBoolean("enabled", quickstart);
+
+        firewall.putBoolean("enabled", firewallEnabled);
+        firewall.putIntArray("allowed_ports", firewallAllowedPorts);
+
+        proxy.putBoolean("enabled", proxyEnabled);
+        proxy.putString("address", proxyAddress);
+        proxy.putString("username", proxyUsername);
+        proxy.putString("password", proxyPassword);
+        proxy.putInt("port", proxyPort);
+        proxy.putInt("type", proxyType.toInt());
+
+        bundle.putBundle("quickstart", qs);
+        bundle.putBundle("bridges", bridges);
+        bundle.putBundle("proxy", proxy);
+        bundle.putBundle("firewall", firewall);
+
+        return bundle;
+    }
+
+    public boolean isLoaded() {
+        return this.loaded;
+    }
+}


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java
=====================================
@@ -0,0 +1,64 @@
+package org.mozilla.geckoview.androidlegacysettings;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import org.mozilla.gecko.GeckoAppShell;
+
+import java.util.Locale;
+
+// tor-android-service utils/Prefs.java
+
+/* package */ class Prefs {
+    private final static String PREF_BRIDGES_ENABLED = "pref_bridges_enabled";
+    private final static String PREF_BRIDGES_LIST = "pref_bridges_list";
+
+    private static SharedPreferences prefs;
+
+    // OrbotConstants
+    private final static String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences";
+
+
+    // tor-android-service utils/TorServiceUtil.java
+
+    private static void setContext() {
+        if (prefs == null) {
+            prefs = GeckoAppShell.getApplicationContext().getSharedPreferences(PREF_TOR_SHARED_PREFS,
+                    Context.MODE_MULTI_PROCESS);
+        }
+    }
+
+    public static boolean getBoolean(String key, boolean def) {
+        setContext();
+        return prefs.getBoolean(key, def);
+    }
+
+    public static void putBoolean(String key, boolean value) {
+        setContext();
+        prefs.edit().putBoolean(key, value).apply();
+    }
+
+    public static void putString(String key, String value) {
+        setContext();
+        prefs.edit().putString(key, value).apply();
+    }
+
+    public static String getString(String key, String def) {
+        setContext();
+        return prefs.getString(key, def);
+    }
+
+    public static boolean bridgesEnabled() {
+        setContext();
+        return prefs.getBoolean(PREF_BRIDGES_ENABLED, false);
+    }
+
+    public static String getBridgesList() {
+        setContext();
+        // was "meek" for (Locale.getDefault().getLanguage().equals("fa")) and "obfs4" for the rest from a 2019 commit
+        // but that has stopped representing a good default sometime since so not importing for new users
+        String list = prefs.getString(PREF_BRIDGES_LIST, "");
+        return list;
+    }
+
+
+}


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java
=====================================
@@ -0,0 +1,84 @@
+package org.mozilla.geckoview.androidlegacysettings;
+
+import java.io.IOException;
+
+import android.content.SharedPreferences;
+
+import org.mozilla.gecko.GeckoAppShell;
+
+import org.mozilla.geckoview.TorSettings;
+
+public class TorLegacyAndroidSettings {
+
+    private static String PREF_USE_MOZ_PREFS = "tor_use_moz_prefs";
+
+    public static boolean unmigrated() {
+        return !Prefs.getBoolean(PREF_USE_MOZ_PREFS, false);
+    }
+
+    public static void setUnmigrated() {
+        Prefs.putBoolean(PREF_USE_MOZ_PREFS, false);
+    }
+
+    public static void setMigrated() {
+        Prefs.putBoolean(PREF_USE_MOZ_PREFS, true);
+    }
+
+    public static TorSettings loadTorSettings() {
+        TorSettings settings = new TorSettings();
+
+        // always true, tor is enabled in TB
+        settings.enabled = true;
+
+        // firefox-android disconnected quick start a while ago so it's untracked
+        settings.quickstart = false;
+
+        settings.bridgesEnabled = Prefs.bridgesEnabled();
+
+        // tor-android-service CustomTorInstaller.java
+/*
+        BridgesList is an overloaded field, which can cause some confusion.
+        The list can be:
+          1) a filter like obfs4, meek, or snowflake OR
+          2) it can be a custom bridge
+        For (1), we just pass back all bridges, the filter will occur
+          elsewhere in the library.
+        For (2) we return the bridge list as a raw stream.
+        If length is greater than 9, then we know this is a custom bridge
+     */
+        String userDefinedBridgeList = Prefs.getBridgesList();
+        boolean userDefinedBridge = userDefinedBridgeList.length() > 9;
+        // Terrible hack. Must keep in sync with topl::addBridgesFromResources.
+        if (!userDefinedBridge) {
+            settings.bridgesSource = TorSettings.BridgeSource.BuiltIn;
+            switch (userDefinedBridgeList) {
+                case "obfs4":
+                    settings.bridgesBuiltinType = "objs4";
+                    break;
+                case "meek":
+                    settings.bridgesBuiltinType = "meek_azure";
+                    break;
+                case "snowflake":
+                    settings.bridgesBuiltinType = "snowflake";
+                    break;
+                default:
+                    settings.bridgesSource = TorSettings.BridgeSource.Invalid;
+                    break;
+            }
+        } else {
+            settings.bridgesSource = TorSettings.BridgeSource.UserProvided; // user provided
+            settings.bridgeBridgeStrings = userDefinedBridgeList.split("\r\n");
+        }
+
+        // Tor Browser Android doesn't take proxy and firewall settings
+        settings.proxyEnabled = false;
+
+        settings.firewallEnabled = false;
+        settings.firewallAllowedPorts = new int[0];
+
+        return settings;
+    }
+}
+
+
+


=====================================
toolkit/modules/TorAndroidIntegration.sys.mjs
=====================================
@@ -8,6 +8,8 @@ const lazy = {};
 ChromeUtils.defineESModuleGetters(lazy, {
   EventDispatcher: "resource://gre/modules/Messaging.sys.mjs",
   TorConnect: "resource://gre/modules/TorConnect.sys.mjs",
+  TorConnectTopics: "resource://gre/modules/TorConnect.sys.mjs",
+  TorSettingsTopics: "resource://gre/modules/TorSettings.sys.mjs",
   TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
   TorSettings: "resource://gre/modules/TorSettings.sys.mjs",
 });
@@ -23,11 +25,22 @@ const logger = new ConsoleAPI({
   prefix: "TorAndroidIntegration",
 });
 
+const EmittedEvents = Object.freeze( {
+  settingsReady: "GeckoView:Tor:SettingsReady",
+  settingsChanged: "GeckoView:Tor:SettingsChanged",
+});
+
 const ListenedEvents = Object.freeze({
   settingsGet: "GeckoView:Tor:SettingsGet",
+  // The data is passed directly to TorSettings.
   settingsSet: "GeckoView:Tor:SettingsSet",
   settingsApply: "GeckoView:Tor:SettingsApply",
   settingsSave: "GeckoView:Tor:SettingsSave",
+  bootstrapBegin: "GeckoView:Tor:BootstrapBegin",
+  // Optionally takes a countryCode, as data.countryCode.
+  bootstrapBeginAuto: "GeckoView:Tor:BootstrapBeginAuto",
+  bootstrapCancel: "GeckoView:Tor:BootstrapCancel",
+  bootstrapGetState: "GeckoView:Tor:BootstrapGetState",
 });
 
 class TorAndroidIntegrationImpl {
@@ -41,6 +54,14 @@ class TorAndroidIntegrationImpl {
 
     this.#bootstrapMethodReset();
     Services.prefs.addObserver(Prefs.useNewBootstrap, this);
+
+    for (const topic in lazy.TorConnectTopics) {
+      Services.obs.addObserver(this, lazy.TorConnectTopics[topic]);
+    }
+
+    for (const topic in lazy.TorSettingsTopics) {
+      Services.obs.addObserver(this, lazy.TorSettingsTopics[topic]);
+    }
   }
 
   async #initNewBootstrap() {
@@ -67,6 +88,14 @@ class TorAndroidIntegrationImpl {
           this.#bootstrapMethodReset();
         }
         break;
+      case lazy.TorConnectTopics.StateChange:
+        break;
+      case lazy.TorSettingsTopics.Ready:
+        lazy.EventDispatcher.instance.sendRequest({
+          type: EmittedEvents.settingsReady,
+          settings: lazy.TorSettings.getSettings(),
+        });
+        break;
     }
   }
 
@@ -74,24 +103,36 @@ class TorAndroidIntegrationImpl {
     logger.debug(`Received event ${event}`, data);
     try {
       switch (event) {
-        case settingsGet:
+        case ListenedEvents.settingsGet:
           callback?.onSuccess(lazy.TorSettings.getSettings());
           return;
-        case settingsSet:
+        case ListenedEvents.settingsSet:
           // This does not throw, so we do not have any way to report the error!
           lazy.TorSettings.setSettings(data);
           break;
-        case settingsApply:
+        case ListenedEvents.settingsApply:
           await lazy.TorSettings.applySettings();
           break;
-        case settingsSave:
+        case ListenedEvents.settingsSave:
           await lazy.TorSettings.saveSettings();
           break;
+        case ListenedEvents.bootstrapBegin:
+          lazy.TorConnect.beginBootstrap();
+          break;
+        case ListenedEvents.bootstrapBeginAuto:
+          lazy.TorConnect.beginAutoBootstrap(data.countryCode);
+          break;
+        case ListenedEvents.bootstrapCancel:
+          lazy.TorConnect.cancelBootstrap();
+          break;
+        case ListenedEvents.bootstrapGetState:
+          callback?.onSuccess(lazy.TorConnect.state);
+          return;
       }
       callback?.onSuccess();
     } catch (e) {
-      logger.error();
-      callback?.sendError(e);
+      logger.error(`Error while handling event ${event}`, e);
+      callback?.onError(e);
     }
   }
 



View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/d823a7e72ba20e816ca09aed6e8efd59b5166ca8...e9cc4840f6735d0e54a50e37a1e0a879d66f26a6

-- 
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/d823a7e72ba20e816ca09aed6e8efd59b5166ca8...e9cc4840f6735d0e54a50e37a1e0a879d66f26a6
You're receiving this email because of your account on gitlab.torproject.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tor-commits/attachments/20231220/db131a1d/attachment-0001.htm>


More information about the tor-commits mailing list