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

Commits:

6 changed files:

Changes:

  • mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
    ... ... @@ -1008,6 +1008,14 @@ public final class GeckoRuntime implements Parcelable {
    1008 1008
         return mPushController;
    
    1009 1009
       }
    
    1010 1010
     
    
    1011
    +  /**
    
    1012
    +   * Get the Tor integration controller for this runtime.
    
    1013
    +   */
    
    1014
    +  @UiThread
    
    1015
    +  public @NonNull TorIntegrationAndroid getTorIntegrationController() {
    
    1016
    +    return mTorIntegration;
    
    1017
    +  }
    
    1018
    +
    
    1011 1019
       /**
    
    1012 1020
        * Appends notes to crash report.
    
    1013 1021
        *
    

  • mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
    ... ... @@ -9,6 +9,10 @@ package org.mozilla.geckoview;
    9 9
     import android.content.Context;
    
    10 10
     import android.util.Log;
    
    11 11
     
    
    12
    +import androidx.annotation.AnyThread;
    
    13
    +import androidx.annotation.NonNull;
    
    14
    +import androidx.annotation.Nullable;
    
    15
    +
    
    12 16
     import java.io.BufferedReader;
    
    13 17
     import java.io.File;
    
    14 18
     import java.io.IOException;
    
    ... ... @@ -22,9 +26,9 @@ import java.nio.file.attribute.PosixFilePermission;
    22 26
     import java.nio.file.attribute.PosixFilePermissions;
    
    23 27
     import java.util.ArrayList;
    
    24 28
     import java.util.HashMap;
    
    29
    +import java.util.HashSet;
    
    25 30
     import java.util.Map;
    
    26 31
     import java.util.Set;
    
    27
    -import java.util.UUID;
    
    28 32
     
    
    29 33
     import org.mozilla.gecko.EventDispatcher;
    
    30 34
     import org.mozilla.gecko.GeckoAppShell;
    
    ... ... @@ -32,13 +36,27 @@ import org.mozilla.gecko.util.BundleEventListener;
    32 36
     import org.mozilla.gecko.util.EventCallback;
    
    33 37
     import org.mozilla.gecko.util.GeckoBundle;
    
    34 38
     
    
    35
    -/* package */ class TorIntegrationAndroid implements BundleEventListener {
    
    39
    +import org.mozilla.geckoview.androidlegacysettings.TorLegacyAndroidSettings;
    
    40
    +
    
    41
    +public class TorIntegrationAndroid implements BundleEventListener {
    
    36 42
         private static final String TAG = "TorIntegrationAndroid";
    
    37 43
     
    
    38
    -    private static final String TOR_EVENT_START = "GeckoView:Tor:StartTor";
    
    39
    -    private static final String TOR_EVENT_STOP = "GeckoView:Tor:StopTor";
    
    40
    -    private static final String MEEK_EVENT_START = "GeckoView:Tor:StartMeek";
    
    41
    -    private static final String MEEK_EVENT_STOP = "GeckoView:Tor:StopMeek";
    
    44
    +    // Events we listen to
    
    45
    +    private static final String EVENT_TOR_START = "GeckoView:Tor:StartTor";
    
    46
    +    private static final String EVENT_TOR_STOP = "GeckoView:Tor:StopTor";
    
    47
    +    private static final String EVENT_MEEK_START = "GeckoView:Tor:StartMeek";
    
    48
    +    private static final String EVENT_MEEK_STOP = "GeckoView:Tor:StopMeek";
    
    49
    +
    
    50
    +    // Events we emit
    
    51
    +    private static final String EVENT_SETTINGS_GET = "GeckoView:Tor:SettingsGet";
    
    52
    +    private static final String EVENT_SETTINGS_SET = "GeckoView:Tor:SettingsSet";
    
    53
    +    private static final String EVENT_SETTINGS_APPLY = "GeckoView:Tor:SettingsApply";
    
    54
    +    private static final String EVENT_SETTINGS_SAVE = "GeckoView:Tor:SettingsSave";
    
    55
    +    private static final String EVENT_BOOTSTRAP_BEGIN = "GeckoView:Tor:BootstrapBegin";
    
    56
    +    private static final String EVENT_BOOTSTRAP_BEGIN_AUTO = "GeckoView:Tor:BootstrapBeginAuto";
    
    57
    +    private static final String EVENT_BOOTSTRAP_CANCEL = "GeckoView:Tor:BootstrapCancel";
    
    58
    +    private static final String EVENT_BOOTSTRAP_GET_STATE = "GeckoView:Tor:BootstrapGetState";
    
    59
    +    private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady";
    
    42 60
     
    
    43 61
         private static final String CONTROL_PORT_FILE = "/control-ipc";
    
    44 62
         private static final String SOCKS_FILE = "/socks-ipc";
    
    ... ... @@ -63,7 +81,9 @@ import org.mozilla.gecko.util.GeckoBundle;
    63 81
         private final HashMap<Integer, MeekTransport> mMeeks = new HashMap<>();
    
    64 82
         private int mMeekCounter;
    
    65 83
     
    
    66
    -    public TorIntegrationAndroid(Context context) {
    
    84
    +    private TorSettings mSettings = null;
    
    85
    +
    
    86
    +    /* package */ TorIntegrationAndroid(Context context) {
    
    67 87
             mLibraryDir = context.getApplicationInfo().nativeLibraryDir;
    
    68 88
             mCacheDir = context.getCacheDir().toPath();
    
    69 89
             mIpcDirectory = mCacheDir + "/tor-private";
    
    ... ... @@ -71,7 +91,7 @@ import org.mozilla.gecko.util.GeckoBundle;
    71 91
             registerListener();
    
    72 92
         }
    
    73 93
     
    
    74
    -    public synchronized void shutdown() {
    
    94
    +    /* package */ synchronized void shutdown() {
    
    75 95
             // FIXME: It seems this never gets called
    
    76 96
             if (mTorProcess != null) {
    
    77 97
                 mTorProcess.shutdown();
    
    ... ... @@ -83,22 +103,36 @@ import org.mozilla.gecko.util.GeckoBundle;
    83 103
             EventDispatcher.getInstance()
    
    84 104
                     .registerUiThreadListener(
    
    85 105
                             this,
    
    86
    -                        TOR_EVENT_START,
    
    87
    -                        MEEK_EVENT_START,
    
    88
    -                        MEEK_EVENT_STOP);
    
    106
    +                        EVENT_TOR_START,
    
    107
    +                        EVENT_MEEK_START,
    
    108
    +                        EVENT_MEEK_STOP,
    
    109
    +                        EVENT_SETTINGS_READY);
    
    89 110
         }
    
    90 111
     
    
    91 112
         @Override // BundleEventListener
    
    92 113
         public synchronized void handleMessage(
    
    93 114
                 final String event, final GeckoBundle message, final EventCallback callback) {
    
    94
    -        if (TOR_EVENT_START.equals(event)) {
    
    115
    +        if (EVENT_TOR_START.equals(event)) {
    
    95 116
                 startDaemon(message, callback);
    
    96
    -        } else if (TOR_EVENT_STOP.equals(event)) {
    
    117
    +        } else if (EVENT_TOR_STOP.equals(event)) {
    
    97 118
                 stopDaemon(message, callback);
    
    98
    -        } else if (MEEK_EVENT_START.equals(event)) {
    
    119
    +        } else if (EVENT_MEEK_START.equals(event)) {
    
    99 120
                 startMeek(message, callback);
    
    100
    -        } else if (MEEK_EVENT_STOP.equals(event)) {
    
    121
    +        } else if (EVENT_MEEK_STOP.equals(event)) {
    
    101 122
                 stopMeek(message, callback);
    
    123
    +        } else if (EVENT_SETTINGS_READY.equals(event)) {
    
    124
    +            loadSettings(message);
    
    125
    +        }
    
    126
    +    }
    
    127
    +
    
    128
    +    private void loadSettings(GeckoBundle message) {
    
    129
    +        if (TorLegacyAndroidSettings.unmigrated()) {
    
    130
    +            mSettings = TorLegacyAndroidSettings.loadTorSettings();
    
    131
    +            setSettings(mSettings);
    
    132
    +            TorLegacyAndroidSettings.setMigrated();
    
    133
    +        } else {
    
    134
    +            GeckoBundle bundle = message.getBundle("settings");
    
    135
    +            mSettings = new TorSettings(bundle);
    
    102 136
             }
    
    103 137
         }
    
    104 138
     
    
    ... ... @@ -145,9 +179,9 @@ import org.mozilla.gecko.util.GeckoBundle;
    145 179
         }
    
    146 180
     
    
    147 181
         class TorProcess extends Thread {
    
    148
    -        private static final String TOR_EVENT_STARTED = "GeckoView:Tor:TorStarted";
    
    149
    -        private static final String TOR_EVENT_START_FAILED = "GeckoView:Tor:TorStartFailed";
    
    150
    -        private static final String TOR_EVENT_EXITED = "GeckoView:Tor:TorExited";
    
    182
    +        private static final String EVENT_TOR_STARTED = "GeckoView:Tor:TorStarted";
    
    183
    +        private static final String EVENT_TOR_START_FAILED = "GeckoView:Tor:TorStartFailed";
    
    184
    +        private static final String EVENT_TOR_EXITED = "GeckoView:Tor:TorExited";
    
    151 185
             private final String mHandle;
    
    152 186
             private Process mProcess = null;
    
    153 187
     
    
    ... ... @@ -202,14 +236,14 @@ import org.mozilla.gecko.util.GeckoBundle;
    202 236
                     final GeckoBundle data = new GeckoBundle(2);
    
    203 237
                     data.putString("handle", mHandle);
    
    204 238
                     data.putString("error", e.getMessage());
    
    205
    -                EventDispatcher.getInstance().dispatch(TOR_EVENT_START_FAILED, data);
    
    239
    +                EventDispatcher.getInstance().dispatch(EVENT_TOR_START_FAILED, data);
    
    206 240
                     return;
    
    207 241
                 }
    
    208 242
                 Log.i(TAG, "Tor process " + mHandle + " started.");
    
    209 243
                 {
    
    210 244
                     final GeckoBundle data = new GeckoBundle(1);
    
    211 245
                     data.putString("handle", mHandle);
    
    212
    -                EventDispatcher.getInstance().dispatch(TOR_EVENT_STARTED, data);
    
    246
    +                EventDispatcher.getInstance().dispatch(EVENT_TOR_STARTED, data);
    
    213 247
                 }
    
    214 248
                 try {
    
    215 249
                     BufferedReader reader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
    
    ... ... @@ -232,7 +266,7 @@ import org.mozilla.gecko.util.GeckoBundle;
    232 266
                 // FIXME: We usually don't reach this when the application is killed!
    
    233 267
                 // So, we don't do our cleanup.
    
    234 268
                 Log.i(TAG, "Tor process " + mHandle + " has exited.");
    
    235
    -            EventDispatcher.getInstance().dispatch(TOR_EVENT_EXITED, data);
    
    269
    +            EventDispatcher.getInstance().dispatch(EVENT_TOR_EXITED, data);
    
    236 270
             }
    
    237 271
     
    
    238 272
             private void cleanIpcDirectory() {
    
    ... ... @@ -432,4 +466,71 @@ import org.mozilla.gecko.util.GeckoBundle;
    432 466
                 }
    
    433 467
             }
    
    434 468
         }
    
    469
    +
    
    470
    +    public static class BootstrapState {
    
    471
    +        // FIXME: We can do better than this :)
    
    472
    +        public GeckoBundle mBundle;
    
    473
    +
    
    474
    +        BootstrapState(GeckoBundle bundle) {
    
    475
    +            mBundle = bundle;
    
    476
    +        }
    
    477
    +    }
    
    478
    +
    
    479
    +    public interface BootstrapStateChangeListener {
    
    480
    +        void onBootstrapStateChange(BootstrapState state);
    
    481
    +    }
    
    482
    +
    
    483
    +    public @NonNull GeckoResult<GeckoBundle> getSettings() {
    
    484
    +        return EventDispatcher.getInstance().queryBundle(EVENT_SETTINGS_GET);
    
    485
    +    }
    
    486
    +
    
    487
    +    public @NonNull GeckoResult<Void> setSettings(final TorSettings settings) {
    
    488
    +        return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SET, settings.asGeckoBundle());
    
    489
    +    }
    
    490
    +
    
    491
    +    public @NonNull GeckoResult<Void> applySettings() {
    
    492
    +        return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_APPLY);
    
    493
    +    }
    
    494
    +
    
    495
    +    public @NonNull GeckoResult<Void> saveSettings() {
    
    496
    +        return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SAVE);
    
    497
    +    }
    
    498
    +
    
    499
    +    public @NonNull GeckoResult<Void> beginBootstrap() {
    
    500
    +        return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN);
    
    501
    +    }
    
    502
    +
    
    503
    +    public @NonNull GeckoResult<Void> beginAutoBootstrap(final String countryCode) {
    
    504
    +        final GeckoBundle bundle = new GeckoBundle(1);
    
    505
    +        bundle.putString("countryCode", countryCode);
    
    506
    +        return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN_AUTO, bundle);
    
    507
    +    }
    
    508
    +
    
    509
    +    public @NonNull GeckoResult<Void> beginAutoBootstrap() {
    
    510
    +        return beginAutoBootstrap(null);
    
    511
    +    }
    
    512
    +
    
    513
    +    public @NonNull GeckoResult<Void> cancelBootstrap() {
    
    514
    +        return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_CANCEL);
    
    515
    +    }
    
    516
    +
    
    517
    +    public @NonNull GeckoResult<BootstrapState> getBootstrapState() {
    
    518
    +        return EventDispatcher.getInstance().queryBundle(EVENT_BOOTSTRAP_GET_STATE).map(new GeckoResult.OnValueMapper<>() {
    
    519
    +            @AnyThread
    
    520
    +            @Nullable
    
    521
    +            public BootstrapState onValue(@Nullable GeckoBundle value) throws Throwable {
    
    522
    +                return new BootstrapState(value);
    
    523
    +            }
    
    524
    +        });
    
    525
    +    }
    
    526
    +
    
    527
    +    public void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
    
    528
    +        mBootstrapStateListeners.add(listener);
    
    529
    +    }
    
    530
    +
    
    531
    +    public void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
    
    532
    +        mBootstrapStateListeners.remove(listener);
    
    533
    +    }
    
    534
    +
    
    535
    +    private final HashSet<BootstrapStateChangeListener> mBootstrapStateListeners = new HashSet<>();
    
    435 536
     }

  • mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java
    1
    +package org.mozilla.geckoview;
    
    2
    +
    
    3
    +import android.util.Log;
    
    4
    +
    
    5
    +import org.json.JSONArray;
    
    6
    +import org.json.JSONObject;
    
    7
    +import org.mozilla.gecko.util.GeckoBundle;
    
    8
    +
    
    9
    +import java.io.ByteArrayInputStream;
    
    10
    +import java.io.File;
    
    11
    +import java.io.FileOutputStream;
    
    12
    +import java.io.IOException;
    
    13
    +import java.io.InputStream;
    
    14
    +import java.io.PrintStream;
    
    15
    +import java.io.SequenceInputStream;
    
    16
    +import java.io.UnsupportedEncodingException;
    
    17
    +import java.util.ArrayList;
    
    18
    +import java.util.Arrays;
    
    19
    +import java.util.List;
    
    20
    +import java.util.Locale;
    
    21
    +import java.util.stream.Collectors;
    
    22
    +
    
    23
    +public class TorSettings {
    
    24
    +
    
    25
    +    public enum BridgeSource {
    
    26
    +        Invalid(-1),
    
    27
    +        BuiltIn(0),
    
    28
    +        BridgeDB(1),
    
    29
    +        UserProvided(2);
    
    30
    +
    
    31
    +        private int source;
    
    32
    +
    
    33
    +        BridgeSource(final int source) {
    
    34
    +            this.source = source;
    
    35
    +        }
    
    36
    +
    
    37
    +        public static BridgeSource fromInt(int i) {
    
    38
    +            switch (i) {
    
    39
    +                case -1: return Invalid;
    
    40
    +                case 0: return BuiltIn;
    
    41
    +                case 1: return BridgeDB;
    
    42
    +                case 2: return UserProvided;
    
    43
    +            }
    
    44
    +            return Invalid;
    
    45
    +        }
    
    46
    +
    
    47
    +        public int toInt() {
    
    48
    +            return this.source;
    
    49
    +        }
    
    50
    +    }
    
    51
    +
    
    52
    +    public enum ProxyType {
    
    53
    +        Invalid(-1),
    
    54
    +        Socks4(0),
    
    55
    +        Socks5(1),
    
    56
    +        HTTPS(2);
    
    57
    +
    
    58
    +        private int type;
    
    59
    +
    
    60
    +        ProxyType(final int type) {
    
    61
    +            this.type = type;
    
    62
    +        }
    
    63
    +
    
    64
    +        public int toInt() {
    
    65
    +            return type;
    
    66
    +        }
    
    67
    +
    
    68
    +        public static ProxyType fromInt(int i) {
    
    69
    +            switch (i) {
    
    70
    +                case -1: return Invalid;
    
    71
    +                case 0: return Socks4;
    
    72
    +                case 1: return Socks5;
    
    73
    +                case 2: return HTTPS;
    
    74
    +            }
    
    75
    +            return Invalid;
    
    76
    +        }
    
    77
    +    }
    
    78
    +
    
    79
    +    private boolean loaded = false;
    
    80
    +
    
    81
    +    public boolean enabled = true;
    
    82
    +
    
    83
    +    public boolean quickstart = false;
    
    84
    +
    
    85
    +    // bridges section
    
    86
    +    public boolean bridgesEnabled = false;
    
    87
    +    public BridgeSource bridgesSource = BridgeSource.Invalid;
    
    88
    +    public String bridgesBuiltinType = "";
    
    89
    +    public String[] bridgeBridgeStrings;
    
    90
    +
    
    91
    +    // proxy section
    
    92
    +    public boolean proxyEnabled = false;
    
    93
    +    public ProxyType proxyType = ProxyType.Invalid;
    
    94
    +    public String proxyAddress = "";
    
    95
    +    public int proxyPort = 0;
    
    96
    +    public String proxyUsername = "";
    
    97
    +    public String proxyPassword = "";
    
    98
    +
    
    99
    +    // firewall section
    
    100
    +    public boolean firewallEnabled = false;
    
    101
    +    public int[] firewallAllowedPorts;
    
    102
    +
    
    103
    +    public TorSettings() {
    
    104
    +    }
    
    105
    +
    
    106
    +    public TorSettings(GeckoBundle bundle) {
    
    107
    +        try {
    
    108
    +            GeckoBundle qs = bundle.getBundle("quickstart");
    
    109
    +            GeckoBundle bridges = bundle.getBundle("bridges");
    
    110
    +            GeckoBundle proxy = bundle.getBundle("proxy");
    
    111
    +            GeckoBundle firewall = bundle.getBundle("firewall");
    
    112
    +
    
    113
    +            bridgesEnabled = bridges.getBoolean("enabled");
    
    114
    +            bridgesSource = BridgeSource.fromInt(bridges.getInt("source"));
    
    115
    +            bridgesBuiltinType = bridges.getString("builtin_type");
    
    116
    +            bridgeBridgeStrings = bridges.getStringArray("bridge_strings");
    
    117
    +
    
    118
    +            quickstart = qs.getBoolean("enabled");
    
    119
    +
    
    120
    +            firewallEnabled = firewall.getBoolean("enabled");
    
    121
    +            firewallAllowedPorts = firewall.getIntArray("allowed_ports");
    
    122
    +
    
    123
    +            proxyEnabled = proxy.getBoolean("enabled");
    
    124
    +            proxyAddress = proxy.getString("address");
    
    125
    +            proxyUsername = proxy.getString("username");
    
    126
    +            proxyPassword = proxy.getString("password");
    
    127
    +            proxyPort = proxy.getInt("port");
    
    128
    +            proxyType = ProxyType.fromInt(proxy.getInt("type"));
    
    129
    +
    
    130
    +            loaded = true;
    
    131
    +        } catch (Exception e) {
    
    132
    +            Log.e("TorSettings", "bundle access error: " + e.toString(), e);
    
    133
    +        }
    
    134
    +    }
    
    135
    +
    
    136
    +    public GeckoBundle asGeckoBundle() {
    
    137
    +        GeckoBundle bundle = new GeckoBundle();
    
    138
    +
    
    139
    +        GeckoBundle qs = new GeckoBundle();
    
    140
    +        GeckoBundle bridges = new GeckoBundle();
    
    141
    +        GeckoBundle proxy = new GeckoBundle();
    
    142
    +        GeckoBundle firewall = new GeckoBundle();
    
    143
    +
    
    144
    +        bridges.putBoolean("enabled", bridgesEnabled);
    
    145
    +        bridges.putInt("source", bridgesSource.toInt());
    
    146
    +        bridges.putString("builtin_type", bridgesBuiltinType);
    
    147
    +        bridges.putStringArray("bridge_strings", bridgeBridgeStrings);
    
    148
    +
    
    149
    +        qs.putBoolean("enabled", quickstart);
    
    150
    +
    
    151
    +        firewall.putBoolean("enabled", firewallEnabled);
    
    152
    +        firewall.putIntArray("allowed_ports", firewallAllowedPorts);
    
    153
    +
    
    154
    +        proxy.putBoolean("enabled", proxyEnabled);
    
    155
    +        proxy.putString("address", proxyAddress);
    
    156
    +        proxy.putString("username", proxyUsername);
    
    157
    +        proxy.putString("password", proxyPassword);
    
    158
    +        proxy.putInt("port", proxyPort);
    
    159
    +        proxy.putInt("type", proxyType.toInt());
    
    160
    +
    
    161
    +        bundle.putBundle("quickstart", qs);
    
    162
    +        bundle.putBundle("bridges", bridges);
    
    163
    +        bundle.putBundle("proxy", proxy);
    
    164
    +        bundle.putBundle("firewall", firewall);
    
    165
    +
    
    166
    +        return bundle;
    
    167
    +    }
    
    168
    +
    
    169
    +    public boolean isLoaded() {
    
    170
    +        return this.loaded;
    
    171
    +    }
    
    172
    +}

  • mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java
    1
    +package org.mozilla.geckoview.androidlegacysettings;
    
    2
    +
    
    3
    +import android.content.Context;
    
    4
    +import android.content.SharedPreferences;
    
    5
    +import org.mozilla.gecko.GeckoAppShell;
    
    6
    +
    
    7
    +import java.util.Locale;
    
    8
    +
    
    9
    +// tor-android-service utils/Prefs.java
    
    10
    +
    
    11
    +/* package */ class Prefs {
    
    12
    +    private final static String PREF_BRIDGES_ENABLED = "pref_bridges_enabled";
    
    13
    +    private final static String PREF_BRIDGES_LIST = "pref_bridges_list";
    
    14
    +
    
    15
    +    private static SharedPreferences prefs;
    
    16
    +
    
    17
    +    // OrbotConstants
    
    18
    +    private final static String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences";
    
    19
    +
    
    20
    +
    
    21
    +    // tor-android-service utils/TorServiceUtil.java
    
    22
    +
    
    23
    +    private static void setContext() {
    
    24
    +        if (prefs == null) {
    
    25
    +            prefs = GeckoAppShell.getApplicationContext().getSharedPreferences(PREF_TOR_SHARED_PREFS,
    
    26
    +                    Context.MODE_MULTI_PROCESS);
    
    27
    +        }
    
    28
    +    }
    
    29
    +
    
    30
    +    public static boolean getBoolean(String key, boolean def) {
    
    31
    +        setContext();
    
    32
    +        return prefs.getBoolean(key, def);
    
    33
    +    }
    
    34
    +
    
    35
    +    public static void putBoolean(String key, boolean value) {
    
    36
    +        setContext();
    
    37
    +        prefs.edit().putBoolean(key, value).apply();
    
    38
    +    }
    
    39
    +
    
    40
    +    public static void putString(String key, String value) {
    
    41
    +        setContext();
    
    42
    +        prefs.edit().putString(key, value).apply();
    
    43
    +    }
    
    44
    +
    
    45
    +    public static String getString(String key, String def) {
    
    46
    +        setContext();
    
    47
    +        return prefs.getString(key, def);
    
    48
    +    }
    
    49
    +
    
    50
    +    public static boolean bridgesEnabled() {
    
    51
    +        setContext();
    
    52
    +        return prefs.getBoolean(PREF_BRIDGES_ENABLED, false);
    
    53
    +    }
    
    54
    +
    
    55
    +    public static String getBridgesList() {
    
    56
    +        setContext();
    
    57
    +        // was "meek" for (Locale.getDefault().getLanguage().equals("fa")) and "obfs4" for the rest from a 2019 commit
    
    58
    +        // but that has stopped representing a good default sometime since so not importing for new users
    
    59
    +        String list = prefs.getString(PREF_BRIDGES_LIST, "");
    
    60
    +        return list;
    
    61
    +    }
    
    62
    +
    
    63
    +
    
    64
    +}

  • mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java
    1
    +package org.mozilla.geckoview.androidlegacysettings;
    
    2
    +
    
    3
    +import java.io.IOException;
    
    4
    +
    
    5
    +import android.content.SharedPreferences;
    
    6
    +
    
    7
    +import org.mozilla.gecko.GeckoAppShell;
    
    8
    +
    
    9
    +import org.mozilla.geckoview.TorSettings;
    
    10
    +
    
    11
    +public class TorLegacyAndroidSettings {
    
    12
    +
    
    13
    +    private static String PREF_USE_MOZ_PREFS = "tor_use_moz_prefs";
    
    14
    +
    
    15
    +    public static boolean unmigrated() {
    
    16
    +        return !Prefs.getBoolean(PREF_USE_MOZ_PREFS, false);
    
    17
    +    }
    
    18
    +
    
    19
    +    public static void setUnmigrated() {
    
    20
    +        Prefs.putBoolean(PREF_USE_MOZ_PREFS, false);
    
    21
    +    }
    
    22
    +
    
    23
    +    public static void setMigrated() {
    
    24
    +        Prefs.putBoolean(PREF_USE_MOZ_PREFS, true);
    
    25
    +    }
    
    26
    +
    
    27
    +    public static TorSettings loadTorSettings() {
    
    28
    +        TorSettings settings = new TorSettings();
    
    29
    +
    
    30
    +        // always true, tor is enabled in TB
    
    31
    +        settings.enabled = true;
    
    32
    +
    
    33
    +        // firefox-android disconnected quick start a while ago so it's untracked
    
    34
    +        settings.quickstart = false;
    
    35
    +
    
    36
    +        settings.bridgesEnabled = Prefs.bridgesEnabled();
    
    37
    +
    
    38
    +        // tor-android-service CustomTorInstaller.java
    
    39
    +/*
    
    40
    +        BridgesList is an overloaded field, which can cause some confusion.
    
    41
    +        The list can be:
    
    42
    +          1) a filter like obfs4, meek, or snowflake OR
    
    43
    +          2) it can be a custom bridge
    
    44
    +        For (1), we just pass back all bridges, the filter will occur
    
    45
    +          elsewhere in the library.
    
    46
    +        For (2) we return the bridge list as a raw stream.
    
    47
    +        If length is greater than 9, then we know this is a custom bridge
    
    48
    +     */
    
    49
    +        String userDefinedBridgeList = Prefs.getBridgesList();
    
    50
    +        boolean userDefinedBridge = userDefinedBridgeList.length() > 9;
    
    51
    +        // Terrible hack. Must keep in sync with topl::addBridgesFromResources.
    
    52
    +        if (!userDefinedBridge) {
    
    53
    +            settings.bridgesSource = TorSettings.BridgeSource.BuiltIn;
    
    54
    +            switch (userDefinedBridgeList) {
    
    55
    +                case "obfs4":
    
    56
    +                    settings.bridgesBuiltinType = "objs4";
    
    57
    +                    break;
    
    58
    +                case "meek":
    
    59
    +                    settings.bridgesBuiltinType = "meek_azure";
    
    60
    +                    break;
    
    61
    +                case "snowflake":
    
    62
    +                    settings.bridgesBuiltinType = "snowflake";
    
    63
    +                    break;
    
    64
    +                default:
    
    65
    +                    settings.bridgesSource = TorSettings.BridgeSource.Invalid;
    
    66
    +                    break;
    
    67
    +            }
    
    68
    +        } else {
    
    69
    +            settings.bridgesSource = TorSettings.BridgeSource.UserProvided; // user provided
    
    70
    +            settings.bridgeBridgeStrings = userDefinedBridgeList.split("\r\n");
    
    71
    +        }
    
    72
    +
    
    73
    +        // Tor Browser Android doesn't take proxy and firewall settings
    
    74
    +        settings.proxyEnabled = false;
    
    75
    +
    
    76
    +        settings.firewallEnabled = false;
    
    77
    +        settings.firewallAllowedPorts = new int[0];
    
    78
    +
    
    79
    +        return settings;
    
    80
    +    }
    
    81
    +}
    
    82
    +
    
    83
    +
    
    84
    +

  • toolkit/modules/TorAndroidIntegration.sys.mjs
    ... ... @@ -8,6 +8,8 @@ const lazy = {};
    8 8
     ChromeUtils.defineESModuleGetters(lazy, {
    
    9 9
       EventDispatcher: "resource://gre/modules/Messaging.sys.mjs",
    
    10 10
       TorConnect: "resource://gre/modules/TorConnect.sys.mjs",
    
    11
    +  TorConnectTopics: "resource://gre/modules/TorConnect.sys.mjs",
    
    12
    +  TorSettingsTopics: "resource://gre/modules/TorSettings.sys.mjs",
    
    11 13
       TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    12 14
       TorSettings: "resource://gre/modules/TorSettings.sys.mjs",
    
    13 15
     });
    
    ... ... @@ -23,11 +25,22 @@ const logger = new ConsoleAPI({
    23 25
       prefix: "TorAndroidIntegration",
    
    24 26
     });
    
    25 27
     
    
    28
    +const EmittedEvents = Object.freeze( {
    
    29
    +  settingsReady: "GeckoView:Tor:SettingsReady",
    
    30
    +  settingsChanged: "GeckoView:Tor:SettingsChanged",
    
    31
    +});
    
    32
    +
    
    26 33
     const ListenedEvents = Object.freeze({
    
    27 34
       settingsGet: "GeckoView:Tor:SettingsGet",
    
    35
    +  // The data is passed directly to TorSettings.
    
    28 36
       settingsSet: "GeckoView:Tor:SettingsSet",
    
    29 37
       settingsApply: "GeckoView:Tor:SettingsApply",
    
    30 38
       settingsSave: "GeckoView:Tor:SettingsSave",
    
    39
    +  bootstrapBegin: "GeckoView:Tor:BootstrapBegin",
    
    40
    +  // Optionally takes a countryCode, as data.countryCode.
    
    41
    +  bootstrapBeginAuto: "GeckoView:Tor:BootstrapBeginAuto",
    
    42
    +  bootstrapCancel: "GeckoView:Tor:BootstrapCancel",
    
    43
    +  bootstrapGetState: "GeckoView:Tor:BootstrapGetState",
    
    31 44
     });
    
    32 45
     
    
    33 46
     class TorAndroidIntegrationImpl {
    
    ... ... @@ -41,6 +54,14 @@ class TorAndroidIntegrationImpl {
    41 54
     
    
    42 55
         this.#bootstrapMethodReset();
    
    43 56
         Services.prefs.addObserver(Prefs.useNewBootstrap, this);
    
    57
    +
    
    58
    +    for (const topic in lazy.TorConnectTopics) {
    
    59
    +      Services.obs.addObserver(this, lazy.TorConnectTopics[topic]);
    
    60
    +    }
    
    61
    +
    
    62
    +    for (const topic in lazy.TorSettingsTopics) {
    
    63
    +      Services.obs.addObserver(this, lazy.TorSettingsTopics[topic]);
    
    64
    +    }
    
    44 65
       }
    
    45 66
     
    
    46 67
       async #initNewBootstrap() {
    
    ... ... @@ -67,6 +88,14 @@ class TorAndroidIntegrationImpl {
    67 88
               this.#bootstrapMethodReset();
    
    68 89
             }
    
    69 90
             break;
    
    91
    +      case lazy.TorConnectTopics.StateChange:
    
    92
    +        break;
    
    93
    +      case lazy.TorSettingsTopics.Ready:
    
    94
    +        lazy.EventDispatcher.instance.sendRequest({
    
    95
    +          type: EmittedEvents.settingsReady,
    
    96
    +          settings: lazy.TorSettings.getSettings(),
    
    97
    +        });
    
    98
    +        break;
    
    70 99
         }
    
    71 100
       }
    
    72 101
     
    
    ... ... @@ -74,24 +103,36 @@ class TorAndroidIntegrationImpl {
    74 103
         logger.debug(`Received event ${event}`, data);
    
    75 104
         try {
    
    76 105
           switch (event) {
    
    77
    -        case settingsGet:
    
    106
    +        case ListenedEvents.settingsGet:
    
    78 107
               callback?.onSuccess(lazy.TorSettings.getSettings());
    
    79 108
               return;
    
    80
    -        case settingsSet:
    
    109
    +        case ListenedEvents.settingsSet:
    
    81 110
               // This does not throw, so we do not have any way to report the error!
    
    82 111
               lazy.TorSettings.setSettings(data);
    
    83 112
               break;
    
    84
    -        case settingsApply:
    
    113
    +        case ListenedEvents.settingsApply:
    
    85 114
               await lazy.TorSettings.applySettings();
    
    86 115
               break;
    
    87
    -        case settingsSave:
    
    116
    +        case ListenedEvents.settingsSave:
    
    88 117
               await lazy.TorSettings.saveSettings();
    
    89 118
               break;
    
    119
    +        case ListenedEvents.bootstrapBegin:
    
    120
    +          lazy.TorConnect.beginBootstrap();
    
    121
    +          break;
    
    122
    +        case ListenedEvents.bootstrapBeginAuto:
    
    123
    +          lazy.TorConnect.beginAutoBootstrap(data.countryCode);
    
    124
    +          break;
    
    125
    +        case ListenedEvents.bootstrapCancel:
    
    126
    +          lazy.TorConnect.cancelBootstrap();
    
    127
    +          break;
    
    128
    +        case ListenedEvents.bootstrapGetState:
    
    129
    +          callback?.onSuccess(lazy.TorConnect.state);
    
    130
    +          return;
    
    90 131
           }
    
    91 132
           callback?.onSuccess();
    
    92 133
         } catch (e) {
    
    93
    -      logger.error();
    
    94
    -      callback?.sendError(e);
    
    134
    +      logger.error(`Error while handling event ${event}`, e);
    
    135
    +      callback?.onError(e);
    
    95 136
         }
    
    96 137
       }
    
    97 138