浏览器扩展的安全与约束

最近把我的一个扩展从 Manifest V2 迁移到Manifest V3,发现因CSP 安全政策,导致一些功能不可用,算是约束了自由。

Content script

Content script 通过浏览器扩展的 manifest.json 文件中的 content_scripts 字段指定。当用户打开一个匹配指定规则的页面时,浏览器会自动将 content_scripts 中指定的 JavaScript 代码注入到页面中。

注入的 content.js 代码段在页面加载完成后执行,content.js 的代码执行顺序是按照浏览器扩展中的 manifest.json 文件中的定义顺序执行的。

  1. “document_start”:在 DOM 树构建前(触发 DOMContentLoaded 事件前)执行;
  2. “document_end”:在 DOM 树构建完成后,但在子资源加载前执行;
  3. “document_idle”:在页面和子资源加载完成后,空闲时执行。
"content_scripts": [
  {
    "matches": ["https://www.example.com/*"],
    "js": ["content_scripts1.js"],
    "run_at": "document_start"
  },
  {
    "matches": ["https://www.example.com/*"],
    "js": ["content_scripts2.js"],
    "run_at": "document_end"
  }
]

因 Manifest V3 CSP 政策的限制

Chrome Manifest V3 限制了eval(code_str) new Function(code_str) 的使用,我想把一些动态的自定义脚本注入到 content.js 中执行,这在Manifest V3 中就被 CSP 政策阻止了。

这里是可以添加不必写死在扩展中的动态代码

最近的twitter Logo 由小蓝鸟换成了Elon Musk 最爱的狗头。很多人就不想看到这个狗头,写脚本换掉。用浏览器扩展的自定义脚本,就很容易,一行代码就可以。比如干脆把 Twitter 的 Logo 换成马一龙老板的头像。

如果不可以再这样灵活的注入动态代码,感觉就不好了。

Background

Chrome 的 Manifest V3 的 background 是 service worker 线程,所有页面的content.js, option.js 都可跟他通信,可以理解成一个后端,它可以管理着扩展的业务数据库。

// background.js
chrome.runtime.onConnect.addListener(function(port) {
  port.onMessage.addListener(request => { // 监听消息
    const type = request.type
    ...
      port.postMessage({ link: _res[request.cmd][0], type  }) // 响应消息
      ...

// content.js
const port2 = chrome.runtime.connect({name: "content-page"});
port2.postMessage({ type: "getpatterns" }); // 发送请求

port2.onMessage.addListener(response => { // 监听消息

localStorage 在Chrome Manifest V3 里用不了了,要用 chrome.storage.local.set chrome.storage.local.get

然而 Firefox 不支持在Manifest V3 中使用 service worker,而是使用 Event-driven background scripts,两套标准了。

https://extensionworkshop.com/documentation/develop/manifest-v3-migration-guide/

Chrome MV3 API: https://developer.chrome.com/docs/extensions/reference/