拓展的执行环境

Chrome 的拓展架构中,background,content script,windows(已加载页面)是完全隔离的,彼此之间的变量,资源的等不允许访问。

并且,不同的拓展之间,不同的 content script 之间(即使在同一个拓展内)也是隔离的。

但他们之间可以通过 postMessage 或 sendMessage 通信。

background page

每个拓展都包含一个background page,是处理拓展主要逻辑的文件,注意这里的主要两字,后面会说道。

background page 有两种类型,一种是 persistent background pagesevent pages

Persistent background pages(持久后台页面),如名称所示,总是打开的。而 Event pages 会在需要时打开或关闭。除非你一定需要 background page 一直运行,否则最好使用 event page。

Persistent background pages 的代码在浏览器启动时执行一次,往后不再执行,里面绑定的事件会一直存在。

event page 的什么时候会被打开:

总的来说是“需要”的时候运行。

content script

假设拓展想要修改已加载页面的 DOM 等操作,只能通过 content script。不同的 content script 之间不能互相访问,同时也不能访问已加载页面的变量,反过来已加载页面也不能访问 content script ,他们的执行环境被完全隔离。

有哪几种加载 content script 的方法呢?

第一种,用编程方式在 background 运行

chrome.tabs.executeScript(null, { file: "checkEnable.js" });

chrome.tabs.executeScript(null, { code:'localStorage.setItem('token','4444')' });

第二种是在配置文件的 content_script 使用

  "content_scripts": [
    {
      "matches": ["http://*/*","https://*/*"],
      "js": ["jquery-3.2.1.min.js", "checked.js","textared.js"]
    }
  ]

manifest.json 内同一位置的 content script 可以互相访问变量,比如使用jquery。

而编程方式 executeScript 加载的 content script 是独立了,即不可以访问外部变量也无法被访问。

popup.html 内的 js 代码无法访问 manifest 的变量。

通信 DEMO

1、background.js 和 popup.js 向当前标签页的 content script 发送消息

//background.js
function sendMsg(obj){
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
        chrome.tabs.sendMessage(tabs[0].id,obj , function(response) {});  
    });
}

//content script 接收
chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {})

2、content script 向 backgroundjs 发送消息

//content script 
var msg = {
        type:'loginsuccess',
        username:localStorage.getItem('username'),
        token:localStorage.getItem('token')
    }
chrome.runtime.sendMessage(msg);

//background.js
chrome.runtime.onMessage.addListener(function(msg) {
    if(msg.type === 'loginsuccess'){
        localStorage.setItem('token',msg.token)
        localStorage.setItem('username',msg.username)
        chrome.tabs.executeScript(null, { file: "./contentScript/noteInit.js" });
        chrome.tabs.executeScript(null, { file: "./contentScript/checkEnable.js" });
    }
});



//content script 
var Msg = {
        type:'icon',
        "enable": !!nodeBox
    };
chrome.runtime.connect().postMessage(Msg);

//background.js
chrome.runtime.onConnect.addListener(function(port) {
  port.onMessage.addListener(function(msg) {
    if(msg.type === 'icon'){
        if(msg.enable){
        chrome.browserAction.setIcon({
            path: "./icons/16_active.png"
        });
        }else{
            chrome.browserAction.setIcon({
                path: "./icons/16.png"
            });
        }
    }
  });
});