/
PluginManager.kt
138 lines (118 loc) · 4.26 KB
/
PluginManager.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
package app.tauri.plugin
import android.content.Context
import android.content.Intent
import android.webkit.WebView
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import app.tauri.FsUtils
import app.tauri.JniMethod
import app.tauri.Logger
class PluginManager(val activity: AppCompatActivity) {
fun interface RequestPermissionsCallback {
fun onResult(permissions: Map<String, Boolean>)
}
fun interface ActivityResultCallback {
fun onResult(result: ActivityResult)
}
private val plugins: HashMap<String, PluginHandle> = HashMap()
private val startActivityForResultLauncher: ActivityResultLauncher<Intent>
private val requestPermissionsLauncher: ActivityResultLauncher<Array<String>>
private var requestPermissionsCallback: RequestPermissionsCallback? = null
private var startActivityForResultCallback: ActivityResultCallback? = null
init {
startActivityForResultLauncher =
activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()
) { result ->
if (startActivityForResultCallback != null) {
startActivityForResultCallback!!.onResult(result)
}
}
requestPermissionsLauncher =
activity.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()
) { result ->
if (requestPermissionsCallback != null) {
requestPermissionsCallback!!.onResult(result)
}
}
}
fun onNewIntent(intent: Intent) {
for (plugin in plugins.values) {
plugin.instance.onNewIntent(intent)
}
}
fun startActivityForResult(intent: Intent, callback: ActivityResultCallback) {
startActivityForResultCallback = callback
startActivityForResultLauncher.launch(intent)
}
fun requestPermissions(
permissionStrings: Array<String>,
callback: RequestPermissionsCallback
) {
requestPermissionsCallback = callback
requestPermissionsLauncher.launch(permissionStrings)
}
@JniMethod
fun onWebViewCreated(webView: WebView) {
for ((_, plugin) in plugins) {
if (!plugin.loaded) {
plugin.load(webView)
}
}
}
@JniMethod
fun load(webView: WebView?, name: String, plugin: Plugin, config: JSObject) {
val handle = PluginHandle(this, name, plugin, config)
plugins[name] = handle
if (webView != null) {
plugin.load(webView)
}
}
@JniMethod
fun postIpcMessage(webView: WebView, pluginId: String, command: String, data: JSObject, callback: Long, error: Long) {
val invoke = Invoke(callback, command, { successResult, errorResult ->
val (fn, result) = if (errorResult == null) Pair(callback, successResult) else Pair(
error,
errorResult
)
webView.evaluateJavascript("window['_$fn']($result)", null)
}, data)
dispatchPluginMessage(invoke, pluginId)
}
@JniMethod
fun runCommand(id: Int, pluginId: String, command: String, data: JSObject) {
val invoke = Invoke(id.toLong(), command, { successResult, errorResult ->
handlePluginResponse(id, successResult?.toString(), errorResult?.toString())
}, data)
dispatchPluginMessage(invoke, pluginId)
}
private fun dispatchPluginMessage(invoke: Invoke, pluginId: String) {
Logger.verbose(
Logger.tags("Plugin"),
"Tauri plugin: pluginId: $pluginId, command: ${invoke.command}"
)
try {
val plugin = plugins[pluginId]
if (plugin == null) {
invoke.reject("Plugin $pluginId not initialized")
} else {
plugins[pluginId]?.invoke(invoke)
}
} catch (e: Exception) {
invoke.reject(e.message)
}
}
companion object {
fun loadConfig(context: Context, plugin: String): JSObject {
val tauriConfigJson = FsUtils.readAsset(context.assets, "tauri.conf.json")
val tauriConfig = JSObject(tauriConfigJson)
val plugins = tauriConfig.getJSObject("plugins", JSObject())
return plugins.getJSObject(plugin, JSObject())
}
}
private external fun handlePluginResponse(id: Int, success: String?, error: String?)
}