zoukankan      html  css  js  c++  java
  • Chrome 请求过滤扩展实现

    目录

    引子

    接着 Chrome 扩展 : 入门,接下来开始实现一开始自己的想法:网络请求过滤。简单的说就是监听某个网站的所有请求,把想要的请求在扩展插件中展示出来。扩展名为 Capture Request 。

    需求具体化

    上面的想法比较模糊,为了达到这个目的,结合文档的示例,要做的有:

    1. 扩展要有对应的图标及提示。
    2. 点击工具栏扩展图标,打开一个新的 Tab 页面,用来展示请求的相关信息。
    3. 扩展监听处于激活 Tab 的网站请求,可以配置过滤监听的网址。
    4. 对监听的请求,支持根据 url 筛选并导出。

    有些功能不方便直接在文档找到,这个时候,建议在 Chrome 商店找一个开源扩展,根据效果看里面用的一些 API ,然后找到对应文档。这里参考了 FeHelper 里面的一些实现。需要注意到是 FeHelper 开发基于 manifest_version 版本为 2 ,以下开发扩展基于的版本是推荐的版本为 3 ,完整代码见 Capture Request

    实现

    图标相关信息配置

    按照入门里面介绍的信息,图标可能出现的地方有工具栏、扩展管理页、权限警告和 favicon 上,在 manifest.json 中配置的下面相关字段:

    {
      "name": "Capture Request",
      "description": "Capture Request",
      "version": "1.0",
      "manifest_version": 3,
      "action": {
        "default_icon": {
          "16": "xxx.png",
          "32": "xxx.png",
        }
      },
      "icons":{
        "16": "xxx.png",
        "32": "xxx.png",
      }
    }
    

    什么尺寸图标用在什么地方的详细说明在这里,文档上推荐用 PNG 的图片格式。按照这个来,发现有的图标太小了会看起来明显模糊,也可以用比较大的尺寸,Chrome 会自己把图片压缩到需要的尺寸。

    点击扩展打开新 Tab 页面

    入门里面点击扩展的展现形式是打开了一个弹窗,在文档 Design the user interface 中介绍的形式有 Popup 、Tooltip、Omnibox、Context menu、Override pages ,最有可能就是 Override pages ,但试了一下发现没有效果,于是去看别人的实现,发现可以通过监听点击图标事件打开新 Tab 。

    但看似可以直接用的 API ,实际上还有下面几点要考虑:

    1. 在哪里监听这事件?
    2. 什么时候监听这个事件?
    3. 怎么打开新 Tab ?
    4. 是否需要权限,如果需要,涉及那些权限?

    入门里面添加功能是通过后台脚本,文档开头说的一句个人觉得很重要:

    扩展是通过基于事件编程来改变或增强 Chrome 浏览体验。

    从文档中可以发现,在后台脚本中可以解决上面提的第 1、2 两个问题,需要的权限是 scripting

    打开 Tab 使用的 API 是 chrome.tabs ,需要的权限是 tabs

    主要做法是在 manifest.json 中添加下面配置:

    {
      ...
    + "permissions": [
    +   "scripting",
    +   "tabs",
    + ],
    + "background": {
    +   "service_worker": "background.js"
    + },
      ...
    }
    
    

    然后新建后台脚本文件 background.js ,并添加下面主要逻辑代码:

    chrome.action.onClicked.addListener(() => {
      chrome.tabs.create({
        url: 'page.html'
      });
    });
    

    监听请求及配置

    要把处于激活 Tab 网站上的请求显示到打开的扩展页面上,主要需要考虑的点有:

    1. 怎么找到激活的 Tab ?
    2. 怎么截获网页请求?
    3. 截获的请求怎么同步到扩展自定义页面上?

    通过上面打开 Tab 的效果实现,可以联想到相关的 API 应该也在 chrome.tabs 中,发现提供了 query 方法可以解决第 1 个问题。

    截获请求的方法通过网上搜索,发现文档 chrome.webRequest ,里面详细的介绍了扩展中请求的生命周期及触发的事件,经过对比思考,个人最后决定监听 onResponseStarted 事件,需要的权限是 webRequest 。这样就解决了第 2 个问题。

    参照入门里面改变颜色的方式,类似的可以把请求缓存到 chrome.storage ,然后在扩展页面获取,需要的权限是 storage 。关于数据同步,可以通过监听 chrome.storage.onChanged 事件拿到变动的最新数据。这样就解决了第 3 个问题。

    在调试的过程中,发现存在本地的数据使用 chrome.storage.sync 时,请求达到一定量后,会报错。看了文档发现这种方式的最大值有一定的限制,不太适合存储大量请求数据的场景,使用 chrome.storage.local 更加合适。

    配置过滤请求的方式可直接按照入门里面的配置方式处理,但有一点需要注意的是,每当配置更新的时候,需要重新监听 onResponseStarted 事件。

    主要做法是在 manifest.jsonpermissions 字段中添加 webRequeststorage

    background.js 中添加主要代码:

    // 储存请求数据默认值
    let requestList = []
    // 网址过滤的默认值
    let urlPattern = '<all_urls>'
    
    // 监听请求事件的处理程序
    const handlerResponseStarted = (details) => {
      // 找到处于激活状态的 Tab
      chrome.tabs.query({ active: true }, (tab) => {
        requestList.unshift(details)
        chrome.storage.local.set({ requestList });
        return { cancel: true };
      })
    }
    
    // 监听 storage 改变事件
    chrome.storage.onChanged.addListener((changeObj, areaName) => {
      const { urlPattern } = changeObj
      // 由于在 page.html 里面也监听了,所以要判断是不是 urlPattern 变动了
      if (areaName !== 'local' || !urlPattern) {
        console.warn('urlPattern does not change')
        return;
      }
      const { newValue } = urlPattern
      const hasAddListen = chrome.webRequest.onResponseStarted.hasListener(handlerResponseStarted)
      if (hasAddListen) {
        chrome.webRequest.onResponseStarted.removeListener(handlerResponseStarted);
      }
      chrome.webRequest.onResponseStarted.addListener(
        handlerResponseStarted,
        { urls: [newValue] },
      );
    })
    

    为扩展页面 page.html 添加脚本文件 pages.js ,添加关键逻辑:

      chrome.storage.onChanged.addListener((changeObj, areaName) => {
        const { requestList } = changeObj
        // 由于在 background.js 里面也监听了,所以要判断是不是 requestList 变动了
        if (areaName !== 'local' || !requestList) {
          console.warn('requestList does not change')
          return;
        }
        const { newValue } = requestList || { newValue: [] }
        const newItem = newValue[0] || null
        if (!newItem) {
          console.warn('no data')
          return;
        }
        // 显示数据的逻辑
        showData(newItem)
      })
    

    导出数据

    截获了想要的数据,有需要导出到本地使用的场景,参考 FeHelper 里面的实现,找到了文档 chrome.downloads ,需要的权限是 downloads

    主要做法是在 manifest.jsonpermissions 字段中添加 downloads

    pages.js 添加关键逻辑:

      let localFilterList = []; // 页面筛选后的数据
      // 点击导出的按钮
      const exportEle = document.querySelector('#operate-export')
      exportEle.addEventListener('click', () => {
        if (!localFilterList.length) {
          alert('无有效数据')
          return;
        }
        const txt = JSON.stringify(localFilterList)
        let blob = new Blob([txt], { type: 'application/octet-stream' });
        // 文件名称获取时间的秒数,可按照自己喜好定义
        let dt = (new Date()).getSeconds();
        chrome.downloads.download({
          url: URL.createObjectURL(blob),
          saveAs: true,
          conflictAction: 'overwrite',
          filename: dt + '.json'
        });
      })
    

    参考资料

  • 相关阅读:
    JDBC数据库连接池的实现
    在java项目中引入dll文件
    动态调用WebService(支持SaopHeader)
    获取CPU,硬盘,网卡信息
    js调用本地程序
    ClickOnce发布的一点小经验总结
    为程序设置快捷键
    构建返回友好信息的WebService
    使用DataReader分页的测试
    【bug】internal class GetCountOfEntitiesByCriterionHibernateCallback : IHibernateCallback<int>
  • 原文地址:https://www.cnblogs.com/thyshare/p/14728019.html
Copyright © 2011-2022 走看看