summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2020-05-27 13:39:55 +0200
committerArne Schwabe <arne@rfc2549.org>2020-05-27 17:01:23 +0200
commit00b10ed048cc1f6490e7ca3e0530dd4471ca5a40 (patch)
tree0ffe2af2125fc0a05b05d8e3f55ab40a950724a6
parent45d8e94d3b8421018fa86a8ca1439210fedbd8de (diff)
Implement internal webview for authenticating when OPEN_URL is used
-rw-r--r--main/src/main/AndroidManifest.xml1
-rw-r--r--main/src/main/java/de/blinkt/openvpn/VpnProfile.java2
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java16
-rwxr-xr-xmain/src/main/res/values/strings.xml1
-rw-r--r--main/src/skeleton/java/de/blinkt/openvpn/core/VariantConfig.java16
-rw-r--r--main/src/ui/AndroidManifest.xml45
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt2
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/activities/InternalWebView.kt99
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/core/VariantConfig.java18
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java31
-rw-r--r--main/src/ui/res/layout/webview_internal.xml24
11 files changed, 210 insertions, 45 deletions
diff --git a/main/src/main/AndroidManifest.xml b/main/src/main/AndroidManifest.xml
index cfa99452..78b45ef2 100644
--- a/main/src/main/AndroidManifest.xml
+++ b/main/src/main/AndroidManifest.xml
@@ -228,6 +228,7 @@
android:value="de.blinkt.openvpn.activities.MainActivity" />
</activity>
<activity android:name=".api.RemoteAction" />
+ <activity android:name=".activities.MainActivity" />
<activity-alias
android:name=".api.ConnectVPN"
diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
index e6815dcf..921ea4db 100644
--- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -673,7 +673,7 @@ public class VpnProfile implements Serializable, Cloneable {
NativeUtils.getNativeAPI(), Build.BRAND, Build.BOARD, Build.MODEL);
}
- public String getVersionEnvString(Context c) {
+ static public String getVersionEnvString(Context c) {
String version = "unknown";
try {
PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);
diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index 51add1cd..eb88e0cc 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -31,14 +31,15 @@ import android.os.IBinder;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
import android.system.OsConstants;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -77,6 +78,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private static final String RESUME_VPN = "de.blinkt.openvpn.RESUME_VPN";
public static final String EXTRA_CHALLENGE_TXT = "de.blinkt.openvpn.core.CR_TEXT_CHALLENGE";
+ public static final String EXTRA_CHALLENGE_OPENURL = "de.blinkt.openvpn.core.OPENURL_CHALLENGE";
private static final int PRIORITY_MIN = -2;
private static final int PRIORITY_DEFAULT = 0;
@@ -174,8 +176,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
return res.getString(R.string.volume_gbyte, bytesUnit);
}
-
-
}
/**
@@ -700,6 +700,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
return null;
}
+
+
@Override
public IBinder asBinder() {
return mBinder;
@@ -1289,13 +1291,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
nbuilder.setContentTitle(getString(reason));
nbuilder.setContentText(url);
-
-
- intent = new Intent(Intent.ACTION_VIEW);
+ intent = VariantConfig.getOpenUrlIntent(this);
intent.setData(Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-
} else if (method.equals("CR_TEXT")) {
String challenge = info.split(":", 2)[1];
reason = R.string.crtext_requested;
diff --git a/main/src/main/res/values/strings.xml b/main/src/main/res/values/strings.xml
index ca7cd0bf..82633350 100755
--- a/main/src/main/res/values/strings.xml
+++ b/main/src/main/res/values/strings.xml
@@ -497,5 +497,6 @@
<string name="request_autologin">Request autologin profile</string>
<string name="import_from_as">Import Profile from Access Server</string>
<string name="no_default_vpn_set">Default VPN not set. Please set the Default VPN before enabling this option.</string>
+ <string name="internal_web_view">Internal WebView</string>
</resources>
diff --git a/main/src/skeleton/java/de/blinkt/openvpn/core/VariantConfig.java b/main/src/skeleton/java/de/blinkt/openvpn/core/VariantConfig.java
new file mode 100644
index 00000000..bbebc2af
--- /dev/null
+++ b/main/src/skeleton/java/de/blinkt/openvpn/core/VariantConfig.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2012-2020 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.openvpn.core;
+
+import android.content.Context;
+import android.content.Intent;
+
+public class VariantConfig {
+ static Intent getOpenUrlIntent(Context c) {
+ return new Intent(Intent.ACTION_VIEW);
+ }
+
+}
diff --git a/main/src/ui/AndroidManifest.xml b/main/src/ui/AndroidManifest.xml
index a4489228..86aa2956 100644
--- a/main/src/ui/AndroidManifest.xml
+++ b/main/src/ui/AndroidManifest.xml
@@ -4,30 +4,33 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- package="de.blinkt.openvpn">
+ xmlns:tools="http://schemas.android.com/tools"
+ package="de.blinkt.openvpn">
+
<uses-feature
- android:name="android.software.leanback"
- android:required="false" />
+ android:name="android.software.leanback"
+ android:required="false" />
<uses-feature
- android:name="android.hardware.touchscreen"
- android:required="false" />
+ android:name="android.hardware.touchscreen"
+ android:required="false" />
+
<application
- android:banner="@mipmap/banner_tv"
- >
- <activity
- android:name=".activities.MainActivity"
- tools:ignore="ExportedActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
+ android:banner="@mipmap/banner_tv"
+ tools:targetApi="lollipop">
+ <activity
+ android:name=".activities.MainActivity"
+ tools:ignore="ExportedActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
- <category android:name="android.intent.category.BROWSABLE" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
- </intent-filter>
- </activity>
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".activities.InternalWebView" />
</application>
</manifest>
diff --git a/main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt b/main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt
index f5d836b9..6c59ca88 100644
--- a/main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt
+++ b/main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt
@@ -5,9 +5,11 @@
package de.blinkt.openvpn.activities
import android.content.Intent
+import android.net.VpnService
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
+import de.blinkt.openvpn.core.OpenVPNService
import de.blinkt.openvpn.core.PasswordDialogFragment.Companion.newInstance
class CredentialsPopup : AppCompatActivity() {
diff --git a/main/src/ui/java/de/blinkt/openvpn/activities/InternalWebView.kt b/main/src/ui/java/de/blinkt/openvpn/activities/InternalWebView.kt
new file mode 100644
index 00000000..2bad9e81
--- /dev/null
+++ b/main/src/ui/java/de/blinkt/openvpn/activities/InternalWebView.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012-2020 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.openvpn.activities
+
+import android.annotation.SuppressLint
+import android.annotation.TargetApi
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.util.Log
+import android.webkit.JavascriptInterface
+import android.webkit.WebResourceRequest
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import android.widget.TextView
+import androidx.annotation.RequiresApi
+import androidx.appcompat.app.AppCompatActivity
+import de.blinkt.openvpn.R
+import de.blinkt.openvpn.VpnProfile
+import org.json.JSONObject
+
+class InternalWebView : AppCompatActivity() {
+
+ lateinit var webView: WebView
+ lateinit var urlTextView: TextView
+
+ @SuppressLint("SetJavaScriptEnabled")
+ override fun onCreate(savedInstanceState: Bundle?) {
+
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.webview_internal)
+
+ webView = findViewById(R.id.internal_webview)
+ urlTextView = findViewById(R.id.url_textview)
+
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
+ attachMessageHandler()
+
+ webView.loadUrl(intent.data.toString())
+
+ webView.settings.javaScriptEnabled = true
+ webView.settings.userAgentString = VpnProfile.getVersionEnvString(this)
+
+ webView.webViewClient = object: WebViewClient() {
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
+ urlTextView.text = request?.url?.toString();
+ return super.shouldOverrideUrlLoading(view, request)
+ }
+
+ }
+ urlTextView.text = intent.data.toString()
+
+ setTitle(R.string.internal_web_view)
+
+ }
+
+ @JavascriptInterface
+ fun postMessage(json: String?, transferList: String?): Boolean {
+ val jObejct = JSONObject(json)
+
+ val action = jObejct.getString("type")
+ Log.i("OpenVPN,InternalWebview", json + " ---- " + transferList)
+
+ if (action == "ACTION_REQUIRED") {
+ // Should show the hidden webview, nothing for us to do
+ return true
+ }
+
+ if (action == "CONNECT_SUCCESS" || action == "CONNECT_FAILED") {
+ runOnUiThread({finish()})
+ }
+
+ /* runOnUiThread({
+ Toast.makeText(this, json + " ---- " + transferList, Toast.LENGTH_LONG).show()
+ }) */
+ return true
+ }
+
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ private fun attachMessageHandler() {
+ webView.addJavascriptInterface(this, "appEvent")
+ }
+
+ override fun onResume() {
+ super.onResume()
+
+ }
+
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+
+ }
+} \ No newline at end of file
diff --git a/main/src/ui/java/de/blinkt/openvpn/core/VariantConfig.java b/main/src/ui/java/de/blinkt/openvpn/core/VariantConfig.java
new file mode 100644
index 00000000..5db8382c
--- /dev/null
+++ b/main/src/ui/java/de/blinkt/openvpn/core/VariantConfig.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2012-2020 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.openvpn.core;
+
+import android.content.Context;
+import android.content.Intent;
+
+import de.blinkt.openvpn.activities.InternalWebView;
+
+public class VariantConfig {
+ /** Return the normal webview or internal webview depending what is available */
+ static Intent getOpenUrlIntent(Context c) {
+ return new Intent(c, InternalWebView.class);
+ }
+}
diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java b/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java
index 629d65da..3804926f 100644
--- a/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java
+++ b/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java
@@ -60,6 +60,7 @@ import de.blinkt.openvpn.core.VpnStatus;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
import static de.blinkt.openvpn.core.OpenVPNService.DISCONNECT_VPN;
+import static de.blinkt.openvpn.core.OpenVPNService.EXTRA_CHALLENGE_TXT;
public class VPNProfileList extends ListFragment implements OnClickListener, VpnStatus.StateListener {
@@ -80,23 +81,28 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
protected VpnProfile mEditProfile = null;
private String mLastStatusMessage;
private ArrayAdapter<VpnProfile> mArrayadapter;
+ private Intent mLastIntent;
@Override
public void updateState(String state, String logmessage, final int localizedResId, ConnectionStatus level, Intent intent) {
requireActivity().runOnUiThread(() -> {
mLastStatusMessage = VpnStatus.getLastCleanLogMessage(getActivity());
+ mLastIntent = intent;
mArrayadapter.notifyDataSetChanged();
showUserRequestDialogIfNeeded(level, intent);
});
}
- private void showUserRequestDialogIfNeeded(ConnectionStatus level, Intent intent) {
+ private boolean showUserRequestDialogIfNeeded(ConnectionStatus level, Intent intent) {
if (level == LEVEL_WAITING_FOR_USER_INPUT) {
- PasswordDialogFragment pwInputFrag = PasswordDialogFragment.Companion.newInstance(intent, false);
-
- pwInputFrag.show(requireFragmentManager(), "dialog");
+ if (intent.getStringExtra(EXTRA_CHALLENGE_TXT) != null) {
+ PasswordDialogFragment pwInputFrag = PasswordDialogFragment.Companion.newInstance(intent, false);
+ pwInputFrag.show(getParentFragmentManager(), "dialog");
+ return true;
+ }
}
+ return false;
}
@Override
@@ -105,8 +111,12 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
private void startOrStopVPN(VpnProfile profile) {
if (VpnStatus.isVPNActive() && profile.getUUIDString().equals(VpnStatus.getLastConnectedVPNProfile())) {
- Intent disconnectVPN = new Intent(getActivity(), DisconnectVPN.class);
- startActivity(disconnectVPN);
+ if (mLastIntent != null) {
+ startActivity(mLastIntent);
+ } else {
+ Intent disconnectVPN = new Intent(getActivity(), DisconnectVPN.class);
+ startActivity(disconnectVPN);
+ }
} else {
startVPN(profile);
}
@@ -600,14 +610,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
});
View settingsview = v.findViewById(R.id.quickedit_settings);
- settingsview.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- editVPN(profile);
-
- }
- });
+ settingsview.setOnClickListener(view -> editVPN(profile));
TextView subtitle = (TextView) v.findViewById(R.id.vpn_item_subtitle);
if (profile.getUUIDString().equals(VpnStatus.getLastConnectedVPNProfile())) {
diff --git a/main/src/ui/res/layout/webview_internal.xml b/main/src/ui/res/layout/webview_internal.xml
new file mode 100644
index 00000000..f1bf17c8
--- /dev/null
+++ b/main/src/ui/res/layout/webview_internal.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (c) 2012-2020 Arne Schwabe
+ ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ -->
+
+<LinearLayout android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <TextView
+ android:id="@+id/url_textview"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ tools:text="https://foo.bar.baz" />
+
+ <WebView
+ android:id="@+id/internal_webview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
+
+</LinearLayout>