最近把我的一个扩展从 Manifest V2 迁移到Manifest V3,发现因CSP 安全政策,导致一些功能不可用,算是约束了自由。
Content script
Content script 通过浏览器扩展的 manifest.json 文件中的 content_scripts 字段指定。当用户打开一个匹配指定规则的页面时,浏览器会自动将 content_scripts 中指定的 JavaScript 代码注入
到页面中。
注入的 content.js 代码段在页面加载完成后执行,content.js 的代码执行顺序是按照浏览器扩展中的 manifest.json 文件中的定义顺序执行的。
- “document_start”:在 DOM 树构建前(触发 DOMContentLoaded 事件前)执行;
- “document_end”:在 DOM 树构建完成后,但在子资源加载前执行;
- “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/