[tbb-commits] [Git][tpo/applications/tor-browser][tor-browser-128.4.0esr-14.5-1] 6 commits: fixup! Bug 40283: Workaround for the file upload bug

Pier Angelo Vendrame (@pierov) git at gitlab.torproject.org
Tue Oct 29 18:08:36 UTC 2024



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


Commits:
41bcfa1b by Pier Angelo Vendrame at 2024-10-29T19:05:48+01:00
fixup! Bug 40283: Workaround for the file upload bug

Lint with android-format.

- - - - -
c8428799 by Pier Angelo Vendrame at 2024-10-29T19:05:53+01:00
fixup! Bug 40171: Make WebRequest and GeckoWebExecutor First-Party aware

Lint with android-format.

- - - - -
cdcb77db by Pier Angelo Vendrame at 2024-10-29T19:05:53+01:00
fixup! Bug 42247: Android helpers for the TorProvider

Lint with android-format.

- - - - -
ad0782df by Pier Angelo Vendrame at 2024-10-29T19:05:54+01:00
fixup! Bug 40597: Implement TorSettings module

Fix a couple of references to Moat in the generic DomainFrontedRequests
module.

- - - - -
6b2120f9 by Pier Angelo Vendrame at 2024-10-29T19:05:54+01:00
fixup! Bug 40597: Implement TorSettings module

ch.asyncOpen is not a JS async function, so no need to await it.
The async in the name means that the channel will call methods from a
listener object that it takes as an argument when it receives data.

- - - - -
464b5a9b by Pier Angelo Vendrame at 2024-10-29T19:05:55+01:00
fixup! Bug 42247: Android helpers for the TorProvider

Bug 43232: Make the Android Meek transport easier to debug.

- - - - -


8 changed files:

- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.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/WebRequest.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/DomainFrontedRequests.sys.mjs
- toolkit/modules/Moat.sys.mjs


Changes:

=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
=====================================
@@ -6319,10 +6319,10 @@ public class GeckoSession {
       }
 
       private static String normalizePath(String input) {
-          // For an unclear reason, Android media picker delivers file paths
-          // starting with double slash. Firefox performs path validation on
-          // all paths, and double slash is deemed invalid.
-          return input.startsWith("//") ? input.substring(1) : input;
+        // For an unclear reason, Android media picker delivers file paths
+        // starting with double slash. Firefox performs path validation on
+        // all paths, and double slash is deemed invalid.
+        return input.startsWith("//") ? input.substring(1) : input;
       }
 
       private static String getFile(final @NonNull Context context, final @NonNull Uri uri) {


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
=====================================
@@ -9,671 +9,720 @@ package org.mozilla.geckoview;
 import android.content.Context;
 import android.os.AsyncTask;
 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.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
-
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
-
 import org.mozilla.geckoview.androidlegacysettings.TorLegacyAndroidSettings;
 
 public class TorIntegrationAndroid implements BundleEventListener {
-    private static final String TAG = "TorIntegrationAndroid";
-
-    // 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";
-    private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged";
-    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";
-    private static final String EVENT_TOR_LOGS = "GeckoView:Tor:Logs";
-    private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady";
-    private static final String EVENT_SETTINGS_CHANGED = "GeckoView:Tor:SettingsChanged";
-    private static final String EVENT_SETTINGS_OPEN = "GeckoView:Tor:OpenSettings";
-
-    // 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 CONTROL_PORT_FILE = "/control-ipc";
-    private static final String SOCKS_FILE = "/socks-ipc";
-    private static final String COOKIE_AUTH_FILE = "/auth-file";
-
-    private final String mLibraryDir;
-    private final String mCacheDir;
-    private final String mIpcDirectory;
-    private final File mDataDir;
-
-    private TorProcess mTorProcess = null;
-    /**
-     * The first time we run a Tor process in this session, we copy some configuration files to be
-     * sure we always have the latest version, but if we re-launch a tor process we do not need to
-     * copy them again.
-     */
-    private boolean mCopiedConfigFiles = false;
-    /**
-     * Allow multiple proxies to be started, even though it might not actually happen.
-     * The key should be positive (also 0 is not allowed).
-     */
-    private final HashMap<Integer, MeekTransport> mMeeks = new HashMap<>();
-    private int mMeekCounter;
-
-    /**
-     * mSettings is a Java-side copy of the authoritative settings in the JS code.
-     * It's useful to maintain as the UI may be fetching these options often and we don't watch each
-     * fetch to be a passthrough to JS with marshalling/unmarshalling each time.
-     */
-    private TorSettings mSettings = null;
-
-    /* package */ TorIntegrationAndroid(Context context) {
-        mLibraryDir = context.getApplicationInfo().nativeLibraryDir;
-        mCacheDir = context.getCacheDir().getAbsolutePath();
-        mIpcDirectory = mCacheDir + "/tor-private";
-        mDataDir = new File(context.getFilesDir(), "tor");
-        registerListener();
+  private static final String TAG = "TorIntegrationAndroid";
+
+  // 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";
+  private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged";
+  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";
+  private static final String EVENT_TOR_LOGS = "GeckoView:Tor:Logs";
+  private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady";
+  private static final String EVENT_SETTINGS_CHANGED = "GeckoView:Tor:SettingsChanged";
+  private static final String EVENT_SETTINGS_OPEN = "GeckoView:Tor:OpenSettings";
+
+  // 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 CONTROL_PORT_FILE = "/control-ipc";
+  private static final String SOCKS_FILE = "/socks-ipc";
+  private static final String COOKIE_AUTH_FILE = "/auth-file";
+
+  private final String mLibraryDir;
+  private final String mCacheDir;
+  private final String mIpcDirectory;
+  private final File mDataDir;
+
+  private TorProcess mTorProcess = null;
+
+  /**
+   * The first time we run a Tor process in this session, we copy some configuration files to be
+   * sure we always have the latest version, but if we re-launch a tor process we do not need to
+   * copy them again.
+   */
+  private boolean mCopiedConfigFiles = false;
+
+  /**
+   * Allow multiple proxies to be started, even though it might not actually happen. The key should
+   * be positive (also 0 is not allowed).
+   */
+  private final HashMap<Integer, MeekTransport> mMeeks = new HashMap<>();
+
+  private int mMeekCounter;
+
+  /**
+   * mSettings is a Java-side copy of the authoritative settings in the JS code. It's useful to
+   * maintain as the UI may be fetching these options often and we don't watch each fetch to be a
+   * passthrough to JS with marshalling/unmarshalling each time.
+   */
+  private TorSettings mSettings = null;
+
+  /* package */ TorIntegrationAndroid(Context context) {
+    mLibraryDir = context.getApplicationInfo().nativeLibraryDir;
+    mCacheDir = context.getCacheDir().getAbsolutePath();
+    mIpcDirectory = mCacheDir + "/tor-private";
+    mDataDir = new File(context.getFilesDir(), "tor");
+    registerListener();
+  }
+
+  /* package */ synchronized void shutdown() {
+    // FIXME: It seems this never gets called
+    if (mTorProcess != null) {
+      mTorProcess.shutdown();
+      mTorProcess = null;
     }
-
-    /* package */ synchronized void shutdown() {
-        // FIXME: It seems this never gets called
-        if (mTorProcess != null) {
-            mTorProcess.shutdown();
-            mTorProcess = null;
-        }
+  }
+
+  private void registerListener() {
+    EventDispatcher.getInstance()
+        .registerUiThreadListener(
+            this,
+            EVENT_TOR_START,
+            EVENT_MEEK_START,
+            EVENT_MEEK_STOP,
+            EVENT_SETTINGS_READY,
+            EVENT_SETTINGS_CHANGED,
+            EVENT_CONNECT_STATE_CHANGED,
+            EVENT_CONNECT_ERROR,
+            EVENT_BOOTSTRAP_PROGRESS,
+            EVENT_BOOTSTRAP_COMPLETE,
+            EVENT_TOR_LOGS,
+            EVENT_SETTINGS_OPEN);
+  }
+
+  @Override // BundleEventListener
+  public synchronized void handleMessage(
+      final String event, final GeckoBundle message, final EventCallback callback) {
+    if (EVENT_TOR_START.equals(event)) {
+      startDaemon(message, callback);
+    } else if (EVENT_TOR_STOP.equals(event)) {
+      stopDaemon(message, callback);
+    } else if (EVENT_MEEK_START.equals(event)) {
+      startMeek(message, callback);
+    } else if (EVENT_MEEK_STOP.equals(event)) {
+      stopMeek(message, callback);
+    } else if (EVENT_SETTINGS_READY.equals(event)) {
+      try {
+        new SettingsLoader().execute(message);
+      } catch (Exception e) {
+        Log.e(TAG, "SettingsLoader error: " + e.toString());
+      }
+    } else if (EVENT_SETTINGS_CHANGED.equals(event)) {
+      GeckoBundle newSettings = message.getBundle("settings");
+      if (newSettings != null) {
+        // TODO: Should we notify listeners?
+        mSettings = new TorSettings(newSettings);
+      } else {
+        Log.w(TAG, "Ignoring a settings changed event that did not have the new settings.");
+      }
+    } else if (EVENT_CONNECT_STATE_CHANGED.equals(event)) {
+      String state = message.getString("state");
+      for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
+        listener.onBootstrapStateChange(state);
+      }
+    } else if (EVENT_CONNECT_ERROR.equals(event)) {
+      String code = message.getString("code");
+      String msg = message.getString("message");
+      String phase = message.getString("phase");
+      String reason = message.getString("reason");
+      for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
+        listener.onBootstrapError(code, msg, phase, reason);
+      }
+    } else if (EVENT_BOOTSTRAP_PROGRESS.equals(event)) {
+      double progress = message.getDouble("progress");
+      boolean hasWarnings = message.getBoolean("hasWarnings");
+      for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
+        listener.onBootstrapProgress(progress, hasWarnings);
+      }
+    } else if (EVENT_BOOTSTRAP_COMPLETE.equals(event)) {
+      for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
+        listener.onBootstrapComplete();
+      }
+    } else if (EVENT_TOR_LOGS.equals(event)) {
+      String msg = message.getString("message");
+      String type = message.getString("logType");
+      for (TorLogListener listener : mLogListeners) {
+        listener.onLog(type, msg);
+      }
+    } else if (EVENT_SETTINGS_OPEN.equals(event)) {
+      for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
+        listener.onSettingsRequested();
+      }
     }
