fix(browser): prefer Chrome for Testing on macOS headless launch

On macOS the shared headless browser daemon launched from the system Google Chrome app bundle, running as a com.google.Chrome instance. macOS LaunchServices could then deliver the user's open-URL Apple Events to the daemon instead of their own Chrome, silently swallowing link clicks.

ensureChromiumExecutable now prefers the isolated Chrome for Testing binary (com.google.chrome.for.testing) on macOS, falling back to system Chrome only when Chrome for Testing cannot be obtained. Other platforms keep the download-avoiding system Chrome preference.

Fixes #8673
This commit is contained in:
roboomp
2026-08-15 19:38:25 +00:00
parent c246f09200
commit d9eb0586bd
4 changed files with 99 additions and 13 deletions
+1 -1
View File
@@ -251,7 +251,7 @@ The tool returns one result per call; no streaming partial output is emitted fro
- Use `read` for static URLs; use `browser` when JavaScript execution, authentication, or interaction is required. A tab must be opened before `run`, and named tabs persist until closed.
- `run` code has full Node/Bun and session-tool access; it is not sandboxed.
- `loadPuppeteer()` and `loadPuppeteerInWorker()` temporarily redirect `cwd` to a safe Puppeteer directory before importing `puppeteer-core`, because Puppeteer probes the current working directory during module load.
- Headless launch prefers a detected system Chrome/Chromium, then `PUPPETEER_EXECUTABLE_PATH`, and only then downloads Chromium.
- Headless launch resolves its executable in this order: `PUPPETEER_EXECUTABLE_PATH` always wins; otherwise, on macOS the isolated Chrome for Testing binary (`com.google.chrome.for.testing`) is preferred over a detected system Chrome and downloaded on first use, falling back to system Chrome only when Chrome for Testing cannot be obtained (a headless daemon launched from a system `Google Chrome.app` bundle shares its `com.google.Chrome` LaunchServices identity, so macOS can route the user's link clicks to the daemon — #8673). On other platforms a detected system Chrome/Chromium is preferred, then a downloaded Chrome for Testing.
- Headless launch always passes `--no-sandbox`, `--disable-setuid-sandbox`, `--disable-blink-features=AutomationControlled`, and a `--window-size=...` matching the initial viewport. It also ignores Puppeteer default args `--disable-extensions`, `--disable-default-apps`, and `--disable-component-extensions-with-background-pages`.
- Proxy-related env vars only affect headless launch argv (shared and local): `PUPPETEER_PROXY`, `PUPPETEER_PROXY_BYPASS_LOOPBACK`, and `PUPPETEER_PROXY_IGNORE_CERT_ERRORS`. For the shared daemon they are baked in at first launch and take effect again after the daemon's next cold start.
- Stealth patches are applied only in headless mode. Spawned or externally connected browsers are intentionally left untouched.