mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-06 17:59:11 +00:00
fix android vpn permission grant (#2023)
* fix android vpn permission grant * fix url input behaviour
This commit is contained in:
@@ -14,6 +14,9 @@ class TauriVpnService : VpnService() {
|
||||
companion object {
|
||||
@JvmField var triggerCallback: (String, JSObject) -> Unit = { _, _ -> }
|
||||
@JvmField var self: TauriVpnService? = null
|
||||
@JvmField var ipv4Addr: String? = null
|
||||
@JvmField var routes: Array<String> = emptyArray()
|
||||
@JvmField var dns: String? = null
|
||||
|
||||
const val IPV4_ADDR = "IPV4_ADDR"
|
||||
const val ROUTES = "ROUTES"
|
||||
@@ -27,6 +30,9 @@ class TauriVpnService : VpnService() {
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
println("vpn on start command ${intent?.getExtras()} $intent")
|
||||
var args = intent?.getExtras()
|
||||
ipv4Addr = args?.getString(IPV4_ADDR)
|
||||
routes = args?.getStringArray(ROUTES) ?: emptyArray()
|
||||
dns = args?.getString(DNS)
|
||||
|
||||
vpnInterface = createVpnInterface(args)
|
||||
println("vpn created ${vpnInterface.fd}")
|
||||
@@ -63,6 +69,13 @@ class TauriVpnService : VpnService() {
|
||||
triggerCallback("vpn_service_stop", JSObject())
|
||||
vpnInterface.close()
|
||||
}
|
||||
clearStatus()
|
||||
}
|
||||
|
||||
private fun clearStatus() {
|
||||
ipv4Addr = null
|
||||
routes = emptyArray()
|
||||
dns = null
|
||||
}
|
||||
|
||||
private fun createVpnInterface(args: Bundle?): ParcelFileDescriptor {
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.plugin.vpnservice
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.VpnService
|
||||
import androidx.activity.result.ActivityResult
|
||||
import app.tauri.annotation.Command
|
||||
import app.tauri.annotation.ActivityCallback
|
||||
import app.tauri.annotation.InvokeArg
|
||||
import app.tauri.annotation.TauriPlugin
|
||||
import app.tauri.plugin.Invoke
|
||||
@@ -48,46 +50,70 @@ class VpnServicePlugin(private val activity: Activity) : Plugin(activity) {
|
||||
|
||||
@Command
|
||||
fun prepareVpn(invoke: Invoke) {
|
||||
println("prepare vpn in plugin")
|
||||
val it = VpnService.prepare(activity)
|
||||
var ret = JSObject()
|
||||
if (it != null) {
|
||||
activity.startActivityForResult(it, 0x0f)
|
||||
ret.put("errorMsg", "again")
|
||||
activity.runOnUiThread {
|
||||
println("prepare vpn in plugin")
|
||||
val it = VpnService.prepare(activity)
|
||||
if (it != null) {
|
||||
startActivityForResult(invoke, it, "onPrepareVpnResult")
|
||||
return@runOnUiThread
|
||||
}
|
||||
val ret = JSObject()
|
||||
ret.put("granted", true)
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
}
|
||||
|
||||
@ActivityCallback
|
||||
fun onPrepareVpnResult(invoke: Invoke, result: ActivityResult) {
|
||||
val ret = JSObject()
|
||||
ret.put("granted", result.resultCode == Activity.RESULT_OK)
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
|
||||
@Command
|
||||
fun startVpn(invoke: Invoke) {
|
||||
val args = invoke.parseArgs(StartVpnArgs::class.java)
|
||||
println("start vpn in plugin, args: $args")
|
||||
activity.runOnUiThread {
|
||||
println("start vpn in plugin, args: $args")
|
||||
|
||||
TauriVpnService.self?.onRevoke()
|
||||
TauriVpnService.self?.onRevoke()
|
||||
|
||||
val it = VpnService.prepare(activity)
|
||||
var ret = JSObject()
|
||||
if (it != null) {
|
||||
ret.put("errorMsg", "need_prepare")
|
||||
} else {
|
||||
var intent = Intent(activity, TauriVpnService::class.java)
|
||||
intent.putExtra(TauriVpnService.IPV4_ADDR, args.ipv4Addr)
|
||||
intent.putExtra(TauriVpnService.ROUTES, args.routes)
|
||||
intent.putExtra(TauriVpnService.DNS, args.dns)
|
||||
intent.putExtra(TauriVpnService.DISALLOWED_APPLICATIONS, args.disallowedApplications)
|
||||
intent.putExtra(TauriVpnService.MTU, args.mtu)
|
||||
val it = VpnService.prepare(activity)
|
||||
val ret = JSObject()
|
||||
if (it != null) {
|
||||
ret.put("errorMsg", "need_prepare")
|
||||
} else {
|
||||
val intent = Intent(activity, TauriVpnService::class.java)
|
||||
intent.putExtra(TauriVpnService.IPV4_ADDR, args.ipv4Addr)
|
||||
intent.putExtra(TauriVpnService.ROUTES, args.routes)
|
||||
intent.putExtra(TauriVpnService.DNS, args.dns)
|
||||
intent.putExtra(TauriVpnService.DISALLOWED_APPLICATIONS, args.disallowedApplications)
|
||||
intent.putExtra(TauriVpnService.MTU, args.mtu)
|
||||
|
||||
activity.startService(intent)
|
||||
activity.startService(intent)
|
||||
}
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
|
||||
@Command
|
||||
fun stopVpn(invoke: Invoke) {
|
||||
println("stop vpn in plugin")
|
||||
TauriVpnService.self?.onRevoke()
|
||||
activity.stopService(Intent(activity, TauriVpnService::class.java))
|
||||
println("stop vpn in plugin end")
|
||||
invoke.resolve(JSObject())
|
||||
activity.runOnUiThread {
|
||||
println("stop vpn in plugin")
|
||||
TauriVpnService.self?.onRevoke()
|
||||
activity.stopService(Intent(activity, TauriVpnService::class.java))
|
||||
println("stop vpn in plugin end")
|
||||
invoke.resolve(JSObject())
|
||||
}
|
||||
}
|
||||
|
||||
@Command
|
||||
fun getVpnStatus(invoke: Invoke) {
|
||||
val ret = JSObject()
|
||||
ret.put("running", TauriVpnService.self != null)
|
||||
ret.put("ipv4Addr", TauriVpnService.ipv4Addr)
|
||||
ret.put("routes", TauriVpnService.routes)
|
||||
ret.put("dns", TauriVpnService.dns)
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ const COMMANDS: &[&str] = &[
|
||||
"prepare_vpn",
|
||||
"start_vpn",
|
||||
"stop_vpn",
|
||||
"get_vpn_status",
|
||||
"registerListener",
|
||||
];
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function ping(value: string): Promise<string | null> {
|
||||
|
||||
export interface InvokeResponse {
|
||||
errorMsg?: string;
|
||||
granted?: boolean;
|
||||
}
|
||||
|
||||
export interface StartVpnRequest {
|
||||
@@ -20,6 +21,13 @@ export interface StartVpnRequest {
|
||||
mtu?: number;
|
||||
}
|
||||
|
||||
export interface VpnStatusResponse {
|
||||
running: boolean;
|
||||
ipv4Addr?: string;
|
||||
routes?: string[];
|
||||
dns?: string;
|
||||
}
|
||||
|
||||
export async function prepare_vpn(): Promise<InvokeResponse | null> {
|
||||
return await invoke<InvokeResponse>('plugin:vpnservice|prepare_vpn', {})
|
||||
}
|
||||
@@ -33,3 +41,7 @@ export async function start_vpn(request: StartVpnRequest): Promise<InvokeRespons
|
||||
export async function stop_vpn(): Promise<InvokeResponse | null> {
|
||||
return await invoke<InvokeResponse>('plugin:vpnservice|stop_vpn', {})
|
||||
}
|
||||
|
||||
export async function get_vpn_status(): Promise<VpnStatusResponse | null> {
|
||||
return await invoke<VpnStatusResponse>('plugin:vpnservice|get_vpn_status', {})
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ class ExamplePlugin: Plugin {
|
||||
let args = try invoke.parseArgs(PingArgs.self)
|
||||
invoke.resolve(["value": args.value ?? ""])
|
||||
}
|
||||
|
||||
@objc public func getVpnStatus(_ invoke: Invoke) {
|
||||
invoke.resolve(["running": false])
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("init_plugin_vpnservice")
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
"$schema" = "../../schemas/schema.json"
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-get-vpn-status"
|
||||
description = "Enables the get_vpn_status command without any pre-configured scope."
|
||||
commands.allow = ["get_vpn_status"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-get-vpn-status"
|
||||
description = "Denies the get_vpn_status command without any pre-configured scope."
|
||||
commands.deny = ["get_vpn_status"]
|
||||
@@ -16,6 +16,32 @@ Default permissions for the plugin
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:allow-get-vpn-status`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the get_vpn_status command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:deny-get-vpn-status`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the get_vpn_status command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
|
||||
@@ -294,6 +294,18 @@
|
||||
"PermissionKind": {
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Enables the get_vpn_status command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "allow-get-vpn-status",
|
||||
"markdownDescription": "Enables the get_vpn_status command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the get_vpn_status command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deny-get-vpn-status",
|
||||
"markdownDescription": "Denies the get_vpn_status command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the ping command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
|
||||
@@ -51,4 +51,10 @@ impl<R: Runtime> Vpnservice<R> {
|
||||
.run_mobile_plugin("stop_vpn", payload)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn get_vpn_status(&self, payload: VoidRequest) -> crate::Result<VpnStatus> {
|
||||
self.0
|
||||
.run_mobile_plugin("get_vpn_status", payload)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,3 +33,12 @@ pub struct StartVpnRequest {
|
||||
pub struct Status {
|
||||
pub error_msg: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VpnStatus {
|
||||
pub running: bool,
|
||||
pub ipv4_addr: Option<String>,
|
||||
pub routes: Option<Vec<String>>,
|
||||
pub dns: Option<String>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user