diff --git a/bridgic/browser/session/_browser.py b/bridgic/browser/session/_browser.py index f3c8ca5..0c2da74 100644 --- a/bridgic/browser/session/_browser.py +++ b/bridgic/browser/session/_browser.py @@ -861,21 +861,27 @@ def _get_launch_options(self) -> Dict[str, Any]: # navigator.webdriver, plugins, chrome object, etc.). _is_system_chrome = bool(self._channel or self._executable_path) - # In headed mode, auto-switch to system Chrome to avoid Google blocking - # "Chrome for Testing" (the Playwright-bundled binary) for OAuth login. - # System Chrome shows as a normal browser in the Dock (no "test" label) - # and passes Google's browser safety checks. + # In headed mode, auto-switch to system Chrome when available. + # Reasons: + # - Anti-detection: Google blocks Playwright's bundled "Chrome + # for Testing" for OAuth login. System Chrome shows as a + # normal browser in the Dock and passes the safety checks. + # - Reliability: bundled Chrome for Testing has been observed + # self-trapping (EXC_BREAKPOINT/SIGTRAP bug_type=309) shortly + # after Playwright launches it in headed mode on some macOS + # versions; Apple-notarized system Chrome has no such reports. + # Only triggered when the user hasn't pinned a channel / + # executable_path and the system Chrome binary is present. _auto_system_chrome = ( not self._headless - and self.stealth_enabled and not _is_system_chrome and _detect_system_chrome() ) if _auto_system_chrome: options["channel"] = "chrome" logger.info( - "Headed mode: auto-switching to system Chrome for anti-detection " - "(Chrome for Testing is blocked by Google OAuth)" + "Headed mode: auto-switching to system Chrome " + "(anti-detection + reliability; pass channel='chromium' to override)" ) # Add stealth args first (if enabled). diff --git a/pyproject.toml b/pyproject.toml index 317c768..16a8264 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "bridgic-browser" -version = "0.0.5.dev15" +version = "0.0.5" license = {text = "MIT"} classifiers = [ "Programming Language :: Python :: 3.10", diff --git a/tests/unit/test_browser.py b/tests/unit/test_browser.py index d75a2fb..ef88e2b 100644 --- a/tests/unit/test_browser.py +++ b/tests/unit/test_browser.py @@ -280,6 +280,39 @@ def test_launch_options_stealth_disabled_headless_unchanged(self): assert options["headless"] is True + def test_launch_options_headed_auto_switches_to_system_chrome(self): + """Headed mode auto-switches to system Chrome when available. + + Bundled Chrome for Testing is blocked by Google OAuth and has been + observed self-trapping (EXC_BREAKPOINT/SIGTRAP bug_type=309) in + headed mode. The switch must happen regardless of stealth setting. + """ + with patch("bridgic.browser.session._browser._detect_system_chrome", return_value=True): + browser = Browser(headless=False, stealth=False) + options = browser._get_launch_options() + assert options.get("channel") == "chrome" + + def test_launch_options_headless_no_auto_switch(self): + """Headless mode does NOT auto-switch — bundled Chromium is fine.""" + with patch("bridgic.browser.session._browser._detect_system_chrome", return_value=True): + browser = Browser(headless=True, stealth=False) + options = browser._get_launch_options() + assert "channel" not in options + + def test_launch_options_headed_user_channel_preserved(self): + """User-pinned channel wins over auto-switch (no override).""" + with patch("bridgic.browser.session._browser._detect_system_chrome", return_value=True): + browser = Browser(headless=False, stealth=False, channel="chrome-beta") + options = browser._get_launch_options() + assert options.get("channel") == "chrome-beta" + + def test_launch_options_headed_no_system_chrome_no_switch(self): + """No system Chrome installed → no auto-switch (would fail with bad channel).""" + with patch("bridgic.browser.session._browser._detect_system_chrome", return_value=False): + browser = Browser(headless=False, stealth=False) + options = browser._get_launch_options() + assert "channel" not in options + class TestBrowserContextOptions: """Tests for Browser context options generation.""" diff --git a/uv.lock b/uv.lock index ed1f068..16afcae 100644 --- a/uv.lock +++ b/uv.lock @@ -196,7 +196,7 @@ wheels = [ [[package]] name = "bridgic-browser" -version = "0.0.5.dev15" +version = "0.0.5" source = { editable = "." } dependencies = [ { name = "bridgic-core" },