1package webkit
2
3import (
4 "context"
5 "net/url"
6 "testing"
7
8 "github.com/bnema/dumber/assets"
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11)
12
13func TestCrashOriginalURI(t *testing.T) {
14 assert.Equal(t, "https://example.com/path?q=1", crashOriginalURI("dumb://home/crash?url=https%3A%2F%2Fexample.com%2Fpath%3Fq%3D1"))
15 assert.Empty(t, crashOriginalURI("dumb://home/crash"))
16 assert.Empty(t, crashOriginalURI("%%%"))
17}
18
19func TestBuildCrashPageHTMLIncludesReloadTarget(t *testing.T) {
20 body := buildCrashPageHTML("https://example.com/foo?a=1&b=2")
21 assert.Contains(t, body, `data-target="https://example.com/foo?a=1&b=2"`)
22 assert.Contains(t, body, "https://example.com/foo?a=1&b=2")
23}
24
25func TestBuildCrashPageHTMLFallbackReloadWithoutTarget(t *testing.T) {
26 body := buildCrashPageHTML("")
27 assert.Contains(t, body, "window.location.reload();")
28}
29
30func TestBuildCrashPageHTMLRejectsUnsafeReloadScheme(t *testing.T) {
31 // buildCrashPageHTML receives already-sanitized input from the caller.
32 // sanitizeCrashPageOriginalURI strips unsafe schemes to "".
33 sanitized := sanitizeCrashPageOriginalURI("javascript:alert(1)")
34 assert.Empty(t, sanitized)
35 body := buildCrashPageHTML(sanitized)
36 assert.Contains(t, body, `data-target=""`)
37}
38
39func TestBuildCrashPageHTMLAllowsDumbSchemeTarget(t *testing.T) {
40 body := buildCrashPageHTML("dumb://home")
41 assert.Contains(t, body, `data-target="dumb://home"`)
42}
43
44func TestBuildCrashPageHTMLEscapesScriptBreakoutPayload(t *testing.T) {
45 payload := `https://example.com/?q=</script><script>alert(1)</script>`
46 body := buildCrashPageHTML(payload)
47 assert.NotContains(t, body, "</script><script>alert(1)</script>")
48 assert.Contains(t, body, "</script><script>alert(1)</script>")
49}
50
51func TestRegisterDefaultsIncludesCrashHandler(t *testing.T) {
52 handler := NewDumbSchemeHandler(context.Background())
53 require.NotNil(t, handler)
54
55 handler.mu.RLock()
56 crashHandler, ok := handler.handlers["/crash"]
57 handler.mu.RUnlock()
58 require.True(t, ok)
59 require.NotNil(t, crashHandler)
60
61 resp := crashHandler.Handle(&SchemeRequest{
62 URI: "dumb://home/crash?url=https%3A%2F%2Fexample.com",
63 Path: "/crash",
64 Method: "GET",
65 Scheme: "dumb",
66 })
67 require.NotNil(t, resp)
68 assert.Equal(t, 200, resp.StatusCode)
69 assert.Equal(t, "text/html; charset=utf-8", resp.ContentType)
70 assert.Contains(t, string(resp.Data), "Renderer process ended")
71}
72
73func TestCrashHandlerSanitizesUnsafeURLQuery(t *testing.T) {
74 handler := NewDumbSchemeHandler(context.Background())
75 require.NotNil(t, handler)
76
77 handler.mu.RLock()
78 crashHandler, ok := handler.handlers["/crash"]
79 handler.mu.RUnlock()
80 require.True(t, ok)
81 require.NotNil(t, crashHandler)
82
83 resp := crashHandler.Handle(&SchemeRequest{
84 URI: "dumb://home/crash?url=javascript%3Aalert(1)",
85 Path: "/crash",
86 Method: "GET",
87 Scheme: "dumb",
88 })
89 require.NotNil(t, resp)
90 assert.Contains(t, string(resp.Data), `data-target=""`)
91}
92
93func TestHandleAsset_WebRTCRootServesInternalWebRTCTester(t *testing.T) {
94 h := NewDumbSchemeHandler(context.Background())
95 h.SetAssets(assets.WebUIAssets)
96
97 u, err := url.Parse("dumb://webrtc/")
98 require.NoError(t, err)
99
100 resp := h.handleAsset(u)
101 require.NotNil(t, resp)
102 assert.Equal(t, "text/html; charset=utf-8", resp.ContentType)
103 assert.Contains(t, string(resp.Data), "webrtc.min.js")
104}
105
106func TestHandleAsset_WebRTCOpaqueFormServesInternalWebRTCTester(t *testing.T) {
107 h := NewDumbSchemeHandler(context.Background())
108 h.SetAssets(assets.WebUIAssets)
109
110 u, err := url.Parse("dumb:webrtc")
111 require.NoError(t, err)
112
113 resp := h.handleAsset(u)
114 require.NotNil(t, resp)
115 assert.Equal(t, "text/html; charset=utf-8", resp.ContentType)
116 assert.Contains(t, string(resp.Data), "webrtc.min.js")
117}
118
119func TestHandleAsset_ConfigOpaqueFormServesConfigPage(t *testing.T) {
120 h := NewDumbSchemeHandler(context.Background())
121 h.SetAssets(assets.WebUIAssets)
122
123 u, err := url.Parse("dumb:config")
124 require.NoError(t, err)
125
126 resp := h.handleAsset(u)
127 require.NotNil(t, resp)
128 assert.Equal(t, "text/html; charset=utf-8", resp.ContentType)
129 assert.Contains(t, string(resp.Data), "config")
130}