Chrome内容和后台脚本可以共享对Blob URL的访问吗? [英] Can Chrome content and background scripts share access to blob: URLs?

查看:55
本文介绍了Chrome内容和后台脚本可以共享对Blob URL的访问吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Chrome扩展程序内容脚本中创建一个 getUserMedia 流,我想将其传递给后台脚本.

I'm creating a getUserMedia stream in a Chrome extension content script, and I'd like to pass it to the background script.

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

You can't pass non-JSON'able data between them, so my strategy is to pass instead the generated blob URL to the stream.

内容脚本:

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/> 元素,此时控制台会显示找不到该文件.

This is fine... until I try to apply it to a generated <video /> element, at which point the console says the file is not found.

我认为是因为后台脚本和内容脚本位于沙盒环境中.

I assume it's because the background and content scripts are in sandboxed environments.

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

Is there any way around this without having to do something nuclear like transfer the stream literally via WebRTC or something?

推荐答案

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

I figured out this is an origins issue.

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

The content script runs in the context of the present webpage, whereas the background script runs in the context of the extension.

blob URL按来源分组,因此,以相同的方式,您通常无法从一个域到另一个域进行AJAX,两个域也不能共享blob URL.

Blob URLs are grouped by origin, so, in the same way you can't ordinarily AJAX from one domain to another, two domains also can't share blob URLs.

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

This is solved by running the content script not in the current webpage (so not specified in the manifest under content_scripts) but in a new tab or pop-up.

背景:

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

内容页面:

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

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

Then, any blob URL generated by content-script.js will be readable to the background, as they are now both running in the context of the extension, i.e. a shared origin.

如果您不喜欢弹出窗口的想法(毕竟,在Mac上,这些窗口均显示为完整标签页),则可以将 iframe 插入当前标签页并运行从那里开始您的内容脚本.

If you don't like the idea of a pop-up window (after all, on Mac these are rendered as full tabs), you could instead inject an iframe into the current tab and run your content script from there.

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

To do this, call a content script from your manifest:

{
    "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);

请注意 chrome.runtime.getURL()-这是在扩展程序(而不是网页)的上下文中托管和运行页面的关键.

Note chrome.runtime.getURL() - that's the key to hosting and running a page in the context of the extension not the webpage.

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

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

然后在那做你的事!

这篇关于Chrome内容和后台脚本可以共享对Blob URL的访问吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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