summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2018-01-28 10:17:12 +0100
committercyBerta <cyberta@riseup.net>2018-01-28 10:17:12 +0100
commit298c33b94c8aada449c98a24cdb2c687af40cbbd (patch)
treec27c162be2fff26538eba1d6ba4db67ed5c4fd9a /app
parent986fe144729b58382641bbf9769a93bf81c06514 (diff)
parent3bb2c2c219359a6016366c4d3533a5e2ef812ea9 (diff)
Merge branch 'origin_0.9.8' into fupduck_8819_config_wizard_design
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle1
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/test/TestEipFragment.java (renamed from app/src/androidTest/java/se/leap/bitmaskclient/test/TestVpnFragment.java)2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Dashboard.java16
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipFragment.java (renamed from app/src/main/java/se/leap/bitmaskclient/VpnFragment.java)107
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/MainActivity.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EIP.java48
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java127
-rw-r--r--app/src/main/res/drawable/black_circle.xml9
-rw-r--r--app/src/main/res/drawable/vpn_connected.xml20
-rw-r--r--app/src/main/res/drawable/vpn_connecting.xml25
-rw-r--r--app/src/main/res/drawable/vpn_disconnected.xml28
-rw-r--r--app/src/main/res/layout/eip_service_fragment.xml178
-rw-r--r--app/src/main/res/values-v21/styles.xml6
-rw-r--r--app/src/main/res/values/colors.xml4
-rw-r--r--app/src/main/res/values/strings.xml1
-rw-r--r--app/src/main/res/values/styles.xml7
19 files changed, 423 insertions, 172 deletions
diff --git a/app/build.gradle b/app/build.gradle
index b28d9f35..2e6604f2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -93,6 +93,7 @@ dependencies {
compile 'com.android.support:appcompat-v7:26.1.0'
compile 'com.android.support:design:26.1.0'
compile 'com.android.support:support-fragment:26.1.0'
+ compile 'com.android.support.constraint:constraint-layout:1.0.2'
}
// Ensure the no-op dependency is always used in JVM tests.
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/TestVpnFragment.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/TestEipFragment.java
index 564e251c..4227f19a 100644
--- a/app/src/androidTest/java/se/leap/bitmaskclient/test/TestVpnFragment.java
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/TestEipFragment.java
@@ -1,6 +1,6 @@
package se.leap.bitmaskclient.test;
-public class TestVpnFragment extends BaseTestDashboardFragment {
+public class TestEipFragment extends BaseTestDashboardFragment {
/**
* This test will fail if Android does not trust VPN connection.
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index 3713e198..741a6f56 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -304,6 +304,8 @@ public class ConfigHelper {
} catch (JSONException e2) {
return null;
}
+ } catch (NullPointerException npe) {
+ return null;
}
}
@@ -322,7 +324,7 @@ public class ConfigHelper {
try {
JSONObject providerJson = new JSONObject(provider);
return providerJson.getString(Provider.DOMAIN);
- } catch (JSONException e) {
+ } catch (JSONException | NullPointerException e) {
return null;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index cb781009..a4db5f84 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -87,7 +87,7 @@ public class Dashboard extends ButterKnifeActivity {
@InjectView(R.id.providerName)
TextView provider_name;
- private VpnFragment eip_fragment;
+ private EipFragment eip_fragment;
private UserStatusFragment user_status_fragment;
private static Provider provider = new Provider();
@@ -290,8 +290,8 @@ public class Dashboard extends ButterKnifeActivity {
* Inflates permanent UI elements of the View and contains logic for what
* service dependent UI elements to include.
*/
- //TODO: REFACTOR ME! Consider implementing a manager that handles most of VpnFragment's logic about handling EIP commands.
- //This way, we could avoid to create UI elements (like fragmentManager.replace(R.id.servicesCollection, eip_fragment, VpnFragment.TAG); )
+ //TODO: REFACTOR ME! Consider implementing a manager that handles most of EipFragment's logic about handling EIP commands.
+ //This way, we could avoid to create UI elements (like fragmentManager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG); )
// just to start services and destroy them afterwards
private void buildDashboard(boolean hideAndTurnOnEipOnBoot) {
setContentView(R.layout.dashboard);
@@ -305,9 +305,9 @@ public class Dashboard extends ButterKnifeActivity {
fragment_manager.replace(R.id.user_status_fragment, user_status_fragment, UserStatusFragment.TAG);
if (provider.hasEIP()) {
- fragment_manager.removePreviousFragment(VpnFragment.TAG);
+ fragment_manager.removePreviousFragment(EipFragment.TAG);
eip_fragment = prepareEipFragment(hideAndTurnOnEipOnBoot);
- fragment_manager.replace(R.id.servicesCollection, eip_fragment, VpnFragment.TAG);
+ fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG);
if (hideAndTurnOnEipOnBoot) {
onBackPressed();
}
@@ -320,13 +320,13 @@ public class Dashboard extends ButterKnifeActivity {
* has caused to start Dashboard
* @return the created VPNFragment
*/
- public VpnFragment prepareEipFragment(boolean hideAndTurnOnEipOnBoot) {
- VpnFragment eip_fragment = new VpnFragment();
+ public EipFragment prepareEipFragment(boolean hideAndTurnOnEipOnBoot) {
+ EipFragment eip_fragment = new EipFragment();
if (hideAndTurnOnEipOnBoot && !isAlwaysOn()) {
preferences.edit().remove(EIP_RESTART_ON_BOOT).apply();
Bundle arguments = new Bundle();
- arguments.putBoolean(VpnFragment.START_EIP_ON_BOOT, true);
+ arguments.putBoolean(EipFragment.START_EIP_ON_BOOT, true);
Log.d(TAG, "set START_EIP_ON_BOOT argument for eip_fragment");
eip_fragment.setArguments(arguments);
diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
index f1463029..414b1f2a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
@@ -24,17 +24,21 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.support.v4.app.Fragment;
+import android.support.v7.widget.AppCompatImageView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.TextView;
import java.util.Observable;
import java.util.Observer;
@@ -46,11 +50,12 @@ import de.blinkt.openvpn.core.IOpenVPNServiceInternal;
import de.blinkt.openvpn.core.OpenVPNService;
import de.blinkt.openvpn.core.ProfileManager;
import de.blinkt.openvpn.core.VpnStatus;
-import mbanje.kurt.fabbutton.FabButton;
import se.leap.bitmaskclient.eip.EIP;
import se.leap.bitmaskclient.eip.EipStatus;
import se.leap.bitmaskclient.eip.VoidVpnService;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
@@ -66,23 +71,35 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
-public class VpnFragment extends Fragment implements Observer {
+public class EipFragment extends Fragment implements Observer {
- public static String TAG = VpnFragment.class.getSimpleName();
+ public static String TAG = EipFragment.class.getSimpleName();
- public static final String IS_PENDING = TAG + ".is_pending";
protected static final String IS_CONNECTED = TAG + ".is_connected";
public static final String START_EIP_ON_BOOT = "start on boot";
private SharedPreferences preferences;
- @InjectView(R.id.vpn_status_image)
- FabButton vpnStatusImage;
+ @InjectView(R.id.background)
+ AppCompatImageView background;
+
+ @InjectView(R.id.key)
+ AppCompatImageView key;
+
+ @InjectView(R.id.cirle)
+ AppCompatImageView circle;
+
@InjectView(R.id.vpn_main_button)
Button mainButton;
- private static EIPReceiver eipReceiver;
- private static EipStatus eipStatus;
+ @InjectView(R.id.routed_text)
+ TextView routedText;
+
+ @InjectView(R.id.vpn_route)
+ TextView vpnRoute;
+
+ private EIPReceiver eipReceiver;
+ private EipStatus eipStatus;
private boolean wantsToConnect;
private IOpenVPNServiceInternal mService;
@@ -156,6 +173,20 @@ public class VpnFragment extends Fragment implements Observer {
}
@OnClick(R.id.vpn_main_button)
+ void onButtonClick() {
+ handleIcon();
+ }
+
+ @OnClick(R.id.key)
+ void onKeyClick() {
+ handleIcon();
+ }
+
+ @OnClick(R.id.cirle)
+ void onCircleClick() {
+ handleIcon();
+ }
+
void handleIcon() {
if (eipStatus.isConnected() || eipStatus.isConnecting())
handleSwitchOff();
@@ -194,8 +225,6 @@ public class VpnFragment extends Fragment implements Observer {
askPendingStartCancellation();
} else if (eipStatus.isConnected()) {
askToStopEIP();
- } else {
- updateIcon();
}
}
@@ -313,44 +342,32 @@ public class VpnFragment extends Fragment implements Observer {
}
});
} else {
- Log.e("VpnFragment", "activity is null");
+ Log.e("EipFragment", "activity is null");
}
}
}
private void handleNewState() {
- updateIcon();
- updateButton();
- }
-
- private void updateIcon() {
- if (eipStatus.isBlocking()) {
- vpnStatusImage.showProgress(false);
- vpnStatusImage.setIcon(R.drawable.ic_stat_vpn_blocking, R.drawable.ic_stat_vpn_blocking);
- vpnStatusImage.setTag(R.drawable.ic_stat_vpn_blocking);
- } else if (eipStatus.isConnecting()) {
- vpnStatusImage.showProgress(true);
- vpnStatusImage.setIcon(R.drawable.ic_stat_vpn_empty_halo, R.drawable.ic_stat_vpn_empty_halo);
- vpnStatusImage.setTag(R.drawable.ic_stat_vpn_empty_halo);
- } else if (eipStatus.isConnected()){
- vpnStatusImage.showProgress(false);
- vpnStatusImage.setIcon(R.drawable.ic_stat_vpn, R.drawable.ic_stat_vpn);
- vpnStatusImage.setTag(R.drawable.ic_stat_vpn);
- } else {
- vpnStatusImage.setIcon(R.drawable.ic_stat_vpn_offline, R.drawable.ic_stat_vpn_offline);
- vpnStatusImage.setTag(R.drawable.ic_stat_vpn_offline);
- vpnStatusImage.showProgress(false);
- }
- }
-
- private void updateButton() {
Activity activity = getActivity();
if (eipStatus.isConnecting()) {
mainButton.setText(activity.getString(android.R.string.cancel));
+ key.setImageResource(R.drawable.vpn_connecting);
+ routedText.setVisibility(GONE);
+ vpnRoute.setVisibility(GONE);
+ colorBackgroundALittle();
} else if (eipStatus.isConnected() || isOpenVpnRunningWithoutNetwork()) {
mainButton.setText(activity.getString(R.string.vpn_button_turn_off));
+ key.setImageResource(R.drawable.vpn_connected);
+ routedText.setVisibility(VISIBLE);
+ vpnRoute.setVisibility(VISIBLE);
+ vpnRoute.setText(ConfigHelper.getProviderName(preferences));
+ colorBackground();
} else {
mainButton.setText(activity.getString(R.string.vpn_button_turn_on));
+ key.setImageResource(R.drawable.vpn_disconnected);
+ routedText.setVisibility(GONE);
+ vpnRoute.setVisibility(GONE);
+ greyscaleBackground();
}
}
@@ -439,8 +456,22 @@ public class VpnFragment extends Fragment implements Observer {
}
}
+ private void greyscaleBackground() {
+ ColorMatrix matrix = new ColorMatrix();
+ matrix.setSaturation(0);
+ ColorMatrixColorFilter cf = new ColorMatrixColorFilter(matrix);
+ background.setColorFilter(cf);
+ background.setImageAlpha(255);
+ }
- public static EIPReceiver getReceiver() {
- return eipReceiver;
+ private void colorBackgroundALittle() {
+ background.setColorFilter(null);
+ background.setImageAlpha(144);
}
+
+ private void colorBackground() {
+ background.setColorFilter(null);
+ background.setImageAlpha(255);
+ }
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
index f4e2ac5f..7629f0b7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
@@ -74,7 +74,7 @@ public class MainActivity extends AppCompatActivity {
switch (intent.getAction()) {
case ACTION_SHOW_VPN_FRAGMENT:
- fragment = new VpnFragment();
+ fragment = new EipFragment();
break;
default:
break;
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
index f60b5cc7..2b0c72db 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
@@ -451,6 +451,12 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
String providerName = ConfigHelper.getProviderName(handledProvider);
String providerDomain = ConfigHelper.getProviderDomain(handledProvider);
+ //FIXME: remove that lines as soon as Provider gets sent via broadcast
+ if (resultCode == PROVIDER_OK && handledProvider == null) {
+ providerName = ConfigHelper.getProviderName(preferences);
+ providerDomain = ConfigHelper.getProviderDomain(preferences);
+ }
+
if (providerName != null && providerName.equalsIgnoreCase(provider.getName()) &&
providerDomain != null &&
providerDomain.equalsIgnoreCase(provider.getDomain())) {
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 ebfb3ba7..090e8d26 100644
--- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
@@ -28,8 +28,8 @@ import android.widget.Toast;
import se.leap.bitmaskclient.ConfigHelper;
import se.leap.bitmaskclient.ProviderListActivity;
+import se.leap.bitmaskclient.EipFragment;
import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.VpnFragment;
import se.leap.bitmaskclient.fragments.AboutFragment;
import se.leap.bitmaskclient.fragments.LogFragment;
@@ -296,7 +296,7 @@ public class NavigationDrawerFragment extends Fragment {
if (parent == mDrawerAccountsListView) {
mTitle = getString(R.string.vpn_fragment_title);
- fragment = new VpnFragment();
+ fragment = new EipFragment();
} else {
Log.d("Drawer", String.format("Selected position %d", position));
switch (position) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
index a2ac9d66..eca5b881 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
@@ -18,7 +18,6 @@ package se.leap.bitmaskclient.eip;
import android.app.Activity;
import android.app.IntentService;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
@@ -30,7 +29,6 @@ import org.json.JSONObject;
import de.blinkt.openvpn.LaunchVPN;
import se.leap.bitmaskclient.OnBootReceiver;
-import se.leap.bitmaskclient.VpnFragment;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_IS_RUNNING;
@@ -59,12 +57,11 @@ public final class EIP extends IntentService {
public final static String TAG = EIP.class.getSimpleName();
public final static String SERVICE_API_PATH = "config/eip-service.json";
- private static Context context;
private static ResultReceiver mReceiver;
private static SharedPreferences preferences;
private static JSONObject eipDefinition;
- private static GatewaysManager gatewaysManager = new GatewaysManager();
+ private GatewaysManager gatewaysManager = new GatewaysManager();
private static Gateway gateway;
public EIP() {
@@ -74,7 +71,6 @@ public final class EIP extends IntentService {
@Override
public void onCreate() {
super.onCreate();
- context = getApplicationContext();
preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
eipDefinition = eipDefinitionFromPreferences();
if (gatewaysManager.isEmpty())
@@ -86,18 +82,30 @@ public final class EIP extends IntentService {
String action = intent.getAction();
mReceiver = intent.getParcelableExtra(EIP_RECEIVER);
- if (action.equals(EIP_ACTION_START))
- startEIP();
- else if (action.equals(EIP_ACTION_START_ALWAYS_ON_EIP))
- startAlwaysOnEIP();
- else if (action.equals(EIP_ACTION_STOP))
- stopEIP();
- else if (action.equals(EIP_ACTION_IS_RUNNING))
- isRunning();
- else if (action.equals(EIP_ACTION_UPDATE))
- updateEIPService();
- else if (action.equals(EIP_ACTION_CHECK_CERT_VALIDITY))
- checkCertValidity();
+ if (action == null) {
+ return;
+ }
+
+ switch (action) {
+ case EIP_ACTION_START:
+ startEIP();
+ break;
+ case EIP_ACTION_START_ALWAYS_ON_EIP:
+ startAlwaysOnEIP();
+ break;
+ case EIP_ACTION_STOP:
+ stopEIP();
+ break;
+ case EIP_ACTION_IS_RUNNING:
+ isRunning();
+ break;
+ case EIP_ACTION_UPDATE:
+ updateEIPService();
+ break;
+ case EIP_ACTION_CHECK_CERT_VALIDITY:
+ checkCertValidity();
+ break;
+ }
}
/**
@@ -114,7 +122,6 @@ public final class EIP extends IntentService {
gateway = gatewaysManager.select();
if (gateway != null && gateway.getProfile() != null) {
- mReceiver = VpnFragment.getReceiver();
launchActiveGateway();
tellToReceiver(EIP_ACTION_START, Activity.RESULT_OK);
} else
@@ -134,7 +141,6 @@ public final class EIP extends IntentService {
gateway = gatewaysManager.select();
if (gateway != null && gateway.getProfile() != null) {
- //mReceiver = VpnFragment.getReceiver();
Log.d(TAG, "startAlwaysOnEIP eip launch avtive gateway vpn");
launchActiveGateway();
} else {
@@ -147,7 +153,7 @@ public final class EIP extends IntentService {
* VpnService is started properly.
*/
private void earlyRoutes() {
- Intent voidVpnLauncher = new Intent(context, VoidVpnLauncher.class);
+ Intent voidVpnLauncher = new Intent(getApplicationContext(), VoidVpnLauncher.class);
voidVpnLauncher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(voidVpnLauncher);
}
@@ -216,7 +222,7 @@ public final class EIP extends IntentService {
private void gatewaysFromPreferences() {
String gatewaysString = preferences.getString(Gateway.TAG, "");
- gatewaysManager = new GatewaysManager(context, preferences);
+ gatewaysManager = new GatewaysManager(this, preferences);
gatewaysManager.addFromString(gatewaysString);
preferences.edit().remove(Gateway.TAG).apply();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
index ddf152d2..0da74872 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
@@ -16,13 +16,15 @@
*/
package se.leap.bitmaskclient.eip;
-import android.content.*;
+import android.content.Context;
import android.os.AsyncTask;
import android.support.annotation.VisibleForTesting;
-import java.util.*;
+import java.util.Observable;
-import de.blinkt.openvpn.core.*;
+import de.blinkt.openvpn.core.ConnectionStatus;
+import de.blinkt.openvpn.core.LogItem;
+import de.blinkt.openvpn.core.VpnStatus;
/**
* EipStatus is a Singleton that represents a reduced set of a vpn's ConnectionStatus.
@@ -31,7 +33,7 @@ import de.blinkt.openvpn.core.*;
*/
public class EipStatus extends Observable implements VpnStatus.StateListener {
public static String TAG = EipStatus.class.getSimpleName();
- private static EipStatus current_status;
+ private static EipStatus currentStatus;
public enum EipLevel {
CONNECTING,
DISCONNECTING,
@@ -42,23 +44,23 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
/**
- * vpn_level holds the connection status of the openvpn vpn and the traffic blocking
+ * vpnLevel holds the connection status of the openvpn vpn and the traffic blocking
* void vpn. LEVEL_BLOCKING is set when the latter vpn is up. All other states are set by
* openvpn.
*/
- private ConnectionStatus vpn_level = ConnectionStatus.LEVEL_NOTCONNECTED;
- private static EipLevel current_eip_level = EipLevel.DISCONNECTED;
+ private ConnectionStatus vpnLevel = ConnectionStatus.LEVEL_NOTCONNECTED;
+ private static EipLevel currentEipLevel = EipLevel.DISCONNECTED;
- int last_error_line = 0;
- private String state, log_message;
- private int localized_res_id;
+ private int lastErrorLine = 0;
+ private String state, logMessage;
+ private int localizedResId;
public static EipStatus getInstance() {
- if (current_status == null) {
- current_status = new EipStatus();
- VpnStatus.addStateListener(current_status);
+ if (currentStatus == null) {
+ currentStatus = new EipStatus();
+ VpnStatus.addStateListener(currentStatus);
}
- return current_status;
+ return currentStatus;
}
private EipStatus() {
@@ -66,16 +68,16 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
@Override
public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
- ConnectionStatus tmp = current_status.getLevel();
- current_status = getInstance();
- current_status.setState(state);
- current_status.setLogMessage(logmessage);
- current_status.setLocalizedResId(localizedResId);
- current_status.setLevel(level);
- current_status.setEipLevel(level);
- if (tmp != current_status.getLevel()) {
- current_status.setChanged();
- current_status.notifyObservers();
+ ConnectionStatus tmp = currentStatus.getLevel();
+ currentStatus = getInstance();
+ currentStatus.setState(state);
+ currentStatus.setLogMessage(logmessage);
+ currentStatus.setLocalizedResId(localizedResId);
+ currentStatus.setLevel(level);
+ currentStatus.setEipLevel(level);
+ if (tmp != currentStatus.getLevel()) {
+ currentStatus.setChanged();
+ currentStatus.notifyObservers();
}
}
@@ -87,7 +89,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
private void setEipLevel(ConnectionStatus level) {
switch (level) {
case LEVEL_CONNECTED:
- current_eip_level = EipLevel.CONNECTED;
+ currentEipLevel = EipLevel.CONNECTED;
break;
case LEVEL_VPNPAUSED:
throw new IllegalStateException("Ics-Openvpn's VPNPAUSED state is not supported by Bitmask");
@@ -95,25 +97,25 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
case LEVEL_CONNECTING_NO_SERVER_REPLY_YET:
case LEVEL_WAITING_FOR_USER_INPUT:
case LEVEL_START:
- current_eip_level = EipLevel.CONNECTING;
+ currentEipLevel = EipLevel.CONNECTING;
break;
case LEVEL_AUTH_FAILED:
case LEVEL_NOTCONNECTED:
- current_eip_level = EipLevel.DISCONNECTED;
+ currentEipLevel = EipLevel.DISCONNECTED;
break;
case LEVEL_NONETWORK:
case LEVEL_BLOCKING:
setEipLevelWithDelay(level);
break;
case UNKNOWN_LEVEL:
- current_eip_level = EipLevel.UNKNOWN; //??
+ currentEipLevel = EipLevel.UNKNOWN; //??
break;
}
}
@VisibleForTesting
EipLevel getEipLevel() {
- return current_eip_level;
+ return currentEipLevel;
}
/**
@@ -123,7 +125,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
* @param futureLevel
*/
private void setEipLevelWithDelay(ConnectionStatus futureLevel) {
- new DelayTask(current_status.getLevel(), futureLevel).execute();
+ new DelayTask(currentStatus.getLevel(), futureLevel).execute();
}
private static class DelayTask extends AsyncTask<Void, Void, Void> {
@@ -131,7 +133,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
private final ConnectionStatus currentLevel;
private final ConnectionStatus futureLevel;
- public DelayTask(ConnectionStatus currentLevel, ConnectionStatus futureLevel) {
+ DelayTask(ConnectionStatus currentLevel, ConnectionStatus futureLevel) {
this.currentLevel = currentLevel;
this.futureLevel = futureLevel;
}
@@ -144,38 +146,38 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
return null;
}
- protected void onPostExecute(Void result) {;
- if (currentLevel == current_status.getLevel()) {
+ protected void onPostExecute(Void result) {
+ if (currentLevel == currentStatus.getLevel()) {
switch (futureLevel) {
case LEVEL_NONETWORK:
- current_eip_level = EipLevel.DISCONNECTED;
+ currentEipLevel = EipLevel.DISCONNECTED;
break;
case LEVEL_BLOCKING:
- current_eip_level = EipLevel.BLOCKING;
+ currentEipLevel = EipLevel.BLOCKING;
break;
default:
break;
}
- current_status.setChanged();
- current_status.notifyObservers();
+ currentStatus.setChanged();
+ currentStatus.notifyObservers();
}
}
}
public boolean isConnecting() {
- return current_eip_level == EipLevel.CONNECTING;
+ return currentEipLevel == EipLevel.CONNECTING;
}
public boolean isConnected() {
- return current_eip_level == EipLevel.CONNECTED;
+ return currentEipLevel == EipLevel.CONNECTED;
}
/**
- * @return true if current_eip_level is for at least a second {@link EipLevel#BLOCKING}.
+ * @return true if currentEipLevel is for at least a second {@link EipLevel#BLOCKING}.
* See {@link #setEipLevelWithDelay(ConnectionStatus)}.
*/
public boolean isBlocking() {
- return current_eip_level == EipLevel.BLOCKING;
+ return currentEipLevel == EipLevel.BLOCKING;
}
/**
@@ -183,20 +185,20 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
* @return true immediately after traffic blocking VoidVpn was established.
*/
public boolean isBlockingVpnEstablished() {
- return vpn_level == ConnectionStatus.LEVEL_BLOCKING;
+ return vpnLevel == ConnectionStatus.LEVEL_BLOCKING;
}
public boolean isDisconnected() {
- return current_eip_level == EipLevel.DISCONNECTED;
+ return currentEipLevel == EipLevel.DISCONNECTED;
}
/**
* ics-openvpn's paused state is not implemented yet
- * @return
+ * @return true if vpn is paused false if not
*/
@Deprecated
public boolean isPaused() {
- return vpn_level == ConnectionStatus.LEVEL_VPNPAUSED;
+ return vpnLevel == ConnectionStatus.LEVEL_VPNPAUSED;
}
public String getState() {
@@ -204,15 +206,15 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
public String getLogMessage() {
- return log_message;
+ return logMessage;
}
- public int getLocalizedResId() {
- return localized_res_id;
+ int getLocalizedResId() {
+ return localizedResId;
}
public ConnectionStatus getLevel() {
- return vpn_level;
+ return vpnLevel;
}
private void setState(String state) {
@@ -220,39 +222,40 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
private void setLogMessage(String log_message) {
- this.log_message = log_message;
+ this.logMessage = log_message;
}
private void setLocalizedResId(int localized_res_id) {
- this.localized_res_id = localized_res_id;
+ this.localizedResId = localized_res_id;
}
private void setLevel(ConnectionStatus level) {
- this.vpn_level = level;
+ this.vpnLevel = level;
}
public boolean errorInLast(int lines, Context context) {
return !lastError(lines, context).isEmpty();
}
- public String lastError(int lines, Context context) {
+ private String lastError(int lines, Context context) {
String error = "";
String[] error_keywords = {"error", "ERROR", "fatal", "FATAL"};
LogItem[] log = VpnStatus.getlogbuffer();
- if(log.length < last_error_line)
- last_error_line = 0;
- String message = "";
+ if(log.length < lastErrorLine)
+ lastErrorLine = 0;
+ String message;
for (int i = 1; i <= lines && log.length > i; i++) {
int line = log.length - i;
- LogItem log_item = log[line];
- message = log_item.getString(context);
- for (int j = 0; j < error_keywords.length; j++)
- if (message.contains(error_keywords[j]) && line > last_error_line) {
+ LogItem logItem = log[line];
+ message = logItem.getString(context);
+ for (String errorKeyword: error_keywords) {
+ if (message.contains(errorKeyword) && line > lastErrorLine) {
error = message;
- last_error_line = line;
+ lastErrorLine = line;
}
+ }
}
return error;
@@ -260,7 +263,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
@Override
public String toString() {
- return "State: " + state + " Level: " + vpn_level.toString();
+ return "State: " + state + " Level: " + vpnLevel.toString();
}
}
diff --git a/app/src/main/res/drawable/black_circle.xml b/app/src/main/res/drawable/black_circle.xml
new file mode 100644
index 00000000..533652d6
--- /dev/null
+++ b/app/src/main/res/drawable/black_circle.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<item>
+ <shape android:shape="oval">
+ <solid android:color="@color/black800"/>
+ <size android:width="250dp" android:height="250dp"/>
+ </shape>
+</item>
+</selector> \ No newline at end of file
diff --git a/app/src/main/res/drawable/vpn_connected.xml b/app/src/main/res/drawable/vpn_connected.xml
new file mode 100644
index 00000000..ea4d61a2
--- /dev/null
+++ b/app/src/main/res/drawable/vpn_connected.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+android:width="48dp"
+android:height="48dp"
+android:viewportWidth="48"
+android:viewportHeight="48">
+
+<path
+ android:fillColor="#ffffff"
+ android:strokeWidth="1"
+ android:pathData="M 12.187013,12.3125 C 5.4647724,12.3125 0,17.760254 0,24.5 c 0,6.739746
+5.4647724,12.21875 12.187013,12.21875 5.305097,0 9.803352,-3.408824
+11.47013,-8.15625 l 8.509091,-0.09375 1.745454,-2.09375 1.153247,-0.03125
+1.828239,2.182795 1.234013,-0.03125 2.049436,-2.307795 1.122078,0
+1.714286,2.21875 2.836364,0 L 48,24.4375 l -2.774026,-4.09375 -21.6,0 C
+21.928439,15.65398 17.450952,12.3125 12.187013,12.3125 z m -4.8311688,8.90625 c
+1.8370556,0 3.3350648,1.50191 3.3350648,3.34375 0,1.84184 -1.4980092,3.3125
+-3.3350648,3.3125 -1.8370556,0 -3.335065,-1.47066 -3.335065,-3.3125 0,-1.84184
+1.4980094,-3.34375 3.335065,-3.34375 z" />
+</vector> \ No newline at end of file
diff --git a/app/src/main/res/drawable/vpn_connecting.xml b/app/src/main/res/drawable/vpn_connecting.xml
new file mode 100644
index 00000000..16c079c4
--- /dev/null
+++ b/app/src/main/res/drawable/vpn_connecting.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#ffffff"
+ android:strokeWidth="1"
+ android:pathData="M12.1875,12.3125 C5.46526,12.3125,0,17.7603,0,24.5
+C0,31.2397,5.46526,36.7188,12.1875,36.7188
+C17.4926,36.7188,21.9895,33.3099,23.6563,28.5625 L32.1563,28.4688
+L33.9063,26.375 L35.0625,26.3438 L36.9063,28.5313 L38.125,28.5 L40.1875,26.1875
+L41.3125,26.1875 L43,28.4063 L45.8438,28.4063 L48,24.4375 L45.2188,20.3438
+L23.625,20.3438 C21.9275,15.654,17.4514,12.3125,12.1875,12.3125 Z
+M12.2188,15.6875 C17.0994,15.6875,21.0313,19.6506,21.0313,24.5313
+C21.0313,29.4119,17.0994,33.375,12.2188,33.375
+C7.33805,33.375,3.375,29.4119,3.375,24.5313
+C3.375,19.6506,7.33805,15.6875,12.2188,15.6875 Z" />
+ <path
+ android:strokeColor="#ffffff"
+ android:strokeWidth="2.50000000000000000"
+ android:pathData="M12.178,17.8729 L12.1779,24.6356 L8.61859,28.1949" />
+</vector> \ No newline at end of file
diff --git a/app/src/main/res/drawable/vpn_disconnected.xml b/app/src/main/res/drawable/vpn_disconnected.xml
new file mode 100644
index 00000000..d6cf067b
--- /dev/null
+++ b/app/src/main/res/drawable/vpn_disconnected.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <path
+ android:fillColor="#ffffff"
+ android:strokeWidth="1"
+ android:pathData="M13.9636,12.4377 L28.7376,28.5002 L32.1662,28.4689 L33.9117,26.3752
+L35.0649,26.3439 L36.9039,28.5314 L38.1195,28.5002 L40.1766,26.1877
+L41.2987,26.1877 L43.013,28.4064 L45.8494,28.4064 L48,24.4377 L45.226,20.344
+L23.626,20.344 C22.1234,16.1928,18.44,13.0938,13.9637,12.4378 Z M8.47792,12.9065
+C3.56807,14.4767,0,19.059,0,24.5002 C0,31.24,5.46477,36.719,12.187,36.719
+C17.2792,36.719,21.6241,33.5759,23.439,29.1253 L8.47792,12.9065 Z
+M7.35584,21.219 C9.1929,21.219,10.6909,22.7209,10.6909,24.5628
+C10.6909,26.4046,9.19289,27.8753,7.35584,27.8753
+C5.51878,27.8753,4.02077,26.4046,4.02077,24.5628
+C4.02077,22.721,5.51878,21.219,7.35583,21.219 Z" />
+ <group android:name="rotationGroup"
+ android:rotation="47.263656">
+ <path
+ android:fillColor="#ffffff"
+ android:strokeWidth="1"
+ android:pathData="M9.50852,-4.62741 L57.4577,-4.62741 L57.4577,-0.305379 L9.50852,-0.305379 L9.50852,-4.62741 Z" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/app/src/main/res/layout/eip_service_fragment.xml b/app/src/main/res/layout/eip_service_fragment.xml
index cef01c18..aa7ba514 100644
--- a/app/src/main/res/layout/eip_service_fragment.xml
+++ b/app/src/main/res/layout/eip_service_fragment.xml
@@ -1,49 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/relativeLayout"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp">
+ android:layout_height="match_parent">
+
+ <android.support.constraint.Guideline
+ android:id="@+id/guideline_horizontal_top"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:orientation="horizontal"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintGuide_percent="0.3"
+ />
+
+ <android.support.constraint.Guideline
+ android:id="@+id/guideline_vertical_left"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:orientation="vertical"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintGuide_percent="0.3"
+ />
+
+
+ <android.support.constraint.Guideline
+ android:id="@+id/guideline_horizontal_bottom"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:orientation="horizontal"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintGuide_percent="0.7"
+ />
+
+ <android.support.constraint.Guideline
+ android:id="@+id/guideline_vertical_right"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:orientation="vertical"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintGuide_percent="0.7"
+ />
+
+ <android.support.v7.widget.AppCompatImageView
+ android:id="@+id/background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="fitXY"
+ app:srcCompat="@drawable/ic_colorsquare" />
+
<TextView
android:id="@+id/eipLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_marginLeft="10dp"
- android:layout_marginStart="10dp"
- android:layout_marginTop="12dp"
- android:layout_marginBottom="12dp"
+ android:layout_marginEnd="@dimen/stdpadding"
+ android:layout_marginStart="@dimen/stdpadding"
+ android:layout_marginTop="@dimen/stdpadding"
+ android:layout_marginLeft="@dimen/stdpadding"
+ android:layout_marginRight="@dimen/stdpadding"
android:text="@string/eip_service_label"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+
+ <android.support.v7.widget.AppCompatImageView
+ android:id="@+id/cirle"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_marginBottom="@dimen/stdpadding"
+ android:layout_marginEnd="@dimen/stdpadding"
+ android:layout_marginStart="@dimen/stdpadding"
+ android:layout_marginTop="@dimen/stdpadding"
+ android:layout_marginLeft="@dimen/stdpadding"
+ android:layout_marginRight="@dimen/stdpadding"
+ app:layout_constraintBottom_toTopOf="@+id/guideline_horizontal_bottom"
+ app:layout_constraintEnd_toStartOf="@+id/guideline_vertical_right"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="@+id/guideline_vertical_left"
+ app:layout_constraintTop_toTopOf="@+id/guideline_horizontal_top"
+ app:layout_constraintVertical_bias="0.0"
+ app:srcCompat="@drawable/black_circle" />
+
+ <android.support.v7.widget.AppCompatImageView
+ android:id="@+id/key"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_marginBottom="@dimen/stdpadding"
+ android:layout_marginEnd="@dimen/stdpadding"
+ android:layout_marginStart="@dimen/stdpadding"
+ android:layout_marginTop="@dimen/stdpadding"
+ android:layout_marginLeft="@dimen/stdpadding"
+ android:layout_marginRight="@dimen/stdpadding"
+ app:layout_constraintBottom_toBottomOf="@+id/cirle"
+ app:layout_constraintEnd_toEndOf="@+id/cirle"
+ app:layout_constraintStart_toStartOf="@+id/cirle"
+ app:layout_constraintTop_toTopOf="@+id/cirle"
+ app:srcCompat="@drawable/vpn_connected" />
- <LinearLayout
+
+ <android.support.v7.widget.AppCompatButton
+ android:id="@+id/vpn_main_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_below="@+id/eipLabel"
- android:layout_centerInParent="true">
-
- <Button
- android:id="@+id/vpn_main_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="12sp"
- />
-
- <se.leap.bitmaskclient.userstatus.FabButton
- android:id="@+id/vpn_status_image"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:layout_marginLeft="3dp"
- android:layout_marginStart="3dp"
- android:color="@android:color/holo_blue_dark"
- android:layout_gravity="center"
- android:visibility="visible"
- android:indeterminate="true"
- android:max="100"
- fbb_autoStart="true"
- fbb_progressColor="#ff170aff"
- fbb_progressWidthRatio="0.1"
- />
- </LinearLayout>
-</RelativeLayout>
+ android:layout_marginBottom="@dimen/stdpadding"
+ android:layout_marginEnd="@dimen/stdpadding"
+ android:layout_marginStart="@dimen/stdpadding"
+ android:layout_marginTop="@dimen/stdpadding"
+ android:layout_marginLeft="@dimen/stdpadding"
+ android:layout_marginRight="@dimen/stdpadding"
+ app:layout_constraintBottom_toBottomOf="@+id/background"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ android:text="@string/vpn.button.turn.on"
+ style="@style/BitmaskButtonBlack"
+ />
+
+ <TextView
+ android:id="@+id/routed_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/stdpadding"
+ android:layout_marginStart="@dimen/stdpadding"
+ android:layout_marginTop="@dimen/stdpadding"
+ android:layout_marginLeft="@dimen/stdpadding"
+ android:layout_marginRight="@dimen/stdpadding"
+ android:text="@string/vpn_securely_routed"
+ android:visibility="visible"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/eipLabel" />
+
+ <TextView
+ android:id="@+id/vpn_route"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/stdpadding"
+ android:layout_marginStart="@dimen/stdpadding"
+ android:layout_marginLeft="@dimen/stdpadding"
+ android:layout_marginRight="@dimen/stdpadding"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/routed_text" />
+
+</android.support.constraint.ConstraintLayout>
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
index b928a79b..9f36e474 100644
--- a/app/src/main/res/values-v21/styles.xml
+++ b/app/src/main/res/values-v21/styles.xml
@@ -31,4 +31,10 @@
<item name="android:backgroundTint">@color/colorPrimary</item>
</style>
+ <style name="BitmaskButtonBlack" parent="android:Widget.Button">
+ <item name="android:textAllCaps">true</item>
+ <item name="android:backgroundTint">@color/black800</item>
+ <item name="android:textColor">@color/white</item>
+ </style>
+
</resources>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index a8a63e4b..53ead009 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -6,6 +6,8 @@
<color name="colorError">#ef9a9a</color>
<color name="colorSuccess">#a5d6a7</color>
+ <color name="black800">#424242</color>
+
<color name="red200">#ef9a9a</color>
<color name="pink200">#f48fb1</color>
<color name="purple200">#ce93d8</color>
@@ -23,4 +25,6 @@
<color name="orange200">#ffcc80</color>
<color name="deepOrange200">#ffab91</color>
+ <color name="white">#ffffff</color>
+
</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 01715c32..c1443138 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -85,6 +85,7 @@
<string name="vpn.button.turn.on">Turn on</string>
<string name="vpn.button.turn.off">Turn off</string>
<string name="vpn_button_turn_off_blocking">Stop blocking</string>
+ <string name="vpn_securely_routed">Your traffic is securely routed through:</string>
<string name="bitmask_log">Bitmask Log</string>
<string name="title_activity_main">Bitmask</string>
<string name="log_fragment_title">Log</string>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 3b1150ea..867fa54f 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -67,4 +67,11 @@
<style name="BitmaskActivity">
<item name="android:padding">@dimen/activity_margin</item>
</style>
+
+ <style name="BitmaskButtonBlack" parent="android:Widget.Button">
+ <item name="android:textAllCaps">true</item>
+ <item name="android:background">@color/black800</item>
+ <item name="android:textColor">@color/white</item>
+ </style>
+
</resources> \ No newline at end of file