首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >cdp 远程调试方案

cdp 远程调试方案

作者头像
政采云前端团队
发布2022-04-27 10:03:44
2.1K0
发布2022-04-27 10:03:44
举报
文章被收录于专栏:采云轩采云轩

👆 这是第 140 篇不掺水的原创,想要了解更多,请戳下方卡片关注我们吧~

CDP 远程调试方案 https://www.zoo.team/article/cdp

什么是 cdp 协议

cdp 协议简称 chrome 调试协议,是基于 scoket(websocket、usb、adb )消息的 json rpc 协议。用来调用 chrome 内部的方法实现 js、css 、dom 的开发调试。 可以将实现了 cdp 协议的应用看做 rpc 调用的服务端( chrome 、puppeteer), 将调试面板看做 rpc 调用的客户端(devtools)。

devtools 调试系统

完整的调试系统分别由前端,后端,协议,通道四部分组成

  • Frontend:调试器前端,如 chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) 一个 web 应用,接收 cdp 事件 & 发送 cdp 命令,实现 dom、network、debugger 的执行调试。
  • Backend: 实现了 cdp 协议的应用,会接收 cdp 命令 & 发送 cdp 事件。Chromium、V8 或 Node.js
  • Protocol:cdp 调试协议,调试器前端和后端使用此协议通信。它分为代表被检查实体的语义方面的域。每个域定义类型、命令(从前端发送到后端的消息)和事件(从后端发送到前端的消息)。该协议基于 json rpc 2.0 运行;
  • Channels:消息通道,后端和前端之间发送协议消息的一种方式。包括:Embedder Channel、WebSocket Channel、Chrome Extensions Channel、USB/ADB Channel。

chrome 远程调试

如上,所有能够消费发送 cdp 消息的应用都可以被 chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) 调试。chrome 集成了 cdp 协议,所以只需要通过消息通道与 chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) 应用建立 socket 链接就可以被调试端调试。调试启动分为三步:

  • 启动 cdp 服务端
  • 启动 cdp 客户端
  • 创建链接

启动 cdp 服务端

以 chrome、puppetter 为例启动 backend 应用,设置调试端口 9222。

  • chrome
 /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=./test
  • puppetter
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: ['--remote-debugging-port=9222', '--remote-debugging-address=0.0.0.0'],
  });  const page = await browser.newPage();
 // let res= await page.goto('https://www.baidu.com');

  console.log(browser.wsEndpoint());
  // output -> ws://127.0.0.1:57724/devtools/browser/705082a5-19e6-4e9a-b8a6-477b7b6e1bd6
})();

此时访问 http://0.0.0.0:9222/json 此时可以获取调试页面 id 和页面的 webSocketDebuggerUrl ,代表 backend 端启动成功。

[ {
   "description": "",
   "devtoolsFrontendUrl": "/devtools/inspector.html?ws=0.0.0.0:9222/devtools/page/659E9C174913FC5670B5F6E78B6B91FD",
   "id": "659E9C174913FC5670B5F6E78B6B91FD",
   "title": "欢迎使用 Chrome",
   "type": "page",
   "url": "chrome://welcome/",
   "webSocketDebuggerUrl": "ws://0.0.0.0:9222/devtools/page/659E9C174913FC5670B5F6E78B6B91FD"
}, {
   "description": "",
   "devtoolsFrontendUrl": "/devtools/inspector.html?ws=0.0.0.0:9222/devtools/page/9902C5D5F55923DFC457B7AA423F957E",
   "faviconUrl": "https://cn.bing.com/sa/simg/favicon-2x.ico",
   "id": "9902C5D5F55923DFC457B7AA423F957E",
   "title": "必应",
   "type": "page",
   "url": "https://cn.bing.com/",
   "webSocketDebuggerUrl": "ws://0.0.0.0:9222/devtools/page/9902C5D5F55923DFC457B7AA423F957E"
}, {
   "description": "",
   "devtoolsFrontendUrl": "/devtools/inspector.html?ws=0.0.0.0:9222/devtools/page/428C9AC3F9B6AF7235CC41D849DD7589",
   "faviconUrl": "https://www.baidu.com/favicon.ico",
   "id": "428C9AC3F9B6AF7235CC41D849DD7589",
   "title": "百度一下,你就知道",
   "type": "page",
   "url": "https://www.baidu.com/",
   "webSocketDebuggerUrl": "ws://0.0.0.0:9222/devtools/page/428C9AC3F9B6AF7235CC41D849DD7589"
} ]

启动 cdp 客户端

chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) 作为一个纯 web 应用,可以通过 koa 部署访问。同时 chrome 默认也集成了 chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) 服务。在 cdp 服务端启动后可以直接访问 http://0.0.0.0:9222/devtools/inspector.html。

创建链接

传入 socket_backend_url ,http://0.0.0.0:9222/devtools/inspector.html?ws=${webSocketDebuggerUrl}

或者直接访问 http://0.0.0.0:9222/ 可以看到浏览器中的的 tab 线程页,点击需要调试的页面,http://0.0.0.0:9222/devtools/inspector.html?ws=0.0.0.0:9222/devtools/page/9902C5D5F55923DFC457B7AA423F957E , 就可以连接 chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) 调试了。

此时打开 network,查看 ws,可以看到 backend 端在接收 chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) 发送的 cdp 命令,并将 dom、network、资源信息返回给远程调试端

cdp协议结构

 cdp 协议按域「Domain」划分能力,每个域下有 Method、Event 和 Types。
