fix(browse): load extensions via --headless=new so no window and extensions run#2281
Conversation
…nsions run BROWSE_EXTENSIONS_DIR launched headed with --window-position=-9999,-9999 + browser.newContext(). On macOS the off-screen window is still shown and the isolated context leaves the loaded extension inert (issue garrytan#432). Route the extension path through launchPersistentContext + Chrome's new headless mode (--headless=new), reusing the pattern launchHeaded()/handoff() already use. Guard close() and isHealthy() for the null context.browser() that persistent contexts return, so an extension session tears down cleanly instead of leaking an orphan Chromium. Fixes garrytan#432
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
|
Heads up on the red
Happy to send a tiny follow-up guarding the push on forks if you'd like them to stop showing a false red: push: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}Just say the word. |
Fixes #432.
Problem
BROWSE_EXTENSIONS_DIRlaunched headed with--window-position=-9999,-9999+browser.newContext(). On macOS the off-screen window is still shown (I measured it landing at x:216, y:30), and the isolatednewContext()means the loaded extension never runs.Fix
Load extensions through
launchPersistentContext()with Chrome's new headless mode (--headless=new): the extension's service worker loads with no visible window. Reuses the persistent-context patternlaunchHeaded()/handoff()already use, plusignoreDefaultArgs: STEALTH_IGNORE_DEFAULT_ARGSto strip Playwright's--disable-extensions.Because persistent contexts return a null
context.browser()(same as the existing headed path),close()andisHealthy()now key offthis.contextinstead of assumingthis.browseris set — otherwise an extension session leaked an orphan Chromium on shutdown.Verification (macOS, Chromium 145)
chrome-extension://…/background.js) with no window.browsebinary withBROWSE_EXTENSIONS_DIRset:gotoreturns 200 headless, launch args show--headless=new+--load-extension,status: healthy, 0 orphan Chromium after stop.bun test browse/test/: no new failures vs. base.Known follow-up
recreateContext()(UA change / viewport--scale) andhandoff()still assume a non-nullthis.browser, so they would throw from an extension session. Left as a focused follow-up to keep this change minimal; the common extension path (launch → browse → close) works.