背景

某一天,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 远程调试协议分析与实战相关推荐

  1. 通过Webkit远程调试协议监听网页崩溃

    背景介绍 因为正在开发一个项目,而这个项目使用到了puppeteer,其中有个功能是在puppeteer打开的chrome里打开多个Tab,并进行管理. 虽然puppeteer可以打开多个网站,但是并 ...

  2. 小花仙 通过远程Chrome远程调试来高清截图

    鄙人一直在竭力简化小花仙高清截图的操作步骤.这次再来尝试使用原生的Chrome远程调试来操作CDP的指令. 参考之前的文章python selenium chrome 控制devtools 一些线索将 ...

  3. 【解决方案】三星手机使用chrome远程调试失败

    问题描述 使用机型 三星note8.三星s8 操作步骤 在chrome输入: chrome://inspect/#devices 使用chrome远程调试失败,inspect没有显示 解决方法 在手机 ...

  4. 如何通过Chrome远程调试Android上的Web页面

    这里写自定义目录标题 准备工作 手机端打开USB调试模式 Chrome远程调试Android手机 准备工作 安卓手机(打开USB调试模式,USB链接电脑) PC端打开chrome浏览器 手机端打开US ...

  5. chrome android 远程调试,chrome 远程调试

    方式一: 远程调式手机的chrome浏览器 Chrome DevTools调试移动设备Brower Page Tabs/WebViews 安卓远程调试目前支持所有操作系统(Windows,Mac, L ...

  6. 移动端Web开发调试之Chrome远程调试(Remote Debugging)

    ​ 一.工具 安卓手机 + USB数据线 + windows 系统电脑 二.调试 1)用数据线连接手机.电脑 手机确保开启USB调试模式[不同机型设置不同], eg: 华为手机[设置 --> 开 ...

  7. NFS协议分析——wireshark实战

    [理论课程FTP协议与NFS协议] 实验目的 1.NFS协议的应用范围 ??文件读写的时候? 2.NFS挂载操作的原理 整个协议,与文件的读写有什么关联?? 3.NFS的安全机制 NFS的安全机制到底 ...

  8. GDB 远程调试试验(gdbserver)【ZT】

    一.基本原理 调试器是运行在host pc机的应用程序, 被调试的程序是运行在target上. 插桩(stub):在目标操作系统和调试器内分别加入某些功能模块,二者互通信息来进行调试. 调试器与被调程 ...

  9. 鲲鹏Devkit编译调试工具课堂笔记—第二讲:手把手带你使用编译调试工具进行代码远程调试

    华为账号hw_Zixin,严禁直接盗用侵权! 一.学习目标 ​​​​​​​ 二.远程编译调试介绍 鲲鹏编译调试插件(Kunpeng Complier Plugin)应运而生,作为一款集成于IDE中的插 ...

最新文章

  1. 个推通知栏修改_浙大一院五一劳动节放假通知!手机办住院手续!还有这些攻略不能错过!...
  2. windows server 2012 FTP 服务器 / 虚拟目录
  3. keras框架实现手写数字识别
  4. 语音识别基础知识_语音识别_CTI论坛
  5. Andrew Ng机器学习公开课笔记 -- 朴素贝叶斯算法
  6. 时间对象与字符串对象之间相互转换
  7. 服务器win10系统开机慢,Win10系统开机慢怎么办 windows10开机慢的解决方法
  8. layui表单元素的radio单选框问题
  9. Django之kindeditor
  10. 关于.NET异常 你应该知道的更多点
  11. 计算机操作系统第4版期末复习
  12. Cisco Webex share screen 显示黑屏解决方法
  13. 内存映射(Memory Map)
  14. linux中rpm命令,linux中rpm命令使用介绍
  15. 用计算机教学体育,体育教学中计算机的应用
  16. 紫薇~还记得大明湖畔的HTML5智力拼图吗?
  17. vue.js的快速入门使用
  18. 对公账户:企业银行结算账户
  19. 微信公众号自动回复机器人
  20. 【微信小程序】关于使用ECharts制作图表

热门文章

  1. 金华资产封存页面问题
  2. python中float可以和int计算吗_python 中int ,float,字符串的操作
  3. mysql server 5.7.16_mysql 5.7.16 安装配置方法图文教程(ubuntu 16.04)
  4. 如何优雅地停止Java进程
  5. java十进制转换成二进制数
  6. Mysql Workbench中EER Diagram逆向生成表
  7. Android开发笔记(七十)反编译初步
  8. Vue-router之路由参数传递
  9. Vue method与computed的区别
  10. JS----正则表达式