diff options
34 files changed, 571 insertions, 291 deletions
diff --git a/app/build.gradle b/app/build.gradle index b28d9f35..2e6604f2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -93,6 +93,7 @@ dependencies { compile 'com.android.support:appcompat-v7:26.1.0' compile 'com.android.support:design:26.1.0' compile 'com.android.support:support-fragment:26.1.0' + compile 'com.android.support.constraint:constraint-layout:1.0.2' } // Ensure the no-op dependency is always used in JVM tests. diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/BaseTestDashboardFragment.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/BaseTestDashboardFragment.java index 956049dc..e187d424 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/BaseTestDashboardFragment.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/BaseTestDashboardFragment.java @@ -7,7 +7,7 @@ import android.view.View; import com.robotium.solo.Solo; -import se.leap.bitmaskclient.ConfigurationWizard; +import se.leap.bitmaskclient.ProviderListActivity; import se.leap.bitmaskclient.Dashboard; import se.leap.bitmaskclient.R; @@ -43,7 +43,7 @@ public abstract class BaseTestDashboardFragment extends ActivityInstrumentationT void tapSwitchProvider() { solo.clickOnMenuItem(solo.getString(R.string.switch_provider_menu_option)); - solo.waitForActivity(ConfigurationWizard.class); + solo.waitForActivity(ProviderListActivity.class); } private void useRegistered() { diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/TestVpnFragment.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/TestEipFragment.java index 564e251c..4227f19a 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/TestVpnFragment.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/TestEipFragment.java @@ -1,6 +1,6 @@ package se.leap.bitmaskclient.test; -public class TestVpnFragment extends BaseTestDashboardFragment { +public class TestEipFragment extends BaseTestDashboardFragment { /** * This test will fail if Android does not trust VPN connection. diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/TestConfigurationWizard.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/TestProviderListActivity.java index c0d3aab1..4ab705e7 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/TestConfigurationWizard.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/TestProviderListActivity.java @@ -7,15 +7,15 @@ import com.robotium.solo.Solo; import java.io.IOException; -import se.leap.bitmaskclient.ConfigurationWizard; +import se.leap.bitmaskclient.ProviderListActivity; import se.leap.bitmaskclient.R; -public class TestConfigurationWizard extends ActivityInstrumentationTestCase2<ConfigurationWizard> { +public class TestProviderListActivity extends ActivityInstrumentationTestCase2<ProviderListActivity> { private Solo solo; - public TestConfigurationWizard() { - super(ConfigurationWizard.class); + public TestProviderListActivity() { + super(ProviderListActivity.class); } diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderListActivity.java index 6481c9f5..823b5635 100644 --- a/app/src/insecure/java/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/app/src/insecure/java/se/leap/bitmaskclient/ProviderListActivity.java @@ -34,7 +34,7 @@ import se.leap.bitmaskclient.ProviderListContent.ProviderItem; * @author parmegv * @author cyberta */ -public class ConfigurationWizard extends BaseConfigurationWizard { +public class ProviderListActivity extends ProviderListBaseActivity { @Override protected void onItemSelectedLogic() { diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ProviderListContent.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderListContent.java index c8dfc092..88e31c9a 100644 --- a/app/src/insecure/java/se/leap/bitmaskclient/ProviderListContent.java +++ b/app/src/insecure/java/se/leap/bitmaskclient/ProviderListContent.java @@ -20,7 +20,7 @@ import java.util.*; import java.net.*; /** - * Models the provider list shown in the ConfigurationWizard. + * Models the provider list shown in the ProviderListActivity. * * @author parmegv */ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c0ab2c75..2ffb54f4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -93,7 +93,7 @@ android:label="@string/title_activity_main" /> <activity - android:name=".ConfigurationWizard" + android:name=".ProviderListActivity" android:label="@string/configuration_wizard_title" /> <activity diff --git a/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java b/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java index bd8ae228..fbb27b58 100644 --- a/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java @@ -22,8 +22,6 @@ import butterknife.InjectView; import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP; -import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT; public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseActivity { @@ -42,8 +40,8 @@ public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseAct try { JSONObject providerJson = new JSONObject(preferences.getString(Provider.KEY, "")); - setProviderHeaderText(getProviderName()); - description.setText(providerJson.getJSONObject(Provider.DESCRIPTION).getString("en")); + setProviderHeaderText(ConfigHelper.getProviderName(preferences)); + description.setText(ConfigHelper.getDescription(preferences)); // Show only the options allowed by the provider ArrayList<String> optionsList = new ArrayList<>(); @@ -74,7 +72,9 @@ public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseAct intent = new Intent(getApplicationContext(), SignupActivity.class); } else { Log.d(TAG, "use anonymously selected"); - setResult(RESULT_OK); + intent = new Intent(); + intent.putExtra(Provider.KEY, provider); + setResult(RESULT_OK, intent); finish(); return; } diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java index ccdf5064..741a6f56 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java @@ -18,8 +18,10 @@ package se.leap.bitmaskclient; import android.content.SharedPreferences; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.util.Log; +import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.json.JSONObject; import org.spongycastle.util.encoders.Base64; @@ -45,6 +47,7 @@ import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Locale; import static android.R.attr.name; import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED; @@ -261,16 +264,6 @@ public class ConfigHelper { } - public static String getCurrentProviderName(@NonNull SharedPreferences preferences) { - try { - JSONObject providerDefintion = new JSONObject(preferences.getString(Provider.KEY, "")); - return providerDefintion.getString(Provider.DOMAIN); - } catch (JSONException e) { - e.printStackTrace(); - } - return null; - } - public static boolean providerInSharedPreferences(@NonNull SharedPreferences preferences) { return preferences.getBoolean(PROVIDER_CONFIGURED, false); } @@ -288,4 +281,74 @@ public class ConfigHelper { return provider; } + public static String getProviderName(String provider) { + return getProviderName(null, provider); + } + + public static String getProviderName(@Nullable SharedPreferences preferences) { + return getProviderName(preferences,null); + } + + public static String getProviderName(@Nullable SharedPreferences preferences, @Nullable String provider) { + if (provider == null && preferences != null) { + provider = preferences.getString(Provider.KEY, ""); + } + try { + JSONObject providerJson = new JSONObject(provider); + String lang = Locale.getDefault().getLanguage(); + return providerJson.getJSONObject(Provider.NAME).getString(lang); + } catch (JSONException e) { + try { + JSONObject providerJson = new JSONObject(provider); + return providerJson.getJSONObject(Provider.NAME).getString("en"); + } catch (JSONException e2) { + return null; + } + } catch (NullPointerException npe) { + return null; + } + } + + public static String getProviderDomain(SharedPreferences preferences) { + return getProviderDomain(preferences, null); + } + + public static String getProviderDomain(String provider) { + return getProviderDomain(null, provider); + } + + public static String getProviderDomain(@Nullable SharedPreferences preferences, @Nullable String provider) { + if (provider == null && preferences != null) { + provider = preferences.getString(Provider.KEY, ""); + } + try { + JSONObject providerJson = new JSONObject(provider); + return providerJson.getString(Provider.DOMAIN); + } catch (JSONException | NullPointerException e) { + return null; + } + } + + public static String getDescription(SharedPreferences preferences) { + try { + JSONObject providerJson = new JSONObject(preferences.getString(Provider.KEY, "")); + String lang = Locale.getDefault().getLanguage(); + return providerJson.getJSONObject(Provider.DESCRIPTION).getString(lang); + } catch (JSONException e) { + try { + JSONObject providerJson = new JSONObject(preferences.getString(Provider.KEY, "")); + return providerJson.getJSONObject(Provider.DESCRIPTION).getString("en"); + } catch (JSONException e1) { + return null; + } + } + } + + public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider) { + preferences.edit().putBoolean(PROVIDER_CONFIGURED, true). + putString(Provider.MAIN_URL, provider.getMainUrlString()). + putString(Provider.KEY, provider.getDefinitionString()). + putString(Provider.CA_CERT, provider.getCaCert()). + apply(); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java index 1ad12042..79a78fe1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java @@ -11,11 +11,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.Locale; - import butterknife.InjectView; import static android.view.View.GONE; @@ -61,19 +56,19 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity { @Override public void setContentView(View view) { super.setContentView(view); - setProviderHeaderText(getProviderName()); + setProviderHeaderText(ConfigHelper.getProviderName(preferences)); } @Override public void setContentView(int layoutResID) { super.setContentView(layoutResID); - setProviderHeaderText(getProviderName()); + setProviderHeaderText(ConfigHelper.getProviderName(preferences)); } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { super.setContentView(view, params); - setProviderHeaderText(getProviderName()); + setProviderHeaderText(ConfigHelper.getProviderName(preferences)); } protected void setProviderHeaderLogo(@DrawableRes int providerHeaderLogo) { @@ -88,43 +83,6 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity { this.providerHeaderText.setText(providerHeaderText); } - protected String getProviderName() { - return getProviderName(null); - } - - protected String getProviderName(@Nullable String provider) { - if (provider == null) { - provider = preferences.getString(Provider.KEY, ""); - } - try { - JSONObject providerJson = new JSONObject(provider); - String lang = Locale.getDefault().getLanguage(); - return providerJson.getJSONObject(Provider.NAME).getString(lang); - } catch (JSONException e) { - try { - JSONObject providerJson = new JSONObject(provider); - return providerJson.getJSONObject(Provider.NAME).getString("en"); - } catch (JSONException e2) { - return null; - } - } - } - - protected String getProviderDomain() { - return getProviderDomain(null); - } - - protected String getProviderDomain(@Nullable String provider) { - if (provider == null) { - provider = preferences.getString(Provider.KEY, ""); - } - try { - JSONObject providerJson = new JSONObject(provider); - return providerJson.getString(Provider.DOMAIN); - } catch (JSONException e) { - return null; - } - } protected void hideProgressBar() { loadingScreen.setVisibility(GONE); content.setVisibility(VISIBLE); diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 5ccb48b5..a4db5f84 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -87,7 +87,7 @@ public class Dashboard extends ButterKnifeActivity { @InjectView(R.id.providerName) TextView provider_name; - private VpnFragment eip_fragment; + private EipFragment eip_fragment; private UserStatusFragment user_status_fragment; private static Provider provider = new Provider(); @@ -232,7 +232,7 @@ public class Dashboard extends ButterKnifeActivity { private void handleConfigureAlwaysOn(Intent intent) { intent.removeExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE); Log.d(TAG, "start Configuration wizard!"); - startActivityForResult(new Intent(this, ConfigurationWizard.class), REQUEST_CODE_CONFIGURE_LEAP); + startActivityForResult(new Intent(this, ProviderListActivity.class), REQUEST_CODE_CONFIGURE_LEAP); } private void prepareEIP(Bundle savedInstanceState) { @@ -255,7 +255,7 @@ public class Dashboard extends ButterKnifeActivity { if (getIntent().hasExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE)) { getIntent().removeExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE); } - startActivityForResult(new Intent(this, ConfigurationWizard.class), REQUEST_CODE_CONFIGURE_LEAP); + startActivityForResult(new Intent(this, ProviderListActivity.class), REQUEST_CODE_CONFIGURE_LEAP); } @SuppressLint("CommitPrefEdits") private void providerToPreferences(Provider provider) { @@ -273,7 +273,7 @@ public class Dashboard extends ButterKnifeActivity { .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - startActivityForResult(new Intent(Dashboard.this, ConfigurationWizard.class), REQUEST_CODE_CONFIGURE_LEAP); + startActivityForResult(new Intent(Dashboard.this, ProviderListActivity.class), REQUEST_CODE_CONFIGURE_LEAP); } }) .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() { @@ -290,8 +290,8 @@ public class Dashboard extends ButterKnifeActivity { * Inflates permanent UI elements of the View and contains logic for what * service dependent UI elements to include. */ - //TODO: REFACTOR ME! Consider implementing a manager that handles most of VpnFragment's logic about handling EIP commands. - //This way, we could avoid to create UI elements (like fragmentManager.replace(R.id.servicesCollection, eip_fragment, VpnFragment.TAG); ) + //TODO: REFACTOR ME! Consider implementing a manager that handles most of EipFragment's logic about handling EIP commands. + //This way, we could avoid to create UI elements (like fragmentManager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG); ) // just to start services and destroy them afterwards private void buildDashboard(boolean hideAndTurnOnEipOnBoot) { setContentView(R.layout.dashboard); @@ -305,9 +305,9 @@ public class Dashboard extends ButterKnifeActivity { fragment_manager.replace(R.id.user_status_fragment, user_status_fragment, UserStatusFragment.TAG); if (provider.hasEIP()) { - fragment_manager.removePreviousFragment(VpnFragment.TAG); + fragment_manager.removePreviousFragment(EipFragment.TAG); eip_fragment = prepareEipFragment(hideAndTurnOnEipOnBoot); - fragment_manager.replace(R.id.servicesCollection, eip_fragment, VpnFragment.TAG); + fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG); if (hideAndTurnOnEipOnBoot) { onBackPressed(); } @@ -320,13 +320,13 @@ public class Dashboard extends ButterKnifeActivity { * has caused to start Dashboard * @return the created VPNFragment */ - public VpnFragment prepareEipFragment(boolean hideAndTurnOnEipOnBoot) { - VpnFragment eip_fragment = new VpnFragment(); + public EipFragment prepareEipFragment(boolean hideAndTurnOnEipOnBoot) { + EipFragment eip_fragment = new EipFragment(); if (hideAndTurnOnEipOnBoot && !isAlwaysOn()) { preferences.edit().remove(EIP_RESTART_ON_BOOT).apply(); Bundle arguments = new Bundle(); - arguments.putBoolean(VpnFragment.START_EIP_ON_BOOT, true); + arguments.putBoolean(EipFragment.START_EIP_ON_BOOT, true); Log.d(TAG, "set START_EIP_ON_BOOT argument for eip_fragment"); eip_fragment.setArguments(arguments); @@ -416,7 +416,7 @@ public class Dashboard extends ButterKnifeActivity { clearDataOfLastProvider(); switching_provider = false; - startActivityForResult(new Intent(this, ConfigurationWizard.class), REQUEST_CODE_SWITCH_PROVIDER); + startActivityForResult(new Intent(this, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER); } private void clearDataOfLastProvider() { @@ -441,7 +441,7 @@ public class Dashboard extends ButterKnifeActivity { preferenceEditor.apply(); switching_provider = false; - startActivityForResult(new Intent(this, ConfigurationWizard.class), REQUEST_CODE_SWITCH_PROVIDER); + startActivityForResult(new Intent(this, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER); } private static class DashboardReceiver implements ProviderAPIResultReceiver.Receiver{ diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index f1463029..414b1f2a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -24,17 +24,21 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ResultReceiver; import android.support.v4.app.Fragment; +import android.support.v7.widget.AppCompatImageView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.TextView; import java.util.Observable; import java.util.Observer; @@ -46,11 +50,12 @@ import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.ProfileManager; import de.blinkt.openvpn.core.VpnStatus; -import mbanje.kurt.fabbutton.FabButton; import se.leap.bitmaskclient.eip.EIP; import se.leap.bitmaskclient.eip.EipStatus; import se.leap.bitmaskclient.eip.VoidVpnService; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK; import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY; import static se.leap.bitmaskclient.Constants.EIP_ACTION_START; @@ -66,23 +71,35 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS; import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; -public class VpnFragment extends Fragment implements Observer { +public class EipFragment extends Fragment implements Observer { - public static String TAG = VpnFragment.class.getSimpleName(); + public static String TAG = EipFragment.class.getSimpleName(); - public static final String IS_PENDING = TAG + ".is_pending"; protected static final String IS_CONNECTED = TAG + ".is_connected"; public static final String START_EIP_ON_BOOT = "start on boot"; private SharedPreferences preferences; - @InjectView(R.id.vpn_status_image) - FabButton vpnStatusImage; + @InjectView(R.id.background) + AppCompatImageView background; + + @InjectView(R.id.key) + AppCompatImageView key; + + @InjectView(R.id.cirle) + AppCompatImageView circle; + @InjectView(R.id.vpn_main_button) Button mainButton; - private static EIPReceiver eipReceiver; - private static EipStatus eipStatus; + @InjectView(R.id.routed_text) + TextView routedText; + + @InjectView(R.id.vpn_route) + TextView vpnRoute; + + private EIPReceiver eipReceiver; + private EipStatus eipStatus; private boolean wantsToConnect; private IOpenVPNServiceInternal mService; @@ -156,6 +173,20 @@ public class VpnFragment extends Fragment implements Observer { } @OnClick(R.id.vpn_main_button) + void onButtonClick() { + handleIcon(); + } + + @OnClick(R.id.key) + void onKeyClick() { + handleIcon(); + } + + @OnClick(R.id.cirle) + void onCircleClick() { + handleIcon(); + } + void handleIcon() { if (eipStatus.isConnected() || eipStatus.isConnecting()) handleSwitchOff(); @@ -194,8 +225,6 @@ public class VpnFragment extends Fragment implements Observer { askPendingStartCancellation(); } else if (eipStatus.isConnected()) { askToStopEIP(); - } else { - updateIcon(); } } @@ -313,44 +342,32 @@ public class VpnFragment extends Fragment implements Observer { } }); } else { - Log.e("VpnFragment", "activity is null"); + Log.e("EipFragment", "activity is null"); } } } private void handleNewState() { - updateIcon(); - updateButton(); - } - - private void updateIcon() { - if (eipStatus.isBlocking()) { - vpnStatusImage.showProgress(false); - vpnStatusImage.setIcon(R.drawable.ic_stat_vpn_blocking, R.drawable.ic_stat_vpn_blocking); - vpnStatusImage.setTag(R.drawable.ic_stat_vpn_blocking); - } else if (eipStatus.isConnecting()) { - vpnStatusImage.showProgress(true); - vpnStatusImage.setIcon(R.drawable.ic_stat_vpn_empty_halo, R.drawable.ic_stat_vpn_empty_halo); - vpnStatusImage.setTag(R.drawable.ic_stat_vpn_empty_halo); - } else if (eipStatus.isConnected()){ - vpnStatusImage.showProgress(false); - vpnStatusImage.setIcon(R.drawable.ic_stat_vpn, R.drawable.ic_stat_vpn); - vpnStatusImage.setTag(R.drawable.ic_stat_vpn); - } else { - vpnStatusImage.setIcon(R.drawable.ic_stat_vpn_offline, R.drawable.ic_stat_vpn_offline); - vpnStatusImage.setTag(R.drawable.ic_stat_vpn_offline); - vpnStatusImage.showProgress(false); - } - } - - private void updateButton() { Activity activity = getActivity(); if (eipStatus.isConnecting()) { mainButton.setText(activity.getString(android.R.string.cancel)); + key.setImageResource(R.drawable.vpn_connecting); + routedText.setVisibility(GONE); + vpnRoute.setVisibility(GONE); + colorBackgroundALittle(); } else if (eipStatus.isConnected() || isOpenVpnRunningWithoutNetwork()) { mainButton.setText(activity.getString(R.string.vpn_button_turn_off)); + key.setImageResource(R.drawable.vpn_connected); + routedText.setVisibility(VISIBLE); + vpnRoute.setVisibility(VISIBLE); + vpnRoute.setText(ConfigHelper.getProviderName(preferences)); + colorBackground(); } else { mainButton.setText(activity.getString(R.string.vpn_button_turn_on)); + key.setImageResource(R.drawable.vpn_disconnected); + routedText.setVisibility(GONE); + vpnRoute.setVisibility(GONE); + greyscaleBackground(); } } @@ -439,8 +456,22 @@ public class VpnFragment extends Fragment implements Observer { } } + private void greyscaleBackground() { + ColorMatrix matrix = new ColorMatrix(); + matrix.setSaturation(0); + ColorMatrixColorFilter cf = new ColorMatrixColorFilter(matrix); + background.setColorFilter(cf); + background.setImageAlpha(255); + } - public static EIPReceiver getReceiver() { - return eipReceiver; + private void colorBackgroundALittle() { + background.setColorFilter(null); + background.setImageAlpha(144); } + + private void colorBackground() { + background.setColorFilter(null); + background.setImageAlpha(255); + } + } diff --git a/app/src/main/java/se/leap/bitmaskclient/LoginActivity.java b/app/src/main/java/se/leap/bitmaskclient/LoginActivity.java index 6ae288c2..a407b0a9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LoginActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/LoginActivity.java @@ -22,11 +22,6 @@ public class LoginActivity extends ProviderCredentialsBaseActivity { } @Override - protected void onResume() { - super.onResume(); - } - - @Override @OnClick(R.id.button) void handleButton() { super.handleButton(); diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java index 3fc1637e..7629f0b7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java @@ -74,7 +74,7 @@ public class MainActivity extends AppCompatActivity { switch (intent.getAction()) { case ACTION_SHOW_VPN_FRAGMENT: - fragment = new VpnFragment(); + fragment = new EipFragment(); break; default: break; @@ -89,10 +89,14 @@ public class MainActivity extends AppCompatActivity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (data == null) { + return; + } + if (requestCode == REQUEST_CODE_CONFIGURE_LEAP) { if (resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) { Provider provider = data.getParcelableExtra(Provider.KEY); - provider.storeInPreferences(preferences); + ConfigHelper.storeProviderInPreferences(preferences, provider); } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 4d8c741d..5ff1949c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -121,10 +121,18 @@ public final class Provider implements Parcelable { return definition; } + String getDefinitionString() { + return getDefinition().toString(); + } + protected String getDomain() { return mainUrl.getDomain(); } + String getMainUrlString() { + return getMainUrl().toString(); + } + protected DefaultedURL getMainUrl() { return mainUrl; } @@ -301,19 +309,12 @@ public final class Provider implements Parcelable { this.caCert = cert; } - public void storeInPreferences(SharedPreferences preferences) { - preferences.edit().putBoolean(PROVIDER_CONFIGURED, true). - putString(Provider.MAIN_URL, getMainUrl().toString()). - putString(Provider.KEY, getDefinition().toString()).apply(); - } - public boolean isDefault() { return getMainUrl().isDefault() && getApiUrl().isDefault() && certificatePin.isEmpty() && certificatePinEncoding.isEmpty() && caCert.isEmpty(); - } } diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java index f51618ad..25dca4e0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java @@ -24,8 +24,6 @@ import se.leap.bitmaskclient.userstatus.SessionDialog; import se.leap.bitmaskclient.userstatus.SessionDialog.ERRORS; import se.leap.bitmaskclient.userstatus.User; -import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT; - import static android.view.View.GONE; import static android.view.View.VISIBLE; import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE; diff --git a/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java index 9db9c3f4..aee00765 100644 --- a/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java @@ -61,7 +61,7 @@ import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY; /** * abstract base Activity that builds and shows the list of known available providers. - * The implementation of BaseConfigurationWizard differ in that they may or may not allow to bypass + * The implementation of ProviderListBaseActivity differ in that they may or may not allow to bypass * secure download mechanisms including certificate validation. * <p/> * It also allows the user to enter custom providers with a button. @@ -70,7 +70,7 @@ import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY; * @author cyberta */ -public abstract class BaseConfigurationWizard extends ConfigWizardBaseActivity +public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity implements NewProviderDialog.NewProviderDialogInterface, DownloadFailedDialog.DownloadFailedDialogInterface, ProviderAPIResultReceiver.Receiver { @InjectView(R.id.provider_list) @@ -81,7 +81,7 @@ public abstract class BaseConfigurationWizard extends ConfigWizardBaseActivity private ProviderManager providerManager; protected Intent mConfigState = new Intent(PROVIDER_NOT_SET); - final public static String TAG = ConfigurationWizard.class.getSimpleName(); + final public static String TAG = ProviderListActivity.class.getSimpleName(); final private static String ACTIVITY_STATE = "ACTIVITY STATE"; @@ -433,26 +433,40 @@ public abstract class BaseConfigurationWizard extends ConfigWizardBaseActivity Bundle resultData = intent.getParcelableExtra(RESULT_KEY); String handledProvider = resultData.getString(Provider.KEY); - String providerDomain = getProviderDomain(handledProvider); - if (providerDomain != null && - providerDomain.equalsIgnoreCase(provider.getDomain())) { - switch (resultCode) { - case PROVIDER_OK: - handleProviderSetUp(); - break; - case CORRECTLY_DOWNLOADED_CERTIFICATE: - handleCorrectlyDownloadedCertificate(); - break; - case INCORRECTLY_DOWNLOADED_CERTIFICATE: - handleIncorrectlyDownloadedCertificate(); - break; - } + String providerName = ConfigHelper.getProviderName(handledProvider); + String providerDomain = ConfigHelper.getProviderDomain(handledProvider); + + //FIXME: remove that lines as soon as Provider gets sent via broadcast + // and make sure providers are the same - remove providersMatch + if (resultCode == PROVIDER_OK && handledProvider == null) { + providerName = ConfigHelper.getProviderName(preferences); + providerDomain = ConfigHelper.getProviderDomain(preferences); + } + boolean providersMatch = true; + if (providerDomain != null) { + providersMatch = providerDomain.equalsIgnoreCase(provider.getDomain()); } + if (providerName != null && !providersMatch) { + providersMatch = providerName.equalsIgnoreCase(provider.getName()); + } + - // providerDomain can be null - if (resultCode == PROVIDER_NOK) { - handleProviderSetupFailed(resultData); + switch (resultCode) { + case PROVIDER_OK: + if (providersMatch) + handleProviderSetUp(); + break; + case PROVIDER_NOK: + if(providersMatch) + handleProviderSetupFailed(resultData); + break; + case CORRECTLY_DOWNLOADED_CERTIFICATE: + handleCorrectlyDownloadedCertificate(); + break; + case INCORRECTLY_DOWNLOADED_CERTIFICATE: + handleIncorrectlyDownloadedCertificate(); + break; } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java index 69079735..f5991538 100644 --- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java @@ -17,7 +17,6 @@ import se.leap.bitmaskclient.userstatus.User; import static se.leap.bitmaskclient.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION; -import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; @@ -56,7 +55,7 @@ public class StartActivity extends Activity { case FIRST: storeAppVersion(); // TODO start ProfileCreation & replace below code - // (new Intent(getActivity(), ConfigurationWizard.class), Constants.REQUEST_CODE_SWITCH_PROVIDER); + // (new Intent(getActivity(), ProviderListActivity.class), Constants.REQUEST_CODE_SWITCH_PROVIDER); break; case UPGRADE: @@ -165,15 +164,19 @@ public class StartActivity extends Activity { if (getIntent().hasExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE)) { getIntent().removeExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE); } - startActivityForResult(new Intent(this, ConfigurationWizard.class), REQUEST_CODE_CONFIGURE_LEAP); + startActivityForResult(new Intent(this, ProviderListActivity.class), REQUEST_CODE_CONFIGURE_LEAP); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (data == null) { + return; + } + if (requestCode == REQUEST_CODE_CONFIGURE_LEAP) { if (resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) { Provider provider = data.getParcelableExtra(Provider.KEY); - provider.storeInPreferences(preferences); + ConfigHelper.storeProviderInPreferences(preferences, provider); showMainActivity(); } else if (resultCode == RESULT_CANCELED) { diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java index dbe99dce..090e8d26 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -27,9 +27,9 @@ import android.widget.ListView; import android.widget.Toast; import se.leap.bitmaskclient.ConfigHelper; -import se.leap.bitmaskclient.ConfigurationWizard; +import se.leap.bitmaskclient.ProviderListActivity; +import se.leap.bitmaskclient.EipFragment; import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.VpnFragment; import se.leap.bitmaskclient.fragments.AboutFragment; import se.leap.bitmaskclient.fragments.LogFragment; @@ -143,7 +143,7 @@ public class NavigationDrawerFragment extends Fragment { android.R.layout.simple_list_item_activated_1, android.R.id.text1); - String providerName = ConfigHelper.getCurrentProviderName(preferences); + String providerName = ConfigHelper.getProviderName(preferences); if (providerName == null) { //TODO: ADD A header to the ListView containing a useful message. //TODO 2: disable switchProvider @@ -296,7 +296,7 @@ public class NavigationDrawerFragment extends Fragment { if (parent == mDrawerAccountsListView) { mTitle = getString(R.string.vpn_fragment_title); - fragment = new VpnFragment(); + fragment = new EipFragment(); } else { Log.d("Drawer", String.format("Selected position %d", position)); switch (position) { @@ -304,7 +304,7 @@ public class NavigationDrawerFragment extends Fragment { // TODO STOP VPN // if (provider.hasEIP()) eip_fragment.stopEipIfPossible(); preferences.edit().clear().apply(); - startActivityForResult(new Intent(getActivity(), ConfigurationWizard.class), REQUEST_CODE_SWITCH_PROVIDER); + startActivityForResult(new Intent(getActivity(), ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER); break; case 1: mTitle = getString(R.string.log_fragment_title); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index a2ac9d66..eca5b881 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -18,7 +18,6 @@ package se.leap.bitmaskclient.eip; import android.app.Activity; import android.app.IntentService; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; @@ -30,7 +29,6 @@ import org.json.JSONObject; import de.blinkt.openvpn.LaunchVPN; import se.leap.bitmaskclient.OnBootReceiver; -import se.leap.bitmaskclient.VpnFragment; import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY; import static se.leap.bitmaskclient.Constants.EIP_ACTION_IS_RUNNING; @@ -59,12 +57,11 @@ public final class EIP extends IntentService { public final static String TAG = EIP.class.getSimpleName(); public final static String SERVICE_API_PATH = "config/eip-service.json"; - private static Context context; private static ResultReceiver mReceiver; private static SharedPreferences preferences; private static JSONObject eipDefinition; - private static GatewaysManager gatewaysManager = new GatewaysManager(); + private GatewaysManager gatewaysManager = new GatewaysManager(); private static Gateway gateway; public EIP() { @@ -74,7 +71,6 @@ public final class EIP extends IntentService { @Override public void onCreate() { super.onCreate(); - context = getApplicationContext(); preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); eipDefinition = eipDefinitionFromPreferences(); if (gatewaysManager.isEmpty()) @@ -86,18 +82,30 @@ public final class EIP extends IntentService { String action = intent.getAction(); mReceiver = intent.getParcelableExtra(EIP_RECEIVER); - if (action.equals(EIP_ACTION_START)) - startEIP(); - else if (action.equals(EIP_ACTION_START_ALWAYS_ON_EIP)) - startAlwaysOnEIP(); - else if (action.equals(EIP_ACTION_STOP)) - stopEIP(); - else if (action.equals(EIP_ACTION_IS_RUNNING)) - isRunning(); - else if (action.equals(EIP_ACTION_UPDATE)) - updateEIPService(); - else if (action.equals(EIP_ACTION_CHECK_CERT_VALIDITY)) - checkCertValidity(); + if (action == null) { + return; + } + + switch (action) { + case EIP_ACTION_START: + startEIP(); + break; + case EIP_ACTION_START_ALWAYS_ON_EIP: + startAlwaysOnEIP(); + break; + case EIP_ACTION_STOP: + stopEIP(); + break; + case EIP_ACTION_IS_RUNNING: + isRunning(); + break; + case EIP_ACTION_UPDATE: + updateEIPService(); + break; + case EIP_ACTION_CHECK_CERT_VALIDITY: + checkCertValidity(); + break; + } } /** @@ -114,7 +122,6 @@ public final class EIP extends IntentService { gateway = gatewaysManager.select(); if (gateway != null && gateway.getProfile() != null) { - mReceiver = VpnFragment.getReceiver(); launchActiveGateway(); tellToReceiver(EIP_ACTION_START, Activity.RESULT_OK); } else @@ -134,7 +141,6 @@ public final class EIP extends IntentService { gateway = gatewaysManager.select(); if (gateway != null && gateway.getProfile() != null) { - //mReceiver = VpnFragment.getReceiver(); Log.d(TAG, "startAlwaysOnEIP eip launch avtive gateway vpn"); launchActiveGateway(); } else { @@ -147,7 +153,7 @@ public final class EIP extends IntentService { * VpnService is started properly. */ private void earlyRoutes() { - Intent voidVpnLauncher = new Intent(context, VoidVpnLauncher.class); + Intent voidVpnLauncher = new Intent(getApplicationContext(), VoidVpnLauncher.class); voidVpnLauncher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(voidVpnLauncher); } @@ -216,7 +222,7 @@ public final class EIP extends IntentService { private void gatewaysFromPreferences() { String gatewaysString = preferences.getString(Gateway.TAG, ""); - gatewaysManager = new GatewaysManager(context, preferences); + gatewaysManager = new GatewaysManager(this, preferences); gatewaysManager.addFromString(gatewaysString); preferences.edit().remove(Gateway.TAG).apply(); } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java index ddf152d2..0da74872 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -16,13 +16,15 @@ */ package se.leap.bitmaskclient.eip; -import android.content.*; +import android.content.Context; import android.os.AsyncTask; import android.support.annotation.VisibleForTesting; -import java.util.*; +import java.util.Observable; -import de.blinkt.openvpn.core.*; +import de.blinkt.openvpn.core.ConnectionStatus; +import de.blinkt.openvpn.core.LogItem; +import de.blinkt.openvpn.core.VpnStatus; /** * EipStatus is a Singleton that represents a reduced set of a vpn's ConnectionStatus. @@ -31,7 +33,7 @@ import de.blinkt.openvpn.core.*; */ public class EipStatus extends Observable implements VpnStatus.StateListener { public static String TAG = EipStatus.class.getSimpleName(); - private static EipStatus current_status; + private static EipStatus currentStatus; public enum EipLevel { CONNECTING, DISCONNECTING, @@ -42,23 +44,23 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } /** - * vpn_level holds the connection status of the openvpn vpn and the traffic blocking + * vpnLevel holds the connection status of the openvpn vpn and the traffic blocking * void vpn. LEVEL_BLOCKING is set when the latter vpn is up. All other states are set by * openvpn. */ - private ConnectionStatus vpn_level = ConnectionStatus.LEVEL_NOTCONNECTED; - private static EipLevel current_eip_level = EipLevel.DISCONNECTED; + private ConnectionStatus vpnLevel = ConnectionStatus.LEVEL_NOTCONNECTED; + private static EipLevel currentEipLevel = EipLevel.DISCONNECTED; - int last_error_line = 0; - private String state, log_message; - private int localized_res_id; + private int lastErrorLine = 0; + private String state, logMessage; + private int localizedResId; public static EipStatus getInstance() { - if (current_status == null) { - current_status = new EipStatus(); - VpnStatus.addStateListener(current_status); + if (currentStatus == null) { + currentStatus = new EipStatus(); + VpnStatus.addStateListener(currentStatus); } - return current_status; + return currentStatus; } private EipStatus() { @@ -66,16 +68,16 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { @Override public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) { - ConnectionStatus tmp = current_status.getLevel(); - current_status = getInstance(); - current_status.setState(state); - current_status.setLogMessage(logmessage); - current_status.setLocalizedResId(localizedResId); - current_status.setLevel(level); - current_status.setEipLevel(level); - if (tmp != current_status.getLevel()) { - current_status.setChanged(); - current_status.notifyObservers(); + ConnectionStatus tmp = currentStatus.getLevel(); + currentStatus = getInstance(); + currentStatus.setState(state); + currentStatus.setLogMessage(logmessage); + currentStatus.setLocalizedResId(localizedResId); + currentStatus.setLevel(level); + currentStatus.setEipLevel(level); + if (tmp != currentStatus.getLevel()) { + currentStatus.setChanged(); + currentStatus.notifyObservers(); } } @@ -87,7 +89,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { private void setEipLevel(ConnectionStatus level) { switch (level) { case LEVEL_CONNECTED: - current_eip_level = EipLevel.CONNECTED; + currentEipLevel = EipLevel.CONNECTED; break; case LEVEL_VPNPAUSED: throw new IllegalStateException("Ics-Openvpn's VPNPAUSED state is not supported by Bitmask"); @@ -95,25 +97,25 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { case LEVEL_CONNECTING_NO_SERVER_REPLY_YET: case LEVEL_WAITING_FOR_USER_INPUT: case LEVEL_START: - current_eip_level = EipLevel.CONNECTING; + currentEipLevel = EipLevel.CONNECTING; break; case LEVEL_AUTH_FAILED: case LEVEL_NOTCONNECTED: - current_eip_level = EipLevel.DISCONNECTED; + currentEipLevel = EipLevel.DISCONNECTED; break; case LEVEL_NONETWORK: case LEVEL_BLOCKING: setEipLevelWithDelay(level); break; case UNKNOWN_LEVEL: - current_eip_level = EipLevel.UNKNOWN; //?? + currentEipLevel = EipLevel.UNKNOWN; //?? break; } } @VisibleForTesting EipLevel getEipLevel() { - return current_eip_level; + return currentEipLevel; } /** @@ -123,7 +125,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { * @param futureLevel */ private void setEipLevelWithDelay(ConnectionStatus futureLevel) { - new DelayTask(current_status.getLevel(), futureLevel).execute(); + new DelayTask(currentStatus.getLevel(), futureLevel).execute(); } private static class DelayTask extends AsyncTask<Void, Void, Void> { @@ -131,7 +133,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { private final ConnectionStatus currentLevel; private final ConnectionStatus futureLevel; - public DelayTask(ConnectionStatus currentLevel, ConnectionStatus futureLevel) { + DelayTask(ConnectionStatus currentLevel, ConnectionStatus futureLevel) { this.currentLevel = currentLevel; this.futureLevel = futureLevel; } @@ -144,38 +146,38 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { return null; } - protected void onPostExecute(Void result) {; - if (currentLevel == current_status.getLevel()) { + protected void onPostExecute(Void result) { + if (currentLevel == currentStatus.getLevel()) { switch (futureLevel) { case LEVEL_NONETWORK: - current_eip_level = EipLevel.DISCONNECTED; + currentEipLevel = EipLevel.DISCONNECTED; break; case LEVEL_BLOCKING: - current_eip_level = EipLevel.BLOCKING; + currentEipLevel = EipLevel.BLOCKING; break; default: break; } - current_status.setChanged(); - current_status.notifyObservers(); + currentStatus.setChanged(); + currentStatus.notifyObservers(); } } } public boolean isConnecting() { - return current_eip_level == EipLevel.CONNECTING; + return currentEipLevel == EipLevel.CONNECTING; } public boolean isConnected() { - return current_eip_level == EipLevel.CONNECTED; + return currentEipLevel == EipLevel.CONNECTED; } /** - * @return true if current_eip_level is for at least a second {@link EipLevel#BLOCKING}. + * @return true if currentEipLevel is for at least a second {@link EipLevel#BLOCKING}. * See {@link #setEipLevelWithDelay(ConnectionStatus)}. */ public boolean isBlocking() { - return current_eip_level == EipLevel.BLOCKING; + return currentEipLevel == EipLevel.BLOCKING; } /** @@ -183,20 +185,20 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { * @return true immediately after traffic blocking VoidVpn was established. */ public boolean isBlockingVpnEstablished() { - return vpn_level == ConnectionStatus.LEVEL_BLOCKING; + return vpnLevel == ConnectionStatus.LEVEL_BLOCKING; } public boolean isDisconnected() { - return current_eip_level == EipLevel.DISCONNECTED; + return currentEipLevel == EipLevel.DISCONNECTED; } /** * ics-openvpn's paused state is not implemented yet - * @return + * @return true if vpn is paused false if not */ @Deprecated public boolean isPaused() { - return vpn_level == ConnectionStatus.LEVEL_VPNPAUSED; + return vpnLevel == ConnectionStatus.LEVEL_VPNPAUSED; } public String getState() { @@ -204,15 +206,15 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } public String getLogMessage() { - return log_message; + return logMessage; } - public int getLocalizedResId() { - return localized_res_id; + int getLocalizedResId() { + return localizedResId; } public ConnectionStatus getLevel() { - return vpn_level; + return vpnLevel; } private void setState(String state) { @@ -220,39 +222,40 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } private void setLogMessage(String log_message) { - this.log_message = log_message; + this.logMessage = log_message; } private void setLocalizedResId(int localized_res_id) { - this.localized_res_id = localized_res_id; + this.localizedResId = localized_res_id; } private void setLevel(ConnectionStatus level) { - this.vpn_level = level; + this.vpnLevel = level; } public boolean errorInLast(int lines, Context context) { return !lastError(lines, context).isEmpty(); } - public String lastError(int lines, Context context) { + private String lastError(int lines, Context context) { String error = ""; String[] error_keywords = {"error", "ERROR", "fatal", "FATAL"}; LogItem[] log = VpnStatus.getlogbuffer(); - if(log.length < last_error_line) - last_error_line = 0; - String message = ""; + if(log.length < lastErrorLine) + lastErrorLine = 0; + String message; for (int i = 1; i <= lines && log.length > i; i++) { int line = log.length - i; - LogItem log_item = log[line]; - message = log_item.getString(context); - for (int j = 0; j < error_keywords.length; j++) - if (message.contains(error_keywords[j]) && line > last_error_line) { + LogItem logItem = log[line]; + message = logItem.getString(context); + for (String errorKeyword: error_keywords) { + if (message.contains(errorKeyword) && line > lastErrorLine) { error = message; - last_error_line = line; + lastErrorLine = line; } + } } return error; @@ -260,7 +263,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { @Override public String toString() { - return "State: " + state + " Level: " + vpn_level.toString(); + return "State: " + state + " Level: " + vpnLevel.toString(); } } diff --git a/app/src/main/res/drawable/black_circle.xml b/app/src/main/res/drawable/black_circle.xml new file mode 100644 index 00000000..533652d6 --- /dev/null +++ b/app/src/main/res/drawable/black_circle.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> +<item> + <shape android:shape="oval"> + <solid android:color="@color/black800"/> + <size android:width="250dp" android:height="250dp"/> + </shape> +</item> +</selector>
\ No newline at end of file diff --git a/app/src/main/res/drawable/vpn_connected.xml b/app/src/main/res/drawable/vpn_connected.xml new file mode 100644 index 00000000..ea4d61a2 --- /dev/null +++ b/app/src/main/res/drawable/vpn_connected.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" +android:width="48dp" +android:height="48dp" +android:viewportWidth="48" +android:viewportHeight="48"> + +<path + android:fillColor="#ffffff" + android:strokeWidth="1" + android:pathData="M 12.187013,12.3125 C 5.4647724,12.3125 0,17.760254 0,24.5 c 0,6.739746 +5.4647724,12.21875 12.187013,12.21875 5.305097,0 9.803352,-3.408824 +11.47013,-8.15625 l 8.509091,-0.09375 1.745454,-2.09375 1.153247,-0.03125 +1.828239,2.182795 1.234013,-0.03125 2.049436,-2.307795 1.122078,0 +1.714286,2.21875 2.836364,0 L 48,24.4375 l -2.774026,-4.09375 -21.6,0 C +21.928439,15.65398 17.450952,12.3125 12.187013,12.3125 z m -4.8311688,8.90625 c +1.8370556,0 3.3350648,1.50191 3.3350648,3.34375 0,1.84184 -1.4980092,3.3125 +-3.3350648,3.3125 -1.8370556,0 -3.335065,-1.47066 -3.335065,-3.3125 0,-1.84184 +1.4980094,-3.34375 3.335065,-3.34375 z" /> +</vector>
\ No newline at end of file diff --git a/app/src/main/res/drawable/vpn_connecting.xml b/app/src/main/res/drawable/vpn_connecting.xml new file mode 100644 index 00000000..16c079c4 --- /dev/null +++ b/app/src/main/res/drawable/vpn_connecting.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48dp" + android:height="48dp" + android:viewportWidth="48" + android:viewportHeight="48"> + + <path + android:fillColor="#ffffff" + android:strokeWidth="1" + android:pathData="M12.1875,12.3125 C5.46526,12.3125,0,17.7603,0,24.5 +C0,31.2397,5.46526,36.7188,12.1875,36.7188 +C17.4926,36.7188,21.9895,33.3099,23.6563,28.5625 L32.1563,28.4688 +L33.9063,26.375 L35.0625,26.3438 L36.9063,28.5313 L38.125,28.5 L40.1875,26.1875 +L41.3125,26.1875 L43,28.4063 L45.8438,28.4063 L48,24.4375 L45.2188,20.3438 +L23.625,20.3438 C21.9275,15.654,17.4514,12.3125,12.1875,12.3125 Z +M12.2188,15.6875 C17.0994,15.6875,21.0313,19.6506,21.0313,24.5313 +C21.0313,29.4119,17.0994,33.375,12.2188,33.375 +C7.33805,33.375,3.375,29.4119,3.375,24.5313 +C3.375,19.6506,7.33805,15.6875,12.2188,15.6875 Z" /> + <path + android:strokeColor="#ffffff" + android:strokeWidth="2.50000000000000000" + android:pathData="M12.178,17.8729 L12.1779,24.6356 L8.61859,28.1949" /> +</vector>
\ No newline at end of file diff --git a/app/src/main/res/drawable/vpn_disconnected.xml b/app/src/main/res/drawable/vpn_disconnected.xml new file mode 100644 index 00000000..d6cf067b --- /dev/null +++ b/app/src/main/res/drawable/vpn_disconnected.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48dp" + android:height="48dp" + android:viewportWidth="48" + android:viewportHeight="48"> + + <path + android:fillColor="#ffffff" + android:strokeWidth="1" + android:pathData="M13.9636,12.4377 L28.7376,28.5002 L32.1662,28.4689 L33.9117,26.3752 +L35.0649,26.3439 L36.9039,28.5314 L38.1195,28.5002 L40.1766,26.1877 +L41.2987,26.1877 L43.013,28.4064 L45.8494,28.4064 L48,24.4377 L45.226,20.344 +L23.626,20.344 C22.1234,16.1928,18.44,13.0938,13.9637,12.4378 Z M8.47792,12.9065 +C3.56807,14.4767,0,19.059,0,24.5002 C0,31.24,5.46477,36.719,12.187,36.719 +C17.2792,36.719,21.6241,33.5759,23.439,29.1253 L8.47792,12.9065 Z +M7.35584,21.219 C9.1929,21.219,10.6909,22.7209,10.6909,24.5628 +C10.6909,26.4046,9.19289,27.8753,7.35584,27.8753 +C5.51878,27.8753,4.02077,26.4046,4.02077,24.5628 +C4.02077,22.721,5.51878,21.219,7.35583,21.219 Z" /> + <group android:name="rotationGroup" + android:rotation="47.263656"> + <path + android:fillColor="#ffffff" + android:strokeWidth="1" + android:pathData="M9.50852,-4.62741 L57.4577,-4.62741 L57.4577,-0.305379 L9.50852,-0.305379 L9.50852,-4.62741 Z" /> + </group> +</vector>
\ No newline at end of file diff --git a/app/src/main/res/layout-xlarge/configuration_wizard_activity.xml b/app/src/main/res/layout-xlarge/configuration_wizard_activity.xml index f82377cb..581b0c9a 100644 --- a/app/src/main/res/layout-xlarge/configuration_wizard_activity.xml +++ b/app/src/main/res/layout-xlarge/configuration_wizard_activity.xml @@ -3,7 +3,7 @@ android:id="@+id/configuration_wizard_layout" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ConfigurationWizard" + tools:context=".ProviderListActivity" style="@style/BitmaskActivity" > <ListView diff --git a/app/src/main/res/layout/configuration_wizard_activity.xml b/app/src/main/res/layout/configuration_wizard_activity.xml index 25da8612..e22d9047 100644 --- a/app/src/main/res/layout/configuration_wizard_activity.xml +++ b/app/src/main/res/layout/configuration_wizard_activity.xml @@ -3,7 +3,7 @@ android:id="@+id/configuration_wizard_layout" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ConfigurationWizard" + tools:context=".ProviderListActivity" style="@style/BitmaskActivity" > <include layout="@layout/loading_screen" /> diff --git a/app/src/main/res/layout/eip_service_fragment.xml b/app/src/main/res/layout/eip_service_fragment.xml index cef01c18..aa7ba514 100644 --- a/app/src/main/res/layout/eip_service_fragment.xml +++ b/app/src/main/res/layout/eip_service_fragment.xml @@ -1,49 +1,151 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/relativeLayout" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="10dp"> + android:layout_height="match_parent"> + + <android.support.constraint.Guideline + android:id="@+id/guideline_horizontal_top" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="horizontal" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintGuide_percent="0.3" + /> + + <android.support.constraint.Guideline + android:id="@+id/guideline_vertical_left" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintGuide_percent="0.3" + /> + + + <android.support.constraint.Guideline + android:id="@+id/guideline_horizontal_bottom" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="horizontal" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintGuide_percent="0.7" + /> + + <android.support.constraint.Guideline + android:id="@+id/guideline_vertical_right" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintGuide_percent="0.7" + /> + + <android.support.v7.widget.AppCompatImageView + android:id="@+id/background" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scaleType="fitXY" + app:srcCompat="@drawable/ic_colorsquare" /> + <TextView android:id="@+id/eipLabel" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_centerHorizontal="true" - android:layout_marginLeft="10dp" - android:layout_marginStart="10dp" - android:layout_marginTop="12dp" - android:layout_marginBottom="12dp" + android:layout_marginEnd="@dimen/stdpadding" + android:layout_marginStart="@dimen/stdpadding" + android:layout_marginTop="@dimen/stdpadding" + android:layout_marginLeft="@dimen/stdpadding" + android:layout_marginRight="@dimen/stdpadding" android:text="@string/eip_service_label" - android:textAppearance="?android:attr/textAppearanceMedium" /> + android:textAppearance="?android:attr/textAppearanceMedium" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + + <android.support.v7.widget.AppCompatImageView + android:id="@+id/cirle" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_marginBottom="@dimen/stdpadding" + android:layout_marginEnd="@dimen/stdpadding" + android:layout_marginStart="@dimen/stdpadding" + android:layout_marginTop="@dimen/stdpadding" + android:layout_marginLeft="@dimen/stdpadding" + android:layout_marginRight="@dimen/stdpadding" + app:layout_constraintBottom_toTopOf="@+id/guideline_horizontal_bottom" + app:layout_constraintEnd_toStartOf="@+id/guideline_vertical_right" + app:layout_constraintHorizontal_bias="1.0" + app:layout_constraintStart_toStartOf="@+id/guideline_vertical_left" + app:layout_constraintTop_toTopOf="@+id/guideline_horizontal_top" + app:layout_constraintVertical_bias="0.0" + app:srcCompat="@drawable/black_circle" /> + + <android.support.v7.widget.AppCompatImageView + android:id="@+id/key" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_marginBottom="@dimen/stdpadding" + android:layout_marginEnd="@dimen/stdpadding" + android:layout_marginStart="@dimen/stdpadding" + android:layout_marginTop="@dimen/stdpadding" + android:layout_marginLeft="@dimen/stdpadding" + android:layout_marginRight="@dimen/stdpadding" + app:layout_constraintBottom_toBottomOf="@+id/cirle" + app:layout_constraintEnd_toEndOf="@+id/cirle" + app:layout_constraintStart_toStartOf="@+id/cirle" + app:layout_constraintTop_toTopOf="@+id/cirle" + app:srcCompat="@drawable/vpn_connected" /> - <LinearLayout + + <android.support.v7.widget.AppCompatButton + android:id="@+id/vpn_main_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="horizontal" - android:layout_below="@+id/eipLabel" - android:layout_centerInParent="true"> - - <Button - android:id="@+id/vpn_main_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textSize="12sp" - /> - - <se.leap.bitmaskclient.userstatus.FabButton - android:id="@+id/vpn_status_image" - android:layout_width="32dp" - android:layout_height="32dp" - android:layout_marginLeft="3dp" - android:layout_marginStart="3dp" - android:color="@android:color/holo_blue_dark" - android:layout_gravity="center" - android:visibility="visible" - android:indeterminate="true" - android:max="100" - fbb_autoStart="true" - fbb_progressColor="#ff170aff" - fbb_progressWidthRatio="0.1" - /> - </LinearLayout> -</RelativeLayout> + android:layout_marginBottom="@dimen/stdpadding" + android:layout_marginEnd="@dimen/stdpadding" + android:layout_marginStart="@dimen/stdpadding" + android:layout_marginTop="@dimen/stdpadding" + android:layout_marginLeft="@dimen/stdpadding" + android:layout_marginRight="@dimen/stdpadding" + app:layout_constraintBottom_toBottomOf="@+id/background" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + android:text="@string/vpn.button.turn.on" + style="@style/BitmaskButtonBlack" + /> + + <TextView + android:id="@+id/routed_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/stdpadding" + android:layout_marginStart="@dimen/stdpadding" + android:layout_marginTop="@dimen/stdpadding" + android:layout_marginLeft="@dimen/stdpadding" + android:layout_marginRight="@dimen/stdpadding" + android:text="@string/vpn_securely_routed" + android:visibility="visible" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/eipLabel" /> + + <TextView + android:id="@+id/vpn_route" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/stdpadding" + android:layout_marginStart="@dimen/stdpadding" + android:layout_marginLeft="@dimen/stdpadding" + android:layout_marginRight="@dimen/stdpadding" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/routed_text" /> + +</android.support.constraint.ConstraintLayout> diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index b928a79b..9f36e474 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -31,4 +31,10 @@ <item name="android:backgroundTint">@color/colorPrimary</item> </style> + <style name="BitmaskButtonBlack" parent="android:Widget.Button"> + <item name="android:textAllCaps">true</item> + <item name="android:backgroundTint">@color/black800</item> + <item name="android:textColor">@color/white</item> + </style> + </resources> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index a8a63e4b..53ead009 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -6,6 +6,8 @@ <color name="colorError">#ef9a9a</color> <color name="colorSuccess">#a5d6a7</color> + <color name="black800">#424242</color> + <color name="red200">#ef9a9a</color> <color name="pink200">#f48fb1</color> <color name="purple200">#ce93d8</color> @@ -23,4 +25,6 @@ <color name="orange200">#ffcc80</color> <color name="deepOrange200">#ffab91</color> + <color name="white">#ffffff</color> + </resources> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c681f861..515e1f37 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -85,6 +85,7 @@ <string name="vpn.button.turn.on">Turn on</string> <string name="vpn.button.turn.off">Turn off</string> <string name="vpn_button_turn_off_blocking">Stop blocking</string> + <string name="vpn_securely_routed">Your traffic is securely routed through:</string> <string name="bitmask_log">Bitmask Log</string> <string name="title_activity_main">Bitmask</string> <string name="log_fragment_title">Log</string> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 3b1150ea..867fa54f 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -67,4 +67,11 @@ <style name="BitmaskActivity"> <item name="android:padding">@dimen/activity_margin</item> </style> + + <style name="BitmaskButtonBlack" parent="android:Widget.Button"> + <item name="android:textAllCaps">true</item> + <item name="android:background">@color/black800</item> + <item name="android:textColor">@color/white</item> + </style> + </resources>
\ No newline at end of file diff --git a/app/src/production/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/production/java/se/leap/bitmaskclient/ProviderListActivity.java index 4e16647a..8403b046 100644 --- a/app/src/production/java/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/app/src/production/java/se/leap/bitmaskclient/ProviderListActivity.java @@ -30,7 +30,7 @@ import java.net.URL; * @author parmegv * @author cyberta */ -public class ConfigurationWizard extends BaseConfigurationWizard { +public class ProviderListActivity extends ProviderListBaseActivity { @Override @@ -52,6 +52,7 @@ public class ConfigurationWizard extends BaseConfigurationWizard { private void autoSelectProvider(Provider provider) { this.provider = provider; onItemSelectedLogic(); + showProgressBar(); } /** diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderListContent.java b/app/src/production/java/se/leap/bitmaskclient/ProviderListContent.java index 6466e769..d9e1d1a9 100644 --- a/app/src/production/java/se/leap/bitmaskclient/ProviderListContent.java +++ b/app/src/production/java/se/leap/bitmaskclient/ProviderListContent.java @@ -20,7 +20,7 @@ import java.util.*; import java.net.*; /** - * Models the provider list shown in the ConfigurationWizard. + * Models the provider list shown in the ProviderListActivity. * * @author parmegv */ |