[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