-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sample: Transfer a blob from a background context to a page #766
Comments
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
It's the wrong goal in the context of the linked issue. I guess its title was initially confusing as it mentioned "web page" instead of "web page's content script", so I've changed it to reflect the contents of the issue, which is about the content script. It's a more difficult task to accomplish securely, but still possible via an iframe inside a closed ShadowDOM with a random token + MessagePort as described in the comment linked in the issue. One change to the scheme would be to send the MessageChannel port from SW to the content script via the iframe, then use this port to transfer The following has been proved wrong, see the clarifying comment.
port1.postMessage(blob, [await blob.arrayBuffer()]);
|
This comment was marked as off-topic.
This comment was marked as off-topic.
Blob is just a wrapper on the same data exposed via arrayBuffer accessor or other getters on the blob, so this code does transfer the actual data instantly. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Not the Blob, the arrayBuffer view of the same data contained in the Blob. |
This comment was marked as off-topic.
This comment was marked as off-topic.
A Blob will be received by the listener, so it can be said that the Blob is effectively transferred. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Blob is not a |
This comment was marked as off-topic.
This comment was marked as off-topic.
I know. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Using the code I posted (with the second parameter using blob.arrayBuffer) will transfer a Blob instantly, it's trivial to verify. |
FWIW, if you're interested what happens under the hood, here's my guess: the blob's actual data being a Transferable (blob.arrayBuffer) is sent instantly, while the Blob itself is just a wrapper over that data, which is structuredClone'able, so it's reconstructed in the receiver using the instantly transferred data. |
This comment was marked as off-topic.
This comment was marked as off-topic.
|
This comment was marked as off-topic.
This comment was marked as off-topic.
It's in the specifications somewhere, which I investigated when I looked for a way to transfer blobs instantly. I found it, confirmed it worked. I don't have the links in browser history anymore, so if you're interested you can investigate and verify it yourself. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Your demo prints the blob in console, just as it should. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Maybe there's no need for arrayBuffer, but try making a 1GB Blob and you will see it's transferred instantly, which is the only thing I care about in this context. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Try sending |
No, you don't get any data at all. The data is not a part of the function's code string. |
The data is any binary generated or downloaded stuff. It is not a part of any function. |
This comment was marked as off-topic.
This comment was marked as off-topic.
It won't contain data from SW, it's a useless exercise in semantics. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
We're going in circles for like 100th time, but it's fun so let's do it once again. A web page can trivially delete any element immediately once it's added as I've shown using DOMNodeInserted event. It can be done using MutationObserver too, as well as using a periodic check, it doesn't matter which one as they all are trivial to implement. This code can't be removed automatically from an unknown web page not because it specifically resists removal but because such code will be an integral part of a large minified bundle, possibly with obfuscation - you'd have to analyze it manually. Such code can be added by another extension as well, not that it's likely, but still possible and trivial to implement. It is trivial, there's no challenge in writing it. Of course there's a way for an extension to protect the iframe: it can override all DOM methods that can be used to remove an element or to rewrite/reload the page or to extract such methods from a new src-less iframe.
All of these are for static data included with the extension, it's not what the linked issue is about. The issue is about data in SW context (and nowhere else within the extension). It can be generated by JS or downloaded from an external URL or captured from desktop. It's not a part of the func's code or of the extension package. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Although Local Modifications is not a part of the extensions API/platform, but indeed its functionality can be replicated via chrome.debugger API, and indeed it can be used to remove the code once we identified it manually. I didn't contest this part. My point is that the analysis for such code can't be reliably automated. Also, chrome.debugger is not an API a typical user would want to allow for an extension that's not related to debugging. Writing to a local file inside the installed extension directory is indeed a possibility but in addition to being slower than sending a Blob directly between contexts it would require either installing the extension inside the default downloads directory or to use a nativeMessaging app to write the file into the directory of an installed extension, finding which reliably and automatically is not always trivial since the browser may be launched with |
This comment was marked as off-topic.
This comment was marked as off-topic.
Ideally |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Fixes GoogleChrome#766 Create offscreen document, use WebRTC RTCDataChannel to send ArrayBuffer(s) from ServiceWorker to Web page. Ideally this can be solved by programmatically setting WindowClient to arbitrary Web page, getting a reference to offscreen window, or setting opener on offscreen window for ability to use onmessage and postMessage(data, target, [data]) directly. RTCDataChannel send() does not transfer data. It does send ArrayBuffer(s) transferred from ServiceWorker to offscreen window to Web page window.
Goal of the demo
Demonstrate how an extension can create a blob in the extension's service worker and transfer it to a page's main world.
Suggested implementation
Sketch of my initial implementation plan
navigator.serviceWorker.controller.postMessage()
structuredClone()
to create a copy of a blob.event.source.postMessage(msg, [transferable])
to reply to the client and transfer the blobwindow.parent.postMessage(msg, "<origin>", [transferable])
to transfer the data to the pageRelated links
Notes
Initial findings suggest that it's not possible to transfer variables across origins. I'm tentatively thinking that to work around this, we can use
URL.createObjectURL()
in the iframe and directly reference the object URL somewhere that's easily visible to the end user (e.g. canvas, Audio/Video element, etc.).The text was updated successfully, but these errors were encountered: