我正在学习可转移对象:http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fast
它们看起来非常棒,我想在我的扩展程序中使用它们来加速将数据从iframe内部传递到iframe之外。
我已经使用了这个示例代码,但它使用了Web Worker:
var s = document.createElement("script");
s.type = "text/js-worker";
s.innerHTML = 'console.log("i ran!");';
document.body.appendChild(s);
var blob = new Blob(Array.prototype.map.call(document.querySelectorAll("script[type=\"text\/js-worker\"]"), function (oScript) {
return oScript.textContent;
}), { type: "text/javascript" });
var worker = new Worker(window.URL.createObjectURL(blob));
var arrayBuffer = new ArrayBuffer(1);
worker.onmessage = function (oEvent) {
console.log("Called back by the worker!\n");
};
console.log("worker:", worker);
worker.postMessage(arrayBuffer, [arrayBuffer]);
if (arrayBuffer.byteLength) {
console.error("nope");
} else {
console.log("it worked");
}
有没有人有任何关于支持的信息,或者支持使用像以下端口的crbug的时间表:
var port = chrome.runtime.connect({
name: 'youTubeIFrameConnectRequest'
});
//port.postMessage -- transferrable object.
我没有看到任何支持它或支持它的任何东西,但这看起来很奇怪!
答案 0 :(得分:13)
通过extension message passing APIs的邮件始终是JSON序列化的。此格式不仅用于在后台页面和内容脚本之间传递消息,还用于native applications。所以,我想传递API的消息不太可能支持更多的项目。
2012年已经请求了结构化克隆算法(比JSON序列化更强大,比转换功能更强大)(Chromium issue 112163)。这个问题仍然存在;有人建议使用SharedWorker
作为“蹦床”。
SharedWorker
受同一原始策略的影响,因此呼叫者需要驻留在同一个来源。为此,您可以将页面添加到web_accessible_resources
,并将此页面嵌入到框架中。
在这个答案的最后,我附上了一个蹦床的简单实现。使用这些文件创建扩展。然后,打开一个标签。此选项卡将包含嵌入式框架,演示将向共享工作程序发送消息。此邮件将传输到后台页面,只需view the console of the background page即可查看这些邮件 演示很少,您需要自己实施端口管理(销毁) 该演示不使用可传递的消息传递(但),因为它是允许多个端口的一般实现。如果您确保最多同时存在两个端口,那么您可以更改代码以使用transferables(只有在收到一个发送者和一个发送者时,transferables才有意义,因为对象的所有权也会被转移)。
如果您的所有代码都在同一个进程中运行,那么您可以使用更简单的方法而不使用SharedWorker
。
相同的原始政策禁止从/向框架和扩展程序直接访问,因此您将使用parent.postMessage
来跨越此桥。然后,在页面的onmessage事件中,您可以使用chrome.extension.getViews
直接引用您的某个扩展页面的window
对象(例如弹出页面,选项页面......)。
在其他页面中,chrome.extension.getBackgroundPage()
提供了对背景页面的window
对象的引用(对于event page,请使用chrome.runtime.getBackroundPage(callback)
)。
如果要连接两个帧,请使用频道消息传递API(请参阅whatwg specification和Opera's dev article)。使用此方法,您将在帧之间建立直接连接,即使它们位于不同的原点!
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工作者的角度来看,发起消息的人并不重要,所以我重新使用了代码来发送和接收消息(毕竟这是一个简单的演示!)。
{
"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"
]
}