Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions bridgic/browser/session/_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
33 changes: 33 additions & 0 deletions tests/unit/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading