Can Chrome content and background scripts share access to blob: URLs?

有些话、适合烂在心里 提交于 2021-02-09 11:52:59

问题


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

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

Content script:

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

Background script:

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
}

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.

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


回答1:


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 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.

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.

Background:

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

Content page:

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

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.

[EDIT]

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

Then in that:

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

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

Then, finally, in page-to-inject-into-iframe.html:

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

Then do your thing in there!




回答2:


blob urls are likely bound to the origin so I don't think this will work. See some discussion here in the adapter repository.

Have you tried creating a RTCPeerConnection between content and background script and send the stream that way? Not ideal for a number of reasons but better than nothing.



来源:https://stackoverflow.com/questions/51082976/can-chrome-content-and-background-scripts-share-access-to-blob-urls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!