Chrome内容和后台脚本可以共享对blob:URL的访问吗?

时间:2018-06-28 12:30:32

标签: javascript google-chrome-extension getusermedia

我正在Chrome扩展程序内容脚本中创建getUserMedia流,并且希望将其传递到后台脚本。

您不能在它们之间传递不可使用JSON的数据,因此我的策略是将生成的Blob URL传递给流。

内容脚本:

function get_stream() {
    navigator.mediaDevices.getUserMedia({video: 1}).then(stream => {
        chrome.runtime.sendMessage({action: 'got_stream', params: {stream_url: URL.createObjectURL(stream)}});
    });

背景脚本:

chrome.runtime.onMessage.addListener(function(data) {
    switch (data.action) {
        case 'got_stream': got_stream(data.params); break;
    }
});

function got_stream(params) {
    let vid = document.createElement('video');
    alert(params.stream_url); //blob:http://...
    vid.src = params.stream_url; //error - file not found
}

这很好...直到我尝试将其应用到生成的<video />元素上为止,此时控制台会显示找不到该文件。

我认为是因为背景脚本和内容脚本位于沙盒环境中。

是否有解决此问题的方法,而不必做一些像通过WebRTC实际传输流之类的核操作?

2 个答案:

答案 0 :(得分:1)

blob网址很可能与来源绑定在一起,因此我认为这不起作用。请参阅适配器存储库中的一些讨论here

您是否尝试过在内容和后台脚本之间创建RTCPeerConnection并以这种方式发送流?由于多种原因并不理想,但总比没有好。

答案 1 :(得分:1)

我发现这是一个起源问题。

内容脚本在当前网页的上下文中运行,而后台脚本在扩展名的上下文中运行。

blob URL按来源分组,因此,以通常无法从一个域到另一域的AJAX相同的方式,两个域也不能确定blob URL。

此问题的解决方法是运行内容脚本而不是在当前网页上运行(因此不在content_scripts下的清单中指定),而是在新标签页或弹出窗口中运行。

背景:

window.open('content-page.html');

内容页面:

<script src='content-script.js'></script>

然后,由content-script.js生成的任何Blob URL都将在后台可读,因为它们现在都在扩展程序的上下文中运行,即共享来源。

[编辑]

如果您不喜欢弹出窗口的想法(毕竟,在Mac上,这些窗口均显示为完整选项卡),则可以将iframe注入当前选项卡并运行contenet脚本从那里。

为此,请从清单中调用内容脚本:

{
    "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content-script-curr-tab.js"]
    }]
}

然后在其中:

let ifr = document.createElement('iframe');
ifr.setAttribute('allow', 'microphone; camera'); //necessary for cross-origin frames that request permissions
ifr.style.display = 'none';
ifr.src = chrome.runtime.getURL('page-to-inject-into-iframe.html');
document.body.appendChild(ifr);

然后,最后在page-to-inject-into-iframe.html中:

<script src='script-to-inject-into-iframe.js'></script>

然后在那做你的事!