From 2bb5c64efda2cefcb2f9768f32be2b2936edadef Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 20 Feb 2018 14:11:47 +0100 Subject: #8853 improve backend callback check for error responses --- app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java index a52df460..a84432e9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java @@ -74,7 +74,7 @@ public class ConfigHelper { public static boolean checkErroneousDownload(String downloadedString) { try { - if (downloadedString == null || downloadedString.isEmpty() || new JSONObject(downloadedString).has(ProviderAPI.ERRORS)) { + if (downloadedString == null || downloadedString.isEmpty() || new JSONObject(downloadedString).has(ProviderAPI.ERRORS) || new JSONObject(downloadedString).has(ProviderAPI.BACKEND_ERROR_KEY)) { return true; } else { return false; -- cgit v1.2.3 From 0e762668e0be37d653d5c65c387eb16be8910f50 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 20 Feb 2018 14:29:28 +0100 Subject: #8853 fix signup for providers that allow only user authed vpn --- .../java/se/leap/bitmaskclient/EipFragment.java | 2 +- .../java/se/leap/bitmaskclient/MainActivity.java | 12 ++----- .../java/se/leap/bitmaskclient/ProviderAPI.java | 1 + .../leap/bitmaskclient/ProviderApiManagerBase.java | 41 +++++++++++----------- .../ProviderCredentialsBaseActivity.java | 18 ++++++---- 5 files changed, 38 insertions(+), 36 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index fb57aea8..8d1fa03a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -60,7 +60,7 @@ import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.ProviderCredentialsBaseActivity.USER_MESSAGE; +import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE; import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; public class EipFragment extends Fragment implements Observer { diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java index 6e778309..b4be55a4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java @@ -20,7 +20,6 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; -import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.json.JSONObject; @@ -58,7 +57,7 @@ import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFI import static se.leap.bitmaskclient.ProviderAPI.ERRORS; import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE; import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.ProviderCredentialsBaseActivity.USER_MESSAGE; +import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE; import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed; import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; @@ -67,12 +66,7 @@ public class MainActivity extends AppCompatActivity implements Observer { public final static String TAG = MainActivity.class.getSimpleName(); - private static final String KEY_ACTIVITY_STATE = "key state of activity"; - private static final String DEFAULT_UI_STATE = "default state"; - private static final String SHOW_DIALOG_STATE = "show dialog"; - private static final String REASON_TO_FAIL = "reason to fail"; - - private static Provider provider = new Provider(); + private Provider provider = new Provider(); private SharedPreferences preferences; private EipStatus eipStatus; private NavigationDrawerFragment navigationDrawerFragment; @@ -198,7 +192,7 @@ public class MainActivity extends AppCompatActivity implements Observer { break; } } - + //TODO: Why do we want this --v? legacy and redundant? Fragment fragment = new EipFragment(); Bundle arguments = new Bundle(); arguments.putParcelable(PROVIDER_KEY, provider); diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java index f5efde05..f1f474d7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java @@ -51,6 +51,7 @@ public class ProviderAPI extends IntentService implements ProviderApiManagerBase ERRORID = "errorId", BACKEND_ERROR_KEY = "error", BACKEND_ERROR_MESSAGE = "message", + USER_MESSAGE = "userMessage", DOWNLOAD_SERVICE_JSON = "ProviderAPI.DOWNLOAD_SERVICE_JSON", PROVIDER_SET_UP = "ProviderAPI.PROVIDER_SET_UP"; diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index b93abaeb..2cde431e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -46,6 +46,7 @@ import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.List; +import java.util.NoSuchElementException; import javax.net.ssl.SSLHandshakeException; @@ -63,19 +64,16 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.ProviderAPI.BACKEND_ERROR_KEY; import static se.leap.bitmaskclient.ProviderAPI.BACKEND_ERROR_MESSAGE; -import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING; -import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON; -import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE; -import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE; import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE; -import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE; import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_SERVICE_JSON; +import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE; import static se.leap.bitmaskclient.ProviderAPI.ERRORID; import static se.leap.bitmaskclient.ProviderAPI.ERRORS; import static se.leap.bitmaskclient.ProviderAPI.FAILED_LOGIN; import static se.leap.bitmaskclient.ProviderAPI.FAILED_SIGNUP; -import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE; import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE; +import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE; import static se.leap.bitmaskclient.ProviderAPI.LOGOUT_FAILED; import static se.leap.bitmaskclient.ProviderAPI.LOG_IN; import static se.leap.bitmaskclient.ProviderAPI.LOG_OUT; @@ -90,15 +88,18 @@ import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_LOGIN; import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_LOGOUT; import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_SIGNUP; import static se.leap.bitmaskclient.ProviderAPI.UPDATE_PROVIDER_DETAILS; +import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE; +import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING; +import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON; +import static se.leap.bitmaskclient.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE; import static se.leap.bitmaskclient.R.string.certificate_error; -import static se.leap.bitmaskclient.R.string.switch_provider_menu_option; -import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; import static se.leap.bitmaskclient.R.string.error_io_exception_user_message; import static se.leap.bitmaskclient.R.string.error_json_exception_user_message; import static se.leap.bitmaskclient.R.string.error_no_such_algorithm_exception_user_message; import static se.leap.bitmaskclient.R.string.malformed_url; import static se.leap.bitmaskclient.R.string.server_unreachable_message; import static se.leap.bitmaskclient.R.string.service_is_down_error; +import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_cert; import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_details; import static se.leap.bitmaskclient.R.string.warning_expired_provider_cert; @@ -290,7 +291,7 @@ public abstract class ProviderApiManagerBase { JSONObject stepResult = null; OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), stepResult); if (okHttpClient == null) { - return authFailedNotification(stepResult, username); + return backendErrorNotification(stepResult, username); } LeapSRPSession client = new LeapSRPSession(username, password); @@ -302,7 +303,7 @@ public abstract class ProviderApiManagerBase { Bundle result = new Bundle(); if (api_result.has(ERRORS) || api_result.has(BACKEND_ERROR_KEY)) - result = authFailedNotification(api_result, username); + result = backendErrorNotification(api_result, username); else { result.putString(CREDENTIALS_USERNAME, username); result.putString(CREDENTIALS_PASSWORD, password); @@ -349,7 +350,7 @@ public abstract class ProviderApiManagerBase { OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), stepResult); if (okHttpClient == null) { - return authFailedNotification(stepResult, username); + return backendErrorNotification(stepResult, username); } LeapSRPSession client = new LeapSRPSession(username, password); @@ -367,15 +368,15 @@ public abstract class ProviderApiManagerBase { if (client.verify(M2)) { result.putBoolean(BROADCAST_RESULT_KEY, true); } else { - authFailedNotification(step_result, username); + backendErrorNotification(step_result, username); } } else { result.putBoolean(BROADCAST_RESULT_KEY, false); result.putString(CREDENTIALS_USERNAME, username); - result.putString(resources.getString(R.string.user_message), resources.getString(R.string.error_srp_math_error_user_message)); + result.putString(USER_MESSAGE, resources.getString(R.string.error_srp_math_error_user_message)); } } catch (JSONException e) { - result = authFailedNotification(step_result, username); + result = backendErrorNotification(step_result, username); e.printStackTrace(); } @@ -391,7 +392,7 @@ public abstract class ProviderApiManagerBase { return true; } - private Bundle authFailedNotification(JSONObject result, String username) { + private Bundle backendErrorNotification(JSONObject result, String username) { Bundle userNotificationBundle = new Bundle(); if (result.has(ERRORS)) { Object baseErrorMessage = result.opt(ERRORS); @@ -400,14 +401,14 @@ public abstract class ProviderApiManagerBase { JSONObject errorMessage = result.getJSONObject(ERRORS); String errorType = errorMessage.keys().next().toString(); String message = errorMessage.get(errorType).toString(); - userNotificationBundle.putString(resources.getString(R.string.user_message), message); - } catch (JSONException e) { + userNotificationBundle.putString(USER_MESSAGE, message); + } catch (JSONException | NoSuchElementException | NullPointerException e) { e.printStackTrace(); } } else if (baseErrorMessage instanceof String) { try { String errorMessage = result.getString(ERRORS); - userNotificationBundle.putString(resources.getString(R.string.user_message), errorMessage); + userNotificationBundle.putString(USER_MESSAGE, errorMessage); } catch (JSONException e) { e.printStackTrace(); } @@ -418,7 +419,7 @@ public abstract class ProviderApiManagerBase { if (result.has(BACKEND_ERROR_MESSAGE)) { backendErrorMessage = resources.getString(R.string.error) + result.getString(BACKEND_ERROR_MESSAGE); } - userNotificationBundle.putString(resources.getString(R.string.user_message), backendErrorMessage); + userNotificationBundle.putString(USER_MESSAGE, backendErrorMessage); } catch (JSONException e) { e.printStackTrace(); } @@ -431,7 +432,7 @@ public abstract class ProviderApiManagerBase { return userNotificationBundle; } - void sendToReceiverOrBroadcast(ResultReceiver receiver, int resultCode, Bundle resultData, Provider provider) { + private void sendToReceiverOrBroadcast(ResultReceiver receiver, int resultCode, Bundle resultData, Provider provider) { if (resultData == null || resultData == Bundle.EMPTY) { resultData = new Bundle(); } diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java index d41be512..e6877756 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java @@ -30,6 +30,7 @@ import org.json.JSONException; import butterknife.InjectView; import butterknife.OnClick; import se.leap.bitmaskclient.Constants.CREDENTIAL_ERRORS; +import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.userstatus.User; import static android.view.View.GONE; @@ -41,9 +42,12 @@ import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.Constants.CREDENTIALS_PASSWORD; import static se.leap.bitmaskclient.Constants.CREDENTIALS_USERNAME; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.ProviderAPI.BACKEND_ERROR_KEY; import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.ProviderAPI.ERRORS; import static se.leap.bitmaskclient.ProviderAPI.LOG_IN; import static se.leap.bitmaskclient.ProviderAPI.SIGN_UP; +import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE; /** * Base Activity for activities concerning a provider interaction @@ -59,7 +63,6 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc final private static String SHOWING_FORM = "SHOWING_FORM"; final private static String PERFORMING_ACTION = "PERFORMING_ACTION"; - final public static String USER_MESSAGE = "USER_MESSAGE"; final private static String USERNAME_ERROR = "USERNAME_ERROR"; final private static String PASSWORD_ERROR = "PASSWORD_ERROR"; final private static String PASSWORD_VERIFICATION_ERROR = "PASSWORD_VERIFICATION_ERROR"; @@ -344,8 +347,8 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc if (arguments.containsKey(CREDENTIAL_ERRORS.USERNAME_MISSING.toString())) { usernameError.setError(getString(R.string.username_ask)); } - if (arguments.containsKey(getString(R.string.user_message))) { - String userMessageString = arguments.getString(getString(R.string.user_message)); + if (arguments.containsKey(USER_MESSAGE)) { + String userMessageString = arguments.getString(USER_MESSAGE); try { userMessageString = new JSONArray(userMessageString).getString(0); } catch (JSONException e) { @@ -395,6 +398,10 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc switch (resultCode) { case ProviderAPI.SUCCESSFUL_SIGNUP: + String password = resultData.getString(CREDENTIALS_PASSWORD); + String username = resultData.getString(CREDENTIALS_USERNAME); + login(username, password); + break; case ProviderAPI.SUCCESSFUL_LOGIN: downloadVpnCertificate(handledProvider); break; @@ -403,12 +410,11 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc handleReceivedErrors((Bundle) intent.getParcelableExtra(BROADCAST_RESULT_KEY)); break; + case ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE: + // error handling takes place in MainActivity case ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE: successfullyFinished(handledProvider); break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE: - // TODO activity.setResult(RESULT_CANCELED); - break; } } } -- cgit v1.2.3 From 339251605b689d6afd4708d851d42d91fd1d3fa5 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 20 Feb 2018 16:01:31 +0100 Subject: #8853 fix provider setup with codigosur.org --- .../main/java/se/leap/bitmaskclient/Provider.java | 32 +++++----------------- 1 file changed, 7 insertions(+), 25 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 7104143c..98662783 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -90,9 +90,8 @@ public final class Provider implements Parcelable { } if (definition != null) { try { - this.definition = new JSONObject(definition); - parseDefinition(this.definition); - } catch (JSONException | NullPointerException e) { + define(new JSONObject(definition)); + } catch (JSONException e) { e.printStackTrace(); } } @@ -133,26 +132,8 @@ public final class Provider implements Parcelable { } public boolean define(JSONObject providerJson) { - /* - * fix against "api_uri": "https://calyx.net.malicious.url.net:4430", - * This method aims to prevent attacks where the provider.json file got manipulated by a third party. - * The main url should not change. - */ - - try { - String providerApiUrl = providerJson.getString(Provider.API_URL); - String providerDomain = providerJson.getString(Provider.DOMAIN); - if (getMainUrlString().contains(providerDomain) && providerApiUrl.contains(providerDomain + ":")) { - definition = providerJson; - parseDefinition(definition); - return true; - } else { - return false; - } - } catch (JSONException e) { - e.printStackTrace(); - return false; - } + definition = providerJson; + return parseDefinition(definition); } public JSONObject getDefinition() { @@ -345,7 +326,7 @@ public final class Provider implements Parcelable { } } - private void parseDefinition(JSONObject definition) { + private boolean parseDefinition(JSONObject definition) { try { String pin = definition.getString(CA_CERT_FINGERPRINT); this.certificatePin = pin.split(":")[1].trim(); @@ -354,8 +335,9 @@ public final class Provider implements Parcelable { this.allowAnonymous = definition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOW_ANONYMOUS); this.allowRegistered = definition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOWED_REGISTERED); this.apiVersion = getDefinition().getString(Provider.API_VERSION); + return true; } catch (JSONException | ArrayIndexOutOfBoundsException | MalformedURLException e) { - e.printStackTrace(); + return false; } } -- cgit v1.2.3 From e4f4521f9d50aad80a7c689eb949e75d1b521bac Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 21 Feb 2018 11:12:21 +0100 Subject: #8858 add custom providers to the providers list on successful setup --- .../main/java/se/leap/bitmaskclient/Provider.java | 3 -- .../bitmaskclient/ProviderListBaseActivity.java | 3 +- .../se/leap/bitmaskclient/ProviderManager.java | 50 +++++++++++++++++++--- 3 files changed, 47 insertions(+), 9 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 7104143c..f4e2c477 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -297,8 +297,6 @@ public final class Provider implements Parcelable { try { json.put(Provider.MAIN_URL, mainUrl); //TODO: add other fields here? - //this is used to save custom providers as json. I guess this doesn't work correctly - //TODO 2: verify that } catch (JSONException e) { e.printStackTrace(); } @@ -446,5 +444,4 @@ public final class Provider implements Parcelable { allowRegistered = false; allowAnonymous = false; } - } diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java index e961b0a2..3bf51a8c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java @@ -207,7 +207,8 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity void handleProviderSetUp(Provider handledProvider) { this.provider = handledProvider; - + adapter.add(provider); + adapter.saveProviders(); if (provider.allowsAnonymous()) { mConfigState.putExtra(SERVICES_RETRIEVED, true); downloadVpnCertificate(); diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java index ed41be67..b625c336 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java @@ -31,6 +31,8 @@ public class ProviderManager implements AdapteeCollection { private File externalFilesDir; private Set defaultProviders; private Set customProviders; + private Set defaultProviderURLs; + private Set customProviderURLs; private static ProviderManager instance; @@ -52,11 +54,20 @@ public class ProviderManager implements AdapteeCollection { private void addDefaultProviders(AssetManager assets_manager) { try { defaultProviders = providersFromAssets(URLS, assets_manager.list(URLS)); + defaultProviderURLs = getProviderUrlSetFromProviderSet(defaultProviders); } catch (IOException e) { e.printStackTrace(); } } + private Set getProviderUrlSetFromProviderSet(Set providers) { + HashSet providerUrls = new HashSet<>(); + for (Provider provider : providers) { + providerUrls.add(provider.getMainUrl().getUrl()); + } + return providerUrls; + } + private Set providersFromAssets(String directory, String[] relativeFilePaths) { Set providers = new HashSet<>(); @@ -89,6 +100,7 @@ public class ProviderManager implements AdapteeCollection { customProviders = externalFilesDir != null && externalFilesDir.isDirectory() ? providersFromFiles(externalFilesDir.list()) : new HashSet(); + customProviderURLs = getProviderUrlSetFromProviderSet(customProviders); } private Set providersFromFiles(String[] files) { @@ -132,6 +144,8 @@ public class ProviderManager implements AdapteeCollection { allProviders.addAll(defaultProviders); if(customProviders != null) allProviders.addAll(customProviders); + //add an option to add a custom provider + //TODO: refactor me? allProviders.add(new Provider()); return allProviders; } @@ -153,30 +167,56 @@ public class ProviderManager implements AdapteeCollection { @Override public boolean add(Provider element) { - return !defaultProviders.contains(element) || customProviders.add(element); + return element != null && + !defaultProviderURLs.contains(element.getMainUrl().getUrl()) && + customProviders.add(element) && + customProviderURLs.add(element.getMainUrl().getUrl()); } @Override public boolean remove(Object element) { - return customProviders.remove(element); + return element instanceof Provider && + customProviders.remove(element) && + customProviderURLs.remove(((Provider) element).getMainUrl().getUrl()); } @Override public boolean addAll(Collection elements) { - return customProviders.addAll(elements); + Iterator iterator = elements.iterator(); + boolean addedAll = true; + while (iterator.hasNext()) { + Provider p = (Provider) iterator.next(); + addedAll = customProviders.add(p) && + customProviderURLs.add(p.getMainUrl().getUrl()) && + addedAll; + } + return addedAll; } @Override public boolean removeAll(Collection elements) { - if(!elements.getClass().equals(Provider.class)) + Iterator iterator = elements.iterator(); + boolean removedAll = true; + try { + while (iterator.hasNext()) { + Provider p = (Provider) iterator.next(); + removedAll = ((defaultProviders.remove(p) && defaultProviderURLs.remove(p.getMainUrl().getUrl())) || + (customProviders.remove(p) && customProviderURLs.remove(p.getMainUrl().getUrl()))) && + removedAll; + } + } catch (ClassCastException e) { return false; - return defaultProviders.removeAll(elements) || customProviders.removeAll(elements); + } + + return removedAll; } @Override public void clear() { defaultProviders.clear(); customProviders.clear(); + customProviderURLs.clear(); + defaultProviderURLs.clear(); } void saveCustomProvidersToFile() { -- cgit v1.2.3 From 8e23cc34861f1b9fe5e04cdcf24563ffedf568b0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 21 Feb 2018 15:00:40 +0100 Subject: #8858 write tests for ProviderManager and some related refactorings --- .../java/se/leap/bitmaskclient/ConfigHelper.java | 40 ++++++---------------- .../se/leap/bitmaskclient/ProviderManager.java | 3 +- 2 files changed, 13 insertions(+), 30 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java index a52df460..083f4da3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java @@ -27,6 +27,8 @@ import org.spongycastle.util.encoders.Base64; import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -47,9 +49,11 @@ import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import static android.R.attr.name; import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION; @@ -125,36 +129,14 @@ public class ConfigHelper { return (X509Certificate) certificate; } + public static String loadInputStreamAsString(java.io.InputStream is) { + java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A"); + return s.hasNext() ? s.next() : ""; + } - public static String loadInputStreamAsString(InputStream inputStream) { - BufferedReader in = null; - try { - StringBuilder buf = new StringBuilder(); - in = new BufferedReader(new InputStreamReader(inputStream)); - - String str; - boolean isFirst = true; - while ( (str = in.readLine()) != null ) { - if (isFirst) - isFirst = false; - else - buf.append('\n'); - buf.append(str); - } - return buf.toString(); - } catch (IOException e) { - Log.e(TAG, "Error opening asset " + name); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - Log.e(TAG, "Error closing asset " + name); - } - } - } - - return null; + //allows us to mock FileInputStream + public static InputStream getInputStreamFrom(String filePath) throws FileNotFoundException { + return new FileInputStream(filePath); } protected static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) { diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java index b625c336..97ba3b98 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java @@ -107,7 +107,7 @@ public class ProviderManager implements AdapteeCollection { Set providers = new HashSet<>(); try { for (String file : files) { - String mainUrl = extractMainUrlFromInputStream(new FileInputStream(externalFilesDir.getAbsolutePath() + "/" + file)); + String mainUrl = extractMainUrlFromInputStream(ConfigHelper.getInputStreamFrom(externalFilesDir.getAbsolutePath() + "/" + file)); providers.add(new Provider(new URL(mainUrl))); } } catch (MalformedURLException | FileNotFoundException e) { @@ -219,6 +219,7 @@ public class ProviderManager implements AdapteeCollection { defaultProviderURLs.clear(); } + //FIXME: removed custom providers should be deleted here as well void saveCustomProvidersToFile() { try { for (Provider provider : customProviders) { -- cgit v1.2.3 From ce71463e93a0ca51a9a893a1eb666f51171e8e9d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 21 Feb 2018 17:50:06 +0100 Subject: #8861 fix splash screen handling --- app/src/main/java/se/leap/bitmaskclient/StartActivity.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java index 39717bd8..b7180f5f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java @@ -184,12 +184,9 @@ public class StartActivity extends Activity { @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)) { + if (resultCode == RESULT_OK && data != null && data.hasExtra(Provider.KEY)) { Provider provider = data.getParcelableExtra(Provider.KEY); ConfigHelper.storeProviderInPreferences(preferences, provider); EipCommand.startVPN(this, false); -- cgit v1.2.3 From cf10c3dc481b154cd8f4d6996c9a80643b67c840 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Thu, 22 Feb 2018 12:04:19 +0100 Subject: 8851 - remove options menu --- .../main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java | 6 ------ 1 file changed, 6 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java index 3bf51a8c..75fffaf7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java @@ -369,12 +369,6 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity } } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu); - return true; - } - public class ProviderAPIBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { -- cgit v1.2.3 From 0f5a0510aa83872417467914ad52aa3d0d663f51 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Thu, 22 Feb 2018 12:23:33 +0100 Subject: 8865 - allow disconnect without internet --- app/src/main/java/se/leap/bitmaskclient/EipFragment.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 8d1fa03a..4d28315f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -171,8 +171,8 @@ public class EipFragment extends Fragment implements Observer { super.onResume(); //FIXME: avoid race conditions while checking certificate an logging in at about the same time //eipCommand(Constants.EIP_ACTION_CHECK_CERT_VALIDITY); - handleNewState(); bindOpenVpnService(); + handleNewState(); } @Override @@ -407,8 +407,10 @@ public class EipFragment extends Fragment implements Observer { private boolean isOpenVpnRunningWithoutNetwork() { boolean isRunning = false; try { - isRunning = eipStatus.getLevel() == LEVEL_NONETWORK && - mService.isVpnRunning(); + if (mService != null) { + isRunning = eipStatus.getLevel() == LEVEL_NONETWORK && + mService.isVpnRunning(); + } } catch (Exception e) { //eat me e.printStackTrace(); -- cgit v1.2.3 From 0cf6368a993d23527802b3eba70ddeda4b5933c6 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Thu, 22 Feb 2018 15:47:32 +0100 Subject: 8867 - add url to username --- .../leap/bitmaskclient/ProviderCredentialsBaseActivity.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java index e6877756..15cd9617 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java @@ -186,7 +186,11 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc String username = usernameField.getText().toString(); String providerDomain = provider.getDomain(); if (username.endsWith(providerDomain)) { - return username.split("@" + providerDomain)[0]; + try { + return username.split("@" + providerDomain)[0]; + } catch (ArrayIndexOutOfBoundsException e) { + return ""; + } } return username; } @@ -240,9 +244,15 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc @Override public void afterTextChanged(Editable s) { if (getUsername().equalsIgnoreCase("")) { + s.clear(); usernameError.setError(getString(R.string.username_ask)); } else { usernameError.setError(null); + String suffix = "@" + provider.getDomain(); + if (!usernameField.getText().toString().endsWith(suffix)) { + s.append(suffix); + usernameField.setSelection(usernameField.getText().toString().indexOf('@')); + } } } }); -- cgit v1.2.3 From 6a683c605aa5bb5ce72f8ea46a4b6bcae0f9e98a Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Thu, 22 Feb 2018 17:00:40 +0100 Subject: 8868 - fix lollipop ui issues --- .../leap/bitmaskclient/ConfigWizardBaseActivity.java | 20 +++++++++++++++++++- .../main/java/se/leap/bitmaskclient/EipFragment.java | 5 +++-- .../java/se/leap/bitmaskclient/StartActivity.java | 4 +--- 3 files changed, 23 insertions(+), 6 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java index ea328216..f0e2de85 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java @@ -1,16 +1,19 @@ package se.leap.bitmaskclient; import android.content.SharedPreferences; +import android.graphics.PorterDuff; +import android.os.Build; import android.os.Bundle; -import android.os.PersistableBundle; import android.support.annotation.DrawableRes; import android.support.annotation.Nullable; import android.support.annotation.StringRes; +import android.support.v4.content.ContextCompat; import android.support.v7.widget.AppCompatImageView; import android.support.v7.widget.AppCompatTextView; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; +import android.widget.ProgressBar; import butterknife.InjectView; @@ -38,6 +41,9 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity { @InjectView(R.id.loading_screen) protected LinearLayout loadingScreen; + @InjectView(R.id.progressbar) + protected ProgressBar progressBar; + @InjectView(R.id.progressbar_description) protected AppCompatTextView progressbarText; @@ -59,6 +65,7 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity { super.setContentView(view); if (provider != null) setProviderHeaderText(provider.getName()); + setProgressbarColorForPreLollipop(); } @Override @@ -66,6 +73,7 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity { super.setContentView(layoutResID); if (provider != null) setProviderHeaderText(provider.getName()); + setProgressbarColorForPreLollipop(); } @Override @@ -73,8 +81,18 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity { super.setContentView(view, params); if (provider != null) setProviderHeaderText(provider.getName()); + setProgressbarColorForPreLollipop(); } + private void setProgressbarColorForPreLollipop() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + progressBar.getIndeterminateDrawable().setColorFilter( + ContextCompat.getColor(this, R.color.colorPrimary), + PorterDuff.Mode.SRC_IN); + } + } + + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 8d1fa03a..08622453 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -31,6 +31,7 @@ import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; import android.support.v7.widget.AppCompatImageView; +import android.support.v7.widget.AppCompatTextView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -84,10 +85,10 @@ public class EipFragment extends Fragment implements Observer { Button mainButton; @InjectView(R.id.routed_text) - TextView routedText; + AppCompatTextView routedText; @InjectView(R.id.vpn_route) - TextView vpnRoute; + AppCompatTextView vpnRoute; private EipStatus eipStatus; diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java index b7180f5f..6bbdeb4f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java @@ -13,12 +13,10 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import de.blinkt.openvpn.core.VpnStatus; -import se.leap.bitmaskclient.eip.EIP; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.userstatus.User; import static se.leap.bitmaskclient.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION; import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION; @@ -32,7 +30,7 @@ import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT; * and acts and calls another activity accordingly. * */ -public class StartActivity extends Activity { +public class StartActivity extends Activity{ public static final String TAG = StartActivity.class.getSimpleName(); @Retention(RetentionPolicy.SOURCE) -- cgit v1.2.3 From 06eb4014837704e04d6ea8e9d7a69475a58c3c65 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 23 Feb 2018 02:22:25 +0100 Subject: #8754 enable pause openvpn on device inactivity feature --- .../java/se/leap/bitmaskclient/ConfigHelper.java | 38 ++-- .../main/java/se/leap/bitmaskclient/Constants.java | 5 + .../main/java/se/leap/bitmaskclient/Dashboard.java | 0 .../leap/bitmaskclient/DrawerSettingsAdapter.java | 219 +++++++++++++++++++++ .../java/se/leap/bitmaskclient/EipFragment.java | 2 +- .../java/se/leap/bitmaskclient/MainActivity.java | 17 +- .../drawer/NavigationDrawerFragment.java | 149 ++++++++++++-- 7 files changed, 399 insertions(+), 31 deletions(-) delete mode 100644 app/src/main/java/se/leap/bitmaskclient/Dashboard.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java index a52df460..50d23106 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java @@ -16,7 +16,9 @@ */ package se.leap.bitmaskclient; +import android.content.Context; import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; @@ -52,6 +54,7 @@ import java.util.Locale; import java.util.Map; import static android.R.attr.name; +import static se.leap.bitmaskclient.Constants.DEFAULT_SHARED_PREFS_BATTERY_SAVER; import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION; import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED; import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION; @@ -383,6 +386,7 @@ public class ConfigHelper { clearDataOfLastProvider(preferences, false); } + @Deprecated public static void clearDataOfLastProvider(SharedPreferences preferences, boolean commit) { Map allEntries = preferences.getAll(); List lastProvidersKeys = new ArrayList<>(); @@ -410,18 +414,30 @@ public class ConfigHelper { } public static void deleteProviderDetailsFromPreferences(@NonNull SharedPreferences preferences, String providerDomain) { - preferences.edit(). - remove(Provider.KEY + "." + providerDomain). - remove(Provider.CA_CERT + "." + providerDomain). - remove(Provider.CA_CERT_FINGERPRINT + "." + providerDomain). - remove(Provider.MAIN_URL + "." + providerDomain). - remove(Provider.KEY + "." + providerDomain). - remove(Provider.CA_CERT + "." + providerDomain). - remove(PROVIDER_EIP_DEFINITION + "." + providerDomain). - remove(PROVIDER_PRIVATE_KEY + "." + providerDomain). - remove(PROVIDER_VPN_CERTIFICATE + "." + providerDomain). - apply(); + preferences.edit(). + remove(Provider.KEY + "." + providerDomain). + remove(Provider.CA_CERT + "." + providerDomain). + remove(Provider.CA_CERT_FINGERPRINT + "." + providerDomain). + remove(Provider.MAIN_URL + "." + providerDomain). + remove(Provider.KEY + "." + providerDomain). + remove(Provider.CA_CERT + "." + providerDomain). + remove(PROVIDER_EIP_DEFINITION + "." + providerDomain). + remove(PROVIDER_PRIVATE_KEY + "." + providerDomain). + remove(PROVIDER_VPN_CERTIFICATE + "." + providerDomain). + apply(); } + public static void saveBattery(Context context, boolean isEnabled) { + if (context == null) { + return; + } + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + preferences.edit().putBoolean(DEFAULT_SHARED_PREFS_BATTERY_SAVER, isEnabled).apply(); + } + + public static boolean getSaveBattery(@NonNull Context context) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + return preferences.getBoolean(DEFAULT_SHARED_PREFS_BATTERY_SAVER, false); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java index 2b7a8113..58145015 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java @@ -81,4 +81,9 @@ public interface Constants { String BROADCAST_RESULT_CODE = "BROADCAST.RESULT_CODE"; String BROADCAST_RESULT_KEY = "BROADCAST.RESULT_KEY"; + + ////////////////////////////////////////////// + // ICS-OPENVPN CONSTANTS + ///////////////////////////////////////////// + String DEFAULT_SHARED_PREFS_BATTERY_SAVER = "screenoff"; } diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java deleted file mode 100644 index e69de29b..00000000 diff --git a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java new file mode 100644 index 00000000..867f3d48 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java @@ -0,0 +1,219 @@ +/** + * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package se.leap.bitmaskclient; + +import android.support.annotation.NonNull; +import android.support.v7.widget.SwitchCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.CompoundButton; +import android.widget.TextView; + +import java.util.ArrayList; + +/** + * Created by cyberta on 21.02.18. + */ + +public class DrawerSettingsAdapter extends BaseAdapter { + + //item types + public static final int NONE = -1; + public static final int SWITCH_PROVIDER = 0; + public static final int LOG = 1; + public static final int ABOUT = 2; + public static final int BATTERY_SAVER = 3; + + //view types + public final static int VIEW_SIMPLE_TEXT = 0; + public final static int VIEW_SWITCH = 1; + + public static class DrawerSettingsItem { + private String description = ""; + private int viewType = VIEW_SIMPLE_TEXT; + private boolean isChecked = false; + private int itemType = NONE; + private CompoundButton.OnCheckedChangeListener callback; + + private DrawerSettingsItem(String description, int viewType, boolean isChecked, int itemType, CompoundButton.OnCheckedChangeListener callback) { + this.description = description; + this.viewType = viewType; + this.isChecked = isChecked; + this.itemType = itemType; + this.callback = callback; + } + + public static DrawerSettingsItem getSimpleTextInstance(String description, int itemType) { + return new DrawerSettingsItem(description, VIEW_SIMPLE_TEXT, false, itemType, null); + } + + public static DrawerSettingsItem getSwitchInstance(String description, boolean isChecked, int itemType, CompoundButton.OnCheckedChangeListener callback) { + return new DrawerSettingsItem(description, VIEW_SWITCH, isChecked, itemType, callback); + } + + public int getItemType() { + return itemType; + } + + public void setChecked(boolean checked) { + isChecked = checked; + } + + public boolean isChecked() { + return isChecked; + } + } + + private ArrayList mData = new ArrayList<>(); + private LayoutInflater mInflater; + + public DrawerSettingsAdapter(LayoutInflater layoutInflater) { + mInflater = layoutInflater; + } + + public void addItem(final DrawerSettingsItem item) { + mData.add(item); + notifyDataSetChanged(); + } + + @Override + public int getItemViewType(int position) { + DrawerSettingsItem item = mData.get(position); + return item.viewType; + } + + @Override + public int getViewTypeCount() { + boolean hasSwitchItem = false; + for (DrawerSettingsItem item : mData) { + if (item.viewType == VIEW_SWITCH) { + hasSwitchItem = true; + break; + } + } + return hasSwitchItem ? 2 : 1; + } + + @Override + public int getCount() { + return mData.size(); + } + + @Override + public DrawerSettingsItem getItem(int position) { + return mData.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + + DrawerSettingsItem drawerSettingsItem = mData.get(position); + ViewHolder holder = null; + int type = getItemViewType(position); + if (convertView == null) { + holder = new ViewHolder(); + switch(type) { + case VIEW_SIMPLE_TEXT: + convertView = initTextViewBinding(holder); + holder.textView.setText(drawerSettingsItem.description); + break; + case VIEW_SWITCH: + convertView = initSwitchBinding(holder); + bindSwitch(drawerSettingsItem, holder); + break; + } + convertView.setTag(holder); + } else { + holder = (ViewHolder)convertView.getTag(); + switch (type) { + case VIEW_SIMPLE_TEXT: + if (holder.isSwitchViewHolder()) { + holder.resetSwitchView(); + convertView = initTextViewBinding(holder); + } + holder.textView.setText(drawerSettingsItem.description); + break; + case VIEW_SWITCH: + if (!holder.isSwitchViewHolder()) { + holder.resetTextView(); + convertView = initSwitchBinding(holder); + } + bindSwitch(drawerSettingsItem, holder); + break; + } + convertView.setTag(holder); + } + return convertView; + } + + private void bindSwitch(DrawerSettingsItem drawerSettingsItem, ViewHolder holder) { + holder.switchView.setChecked(drawerSettingsItem.isChecked); + holder.switchView.setText(drawerSettingsItem.description); + holder.switchView.setOnCheckedChangeListener(drawerSettingsItem.callback); + } + + @NonNull + private View initSwitchBinding(ViewHolder holder) { + View convertView = mInflater.inflate(R.layout.switch_list_item, null); + holder.switchView = convertView.findViewById(android.R.id.text1); + return convertView; + } + + @NonNull + private View initTextViewBinding(ViewHolder holder) { + View convertView = mInflater.inflate(R.layout.single_list_item, null); + holder.textView = convertView.findViewById(android.R.id.text1); + return convertView; + } + + public DrawerSettingsItem getDrawerItem(int elementType) { + for (DrawerSettingsItem item : mData) { + if (item.itemType == elementType) { + return item; + } + } + return null; + } + + static class ViewHolder { + TextView textView; + SwitchCompat switchView; + + boolean isSwitchViewHolder() { + return switchView != null; + } + + void resetSwitchView() { + switchView.setOnCheckedChangeListener(null); + switchView = null; + } + + void resetTextView() { + textView = null; + } + } +} + + + diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index fb57aea8..7b84657c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * Copyright (c) 2018 LEAP Encryption Access Project and contributers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java index 6e778309..952f2d1f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java @@ -1,3 +1,19 @@ +/** + * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package se.leap.bitmaskclient; @@ -20,7 +36,6 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; -import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.json.JSONObject; 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 772140b0..ebe5783a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -1,6 +1,24 @@ +/** + * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package se.leap.bitmaskclient.drawer; +import android.app.Activity; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; @@ -11,6 +29,7 @@ import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; @@ -22,10 +41,13 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.CompoundButton; import android.widget.ListView; import android.widget.Toast; import se.leap.bitmaskclient.ConfigHelper; +import se.leap.bitmaskclient.DrawerSettingsAdapter; +import se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem; import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.ProviderListActivity; import se.leap.bitmaskclient.EipFragment; @@ -35,9 +57,19 @@ import se.leap.bitmaskclient.fragments.LogFragment; import static android.content.Context.MODE_PRIVATE; import static se.leap.bitmaskclient.BitmaskApp.getRefWatcher; +import static se.leap.bitmaskclient.ConfigHelper.getSaveBattery; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.DrawerSettingsAdapter.ABOUT; +import static se.leap.bitmaskclient.DrawerSettingsAdapter.BATTERY_SAVER; +import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSimpleTextInstance; +import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSwitchInstance; +import static se.leap.bitmaskclient.DrawerSettingsAdapter.LOG; +import static se.leap.bitmaskclient.DrawerSettingsAdapter.SWITCH_PROVIDER; +import static se.leap.bitmaskclient.R.string.about_fragment_title; +import static se.leap.bitmaskclient.R.string.log_fragment_title; +import static se.leap.bitmaskclient.R.string.switch_provider_menu_option; /** * Fragment used for managing interactions for and presentation of a navigation drawer. @@ -63,6 +95,7 @@ public class NavigationDrawerFragment extends Fragment { private ListView mDrawerAccountsListView; private View mFragmentContainerView; private ArrayAdapter accountListAdapter; + private DrawerSettingsAdapter settingsListAdapter; private boolean mFromSavedInstanceState; private boolean mUserLearnedDrawer; @@ -71,17 +104,23 @@ public class NavigationDrawerFragment extends Fragment { private SharedPreferences preferences; + private final static String KEY_SHOW_ENABLE_EXPERIMENTAL_FEATURE = "KEY_SHOW_ENABLE_EXPERIMENTAL_FEATURE"; + private boolean showEnableExperimentalFeature = false; + AlertDialog alertDialog; + public NavigationDrawerFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Read in the flag indicating whether or not the user has demonstrated awareness of the // drawer. See PREF_USER_LEARNED_DRAWER for details. preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); mUserLearnedDrawer = preferences.getBoolean(PREF_USER_LEARNED_DRAWER, false); + if (savedInstanceState != null) { + mFromSavedInstanceState = true; + } } @Override @@ -95,7 +134,9 @@ public class NavigationDrawerFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mDrawerView = inflater.inflate(R.layout.drawer_main, container, false); + restoreFromSavedInstance(savedInstanceState); return mDrawerView; + } public boolean isDrawerOpen() { @@ -119,16 +160,23 @@ public class NavigationDrawerFragment extends Fragment { selectItem(parent, position); } }); + settingsListAdapter = new DrawerSettingsAdapter(getLayoutInflater()); + if (getContext() != null) { + settingsListAdapter.addItem(getSwitchInstance(getString(R.string.save_battery), + getSaveBattery(getContext()), + BATTERY_SAVER, + new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean newStateIsChecked) { + onSwitchItemSelected(BATTERY_SAVER, newStateIsChecked); + } + })); + } + settingsListAdapter.addItem(getSimpleTextInstance(getString(switch_provider_menu_option), SWITCH_PROVIDER)); + settingsListAdapter.addItem(getSimpleTextInstance(getString(log_fragment_title), LOG)); + settingsListAdapter.addItem(getSimpleTextInstance(getString(about_fragment_title), ABOUT)); - mDrawerSettingsListView.setAdapter(new ArrayAdapter( - actionBar.getThemedContext(), - R.layout.single_list_item, - android.R.id.text1, - new String[]{ - getString(R.string.switch_provider_menu_option), - getString(R.string.log_fragment_title), - getString(R.string.about_fragment_title), - })); + mDrawerSettingsListView.setAdapter(settingsListAdapter); mDrawerAccountsListView = mDrawerView.findViewById(R.id.accountList); mDrawerAccountsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @@ -215,12 +263,55 @@ public class NavigationDrawerFragment extends Fragment { if (mDrawerLayout != null) { mDrawerLayout.closeDrawer(mFragmentContainerView); } - onNavigationDrawerItemSelected(list, position); + onTextItemSelected(list, position); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); + if (showEnableExperimentalFeature) { + outState.putBoolean(KEY_SHOW_ENABLE_EXPERIMENTAL_FEATURE, true); + alertDialog.dismiss(); + } + } + + private void restoreFromSavedInstance(Bundle savedInstanceState) { + if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SHOW_ENABLE_EXPERIMENTAL_FEATURE)) { + showEnableExperimentalFeature = true; + showExperimentalFeatureAlert(); + } + } + + private void showExperimentalFeatureAlert() { + Activity activity = getActivity(); + if (activity == null) { + return; + } + + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity()); + showEnableExperimentalFeature = true; + alertDialog = alertBuilder.setTitle(activity.getString(R.string.experimental_feature_title)) + .setMessage(activity.getString(R.string.experimental_feature_message)) + .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + DrawerSettingsItem item = settingsListAdapter.getDrawerItem(BATTERY_SAVER); + item.setChecked(true); + settingsListAdapter.notifyDataSetChanged(); + ConfigHelper.saveBattery(getContext(), item.isChecked()); + } + }) + .setNegativeButton(activity.getString(android.R.string.no), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + disableSwitch(BATTERY_SAVER); + } + }).setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + showEnableExperimentalFeature = false; + } + }).show(); } @Override @@ -272,7 +363,28 @@ public class NavigationDrawerFragment extends Fragment { return ((AppCompatActivity) getActivity()).getSupportActionBar(); } - public void onNavigationDrawerItemSelected(AdapterView parent, int position) { + private void onSwitchItemSelected(int elementType, boolean newStateIsChecked) { + switch (elementType) { + case BATTERY_SAVER: + if (newStateIsChecked) { + showExperimentalFeatureAlert(); + } else { + ConfigHelper.saveBattery(this.getContext(), false); + disableSwitch(BATTERY_SAVER); + } + break; + default: + break; + } + } + + private void disableSwitch(int elementType) { + DrawerSettingsItem item = settingsListAdapter.getDrawerItem(elementType); + item.setChecked(false); + settingsListAdapter.notifyDataSetChanged(); + } + + public void onTextItemSelected(AdapterView parent, int position) { // update the main content by replacing fragments FragmentManager fragmentManager = getFragmentManager(); Fragment fragment = null; @@ -286,16 +398,17 @@ public class NavigationDrawerFragment extends Fragment { fragment.setArguments(arguments); } else { Log.d("Drawer", String.format("Selected position %d", position)); - switch (position) { - case 0: + DrawerSettingsItem settingsItem = settingsListAdapter.getItem(position); + switch (settingsItem.getItemType()) { + case SWITCH_PROVIDER: getActivity().startActivityForResult(new Intent(getActivity(), ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER); break; - case 1: - mTitle = getString(R.string.log_fragment_title); + case LOG: + mTitle = getString(log_fragment_title); fragment = new LogFragment(); break; - case 2: - mTitle = getString(R.string.about_fragment_title); + case ABOUT: + mTitle = getString(about_fragment_title); fragment = new AboutFragment(); break; default: -- cgit v1.2.3 From ad086ab192b9094278b27f94120566a7ca21dccc Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 23 Feb 2018 02:34:55 +0100 Subject: #8754 fix dialog cancellation handling and change dialog title --- .../leap/bitmaskclient/drawer/NavigationDrawerFragment.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'app/src/main/java/se/leap') 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 ebe5783a..25ef9161 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -290,8 +290,8 @@ public class NavigationDrawerFragment extends Fragment { AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity()); showEnableExperimentalFeature = true; - alertDialog = alertBuilder.setTitle(activity.getString(R.string.experimental_feature_title)) - .setMessage(activity.getString(R.string.experimental_feature_message)) + alertDialog = alertBuilder.setTitle(activity.getString(R.string.save_battery)) + .setMessage(activity.getString(R.string.save_battery_message)) .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -311,7 +311,13 @@ public class NavigationDrawerFragment extends Fragment { public void onDismiss(DialogInterface dialog) { showEnableExperimentalFeature = false; } - }).show(); + }).setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + disableSwitch(BATTERY_SAVER); + } + }) + .show(); } @Override -- cgit v1.2.3 From e317fd9029948a06afd0842c69a714f3d9d0862d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 23 Feb 2018 03:50:51 +0100 Subject: #8754 disable dialog flag on cancel --- .../main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java | 1 + 1 file changed, 1 insertion(+) (limited to 'app/src/main/java/se/leap') 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 25ef9161..3651cd05 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -315,6 +315,7 @@ public class NavigationDrawerFragment extends Fragment { @Override public void onCancel(DialogInterface dialog) { disableSwitch(BATTERY_SAVER); + showEnableExperimentalFeature = false; } }) .show(); -- cgit v1.2.3 From 0ab7afb26280510f6097fe403a280a5ede3f40f7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 24 Feb 2018 14:21:21 +0100 Subject: #8754 ignore initial onCheckedChanged callback during ui setup --- .../java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app/src/main/java/se/leap') 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 3651cd05..111c02f5 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -277,7 +277,6 @@ public class NavigationDrawerFragment extends Fragment { private void restoreFromSavedInstance(Bundle savedInstanceState) { if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SHOW_ENABLE_EXPERIMENTAL_FEATURE)) { - showEnableExperimentalFeature = true; showExperimentalFeatureAlert(); } } @@ -373,6 +372,10 @@ public class NavigationDrawerFragment extends Fragment { private void onSwitchItemSelected(int elementType, boolean newStateIsChecked) { switch (elementType) { case BATTERY_SAVER: + if (ConfigHelper.getSaveBattery(getContext()) == newStateIsChecked) { + //initial ui setup, ignore + return; + } if (newStateIsChecked) { showExperimentalFeatureAlert(); } else { -- cgit v1.2.3 From 2324de2a0bbcdd6befe4bbe1fea70731d538b664 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Sun, 25 Feb 2018 10:24:49 +0100 Subject: 8865 - resolve discussions --- .../java/se/leap/bitmaskclient/EipFragment.java | 55 ++++++++++++---------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 4d28315f..35693c9b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -48,7 +48,6 @@ import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipStatus; -import se.leap.bitmaskclient.eip.VoidVpnService; import se.leap.bitmaskclient.views.VpnStateImage; import static android.view.View.GONE; @@ -67,7 +66,6 @@ public class EipFragment extends Fragment implements Observer { public final static String TAG = EipFragment.class.getSimpleName(); - public static final String START_EIP_ON_BOOT = "start on boot"; public static final String ASK_TO_CANCEL_VPN = "ask_to_cancel_vpn"; @@ -100,23 +98,7 @@ public class EipFragment extends Fragment implements Observer { AlertDialog alertDialog; private IOpenVPNServiceInternal mService; - private ServiceConnection openVpnConnection = new ServiceConnection() { - - - - @Override - public void onServiceConnected(ComponentName className, - IBinder service) { - - mService = IOpenVPNServiceInternal.Stub.asInterface(service); - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - mService = null; - } - - }; + private ServiceConnection openVpnConnection; @Override public void onAttach(Context context) { @@ -141,6 +123,7 @@ public class EipFragment extends Fragment implements Observer { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + openVpnConnection = new EipFragmentServiceConnection(); eipStatus = EipStatus.getInstance(); Activity activity = getActivity(); if (activity != null) { @@ -230,7 +213,7 @@ public class EipFragment extends Fragment implements Observer { } void handleIcon() { - if (eipStatus.isConnected() || eipStatus.isConnecting()) + if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting()) handleSwitchOff(); else handleSwitchOn(); @@ -386,10 +369,20 @@ public class EipFragment extends Fragment implements Observer { routedText.setVisibility(GONE); vpnRoute.setVisibility(GONE); colorBackgroundALittle(); - } else if (eipStatus.isConnected() || isOpenVpnRunningWithoutNetwork()) { + } else if (eipStatus.isConnected() ) { mainButton.setText(activity.getString(R.string.vpn_button_turn_off)); vpnStateImage.setStateIcon(R.drawable.vpn_connected); vpnStateImage.stopProgress(true); + routedText.setText(R.string.vpn_securely_routed); + routedText.setVisibility(VISIBLE); + vpnRoute.setVisibility(VISIBLE); + vpnRoute.setText(ConfigHelper.getProviderName(preferences)); + colorBackground(); + } else if(isOpenVpnRunningWithoutNetwork()){ + mainButton.setText(activity.getString(R.string.vpn_button_turn_off)); + vpnStateImage.setStateIcon(R.drawable.vpn_disconnected); + vpnStateImage.stopProgress(true); + routedText.setText(R.string.vpn_securely_routed_no_internet); routedText.setVisibility(VISIBLE); vpnRoute.setVisibility(VISIBLE); vpnRoute.setText(ConfigHelper.getProviderName(preferences)); @@ -407,10 +400,8 @@ public class EipFragment extends Fragment implements Observer { private boolean isOpenVpnRunningWithoutNetwork() { boolean isRunning = false; try { - if (mService != null) { - isRunning = eipStatus.getLevel() == LEVEL_NONETWORK && - mService.isVpnRunning(); - } + isRunning = eipStatus.getLevel() == LEVEL_NONETWORK && + mService.isVpnRunning(); } catch (Exception e) { //eat me e.printStackTrace(); @@ -467,4 +458,18 @@ public class EipFragment extends Fragment implements Observer { activity.startActivityForResult(intent, REQUEST_CODE_LOG_IN); } } + + private class EipFragmentServiceConnection implements ServiceConnection { + @Override + public void onServiceConnected(ComponentName className, + IBinder service) { + mService = IOpenVPNServiceInternal.Stub.asInterface(service); + handleNewState(); + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + mService = null; + } + } } -- cgit v1.2.3 From e02f1648353dad012c3c556f996a667640da11ce Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 25 Feb 2018 11:39:54 +0100 Subject: #8754 don't cancel dialog onSavedInstanceState --- .../drawer/NavigationDrawerFragment.java | 69 +++++++++++----------- 1 file changed, 35 insertions(+), 34 deletions(-) (limited to 'app/src/main/java/se/leap') 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 111c02f5..6e39e9ed 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -48,9 +48,9 @@ import android.widget.Toast; import se.leap.bitmaskclient.ConfigHelper; import se.leap.bitmaskclient.DrawerSettingsAdapter; import se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem; +import se.leap.bitmaskclient.EipFragment; import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.ProviderListActivity; -import se.leap.bitmaskclient.EipFragment; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.fragments.AboutFragment; import se.leap.bitmaskclient.fragments.LogFragment; @@ -136,7 +136,6 @@ public class NavigationDrawerFragment extends Fragment { mDrawerView = inflater.inflate(R.layout.drawer_main, container, false); restoreFromSavedInstance(savedInstanceState); return mDrawerView; - } public boolean isDrawerOpen() { @@ -271,7 +270,6 @@ public class NavigationDrawerFragment extends Fragment { super.onSaveInstanceState(outState); if (showEnableExperimentalFeature) { outState.putBoolean(KEY_SHOW_ENABLE_EXPERIMENTAL_FEATURE, true); - alertDialog.dismiss(); } } @@ -287,37 +285,40 @@ public class NavigationDrawerFragment extends Fragment { return; } - AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity()); - showEnableExperimentalFeature = true; - alertDialog = alertBuilder.setTitle(activity.getString(R.string.save_battery)) - .setMessage(activity.getString(R.string.save_battery_message)) - .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - DrawerSettingsItem item = settingsListAdapter.getDrawerItem(BATTERY_SAVER); - item.setChecked(true); - settingsListAdapter.notifyDataSetChanged(); - ConfigHelper.saveBattery(getContext(), item.isChecked()); - } - }) - .setNegativeButton(activity.getString(android.R.string.no), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - disableSwitch(BATTERY_SAVER); - } - }).setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - showEnableExperimentalFeature = false; - } - }).setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - disableSwitch(BATTERY_SAVER); - showEnableExperimentalFeature = false; - } - }) - .show(); + try { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity()); + showEnableExperimentalFeature = true; + alertDialog = alertBuilder.setTitle(activity.getString(R.string.save_battery)) + .setMessage(activity.getString(R.string.save_battery_message)) + .setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + DrawerSettingsItem item = settingsListAdapter.getDrawerItem(BATTERY_SAVER); + item.setChecked(true); + settingsListAdapter.notifyDataSetChanged(); + ConfigHelper.saveBattery(getContext(), item.isChecked()); + } + }) + .setNegativeButton(activity.getString(android.R.string.no), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + disableSwitch(BATTERY_SAVER); + } + }).setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + showEnableExperimentalFeature = false; + } + }).setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + disableSwitch(BATTERY_SAVER); + } + }).show(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + } @Override -- cgit v1.2.3 From 0bf176d8e925c71be7853c67f7c8b57d58df0ce3 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Sun, 25 Feb 2018 15:47:49 +0100 Subject: 8865 - set correct route as in 8824 --- app/src/main/java/se/leap/bitmaskclient/EipFragment.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 35693c9b..f80d15e7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -44,8 +44,10 @@ import java.util.Observer; import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnClick; +import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; +import de.blinkt.openvpn.core.ProfileManager; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipStatus; import se.leap.bitmaskclient.views.VpnStateImage; @@ -376,7 +378,7 @@ public class EipFragment extends Fragment implements Observer { routedText.setText(R.string.vpn_securely_routed); routedText.setVisibility(VISIBLE); vpnRoute.setVisibility(VISIBLE); - vpnRoute.setText(ConfigHelper.getProviderName(preferences)); + setVpnRouteText(); colorBackground(); } else if(isOpenVpnRunningWithoutNetwork()){ mainButton.setText(activity.getString(R.string.vpn_button_turn_off)); @@ -385,7 +387,7 @@ public class EipFragment extends Fragment implements Observer { routedText.setText(R.string.vpn_securely_routed_no_internet); routedText.setVisibility(VISIBLE); vpnRoute.setVisibility(VISIBLE); - vpnRoute.setText(ConfigHelper.getProviderName(preferences)); + setVpnRouteText(); colorBackground(); } else { mainButton.setText(activity.getString(R.string.vpn_button_turn_on)); @@ -459,6 +461,15 @@ public class EipFragment extends Fragment implements Observer { } } + private void setVpnRouteText() { + String vpnRouteString = provider.getName(); + VpnProfile vpnProfile = ProfileManager.getLastConnectedVpn(); + if (vpnProfile != null && vpnProfile.mName != null) { + vpnRouteString += " (" + vpnProfile.mName + ")"; + } + vpnRoute.setText(vpnRouteString); + } + private class EipFragmentServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName className, -- cgit v1.2.3 From 304efac028b1a2e2b145e5b2cba474c4b84fd3cf Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Sun, 25 Feb 2018 16:10:05 +0100 Subject: 8865 - color background only a little if not internet connection --- app/src/main/java/se/leap/bitmaskclient/EipFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 7c61ddae..c4f4dbc9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -389,7 +389,7 @@ public class EipFragment extends Fragment implements Observer { routedText.setVisibility(VISIBLE); vpnRoute.setVisibility(VISIBLE); setVpnRouteText(); - colorBackground(); + colorBackgroundALittle(); } else { mainButton.setText(activity.getString(R.string.vpn_button_turn_on)); vpnStateImage.setStateIcon(R.drawable.vpn_disconnected); -- cgit v1.2.3 From 44322f28b28676a8938f4c1066a75ba47397aa7d Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Mon, 26 Feb 2018 20:31:48 +0100 Subject: 8865 - allow disconnecting without internet * moved logic from MainActivity to EIP --- .../java/se/leap/bitmaskclient/EipFragment.java | 3 +- .../java/se/leap/bitmaskclient/MainActivity.java | 74 +-------------- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 103 +++++++++++++++++++-- 3 files changed, 99 insertions(+), 81 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index c4f4dbc9..956cd67e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -37,7 +37,6 @@ 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; @@ -252,7 +251,7 @@ public class EipFragment extends Fragment implements Observer { } private void handleSwitchOff() { - if (eipStatus.isConnecting()) { + if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnecting()) { askPendingStartCancellation(); } else if (eipStatus.isConnected()) { askToStopEIP(); diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java index b4be55a4..ee754b32 100644 --- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java @@ -2,15 +2,11 @@ package se.leap.bitmaskclient; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.ServiceConnection; import android.content.SharedPreferences; import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; @@ -26,14 +22,9 @@ import org.json.JSONObject; import java.util.Observable; import java.util.Observer; -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 se.leap.bitmaskclient.drawer.NavigationDrawerFragment; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipStatus; -import se.leap.bitmaskclient.eip.VoidVpnService; import se.leap.bitmaskclient.fragments.LogFragment; import static android.content.Intent.CATEGORY_DEFAULT; @@ -43,9 +34,7 @@ import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE; import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN; import static se.leap.bitmaskclient.Constants.EIP_REQUEST; -import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN; @@ -62,31 +51,15 @@ import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed; import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; -public class MainActivity extends AppCompatActivity implements Observer { +public class MainActivity extends AppCompatActivity { public final static String TAG = MainActivity.class.getSimpleName(); private Provider provider = new Provider(); private SharedPreferences preferences; - private EipStatus eipStatus; private NavigationDrawerFragment navigationDrawerFragment; private MainActivityBroadcastReceiver mainActivityBroadcastReceiver; - private IOpenVPNServiceInternal mService; - private ServiceConnection openVpnConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, - IBinder service) { - mService = IOpenVPNServiceInternal.Stub.asInterface(service); - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - mService = null; - } - - }; - public final static String ACTION_SHOW_VPN_FRAGMENT = "action_show_vpn_fragment"; public final static String ACTION_SHOW_LOG_FRAGMENT = "action_show_log_fragment"; @@ -114,14 +87,12 @@ public class MainActivity extends AppCompatActivity implements Observer { R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout)); - eipStatus = EipStatus.getInstance(); handleIntentAction(getIntent()); } @Override protected void onResume() { super.onResume(); - bindOpenVpnService(); } @Override @@ -205,7 +176,6 @@ public class MainActivity extends AppCompatActivity implements Observer { @Override protected void onPause() { super.onPause(); - unbindService(openVpnConnection); } @Override @@ -215,14 +185,6 @@ public class MainActivity extends AppCompatActivity implements Observer { super.onDestroy(); } - - @Override - public void update(Observable observable, Object data) { - if (observable instanceof EipStatus) { - eipStatus = (EipStatus) observable; - } - } - private void setUpBroadcastReceiver() { IntentFilter updateIntentFilter = new IntentFilter(BROADCAST_EIP_EVENT); updateIntentFilter.addAction(BROADCAST_PROVIDER_API_EVENT); @@ -283,7 +245,6 @@ public class MainActivity extends AppCompatActivity implements Observer { case EIP_ACTION_STOP: switch (resultCode) { case RESULT_OK: - stop(); break; case RESULT_CANCELED: break; @@ -343,39 +304,6 @@ public class MainActivity extends AppCompatActivity implements Observer { } - - private void stop() { - preferences.edit().putBoolean(EIP_RESTART_ON_BOOT, false).apply(); - if (eipStatus.isBlockingVpnEstablished()) { - stopBlockingVpn(); - } - disconnect(); - } - - private void stopBlockingVpn() { - Log.d(TAG, "stop VoidVpn!"); - Intent stopVoidVpnIntent = new Intent(this, VoidVpnService.class); - stopVoidVpnIntent.setAction(EIP_ACTION_STOP_BLOCKING_VPN); - startService(stopVoidVpnIntent); - } - - private void disconnect() { - ProfileManager.setConntectedVpnProfileDisconnected(this); - if (mService != null) { - try { - mService.stopVPN(false); - } catch (RemoteException e) { - VpnStatus.logException(e); - } - } - } - - private void bindOpenVpnService() { - Intent intent = new Intent(this, OpenVPNService.class); - intent.setAction(OpenVPNService.START_SERVICE); - bindService(intent, openVpnConnection, Context.BIND_AUTO_CREATE); - } - private void askUserToLogIn(String userMessage) { Intent intent = new Intent(this, LoginActivity.class); intent.putExtra(PROVIDER_KEY, provider); 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 5cf180d3..0c83c261 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -17,9 +17,13 @@ package se.leap.bitmaskclient.eip; import android.app.IntentService; +import android.content.ComponentName; import android.content.Intent; +import android.content.ServiceConnection; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; import android.os.ResultReceiver; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; @@ -28,13 +32,20 @@ import org.json.JSONException; import org.json.JSONObject; import java.lang.ref.WeakReference; +import java.util.Observable; +import java.util.Observer; import de.blinkt.openvpn.LaunchVPN; +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 se.leap.bitmaskclient.OnBootReceiver; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; import static android.content.Intent.CATEGORY_DEFAULT; +import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK; import static se.leap.bitmaskclient.Constants.BROADCAST_EIP_EVENT; import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE; import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; @@ -43,6 +54,7 @@ import static se.leap.bitmaskclient.Constants.EIP_ACTION_IS_RUNNING; import static se.leap.bitmaskclient.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP; +import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN; import static se.leap.bitmaskclient.Constants.EIP_EARLY_ROUTES; import static se.leap.bitmaskclient.Constants.EIP_RECEIVER; import static se.leap.bitmaskclient.Constants.EIP_REQUEST; @@ -63,7 +75,7 @@ import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; * @author Sean Leonard * @author Parménides GV */ -public final class EIP extends IntentService { +public final class EIP extends IntentService implements Observer{ public final static String TAG = EIP.class.getSimpleName(), SERVICE_API_PATH = "config/eip-service.json", @@ -73,6 +85,27 @@ public final class EIP extends IntentService { private WeakReference mReceiverRef = new WeakReference<>(null); private SharedPreferences preferences; + private EipStatus eipStatus; + private IOpenVPNServiceInternal mService; + private boolean stopEipIfConnectionIsEstablished = false; + + private ServiceConnection openVpnConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, + IBinder service) { + mService = IOpenVPNServiceInternal.Stub.asInterface(service); + if (stopEipIfConnectionIsEstablished) { + stopEipIfConnectionIsEstablished = false; + stopEIP(); + } + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + mService = null; + } + }; + public EIP() { super(TAG); } @@ -80,9 +113,30 @@ public final class EIP extends IntentService { @Override public void onCreate() { super.onCreate(); + eipStatus = EipStatus.getInstance(); + eipStatus.addObserver(this); + Intent intent = new Intent(this, OpenVPNService.class); + intent.setAction(OpenVPNService.START_SERVICE); + bindOpenVpnService(); preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); } + @Override + public void onDestroy() { + super.onDestroy(); + unbindService(openVpnConnection); + eipStatus.deleteObserver(this); + eipStatus = null; + mService = null; + } + + @Override + public void update(Observable observable, Object data) { + if (observable instanceof EipStatus) { + eipStatus = (EipStatus) observable; + } + } + @Override protected void onHandleIntent(Intent intent) { String action = intent.getAction(); @@ -183,22 +237,41 @@ public final class EIP extends IntentService { } private void stopEIP() { - // TODO stop eip from here if possible... - EipStatus eipStatus = EipStatus.getInstance(); + if (mService == null) { + stopEipIfConnectionIsEstablished = true; + return; + } + int resultCode = RESULT_CANCELED; - if (eipStatus.isConnected() || eipStatus.isConnecting()) + if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting()) { + preferences.edit().putBoolean(EIP_RESTART_ON_BOOT, false).apply(); + if (eipStatus.isBlockingVpnEstablished()) { + stopBlockingVpn(); + } + ProfileManager.setConntectedVpnProfileDisconnected(this); + try { + mService.stopVPN(false); + } catch (RemoteException e) { + VpnStatus.logException(e); + } resultCode = RESULT_OK; - + } tellToReceiverOrBroadcast(EIP_ACTION_STOP, resultCode); } + private void stopBlockingVpn() { + Log.d(TAG, "stop VoidVpn!"); + Intent stopVoidVpnIntent = new Intent(this, VoidVpnService.class); + stopVoidVpnIntent.setAction(EIP_ACTION_STOP_BLOCKING_VPN); + startService(stopVoidVpnIntent); + } + /** * Checks the last stored status notified by ics-openvpn * Sends Activity.RESULT_CANCELED to the ResultReceiver that made the * request if it's not connected, Activity.RESULT_OK otherwise. */ private void isRunning() { - EipStatus eipStatus = EipStatus.getInstance(); int resultCode = (eipStatus.isConnected()) ? RESULT_OK : RESULT_CANCELED; @@ -278,4 +351,22 @@ public final class EIP extends IntentService { e.printStackTrace(); } } + + private boolean isOpenVpnRunningWithoutNetwork() { + boolean isRunning = false; + try { + isRunning = eipStatus.getLevel() == LEVEL_NONETWORK && + mService.isVpnRunning(); + } catch (Exception e) { + //eat me + e.printStackTrace(); + } + return isRunning; + } + + private void bindOpenVpnService() { + Intent intent = new Intent(this, OpenVPNService.class); + intent.setAction(OpenVPNService.START_SERVICE); + bindService(intent, openVpnConnection, BIND_AUTO_CREATE); + } } -- cgit v1.2.3 From e5c09ca83bafd5cc8d473793b18c82f649ba02f7 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Tue, 27 Feb 2018 17:57:32 +0100 Subject: Revert "8865 - allow disconnecting without internet" This reverts commit 44322f28b28676a8938f4c1066a75ba47397aa7d. --- .../java/se/leap/bitmaskclient/EipFragment.java | 3 +- .../java/se/leap/bitmaskclient/MainActivity.java | 74 ++++++++++++++- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 103 ++------------------- 3 files changed, 81 insertions(+), 99 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 956cd67e..c4f4dbc9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -37,6 +37,7 @@ 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; @@ -251,7 +252,7 @@ public class EipFragment extends Fragment implements Observer { } private void handleSwitchOff() { - if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnecting()) { + if (eipStatus.isConnecting()) { askPendingStartCancellation(); } else if (eipStatus.isConnected()) { askToStopEIP(); diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java index ee754b32..b4be55a4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java @@ -2,11 +2,15 @@ package se.leap.bitmaskclient; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.ServiceConnection; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; @@ -22,9 +26,14 @@ import org.json.JSONObject; import java.util.Observable; import java.util.Observer; +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 se.leap.bitmaskclient.drawer.NavigationDrawerFragment; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipStatus; +import se.leap.bitmaskclient.eip.VoidVpnService; import se.leap.bitmaskclient.fragments.LogFragment; import static android.content.Intent.CATEGORY_DEFAULT; @@ -34,7 +43,9 @@ import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE; import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP; +import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN; import static se.leap.bitmaskclient.Constants.EIP_REQUEST; +import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN; @@ -51,15 +62,31 @@ import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed; import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; -public class MainActivity extends AppCompatActivity { +public class MainActivity extends AppCompatActivity implements Observer { public final static String TAG = MainActivity.class.getSimpleName(); private Provider provider = new Provider(); private SharedPreferences preferences; + private EipStatus eipStatus; private NavigationDrawerFragment navigationDrawerFragment; private MainActivityBroadcastReceiver mainActivityBroadcastReceiver; + private IOpenVPNServiceInternal mService; + private ServiceConnection openVpnConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, + IBinder service) { + mService = IOpenVPNServiceInternal.Stub.asInterface(service); + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + mService = null; + } + + }; + public final static String ACTION_SHOW_VPN_FRAGMENT = "action_show_vpn_fragment"; public final static String ACTION_SHOW_LOG_FRAGMENT = "action_show_log_fragment"; @@ -87,12 +114,14 @@ public class MainActivity extends AppCompatActivity { R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout)); + eipStatus = EipStatus.getInstance(); handleIntentAction(getIntent()); } @Override protected void onResume() { super.onResume(); + bindOpenVpnService(); } @Override @@ -176,6 +205,7 @@ public class MainActivity extends AppCompatActivity { @Override protected void onPause() { super.onPause(); + unbindService(openVpnConnection); } @Override @@ -185,6 +215,14 @@ public class MainActivity extends AppCompatActivity { super.onDestroy(); } + + @Override + public void update(Observable observable, Object data) { + if (observable instanceof EipStatus) { + eipStatus = (EipStatus) observable; + } + } + private void setUpBroadcastReceiver() { IntentFilter updateIntentFilter = new IntentFilter(BROADCAST_EIP_EVENT); updateIntentFilter.addAction(BROADCAST_PROVIDER_API_EVENT); @@ -245,6 +283,7 @@ public class MainActivity extends AppCompatActivity { case EIP_ACTION_STOP: switch (resultCode) { case RESULT_OK: + stop(); break; case RESULT_CANCELED: break; @@ -304,6 +343,39 @@ public class MainActivity extends AppCompatActivity { } + + private void stop() { + preferences.edit().putBoolean(EIP_RESTART_ON_BOOT, false).apply(); + if (eipStatus.isBlockingVpnEstablished()) { + stopBlockingVpn(); + } + disconnect(); + } + + private void stopBlockingVpn() { + Log.d(TAG, "stop VoidVpn!"); + Intent stopVoidVpnIntent = new Intent(this, VoidVpnService.class); + stopVoidVpnIntent.setAction(EIP_ACTION_STOP_BLOCKING_VPN); + startService(stopVoidVpnIntent); + } + + private void disconnect() { + ProfileManager.setConntectedVpnProfileDisconnected(this); + if (mService != null) { + try { + mService.stopVPN(false); + } catch (RemoteException e) { + VpnStatus.logException(e); + } + } + } + + private void bindOpenVpnService() { + Intent intent = new Intent(this, OpenVPNService.class); + intent.setAction(OpenVPNService.START_SERVICE); + bindService(intent, openVpnConnection, Context.BIND_AUTO_CREATE); + } + private void askUserToLogIn(String userMessage) { Intent intent = new Intent(this, LoginActivity.class); intent.putExtra(PROVIDER_KEY, provider); 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 0c83c261..5cf180d3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -17,13 +17,9 @@ package se.leap.bitmaskclient.eip; import android.app.IntentService; -import android.content.ComponentName; import android.content.Intent; -import android.content.ServiceConnection; import android.content.SharedPreferences; import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; import android.os.ResultReceiver; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; @@ -32,20 +28,13 @@ import org.json.JSONException; import org.json.JSONObject; import java.lang.ref.WeakReference; -import java.util.Observable; -import java.util.Observer; import de.blinkt.openvpn.LaunchVPN; -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 se.leap.bitmaskclient.OnBootReceiver; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; import static android.content.Intent.CATEGORY_DEFAULT; -import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK; import static se.leap.bitmaskclient.Constants.BROADCAST_EIP_EVENT; import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE; import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; @@ -54,7 +43,6 @@ import static se.leap.bitmaskclient.Constants.EIP_ACTION_IS_RUNNING; import static se.leap.bitmaskclient.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN; import static se.leap.bitmaskclient.Constants.EIP_EARLY_ROUTES; import static se.leap.bitmaskclient.Constants.EIP_RECEIVER; import static se.leap.bitmaskclient.Constants.EIP_REQUEST; @@ -75,7 +63,7 @@ import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; * @author Sean Leonard * @author Parménides GV */ -public final class EIP extends IntentService implements Observer{ +public final class EIP extends IntentService { public final static String TAG = EIP.class.getSimpleName(), SERVICE_API_PATH = "config/eip-service.json", @@ -85,27 +73,6 @@ public final class EIP extends IntentService implements Observer{ private WeakReference mReceiverRef = new WeakReference<>(null); private SharedPreferences preferences; - private EipStatus eipStatus; - private IOpenVPNServiceInternal mService; - private boolean stopEipIfConnectionIsEstablished = false; - - private ServiceConnection openVpnConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, - IBinder service) { - mService = IOpenVPNServiceInternal.Stub.asInterface(service); - if (stopEipIfConnectionIsEstablished) { - stopEipIfConnectionIsEstablished = false; - stopEIP(); - } - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - mService = null; - } - }; - public EIP() { super(TAG); } @@ -113,30 +80,9 @@ public final class EIP extends IntentService implements Observer{ @Override public void onCreate() { super.onCreate(); - eipStatus = EipStatus.getInstance(); - eipStatus.addObserver(this); - Intent intent = new Intent(this, OpenVPNService.class); - intent.setAction(OpenVPNService.START_SERVICE); - bindOpenVpnService(); preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); } - @Override - public void onDestroy() { - super.onDestroy(); - unbindService(openVpnConnection); - eipStatus.deleteObserver(this); - eipStatus = null; - mService = null; - } - - @Override - public void update(Observable observable, Object data) { - if (observable instanceof EipStatus) { - eipStatus = (EipStatus) observable; - } - } - @Override protected void onHandleIntent(Intent intent) { String action = intent.getAction(); @@ -237,33 +183,13 @@ public final class EIP extends IntentService implements Observer{ } private void stopEIP() { - if (mService == null) { - stopEipIfConnectionIsEstablished = true; - return; - } - + // TODO stop eip from here if possible... + EipStatus eipStatus = EipStatus.getInstance(); int resultCode = RESULT_CANCELED; - if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting()) { - preferences.edit().putBoolean(EIP_RESTART_ON_BOOT, false).apply(); - if (eipStatus.isBlockingVpnEstablished()) { - stopBlockingVpn(); - } - ProfileManager.setConntectedVpnProfileDisconnected(this); - try { - mService.stopVPN(false); - } catch (RemoteException e) { - VpnStatus.logException(e); - } + if (eipStatus.isConnected() || eipStatus.isConnecting()) resultCode = RESULT_OK; - } - tellToReceiverOrBroadcast(EIP_ACTION_STOP, resultCode); - } - private void stopBlockingVpn() { - Log.d(TAG, "stop VoidVpn!"); - Intent stopVoidVpnIntent = new Intent(this, VoidVpnService.class); - stopVoidVpnIntent.setAction(EIP_ACTION_STOP_BLOCKING_VPN); - startService(stopVoidVpnIntent); + tellToReceiverOrBroadcast(EIP_ACTION_STOP, resultCode); } /** @@ -272,6 +198,7 @@ public final class EIP extends IntentService implements Observer{ * request if it's not connected, Activity.RESULT_OK otherwise. */ private void isRunning() { + EipStatus eipStatus = EipStatus.getInstance(); int resultCode = (eipStatus.isConnected()) ? RESULT_OK : RESULT_CANCELED; @@ -351,22 +278,4 @@ public final class EIP extends IntentService implements Observer{ e.printStackTrace(); } } - - private boolean isOpenVpnRunningWithoutNetwork() { - boolean isRunning = false; - try { - isRunning = eipStatus.getLevel() == LEVEL_NONETWORK && - mService.isVpnRunning(); - } catch (Exception e) { - //eat me - e.printStackTrace(); - } - return isRunning; - } - - private void bindOpenVpnService() { - Intent intent = new Intent(this, OpenVPNService.class); - intent.setAction(OpenVPNService.START_SERVICE); - bindService(intent, openVpnConnection, BIND_AUTO_CREATE); - } } -- cgit v1.2.3 From 8a08d44facafd405e89e22b84dd82dfa3e85923c Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Tue, 27 Feb 2018 18:12:21 +0100 Subject: 8865 - allow disconnect without connection * revert last commit * dirty fix to disconnect - see #8876 * add padding in EipFragment --- .../main/java/se/leap/bitmaskclient/EipFragment.java | 17 +++++++++++++++++ app/src/main/java/se/leap/bitmaskclient/eip/EIP.java | 1 + 2 files changed, 18 insertions(+) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index c4f4dbc9..1a6ad8d2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -29,6 +29,7 @@ import android.os.Bundle; import android.os.IBinder; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; +import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AlertDialog; import android.support.v7.widget.AppCompatImageView; import android.support.v7.widget.AppCompatTextView; @@ -56,6 +57,11 @@ import se.leap.bitmaskclient.views.VpnStateImage; 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.BROADCAST_EIP_EVENT; +import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE; +import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; +import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP; +import static se.leap.bitmaskclient.Constants.EIP_REQUEST; import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN; @@ -256,6 +262,17 @@ public class EipFragment extends Fragment implements Observer { askPendingStartCancellation(); } else if (eipStatus.isConnected()) { askToStopEIP(); + } else if (isOpenVpnRunningWithoutNetwork()) { + // TODO move to EIP + // TODO see stopEIP function + Bundle resultData = new Bundle(); + resultData.putString(EIP_REQUEST, EIP_ACTION_STOP); + Intent intentUpdate = new Intent(BROADCAST_EIP_EVENT); + intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); + intentUpdate.putExtra(BROADCAST_RESULT_CODE, Activity.RESULT_OK); + intentUpdate.putExtra(BROADCAST_RESULT_KEY, resultData); + Log.d(TAG, "sending broadcast"); + LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intentUpdate); } } 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 5cf180d3..665e0ebd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -184,6 +184,7 @@ public final class EIP extends IntentService { private void stopEIP() { // TODO stop eip from here if possible... + // TODO then refactor EipFragment.handleSwitchOff EipStatus eipStatus = EipStatus.getInstance(); int resultCode = RESULT_CANCELED; if (eipStatus.isConnected() || eipStatus.isConnecting()) -- cgit v1.2.3 From 9787e857bca4dca056d9e55cc9c8eaa1756eb990 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Tue, 27 Feb 2018 19:04:18 +0100 Subject: 8865 - disconnect without internet * move function to dialog --- .../java/se/leap/bitmaskclient/EipFragment.java | 28 ++++++++++++---------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'app/src/main/java/se/leap') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 1a6ad8d2..cb98aaac 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -258,21 +258,10 @@ public class EipFragment extends Fragment implements Observer { } private void handleSwitchOff() { - if (eipStatus.isConnecting()) { + if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnecting()) { askPendingStartCancellation(); } else if (eipStatus.isConnected()) { askToStopEIP(); - } else if (isOpenVpnRunningWithoutNetwork()) { - // TODO move to EIP - // TODO see stopEIP function - Bundle resultData = new Bundle(); - resultData.putString(EIP_REQUEST, EIP_ACTION_STOP); - Intent intentUpdate = new Intent(BROADCAST_EIP_EVENT); - intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); - intentUpdate.putExtra(BROADCAST_RESULT_CODE, Activity.RESULT_OK); - intentUpdate.putExtra(BROADCAST_RESULT_KEY, resultData); - Log.d(TAG, "sending broadcast"); - LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intentUpdate); } } @@ -293,7 +282,20 @@ public class EipFragment extends Fragment implements Observer { protected void stopEipIfPossible() { Context context = getContext(); if (context != null) { - EipCommand.stopVPN(getContext()); + if (isOpenVpnRunningWithoutNetwork()) { + // TODO move to EIP + // TODO see stopEIP function + Bundle resultData = new Bundle(); + resultData.putString(EIP_REQUEST, EIP_ACTION_STOP); + Intent intentUpdate = new Intent(BROADCAST_EIP_EVENT); + intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); + intentUpdate.putExtra(BROADCAST_RESULT_CODE, Activity.RESULT_OK); + intentUpdate.putExtra(BROADCAST_RESULT_KEY, resultData); + Log.d(TAG, "sending broadcast"); + LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intentUpdate); + } else { + EipCommand.stopVPN(getContext()); + } } else { Log.e(TAG, "context is null when trying to stop EIP"); } -- cgit v1.2.3