Chrome扩展中设置为MAIN世界的内容脚本如何向后台脚本发送数据?
Chrome扩展中设置为MAIN世界的内容脚本如何向后台脚本发送数据?
你遇到的这个问题确实挺常见的——因为设置了world: "MAIN"的内容脚本运行在页面的主上下文里,这里没有Chrome扩展API的访问权限,所以chrome.runtime.sendMessage自然会返回undefined。不过别担心,我们可以通过自定义DOM事件+隔离世界内容脚本中转的方式来实现数据传递,具体做法如下:
核心思路
MAIN世界的脚本没法直接调用扩展API,但可以通过自定义DOM事件把数据传递给运行在「隔离世界」的内容脚本(这是Chrome扩展默认的内容脚本上下文,拥有完整的扩展API权限),再由隔离世界的脚本把数据转发给后台。
具体实现步骤
修改manifest.json,添加隔离世界的内容脚本
在原有的MAIN世界内容脚本配置外,新增一个默认隔离世界的内容脚本:"content_scripts": [ { "matches": ["<all_urls>"], "js": ["content-main.js"], // 原MAIN世界的脚本,重命名区分 "run_at": "document_start", "world": "MAIN" }, { "matches": ["<all_urls>"], "js": ["content-isolated.js"], // 新增的隔离世界脚本 "run_at": "document_start" } ]修改MAIN世界的脚本(content-main.js)
把原来调用chrome.runtime.sendMessage的逻辑,换成触发自定义DOM事件,把数据放在事件的detail属性里:listenerFn = (event) => { const url = event.target.responseURL; if (url.startsWith("https://example.com/api/v2/home/allfeed")) { // 创建自定义事件并携带数据 const transferEvent = new CustomEvent("forwardToBackground", { detail: { type: "response", data: event.target.responseText } }); document.dispatchEvent(transferEvent); } }; (() => { let XHR = XMLHttpRequest.prototype; let send = XHR.send; XHR.send = function () { this.addEventListener("load", listenerFn); return send.apply(this, arguments); }; })();编写隔离世界的中转脚本(content-isolated.js)
监听自定义DOM事件,收到数据后调用chrome.runtime.sendMessage转发给后台:// 监听MAIN世界发来的自定义事件 document.addEventListener("forwardToBackground", (event) => { // 调用扩展API发送数据到后台 chrome.runtime.sendMessage(event.detail, (response) => { // 可选:处理后台的响应 if (chrome.runtime.lastError) { console.error("发送数据失败:", chrome.runtime.lastError); } else { console.log("后台响应:", response); } }); });
注意事项
- 自定义事件的名称可以自行定义,只要两个脚本保持一致即可
- 如果传递的是复杂数据(比如对象),要确保数据能被DOM事件正确序列化,避免出现循环引用等问题
- 这种方式只会在你的扩展内部传递数据,不会被页面其他脚本监听(隔离世界的脚本和页面脚本是隔离的)
备注:内容来源于stack exchange,提问作者Amit Kumar
相关产品推荐
相关产品推荐

