通过扩展消息传递 API的消息始终是 JSON 序列化的。这种格式不仅用于在后台页面和内容脚本之间传递消息,还用于原生应用程序。所以,我猜消息传递 API 不太可能支持更多项目。
2012 年已经请求结构化克隆算法(比 JSON 序列化更强大,不如可转移强大)(Chromium 问题 112163)。这个问题仍然悬而未决;有人建议使用 aSharedWorker作为“蹦床”。
SharedWorker受同源策略的影响,所以调用者需要驻留在同源。为此,您可以向 中添加一个页面web_accessible_resources,并将该页面嵌入到框架中。
在这个答案的最后,我附上了一个蹦床的裸露实现。使用这些文件创建扩展。然后,打开一个选项卡。此选项卡将包含嵌入的框架,并且演示将向共享工作者发送消息。这条消息会被传送到后台页面,只要查看后台页面的控制台就可以看到这些消息。
演示是最小的,你需要自己实现端口管理(销毁)。
该演示(还)不使用可传输的消息传递,因为它是一个允许多个端口的通用实现。如果您确保最多同时存在两个端口,那么您可以更改代码以使用可转移对象(可转移对象仅在有一个接收者和一个发送者时才有意义,因为对象的所有权也会转移)。
特例:同流程
如果您的所有代码都在同一个进程中运行,那么您可以使用不带SharedWorkers 的更简单的方法。
同源策略禁止从/到框架和扩展的直接访问,因此您将使用parent.postMessage此桥接。然后,在页面的 onmessage 事件中,您可以使用chrome.extension.getViews获取window对您的扩展页面之一的对象的直接引用(例如弹出页面、选项页面,...)。
从其他页面,chrome.extension.getBackgroundPage()提供对背景页面对象的引用window(对于事件页面,使用chrome.runtime.getBackroundPage(callback))。
如果您想连接两个框架,请使用 Channel 消息传递 API(请参阅whatwg 规范和Opera 的开发文章)。使用此方法,您将在框架之间建立直接连接,即使它们位于不同的来源!
示例:蹦床
worker.js
var ports = [];
onconnect = function(event) {
var port = event.ports[0];
ports.push(port);
port.start();
port.onmessage = function(event) {
for (var i = 0; i < ports.length; ++i) {
if (ports[i] != port) {
ports[i].postMessage(event.data);
}
}
};
};
trampoline.js
var worker = new SharedWorker(chrome.runtime.getURL('worker.js'));
worker.port.start();
// Demo: Print the message to the console, and remember the last result
worker.port.onmessage = function(event) {
console.log('Received message', event.data);
window.lastMessage = event.data;
};
// Demo: send a message
worker.port.postMessage('Hello');
trampoline.html
<script src="trampoline.js"></script>
contentscript.js
var f = document.createElement('iframe');
f.src = chrome.runtime.getURL('trampoline.html');
f.hidden = true;
(document.body || document.documentElement).appendChild(f);
manifest.json
注意:我将trampoline.js其作为后台脚本以节省此答案的空间。从 Web worker 的角度来看,消息是谁发起的并不重要,所以我重用了发送和接收消息的代码(毕竟这是一个简单的演示!)。
{
"name": "Trampoline demo",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["trampoline.js"],
"persistent": true
},
"content_scripts": [{
"js": ["contentscript.js"],
"matches": ["<all_urls>"]
}],
"web_accessible_resources": [
"trampoline.html"
]
}