From 39f5c390072cc51a60ab17264963c33f55528e46 Mon Sep 17 00:00:00 2001 From: Norbel AMBANUMBEN Date: Sat, 12 Oct 2024 21:21:23 +0100 Subject: chore: bootstrap censorship circumvention fragment. --- .../fragments/CensorshipCircumventionFragment.java | 128 +++++++++++++++++++++ .../base/fragments/SettingsFragment.java | 36 +++--- 2 files changed, 147 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java (limited to 'app/src/main/java') 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 new file mode 100644 index 00000000..cecf98da --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java @@ -0,0 +1,128 @@ +package se.leap.bitmaskclient.base.fragments; + +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.useSnowflake; +import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RadioButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.databinding.FCensorshipCircumventionBinding; + +public class CensorshipCircumventionFragment extends Fragment { + public static int DISCOVERY_NONE = 100200000; + public static int DISCOVERY_SNOWFLAKE = 100200001; + public static int DISCOVERY_INVITE_PROXY = 100200002; + + public static int TUNNELING_NONE = 100300000; + public static int TUNNELING_OBFS4 = 100300001; + public static int TUNNELING_OBFS4_KCP = 100300002; + + private @NonNull FCensorshipCircumventionBinding binding; + + public static CensorshipCircumventionFragment newInstance() { + CensorshipCircumventionFragment fragment = new CensorshipCircumventionFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + binding = FCensorshipCircumventionBinding.inflate(getLayoutInflater(), container, false); + return binding.getRoot(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + setActionBarSubtitle(this, R.string.censorship_circumvention); + initDiscovery(); + initTunneling(); + initPortHopping(); + } + + + private void initDiscovery() { + + RadioButton noneRadioButton = new RadioButton(binding.getRoot().getContext()); + noneRadioButton.setText(getText(R.string.none)); + noneRadioButton.setId(DISCOVERY_NONE); + binding.discoveryRadioGroup.addView(noneRadioButton); + + if (hasSnowflakePrefs()) { + + RadioButton snowflakeRadioButton = new RadioButton(binding.getRoot().getContext()); + snowflakeRadioButton.setText(getText(R.string.snowflake)); + snowflakeRadioButton.setId(DISCOVERY_SNOWFLAKE); + snowflakeRadioButton.setChecked(hasSnowflakePrefs() && getUseSnowflake()); + binding.discoveryRadioGroup.addView(snowflakeRadioButton); + + } + + RadioButton inviteProxyRadioButton = new RadioButton(binding.getRoot().getContext()); + inviteProxyRadioButton.setText(getText(R.string.invite_proxy)); + inviteProxyRadioButton.setId(DISCOVERY_INVITE_PROXY); + binding.discoveryRadioGroup.addView(inviteProxyRadioButton); + + binding.discoveryRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { + if (checkedId == DISCOVERY_NONE) { + useSnowflake(false); + } else if (checkedId == DISCOVERY_SNOWFLAKE) { + useSnowflake(true); + } else if (checkedId == DISCOVERY_INVITE_PROXY) { + useSnowflake(false); + } + }); + } + + + private void initTunneling() { + RadioButton noneRadioButton = new RadioButton(binding.getRoot().getContext()); + noneRadioButton.setText(getText(R.string.none)); + noneRadioButton.setId(TUNNELING_NONE); + binding.tunnelingRadioGroup.addView(noneRadioButton); + + RadioButton obfs4RadioButton = new RadioButton(binding.getRoot().getContext()); + obfs4RadioButton.setText(getText(R.string.tunnelling_obfs4)); + obfs4RadioButton.setId(TUNNELING_OBFS4); + binding.tunnelingRadioGroup.addView(obfs4RadioButton); + + RadioButton obfs4KcpRadioButton = new RadioButton(binding.getRoot().getContext()); + obfs4KcpRadioButton.setText(getText(R.string.tunnelling_obfs4_kcp)); + obfs4KcpRadioButton.setId(TUNNELING_OBFS4_KCP); + binding.tunnelingRadioGroup.addView(obfs4KcpRadioButton); + + binding.tunnelingRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { + if (checkedId == TUNNELING_NONE) { + // TODO set up none + } else if (checkedId == TUNNELING_OBFS4) { + // TODO set up obfs4 + } else if (checkedId == TUNNELING_OBFS4_KCP) { + // TODO set up obfs4 + kcp + } + + }); + } + + private void initPortHopping() { + binding.portHoppingSwitch.findViewById(R.id.material_icon).setVisibility(View.GONE); + binding.portHoppingSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { + // TODO set up port hopping + }); + } +} \ No newline at end of file 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 51bce6d4..4aed0643 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 @@ -14,14 +14,11 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps; 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.getUseSnowflake; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.hasSnowflakePrefs; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.preferUDP; 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.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.ViewHelper.setActionBarSubtitle; import android.app.AlertDialog; @@ -79,7 +76,8 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh initExcludeAppsEntry(view); initPreferUDPEntry(view); initUseBridgesEntry(view); - initUseSnowflakeEntry(view); + initAutomaticCircumventionEntry(view); + initManualCircumventionEntry(view); initFirewallEntry(view); initTetheringEntry(view); initGatewayPinningEntry(view); @@ -89,6 +87,22 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh return view; } + private void initAutomaticCircumventionEntry(View rootView) { + IconSwitchEntry automaticCircumvention = rootView.findViewById(R.id.bridge_automatic_switch); + automaticCircumvention.setOnCheckedChangeListener((buttonView, isChecked) -> { + + }); + } + + private void initManualCircumventionEntry(View rootView) { + FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); + IconSwitchEntry manualConfiguration = rootView.findViewById(R.id.bridge_manual_switch); + manualConfiguration.setOnClickListener((buttonView) -> { + Fragment fragment = CensorshipCircumventionFragment.newInstance(); + fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); + }); + } + @Override public void onDestroy() { PreferenceHelper.unregisterOnSharedPreferenceChangeListener(this); @@ -121,18 +135,6 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh } } - private void initUseSnowflakeEntry(View rootView) { - IconSwitchEntry useSnowflake = rootView.findViewById(R.id.snowflake_switch); - useSnowflake.setVisibility(VISIBLE); - useSnowflake.setChecked(hasSnowflakePrefs() && getUseSnowflake()); - useSnowflake.setOnCheckedChangeListener((buttonView, isChecked) -> { - if (!buttonView.isPressed()) { - return; - } - useSnowflake(isChecked); - }); - } - private void initAlwaysOnVpnEntry(View rootView) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { IconTextEntry alwaysOnVpn = rootView.findViewById(R.id.always_on_vpn); @@ -350,7 +352,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh return; } if (key.equals(USE_BRIDGES) || key.equals(PREFER_UDP)) { - initUseBridgesEntry(rootView); + //initUseBridgesEntry(rootView); initPreferUDPEntry(rootView); } else if (key.equals(USE_IPv6_FIREWALL)) { initFirewallEntry(getView()); -- cgit v1.2.3