diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java index c62ecb854e1352b19e9f2c60b72db88f62065cef..fa7d2fac2fa87ad84636da7a92388969446300db 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java @@ -76,6 +76,7 @@ import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS; import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY; import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT; import static org.briarproject.bramble.api.plugin.TorConstants.ID; +import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_DISABLE_BLOCKED; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_ALWAYS; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER; @@ -128,8 +129,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { LocationUtils locationUtils, SocketFactory torSocketFactory, Clock clock, CircumventionProvider circumventionProvider, Backoff backoff, DuplexPluginCallback callback, - String architecture, - int maxLatency, int maxIdleTime) { + String architecture, int maxLatency, int maxIdleTime) { this.ioExecutor = ioExecutor; this.appContext = appContext; this.networkManager = networkManager; @@ -661,6 +661,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { circumventionProvider.isTorProbablyBlocked(country); Settings s = callback.getSettings(); int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS); + boolean disableWhenBlocked = + s.getBoolean(PREF_TOR_DISABLE_BLOCKED, true); if (LOG.isLoggable(INFO)) { LOG.info("Online: " + online + ", wifi: " + wifi); @@ -681,9 +683,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { LOG.info("Enabling network, using bridges"); enableBridges(true); enableNetwork(true); - } else { + } else if (disableWhenBlocked) { LOG.info("Disabling network, country is blocked"); enableNetwork(false); + } else { + LOG.info("Enabling network but country is blocked"); + enableBridges(false); + enableNetwork(true); } } else { LOG.info("Enabling network"); diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java index 8f265a95ed6a839a2c5c1d560c80b5ee4877650b..6e9f712f9485bb5f2cca638bd4b9112e72456a67 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java @@ -14,6 +14,7 @@ public interface TorConstants { String PREF_TOR_NETWORK = "network"; String PREF_TOR_PORT = "port"; + String PREF_TOR_DISABLE_BLOCKED = "disableWhenBlocked"; int PREF_TOR_NETWORK_NEVER = 0; int PREF_TOR_NETWORK_WIFI = 1; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java index f5c38f23cc92d71d43a2ef6eb4b02ba5e2015329..27467c6a52a3e4fdb88b16ac7c8f1339d8233bd9 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java @@ -43,6 +43,7 @@ import org.briarproject.briar.android.util.UiUtils; import org.briarproject.briar.android.util.UserFeedback; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.logging.Logger; @@ -67,14 +68,19 @@ import static android.provider.Settings.EXTRA_CHANNEL_ID; import static android.provider.Settings.System.DEFAULT_NOTIFICATION_URI; import static android.support.v4.view.ViewCompat.LAYOUT_DIRECTION_LTR; import static android.widget.Toast.LENGTH_SHORT; +import static java.util.Arrays.asList; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE; +import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_DISABLE_BLOCKED; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_ALWAYS; +import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BLOCKED; +import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BRIDGES; import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.now; +import static org.briarproject.bramble.util.StringUtils.join; import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_DARK_THEME; import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_SIGN_IN_REMINDER; import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD; @@ -104,6 +110,7 @@ public class SettingsFragment extends PreferenceFragmentCompat public static final String TOR_NAMESPACE = TorConstants.ID.getString(); public static final String LANGUAGE = "pref_key_language"; public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in"; + public static final String TOR_LOCATION = "pref_key_tor_location"; private static final Logger LOG = Logger.getLogger(SettingsFragment.class.getName()); @@ -112,6 +119,7 @@ public class SettingsFragment extends PreferenceFragmentCompat private ListPreference language; private ListPreference enableBluetooth; private ListPreference torNetwork; + private CheckBoxPreference torBlocked; private CheckBoxPreference notifyPrivateMessages; private CheckBoxPreference notifyGroupMessages; private CheckBoxPreference notifyForumPosts; @@ -150,6 +158,8 @@ public class SettingsFragment extends PreferenceFragmentCompat (ListPreference) findPreference("pref_key_theme"); enableBluetooth = (ListPreference) findPreference("pref_key_bluetooth"); torNetwork = (ListPreference) findPreference("pref_key_tor_network"); + torBlocked = (CheckBoxPreference) findPreference(TOR_LOCATION); + setBlockedCountries(); CheckBoxPreference notifySignIn = (CheckBoxPreference) findPreference(NOTIFY_SIGN_IN); notifyPrivateMessages = (CheckBoxPreference) findPreference( @@ -189,6 +199,7 @@ public class SettingsFragment extends PreferenceFragmentCompat }); enableBluetooth.setOnPreferenceChangeListener(this); torNetwork.setOnPreferenceChangeListener(this); + torBlocked.setOnPreferenceChangeListener(this); if (SDK_INT >= 21) { notifyLockscreen.setVisible(true); notifyLockscreen.setOnPreferenceChangeListener(this); @@ -288,6 +299,14 @@ public class SettingsFragment extends PreferenceFragmentCompat return direction == LAYOUT_DIRECTION_LTR; } + private void setBlockedCountries() { + List<String> countries = new ArrayList<>(asList(BLOCKED)); + countries.removeAll(asList(BRIDGES)); + Collections.sort(countries); + String format = getString(R.string.tor_location_setting_hint_format); + torBlocked.setSummary(String.format(format, join(countries, ", "))); + } + private void loadSettings() { listener.runOnDbThread(() -> { try { @@ -299,19 +318,24 @@ public class SettingsFragment extends PreferenceFragmentCompat logDuration(LOG, "Loading settings", start); boolean btSetting = btSettings.getBoolean(PREF_BT_ENABLE, false); - int torSetting = torSettings.getInt(PREF_TOR_NETWORK, + int torNetworkSetting = torSettings.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS); - displaySettings(btSetting, torSetting); + boolean torBlockedSetting = + torSettings.getBoolean(PREF_TOR_DISABLE_BLOCKED, true); + displaySettings(btSetting, torNetworkSetting, + torBlockedSetting); } catch (DbException e) { logException(LOG, WARNING, e); } }); } - private void displaySettings(boolean btSetting, int torSetting) { + private void displaySettings(boolean btSetting, int torNetworkSetting, + boolean torBlockedSetting) { listener.runOnUiThreadUnlessDestroyed(() -> { enableBluetooth.setValue(Boolean.toString(btSetting)); - torNetwork.setValue(Integer.toString(torSetting)); + torNetwork.setValue(Integer.toString(torNetworkSetting)); + torBlocked.setChecked(torBlockedSetting); if (SDK_INT < 26) { notifyPrivateMessages.setChecked(settings.getBoolean( @@ -371,6 +395,7 @@ public class SettingsFragment extends PreferenceFragmentCompat // - pref_key_notify_sign_in enableBluetooth.setEnabled(enabled); torNetwork.setEnabled(enabled); + torBlocked.setEnabled(enabled); notifyPrivateMessages.setEnabled(enabled); notifyGroupMessages.setEnabled(enabled); notifyForumPosts.setEnabled(enabled); @@ -430,8 +455,11 @@ public class SettingsFragment extends PreferenceFragmentCompat boolean btSetting = Boolean.valueOf((String) newValue); storeBluetoothSettings(btSetting); } else if (preference == torNetwork) { - int torSetting = Integer.valueOf((String) newValue); - storeTorSettings(torSetting); + int torNetworkSetting = Integer.valueOf((String) newValue); + storeTorNetworkSetting(torNetworkSetting); + } else if (preference == torBlocked) { + boolean torBlockedSetting = (Boolean) newValue; + storeTorBlockedSetting(torBlockedSetting); } else if (preference == notifyPrivateMessages) { Settings s = new Settings(); s.putBoolean(PREF_NOTIFY_PRIVATE, (Boolean) newValue); @@ -480,39 +508,33 @@ public class SettingsFragment extends PreferenceFragmentCompat builder.show(); } - private void storeTorSettings(int torSetting) { - listener.runOnDbThread(() -> { - try { - Settings s = new Settings(); - s.putInt(PREF_TOR_NETWORK, torSetting); - long start = now(); - settingsManager.mergeSettings(s, TOR_NAMESPACE); - logDuration(LOG, "Merging settings", start); - } catch (DbException e) { - logException(LOG, WARNING, e); - } - }); + private void storeTorNetworkSetting(int torNetworkSetting) { + Settings s = new Settings(); + s.putInt(PREF_TOR_NETWORK, torNetworkSetting); + mergeSettings(s, TOR_NAMESPACE); + } + + private void storeTorBlockedSetting(boolean torBlockedSetting) { + Settings s = new Settings(); + s.putBoolean(PREF_TOR_DISABLE_BLOCKED, torBlockedSetting); + mergeSettings(s, TOR_NAMESPACE); } private void storeBluetoothSettings(boolean btSetting) { - listener.runOnDbThread(() -> { - try { - Settings s = new Settings(); - s.putBoolean(PREF_BT_ENABLE, btSetting); - long start = now(); - settingsManager.mergeSettings(s, BT_NAMESPACE); - logDuration(LOG, "Merging settings", start); - } catch (DbException e) { - logException(LOG, WARNING, e); - } - }); + Settings s = new Settings(); + s.putBoolean(PREF_BT_ENABLE, btSetting); + mergeSettings(s, BT_NAMESPACE); + } + + private void storeSettings(Settings s) { + mergeSettings(s, SETTINGS_NAMESPACE); } - private void storeSettings(Settings settings) { + private void mergeSettings(Settings s, String namespace) { listener.runOnDbThread(() -> { try { long start = now(); - settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); + settingsManager.mergeSettings(s, namespace); logDuration(LOG, "Merging settings", start); } catch (DbException e) { logException(LOG, WARNING, e); diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index 06a09ddce823d4463d6cdaba9e12a12216e86e2d..086ff8c3febebee793fe29f563b1e5620850fbeb 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -348,6 +348,8 @@ <string name="tor_network_setting_never">Never</string> <string name="tor_network_setting_wifi">Only when using Wi-Fi</string> <string name="tor_network_setting_always">When using Wi-Fi or mobile data</string> + <string name="tor_location_setting_title">Disable Tor based on location</string> + <string name="tor_location_setting_hint_format">Disable Tor in countries where it is likely to be blocked (%1$s)</string> <!-- Settings Security and Panic --> <string name="security_settings_title">Security</string> diff --git a/briar-android/src/main/res/xml/settings.xml b/briar-android/src/main/res/xml/settings.xml index c81fbb2ad497c3493f7e3766678f3b4aeef7dfdd..7f943ba89ea7b4b133987af86f413b8c858b7e7f 100644 --- a/briar-android/src/main/res/xml/settings.xml +++ b/briar-android/src/main/res/xml/settings.xml @@ -44,6 +44,12 @@ android:summary="%s" android:title="@string/tor_network_setting"/> + <CheckBoxPreference + android:defaultValue="true" + android:key="pref_key_tor_location" + android:persistent="false" + android:title="@string/tor_location_setting_title"/> + </PreferenceCategory> <PreferenceCategory