Skip to content

Commit c1e6dec

Browse files
committed
Add force kill option for WebUI process
Introduces a new 'Force Kill WebUI Process' setting, allowing users to immediately terminate the running WebUI X process. This includes UI, data model, repository, and activity logic updates, as well as a corresponding string resource and JavaScript interface support.
1 parent 1b0a66e commit c1e6dec

File tree

10 files changed

+87
-41
lines changed

10 files changed

+87
-41
lines changed

app/src/main/java/com/dergoogler/mmrl/wx/ui/activity/webui/WebUIActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class WebUIActivity : WXActivity() {
8686
appVersionCode = BuildConfig.VERSION_CODE,
8787
remoteDebug = userPrefs.useWebUiDevUrl,
8888
enableEruda = userPrefs.enableErudaConsole,
89+
forceKillWebUIProcess = userPrefs.forceKillWebUIProcess,
8990
autoOpenEruda = userPrefs.enableAutoOpenEruda,
9091
debugDomain = userPrefs.webUiDevUrl,
9192
userAgentString = userAgent,

app/src/main/java/com/dergoogler/mmrl/wx/ui/screens/settings/DeveloperScreen.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ fun DeveloperScreen() {
120120
Description(R.string.settings_security_auto_open_eruda_desc)
121121
}
122122

123+
DeveloperSwitch(
124+
checked = userPreferences.forceKillWebUIProcess,
125+
onChange = viewModel::setForceKillWebUIProcess
126+
) {
127+
Title(R.string.settings_force_kill_webui_process)
128+
Description(R.string.settings_force_kill_webui_process_desc)
129+
}
130+
123131
TextEditDialogItem(
124132
enabled = userPreferences.developerMode,
125133
value = userPreferences.webUiDevUrl,

app/src/main/java/com/dergoogler/mmrl/wx/viewmodel/SettingsViewModel.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ package com.dergoogler.mmrl.wx.viewmodel
22

33
import androidx.compose.runtime.staticCompositionLocalOf
44
import androidx.lifecycle.ViewModel
5-
import com.dergoogler.mmrl.wx.datastore.UserPreferencesRepository
65
import androidx.lifecycle.viewModelScope
76
import com.dergoogler.mmrl.datastore.model.DarkMode
8-
import com.dergoogler.mmrl.datastore.model.Homepage
9-
import com.dergoogler.mmrl.wx.datastore.model.WebUIEngine
107
import com.dergoogler.mmrl.datastore.model.WorkingMode
118
import com.dergoogler.mmrl.platform.PlatformManager
9+
import com.dergoogler.mmrl.wx.datastore.UserPreferencesRepository
10+
import com.dergoogler.mmrl.wx.datastore.model.WebUIEngine
1211
import dagger.hilt.android.lifecycle.HiltViewModel
1312
import kotlinx.coroutines.launch
1413
import javax.inject.Inject
@@ -85,6 +84,12 @@ class SettingsViewModel @Inject constructor(
8584
}
8685
}
8786

87+
fun setForceKillWebUIProcess(value: Boolean) {
88+
viewModelScope.launch {
89+
userPreferencesRepository.setForceKillWebUIProcess(value)
90+
}
91+
}
92+
8893
fun setWebUIEngine(value: WebUIEngine) {
8994
viewModelScope.launch {
9095
userPreferencesRepository.setWebUIEngine(value)

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,6 @@
127127
<string name="latest_commit_id">Latest Commit ID</string>
128128
<string name="build_tools_version">Build Tools Version</string>
129129
<string name="compile_sdk">Compile SDK</string>
130+
<string name="settings_force_kill_webui_process">Force Kill WebUI Process</string>
131+
<string name="settings_force_kill_webui_process_desc">Immediately terminates the currently running WebUI X process. [bold]This does not affect KSU WebUI.[/bold]</string>
130132
</resources>

datastore/src/main/kotlin/com/dergoogler/mmrl/wx/datastore/UserPreferencesDataSource.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ class UserPreferencesDataSource @Inject constructor(
9595
}
9696
}
9797

98+
suspend fun setForceKillWebUIProcess(value: Boolean) = withContext(Dispatchers.IO) {
99+
userPreferences.updateData {
100+
it.copy(
101+
forceKillWebUIProcess = value
102+
)
103+
}
104+
}
105+
98106
suspend fun setWebUIEngine(value: WebUIEngine) = withContext(Dispatchers.IO) {
99107
userPreferences.updateData {
100108
it.copy(

datastore/src/main/kotlin/com/dergoogler/mmrl/wx/datastore/UserPreferencesRepository.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package com.dergoogler.mmrl.wx.datastore
22

33
import com.dergoogler.mmrl.datastore.model.DarkMode
44
import com.dergoogler.mmrl.datastore.model.ModulesMenu
5-
import com.dergoogler.mmrl.wx.datastore.model.WebUIEngine
65
import com.dergoogler.mmrl.datastore.model.WorkingMode
6+
import com.dergoogler.mmrl.wx.datastore.model.WebUIEngine
77
import javax.inject.Inject
88
import javax.inject.Singleton
99

@@ -39,6 +39,9 @@ class UserPreferencesRepository @Inject constructor(
3939
suspend fun setEnableAutoOpenEruda(value: Boolean) =
4040
userPreferencesDataSource.setEnableAutoOpenEruda(value)
4141

42+
suspend fun setForceKillWebUIProcess(value: Boolean) =
43+
userPreferencesDataSource.setForceKillWebUIProcess(value)
44+
4245
suspend fun setWebUIEngine(value: WebUIEngine) =
4346
userPreferencesDataSource.setWebUIEngine(value)
4447
}

datastore/src/main/kotlin/com/dergoogler/mmrl/wx/datastore/model/UserPreferences.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ data class UserPreferences(
3636
@ProtoNumber(35) val enableErudaConsole: Boolean = false,
3737
@ProtoNumber(37) val webuiEngine: WebUIEngine = WebUIEngine.PREFER_MODULE,
3838
@ProtoNumber(38) val enableAutoOpenEruda: Boolean = false,
39+
@ProtoNumber(39) val forceKillWebUIProcess: Boolean = false,
3940
) {
4041
fun isDarkMode() = when (darkMode) {
4142
DarkMode.AlwaysOff -> false

webui/src/main/kotlin/com/dergoogler/mmrl/webui/activity/WXActivity.kt

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.dergoogler.mmrl.webui.activity
22

3+
import android.app.Activity
34
import android.app.ActivityManager
45
import android.content.Context
56
import android.content.Intent
67
import android.graphics.Rect
78
import android.os.Bundle
9+
import android.os.Process
810
import android.view.Gravity
911
import android.view.View
1012
import android.view.ViewGroup
@@ -40,6 +42,7 @@ import com.dergoogler.mmrl.webui.view.WXView
4042
import com.dergoogler.mmrl.webui.view.WebUIXView
4143
import kotlinx.coroutines.CoroutineScope
4244
import kotlinx.coroutines.launch
45+
import kotlin.system.exitProcess
4346

4447
/**
4548
* Base activity class for displaying web content using [WXView].
@@ -178,53 +181,55 @@ open class WXActivity : ComponentActivity() {
178181
private fun registerBackEvents() {
179182
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
180183
override fun handleOnBackPressed() {
181-
view.nullply {
182-
val backHandler = options.config.backHandler
183-
val interceptor = options.config.backInterceptor
184+
val options = view?.options ?: return
185+
val wx = view?.wx ?: return
184186

185-
if (backHandler != true) {
186-
handleNativeBack()
187-
return
188-
}
187+
val backHandler = options.config.backHandler
188+
val interceptor = options.config.backInterceptor
189189

190-
when (interceptor) {
191-
"native" -> handleNativeBack()
192-
"javascript" -> wx.postWXEvent(
193-
WXEventHandler(WXEvent.WX_ON_BACK, null)
194-
)
190+
if (backHandler != true) {
191+
handleNativeBack()
192+
return
193+
}
195194

196-
true -> handleNativeBack()
197-
null -> handleNativeBack()
198-
false -> finish()
199-
else -> finish()
200-
}
195+
when (interceptor) {
196+
"native" -> handleNativeBack()
197+
"javascript" -> wx.postWXEvent(
198+
WXEventHandler(WXEvent.WX_ON_BACK, null)
199+
)
200+
201+
true -> handleNativeBack()
202+
null -> handleNativeBack()
203+
false -> exit(options)
204+
else -> exit(options)
201205
}
202206
}
203207
})
204208
}
205209

206210
private fun handleNativeBack() {
207-
view.nullply {
208-
if (wx.canGoBack()) {
209-
wx.goBack()
210-
return
211-
}
211+
val options = view?.options ?: return
212+
val wx = view?.wx ?: return
212213

213-
if (options.config.exitConfirm) {
214-
confirm(
215-
confirmData = ConfirmData(
216-
title = getString(R.string.exit),
217-
description = getString(R.string.exit_desc),
218-
onConfirm = { finish() },
219-
onClose = {}
220-
),
221-
colorScheme = options.colorScheme
222-
)
223-
return
224-
}
214+
if (wx.canGoBack()) {
215+
wx.goBack()
216+
return
217+
}
225218

226-
finish()
219+
if (options.config.exitConfirm) {
220+
confirm(
221+
confirmData = ConfirmData(
222+
title = getString(R.string.exit),
223+
description = getString(R.string.exit_desc),
224+
onConfirm = { exit(options) },
225+
onClose = {}
226+
),
227+
colorScheme = options.colorScheme
228+
)
229+
return
227230
}
231+
232+
exit(options)
228233
}
229234

230235
@CallSuper
@@ -337,6 +342,17 @@ open class WXActivity : ComponentActivity() {
337342
this.startActivity(intent)
338343
}
339344

345+
internal fun Activity.exit(options: WebUIOptions) {
346+
if (!options.forceKillWebUIProcess) {
347+
finish()
348+
return
349+
}
350+
351+
finish()
352+
Process.killProcess(Process.myPid())
353+
exitProcess(0)
354+
}
355+
340356
/**
341357
* Launches a new instance of the specified [ComponentActivity] (`T`) as a Web UI.
342358
*

webui/src/main/kotlin/com/dergoogler/mmrl/webui/interfaces/ApplicationInterface.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import androidx.annotation.Keep
77
import androidx.core.content.pm.PackageInfoCompat
88
import com.dergoogler.mmrl.compat.MediaStoreCompat.getPathForUri
99
import com.dergoogler.mmrl.platform.PlatformManager
10+
import com.dergoogler.mmrl.webui.activity.WXActivity.Companion.exit
1011
import com.dergoogler.mmrl.webui.model.App
1112
import com.squareup.moshi.JsonClass
1213
import kotlinx.coroutines.Dispatchers
@@ -21,8 +22,8 @@ class ApplicationInterface(
2122

2223
@JavascriptInterface
2324
fun exit() {
24-
withActivity<Unit> {
25-
finish()
25+
withActivity {
26+
exit(options)
2627
}
2728
}
2829

webui/src/main/kotlin/com/dergoogler/mmrl/webui/util/rememberWebUIOptions.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ data class WebUIOptions(
7373
val debugDomain: String = "https://127.0.0.1:8080",
7474
val onUnsafeDomainRequest: ((Uri) -> Unit)? = null,
7575
val isDarkMode: Boolean = false,
76+
val forceKillWebUIProcess: Boolean = false,
7677
val userAgentString: String = "DON'T TRACK ME DOWN MOTHERFUCKER!",
7778
val colorScheme: ColorScheme = context.getColorScheme(id = 0, darkMode = isDarkMode),
7879
val client: ((WebUIOptions, Insets, assetHandlers: List<Pair<String, PathHandler>>) -> WXClient)? = null,

0 commit comments

Comments
 (0)