test: cover android canvas a2ui trust gate

This commit is contained in:
Peter Steinberger 2026-04-04 20:33:16 +09:00
parent 1efce6f23c
commit 72847db28b
No known key found for this signature in database
3 changed files with 55 additions and 3 deletions

View File

@ -17,17 +17,19 @@ object CanvasActionTrust {
val normalizedCandidate = normalizeTrustedRemoteA2uiUri(candidateUri) ?: return false
return trustedA2uiUrls.any { trusted ->
isTrustedA2uiPage(normalizedCandidate, trusted)
matchesTrustedRemoteA2uiUrlExact(normalizedCandidate, trusted)
}
}
private fun isTrustedA2uiPage(candidateUri: URI, trustedUrl: String): Boolean {
private fun matchesTrustedRemoteA2uiUrlExact(candidateUri: URI, trustedUrl: String): Boolean {
val trustedUri = parseUri(trustedUrl) ?: return false
val normalizedTrusted = normalizeTrustedRemoteA2uiUri(trustedUri) ?: return false
return candidateUri == normalizedTrusted
}
private fun normalizeTrustedRemoteA2uiUri(uri: URI): URI? {
// Keep Android trust normalization aligned with iOS ScreenController:
// exact remote URL match, scheme/host normalized, fragment ignored.
val scheme = uri.scheme?.lowercase() ?: return null
if (scheme != "http" && scheme != "https") return null

View File

@ -163,7 +163,7 @@ private fun disableForceDarkIfSupported(settings: WebSettings) {
WebSettingsCompat.setForceDark(settings, WebSettingsCompat.FORCE_DARK_OFF)
}
private class CanvasA2UIActionBridge(
internal class CanvasA2UIActionBridge(
private val isTrustedPage: () -> Boolean,
private val onMessage: (String) -> Unit,
) {

View File

@ -0,0 +1,50 @@
package ai.openclaw.app.ui
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
class CanvasA2UIActionBridgeTest {
@Test
fun forwardsTrimmedPayloadFromTrustedPage() {
val forwarded = mutableListOf<String>()
val bridge =
CanvasA2UIActionBridge(
isTrustedPage = { true },
onMessage = { forwarded += it },
)
bridge.postMessage(" {\"ok\":true} ")
assertEquals(listOf("{\"ok\":true}"), forwarded)
}
@Test
fun rejectsPayloadFromUntrustedPage() {
val forwarded = mutableListOf<String>()
val bridge =
CanvasA2UIActionBridge(
isTrustedPage = { false },
onMessage = { forwarded += it },
)
bridge.postMessage("{\"ok\":true}")
assertTrue(forwarded.isEmpty())
}
@Test
fun rejectsBlankPayloadBeforeForwarding() {
val forwarded = mutableListOf<String>()
val bridge =
CanvasA2UIActionBridge(
isTrustedPage = { true },
onMessage = { forwarded += it },
)
bridge.postMessage(" ")
bridge.postMessage(null)
assertTrue(forwarded.isEmpty())
}
}