Open fregante opened 11 months ago
Once browsers support both browser.runtime.getTarget()
and chrome.runtime.getContexts()
, one could trivially retrieve both tabId
and documentId
by combining them together. Of course, there is some inefficiency in two consecutive async calls and some potential data race in frames being navigated, loaded, etc.
runtime.getContexts
like extension.getViews
is not available in content scripts, while runtime.getFrameId
is only available in content scripts, so you can't combine the two.
Ideally this info must be available synchronously because async call may take several seconds to complete on a slower device if the site is busy (e.g. compiling/running a big js or building its virtual DOM or whatever else). AFAIK documentId in Chrome is stored in the document's renderer, so it can be exposed as a field in chrome.runtime
.
I'm supportive of the capability requests, i.e. the ability to retrieve the current tabId/documentId, asynchronously.
I'd like this to be part of the "Contexts" feature (getContexts) rather than separate synchronous methods.
The runtime.getContexts()
proposal at https://github.com/w3c/webextensions/blob/main/proposals/runtime_get_contexts.md includes the relevant part already:
https://github.com/w3c/webextensions/blob/10a84ee95a36646b88b538a1722ca4b2b2fff863/proposals/runtime_get_contexts.md#L264-L279
That makes sense but then one has to match the objects returned with each <iframe>
element manually. Also I'd need this API in the content script, not just on extension pages (unlike the previous getViews
)
That makes sense but then one has to match the objects returned with each
<iframe>
element manually.
What is the use case for this?
Also I'd need this API in the content script, not just on extension pages (unlike the previous
getViews
)
In my comment I referenced the part of the proposal that calls out the potential to introduce getCurrentContext, AND making the concept available to content scripts.
In my comment
Sorry, on mobile the link opened the page without deep-linking, I didn't see the specific section.
That makes sense but then one has to match the objects returned with each
<iframe>
element manually.What is the use case for this?
One of the usages was to enable communication between frames, e.g.:
chrome-extension://
document served in an iframe.Other than postMessage
, which isn't particularly convenient nor safe (https://github.com/w3c/webextensions/issues/77), this can only be done:
runtime.sendMessage()
, which broadcasts to all contexts, so it needs a way to match sender.tabId === thisIframedDocument.tabId
in the onMessage
handlertabs.sendMessage()
, which requires knowing which tab the current iframe is inThis new API would allow:
// From a `chrome-extension://` iframe to a `http://` top frame
const {tabId, iframeId} = await browser.runtime.getTarget(window.top)
chrome.tabs.sendMessage(tabId, message, {frameId})
and:
// From a `chrome-extension://` top frame to a `http://` iframe
const {tabId, iframeId} = await browser.runtime.getTarget($('iframe'))
chrome.tabs.sendMessage(tabId, message, {frameId})
or via runtime
message routing in any direction
I suppose https://github.com/w3c/webextensions/issues/77 would be a more direct solution to this, but it would not be enough "iframe to iframe" communication, because they don't have access to each other's iframe
element.
browser.runtime.getTarget($('iframe')) browser.runtime.getTarget(window.top)
Since window.top
is a Window, it would be more consistent to use frameElem.contentWindow
here. It would also allow using a Window-typed event.source in a message.
This is also important that this is synchronous as I can use this ID to do browser.scripting.executeScript
on the page that the content script runs since the injection.target
is mandatory and acquiring this asynchronously would miss the document-start
timepoint.
I'm looking for a way to securely do sendMessage
from MAIN
world script to background service worker. Currently it would be impossible to do this without involving postMessage
.
@wfjsw, it's not possible to achieve a real document_start with executeScript because it injects asynchronously, messaging is asynchronous as well. A real document_start can be achieved by using a declared or registered content script (chrome.scripting.registerContentScripts).
I'm looking for a way to securely do sendMessage from MAIN world script to background service worker. Currently it would be impossible to do this without involving postMessage.
It will be implemented as a separate API to communicate between the worlds securely. Note that your code in the MAIN world may run in an already poisoned JS environment (https://crbug.com/40202434 applies to all browsers). Currently the only secure way is to create a temporary iframe to extract dispatchEvent/addEventListener/etc. to establish a secure channel, it's very complicated and you can see how it's done in Violentmonkey. In ManifestV3 it requires using the userScripts API permission, which is problematic because it misrepresents the function of the extensions, also users in Chrome must enable "developer mode" in chrome://extensions.
This was already requested in the previous thread, but it was probably too late by then, so I'll extract it into its own request
Could this be expanded to include the tab ID as well?
It's a pretty common request to know "this" tab ID: https://stackoverflow.com/q/6202953/288906 (123 upvotes)
Currently this requires a ping to the runtime, which may or may not be "quick".
Including the recently-added
documentId
would be great. There's a lot of potential here so limiting it to just aframeId
seems overly specific; returning an object makes it more flexible for future usage without having to create specific APIs.