aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEric Kuck <eric@bluelinelabs.com>2018-07-08 15:42:48 -0500
committerJason A. Donenfeld <Jason@zx2c4.com>2018-07-09 17:08:41 +0200
commit6887ef89695dc1d588e621370b23aa6237af10f7 (patch)
tree290b1a2963dd92493f935c307664490e1021cd3a
parentUse instanceOf instead of getClass (diff)
downloadwireguard-android-6887ef89695dc1d588e621370b23aa6237af10f7.tar.xz
wireguard-android-6887ef89695dc1d588e621370b23aa6237af10f7.zip
Request VPN permissions on activation
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
-rw-r--r--app/src/main/java/com/wireguard/android/Application.java4
-rw-r--r--app/src/main/java/com/wireguard/android/activity/BaseActivity.java10
-rw-r--r--app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java7
-rw-r--r--app/src/main/java/com/wireguard/android/fragment/BaseFragment.java75
-rw-r--r--app/src/main/java/com/wireguard/android/fragment/TunnelController.java58
-rw-r--r--app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java2
-rw-r--r--app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java30
-rw-r--r--app/src/main/res/layout/tunnel_detail_fragment.xml8
-rw-r--r--app/src/main/res/layout/tunnel_list_item.xml8
9 files changed, 107 insertions, 95 deletions
diff --git a/app/src/main/java/com/wireguard/android/Application.java b/app/src/main/java/com/wireguard/android/Application.java
index f41bd3a..f304583 100644
--- a/app/src/main/java/com/wireguard/android/Application.java
+++ b/app/src/main/java/com/wireguard/android/Application.java
@@ -25,7 +25,7 @@ import com.wireguard.android.util.ToolsInstaller;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
import java.util.concurrent.Executor;
public class Application extends android.app.Application {
@@ -37,7 +37,7 @@ public class Application extends android.app.Application {
private ToolsInstaller toolsInstaller;
private TunnelManager tunnelManager;
private Handler handler;
- private List<BackendCallback> haveBackendCallbacks = new ArrayList<>();
+ private Collection<BackendCallback> haveBackendCallbacks = new ArrayList<>();
private final Object haveBackendCallbacksLock = new Object();
public Application() {
diff --git a/app/src/main/java/com/wireguard/android/activity/BaseActivity.java b/app/src/main/java/com/wireguard/android/activity/BaseActivity.java
index e5aaadf..9b535d7 100644
--- a/app/src/main/java/com/wireguard/android/activity/BaseActivity.java
+++ b/app/src/main/java/com/wireguard/android/activity/BaseActivity.java
@@ -6,13 +6,11 @@
package com.wireguard.android.activity;
-import android.content.Intent;
import android.databinding.CallbackRegistry;
import android.databinding.CallbackRegistry.NotifierCallback;
import android.os.Bundle;
import com.wireguard.android.Application;
-import com.wireguard.android.backend.GoBackend;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.model.TunnelManager;
@@ -52,14 +50,6 @@ public abstract class BaseActivity extends ThemeChangeAwareActivity {
// The selected tunnel must be set before the superclass method recreates fragments.
super.onCreate(savedInstanceState);
-
- Application.onHaveBackend(backend -> {
- if (backend instanceof GoBackend) {
- final Intent intent = GoBackend.VpnService.prepare(this);
- if (intent != null)
- startActivityForResult(intent, 0);
- }
- });
}
@Override
diff --git a/app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java b/app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java
index 79168e4..d45e60a 100644
--- a/app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java
+++ b/app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java
@@ -14,7 +14,6 @@ import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
import android.view.LayoutInflater;
-import android.view.View;
import android.view.ViewGroup;
import com.wireguard.android.BR;
@@ -78,7 +77,7 @@ public class ObservableKeyedRecyclerViewAdapter<K, E extends Keyed<? extends K>>
holder.binding.executePendingBindings();
if (rowConfigurationHandler != null) {
- rowConfigurationHandler.onConfigureRow(holder.binding.getRoot(), getItem(position), position);
+ rowConfigurationHandler.onConfigureRow(holder.binding, getItem(position), position);
}
}
@@ -149,8 +148,8 @@ public class ObservableKeyedRecyclerViewAdapter<K, E extends Keyed<? extends K>>
}
}
- public interface RowConfigurationHandler<T> {
- void onConfigureRow(View view, T item, int position);
+ public interface RowConfigurationHandler<B extends ViewDataBinding, T> {
+ void onConfigureRow(B binding, T item, int position);
}
}
diff --git a/app/src/main/java/com/wireguard/android/fragment/BaseFragment.java b/app/src/main/java/com/wireguard/android/fragment/BaseFragment.java
index e476a7f..510b1ca 100644
--- a/app/src/main/java/com/wireguard/android/fragment/BaseFragment.java
+++ b/app/src/main/java/com/wireguard/android/fragment/BaseFragment.java
@@ -7,11 +7,25 @@
package com.wireguard.android.fragment;
import android.content.Context;
+import android.content.Intent;
+import android.databinding.DataBindingUtil;
+import android.databinding.ViewDataBinding;
+import android.support.annotation.NonNull;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.View;
+import com.wireguard.android.Application;
+import com.wireguard.android.R;
import com.wireguard.android.activity.BaseActivity;
import com.wireguard.android.activity.BaseActivity.OnSelectedTunnelChangedListener;
+import com.wireguard.android.backend.GoBackend;
+import com.wireguard.android.databinding.TunnelDetailFragmentBinding;
+import com.wireguard.android.databinding.TunnelListItemBinding;
import com.wireguard.android.model.Tunnel;
+import com.wireguard.android.model.Tunnel.State;
+import com.wireguard.android.util.ExceptionLoggers;
/**
* Base class for fragments that need to know the currently-selected tunnel. Only does anything when
@@ -19,7 +33,12 @@ import com.wireguard.android.model.Tunnel;
*/
public abstract class BaseFragment extends Fragment implements OnSelectedTunnelChangedListener {
+ private static final String TAG = "WireGuard/" + BaseFragment.class.getSimpleName();
+ private static final int REQUEST_CODE_VPN_PERMISSION = 23491;
+
private BaseActivity activity;
+ private Tunnel pendingTunnel;
+ private Boolean pendingTunnelUp;
protected Tunnel getSelectedTunnel() {
return activity != null ? activity.getSelectedTunnel() : null;
@@ -44,8 +63,64 @@ public abstract class BaseFragment extends Fragment implements OnSelectedTunnelC
super.onDetach();
}
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_CODE_VPN_PERMISSION) {
+ if (pendingTunnel != null && pendingTunnelUp != null)
+ setTunnelStateWithPermissionsResult(pendingTunnel, pendingTunnelUp);
+ pendingTunnel = null;
+ pendingTunnelUp = null;
+ }
+ }
+
protected void setSelectedTunnel(final Tunnel tunnel) {
if (activity != null)
activity.setSelectedTunnel(tunnel);
}
+
+ public void setTunnelState(final View view, final boolean checked) {
+ final ViewDataBinding binding = DataBindingUtil.findBinding(view);
+ final Tunnel tunnel;
+ if (binding instanceof TunnelDetailFragmentBinding)
+ tunnel = ((TunnelDetailFragmentBinding) binding).getTunnel();
+ else if (binding instanceof TunnelListItemBinding)
+ tunnel = ((TunnelListItemBinding) binding).getItem();
+ else
+ return;
+
+ Application.onHaveBackend(backend -> {
+ if (backend instanceof GoBackend) {
+ final Intent intent = GoBackend.VpnService.prepare(view.getContext());
+ if (intent != null) {
+ pendingTunnel = tunnel;
+ pendingTunnelUp = checked;
+ startActivityForResult(intent, REQUEST_CODE_VPN_PERMISSION);
+ return;
+ }
+ }
+
+ setTunnelStateWithPermissionsResult(tunnel, checked);
+ });
+ }
+
+ private void setTunnelStateWithPermissionsResult(@NonNull final Tunnel tunnel, final boolean checked) {
+ tunnel.setState(State.of(checked)).whenComplete((state, throwable) -> {
+ if (throwable == null)
+ return;
+ final View view = getView();
+ if (view == null) {
+ Log.e(TAG, "setTunnelStateWithPermissionsResult() with no view");
+ return;
+ }
+ final Context context = view.getContext();
+ final String error = ExceptionLoggers.unwrapMessage(throwable);
+ final int messageResId = checked ? R.string.error_up : R.string.error_down;
+ final String message = context.getString(messageResId, error);
+ Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
+ Log.e(TAG, message, throwable);
+ });
+ }
+
}
diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelController.java b/app/src/main/java/com/wireguard/android/fragment/TunnelController.java
deleted file mode 100644
index dcaa92e..0000000
--- a/app/src/main/java/com/wireguard/android/fragment/TunnelController.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright © 2018 Samuel Holland <samuel@sholland.org>
- * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.android.fragment;
-
-import android.content.Context;
-import android.databinding.DataBindingUtil;
-import android.databinding.ViewDataBinding;
-import android.support.design.widget.Snackbar;
-import android.util.Log;
-import android.view.View;
-
-import com.wireguard.android.R;
-import com.wireguard.android.databinding.TunnelDetailFragmentBinding;
-import com.wireguard.android.databinding.TunnelListItemBinding;
-import com.wireguard.android.model.Tunnel;
-import com.wireguard.android.model.Tunnel.State;
-import com.wireguard.android.util.ExceptionLoggers;
-
-/**
- * Helper method shared by TunnelListFragment and TunnelDetailFragment.
- */
-
-public final class TunnelController {
- private static final String TAG = "WireGuard/" + TunnelController.class.getSimpleName();
-
- private TunnelController() {
- // Prevent instantiation.
- }
-
- public static void setTunnelState(final View view, final boolean checked) {
- final ViewDataBinding binding = DataBindingUtil.findBinding(view);
- final Tunnel tunnel;
- if (binding instanceof TunnelDetailFragmentBinding)
- tunnel = ((TunnelDetailFragmentBinding) binding).getTunnel();
- else if (binding instanceof TunnelListItemBinding)
- tunnel = ((TunnelListItemBinding) binding).getItem();
- else
- tunnel = null;
- if (tunnel == null) {
- Log.e(TAG, "setChecked() from a null tunnel", new IllegalStateException("No tunnel"));
- return;
- }
- tunnel.setState(State.of(checked)).whenComplete((state, throwable) -> {
- if (throwable == null)
- return;
- final Context context = view.getContext();
- final String error = ExceptionLoggers.unwrapMessage(throwable);
- final int messageResId = checked ? R.string.error_up : R.string.error_down;
- final String message = context.getString(messageResId, error);
- Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
- Log.e(TAG, message, throwable);
- });
- }
-}
diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java b/app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java
index 570e358..5c35686 100644
--- a/app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java
+++ b/app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java
@@ -69,7 +69,9 @@ public class TunnelDetailFragment extends BaseFragment {
@Override
public void onViewStateRestored(final Bundle savedInstanceState) {
+ binding.setFragment(this);
onSelectedTunnelChanged(null, getSelectedTunnel());
super.onViewStateRestored(savedInstanceState);
}
+
}
diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java b/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java
index 66c1d7b..88d9c0b 100644
--- a/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java
+++ b/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java
@@ -32,8 +32,10 @@ import com.wireguard.android.R;
import com.wireguard.android.activity.TunnelCreatorActivity;
import com.wireguard.android.databinding.ObservableKeyedRecyclerViewAdapter;
import com.wireguard.android.databinding.TunnelListFragmentBinding;
+import com.wireguard.android.databinding.TunnelListItemBinding;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.util.ExceptionLoggers;
+import com.wireguard.android.widget.ToggleSwitch;
import com.wireguard.config.Config;
import java.io.BufferedReader;
@@ -269,23 +271,21 @@ public class TunnelListFragment extends BaseFragment {
super.onViewStateRestored(savedInstanceState);
binding.setFragment(this);
binding.setTunnels(Application.getTunnelManager().getTunnels());
- binding.setRowConfigurationHandler(new ObservableKeyedRecyclerViewAdapter.RowConfigurationHandler<Tunnel>() {
- @Override
- public void onConfigureRow(View view, Tunnel tunnel, int position) {
- view.setOnClickListener(clicked -> {
- if (actionMode == null) {
- setSelectedTunnel(tunnel);
- } else {
- actionModeListener.toggleItemChecked(position);
- }
- });
- view.setOnLongClickListener(clicked -> {
+ binding.setRowConfigurationHandler((ObservableKeyedRecyclerViewAdapter.RowConfigurationHandler<TunnelListItemBinding, Tunnel>) (binding, tunnel, position) -> {
+ binding.setFragment(this);
+ binding.getRoot().setOnClickListener(clicked -> {
+ if (actionMode == null) {
+ setSelectedTunnel(tunnel);
+ } else {
actionModeListener.toggleItemChecked(position);
- return true;
- });
+ }
+ });
+ binding.getRoot().setOnLongClickListener(clicked -> {
+ actionModeListener.toggleItemChecked(position);
+ return true;
+ });
- view.setActivated(actionModeListener.checkedItems.contains(position));
- }
+ binding.getRoot().setActivated(actionModeListener.checkedItems.contains(position));
});
}
diff --git a/app/src/main/res/layout/tunnel_detail_fragment.xml b/app/src/main/res/layout/tunnel_detail_fragment.xml
index 3fa3c75..ed43cc0 100644
--- a/app/src/main/res/layout/tunnel_detail_fragment.xml
+++ b/app/src/main/res/layout/tunnel_detail_fragment.xml
@@ -5,13 +5,15 @@
<data>
- <import type="com.wireguard.android.fragment.TunnelController" />
-
<import type="com.wireguard.android.model.Tunnel.State" />
<import type="com.wireguard.android.util.ClipboardUtils" />
<variable
+ name="fragment"
+ type="com.wireguard.android.fragment.TunnelDetailFragment" />
+
+ <variable
name="tunnel"
type="com.wireguard.android.model.Tunnel" />
@@ -63,7 +65,7 @@
android:layout_alignBaseline="@+id/interface_title"
android:layout_alignParentEnd="true"
app:checked="@{tunnel.state == State.UP}"
- app:onBeforeCheckedChanged="@{TunnelController::setTunnelState}" />
+ app:onBeforeCheckedChanged="@{fragment::setTunnelState}" />
<TextView
android:id="@+id/interface_name_label"
diff --git a/app/src/main/res/layout/tunnel_list_item.xml b/app/src/main/res/layout/tunnel_list_item.xml
index 7fbd61f..f0a5b88 100644
--- a/app/src/main/res/layout/tunnel_list_item.xml
+++ b/app/src/main/res/layout/tunnel_list_item.xml
@@ -4,8 +4,6 @@
<data>
- <import type="com.wireguard.android.fragment.TunnelController" />
-
<import type="com.wireguard.android.model.Tunnel" />
<import type="com.wireguard.android.model.Tunnel.State" />
@@ -21,6 +19,10 @@
<variable
name="item"
type="com.wireguard.android.model.Tunnel" />
+
+ <variable
+ name="fragment"
+ type="com.wireguard.android.fragment.TunnelListFragment" />
</data>
<RelativeLayout
@@ -49,6 +51,6 @@
android:layout_alignBaseline="@+id/tunnel_name"
android:layout_alignParentEnd="true"
app:checked="@{item.state == State.UP}"
- app:onBeforeCheckedChanged="@{TunnelController::setTunnelState}" />
+ app:onBeforeCheckedChanged="@{fragment::setTunnelState}" />
</RelativeLayout>
</layout>