package webkit import ( "context" "encoding/json" "sync" "testing" "github.com/bnema/dumber/internal/application/port" "github.com/stretchr/testify/require" ) type messageRouterContextKey struct{} func TestMessageRouterBaseContextConcurrentUpdate(t *testing.T) { t.Parallel() router := NewMessageRouter(context.Background()) var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() for i := range 1000 { router.SetBaseContext(context.WithValue(context.Background(), messageRouterContextKey{}, i)) } }() go func() { defer wg.Done() for range 1000 { if router.baseContext() == nil { t.Error("base context must never be nil") } } }() wg.Wait() } func TestHandleAllowlistedEditableFocusMessage_AllowsUntrustedPage(t *testing.T) { router := NewMessageRouter(context.Background()) wv := &WebView{uri: "https://example.com", editableFocusBridgeToken: "secret-token"} var states []bool wv.SetCallbacks(&port.WebViewCallbacks{ OnEditableFocusChanged: func(editable bool) { states = append(states, editable) }, }) handled := router.handleAllowlistedBridgeMessage(wv, Message{ Type: "editable_focus_changed", Payload: json.RawMessage(`{"editable":true,"token":"secret-token"}`), }) require.True(t, handled) require.Equal(t, []bool{true}, states) } func TestHandleAllowlistedEditableFocusMessage_IsNoopAfterPoolReuse(t *testing.T) { router := NewMessageRouter(context.Background()) wv := &WebView{uri: "https://example.com", editableFocusBridgeToken: "secret-token"} wv.ResetForPoolReuse() // Re-register after reset so a stale token is the only reason handling is a noop. called := false wv.SetCallbacks(&port.WebViewCallbacks{ OnEditableFocusChanged: func(bool) { called = true }, }) handled := router.handleAllowlistedBridgeMessage(wv, Message{ Type: "editable_focus_changed", Payload: json.RawMessage(`{"editable":true,"token":"secret-token"}`), }) require.True(t, handled) require.False(t, called) } func TestResetForPoolReuse_RotatesEditableFocusBridgeToken(t *testing.T) { wv := &WebView{editableFocusBridgeToken: "secret-token"} wv.ResetForPoolReuse() require.NotEmpty(t, wv.EditableFocusBridgeToken()) require.NotEqual(t, "secret-token", wv.EditableFocusBridgeToken()) } func TestIsTrustedBridgeURI(t *testing.T) { t.Parallel() trusted := []string{ "dumb://history", "dumb://favorites", "dumb://config", "dumb://error", "dumb://crash", "dumb://history/path?cursor=1", } for _, raw := range trusted { t.Run(raw, func(t *testing.T) { t.Parallel() require.True(t, isTrustedBridgeURI(raw)) }) } untrusted := []string{ "", "https://example.com", "http://localhost", "file:///tmp/history.html", "dumb://evil/history", "dumb://example.com", "javascript:alert(1)", } for _, raw := range untrusted { t.Run(raw, func(t *testing.T) { t.Parallel() require.False(t, isTrustedBridgeURI(raw)) }) } }