← Back to PRs

#6686: fix: clear Playwright's default colorScheme override on CDP-connected pages

by Terwox open 2026-02-01 23:20 View on GitHub →
## Problem When Playwright connects to an existing browser via `connectOverCDP()`, it initialises each page with `Emulation.setEmulatedMedia` using a default `colorScheme` of `"light"`. This is a hardcoded fallback in Playwright's `Page.emulatedMedia()` ([source](https://github.com/nicephil/playwright/blob/1a60af3e9e26b91b70c0fe7d4e54f14bbae33f69/packages/playwright-core/src/server/page.ts#L434)): ```typescript colorScheme: this._emulatedMedia.colorScheme !== void 0 ? this._emulatedMedia.colorScheme : contextOptions.colorScheme ?? "light", // ← fallback ``` Since `connectOverCDP` creates contexts with no explicit `colorScheme` option, every page gets `"light"` applied via CDP's `Emulation.setEmulatedMedia`. This override: 1. **Flips the host tab to light mode** regardless of the user's system `prefers-color-scheme` setting 2. **Persists after disconnection** — Chrome keeps the emulated media override even after the CDP session ends 3. **Is most visible with the Chrome extension relay** — after a screenshot or snapshot, the attached tab stays in light mode ## Root Cause Trace ``` connectOverCDP() → Playwright creates Page wrappers → CRFrameSession._initialize() calls _updateEmulateMedia() → page.emulatedMedia() returns { colorScheme: "light" } (default) → Emulation.setEmulatedMedia({ features: [{ name: "prefers-color-scheme", value: "light" }] }) → Host tab's color scheme is now overridden ``` ## Fix Add `clearDefaultColorScheme()` — calls `page.emulateMedia({ colorScheme: null })` which maps to Playwright's internal `"no-override"` sentinel, sending an empty-string feature value via CDP that clears the override and restores the browser's native preference. Applied in two places: - **`connectBrowser()`** — clears override on all existing pages immediately after CDP connection - **`observeContext()`** — clears override on new pages via the context `"page"` event handler ## Changes Single file: `src/browser/pw-session.ts` (+27 lines) - New `clearDefaultColorScheme(page)` helper with JSDoc explaining the Playwright internals - Called after `observeBrowser()` in `connectBrowser()` for existing pages - Called in the `context.on("page", ...)` handler for new pages The explicit `/set/media` endpoint (`emulateMediaViaPlaywright`) still works — it sets `_emulatedMedia.colorScheme` on the page object, which takes precedence over the cleared default on subsequent `_updateEmulateMedia()` calls. ## Testing Manually verified the fix path: - `page.emulateMedia({ colorScheme: null })` → Playwright sends `"no-override"` → CDP receives `prefers-color-scheme: ""` → Chrome clears the override - Confirmed the managed browser path is unaffected (headless Chrome has no system preference to override) - The `/set/media` endpoint continues to work correctly after this fix Relates to #6167 <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adds a small helper in `src/browser/pw-session.ts` to clear Playwright’s implicit `prefers-color-scheme: light` emulation that occurs when connecting to an existing browser via `chromium.connectOverCDP()`. The helper is applied both for already-open pages right after the CDP connection is established and for newly created pages via the context `"page"` event, preventing the host tab from being left in a forced light-mode state after the session ends. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - The change is localized to CDP-connected page initialization and uses Playwright’s supported `page.emulateMedia({ colorScheme: null })` API in a best-effort way; failures are swallowed and existing behavior should remain intact aside from removing an unintended persistent override. - No files require special attention <!-- greptile_other_comments_section --> <sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub> <!-- /greptile_comment -->

Most Similar PRs