3.创建链接
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=./testpuppetter
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.duidaima.com/favicon.ico", "id": "428C9AC3F9B6AF7235CC41D849DD7589", "title": "堆代码", "type": "page", "url": "https://www.duidaima.com/", "webSocketDebuggerUrl": "ws://0.0.0.0:9222/devtools/page/428C9AC3F9B6AF7235CC41D849DD7589" } ]启动 cdp 客户端
此时打开 network,查看 ws ,可以看到 backend 端在接收 chrome-devtools-frontend 发送的 cdp 命令,并将 dom,network,资源信息返回给远程调试端
// 堆代码 duidaima.com 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 } }
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.debugger.onEvent.addListene: 监听指定选项卡页中的所有事件,在回调函数 response cdp 消息到 scocket 服务端。
5. 调用 chrome.debugger.onEvent.addListener,监听调试页的所有事件,转成 cdp 的消息结构 {method: method, params: params} ,发送消息事件名为 data.event 到代理服务器,最终转发到调试应用
此外社区还有 chobitsu 这样的 cdp 解析库,提供了 Storage、Runtime、Network、DOM、DOMDebugger、DOMStorage 的能力。与需要依赖在插件 background 层执行 chrome.debugger API 的方案不同。chobitsu 在浏览器运行时环境中手动实现了cdp 协议。 基于chobitsu 的能力可以实现待调试页面通过加载 backend.js 监听浏览器事件 执行 cdp 命令,实现 dom css network 的远程调试。 具体用例可以参考 devtools-pro 。由此方案进一步联想到xss安全的重要性。