0

    [FE] 如何扩展Chrome DevTools来获取页面请求

    2023.04.29 | admin | 147次围观

    1. Chrome DevTools Extension

    熟悉React的同学,可能对React Developer Tools并不陌生,

    刚看到的时候,我也觉得很神奇,

    因为React Developer Tools和其他Chrome Extension不同,

    它居然出现在了Chrome开发者工具栏中,和原生的DevTools一样强大。

    例如,可以审查元素,查看元素的属性,等等。

    后来才知道,像这种出现在Chrome开发者工具栏中的扩展,称为Chrome DevTools Extension。

    比起普通的Chrome Extension,Chrome DevTools Extension可以访问更多API,例如,

    (1)devtools.inspectedWindow

    (2)devtools.network

    (3)devtools.panels

    其中包括了,与当前审查窗口相关的,与网络请求相关的,以及与开发者工具栏相关的API。

    2. 背景 & 基本概念

    在某一具体项目中,有一个这样的需求,

    我们需要选择页面中发起的http请求,然后将它们保存到数据库中。

    由于页面发起的请求可能会发往不同的服务器,所以在服务器端解决这个问题就显得比较麻烦,

    而编写一个Chrome DevTools Extension会更简单直接。

    下文我将这个功能的核心抽离出来,作为一个例子,来还原Chrome DevTools Extension的编写方法。

    为此,我们先熟悉几个基本的概念。

    (1)tab页

    Chrome浏览器是由tab页组成的,一个浏览器实例中可以打开多个tab页。

    (2)DevTools Window

    每个tab页,都可以打开自己的开发者工具窗口,称为DevTools Window。

    注意,每个tab页都有自己独立的DevTools Window,

    只是切换tab页的时候,只会显示当前tab页的DevTools Window。

    (3)DevTools Page 和 Panel

    下面我们来创建一个Chrome DevTools Extension项目,目录结构如下,

    chrome-devtools-extension-example
    ├── devtools.html    // DevTool Page
    ├── devtools.js      // DevTool Page中引用的js
    ├── manifest.json    // 入口
    ├── panel.html       // 开发者工具栏选项卡页面
    └── panel.js         // 选项卡页面中引用的js
    

    其中manifest.json是入口,它会声明一个对用户不可见的DevTools Page。

    在本例中为devtools.html,

    {
      "name": "PageRecorder",
      "version": "1.1.0",
      "minimum_chrome_version": "10.0",
      "description": "Record all http requests in a page.",
      "devtools_page": "devtools.html",
      "manifest_version": 2
    }
    

    DevTools Page引入的js,具有访问DevTools API的能力,

    包括上文提到的那些API,devtools.inspectedWindow,devtools.network,devtools.panels。

    DevTools Page对用户是不可见的,如果需要在开发者工具栏中创建新的DevTool选项卡,

    还需要在DevTools Page使用一下方法来创建,DevTool选项卡,官方称为Panel。

    原生的Panel包括,Elements,Console,Network,等等。

    // 创建一个Panel
    chrome.devtools.panels.create(
      // title
      'ChromeDevToolsExtensionExample',
      // iconPath
      null,
      // pagePath
      'panel.html'
    );
    

    以上js当前页面网络请求,我们在DevTool Page中创建了一个新的Panel,名字为ChromeDevToolsExtensionExample。

    其中,panel.html,我们只是简单的写了一个Hello World!。

    值得注意的是,每个Panel都可以加载自己的html,js和css,且具有和DevTools Page一样的权限。

    (4)Panel的生命周期

    Panel只有在第一次被激活的时候,才进行实例化,

    同一个DevTools Window中的不同Panel切换时,不会重新加载。

    当前tab页刷新时,Panel也不会重新加载。

    DevTools Window关闭后,Panel将被销毁。

    因此,我们要想使用Chrome DevTools Extension,就必须先打开开发者工具窗口js当前页面网络请求

    然后再激活我们新建的DevTools Panel。

    3. 监听请求

    上文我们提到了,Chrome DevTools Extension可以访问devtools.network API,

    现在我们来展示使用chrome.devtools.network.onRequestFinished.addListener来获取请求。

    为此,我们新建了一个panel.js文件,并在panel.html中引用它。

    // Chrome DevTools Extension中不能使用console.log
    const log = (...args) => chrome.devtools.inspectedWindow.eval(`
        console.log(...${JSON.stringify(args)});
    `);
    // 注册回调,每一个http请求响应后,都触发该回调
    chrome.devtools.network.onRequestFinished.addListener(async (...args) => {
        try {
            const [{
                // 请求的类型,查询参数,以及url
                request: { method, queryString, url },
                // 该方法可用于获取响应体
                getContent,
            }] = args;
            log(method, queryString, url);
            // 将callback转为await promise
            // warn: content在getContent回调函数中,而不是getContent的返回值
            const content = await new Promise((res, rej) => getContent(res));
            log(content);
        } catch (err) {
            log(err.stack || err.toString());
        }
    });
    

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    标签: 谷歌浏览器
    发表评论