chrome.runtime是否支持使用可转移对象发布消息? [英] Does chrome.runtime support posting messages with transferable objects?

查看:130
本文介绍了chrome.runtime是否支持使用可转移对象发布消息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习Transferable对象: 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(我跑了!);';
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(由工作人员回电!\\\
);
};

console.log(worker:,worker);
worker.postMessage(arrayBuffer,[arrayBuffer]);

if(arrayBuffer.byteLength){
console.error(nope);
} else {
console.log(it worked);





$ b

有没有人有任何关于支持的信息,或支持/一个用于使用端口的crbug,如:

  var port = chrome.runtime.connect({
name:'youTubeIFrameConnectRequest '
});

//port.postMessage - 可传输对象。

我没有看到支持它或支持它的任何事情,但那似乎很奇怪!

解决方案

通过扩展消息传递API 始终是JSON序列化的。这种格式不仅用于在后台页面和内容脚本之间传递消息,而且还用于本地应用程序。所以,我猜想消息传递APIs不太可能支持更多的项目。



结构化克隆算法的请求(比JSON序列化更强大,功能更强大比可转让)已于2012年提出请求( Chromium issue 112163 )。问题仍然存在;有人建议使用 SharedWorker 作为蹦床。



SharedWorker 受相同的原始策略影响,因此调用者需要驻留在同一个原始位置。要实现此目的,您可以添加一个页面以 web_accessible_resources ,并将此页面嵌入到框架中。



在本答案的末尾,我附加了一个蹦床的裸机实现。用这些文件创建一个扩展。然后,打开一个选项卡。此选项卡将包含嵌入的框架,演示将向共享工作人员发送消息。此消息将被传送到后台页面,只需查看后台页面的控制台以查看这些消息。

该演示非常少,您需要自己实施端口管理(销毁)。

演示不使用可转移的消息传递(还),因为它是允许多个端口的通用实现。如果您确保最多同时存在两个端口,那么您可以将代码更改为使用可转发的内容(当收到一个端口和一个发送端时,可转发端口才有意义,因为对象的所有权也会传输)。



特殊情况:同一进程



如果所有代码都在同一个进程中运行,那么可以使用更简单的方法不需要 SharedWorker s。



相同的源策略禁止从/到帧和扩展的直接访问,您将使用 parent.postMessage 穿过这座桥。然后,在页面的onmessage事件中,您可以使用 chrome.extension.getViews 可以直接引用其中一个扩展页面的窗口对象(例如弹出页面,选项页面,...)。

从其他页面, chrome.extension.getBackgroundPage() 给出了对背景页面的窗口对象的引用(对于活动页面,请使用 chrome.runtime.getBackroundPage(callback) ) p>

如果您想连接两个帧,请使用Channel messaging 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();
//演示:将消息打印到控制台,并记住最后的结果
worker.port.onmessage = function(event){
console.log('Received message',event。数据);
window.lastMessage = event.data;
};
//演示:发送消息
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 作为后台脚本以节省此答案中的空间。从网络工作者的角度来看,谁发起这个消息并不重要,所以我重新使用了发送和接收消息的代码(毕竟它只是一个简单的演示!)。

{
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

}


I am learning about Transferable Objects: http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fast

They seem pretty awesome and I would like to use them in my extension to speed up passing data from inside of an iframe to outside of an iframe.

I've got this example code working, but it uses a 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");
}

Does anyone have any information about support for, or a timeline for support for / a crbug for using a port like:

var port = chrome.runtime.connect({
    name: 'youTubeIFrameConnectRequest'
});

//port.postMessage -- transferrable object.

I don't see any support for it or anything about supporting it, but that seems really odd!

解决方案

Messages that go through the extension message passing APIs are always JSON-serialized. This format is not only used for passing messages between background page and content scripts, but also with native applications. So, I guess that it's not very likely that the message passing APIs support more items.

A request for the structured cloning algorithm (more powerful than JSON-serialization, less powerful than transferables) was requested in 2012 already (Chromium issue 112163). The issue is still open; someone has suggested to use a SharedWorker as a "trampoline".

The SharedWorker is affected by the same origin policy, so the callers need to reside at the same origin. To achieve this, you could add a page to web_accessible_resources, and embed this page in a frame.

At the end of this answer, I've attached a bare implementation of a trampoline. Create an extension with these files. Then, open a tab. This tab will contain the embedded frame, and the demo will send a message to the shared worker. This message will be transported to the background page, just view the console of the background page to see these messages.
The demo is minimal, you need to implement the port management (destruction) yourself.
The demo does not use transferable message passing (yet), because it's a general implementation that allows multiple ports. If you ensure that at most two ports exist at the same time, then you could change the code to use transferables (transferables only make sense when there's one received and one sender, because the ownership of the object is also transferred).

Special case: Same-process

If all of your code runs in the same process, then you can use a simpler approach without SharedWorkers.

The same origin policy forbids direct access from/to the frame and the extension, so you will use parent.postMessage to cross this bridge. Then, in the onmessage event of the page, you can use chrome.extension.getViews to get a direct reference to the window object of one of your extension pages (e.g. popup page, options page, ...).
From the other pages, chrome.extension.getBackgroundPage() gives a reference to the window object of the background page (for an event page, use chrome.runtime.getBackroundPage(callback)).

If you want to connect two frames, use the Channel messaging API (see whatwg specification and Opera's dev article). With this method, you'll establish a direct connection between the frames, even if they are located on different origins!

Example: Trampoline

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

Note: I put trampoline.js as a background script to save space in this answer. From the perspective of the Web worker, it doesn't matter who initiated the message, so I have re-used the code for sending and receiving messages (it's a simple demo, after all!).

{
    "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"
    ]   
}

这篇关于chrome.runtime是否支持使用可转移对象发布消息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