关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » UI前端 »Webkit 远程调试协议初探教程

    Webkit 远程调试协议初探教程

    2015-11-22 00:00:00 出处:github
    分享

    任何做过 Web 开发的同学,都避免不了在浏览器内进行调试。而大部分同学的首选工具,就是 Chrome DevTools。DevTools 本身我们无需多说,是一个大家不能再熟悉的工具了。但是埋藏在 DevTools 下面的开放协议以及它赋予的众多可能性,至今仍未见到充分的剖析和应用。

    Webkit 的远程调试协议是 Webkit 在 2012 年引入的。目前所有 Webkit 内核的浏览器都支持这一特性。但是我们还是以 DevTools 和 Chrome 为出发点,来做讨论。

    Webkit 远程调试协议初探

    为什么我们关注 DevTools:

    原因 1:DevTools 是开源项目

    DevTools 的源码就在 Google 的 blink 项目 中,高度的开放。目前这么多丰富的功能,正是 Google 和其社区的共同贡献。同时它的 License 也不拒绝任何的二次开发。

    原因 2:它足够简单

    DevTools 仅仅是简单的由 HTML、JavaScript、CSS、Images 组成的,本质上就是一个 WebApp,纯粹的前端应用。当你去了解、修改它时,你不需要理解 C++ 和任何编译的知识。

    原因 3:它的应用架构足够开放,满足任何形式的功能扩展。

    事实上 Devtools 是一个充分模块化的 JavaScript 网页应用。它的每个功能你都可以去扩展(仅需要了解 JavaScript)。

    原因 4:大部分前端都已经习惯它并且喜欢它。

    Webkit 的远程调试特性

    谈到远程调试前,有必要先了解各组件之间的关系。

    Webkit 远程调试协议初探

    浏览器拥有多个 Tab,并为每个 Tab 单独提供 WebSocket 的 Endpoint URI 每个 DevTool 实例只能检视一个 Tab,即只能与一个 Tab 保持通讯

    DevTools 的界面是数据驱动的。数据的来源就是 WebSocket API。Google 对 Webkit 的调试协议做了进一步的封装,提供了以 JSON 为序列化格式的 WebSocket 界面。

    大家在本地电脑上就可以体验这个远程调试是怎样一回事。执行如下步骤:

    彻底关闭当前 Chrome 进程 在 Chrome 的启动参数上加上 –remote-debugging-port=9222,例如 Mac 平台:
    open -a Google/ Chrome –args –remote-debugging-port=9222
    在开启的 Chrome 浏览器里打开任意网页,例如:http://www.taobao.com/ 在其他浏览器或者 Chrome 的新 Tab 打开 http://localhost:9222,你会得到这样的界面:

    Webkit 远程调试协议初探

    点击 “淘宝网” 的方框,就进入页面的调试界面了:

    Webkit 远程调试协议初探

    注意看地址栏,我们访问的是一个标准的 HTTP 协议下的网页,不是 Chrome 的私有协议。这里,你可以用 DevTools 再次检视这个页面,即按下 CMD + OPTION + i。你会发现,这真的就是一个 HTML 应用。

    再观察一下这个 URL:

    http://localhost:9222/devtools/inspector.html ws=localhost:9222/devtools/page/06D198AC-907F-430C-999C-16CCD7D2D489

    通过 QueryString,我们告诉了 DevTools 的前端应用,它应该连接到哪个 WebSocket 服务。

    你可以再你刚打开的检视 DevTools 的 DevTools(好绕口)里面,观察整个调试过程中的 WebSocket 通讯。例如:

    Webkit 远程调试协议初探

    以前用 WebSocket 做过 RPC 的同学应该看得出来,Google 实现的的确就是一个远程调用的接口。这个接口里面有两种通讯模式:

    request/response:就如同一个异步调用,通过请求的信息,获取相应的返回结果。这样的通讯必然有一个 message id,否则两方都无法正确的判断请求和返回的匹配状况。 notification:和第一种不同,这种模式用于由一方单方面的通知另一方某个信息。和 “事件” 的概念类似。

    实验一:通过调试协议获取页面加载的 Timeline 数据

    通过调试协议来获取页面加载的所有网络请求并打印。为了简单,我们编写一个 Node.js 的应用来实现。大致步骤如下:

    用 WebSocket 客户端连接调试服务 分别监听Network.requestWillBeSent、Network.loadingFailed、Network.loadingFinished、Network.responseReceived、Network.requestServedFromCache 的 Notification,并且打印相关的 log。 发送 Page.navigate 的请求,将页面跳转到某个页面,例如:http://www.taobao.com/

    这里拿到的数据足以绘制一个非常准确的页面加载的瀑布图。从调试协议里拿到的数据具有以下特点:

    准确,这是 Webkit 内核反馈的数据;而不是外层 JavaScript 接口的统计,也不是通过代理监控网络数据拿到的结果。 丰富,有很多数据,别的方法根本拿不到。例如,缓存状况、JavaScript 方法执行情况。 标准,调试协议本身已经定义了大量的 JSON 数据结构,你不需要再次进行抽象设计。

    完整代码如下(请先安装好相应的 npm 模块,并且打开 Chrome 本地的 9222 调试端口):

    var WebSocketClient = require("websocket").client,
        util = require("util"),
        EE = require("events").EventEmitter,
        request = require("request"),
        chalk = require("chalk"),
        exec = require("child_process").exec;
    
    // `Commander` class is message handler that talks to debug service exposed by Chrome
    var Commander = function(conn) {
      EE.call(this);
      this.connection = conn;
      this.sendCommands = [];
      var self = this;
      Object.defineProperty(this, "nextMsgId", {
        get: function() {
          return self.sendCommands.length;
        },
        enumerable: true,
        configurable: false
      });
      conn.on("message", this.onMessage.bind(this));
    };
    util.inherits(Commander, EE);
    
    // Send message using websocket connection
    Commander.prototype.send = function(method, params, callback) {
      this.sendCommands.push([method, params, callback]);
      var msg = JSON.stringify({
        id: this.nextMsgId,
        method: method,
        params: params
      });
      console.log(msg);
      this.connection.send(msg);
    };
    
    //handler for receiving a message
    Commander.prototype.onMessage = function(msg) {
      var command, data;
      if(msg.type === "utf8") {
        data = JSON.parse(msg.utf8Data);
        if(data.id) {//it's method request/response invocation
          command = this.sendCommands[data.id-1];
          if(command) {
            if(command.callback) {
              command.callback(data.params);
            }
          } else {
            console.warn("unmatched message id %s", data.id);
          }
        } else {//notifications
          this.emit(data.method, data.params);
        }
      } else {
        console.warn("message of unknown encoding");
      }
    };
    
    //find tab info
    request("http://localhost:9222/json", function(e, res, data) {
      data = JSON.parse(data);
      var url = data[0].webSocketDebuggerUrl;
      if(!url) {
        throw new Error("no url");
      }
    
      var client = new WebSocketClient();
    
      //once it's connect, start our actions
      client.on("connect", function(conn) {
        console.log("client connceted");
        var commander = new Commander(conn);
    
        //Shoud enable this freatures
        commander.send("Network.enable",{});
        commander.send("Page.enable",{});
    
        //Listen to wanted notifications
        commander.on("Network.requestWillBeSent", function(data) {
          console.log("[%s] %s %s: %s", chalk.green(data.timestamp), chalk.blue("WillSend"), data.requestId, data.request.url);
        });
        commander.on("Network.loadingFailed", function(data) {
          console.log("[%s] %s %s", chalk.green(data.timestamp), chalk.red("LoadFail"), data.requestId);
        });
        commander.on("Network.loadingFinished", function(data) {
          console.log("[%s] %s %s", chalk.green(data.timestamp), chalk.magenta("LoadDone"), data.requestId);
        });
        commander.on("Network.responseReceived", function(data) {
          console.log("[%s] %s %s: %s Status %s %s", chalk.cyan(data.timestamp), chalk.red("RespRecv"), data.requestId, data.type, data.response.status, data.response.headers["Content-Length"]);
        });
        commander.on("Network.requestServedFromCache", function(data) {
          console.log("%s %s", chalk.gray(data.timestamp), chalk.red("RespCache"), data.requestId);
        });
    
        commander.on("Page.domContentEventFired", function() {
          console.log(chalk.bgGreen("OnDOMContentLoad/t/t/t/t/t/t/t/t"));
        });
    
        commander.on("Page.loadEventFired", function() {
          console.log(chalk.bgCyan("OnLoad/t/t/t/t/t/t/t/t"));
        });
    
        //Navigate to target page
        commander.send("Page.navigate", {url: "http://www.taobao.com"});
    
      });
    
      client.connect(url);
    
    });

    运行后的结果如下:

    Webkit 远程调试协议初探

    结语

    该文内容仅仅介绍调试协议这个概念,以及它的通讯原理。并且,我们通过一个实验,来展示这套协议的强大特性。后面,我们还会讨论其他浏览器的调试协议,以及移动设备的调试。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。