manager: Add more abilities to js exec

This commit is contained in:
weishu
2024-02-22 20:39:46 +08:00
parent e6b05b1d3c
commit 66e7db2a4e

View File

@@ -5,8 +5,10 @@ import android.app.Activity
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.view.Window
import android.webkit.JavascriptInterface
import android.webkit.WebView
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
@@ -25,6 +27,7 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.topjohnwu.superuser.ShellUtils
import me.weishu.kernelsu.ui.util.createRootShell
import me.weishu.kernelsu.ui.util.serveModule
import org.json.JSONObject
@SuppressLint("SetJavaScriptEnabled")
@Destination
@@ -52,17 +55,17 @@ fun WebScreen(navigator: DestinationsNavigator, moduleId: String, moduleName: St
.fillMaxSize()
.padding(innerPadding),
factory = { context ->
android.webkit.WebView(context).apply {
WebView(context).apply {
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
settings.allowFileAccess = true
addJavascriptInterface(WebViewInterface(context), "ksu")
addJavascriptInterface(WebViewInterface(context, this), "ksu")
}
})
}
}
class WebViewInterface(val context: Context) {
class WebViewInterface(val context: Context, val webView: WebView) {
companion object {
var isHideSystemUI: Boolean = false
@@ -74,6 +77,61 @@ class WebViewInterface(val context: Context) {
return ShellUtils.fastCmd(shell, cmd)
}
@JavascriptInterface
fun exec(cmd: String, successCallbackName: String, errorCallbackName: String) {
exec(cmd, null, successCallbackName, errorCallbackName)
}
@JavascriptInterface
fun exec(
cmd: String,
options: String?,
successCallbackName: String,
errorCallbackName: String
) {
val opts = if (options == null) JSONObject() else {
JSONObject(options)
}
val finalCommand = StringBuilder()
val cwd = opts.optString("cwd")
if (!TextUtils.isEmpty(cwd)) {
finalCommand.append("cd ${cwd};")
}
opts.optJSONObject("env")?.let { env ->
env.keys().forEach { key ->
finalCommand.append("export ${key}=${env.getString(key)};")
}
}
finalCommand.append(cmd)
val shell = createRootShell()
val result = shell.newJob().add(finalCommand.toString()).to(ArrayList(), ArrayList()).exec()
if (!result.isSuccess) {
val jsCode =
"javascript: (function() { try { ${errorCallbackName}(${result.code}); } catch(e) { console.error(e); } })();"
webView.post {
webView.loadUrl(jsCode)
}
} else {
val stdout = result.out.joinToString(separator = "\n")
val stderr = result.err.joinToString(separator = "\n")
val jsCode =
"javascript: (function() { try { ${successCallbackName}(${JSONObject.quote(stdout)}, ${
JSONObject.quote(
stderr
)
}); } catch(e) { console.error(e); } })();"
webView.post {
webView.loadUrl(jsCode)
}
}
}
@JavascriptInterface
fun fullScreen(enable: Boolean) {
if (context is Activity) {