chrome 扩展:message passing 与 网络监控 笔记

3,305 阅读3分钟

用来练手的简单应用:淘宝秒杀插件

popup页面不允许执行行内script,所以需要在header中引入相关的script,而且只能是本地的

<head>
  <script type="text/javascript" src="popup.js"></script>
</head>
<body>
    <h1>淘宝秒杀插件</h1>
    <p>1.秒杀物品添加到购物车</p>
    <p>2.进入购物车页面,设置定时时间</p>
        <input class="round" type="text" placeholder="格式:1970-01-01 18:00 年-月-日 小时:分钟">
        <button class="round" id="test">添加</button>
    </div>
</body>

通过message API 在不同脚本间传递信息

popup->background:

​ popup可以调用background 的方法

个人测试使用ES6 箭头函数popup会无法识别bg中的方法,原因未知

//popup.js
const bg = chrome.extension.getBackgroundPage()
bg.test()//test是background.js定义的函数 

popup->content

由于content页面可能有多个,所以popup需要知道正在使用的是哪一个页面,然后再调用message api进行传递消息

//popup.js
chrome.tabs.query({ active: true, currentWindow: true },tabs=>{
  chrome.tabs.sendMessage(tabs[0].id,'msg content',res=>{
    //接受content 的返回信息
  })
})
//content.js
chrome.runtime.onMessage.addListener((request,sender,response)=>{
	  //request 为接收到的信息
  //sender 为发送者
  //response 为需要反馈给发送者的内容
})

Content->background

//content.js
chrome.runtime.sendMessage('msg content', response => {
  alert('content 接收到来自background的信息' + response)
})

//background.js
chrome.runtime.onMessage.addListener((request,sender,response)=>{
	//...
})

Background->Content

  1. Message API

    //background.js
    chrome.tabs.query({ active: true, currentWindow: true },tabs=>{
      chrome.tabs.sendMessage(tabs[0].id,'msg content',res=>{
        //接受content 的返回信息
      })
    })
    //content.js
    chrome.runtime.onMessage.addListener((request,sender,response)=>{
    	//...
    })
    
  2. 长连接,解决background->content :Receiving end not exists

    //content 创建连接
    const port = chrome.runtime.connect({name:"knockknock"})
    port.onMessage.addListener(listenMethod)
    //background 与其连接
    chrome.runtime.onConnect.addListener(port => {
      port.postMessage('networkComplete')
    })
    

脚本发送ajax 请求的方法

思路:在background.js 中定义ajax 方法,通过getBackgroundPage API 在popup中实现用户交互

简单例子:

//popup.js 监听点击事件(点击按钮,获取淘宝timestamp)
document.addEventListener('click', e => {
    let bg = chrome.extension.getBackgroundPage();
    bg.test()
})
//background.js
function test() {
    $.get("http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp", function (data) {
        alert(data.data.t)
    });
}

网络监控,拦截,与重定向

background/webRequest API

  • 能够监控Chrome的网络请求,实现重定向
  • persistent设置为true 保证一直运行
  1. 在manifest 中的permission 中添加

    {
          {
            "name": "My extension",
            ...
            "permissions": [
              "webRequest",
              "webRequestBlocking",//当想要拦截请求,必须添加这个字段
              "*://*.google.com/" //想要监听的域名,如果想要监听全局,则设置为:"https://*/*","http://*/*",
            ],
            ...
          }
    }
    
  2. web request 的生命周期

web request 的生命周期

可操作的生命周期

  • onBeforeRequest:当web请求发生后,这个事件在tcp 连接之前发生,用作取消请求和重定向
  • onBeforeSendHeaders:发生在 tcp header 初始化完成前,用作修改header
  • onHeadersReceived:用作修改 response header
  • onAuthRequired:当web 请求需要user认证的时候,用作提供认证信息

只能监听的生命周期

  • onCompleted:请求成功,常用来监听某个请求是否完成,执行相关操作
  • onErrorOccurred:请求失败

核心概念

    "background": {
        "scripts": [
            "lib/jquery.js",//使用jquery 需要将其在脚本的前面防止
            "background.js"
        ],
        "persistent": true//网络监控持续监控
    },

相关变量解释

var callback = function(details) {...};//接受参数detail为当前url请求的信息,信息量由opt_extraInfoSpec数组决定
var filter = {...};
var opt_extraInfoSpec = [...];//['blocking'] / ['asyncBlocking'] 

filter:指定 哪种请求 会被监听

允许的字段:url、types、tabID、window ID

urls:可以设置为"<all_urls>"*://www.google.com/foo*bar

types:"main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", or "other"

opt_extraInfoSpec:监听的模式,一般设置为blocking

callback 需要返回webRequest.BlockingResponse 相关信息 ,这样就能够实现取消请求、重定向、修改header、提供认证信息 等生命周期的方法

具体例子

block 所有来自www.evil.com的信息

chrome.webRequest.onBeforeRequest.addListener(
  detail=> {cancel: true},
  {urls: ["*://www.evil.com/*"]},
  ["blocking"]
);

重定向 指定网址:

// background.js
chrome.webRequest.onBeforeRequest.addListener(
  function (details) {
    const url = details.url;

    if (url ==='xxx') {
      return {redirectUrl: 'new url'}
    }

    return {cancel: false}
  },
  {urls: ["<all_urls>"]},
  ["blocking"]
)

监听某个请求是否完成

/**监控订单页面的网络请求 */
chrome.webRequest.onCompleted.addListener(details => {
  //自定义操作。。。
}, { urls: ['*://buy.taobao.com/*', "https://buy.tmall.com/order/*"] }, [])