([https://chromedevtools.github.io/devtools-protocol/tot/Debugger/](https://chromedevtools.github.io/devtools-protocol/tot/Debugger/) )

Method 对应 socket 通信的请求 / 响应模式,Events 对应 socket 通信的发布 / 订阅模式,Types 为交互中使用到的实体。

用远程执行一段 js 为例,在 chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) 控制台输入下面代码,backend 端分别收到执行三个 cdp 命令。Runtime.compileScript -> Runtime.evaluate -> Runtime.compileScript

pp=function(){
  alert(244)
}
pp()
{
    "id": 47,
    "method": "Runtime.evaluate",
    "params": {
        "expression": "pp=function(){alert(244)}",
        "includeCommandLineAPI": true,
        "generatePreview": true,
        "userGesture": false,
        "awaitPromise": false,
        "throwOnSideEffect": true,
        "timeout": 500,
        "disableBreaks": true,
        "replMode": true,
        "uniqueContextId": "-3083772769491583108.6833303176535544523"
    }
}
{
    "id": 178,
    "method": "Runtime.compileScript",
    "params": {
        "expression": "pp=function(){alert(244)}",
        "sourceURL": "",
        "persistScript": false,
        "executionContextId": 7
    }
}
{
    "id": 100,
    "method": "Runtime.compileScript",
    "params": {
        "expression": "pp()",
        "sourceURL": "",
        "persistScript": false,
        "executionContextId": 7
    }
}

手动实现

H5 端通过 cdp 协议调用调试

var ws = new WebSocket('ws://127.0.0.1:9222/devtools/page/620F91C22D41B614947001C52AC55E53');

window.ppp=function(){
// 调用 Command

  debugger
  ws.onmessage = function(event) {
    console.log(event.data);
    // 获取数据:{"method": "Page.loadEventFired", "params": {"timestamp": 1402317772.874949}}
  };
  ws.send('{"id": 1, "method": "Page.navigate", "params": {"url": "http://www.github.com"}}');
}

远程调试

chrome 社区提供了基础的远程调试方案 :devtools-remote(https://github.com/auchenberg/devtools-remote)。分别提供 websocket 服务做消息转发和 chrome 插件在 backend 端来监听执行发送 cdp 消息。

devtools-remote(https://github.com/auchenberg/devtools-remote) 调试插件在 background 层实现 cdp 消息监听, 响应和执行。主要依赖下面几个 api。Chrome Extensions Api(chrome.debugger(https://developer.chrome.com/docs/extensions/reference/debugger/#type-Debuggee)

  • chrome.debugger.getTargets:获取可调试目标的列表( tab_id )
  • chrome.debugger.attach:将调试器附加到指定目标。
  • chrome.debugger.sendCommand:将 cdp 命令发送至调试目标。
  • chrome.debugger.onEvent.addListene:监听指定选项卡页中的所有事件,再回调函数 response cdp 消息到 scocket 服务端。

插件内部逻辑实现

  1. 点击插件(chrome.browserAction.onClicked.addListener)获取当前页 tabID ,即目标 id.
  2. 调用 chrome.debugger.attach,将调试器附加到指定目标。
  3. socket connect 连接代理 websocket 服务器。(代理服务器连接调试应用 chrome-devtools-frontend(https://github.com/ChromeDevTools/devtools-frontend) )
  4. 插件连接成功:监听从代理服务器推送的 data.request 类型消息。调用 chrome.debugger.sendCommand 执行 cdp 协议的命令, 将执行结果返回给 socket 服务端消息事件名为 data.response 消息 id 保持一致)。
  5. 调用 chrome.debugger.onEvent.addListener,监听调试页的所有事件,转成 cdp 的消息结构 {method: method, params: params} ,发送消息事件名为 data.event 到代理服务器,最终转发到调试应用

socket_proxy 逻辑代理服务器的逻辑很简单,将来自插件端 'data.response' 、 'data.event' 的事件消息转发到调试应用上。将来自调试应用 'data.request' 事件消息转发到 backend 插件端。

此外社区还有 chobitsu 这样的 cdp 解析库,提供了 Storage、Runtime、Network、DOM、DOMDebugger、DOMStorage 的能力。与需要依赖在插件 background 层执行 chrome.debugger API 的方案不同。chobitsu 在浏览器运行时环境中手动实现了cdp 协议。 基于chobitsu 的能力可以实现待调试页面通过加载 backend.js 监听浏览器事件 执行 cdp 命令,实现 dom css network 的远程调试。具体用例可以参考 devtools-pro(https://github.com/wanwu/devtools-pro.git) 。由此方案进一步联想到 xss 安全的重要性。

同理 react-devtools 的实现方案,也与 cdp 方案类似, 在调试页面中引入或者通过插件插入 backend.js,监听变化发送到调试应用。

PS:之前我们有输出过在线调试的方法,链接是 前端工程师生产环境 debugger 技巧,感兴趣的同学可以点开看一下。

参考文档

chrome DevTools Protocol(https://chromedevtools.github.io/devtools-protocol/tot/Debugger/) chrome-remote-interface(https://github.com/cyrus-and/chrome-remote-interface) 深入理解 Chrome DevTools(https://zhaomenghuan.js.org/blog/chrome-devtools.html)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 政采云技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是 cdp 协议
  • devtools 调试系统
  • chrome 远程调试
    • 启动 cdp 服务端
      • 启动 cdp 客户端
        • 创建链接
          • H5 端通过 cdp 协议调用调试
      • cdp协议结构
      • 手动实现
        • 远程调试
        相关产品与服务
        远程调试
        远程调试(Remote Debugging,RD)在云端为用户提供上千台真实手机/定制机/模拟器设备,快速实现随时随地测试。运用云测技术对测试方式、操作体验进行了优化,具备多样性的测试能力,包括随时截图和记录调试日志,稳定的支持自动化测试, 设备灵活调度,用例高效执行, 快速定位产品功能和兼容性问题。云手机帮助应用、移动游戏快速发现和解决问题,节省百万硬件费用,加速敏捷研发流程。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档