fix(chrome): enable the swiftshader webgl fallback

Headless Chrome runs with --disable-gpu, and without this flag it refuses the
software WebGL backend: getContext returns null, so a canvas-rendered app paints
nothing and every screenshot is identical black.

Claude-Session: https://claude.ai/code/session_01Fj4wJUikdABuMQEETwW55J
This commit is contained in:
pj committed 2026-08-12 16:48:52 +05:30
1 parent 715d239477
commit be2fbadc9d
2 files changed
+27

No files matched your search

+5
View File
@@ -39,6 +39,11 @@ func New() *Driver {
append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.Flag("headless", true),
chromedp.Flag("disable-gpu", true),
// Chrome refuses to fall back to the SwiftShader WebGL backend
// without this flag, so with --disable-gpu a canvas app (Compose
// for Web, Flutter web, anything on WebGL) gets a null context and
// paints nothing: black screenshots and an empty accessibility DOM.
chromedp.Flag("enable-unsafe-swiftshader", true),
chromedp.NoSandbox,
// CI runners give Chrome a tiny /dev/shm; without this the browser
// process hangs on startup and never reports its DevTools socket.
+22
View File
@@ -62,6 +62,28 @@ func TestLaunch_ClearStateWipesStorageForTheTargetOrigin(t *testing.T) {
}
}
// TestLaunch_WebGLContextIsAvailable pins the SwiftShader fallback. Headless
// Chrome runs with --disable-gpu, and without --enable-unsafe-swiftshader it
// refuses the software WebGL backend: getContext returns null, so a
// canvas-rendered app paints nothing and every screenshot is identical black.
func TestLaunch_WebGLContextIsAvailable(t *testing.T) {
d := New()
defer d.Terminate(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
if err := d.Launch(ctx, "data:text/html,<body></body>", false, nil); err != nil {
t.Fatalf("Launch: %v", err)
}
var hasContext bool
if err := chromedp.Run(d.tabCtx, chromedp.Evaluate(
`!!document.createElement("canvas").getContext("webgl2")`, &hasContext)); err != nil {
t.Fatalf("evaluate: %v", err)
}
if !hasContext {
t.Error("webgl2 context is null; a canvas-rendered app would render nothing")
}
}
// TestActionMethods_HonorCallerCancellation confirms the DeviceDriver action
// methods route through runCtx so a cancelled caller context aborts the CDP
// round-trip instead of blocking on d.tabCtx. Without this a hung browser would