Chrome 内容和后台脚本可以共享对 blob: URL 的访问吗?
Can Chrome content and background scripts share access to blob: URLs?
我正在 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 或其他方式逐字传输流那样做一些核心的事情?
blob url 可能绑定到来源,所以我认为这行不通。请参阅适配器存储库中的一些讨论 here。
您是否尝试过在内容和后台脚本之间创建 RTCPeerConnection 并以此方式发送流?由于多种原因并不理想,但总比没有好。
我发现这是一个起源问题。
内容脚本 运行 在当前网页的上下文中,而背景脚本 运行 在扩展的上下文中。
Blob URLs 按来源分组,因此,以同样的方式,您通常不能 AJAX 从一个域到另一个域,两个域也不能共享 blob URLs.
这通过 运行 解决当前网页中的内容脚本(因此未在 content_scripts
下的清单中指定)但在新选项卡或弹出窗口中。
背景:
window.open('content-page.html');
内容页:
<script src='content-script.js'></script>
然后,由 content-script.js 生成的任何 blob URL 都将在后台可读,因为它们现在都 运行ning 在扩展的上下文中,即共享来源。
[编辑]
如果您不喜欢弹出窗口 window 的想法(毕竟,在 Mac 上,它们呈现为完整的选项卡),您可以注入一个 iframe
进入当前选项卡并从那里 运行 您的内容脚本。
为此,请从您的清单中调用内容脚本:
{
"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()
- 这是在扩展而非网页的上下文中托管和 运行 页面的关键。
然后,最后,在page-to-inject-into-iframe.html
:
<script src='script-to-inject-into-iframe.js'></script>
那就在那里做你的事吧!
我正在 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 或其他方式逐字传输流那样做一些核心的事情?
blob url 可能绑定到来源,所以我认为这行不通。请参阅适配器存储库中的一些讨论 here。
您是否尝试过在内容和后台脚本之间创建 RTCPeerConnection 并以此方式发送流?由于多种原因并不理想,但总比没有好。
我发现这是一个起源问题。
内容脚本 运行 在当前网页的上下文中,而背景脚本 运行 在扩展的上下文中。
Blob URLs 按来源分组,因此,以同样的方式,您通常不能 AJAX 从一个域到另一个域,两个域也不能共享 blob URLs.
这通过 运行 解决当前网页中的内容脚本(因此未在 content_scripts
下的清单中指定)但在新选项卡或弹出窗口中。
背景:
window.open('content-page.html');
内容页:
<script src='content-script.js'></script>
然后,由 content-script.js 生成的任何 blob URL 都将在后台可读,因为它们现在都 运行ning 在扩展的上下文中,即共享来源。
[编辑]
如果您不喜欢弹出窗口 window 的想法(毕竟,在 Mac 上,它们呈现为完整的选项卡),您可以注入一个 iframe
进入当前选项卡并从那里 运行 您的内容脚本。
为此,请从您的清单中调用内容脚本:
{
"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()
- 这是在扩展而非网页的上下文中托管和 运行 页面的关键。
然后,最后,在page-to-inject-into-iframe.html
:
<script src='script-to-inject-into-iframe.js'></script>
那就在那里做你的事吧!