From 636130f7921504f1e7339732e54dc0acdb3f74ae Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Tue, 28 Jan 2025 11:16:41 +0100 Subject: [PATCH 01/12] fix automatic bridge selection settings string --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 57da5bf2a..6351ade78 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -250,7 +250,7 @@ <string name="scan_qr_code">Scan QR Code</string> <string name="invalid_code">Invalid code</string> <string name="automatic_bridge">Automatic (recommended)</string> - <string name="automatic_bridge_description">Connection wil be attemptd using the best available birdges and protocols.</string> + <string name="automatic_bridge_description">Connection will be attempted using the best available bridges and protocols.</string> <string name="manual_bridge">Manual Configuration</string> <string name="manual_bridge_description">Select private bridges and specific protocols</string> <string name="censorship_circumvention_description">Manual configuration requires technical understanding. Proceed with caution.</string> -- GitLab From 7b780c06de54d6188a08c4e87334501b342c3e6d Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Tue, 28 Jan 2025 14:02:11 +0100 Subject: [PATCH 02/12] ensure we default to use bridges in case we switch the provider using an invite code --- .../providersetup/fragments/ConfigureProviderFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java index 8b4b7ad8b..2aeaba7fd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java @@ -138,6 +138,10 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Prop if (ProviderSetupObservable.isSetupRunning()) { handleResult(ProviderSetupObservable.getResultCode(), ProviderSetupObservable.getResultData(), true); } else { + Provider provider = setupActivityCallback.getSelectedProvider(); + if (provider != null && provider.hasIntroducer()) { + PreferenceHelper.useBridges(true); + } ProviderSetupObservable.startSetup(); Bundle parameters = new Bundle(); parameters.putString(Constants.COUNTRYCODE, PreferenceHelper.getBaseCountry()); -- GitLab From bb0128e8c9262d77a8857f12b95f38b2cafee9d8 Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Tue, 28 Jan 2025 21:14:58 +0100 Subject: [PATCH 03/12] rename TUNNELING_NONE to TUNNELING_AUTOMATICALLY and DISCOVERY_NONE to DISCOVERY_AUTOMATICALLY --- .../fragments/CensorshipCircumventionFragment.java | 10 +++++----- .../bitmaskclient/base/fragments/SettingsFragment.java | 6 +++--- .../bitmaskclient/base/utils/PreferenceHelper.java | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java index 37f9eb18e..3d6bb52cc 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java @@ -29,11 +29,11 @@ import se.leap.bitmaskclient.databinding.FCensorshipCircumventionBinding; import se.leap.bitmaskclient.eip.EipCommand; public class CensorshipCircumventionFragment extends Fragment { - public static int DISCOVERY_NONE = 100200000; + public static int DISCOVERY_AUTOMATICALLY = 100200000; public static int DISCOVERY_SNOWFLAKE = 100200001; public static int DISCOVERY_INVITE_PROXY = 100200002; - public static int TUNNELING_NONE = 100300000; + public static int TUNNELING_AUTOMATICALLY = 100300000; public static int TUNNELING_OBFS4 = 100300001; public static int TUNNELING_OBFS4_KCP = 100300002; @@ -71,7 +71,7 @@ public class CensorshipCircumventionFragment extends Fragment { RadioButton noneRadioButton = new RadioButton(binding.getRoot().getContext()); noneRadioButton.setText(getText(R.string.automatically_select)); - noneRadioButton.setId(DISCOVERY_NONE); + noneRadioButton.setId(DISCOVERY_AUTOMATICALLY); noneRadioButton.setChecked(!(hasSnowflakePrefs() && getUseSnowflake()) && !ProviderObservable.getInstance().getCurrentProvider().hasIntroducer()); binding.discoveryRadioGroup.addView(noneRadioButton); @@ -91,7 +91,7 @@ public class CensorshipCircumventionFragment extends Fragment { binding.discoveryRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { useBridges(true); - if (checkedId == DISCOVERY_NONE) { + if (checkedId == DISCOVERY_AUTOMATICALLY) { useSnowflake(false); } else if (checkedId == DISCOVERY_SNOWFLAKE) { useSnowflake(true); @@ -115,7 +115,7 @@ public class CensorshipCircumventionFragment extends Fragment { RadioButton noneRadioButton = new RadioButton(binding.getRoot().getContext()); noneRadioButton.setText(getText(R.string.automatically_select)); noneRadioButton.setChecked(!getUseObfs4() && !getUseObfs4Kcp()); - noneRadioButton.setId(TUNNELING_NONE); + noneRadioButton.setId(TUNNELING_AUTOMATICALLY); binding.tunnelingRadioGroup.addView(noneRadioButton); if (ProviderObservable.getInstance().getCurrentProvider().supportsObfs4()) { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java index eb777abc5..1a14995c2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java @@ -3,7 +3,7 @@ package se.leap.bitmaskclient.base.fragments; import static android.view.View.GONE; import static android.view.View.VISIBLE; import static se.leap.bitmaskclient.R.string.advanced_settings; -import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_NONE; +import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_AUTOMATICALLY; import static se.leap.bitmaskclient.base.models.Constants.GATEWAY_PINNING; import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; @@ -105,7 +105,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh if (isChecked) { useSnowflake(false); - setUseTunnel(TUNNELING_NONE); + setUseTunnel(TUNNELING_AUTOMATICALLY); setUsePortHopping(false); } useBridges(isChecked); @@ -153,7 +153,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh private void resetManualConfig() { useSnowflake(false); - setUseTunnel(TUNNELING_NONE); + setUseTunnel(TUNNELING_AUTOMATICALLY); setUsePortHopping(false); useBridges(false); if (VpnStatus.isVPNActive()) { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index 25a9a3fbb..a698630c1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -1,7 +1,7 @@ package se.leap.bitmaskclient.base.utils; import static android.content.Context.MODE_PRIVATE; -import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_NONE; +import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_AUTOMATICALLY; import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_OBFS4; import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_OBFS4_KCP; import static se.leap.bitmaskclient.base.models.Constants.ALLOW_EXPERIMENTAL_TRANSPORTS; @@ -632,7 +632,7 @@ public class PreferenceHelper { } public static int getUseTunnel() { - return getInt(USE_TUNNEL, TUNNELING_NONE); + return getInt(USE_TUNNEL, TUNNELING_AUTOMATICALLY); } public static boolean useIpv6Firewall() { -- GitLab From 457ae5f4d7ebc10c70f6712f2bcf9e10a5b22f26 Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Wed, 29 Jan 2025 01:21:43 +0100 Subject: [PATCH 04/12] Always show autommatic circumvention settings. If a provider doesn't support bridges, this settings still influences the API communication obfuscation. --- .../CensorshipCircumventionFragment.java | 16 +++--- .../base/fragments/SettingsFragment.java | 56 ++++++++++--------- .../base/utils/PreferenceHelper.java | 24 ++++---- .../bitmaskclient/eip/GatewaysManager.java | 3 - .../fragments/CircumventionSetupFragment.java | 8 ++- app/src/main/res/layout/f_settings.xml | 2 + 6 files changed, 56 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java index 3d6bb52cc..888a6f6f0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java @@ -5,6 +5,7 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4Kcp; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUsePortHopping; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseSnowflake; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.hasSnowflakePrefs; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.resetSnowflakeSettings; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUsePortHopping; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUseTunnel; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; @@ -68,12 +69,11 @@ public class CensorshipCircumventionFragment extends Fragment { private void initDiscovery() { - - RadioButton noneRadioButton = new RadioButton(binding.getRoot().getContext()); - noneRadioButton.setText(getText(R.string.automatically_select)); - noneRadioButton.setId(DISCOVERY_AUTOMATICALLY); - noneRadioButton.setChecked(!(hasSnowflakePrefs() && getUseSnowflake()) && !ProviderObservable.getInstance().getCurrentProvider().hasIntroducer()); - binding.discoveryRadioGroup.addView(noneRadioButton); + RadioButton automaticallyRadioButton = new RadioButton(binding.getRoot().getContext()); + automaticallyRadioButton.setText(getText(R.string.automatically_select)); + automaticallyRadioButton.setId(DISCOVERY_AUTOMATICALLY); + automaticallyRadioButton.setChecked(!(hasSnowflakePrefs() && getUseSnowflake()) && !ProviderObservable.getInstance().getCurrentProvider().hasIntroducer()); + binding.discoveryRadioGroup.addView(automaticallyRadioButton); RadioButton snowflakeRadioButton = new RadioButton(binding.getRoot().getContext()); snowflakeRadioButton.setText(getText(R.string.snowflake)); @@ -92,14 +92,12 @@ public class CensorshipCircumventionFragment extends Fragment { binding.discoveryRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { useBridges(true); if (checkedId == DISCOVERY_AUTOMATICALLY) { - useSnowflake(false); + resetSnowflakeSettings(); } else if (checkedId == DISCOVERY_SNOWFLAKE) { useSnowflake(true); } else if (checkedId == DISCOVERY_INVITE_PROXY) { useSnowflake(false); } - - tryReconnectVpn(); }); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java index 1a14995c2..4567bf974 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java @@ -16,6 +16,7 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferUDP; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getShowAlwaysOnDialog; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.preferUDP; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.resetSnowflakeSettings; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setAllowExperimentalTransports; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUseObfuscationPinning; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUsePortHopping; @@ -23,7 +24,7 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUseTunnel; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useObfuscationPinning; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useSnowflake; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.usesManualBridges; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useManualBridgeSettings; import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; import android.app.AlertDialog; @@ -37,10 +38,12 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; +import android.widget.LinearLayout; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatTextView; import androidx.appcompat.widget.SwitchCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; @@ -94,43 +97,42 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh private void initAutomaticCircumventionEntry(View rootView) { IconSwitchEntry automaticCircumvention = rootView.findViewById(R.id.bridge_automatic_switch); - if (ProviderObservable.getInstance().getCurrentProvider().supportsPluggableTransports()) { - automaticCircumvention.setVisibility(VISIBLE); - - automaticCircumvention.setChecked(getUseBridges() && !usesManualBridges()); - automaticCircumvention.setOnCheckedChangeListener((buttonView, isChecked) -> { - if (!buttonView.isPressed()) { - return; - } + automaticCircumvention.setChecked(getUseBridges() && !useManualBridgeSettings()); + automaticCircumvention.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (!buttonView.isPressed()) { + return; + } - if (isChecked) { - useSnowflake(false); - setUseTunnel(TUNNELING_AUTOMATICALLY); - setUsePortHopping(false); - } + if (isChecked) { + resetSnowflakeSettings(); + setUseTunnel(TUNNELING_AUTOMATICALLY); + setUsePortHopping(false); + } else { + useSnowflake(false); + } + if (ProviderObservable.getInstance().getCurrentProvider().supportsPluggableTransports()) { useBridges(isChecked); if (VpnStatus.isVPNActive()) { EipCommand.startVPN(getContext(), false); Toast.makeText(getContext(), R.string.reconnecting, Toast.LENGTH_LONG).show(); } - }); + } + }); - //We check the UI state of the useUdpEntry here as well, in order to avoid a situation - //where both entries are disabled, because both preferences are enabled. - //bridges can be enabled not only from here but also from error handling - boolean useUDP = getPreferUDP() && useUdpEntry.isEnabled(); - automaticCircumvention.setEnabled(!useUDP); - automaticCircumvention.setSubtitle(getString(useUDP?R.string.disabled_while_udp_on:R.string.automatic_bridge_description)); - } else { - automaticCircumvention.setVisibility(GONE); - } + //We check the UI state of the useUdpEntry here as well, in order to avoid a situation + //where both entries are disabled, because both preferences are enabled. + //bridges can be enabled not only from here but also from error handling + boolean useUDP = getPreferUDP() && useUdpEntry.isEnabled(); + automaticCircumvention.setEnabled(!useUDP); + automaticCircumvention.setSubtitle(getString(useUDP ? R.string.disabled_while_udp_on : R.string.automatic_bridge_description)); } private void initManualCircumventionEntry(View rootView) { + LinearLayout manualConfigRoot = rootView.findViewById(R.id.bridge_manual_switch_entry); + manualConfigRoot.setVisibility(ProviderObservable.getInstance().getCurrentProvider().supportsPluggableTransports() ? VISIBLE : GONE); IconTextEntry manualConfiguration = rootView.findViewById(R.id.bridge_manual_switch); - manualConfiguration.setVisibility(ProviderObservable.getInstance().getCurrentProvider().supportsPluggableTransports() ? VISIBLE : GONE); SwitchCompat manualConfigurationSwitch = rootView.findViewById(R.id.bridge_manual_switch_control); - boolean usesManualBridge = usesManualBridges(); + boolean usesManualBridge = useManualBridgeSettings(); manualConfigurationSwitch.setChecked(usesManualBridge); manualConfigurationSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { if (!buttonView.isPressed()) { @@ -148,7 +150,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh //bridges can be enabled not only from here but also from error handling boolean useUDP = getPreferUDP() && useUdpEntry.isEnabled(); manualConfiguration.setEnabled(!useUDP); - manualConfiguration.setSubtitle(getString(useUDP? R.string.disabled_while_udp_on:R.string.manual_bridge_description)); + manualConfiguration.setSubtitle(getString(useUDP ? R.string.disabled_while_udp_on : R.string.manual_bridge_description)); } private void resetManualConfig() { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index a698630c1..0bf5dfb25 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -65,13 +65,10 @@ import androidx.annotation.WorkerThread; import androidx.security.crypto.EncryptedSharedPreferences; import androidx.security.crypto.MasterKey; -import com.google.gson.Gson; - import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; -import java.net.MalformedURLException; import java.net.URL; import java.security.GeneralSecurityException; import java.util.HashMap; @@ -81,9 +78,6 @@ import java.util.Set; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.NativeUtils; -import io.swagger.client.JSON; -import mobile.BitmaskMobile; -import mobilemodels.BitmaskMobileCore; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.base.models.Introducer; import se.leap.bitmaskclient.base.models.Provider; @@ -491,6 +485,10 @@ public class PreferenceHelper { return hasKey(USE_SNOWFLAKE); } + public static void resetSnowflakeSettings() { + removeKey(USE_SNOWFLAKE); + } + public static Boolean getUseSnowflake() { return getBoolean(USE_SNOWFLAKE, true); } @@ -619,12 +617,8 @@ public class PreferenceHelper { return getUseTunnel() == TUNNELING_OBFS4_KCP; } - public static boolean usesManualBridges(){ - return getUseSnowflake() || usesSpecificTunnel() || getUsePortHopping(); - } - - public static boolean usesSpecificTunnel() { - return getUseObfs4() || getUseObfs4Kcp(); + public static boolean useManualBridgeSettings(){ + return (hasSnowflakePrefs() && getUseSnowflake()) || getUseObfs4() || getUseObfs4Kcp() || getUsePortHopping(); } public static void setUseTunnel(int tunnel) { @@ -709,6 +703,12 @@ public class PreferenceHelper { } } + public static void removeKey(String key) { + synchronized (LOCK) { + preferences.edit().remove(key).apply(); + } + } + public static long getLong(String key, long defValue) { synchronized (LOCK) { return preferences.getLong(key, defValue); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index d7f3b42ea..9655013c6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -37,7 +37,6 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4Kcp; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUsePortHopping; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.usesSpecificTunnel; import android.content.Context; import android.util.Log; @@ -54,10 +53,8 @@ import org.json.JSONObject; import java.io.IOException; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Set; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java index 58fccc651..d7d8516eb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java @@ -1,5 +1,6 @@ package se.leap.bitmaskclient.providersetup.fragments; +import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_AUTOMATICALLY; import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; import android.graphics.Typeface; @@ -35,14 +36,17 @@ public class CircumventionSetupFragment extends BaseSetupFragment implements Can if (binding.rbCircumvention.getId() == checkedId) { PreferenceHelper.useBridges(true); PreferenceHelper.useSnowflake(true); + PreferenceHelper.setUseTunnel(TUNNELING_AUTOMATICALLY); binding.tvCircumventionDetailDescription.setVisibility(View.VISIBLE); binding.rbCircumvention.setTypeface(Typeface.DEFAULT, Typeface.BOLD); binding.rbPlainVpn.setTypeface(Typeface.DEFAULT, Typeface.NORMAL); return; } - + // otherwise don't use obfuscation PreferenceHelper.useBridges(false); - PreferenceHelper.useSnowflake(false); + PreferenceHelper.resetSnowflakeSettings(); + PreferenceHelper.setUsePortHopping(false); + PreferenceHelper.setUseTunnel(TUNNELING_AUTOMATICALLY); binding.tvCircumventionDetailDescription.setVisibility(View.GONE); binding.rbPlainVpn.setTypeface(Typeface.DEFAULT, Typeface.BOLD); binding.rbCircumvention.setTypeface(Typeface.DEFAULT, Typeface.NORMAL); diff --git a/app/src/main/res/layout/f_settings.xml b/app/src/main/res/layout/f_settings.xml index e7b4356f9..87a974553 100644 --- a/app/src/main/res/layout/f_settings.xml +++ b/app/src/main/res/layout/f_settings.xml @@ -60,9 +60,11 @@ app:text="@string/automatic_bridge" app:subtitle="@string/automatic_bridge_description" app:icon="@drawable/bridge_automatic" + android:visibility="visible" app:singleLine="false" /> <LinearLayout + android:id="@+id/bridge_manual_switch_entry" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> -- GitLab From a6494501cf6475fcc4c72610894e56b584f63fa4 Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Wed, 29 Jan 2025 01:26:03 +0100 Subject: [PATCH 05/12] provider setup: reset circumvention settings to defaults if a provider gets configured via an invite code. This ensures that the circumvention settings are correctly reset when switching between providers --- .../fragments/ConfigureProviderFragment.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java index 2aeaba7fd..fa705c309 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java @@ -7,11 +7,15 @@ import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE; import static se.leap.bitmaskclient.R.string.app_name; import static se.leap.bitmaskclient.R.string.description_configure_provider; import static se.leap.bitmaskclient.R.string.description_configure_provider_circumvention; +import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_AUTOMATICALLY; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseSnowflake; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUsePortHopping; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUseTunnel; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useSnowflake; import static se.leap.bitmaskclient.base.utils.ViewHelper.animateContainerVisibility; import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE; @@ -140,7 +144,11 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Prop } else { Provider provider = setupActivityCallback.getSelectedProvider(); if (provider != null && provider.hasIntroducer()) { - PreferenceHelper.useBridges(true); + // enable automatic selection of bridges + useSnowflake(false); + setUseTunnel(TUNNELING_AUTOMATICALLY); + setUsePortHopping(false); + PreferenceHelper.useBridges(true); } ProviderSetupObservable.startSetup(); Bundle parameters = new Bundle(); -- GitLab From ba06108aa2efa042b28b41e7834080789120e6b6 Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Wed, 29 Jan 2025 01:39:23 +0100 Subject: [PATCH 06/12] show configuration logs detail container only if VPN is not running --- .../providersetup/fragments/ConfigureProviderFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java index fa705c309..b9051b1e2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java @@ -13,6 +13,7 @@ import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseSnowflake; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.hasSnowflakePrefs; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUsePortHopping; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUseTunnel; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useSnowflake; @@ -52,6 +53,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; +import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Constants; import se.leap.bitmaskclient.base.models.Provider; @@ -130,7 +132,7 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Prop public void onFragmentSelected() { super.onFragmentSelected(); ignoreProviderAPIUpdates = false; - binding.detailContainer.setVisibility(getUseSnowflake() ? VISIBLE : GONE); + binding.detailContainer.setVisibility(!VpnStatus.isVPNActive() && hasSnowflakePrefs() && getUseSnowflake() ? VISIBLE : GONE); binding.tvCircumventionDescription.setText(getUseSnowflake() ? getString(description_configure_provider_circumvention, getString(app_name)) : getString(description_configure_provider, getString(app_name))); if (!isDefaultBitmask()) { Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.setup_progress_spinner, null); -- GitLab From 8feb66a1e6067540ae30c691a6ed585e10be4abd Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Wed, 29 Jan 2025 02:28:39 +0100 Subject: [PATCH 07/12] remove demo provider from debug builds --- .../assets/demo.bitmask.net.json | 37 ------------------- .../assets/demo.bitmask.net.pem | 10 ----- .../assets/urls/demo.bitmask.net.url | 4 -- 3 files changed, 51 deletions(-) delete mode 100644 app/src/normalProductionFatDebug/assets/demo.bitmask.net.json delete mode 100644 app/src/normalProductionFatDebug/assets/demo.bitmask.net.pem delete mode 100644 app/src/normalProductionFatDebug/assets/urls/demo.bitmask.net.url diff --git a/app/src/normalProductionFatDebug/assets/demo.bitmask.net.json b/app/src/normalProductionFatDebug/assets/demo.bitmask.net.json deleted file mode 100644 index f5998c9bd..000000000 --- a/app/src/normalProductionFatDebug/assets/demo.bitmask.net.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "api_uri":"https://api.demo.bitmask.net:4430", - "api_version":"3", - "ca_cert_fingerprint":"SHA256: 40ed9d9c13872c1fcba25abdcf26a7b1bdeded433d74fbe1ccb58fbaaab58e23", - "ca_cert_uri":"https://api.demo.bitmask.net/ca.crt", - "default_language":"en", - "description":{ - "en":"This is a demo provider" - }, - "domain":"demo.bitmask.net", - "enrollment_policy":"open", - "languages":[ - "en" - ], - "name":{ - "en":"Demo provider" - }, - "service":{ - "allow_anonymous":true, - "allow_free":true, - "allow_limited_bandwidth":false, - "allow_paid":false, - "allow_registration":false, - "allow_unlimited_bandwidth":true, - "bandwidth_limit":102400, - "default_service_level":1, - "levels":{ - "1":{ - "description":"Please donate.", - "name":"free" - } - } - }, - "services":[ - "openvpn" - ] -} \ No newline at end of file diff --git a/app/src/normalProductionFatDebug/assets/demo.bitmask.net.pem b/app/src/normalProductionFatDebug/assets/demo.bitmask.net.pem deleted file mode 100644 index f1ede7ab4..000000000 --- a/app/src/normalProductionFatDebug/assets/demo.bitmask.net.pem +++ /dev/null @@ -1,10 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBYTCCAQigAwIBAgIBATAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxMRUFQIFJv -b3QgQ0EwHhcNMjQwMjIxMTEzMTUwWhcNMjkwMjIxMTEzNjUwWjAXMRUwEwYDVQQD -EwxMRUFQIFJvb3QgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARKTm8AKkqK -aMI7dEarRRGEOPa3i49YE4bGNHxO97h14urXOROJWjnwHJdJ3dJk16oR0HKohXR7 -jSxyukoonJkgo0UwQzAOBgNVHQ8BAf8EBAMCAqQwEgYDVR0TAQH/BAgwBgEB/wIB -ATAdBgNVHQ4EFgQUMVywfKRY9Ec3n98PVIEu7kyWKHwwCgYIKoZIzj0EAwIDRwAw -RAIgeSMNJ51+EvNJzqsISauhOTbFxiUnnmV2z/+dxYeCPzUCIEMXM/X2ekzHEz6V -l7zSfosiYvtQQL3ML3sLnVMmxdmd ------END CERTIFICATE----- \ No newline at end of file diff --git a/app/src/normalProductionFatDebug/assets/urls/demo.bitmask.net.url b/app/src/normalProductionFatDebug/assets/urls/demo.bitmask.net.url deleted file mode 100644 index 459d6d10b..000000000 --- a/app/src/normalProductionFatDebug/assets/urls/demo.bitmask.net.url +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main_url" : "https://demo.bitmask.net", - "geoip_url" : "https://menshen.demo.bitmask.net/json" -} -- GitLab From 1d4883b2434ef261bc45b5967f697ee7d34c42d9 Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Wed, 29 Jan 2025 02:31:25 +0100 Subject: [PATCH 08/12] update preshipped riseup provider.json --- app/src/custom/assets/riseup.net.json | 52 +++++++++++++-------------- app/src/normal/assets/riseup.net.json | 52 +++++++++++++-------------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/app/src/custom/assets/riseup.net.json b/app/src/custom/assets/riseup.net.json index 5e14abc38..407e2e22d 100644 --- a/app/src/custom/assets/riseup.net.json +++ b/app/src/custom/assets/riseup.net.json @@ -1,37 +1,37 @@ { - "api_uri":"https://api.black.riseup.net:4430", - "api_version":"3", - "ca_cert_fingerprint":"SHA256: dd919b7513b4a1368faa20e38cd3314156805677f48b787cdd9b4a92dec64eb0", - "ca_cert_uri":"https://black.riseup.net/ca.crt", - "default_language":"en", - "description":{ - "en": "Riseup is a non-profit collective in Seattle that provides online communication tools for people and groups working toward liberatory social change." + "api_uri": "https://api.black.riseup.net:4430", + "api_version": "3", + "ca_cert_fingerprint": "SHA256: dd919b7513b4a1368faa20e38cd3314156805677f48b787cdd9b4a92dec64eb0", + "ca_cert_uri": "https://black.riseup.net/ca.crt", + "default_language": "en", + "description": { + "en": "Riseup Networks" }, - "domain":"riseup.net", - "enrollment_policy":"open", - "languages":[ + "domain": "riseup.net", + "enrollment_policy": "open", + "languages": [ "en" ], - "name":{ - "en":"Riseup Networks" + "name": { + "en": "Riseup Networks" }, - "service":{ - "allow_anonymous":true, - "allow_free":true, - "allow_limited_bandwidth":false, - "allow_paid":false, - "allow_registration":false, - "allow_unlimited_bandwidth":true, - "bandwidth_limit":102400, - "default_service_level":1, - "levels":{ - "1":{ - "description":"Please donate.", - "name":"free" + "service": { + "allow_anonymous": true, + "allow_free": true, + "allow_limited_bandwidth": false, + "allow_paid": false, + "allow_registration": false, + "allow_unlimited_bandwidth": true, + "bandwidth_limit": 102400, + "default_service_level": 1, + "levels": { + "1": { + "description": "Please donate.", + "name": "free" } } }, - "services":[ + "services": [ "openvpn" ] } \ No newline at end of file diff --git a/app/src/normal/assets/riseup.net.json b/app/src/normal/assets/riseup.net.json index 5e14abc38..407e2e22d 100644 --- a/app/src/normal/assets/riseup.net.json +++ b/app/src/normal/assets/riseup.net.json @@ -1,37 +1,37 @@ { - "api_uri":"https://api.black.riseup.net:4430", - "api_version":"3", - "ca_cert_fingerprint":"SHA256: dd919b7513b4a1368faa20e38cd3314156805677f48b787cdd9b4a92dec64eb0", - "ca_cert_uri":"https://black.riseup.net/ca.crt", - "default_language":"en", - "description":{ - "en": "Riseup is a non-profit collective in Seattle that provides online communication tools for people and groups working toward liberatory social change." + "api_uri": "https://api.black.riseup.net:4430", + "api_version": "3", + "ca_cert_fingerprint": "SHA256: dd919b7513b4a1368faa20e38cd3314156805677f48b787cdd9b4a92dec64eb0", + "ca_cert_uri": "https://black.riseup.net/ca.crt", + "default_language": "en", + "description": { + "en": "Riseup Networks" }, - "domain":"riseup.net", - "enrollment_policy":"open", - "languages":[ + "domain": "riseup.net", + "enrollment_policy": "open", + "languages": [ "en" ], - "name":{ - "en":"Riseup Networks" + "name": { + "en": "Riseup Networks" }, - "service":{ - "allow_anonymous":true, - "allow_free":true, - "allow_limited_bandwidth":false, - "allow_paid":false, - "allow_registration":false, - "allow_unlimited_bandwidth":true, - "bandwidth_limit":102400, - "default_service_level":1, - "levels":{ - "1":{ - "description":"Please donate.", - "name":"free" + "service": { + "allow_anonymous": true, + "allow_free": true, + "allow_limited_bandwidth": false, + "allow_paid": false, + "allow_registration": false, + "allow_unlimited_bandwidth": true, + "bandwidth_limit": 102400, + "default_service_level": 1, + "levels": { + "1": { + "description": "Please donate.", + "name": "free" } } }, - "services":[ + "services": [ "openvpn" ] } \ No newline at end of file -- GitLab From 5dfe7ac7fa0ed2389dc5615ff9ec599f141dfb58 Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Wed, 29 Jan 2025 02:36:45 +0100 Subject: [PATCH 09/12] provider selection UI: add some comments about where which provider selection entries are added --- .../providersetup/fragments/ProviderSelectionFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java index 66b1dd006..823004b23 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java @@ -75,6 +75,7 @@ public class ProviderSelectionFragment extends BaseSetupFragment implements Canc binding = FProviderSelectionBinding.inflate(inflater, container, false); radioButtons = new ArrayList<>(); + // add configured providers for (int i = 0; i < viewModel.size(); i++) { RadioButton radioButton = new RadioButton(binding.getRoot().getContext()); radioButton.setText(viewModel.getProviderName(i)); @@ -83,13 +84,14 @@ public class ProviderSelectionFragment extends BaseSetupFragment implements Canc radioButtons.add(radioButton); } + // add new provider entry RadioButton addProviderRadioButton = new RadioButton(binding.getRoot().getContext()); addProviderRadioButton.setText(getText(R.string.add_provider)); addProviderRadioButton.setId(ADD_PROVIDER); binding.providerRadioGroup.addView(addProviderRadioButton); radioButtons.add(addProviderRadioButton); - + // invite code entry RadioButton inviteCodeRadioButton = new RadioButton(binding.getRoot().getContext()); inviteCodeRadioButton.setText(R.string.enter_invite_code); inviteCodeRadioButton.setId(INVITE_CODE_PROVIDER); -- GitLab From 383840d7f875bb2447890714c4850da3924a2684 Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Fri, 31 Jan 2025 15:07:39 +0100 Subject: [PATCH 10/12] persist v5 provider on successful provider setup, ensure introducer is also saved --- .../base/utils/PreferenceHelper.java | 24 +++++++++---------- .../providersetup/ProviderApiManagerV5.java | 1 + .../providersetup/ProviderManager.java | 9 ++++--- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index 0bf5dfb25..b7c6db5d7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -71,6 +71,7 @@ import org.json.JSONObject; import java.io.IOException; import java.net.URL; import java.security.GeneralSecurityException; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -212,20 +213,17 @@ public class PreferenceHelper { public static HashMap<String, Provider> getCustomProviders() { Set<String> providerDomains = getCustomProviderDomains(); HashMap<String, Provider> customProviders = new HashMap<>(); - if (providerDomains.size() > 0) { - for (String domain : providerDomains) { - String mainURL = preferences.getString(Provider.MAIN_URL + "." + domain, null); - if (mainURL != null) { - Introducer introducer = null; - try { - introducer = Introducer.fromUrl(BitmaskCoreProvider.getBitmaskMobile().getIntroducerURLByDomain(domain)); - } catch (Exception e) { - e.printStackTrace(); - } - customProviders.put(mainURL, Provider.createCustomProvider(mainURL, domain, introducer)); + for (String domain : providerDomains) { + String mainURL = preferences.getString(Provider.MAIN_URL + "." + domain, null); + if (mainURL != null) { + Introducer introducer = null; + try { + introducer = Introducer.fromUrl(BitmaskCoreProvider.getBitmaskMobile().getIntroducerURLByDomain(domain)); + } catch (Exception e) { + e.printStackTrace(); } + customProviders.put(mainURL, Provider.createCustomProvider(mainURL, domain, introducer)); } - } return customProviders; @@ -851,7 +849,7 @@ public class PreferenceHelper { @Override public byte[] getByteArray(String s) { - String encodedString = preferences.getString(s, ""); + String encodedString = preferences.getString(s, Arrays.toString(Base64.encode(new byte[0], Base64.DEFAULT))); try { return Base64.decode(encodedString, Base64.DEFAULT); } catch (IllegalArgumentException e) { diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java index 9af14eda4..2e2497d51 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java @@ -66,6 +66,7 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro case SET_UP_PROVIDER: result = setupProvider(provider, parameters); if (result.getBoolean(BROADCAST_RESULT_KEY)) { + serviceCallback.saveProvider(provider); eventSender.sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); } else { eventSender.sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java index 63fbde09e..bcb177e2b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java @@ -45,8 +45,11 @@ public class ProviderManager { private boolean addDummyEntry = false; public static ProviderManager getInstance(AssetManager assetsManager) { - if (instance == null) + if (instance == null) { instance = new ProviderManager(assetsManager); + } else { + instance.updateCustomProviders(); + } return instance; } @@ -63,7 +66,7 @@ public class ProviderManager { private ProviderManager(AssetManager assetManager) { this.assetsManager = assetManager; addDefaultProviders(assetManager); - addCustomProviders(); + updateCustomProviders(); } private void addDefaultProviders(AssetManager assetManager) { @@ -117,7 +120,7 @@ public class ProviderManager { } - private void addCustomProviders() { + public void updateCustomProviders() { customProviders = PreferenceHelper.getCustomProviders(); } -- GitLab From c5ee72fb3181df7cff17bed335acf1bcd983997b Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Fri, 31 Jan 2025 18:51:52 +0100 Subject: [PATCH 11/12] udpate bitmask-core-android, including golang fixes wrt. introducer handling --- bitmask-core-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitmask-core-android b/bitmask-core-android index 8b802cc79..46b7f4829 160000 --- a/bitmask-core-android +++ b/bitmask-core-android @@ -1 +1 @@ -Subproject commit 8b802cc791d1d913c03fe57c251d3eb40a6a59a2 +Subproject commit 46b7f48299017d7851f8a16ff395dcac9792df97 -- GitLab From 447cfa0ce606257b5c976ca8cc8cd8656211b9c9 Mon Sep 17 00:00:00 2001 From: cyBerta <cyberta@riseup.net> Date: Mon, 3 Feb 2025 16:11:18 +0100 Subject: [PATCH 12/12] deduplicate code and improve intialization of discovery settings in circumvention settings screen --- .../base/fragments/CensorshipCircumventionFragment.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java index 888a6f6f0..e8789b32c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java @@ -69,19 +69,20 @@ public class CensorshipCircumventionFragment extends Fragment { private void initDiscovery() { + boolean hasIntroducer = ProviderObservable.getInstance().getCurrentProvider().hasIntroducer(); RadioButton automaticallyRadioButton = new RadioButton(binding.getRoot().getContext()); automaticallyRadioButton.setText(getText(R.string.automatically_select)); automaticallyRadioButton.setId(DISCOVERY_AUTOMATICALLY); - automaticallyRadioButton.setChecked(!(hasSnowflakePrefs() && getUseSnowflake()) && !ProviderObservable.getInstance().getCurrentProvider().hasIntroducer()); + automaticallyRadioButton.setChecked(!hasSnowflakePrefs() && !hasIntroducer); binding.discoveryRadioGroup.addView(automaticallyRadioButton); RadioButton snowflakeRadioButton = new RadioButton(binding.getRoot().getContext()); snowflakeRadioButton.setText(getText(R.string.snowflake)); snowflakeRadioButton.setId(DISCOVERY_SNOWFLAKE); - snowflakeRadioButton.setChecked(hasSnowflakePrefs() && getUseSnowflake()); + snowflakeRadioButton.setChecked(!hasIntroducer && hasSnowflakePrefs() && getUseSnowflake()); binding.discoveryRadioGroup.addView(snowflakeRadioButton); - if (ProviderObservable.getInstance().getCurrentProvider().hasIntroducer()) { + if (hasIntroducer) { RadioButton inviteProxyRadioButton = new RadioButton(binding.getRoot().getContext()); inviteProxyRadioButton.setText(getText(R.string.invite_proxy)); inviteProxyRadioButton.setId(DISCOVERY_INVITE_PROXY); -- GitLab