Skip to content

feat: 兼容 Chrome 136+ DevTools Remote Debugging 的 CDP 连接(WebSocket/TCP fallback)#186

Open
aquaqu-v246 wants to merge 1 commit intoepiral:mainfrom
aquaqu-v246:feat/cdp-websocket-fallback
Open

feat: 兼容 Chrome 136+ DevTools Remote Debugging 的 CDP 连接(WebSocket/TCP fallback)#186
aquaqu-v246 wants to merge 1 commit intoepiral:mainfrom
aquaqu-v246:feat/cdp-websocket-fallback

Conversation

@aquaqu-v246
Copy link
Copy Markdown
Contributor

背景

从 Chrome 136 版本开始,Chromium 出于安全考虑(防止恶意软件通过 CDP 窃取用户 Cookie/凭据),对默认 user profile 禁用了 HTTP 发现端点(/json/version/json/list),这些端点直接返回 404。

这导致 bb-browser 无法连接那些通过浏览器内置 DevTools 设置(chrome://inspect/#remote-debugging)开启远程调试的浏览器(如 Comet 浏览器等),因为当前代码依赖 /json/version 来判断 CDP 端口是否可用。

核心发现

虽然 HTTP 发现端点被禁用了,但 WebSocket CDP 端点(ws://host:port/devtools/browser)仍然完全可用,且支持全部 CDP 1.3 协议功能。

实际测试结果:

端点 结果
GET /json/version ❌ 404 Not Found
ws://host:port/devtools/browser ✅ 连接成功
Browser.getVersion ✅ 返回完整版本信息
Target.getTargets ✅ 返回所有页面 targets
页面操作(open/click/eval) ✅ 全功能正常

改动内容

1. CLI 端口探测:canConnect()(cdp-discovery.ts)

  • 原逻辑:仅通过 fetch("/json/version") 判断端口可用性
  • 新逻辑:HTTP 返回 404 后,fallback 到 TCP 端口检测net.connect
  • 使用 TCP 而非 WebSocket 探测,是为了避免触发浏览器弹出 CDP 权限确认框

2. Daemon 端口探测:discoverCdpPort()(index.ts)

  • 提取 canConnectCdp() 公共函数,复用 HTTP + TCP 双重检测逻辑
  • 消除了原有两处重复的 HTTP 检测代码

3. Daemon WebSocket 连接:doConnect()(cdp-connection.ts)

  • 原逻辑:必须通过 /json/version 获取 webSocketDebuggerUrl
  • 新逻辑:HTTP 获取失败时,直接构造 ws://host:port/devtools/browser 连接

关于权限弹框

Chrome 的 Remote Debugging 在首次 WebSocket 连接时会弹出用户确认框,这是安全机制,无法绕过。

本次改动通过将探测阶段的 WebSocket 改为 TCP,将弹框从 3 次减少到 1 次(仅在 daemon 建立真正的持久连接时弹出)。daemon 存活期间复用同一个连接,不会再弹。

测试结果

  • 现有单元测试:全部通过(daemon 106 pass / cli 24 pass / 0 fail)
  • 手动验证:openget titleget urlclose 全功能正常
  • 标准 --remote-debugging-port 工作流:无影响(优先走 HTTP 路径,仅在 HTTP 失败时 fallback)

Chrome 136+ disables HTTP discovery endpoints (/json/version) for
default user profiles while WebSocket CDP endpoints remain functional.
This affects browsers like Comet that enable remote debugging via
DevTools settings rather than --remote-debugging-port flag.

Changes:
- cli/cdp-discovery.ts: canConnect() falls back to TCP port check
  when HTTP /json/version returns 404
- daemon/index.ts: extract canConnectCdp() with same TCP fallback,
  used by discoverCdpPort()
- daemon/cdp-connection.ts: doConnect() constructs WebSocket URL
  directly (ws://host:port/devtools/browser) when HTTP discovery fails

TCP port checks (net.connect) are used instead of WebSocket probes
in discovery functions to avoid triggering browser CDP permission
prompts. Only the actual persistent connection in doConnect() uses
WebSocket, resulting in a single permission prompt per daemon session.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants