← Back to PRs

#8007: Firefox browser support

by krazyjakee open 2026-02-03 13:02 View on GitHub →
stale
## Summary - Add Firefox browser support via Playwright's **juggler** protocol, enabling Firefox as an alternative browser engine for browser profiles - Introduce `engine: "firefox"` config option for browser profiles alongside the existing Chromium path - Auto-resolve Playwright's bundled (juggler‑patched) Firefox from the Playwright cache, since stock Firefox doesn't support the juggler protocol ## Changes ### New files - `src/browser/firefox.ts` — Firefox lifecycle management (launch, stop, reachability check) using Playwright persistent contexts - `src/browser/firefox.executables.ts` — Cross-platform Firefox executable discovery (macOS, Linux, Windows) with Playwright cache scanner - `src/browser/firefox.executables.test.ts` — Tests for executable resolution across all platforms - `src/browser/firefox.test.ts` — Basic Firefox helper tests - `src/browser/browser-process.ts` — Shared `RunningBrowser` type extracted to support both Chrome and Firefox engines ### Modified files - `src/browser/config.ts` / `config.test.ts` — Add `engine` field to `ResolvedBrowserProfile`; validate that Firefox rejects the extension driver - `src/browser/profiles-service.ts` / `profiles-service.test.ts` — Persist `engine` field on profile creation; reject Firefox + extension driver combo - `src/config/types.browser.ts` — Add `engine` to `BrowserProfileConfig` - `src/config/zod-schema.ts` — Add `engine` to the config schema validation - `src/browser/server-context.ts` — Wire Firefox launch/stop/reachability into the profile lifecycle (launch, tab management, focus, close, status) - `src/browser/pw-session.ts` — Firefox page routing: - Synthetic tab IDs (`ff-1`, `ff-2`, …) since Firefox lacks CDP target IDs - Firefox code paths for: - `getPageForTargetId` - `listPagesViaPlaywright` - `createPageViaPlaywright` - `closePageByTargetIdViaPlaywright` - `focusPageByTargetIdViaPlaywright` - `src/browser/pw-tools-core.snapshot.ts` — Firefox fallback for ARIA snapshots (Playwright `ariaSnapshot()` instead of CDP `Accessibility.enable`) - `src/browser/pw-tools-core.state.ts` — Guard CDP-only features (locale/timezone override, device UA emulation) for Firefox; viewport works cross‑browser - `src/browser/pw-tools-core.interactions.ts` — Thread `engine` / `profileName` through interaction tool functions - `src/browser/routes/agent.act.ts` - `src/browser/routes/agent.snapshot.ts` - `src/browser/routes/agent.storage.ts` - `src/browser/routes/agent.debug.ts` - `src/browser/routes/basic.ts` — Pass engine options through all route handlers - `docs/tools/browser.md` — Add Docker Playwright install instructions ## Design decisions - **Playwright persistent context** Firefox doesn't expose CDP, so we use `firefox.launchPersistentContext()` to manage the browser lifecycle. This provides a `BrowserContext` that stays alive for the session. - **Synthetic tab IDs** Since Firefox has no CDP target IDs, we assign stable synthetic IDs (`ff-1`, `ff-2`, …) via a `WeakMap` so tab references work consistently across tool calls. - **Bundled Firefox preferred** Playwright's bundled Firefox includes juggler patches required for automation. The resolver checks `~/.cache/ms-playwright` (or `PLAYWRIGHT_BROWSERS_PATH`) first, falling back to system Firefox installs. - **Extension driver guard** The Chrome extension relay is inherently Chromium-only, so `engine: "firefox"` + `driver: "extension"` is rejected at config resolution and profile creation time. - **Graceful degradation** CDP-only features (locale override, timezone override, device UA spoofing) throw a clear error for Firefox profiles; viewport and most Playwright-level operations work cross‑browser. ## Test plan - Unit tests for Firefox executable discovery across macOS/Linux/Windows - Unit tests for config resolution with `engine: "firefox"` - Unit tests for profile creation with Firefox engine (and rejection of Firefox + extension) - Unit tests for Firefox helper functions (`isFirefoxReachable`, `getFirefoxContext`) - Manual: create a Firefox profile (`openclaw config set browser.profiles.ff.engine firefox`), launch, navigate, take snapshots - Manual: verify Playwright-bundled Firefox is preferred over system Firefox - Manual: verify extension driver + Firefox is rejected with a clear error <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adds a new `engine` setting for browser profiles (`chromium` default, `firefox` optional) and wires Firefox support through the browser server lifecycle. Firefox is implemented using Playwright’s `firefox.launchPersistentContext()` and a per-profile in-memory context map, with synthetic `ff-*` tab IDs to replace CDP target IDs. Tooling is updated to route page/tab operations through Playwright for Firefox (and for remote profiles), and CDP-only features are guarded/disabled for Firefox. Key areas touched: - Profile config/schema/type updates (`engine` + validation rejecting `firefox` + `extension`). - New Firefox launch/stop/reachability helpers and executable discovery with Playwright cache scanning. - `server-context` integration for launching and tab ops. - `pw-session` Playwright tab listing/creation/close/focus updated to support Firefox contexts and synthetic IDs. - Snapshot/state tools updated to handle Firefox limitations (no CDP). <h3>Confidence Score: 3/5</h3> - This PR is generally safe to merge, but Firefox support has a few correctness gaps that will likely surface in real usage. - The overall integration approach is consistent (engine flag, Playwright persistent context, synthetic tab IDs), and tests cover several paths, but there are some concrete issues: Windows Playwright-cache Firefox resolution is missing, `stopOpenClawFirefox` can pick the wrong profile due to substring matching, and Firefox ARIA snapshot refs are not wired into the existing ref-resolution mechanism. These can lead to using the wrong browser binary, stopping the wrong session, or producing unusable refs for later actions. - src/browser/firefox.executables.ts, src/browser/firefox.ts, src/browser/pw-tools-core.snapshot.ts, src/browser/browser-process.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs