无法从外部网页向Chrome扩展V3传消息及双向通信实现咨询
Chrome Extension Manifest V3 与外部网页双向通信问题解决
问题根源
网页通过window.postMessage发送的消息无法直接被后台脚本(Service Worker)接收,因为后台脚本独立于页面上下文,无法监听页面的window事件,必须通过内容脚本作为中间桥梁完成通信。
解决方案步骤
1. 更新 Manifest 配置
添加content_scripts字段,注入内容脚本到目标网页:
{ "name": "Default Name", "version": "1.0", "manifest_version": 3, "action": { "default_title": "Default Title" }, "permissions": [ "windows", "activeTab", "tabs", "identity" ], "background": { "service_worker": "background.js" }, "content_scripts": [ { "matches": ["http://localhost/*", "http://localhost:3000/*", "https://localhost/*", "https://localhost:3000/*", "http://localhost:63342/*"], "js": ["content.js"] } ], "externally_connectable": { "ids": ["*"], "matches": ["http://localhost/*", "http://localhost:3000/*", "https://localhost/*", "https://localhost:3000/*", "http://localhost:63342/*"] }, "host_permissions": ["http://*/*", "https://*/*", "*://*/*"] }
2. 创建内容脚本 content.js
作为网页与后台的通信中间层,转发消息并处理回复:
// 监听网页发送的消息,转发给后台 window.addEventListener('message', (event) => { // 验证消息来源,提升安全性 if (event.origin.startsWith('http://localhost') || event.origin.startsWith('https://localhost')) { chrome.runtime.sendMessage(event.data, (response) => { // 将后台的回复发回网页 window.postMessage({ type: 'FROM_EXTENSION', text: response }, event.origin); }); } }); // 监听后台发送的消息,转发给网页 chrome.runtime.onMessage.addListener((message) => { if (message.type === 'TO_PAGE') { window.postMessage(message, '*'); // 建议替换为具体域名,如"http://localhost:3000" } });
3. 修正后台脚本 background.js
处理来自内容脚本的消息,并发送回复:
chrome.runtime.onInstalled.addListener(() => { console.log("just installed"); }); chrome.runtime.onMessage.addListener((data, sender, sendResponse) => { console.log("data", data); // 修复原代码中的拼写错误(date → data) console.log("sender", sender); // 发送回复给内容脚本,再由内容脚本转发到网页 sendResponse("Hello from background!"); });
4. 更新外部网页代码
添加监听扩展回复的逻辑:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript"> const clickMe = () => { console.log("button has been clicked"); window.postMessage( { type: "FROM_PAGE", text: "Hello from the webpage!" }, "http://localhost:3000"); // 指定具体origin更安全 } // 监听扩展发来的回复 window.addEventListener('message', (event) => { if (event.data.type === 'FROM_EXTENSION') { console.log("Received from extension:", event.data.text); } }); </script> </head> <body> <button onclick="clickMe()">click me</button> </body> </html>
双向通信说明
- 网页 → 扩展:网页通过
window.postMessage发消息 → 内容脚本监听message事件 → 内容脚本用chrome.runtime.sendMessage转发给后台 → 后台处理消息。 - 扩展 → 网页:后台用
chrome.tabs.sendMessage(需指定tab ID)发消息给内容脚本 → 内容脚本监听chrome.runtime.onMessage事件 → 内容脚本用window.postMessage转发给网页 → 网页监听message事件接收回复。
内容的提问来源于stack exchange,提问作者Itzik.B
相关产品推荐
相关产品推荐

