fix: final review findings - thread safety, xss, cache
This commit is contained in:
@@ -75,8 +75,10 @@ class JsBridge(
|
||||
Log.d("HearthBridge", "openWebApp: unknown id=$id")
|
||||
return
|
||||
}
|
||||
container.open(id, app.url, app.name)
|
||||
// 状态变更与 View 变更统一在主线程串行,避免与 onBackPressed/listTabs 并发读写
|
||||
// Mutate tab state and view on the main thread together, serializing access
|
||||
onMain {
|
||||
container.open(id, app.url, app.name)
|
||||
host.openWebView(id, app.url)
|
||||
host.syncTabs(container.tabs())
|
||||
}
|
||||
@@ -90,14 +92,14 @@ class JsBridge(
|
||||
fun closeWebApp(id: String) {
|
||||
val container = webAppContainer ?: return
|
||||
val host = webAppHost ?: return
|
||||
container.close(id)
|
||||
val nextActiveId = container.activeTabId()
|
||||
onMain {
|
||||
container.close(id)
|
||||
val nextActiveId = container.activeTabId()
|
||||
host.closeWebView(id)
|
||||
nextActiveId?.let { host.switchWebView(it) }
|
||||
host.syncTabs(container.tabs())
|
||||
Log.d("HearthBridge", "closeWebApp: id=$id remaining=${container.tabs().size}")
|
||||
}
|
||||
Log.d("HearthBridge", "closeWebApp: id=$id remaining=${container.tabs().size}")
|
||||
}
|
||||
|
||||
// 切换激活标签:校验 id 存在后更新状态 → 主线程切换 WebView 可见性 → 同步顶栏
|
||||
@@ -107,10 +109,11 @@ class JsBridge(
|
||||
fun switchTab(id: String) {
|
||||
val container = webAppContainer ?: return
|
||||
val host = webAppHost ?: return
|
||||
if (!container.switchTo(id)) return
|
||||
onMain {
|
||||
host.switchWebView(id)
|
||||
host.syncTabs(container.tabs())
|
||||
if (container.switchTo(id)) {
|
||||
host.switchWebView(id)
|
||||
host.syncTabs(container.tabs())
|
||||
}
|
||||
}
|
||||
Log.d("HearthBridge", "switchTab: id=$id")
|
||||
}
|
||||
@@ -153,12 +156,15 @@ class JsBridge(
|
||||
Log.d("HearthBridge", "webReload called")
|
||||
}
|
||||
|
||||
// 清单内存缓存:首次拉取后缓存,后续复用(避免 openWebApp 重复 I/O)
|
||||
// In-memory manifest cache: fetch once, reuse afterwards (avoid repeated I/O)
|
||||
// 清单内存缓存:首次拉取成功后缓存,后续复用(避免 openWebApp 重复 I/O)
|
||||
// 空结果(离线失败)不缓存,下次调用重试拉取,避免空清单被永久缓存
|
||||
// In-memory manifest cache: cache only on a successful non-empty fetch (avoid
|
||||
// repeated I/O); empty results (offline failure) are never cached so the next
|
||||
// call retries instead of being permanently stuck with an empty manifest
|
||||
private fun manifest(): List<WebApp> {
|
||||
manifestCache?.let { return it }
|
||||
val apps = webAppRepository?.fetchManifest() ?: emptyList<WebApp>()
|
||||
manifestCache = apps
|
||||
if (apps.isNotEmpty()) manifestCache = apps
|
||||
return apps
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user