Skip to content
Open
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
54 changes: 50 additions & 4 deletions src/browser_harness/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,16 +734,62 @@ def _chrome_running():
return False


# Chromium-based browsers that honor the remote-debugging checkbox, in
# preference order: a user whose daily browser is Dia/Arc/Edge/Brave should be
# pointed at THAT browser, not Google Chrome. Each entry is
# (macOS application name, inspect-URL scheme) — Edge serves the inspector under
# ``edge://`` while the rest use ``chrome://``.
_CHROMIUM_MAC_APPS = (
("Dia", "chrome"),
("Arc", "chrome"),
("Microsoft Edge", "edge"),
("Brave Browser", "chrome"),
("Chromium", "chrome"),
("Helium", "chrome"),
("Google Chrome", "chrome"),
)


def _running_chromium_app():
"""(macOS) Best-effort: the running Chromium browser to drive for the
remote-debugging prompt, as ``(app_name, inspect_scheme)``.

Prefers a non-Chrome browser the user actually has open so we don't
force-open Google Chrome for Dia/Arc/Edge/Brave users (issue #425). Falls
back to Google Chrome when nothing matches. Returns ``None`` off macOS, where
callers use the generic ``webbrowser`` path instead.
"""
import platform, subprocess
if platform.system() != "Darwin":
return None
try:
out = subprocess.check_output(["ps", "-A", "-o", "comm="], text=True, timeout=5).lower()
except Exception:
out = ""
for name, scheme in _CHROMIUM_MAC_APPS:
if name.lower() in out:
return name, scheme
return "Google Chrome", "chrome"


def _open_chrome_inspect():
"""Open chrome://inspect/#remote-debugging so the user can tick the checkbox."""
"""Open ``<scheme>://inspect/#remote-debugging`` in the user's running
Chromium browser so they can tick the remote-debugging checkbox.

Previously hardcoded Google Chrome, which force-opened Chrome for users whose
daily browser is Dia/Arc/Edge/Brave (issue #425).
"""
import platform, subprocess, webbrowser
url = "chrome://inspect/#remote-debugging"
if platform.system() == "Darwin":
app = _running_chromium_app()
if app is not None:
name, scheme = app
url = f"{scheme}://inspect/#remote-debugging"
try:
subprocess.run([
"osascript",
"-e", 'tell application "Google Chrome" to activate',
"-e", f'tell application "Google Chrome" to open location "{url}"',
"-e", f'tell application "{name}" to activate',
"-e", f'tell application "{name}" to open location "{url}"',
], timeout=5, check=False)
return
except Exception:
Expand Down
54 changes: 54 additions & 0 deletions tests/unit/test_open_chrome_inspect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""Regression for #425: the remote-debugging recovery must target the user's
running Chromium browser (Dia/Arc/Edge/Brave/…), not force-open Google Chrome.
"""

import platform as _platform
import subprocess as _subprocess

from browser_harness import admin


def _force_mac_ps(monkeypatch, comm_output):
monkeypatch.setattr(_platform, "system", lambda: "Darwin")
monkeypatch.setattr(_subprocess, "check_output", lambda *a, **k: comm_output)


def test_running_chromium_app_prefers_non_chrome(monkeypatch):
_force_mac_ps(monkeypatch, "Dia\nGoogle Chrome\nFinder\n")
assert admin._running_chromium_app() == ("Dia", "chrome")


def test_running_chromium_app_edge_uses_edge_scheme(monkeypatch):
_force_mac_ps(monkeypatch, "Microsoft Edge\n")
assert admin._running_chromium_app() == ("Microsoft Edge", "edge")


def test_running_chromium_app_falls_back_to_chrome(monkeypatch):
_force_mac_ps(monkeypatch, "Finder\nSafari\n")
assert admin._running_chromium_app() == ("Google Chrome", "chrome")


def test_running_chromium_app_none_off_macos(monkeypatch):
monkeypatch.setattr(_platform, "system", lambda: "Linux")
assert admin._running_chromium_app() is None


def test_open_inspect_targets_detected_browser(monkeypatch):
monkeypatch.setattr(admin, "_running_chromium_app", lambda: ("Dia", "chrome"))
captured = {}
monkeypatch.setattr(_subprocess, "run", lambda args, **k: captured.setdefault("args", args))
admin._open_chrome_inspect()
joined = " ".join(captured.get("args", []))
assert 'tell application "Dia"' in joined
assert "chrome://inspect/#remote-debugging" in joined
assert "Google Chrome" not in joined


def test_open_inspect_edge_uses_edge_scheme(monkeypatch):
monkeypatch.setattr(admin, "_running_chromium_app", lambda: ("Microsoft Edge", "edge"))
captured = {}
monkeypatch.setattr(_subprocess, "run", lambda args, **k: captured.setdefault("args", args))
admin._open_chrome_inspect()
joined = " ".join(captured.get("args", []))
assert 'tell application "Microsoft Edge"' in joined
assert "edge://inspect/#remote-debugging" in joined