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.content.Context
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.text.TextUtils
import android.view.Window import android.view.Window
import android.webkit.JavascriptInterface import android.webkit.JavascriptInterface
import android.webkit.WebView
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@@ -25,6 +27,7 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.topjohnwu.superuser.ShellUtils import com.topjohnwu.superuser.ShellUtils
import me.weishu.kernelsu.ui.util.createRootShell import me.weishu.kernelsu.ui.util.createRootShell
import me.weishu.kernelsu.ui.util.serveModule import me.weishu.kernelsu.ui.util.serveModule
import org.json.JSONObject
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
@Destination @Destination
@@ -52,17 +55,17 @@ fun WebScreen(navigator: DestinationsNavigator, moduleId: String, moduleName: St
.fillMaxSize() .fillMaxSize()
.padding(innerPadding), .padding(innerPadding),
factory = { context -> factory = { context ->
android.webkit.WebView(context).apply { WebView(context).apply {
settings.javaScriptEnabled = true settings.javaScriptEnabled = true
settings.domStorageEnabled = true settings.domStorageEnabled = true
settings.allowFileAccess = 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 { companion object {
var isHideSystemUI: Boolean = false var isHideSystemUI: Boolean = false
@@ -74,6 +77,61 @@ class WebViewInterface(val context: Context) {
return ShellUtils.fastCmd(shell, cmd) 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 @JavascriptInterface
fun fullScreen(enable: Boolean) { fun fullScreen(enable: Boolean) {
if (context is Activity) { if (context is Activity) {