-
-    private void registerListener() {
-        EventDispatcher.getInstance()
-                .registerUiThreadListener(
-                        this,
-                        EVENT_TOR_START,
-                        EVENT_MEEK_START,
-                        EVENT_MEEK_STOP,
-                        EVENT_SETTINGS_READY,
-                        EVENT_SETTINGS_CHANGED,
-                        EVENT_CONNECT_STATE_CHANGED,
-                        EVENT_CONNECT_ERROR,
-                        EVENT_BOOTSTRAP_PROGRESS,
-                        EVENT_BOOTSTRAP_COMPLETE,
-                        EVENT_TOR_LOGS,
-                        EVENT_SETTINGS_OPEN);
+  }
+
+  private class SettingsLoader extends AsyncTask<GeckoBundle, Void, TorSettings> {
+    protected TorSettings doInBackground(GeckoBundle... messages) {
+      GeckoBundle message = messages[0];
+      TorSettings settings;
+      if (TorLegacyAndroidSettings.unmigrated()) {
+        settings = TorLegacyAndroidSettings.loadTorSettings();
+      } else {
+        GeckoBundle bundle = message.getBundle("settings");
+        settings = new TorSettings(bundle);
+      }
+      return settings;
     }
 
-    @Override // BundleEventListener
-    public synchronized void handleMessage(
-            final String event, final GeckoBundle message, final EventCallback callback) {
-        if (EVENT_TOR_START.equals(event)) {
-            startDaemon(message, callback);
-        } else if (EVENT_TOR_STOP.equals(event)) {
-            stopDaemon(message, callback);
-        } else if (EVENT_MEEK_START.equals(event)) {
-            startMeek(message, callback);
-        } else if (EVENT_MEEK_STOP.equals(event)) {
-            stopMeek(message, callback);
-        } else if (EVENT_SETTINGS_READY.equals(event)) {
-            try {
-                new SettingsLoader().execute(message);
-            } catch(Exception e) {
-                Log.e(TAG, "SettingsLoader error: "+ e.toString());
-            }
-        } else if (EVENT_SETTINGS_CHANGED.equals(event)) {
-            GeckoBundle newSettings = message.getBundle("settings");
-            if (newSettings != null) {
-                // TODO: Should we notify listeners?
-                mSettings = new TorSettings(newSettings);
-            } else {
-                Log.w(TAG, "Ignoring a settings changed event that did not have the new settings.");
-            }
-        } else if (EVENT_CONNECT_STATE_CHANGED.equals(event)) {
-            String state = message.getString("state");
-            for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
-                listener.onBootstrapStateChange(state);
-            }
-        } else if (EVENT_CONNECT_ERROR.equals(event)) {
-            String code = message.getString("code");
-            String msg = message.getString("message");
-            String phase = message.getString("phase");
-            String reason = message.getString("reason");
-            for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
-                listener.onBootstrapError(code, msg, phase, reason);
-            }
-        } else if (EVENT_BOOTSTRAP_PROGRESS.equals(event)) {
-            double progress = message.getDouble("progress");
-            boolean hasWarnings = message.getBoolean("hasWarnings");
-            for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
-                listener.onBootstrapProgress(progress, hasWarnings);
-            }
-        } else if (EVENT_BOOTSTRAP_COMPLETE.equals(event)) {
-            for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
-                listener.onBootstrapComplete();
-            }
-        } else if (EVENT_TOR_LOGS.equals(event)) {
-            String msg = message.getString("message");
-            String type = message.getString("logType");
-            for (TorLogListener listener: mLogListeners) {
-                    listener.onLog(type, msg);
-            }
-        } else if (EVENT_SETTINGS_OPEN.equals(event)) {
-            for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
-                listener.onSettingsRequested();
-            }
-        }
+    @Override
+    protected void onPostExecute(TorSettings torSettings) {
+      mSettings = torSettings;
+      if (TorLegacyAndroidSettings.unmigrated()) {
+        setSettings(mSettings, true, true);
+        TorLegacyAndroidSettings.setMigrated();
+      }
+    }
+  }
+
+  private synchronized void startDaemon(final GeckoBundle message, final EventCallback callback) {
+    // Let JS generate this to possibly reduce the chance of race conditions.
+    String handle = message.getString("handle", "");
+    if (handle.isEmpty()) {
+      Log.e(TAG, "Requested to start a tor process without a handle.");
+      callback.sendError("Expected a handle for the new process.");
+      return;
     }
+    Log.d(TAG, "Starting the a tor process with handle " + handle);
 
-    private class SettingsLoader extends AsyncTask<GeckoBundle, Void, TorSettings> {
-        protected TorSettings doInBackground(GeckoBundle... messages) {
-            GeckoBundle message = messages[0];
-            TorSettings settings;
-            if (TorLegacyAndroidSettings.unmigrated()) {
-                settings = TorLegacyAndroidSettings.loadTorSettings();
-            } else {
-                GeckoBundle bundle = message.getBundle("settings");
-                settings = new TorSettings(bundle);
-            }
-            return settings;
-        }
+    TorProcess previousProcess = mTorProcess;
+    if (previousProcess != null) {
+      Log.w(TAG, "We still have a running process: " + previousProcess.getHandle());
+    }
+    mTorProcess = new TorProcess(handle);
+
+    GeckoBundle bundle = new GeckoBundle(3);
+    bundle.putString("controlPortPath", mIpcDirectory + CONTROL_PORT_FILE);
+    bundle.putString("socksPath", mIpcDirectory + SOCKS_FILE);
+    bundle.putString("cookieFilePath", mIpcDirectory + COOKIE_AUTH_FILE);
+    callback.sendSuccess(bundle);
+  }
+
+  private synchronized void stopDaemon(final GeckoBundle message, final EventCallback callback) {
+    if (mTorProcess == null) {
+      if (callback != null) {
+        callback.sendSuccess(null);
+      }
+      return;
+    }
+    String handle = message.getString("handle", "");
+    if (!mTorProcess.getHandle().equals(handle)) {
+      GeckoBundle bundle = new GeckoBundle(1);
+      bundle.putString(
+          "error", "The requested process has not been found. It might have already been stopped.");
+      callback.sendError(bundle);
+      return;
+    }
+    mTorProcess.shutdown();
+    mTorProcess = null;
+    callback.sendSuccess(null);
+  }
+
+  class TorProcess extends Thread {
+    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;
+
+    TorProcess(String handle) {
+      mHandle = handle;
+      setName("tor-process-" + handle);
+      start();
+    }
 
-        @Override
-        protected void onPostExecute(TorSettings torSettings) {
-            mSettings = torSettings;
-            if (TorLegacyAndroidSettings.unmigrated()) {
-                setSettings(mSettings, true, true);
-                TorLegacyAndroidSettings.setMigrated();
-            }
+    @Override
+    public void run() {
+      cleanIpcDirectory();
+
+      final String ipcDir = TorIntegrationAndroid.this.mIpcDirectory;
+      final ArrayList<String> args = new ArrayList<>();
+      args.add(mLibraryDir + "/libTor.so");
+      args.add("DisableNetwork");
+      args.add("1");
+      args.add("+__ControlPort");
+      args.add("unix:" + ipcDir + CONTROL_PORT_FILE);
+      args.add("+__SocksPort");
+      args.add("unix:" + ipcDir + SOCKS_FILE + " IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth");
+      args.add("CookieAuthentication");
+      args.add("1");
+      args.add("CookieAuthFile");
+      args.add(ipcDir + COOKIE_AUTH_FILE);
+      args.add("DataDirectory");
+      args.add(mDataDir.getAbsolutePath());
+      boolean copied = true;
+      try {
+        copyAndUseConfigFile("--defaults-torrc", "torrc-defaults", args);
+      } catch (IOException e) {
+        Log.w(
+            TAG, "torrc-default cannot be created, pluggable transports will not be available", e);
+        copied = false;
+      }
+      // tor-browser#42607: For now we do not ship geoip databases, as we
+      // do not have the circuit display functionality and they allow us
+      // to save some space in the final APK.
+      /*try {
+          copyAndUseConfigFile("GeoIPFile", "geoip", args);
+          copyAndUseConfigFile("GeoIPv6File", "geoip6", args);
+      } catch (IOException e) {
+          Log.w(TAG, "GeoIP files cannot be created, this feature will not be available.", e);
+          copied = false;
+      }*/
+      mCopiedConfigFiles = copied;
+
+      Log.d(TAG, "Starting tor with the follwing args: " + args.toString());
+      final ProcessBuilder builder = new ProcessBuilder(args);
+      builder.directory(new File(mLibraryDir));
+      try {
+        mProcess = builder.start();
+      } catch (IOException e) {
+        Log.e(TAG, "Cannot start tor " + mHandle, e);
+        final GeckoBundle data = new GeckoBundle(2);
+        data.putString("handle", mHandle);
+        data.putString("error", e.getMessage());
+        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(EVENT_TOR_STARTED, data);
+      }
+      try {
+        BufferedReader reader =
+            new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
+        String line;
+        while ((line = reader.readLine()) != null) {
+          Log.i(TAG, "[tor-" + mHandle + "] " + line);
         }
+      } catch (IOException e) {
+        Log.e(TAG, "Failed to read stdout of the tor process " + mHandle, e);
+      }
+      Log.d(TAG, "Exiting the stdout loop for process " + mHandle);
+      final GeckoBundle data = new GeckoBundle(2);
+      data.putString("handle", mHandle);
+      try {
+        data.putInt("status", mProcess.waitFor());
+      } catch (InterruptedException e) {
+        Log.e(TAG, "Failed to wait for the tor process " + mHandle, e);
+        data.putInt("status", 0xdeadbeef);
+      }
+      // 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(EVENT_TOR_EXITED, data);
     }
 
-    private synchronized void startDaemon(final GeckoBundle message, final EventCallback callback) {
-        // Let JS generate this to possibly reduce the chance of race conditions.
-        String handle = message.getString("handle", "");
-        if (handle.isEmpty()) {
-            Log.e(TAG, "Requested to start a tor process without a handle.");
-            callback.sendError("Expected a handle for the new process.");
-            return;
+    private void cleanIpcDirectory() {
+      File directory = new File(TorIntegrationAndroid.this.mIpcDirectory);
+      if (!directory.isDirectory()) {
+        if (!directory.mkdirs()) {
+          Log.e(TAG, "Failed to create the IPC directory.");
+          return;
         }
-        Log.d(TAG, "Starting the a tor process with handle " + handle);
-
-        TorProcess previousProcess = mTorProcess;
-        if (previousProcess != null) {
-            Log.w(TAG, "We still have a running process: " + previousProcess.getHandle());
+        try {
+          // First remove the permissions for everybody...
+          directory.setReadable(false, false);
+          directory.setWritable(false, false);
+          directory.setExecutable(false, false);
+          // ... then add them back, but only for the owner.
+          directory.setReadable(true, true);
+          directory.setWritable(true, true);
+          directory.setExecutable(true, true);
+        } catch (SecurityException e) {
+          Log.e(TAG, "Could not set the permissions to the IPC directory.", e);
         }
-        mTorProcess = new TorProcess(handle);
+        return;
+      }
+      // We assume we do not have child directories, only files
+      File[] maybeFiles = directory.listFiles();
+      if (maybeFiles != null) {
+        for (File file : maybeFiles) {
+          if (!file.delete()) {
+            Log.d(TAG, "Could not delete " + file);
+          }
+        }
+      }
+    }
 
-        GeckoBundle bundle = new GeckoBundle(3);
-        bundle.putString("controlPortPath", mIpcDirectory + CONTROL_PORT_FILE);
-        bundle.putString("socksPath", mIpcDirectory + SOCKS_FILE);
-        bundle.putString("cookieFilePath", mIpcDirectory + COOKIE_AUTH_FILE);
-        callback.sendSuccess(bundle);
+    private void copyAndUseConfigFile(String option, String name, ArrayList<String> args)
+        throws IOException {
+      File file = copyConfigFile(name);
+      args.add(option);
+      args.add(file.getAbsolutePath());
     }
 
-    private synchronized void stopDaemon(final GeckoBundle message, final EventCallback callback) {
-        if (mTorProcess == null) {
-            if (callback != null) {
-                callback.sendSuccess(null);
-            }
-            return;
+    private File copyConfigFile(String name) throws IOException {
+      final File file = new File(mCacheDir, name);
+      if (mCopiedConfigFiles && file.exists()) {
+        return file;
+      }
+
+      final Context context = GeckoAppShell.getApplicationContext();
+      final InputStream in = context.getAssets().open("common/" + name);
+      // Files.copy is API 26+, so use java.io and a loop for now.
+      FileOutputStream out = null;
+      try {
+        out = new FileOutputStream(file);
+      } catch (IOException e) {
+        in.close();
+        throw e;
+      }
+      try {
+        byte buffer[] = new byte[4096];
+        int read;
+        while ((read = in.read(buffer)) >= 0) {
+          out.write(buffer, 0, read);
         }
-        String handle = message.getString("handle", "");
-        if (!mTorProcess.getHandle().equals(handle)) {
-            GeckoBundle bundle = new GeckoBundle(1);
-            bundle.putString("error", "The requested process has not been found. It might have already been stopped.");
-            callback.sendError(bundle);
-            return;
+      } finally {
+        try {
+          in.close();
+        } catch (IOException e) {
+          Log.w(TAG, "Cannot close the input stream for " + name);
         }
-        mTorProcess.shutdown();
-        mTorProcess = null;
-        callback.sendSuccess(null);
+        try {
+          out.close();
+        } catch (IOException e) {
+          Log.w(TAG, "Cannot close the output stream for " + name);
+        }
+      }
+      return file;
     }
 
-    class TorProcess extends Thread {
-        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;
-
-        TorProcess(String handle) {
-            mHandle = handle;
-            setName("tor-process-" + handle);
-            start();
+    public void shutdown() {
+      if (mProcess != null && mProcess.isAlive()) {
+        mProcess.destroy();
+      }
+      if (isAlive()) {
+        try {
+          join();
+        } catch (InterruptedException e) {
+          Log.e(
+              TAG,
+              "Cannot join the thread for tor process " + mHandle + ", possibly already terminated",
+              e);
         }
+      }
+    }
 
-        @Override
-        public void run() {
-            cleanIpcDirectory();
-
-            final String ipcDir = TorIntegrationAndroid.this.mIpcDirectory;
-            final ArrayList<String> args = new ArrayList<>();
-            args.add(mLibraryDir + "/libTor.so");
-            args.add("DisableNetwork");
-            args.add("1");
-            args.add("+__ControlPort");
-            args.add("unix:" + ipcDir + CONTROL_PORT_FILE);
-            args.add("+__SocksPort");
-            args.add("unix:" + ipcDir + SOCKS_FILE + " IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth");
-            args.add("CookieAuthentication");
-            args.add("1");
-            args.add("CookieAuthFile");
-            args.add(ipcDir + COOKIE_AUTH_FILE);
-            args.add("DataDirectory");
-            args.add(mDataDir.getAbsolutePath());
-            boolean copied = true;
-            try {
-                copyAndUseConfigFile("--defaults-torrc", "torrc-defaults", args);
-            } catch (IOException e) {
-                Log.w(TAG, "torrc-default cannot be created, pluggable transports will not be available", e);
-                copied = false;
-            }
-            // tor-browser#42607: For now we do not ship geoip databases, as we
-            // do not have the circuit display functionality and they allow us
-            // to save some space in the final APK.
-            /*try {
-                copyAndUseConfigFile("GeoIPFile", "geoip", args);
-                copyAndUseConfigFile("GeoIPv6File", "geoip6", args);
-            } catch (IOException e) {
-                Log.w(TAG, "GeoIP files cannot be created, this feature will not be available.", e);
-                copied = false;
-            }*/
-            mCopiedConfigFiles = copied;
-
-            Log.d(TAG, "Starting tor with the follwing args: " + args.toString());
-            final ProcessBuilder builder = new ProcessBuilder(args);
-            builder.directory(new File(mLibraryDir));
-            try {
-                mProcess = builder.start();
-            } catch (IOException e) {
-                Log.e(TAG, "Cannot start tor " + mHandle, e);
-                final GeckoBundle data = new GeckoBundle(2);
-                data.putString("handle", mHandle);
-                data.putString("error", e.getMessage());
-                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(EVENT_TOR_STARTED, data);
-            }
-            try {
-                BufferedReader reader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
-                String line;
-                while ((line = reader.readLine()) != null) {
-                    Log.i(TAG, "[tor-" + mHandle + "] " + line);
-                }
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to read stdout of the tor process " + mHandle, e);
-            }
-            Log.d(TAG, "Exiting the stdout loop for process " + mHandle);
-            final GeckoBundle data = new GeckoBundle(2);
-            data.putString("handle", mHandle);
-            try {
-                data.putInt("status", mProcess.waitFor());
-            } catch (InterruptedException e) {
-                Log.e(TAG, "Failed to wait for the tor process " + mHandle, e);
-                data.putInt("status", 0xdeadbeef);
-            }
-            // 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(EVENT_TOR_EXITED, data);
-        }
+    public String getHandle() {
+      return mHandle;
+    }
+  }
+
+  private synchronized void startMeek(final GeckoBundle message, final EventCallback callback) {
+    if (callback == null) {
+      Log.e(TAG, "Tried to start Meek without a callback.");
+      return;
+    }
+    mMeekCounter++;
+    mMeeks.put(
+        new Integer(mMeekCounter),
+        new MeekTransport(callback, mMeekCounter, message.getStringArray("arguments")));
+  }
+
+  private synchronized void stopMeek(final GeckoBundle message, final EventCallback callback) {
+    final Integer key = message.getInteger("id");
+    final MeekTransport meek = mMeeks.remove(key);
+    if (meek != null) {
+      meek.shutdown();
+    }
+    if (callback != null) {
+      callback.sendSuccess(null);
+    }
+  }
+
+  private class MeekTransport extends Thread {
+    private static final String TRANSPORT = "meek_lite";
+    private Process mProcess;
+    private final EventCallback mCallback;
+    private final int mId;
+
+    MeekTransport(final EventCallback callback, int id, String[] args) {
+      setName("meek-" + id);
+
+      final String command = mLibraryDir + "/libObfs4proxy.so";
+      ArrayList<String> argList = new ArrayList<String>();
+      argList.add(command);
+      if (args != null && args.length > 0) {
+        // Normally not used, but it helps to debug only by editing JS.
+        Log.d(TAG, "Requested custom arguments for meek: " + String.join(" ", args));
+        argList.addAll(Arrays.asList(args));
+      }
+      final ProcessBuilder builder = new ProcessBuilder(argList);
+
+      File ptStateDir = new File(mDataDir, "pt_state");
+      Log.d(TAG, "Using " + ptStateDir.getAbsolutePath() + " as a state directory for meek.");
+      final Map<String, String> env = builder.environment();
+      env.put("TOR_PT_MANAGED_TRANSPORT_VER", "1");
+      env.put("TOR_PT_STATE_LOCATION", ptStateDir.getAbsolutePath());
+      env.put("TOR_PT_EXIT_ON_STDIN_CLOSE", "1");
+      env.put("TOR_PT_CLIENT_TRANSPORTS", TRANSPORT);
+
+      mCallback = callback;
+      mId = id;
+      try {
+        // We expect this process to be short-lived, therefore we do not bother with
+        // implementing this as a service.
+        mProcess = builder.start();
+      } catch (IOException e) {
+        Log.e(TAG, "Cannot start the PT", e);
+        callback.sendError(e.getMessage());
+        return;
+      }
+      start();
+    }
 
-        private void cleanIpcDirectory() {
-            File directory = new File(TorIntegrationAndroid.this.mIpcDirectory);
-            if (!directory.isDirectory()) {
-                if (!directory.mkdirs()) {
-                    Log.e(TAG, "Failed to create the IPC directory.");
-                    return;
-                }
-                try {
-                    // First remove the permissions for everybody...
-                    directory.setReadable(false, false);
-                    directory.setWritable(false, false);
-                    directory.setExecutable(false, false);
-                    // ... then add them back, but only for the owner.
-                    directory.setReadable(true, true);
-                    directory.setWritable(true, true);
-                    directory.setExecutable(true, true);
-                } catch (SecurityException e) {
-                    Log.e(TAG, "Could not set the permissions to the IPC directory.", e);
-                }
-                return;
+    /**
+     * Parse the standard output of the pluggable transport to find the hostname and port it is
+     * listening on.
+     *
+     * <p>See also the specs for the IPC protocol at https://spec.torproject.org/pt-spec/ipc.html.
+     */
+    @Override
+    public void run() {
+      final String PROTOCOL_VERSION = "1";
+      String hostname = "";
+      boolean valid = false;
+      int port = 0;
+      String error = "Did not see a CMETHOD";
+      try {
+        InputStreamReader isr = new InputStreamReader(mProcess.getInputStream());
+        BufferedReader reader = new BufferedReader(isr);
+        String line;
+        while ((line = reader.readLine()) != null) {
+          line = line.trim();
+          Log.d(TAG, "Meek line: " + line);
+          // Split produces always at least one item
+          String[] tokens = line.split(" ");
+          if ("VERSION".equals(tokens[0])
+              && (tokens.length != 2 || !PROTOCOL_VERSION.equals(tokens[1]))) {
+            error = "Bad version: " + line;
+            break;
+          }
+          if ("CMETHOD".equals(tokens[0])) {
+            if (tokens.length != 4) {
+              error = "Bad number of tokens in CMETHOD: " + line;
+              break;
             }
-            // We assume we do not have child directories, only files
-            File[] maybeFiles = directory.listFiles();
-            if (maybeFiles != null) {
-                for (File file : maybeFiles) {
-                    if (!file.delete()) {
-                        Log.d(TAG, "Could not delete " + file);
-                    }
-                }
+            if (!tokens[1].equals(TRANSPORT)) {
+              error = "Unexpected transport: " + tokens[1];
+              break;
             }
-        }
-
-        private void copyAndUseConfigFile(String option, String name, ArrayList<String> args) throws IOException {
-            File file = copyConfigFile(name);
-            args.add(option);
-            args.add(file.getAbsolutePath());
-        }
-
-        private File copyConfigFile(String name) throws IOException {
-            final File file = new File(mCacheDir, name);
-            if (mCopiedConfigFiles && file.exists()) {
-                return file;
+            if (!"socks5".equals(tokens[2])) {
+              error = "Unexpected proxy type: " + tokens[2];
+              break;
             }
-
-            final Context context = GeckoAppShell.getApplicationContext();
-            final InputStream in = context.getAssets().open("common/" + name);
-            // Files.copy is API 26+, so use java.io and a loop for now.
-            FileOutputStream out = null;
-            try {
-                out = new FileOutputStream(file);
-            } catch (IOException e) {
-                in.close();
-                throw e;
+            String[] addr = tokens[3].split(":");
+            if (addr.length != 2) {
+              error = "Invalid address";
+              break;
             }
+            hostname = addr[0];
             try {
-                byte buffer[] = new byte[4096];
-                int read;
-                while ((read = in.read(buffer)) >= 0) {
-                    out.write(buffer, 0, read);
-                }
-            } finally {
-                try {
-                    in.close();
-                } catch (IOException e) {
-                    Log.w(TAG, "Cannot close the input stream for " + name);
-                }
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    Log.w(TAG, "Cannot close the output stream for " + name);
-                }
-            }
-            return file;
-        }
-
-        public void shutdown() {
-            if (mProcess != null && mProcess.isAlive()) {
-                mProcess.destroy();
+              port = Integer.parseInt(addr[1]);
+            } catch (NumberFormatException e) {
+              error = "Invalid port: " + e.getMessage();
+              break;
             }
-            if (isAlive()) {
-                try {
-                    join();
-                } catch (InterruptedException e) {
-                    Log.e(TAG, "Cannot join the thread for tor process " + mHandle + ", possibly already terminated", e);
-                }
+            if (port < 1 || port > 65535) {
+              error = "Invalid port: out of bounds";
+              break;
             }
+            valid = true;
+            break;
+          }
+          if (tokens[0].endsWith("-ERROR")) {
+            error = "Seen an error: " + line;
+            break;
+          }
         }
-
-        public String getHandle() {
-            return mHandle;
-        }
+      } catch (Exception e) {
+        error = e.getMessage();
+      }
+      if (valid) {
+        Log.d(TAG, "Setup a meek transport " + mId + ": " + hostname + ":" + port);
+        final GeckoBundle bundle = new GeckoBundle(3);
+        bundle.putInt("id", mId);
+        bundle.putString("address", hostname);
+        bundle.putInt("port", port);
+        mCallback.sendSuccess(bundle);
+      } else {
+        Log.e(TAG, "Failed to get a usable config from the PT: " + error);
+        mCallback.sendError(error);
+        return;
+      }
+      dumpStdout();
     }
 
-    private synchronized void startMeek(final GeckoBundle message, final EventCallback callback) {
-        if (callback == null) {
-            Log.e(TAG, "Tried to start Meek without a callback.");
-            return;
-        }
-        mMeekCounter++;
-        mMeeks.put(new Integer(mMeekCounter), new MeekTransport(callback, mMeekCounter));
+    void shutdown() {
+      if (mProcess != null) {
+        Log.i(TAG, "Shutting down meek process " + mId);
+        mProcess.destroy();
+        mProcess = null;
+      } else {
+        Log.w(
+            TAG,
+            "Shutdown request on the meek process " + mId + " that has already been shutdown.");
+      }
+      try {
+        join();
+      } catch (InterruptedException e) {
+        Log.e(TAG, "Could not join the meek thread", e);
+      }
     }
 
-    private synchronized void stopMeek(final GeckoBundle message, final EventCallback callback) {
-        final Integer key = message.getInteger("id");
-        final MeekTransport meek = mMeeks.remove(key);
-        if (meek != null) {
-            meek.shutdown();
-        }
-        if (callback != null) {
-            callback.sendSuccess(null);
+    void dumpStdout() {
+      try {
+        BufferedReader reader =
+            new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
+        String line;
+        while ((line = reader.readLine()) != null) {
+          Log.d(TAG, "[meek-" + mId + "] " + line);
         }
+      } catch (InterruptedIOException e) {
+        // This happens normally, do not log it.
+      } catch (IOException e) {
+        Log.e(TAG, "Failed to read stdout of the meek process process " + mId, e);
+      }
     }
+  }
 
-    private class MeekTransport extends Thread {
-        private static final String TRANSPORT = "meek_lite";
-        private Process mProcess;
-        private final EventCallback mCallback;
-        private final int mId;
-
-        MeekTransport(final EventCallback callback, int id) {
-            setName("meek-" + id);
-            final ProcessBuilder builder = new ProcessBuilder(mLibraryDir + "/libObfs4proxy.so");
-            {
-                File ptStateDir = new File(mDataDir, "pt_state");
-                final Map<String, String> env = builder.environment();
-                env.put("TOR_PT_MANAGED_TRANSPORT_VER", "1");
-                env.put("TOR_PT_STATE_LOCATION", ptStateDir.getAbsolutePath());
-                env.put("TOR_PT_EXIT_ON_STDIN_CLOSE", "1");
-                env.put("TOR_PT_CLIENT_TRANSPORTS", TRANSPORT);
-            }
-            mCallback = callback;
-            mId = id;
-            try {
-                // We expect this process to be short-lived, therefore we do not bother with
-                // implementing this as a service.
-                mProcess = builder.start();
-            } catch (IOException e) {
-                Log.e(TAG, "Cannot start the PT", e);
-                callback.sendError(e.getMessage());
-                return;
-            }
-            start();
-        }
+  public interface BootstrapStateChangeListener {
+    void onBootstrapStateChange(String state);
 
-        /**
-         * Parse the standard output of the pluggable transport to find the hostname and port it is
-         * listening on.
-         * <p>
-         * See also the specs for the IPC protocol at https://spec.torproject.org/pt-spec/ipc.html.
-         */
-        @Override
-        public void run() {
-            final String PROTOCOL_VERSION = "1";
-            String hostname = "";
-            boolean valid = false;
-            int port = 0;
-            String error = "Did not see a CMETHOD";
-            try {
-                InputStreamReader isr = new InputStreamReader(mProcess.getInputStream());
-                BufferedReader reader = new BufferedReader(isr);
-                String line;
-                while ((line = reader.readLine()) != null) {
-                    line = line.trim();
-                    Log.d(TAG, "Meek line: " + line);
-                    // Split produces always at least one item
-                    String[] tokens = line.split(" ");
-                    if ("VERSION".equals(tokens[0]) && (tokens.length != 2 || !PROTOCOL_VERSION.equals(tokens[1]))) {
-                        error = "Bad version: " + line;
-                        break;
-                    }
-                    if ("CMETHOD".equals(tokens[0])) {
-                        if (tokens.length != 4) {
-                            error = "Bad number of tokens in CMETHOD: " + line;
-                            break;
-                        }
-                        if (!tokens[1].equals(TRANSPORT)) {
-                            error = "Unexpected transport: " + tokens[1];
-                            break;
-                        }
-                        if (!"socks5".equals(tokens[2])) {
-                            error = "Unexpected proxy type: " + tokens[2];
-                            break;
-                        }
-                        String[] addr = tokens[3].split(":");
-                        if (addr.length != 2) {
-                            error = "Invalid address";
-                            break;
-                        }
-                        hostname = addr[0];
-                        try {
-                            port = Integer.parseInt(addr[1]);
-                        } catch (NumberFormatException e) {
-                            error = "Invalid port: " + e.getMessage();
-                            break;
-                        }
-                        if (port < 1 || port > 65535) {
-                            error = "Invalid port: out of bounds";
-                            break;
-                        }
-                        valid = true;
-                        break;
-                    }
-                    if (tokens[0].endsWith("-ERROR")) {
-                        error = "Seen an error: " + line;
-                        break;
-                    }
-                }
-            } catch (Exception e) {
-                error = e.getMessage();
-            }
-            if (valid) {
-                Log.d(TAG, "Setup a meek transport " + mId + ": " + hostname + ":" + port);
-                final GeckoBundle bundle = new GeckoBundle(3);
-                bundle.putInt("id", mId);
-                bundle.putString("address", hostname);
-                bundle.putInt("port", port);
-                mCallback.sendSuccess(bundle);
-            } else {
-                Log.e(TAG, "Failed to get a usable config from the PT: " + error);
-                mCallback.sendError(error);
-            }
-        }
+    void onBootstrapProgress(double progress, boolean hasWarnings);
 
-        void shutdown() {
-            if (mProcess != null) {
-                mProcess.destroy();
-                mProcess = null;
-            }
-            try {
-                join();
-            } catch (InterruptedException e) {
-                Log.e(TAG, "Could not join the meek thread", e);
-            }
-        }
-    }
+    void onBootstrapComplete();
 
-    public interface BootstrapStateChangeListener {
-        void onBootstrapStateChange(String state);
-        void onBootstrapProgress(double progress, boolean hasWarnings);
-        void onBootstrapComplete();
-        void onBootstrapError(String code, String message, String phase, String reason);
-        void onSettingsRequested();
-    }
+    void onBootstrapError(String code, String message, String phase, String reason);
 
-    public interface TorLogListener {
-        void onLog(String logType, String message);
-    }
+    void onSettingsRequested();
+  }
 
-    private @NonNull void reloadSettings() {
-        EventDispatcher.getInstance().queryBundle(EVENT_SETTINGS_GET).then( new GeckoResult.OnValueListener<GeckoBundle, Void>() {
-            public GeckoResult<Void> onValue(final GeckoBundle bundle) {
+  public interface TorLogListener {
+    void onLog(String logType, String message);
+  }
+
+  private @NonNull void reloadSettings() {
+    EventDispatcher.getInstance()
+        .queryBundle(EVENT_SETTINGS_GET)
+        .then(
+            new GeckoResult.OnValueListener<GeckoBundle, Void>() {
+              public GeckoResult<Void> onValue(final GeckoBundle bundle) {
                 mSettings = new TorSettings(bundle);
                 return new GeckoResult<Void>();
-            }
-        });
-    }
+              }
+            });
+  }
 
-    public TorSettings getSettings() {
-        return mSettings;
-    }
+  public TorSettings getSettings() {
+    return mSettings;
+  }
 
-    public void setSettings(final TorSettings settings, boolean save, boolean apply) {
-        mSettings = settings;
+  public void setSettings(final TorSettings settings, boolean save, boolean apply) {
+    mSettings = settings;
 
-        emitSetSettings(settings, save, apply).then(
+    emitSetSettings(settings, save, apply)
+        .then(
             new GeckoResult.OnValueListener<Void, Void>() {
-                public GeckoResult<Void> onValue(Void v) {
-                    return new GeckoResult<Void>();
-                }
+              public GeckoResult<Void> onValue(Void v) {
+                return new GeckoResult<Void>();
+              }
             },
             new GeckoResult.OnExceptionListener<Void>() {
-                public GeckoResult<Void> onException(final Throwable e) {
-                    Log.e(TAG, "Failed to set settings", e);
-                    reloadSettings();
-                    return new GeckoResult<Void>();
-                }
+              public GeckoResult<Void> onException(final Throwable e) {
+                Log.e(TAG, "Failed to set settings", e);
+                reloadSettings();
+                return new GeckoResult<Void>();
+              }
             });
-    }
-
-    private @NonNull GeckoResult<Void> emitSetSettings(final TorSettings settings, boolean save, boolean apply) {
-        GeckoBundle bundle = new GeckoBundle(3);
-        bundle.putBoolean("save", save);
-        bundle.putBoolean("apply", apply);
-        bundle.putBundle("settings", settings.asGeckoBundle());
-        return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SET, bundle);
-    }
-
-    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 void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
-        mBootstrapStateListeners.add(listener);
-    }
-
-    public void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
-        mBootstrapStateListeners.remove(listener);
-    }
-
-    private final HashSet<BootstrapStateChangeListener> mBootstrapStateListeners = new HashSet<>();
-
-    public void registerLogListener(TorLogListener listener) {
-        mLogListeners.add(listener);
-    }
-
-    public void unregisterLogListener(TorLogListener listener) {
-        mLogListeners.remove(listener);
-    }
-
-    private final HashSet<TorLogListener> mLogListeners = new HashSet<>();
+  }
+
+  private @NonNull GeckoResult<Void> emitSetSettings(
+      final TorSettings settings, boolean save, boolean apply) {
+    GeckoBundle bundle = new GeckoBundle(3);
+    bundle.putBoolean("save", save);
+    bundle.putBoolean("apply", apply);
+    bundle.putBundle("settings", settings.asGeckoBundle());
+    return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SET, bundle);
+  }
+
+  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 void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
+    mBootstrapStateListeners.add(listener);
+  }
+
+  public void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
+    mBootstrapStateListeners.remove(listener);
+  }
+
+  private final HashSet<BootstrapStateChangeListener> mBootstrapStateListeners = new HashSet<>();
+
+  public void registerLogListener(TorLogListener listener) {
+    mLogListeners.add(listener);
+  }
+
+  public void unregisterLogListener(TorLogListener listener) {
+    mLogListeners.remove(listener);
+  }
+
+  private final HashSet<TorLogListener> mLogListeners = new HashSet<>();
 }


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java
=====================================
@@ -1,185 +1,192 @@
 package org.mozilla.geckoview;
 
 import android.util.Log;
-
 import org.mozilla.gecko.util.GeckoBundle;
 
 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 BridgeSource {
+    Invalid(-1),
+    BuiltIn(0),
+    BridgeDB(1),
+    UserProvided(2);
+
+    private int source;
+
+    BridgeSource(final int source) {
+      this.source = 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;
-        }
+    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 enum BridgeBuiltinType {
-        /* TorSettings.sys.mjs ~ln43:  string: obfs4|meek-azure|snowflake|etc */
-        Invalid("invalid"),
-        Obfs4("obfs4"),
-        MeekAzure("meek-azure"),
-        Snowflake("snowflake");
+    public int toInt() {
+      return this.source;
+    }
+  }
 
+  public enum ProxyType {
+    Invalid(-1),
+    Socks4(0),
+    Socks5(1),
+    HTTPS(2);
 
-        private String type;
+    private int type;
 
-        BridgeBuiltinType(String type) {
-            this.type = type;
-        }
+    ProxyType(final int type) {
+      this.type = type;
+    }
 
-        public String toString() {
-            return type;
-        }
+    public int toInt() {
+      return type;
+    }
 
-        public static BridgeBuiltinType fromString(String s) {
-            switch (s) {
-                case "obfs4": return Obfs4;
-                case "meek-azure": return MeekAzure;
-                case "snowflake": return Snowflake;
-            }
-            return Invalid;
-        }
+    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;
+    }
+  }
+
+  public enum BridgeBuiltinType {
+    /* TorSettings.sys.mjs ~ln43:  string: obfs4|meek-azure|snowflake|etc */
+    Invalid("invalid"),
+    Obfs4("obfs4"),
+    MeekAzure("meek-azure"),
+    Snowflake("snowflake");
+
+    private String type;
 
+    BridgeBuiltinType(String type) {
+      this.type = type;
     }
 
-    private boolean loaded = false;
+    public String toString() {
+      return type;
+    }
 
-    public boolean enabled = true;
+    public static BridgeBuiltinType fromString(String s) {
+      switch (s) {
+        case "obfs4":
+          return Obfs4;
+        case "meek-azure":
+          return MeekAzure;
+        case "snowflake":
+          return Snowflake;
+      }
+      return Invalid;
+    }
+  }
 
-    public boolean quickstart = false;
+  private boolean loaded = false;
 
-    // bridges section
-    public boolean bridgesEnabled = false;
-    public BridgeSource bridgesSource = BridgeSource.Invalid;
-    public BridgeBuiltinType bridgesBuiltinType = BridgeBuiltinType.Invalid;
-    public String[] bridgeBridgeStrings;
+  public boolean enabled = true;
 
-    // proxy section
-    public boolean proxyEnabled = false;
-    public ProxyType proxyType = ProxyType.Invalid;
-    public String proxyAddress = "";
-    public int proxyPort = 0;
-    public String proxyUsername = "";
-    public String proxyPassword = "";
+  public boolean quickstart = false;
 
-    // firewall section
-    public boolean firewallEnabled = false;
-    public int[] firewallAllowedPorts;
+  // bridges section
+  public boolean bridgesEnabled = false;
+  public BridgeSource bridgesSource = BridgeSource.Invalid;
+  public BridgeBuiltinType bridgesBuiltinType = BridgeBuiltinType.Invalid;
+  public String[] bridgeBridgeStrings;
 
-    public TorSettings() {
-    }
+  // 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 = BridgeBuiltinType.fromString(bridges.getString("builtin_type"));
+      bridgeBridgeStrings = bridges.getStringArray("bridge_strings");
 
-    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 = BridgeBuiltinType.fromString(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);
-        }
+      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();
+  public GeckoBundle asGeckoBundle() {
+    GeckoBundle bundle = new GeckoBundle();
 
-        GeckoBundle qs = new GeckoBundle();
-        GeckoBundle bridges = new GeckoBundle();
-        GeckoBundle proxy = new GeckoBundle();
-        GeckoBundle firewall = 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.toString());
-        bridges.putStringArray("bridge_strings", bridgeBridgeStrings);
+    bridges.putBoolean("enabled", bridgesEnabled);
+    bridges.putInt("source", bridgesSource.toInt());
+    bridges.putString("builtin_type", bridgesBuiltinType.toString());
+    bridges.putStringArray("bridge_strings", bridgeBridgeStrings);
 
-        qs.putBoolean("enabled", quickstart);
+    qs.putBoolean("enabled", quickstart);
 
-        firewall.putBoolean("enabled", firewallEnabled);
-        firewall.putIntArray("allowed_ports", firewallAllowedPorts);
+    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());
+    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);
+    bundle.putBundle("quickstart", qs);
+    bundle.putBundle("bridges", bridges);
+    bundle.putBundle("proxy", proxy);
+    bundle.putBundle("firewall", firewall);
 
-        return bundle;
-    }
+    return bundle;
+  }
 
-    public boolean isLoaded() {
-        return this.loaded;
-    }
+  public boolean isLoaded() {
+    return this.loaded;
+  }
 }


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java
=====================================
@@ -49,9 +49,7 @@ public class WebRequest extends WebMessage {
   /** The value of the Referer header for this request. */
   public final @Nullable String referrer;
 
-  /**
-   * The value of the origin of this request.
-   */
+  /** The value of the origin of this request. */
   public final @Nullable String origin;
 
   @Retention(RetentionPolicy.SOURCE)
@@ -248,10 +246,10 @@ public class WebRequest extends WebMessage {
      * @param origin A URI String
      * @return This Builder instance.
      */
-     public @NonNull Builder origin(final @Nullable String origin) {
-       mOrigin = origin;
-       return this;
-     }
+    public @NonNull Builder origin(final @Nullable String origin) {
+      mOrigin = origin;
+      return this;
+    }
 
     /**
      * @return A {@link WebRequest} constructed with the values from this Builder instance.


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java
=====================================
@@ -2,71 +2,68 @@ package org.mozilla.geckoview.androidlegacysettings;
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import org.mozilla.gecko.GeckoAppShell;
-
 import java.util.Locale;
+import org.mozilla.gecko.GeckoAppShell;
 
 // 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 final String PREF_BRIDGES_ENABLED = "pref_bridges_enabled";
+  private static final String PREF_BRIDGES_LIST = "pref_bridges_list";
 
-    private static SharedPreferences prefs;
+  private static SharedPreferences prefs;
 
-    // OrbotConstants
-    private final static String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences";
+  // OrbotConstants
+  private static final String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences";
 
+  // tor-android-service utils/TorServiceUtil.java
 
-    // 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);
-        }
+  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 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();
+    // for Locale.getDefault().getLanguage().equals("fa"), bridges were enabled by default (and
+    // it was meek). This was a default set in 2019 code, but it is not a good default anymore,
+    // so we removed the check.
+    return prefs.getBoolean(PREF_BRIDGES_ENABLED, false);
+  }
+
+  public static String getBridgesList() {
+    setContext();
+    String list = prefs.getString(PREF_BRIDGES_LIST, "");
+    // list might be empty if the default PT was used, so check also if bridges are enabled.
+    if (list.isEmpty() && prefs.getBoolean(PREF_BRIDGES_ENABLED, false)) {
+      // Even though the check on the fa locale is not good to enable bridges by default, we
+      // still check it here, because if the list was empty, it was likely that it was the
+      // choice for users with this locale.
+      return (Locale.getDefault().getLanguage().equals("fa")) ? "meek" : "obfs4";
     }
-
-    public static String getString(String key, String def) {
-        setContext();
-        return prefs.getString(key, def);
-    }
-
-    public static boolean bridgesEnabled() {
-        setContext();
-        // for Locale.getDefault().getLanguage().equals("fa"), bridges were enabled by default (and
-        // it was meek). This was a default set in 2019 code, but it is not a good default anymore,
-        // so we removed the check.
-        return prefs.getBoolean(PREF_BRIDGES_ENABLED, false);
-    }
-
-    public static String getBridgesList() {
-        setContext();
-        String list = prefs.getString(PREF_BRIDGES_LIST, "");
-        // list might be empty if the default PT was used, so check also if bridges are enabled.
-        if (list.isEmpty() && prefs.getBoolean(PREF_BRIDGES_ENABLED, false)) {
-            // Even though the check on the fa locale is not good to enable bridges by default, we
-            // still check it here, because if the list was empty, it was likely that it was the
-            // choice for users with this locale.
-            return (Locale.getDefault().getLanguage().equals("fa")) ? "meek": "obfs4";
-        }
-        return list;
-    }
-
-
+    return list;
+  }
 }


=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java
=====================================
@@ -4,70 +4,71 @@ import org.mozilla.geckoview.TorSettings;
 
 public class TorLegacyAndroidSettings {
 
-    private static String PREF_USE_MOZ_PREFS = "tor_use_moz_prefs";
+  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 boolean unmigrated() {
+    return !Prefs.getBoolean(PREF_USE_MOZ_PREFS, false);
+  }
 
-    public static void setUnmigrated() {
-        Prefs.putBoolean(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 void setMigrated() {
+    Prefs.putBoolean(PREF_USE_MOZ_PREFS, true);
+  }
 
-    public static TorSettings loadTorSettings() {
-        TorSettings settings = new TorSettings();
+  public static TorSettings loadTorSettings() {
+    TorSettings settings = new TorSettings();
 
-        // always true, tor is enabled in TB
-        settings.enabled = true;
+    // 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;
+    // firefox-android disconnected quick start a while ago so it's untracked
+    settings.quickstart = false;
 
-        settings.bridgesEnabled = Prefs.bridgesEnabled();
+    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":
-                case "snowflake":
-                    settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.fromString(userDefinedBridgeList);
-                    break;
-                case "meek":
-                    settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.MeekAzure;
-                    break;
-                default:
-                    settings.bridgesSource = TorSettings.BridgeSource.Invalid;
-                    break;
-            }
-        } else {
-            settings.bridgesSource = TorSettings.BridgeSource.UserProvided; // user provided
-            settings.bridgeBridgeStrings = userDefinedBridgeList.split("\r\n");
-        }
+    // 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":
+        case "snowflake":
+          settings.bridgesBuiltinType =
+              TorSettings.BridgeBuiltinType.fromString(userDefinedBridgeList);
+          break;
+        case "meek":
+          settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.MeekAzure;
+          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;
+    // Tor Browser Android doesn't take proxy and firewall settings
+    settings.proxyEnabled = false;
 
-        settings.firewallEnabled = false;
-        settings.firewallAllowedPorts = new int[0];
+    settings.firewallEnabled = false;
+    settings.firewallAllowedPorts = new int[0];
 
-        return settings;
-    }
+    return settings;
+  }
 }


=====================================
toolkit/modules/DomainFrontedRequests.sys.mjs
=====================================
@@ -444,7 +444,7 @@ export class DomainFrontRequestBuilder {
 
   async init(reflector, front) {
     if (this.#inited) {
-      throw new Error("MoatRPC: Already initialized");
+      throw new Error("DomainFrontRequestBuilder: Already initialized");
     }
 
     const meekTransport =
@@ -464,7 +464,7 @@ export class DomainFrontRequestBuilder {
 
   buildHttpHandler(uriString) {
     if (!this.#inited) {
-      throw new Error("MoatRPC: Not initialized");
+      throw new Error("DomainFrontRequestBuilder: Not initialized");
     }
 
     const { proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword } =


=====================================
toolkit/modules/Moat.sys.mjs
=====================================
@@ -119,7 +119,7 @@ export class MoatRPC {
     ch.requestMethod = "HEAD";
 
     const listener = new InternetTestResponseListener();
-    await ch.asyncOpen(listener, ch);
+    ch.asyncOpen(listener, ch);
     return listener.status;
   }
 



View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/70283a2f2939955e4a3c442825c6427390f956a4...464b5a9ba3bd287ecd18c921eb87ba57d7c2eac3

-- 
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/70283a2f2939955e4a3c442825c6427390f956a4...464b5a9ba3bd287ecd18c921eb87ba57d7c2eac3
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/tbb-commits/attachments/20241029/e1bf7b0a/attachment-0001.htm>


More information about the tbb-commits mailing list