Chrome 远程调试协议分析与实战
背景
某一天,A 君想获取 Chrome 页面中的性能数据,诸如时间、白屏和首屏等,因为需要和竞品进行对比分析,无法注入代码,该怎么办?
此时,你也许能想到开发者工具(DevTools),也许知道Timeline(包含浏览器完整的行为数据),该怎么自动获取到 Timeline 数据呢?
开发者工具
开发者工具(DevTools)是一个独立的 Web 应用程序(HTML+CSS+Javascript),被集成在浏览器中,通过远程调试协议(remote debugging protocol)和浏览器内核进行交互,直接使用 Ctrl+Shift+I 呼出。
可以在当前的浏览器页面直接打开 DevTools 调试,也可以在浏览器之外进行调试,本文的实战内容基于 PC 平台浏览器之外的远程调试。
远程调试协议
远程调试协议基于 WebSocket,利用 WebSocket 建立连接 DevTools 和浏览器内核的快速数据通道。DevTools 中的源代码(Main.js:220)如下:
var ws;
if ("ws" in WebInspector.queryParamsObject)ws = "ws://" + WebInspector.queryParamsObject.ws;
else if ("page" in WebInspector.queryParamsObject) {var page = WebInspector.queryParamsObject.page;var host = "host" in WebInspector.queryParamsObject ? WebInspector.queryParamsObject.host : window.location.host;ws = "ws://" + host + "/devtools/page/" + page;
}
该协议把操作划分为不同的域(domain),比如 DOM、Debugger、Network、Console 和 Timeline 等,可以理解为 DevTools 中的不同功能模块。
每个域(domain)定义了它所支持的 command 和它所产生的 event。
每个 command 包含 request 和 response 两部分,request 部分指定所要进行的操作以及操作说要的参数,response 部分表明操作状态,成功或失败。
command 和 event 中可能涉及到非基本数据类型,在 domain 中被归为 Type,比如:’frameId’: <FrameId>
,其中 FrameId 为非基本数据类型
至此,不难理解:
domain = command + event + type
远程调试协议应用场景
针对移动端的远程调试,因为移动平台一般都不会提供足够大的区域来显示 DevTools,必须要在手机浏览器之外进行远程调试,具体配置请参看这篇文章
获取 JS 的Runtime数据,常用的如window.performance和
window.chrome.loadTimes()
等获取Network及Timeline数据,进行自动性能分析
与强大的phantomjs合体,phantomjs 暂时只支持基于 remote debugging protocol 的调试,希望能支持 Network 及 Timeline 数据的获取,phantomjs 的最新技术请点击进入
远程调试协议结构
以 Page domain 为例
command 结构如下:
Page.navigate
request: {"id": <number>,"method": "Page.navigate","params": {"url": <string>}
}
response: {"id": <number>,"error": <object>
}
执行 Page.navigate 操作,需要参数 url,id 可以随意指定,不过要确认全局的唯一性,因为需要通过 id 关联 request 和 response。
event 结构如下:
Page.loadEventFired
{"method": "Page.loadEventFired","params": {"timestamp": <number>}
}
Page domain 派发 loadEventFired 事件结构数据(通过 WebSocket 的 onmessage 获取),并包含参数 timestamp
type 结构如下:
Frame: objectid ( string )Frame unique identifier.loaderId ( Network.LoaderId )Identifier of the loader associated with this frame.mimeType ( string )Frame document's mimeType as determined by the browser.name ( optional string )Frame's name as specified in the tag.parentId ( optional string )Parent frame identifier.securityOrigin ( string )Frame document's security origin.url ( string )Frame document's URL.
Frame type 为包含 id,loaderId,mimeType,name,parentId,securityOrigin 和 url 字段的 Object 数据类型,其中 loaderId 为另外一个定义在 Network domain 中的 type
更多协议内容请猛戳
注意:每次只能进行一次 WebSocket 连接,之后的连接都会失败
调用 Command
WebSocket 通道建立完成之后,通过如下方式进行调用:
打开指定页面,并进行事件监听(以 Page.loadEventFired 为例):
ws.onmessage = function(event) {console.log(event.data);
};
ws.send('{"id": 1, "method": "Page.navigate", "params": {"url": "http://www.baidu.com"}}')
获取到的 loadEventFired 事件数据如下:
{"method": "Page.loadEventFired", "params": {"timestamp": 1402317772.874949}}
更多连接方式
nodejs ws
非常轻量级的 WebSocket 库,支持 client 端和 server 端,使用方式基本同 HTML5 的标准 WebSocket 库
client 示例:
var WebSocket = require('ws');
var ws = new WebSocket('ws://www.host.com/path');
ws.on('open', function() {ws.send('something');
});
ws.on('message', function(data, flags) {// flags.binary will be set if a binary data is received// flags.masked will be set if the data was masked
});
server 示例:
var WebSocketServer = require('ws').Server, wss = new WebSocketServer({port: 8080});wss.on('connection', function(ws) {ws.on('message', function(message) {console.log('received: %s', message);});ws.send('something');});
请移步:
官方 ws 库
nodejs chrome-remote-interface
一个实现了 remote debugging protocol 的 nodejs 库,其中 WebSocket 使用的是 ws 库,使用方便,推荐使用
示例代码:
var Chrome = require('chrome-remote-interface');
Chrome(function (chrome) {with (chrome) {on('Page.loadEventFired', function(time) {send('Runtime.evaluate',{'expression': 'chrome.loadTimes()', returnByValue: true}, function(err, result) {//console.log(err, result );});});Page.enable();Page.navigate({'url': 'http://www.baidu.com'});}
});
请移步:官方 chrome-remote-interface
nodejs socket.io
功能强大,支持集成 WebSocket 服务器端和 Express3 框架与一身,使用简单,有兴趣者请移步:官方 socket.io
WebSocket
协议
它是 HTML5 一种新的协议,实现了浏览器与服务器全双工通信,只需要一个握手动作,浏览器和服务器之间就形成了一个快速通道,然后进行数据互传。
优点:
1、交互时的 header 只有约 2Bytes
2、服务端可以主动推送数据给客户端
header 格式(握手时):
request:
Cache-Control:no-cache
Connection:Upgrade
Host:localhost:9222
Origin:http://family.baidu.com
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits, x-webkit-deflate-frame
Sec-WebSocket-Key:TKSQVug6zSIH4uzIyTYBcg==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1914.0 Safari/537.36
response:
Connection:Upgrade
Sec-WebSocket-Accept:HyjfMUpyYgWgkYLn/vDDf6rZLuk=
Upgrade:WebSocket
header 格式(交互时):
request:
User-Agent: Fiddler
Content-Type: application/json; charset=utf-8
Host: fakewebsocket
Content-Length: 211
response:
FiddlerTemplate: True
Date: Fri, 25 Jan 2013 16:49:29 GMT
Content-Length: 51
查看 WebSocket 连接
DevTools
直接使用 DevTools,在控制台建立 WebSocket 连接并交互,在 Network 面板中直接显示
fiddler
自定义 fiddler 的规则,根据 WebSocket 特征提取信息并伪造 WebSocket 结构数据
因为伪造时,host 为 fakewebsocket,无法识别,所以通过 AutoResponder 伪造 respose 数据
请移步:Debug / Inspect WebSocket traffic with Fiddler
更多参考
- WebSocket 的原理及使用方法可参考阮一峰的新作:《JavaScript 标准参考教程(alpha)》
- 数据格式相关内容可参考:Real-time data exchange in HTML5 with WebSockets
- 具体的协议格式参考:官方
Chrome 远程调试协议分析与实战相关推荐
- 通过Webkit远程调试协议监听网页崩溃
背景介绍 因为正在开发一个项目,而这个项目使用到了puppeteer,其中有个功能是在puppeteer打开的chrome里打开多个Tab,并进行管理. 虽然puppeteer可以打开多个网站,但是并 ...
- 小花仙 通过远程Chrome远程调试来高清截图
鄙人一直在竭力简化小花仙高清截图的操作步骤.这次再来尝试使用原生的Chrome远程调试来操作CDP的指令. 参考之前的文章python selenium chrome 控制devtools 一些线索将 ...
- 【解决方案】三星手机使用chrome远程调试失败
问题描述 使用机型 三星note8.三星s8 操作步骤 在chrome输入: chrome://inspect/#devices 使用chrome远程调试失败,inspect没有显示 解决方法 在手机 ...
- 如何通过Chrome远程调试Android上的Web页面
这里写自定义目录标题 准备工作 手机端打开USB调试模式 Chrome远程调试Android手机 准备工作 安卓手机(打开USB调试模式,USB链接电脑) PC端打开chrome浏览器 手机端打开US ...
- chrome android 远程调试,chrome 远程调试
方式一: 远程调式手机的chrome浏览器 Chrome DevTools调试移动设备Brower Page Tabs/WebViews 安卓远程调试目前支持所有操作系统(Windows,Mac, L ...
- 移动端Web开发调试之Chrome远程调试(Remote Debugging)
一.工具 安卓手机 + USB数据线 + windows 系统电脑 二.调试 1)用数据线连接手机.电脑 手机确保开启USB调试模式[不同机型设置不同], eg: 华为手机[设置 --> 开 ...
- NFS协议分析——wireshark实战
[理论课程FTP协议与NFS协议] 实验目的 1.NFS协议的应用范围 ??文件读写的时候? 2.NFS挂载操作的原理 整个协议,与文件的读写有什么关联?? 3.NFS的安全机制 NFS的安全机制到底 ...
- GDB 远程调试试验(gdbserver)【ZT】
一.基本原理 调试器是运行在host pc机的应用程序, 被调试的程序是运行在target上. 插桩(stub):在目标操作系统和调试器内分别加入某些功能模块,二者互通信息来进行调试. 调试器与被调程 ...
- 鲲鹏Devkit编译调试工具课堂笔记—第二讲:手把手带你使用编译调试工具进行代码远程调试
华为账号hw_Zixin,严禁直接盗用侵权! 一.学习目标 二.远程编译调试介绍 鲲鹏编译调试插件(Kunpeng Complier Plugin)应运而生,作为一款集成于IDE中的插 ...
最新文章
- 个推通知栏修改_浙大一院五一劳动节放假通知!手机办住院手续!还有这些攻略不能错过!...
- windows server 2012 FTP 服务器 / 虚拟目录
- keras框架实现手写数字识别
- 语音识别基础知识_语音识别_CTI论坛
- Andrew Ng机器学习公开课笔记 -- 朴素贝叶斯算法
- 时间对象与字符串对象之间相互转换
- 服务器win10系统开机慢,Win10系统开机慢怎么办 windows10开机慢的解决方法
- layui表单元素的radio单选框问题
- Django之kindeditor
- 关于.NET异常 你应该知道的更多点
- 计算机操作系统第4版期末复习
- Cisco Webex share screen 显示黑屏解决方法
- 内存映射(Memory Map)
- linux中rpm命令,linux中rpm命令使用介绍
- 用计算机教学体育,体育教学中计算机的应用
- 紫薇~还记得大明湖畔的HTML5智力拼图吗?
- vue.js的快速入门使用
- 对公账户:企业银行结算账户
- 微信公众号自动回复机器人
- 【微信小程序】关于使用ECharts制作图表
热门文章
- 金华资产封存页面问题
- python中float可以和int计算吗_python 中int ,float,字符串的操作
- mysql server 5.7.16_mysql 5.7.16 安装配置方法图文教程(ubuntu 16.04)
- 如何优雅地停止Java进程
- java十进制转换成二进制数
- Mysql Workbench中EER Diagram逆向生成表
- Android开发笔记(七十)反编译初步
- Vue-router之路由参数传递
- Vue method与computed的区别
- JS----正则表达式