入门 Chrome-EXT 的一些注意

我前几天做Chrome-EXT开发的时候,遇到一些坑。 Chrome扩展是有好几个沙盒环境一起协同工作的,如果你之前做过 IOS-WebView 的二次开发,应该有印象: JavaScript的注入,是有“World”概念的,默认是MAIN-World,这个就是网页的默认js执行环境。 然后还能自定义World,这种属于ISOLATED-World,和MAIN-World在同一个线程里面,但是内存是完全隔离的,类似于在一个独立的iframe环境中。

MAIN-World 有非常严格的安全限制。比如我就不能再MAIN-World里面去发起 ws://localhost 的链接。因为Google的网页非常注重安全,都会开启“内容安全协议限制”,比如不能Eval、new Function;以及MAIN-World的资源来源会有域名限制;甚至不可以和Chrome扩展的Servical-Worker通讯。

所以必须是这样的通讯路径: “网页脚本(MAIN-World) ⇄ content-script(ISOLATED-World) ⇄ background/service-worker” “网页脚本(MAIN-World) ⇄ content-script(ISOLATED-World) ⇄ backend-server/websocket”


以下是AI总结了一些区别:

content-script 到底有哪些“网页脚本做不到”的能力?

一句话:能跨域、能调扩展 API、能访问 Chrome 内部数据,但又不必暴露给页面
具体列出来:

能力页面脚本能否做到content-script 能否做到备注
访问任意扩展 API(chrome.runtime.sendMessagechrome.storagechrome.i18n…)页面脚本没有这些 API。
跨域请求(无视 CORS)只要在 manifest.json 里给 host 权限即可。
读取/修改 DOM,但不会被页面脚本看到(如果 Shadow DOM 方式注入)部分页面脚本无法直接访问 content-script 的变量。
注入到每一个匹配的页面,无需用户手动安装只要 URL 匹配,扩展安装后自动注入。
在页面加载早期(document_start)就执行可以抢在页面脚本之前跑。
通过 chrome.runtime.onMessage 与 background/popup 双向通讯页面脚本没有 chrome.runtime
使用 chrome.runtime.getURL 拿到扩展内部资源(图片、wasm、worker)页面脚本拿不到 chrome-extension:// 的内部 URL。
在 Manifest V3 下,使用 chrome.scripting.executeScript 动态注入到任意标签页面脚本无法调用扩展 API。

background service-worker 独有的“超能力”

能力说明
长期离线事件监听浏览器冷启动后仍能监听 chrome.runtime.onInstalled / chrome.alarms / chrome.webRequest
无前台限制的网络请求可跨域 fetch() 任意 URL(只要 host_permissions 里声明),不受 CORS 限制
webRequest/declarativeNetRequest拦截、修改、阻断整个浏览器的 HTTP 请求
管理浏览器级数据cookies、历史记录、书签、下载、代理设置、标签、窗口、扩展管理
后台定时任务chrome.alarms 可在浏览器重启后继续触发
native messaging与本地二进制程序建立长期双向通道
推送消息(GCM/FCM)接收云端推送,唤醒扩展
contextMenus右键菜单全局注册
** omnibox 关键字**地址栏关键字建议
chrome.storage.sessionMV3 新提供的会话级存储,content-script 无法直接访问
chrome.scripting.executeScript动态向任意标签页注入脚本,无需在 manifest 声明静态 content-script