关闭 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 远程调试协议初探

    结语

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

    上一篇返回首页 下一篇

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

    别人在看

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

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

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

    帝国CMS7.5编辑器上传图片取消宽高的三种方法

    帝国cms如何自动生成缩略图的实现方法

    Windows 12即将到来,将彻底改变人机交互

    帝国CMS 7.5忘记登陆账号密码怎么办?可以phpmyadmin中重置管理员密码

    帝国CMS 7.5 后台编辑器换行,修改回车键br换行为p标签

    Windows 11 版本与 Windows 10比较,新功能一览

    Windows 11激活产品密钥收集及专业版激活方法

    IT头条

    无线路由大厂 TP-Link突然大裁员:补偿N+3

    02:39

    Meta 千万美金招募AI高级人才

    00:22

    更容易爆炸?罗马仕充电宝被北京多所高校禁用,公司紧急回应

    17:19

    天衍”量子计算云平台,“超算+量算” 告别“算力孤岛时代”

    18:18

    华为Pura80系列新机预热,余承东力赞其复杂光线下的视频拍摄实力

    01:28

    技术热点

    MySQL基本调度策略浅析

    MySQL使用INSERT插入多条记录

    SQL Server高可用的常见问题

    3D立体图片展示幻灯片JS特效

    windows 7上网看视频出现绿屏的原因及解决方法

    windows 7 64位系统的HOSTS文件在哪里?想用它加快域名解析

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

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