Skip to content
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

Proposal: one-time message passing addressed to a specific documentId or contextId #294

Open
bershanskiy opened this issue Oct 16, 2022 · 4 comments
Labels
proposal Proposal for a change or new feature supportive: chrome Supportive from Chrome supportive: firefox Supportive from Firefox supportive: safari Supportive from Safari

Comments

@bershanskiy
Copy link
Member

bershanskiy commented Oct 16, 2022

Summary

Currently, there are two types of messaging: one-time messages and persistent ports. Persistent ports have some efficiency implications while one-time messages work only in contexts clearly associated with a tab and messages sent from background to content scripts can accidentally be delivered to a wrong content script if there is a race between tab update and message sending.

Problem

Ergonomics: not all contexts have associated tab

One-time messaging is routed based on tabId and frameId, which, of course, exist only for tab contexts. These attributes do not exist on messages sent from Sidebars (tested on Firefox and Opera), Extension Actions, and Extension options. This necessitates some trickery for initiating sending messages from background to these contexts (e.g., background context can open a short-lived persistent port, saving message to storage for recipient to get onChanged event or similar place, etc.) Therefore, background can initiate messaging, but it is very not ergonomic.

Confused recipient problem: tabId and frameId are not globally unique, frames can load different documents

Update: Chromium supports this via documentId option on tabs.sendMessage().

Currently, some browsers use simple counters for tabId and even frameId (e.g., Firefox) while others started to generate somewhat unique numbers (e.g., Chromium). However, all browsers have to set main frame id to 0 following prior convention. This means that background can accidentally mean to send message to a particular context (tab's top frame or a subframe) but this context can be replaced with another one (page navigation or reload) and message would be delivered to the new context.

Also, a minor nit: in the current framework it is conceptually impossible to communicate with contexts which are being unloaded or prerendered. I'm not sure how useful that would be in practice, but previously I had cases where I need to clean up data in storage.StorageArea associated with a particular tab/frame when said frame is destroyed and I had to choose between developer ergonomics and efficiency (e.g., using non-passive unload handler is easy and produces maintainable code, but breaks BFCache). Conceptually, it would be nice if it was possible to navigate away from a frame but still be able to communicate with document for a short while (e.g., 10 seconds) to finalize some stuff.

Solution

Browsers already assign unique identifiers to document contexts: Chromium calls these documentId while Firefox calls them contextId. It would be nice to be able to route messages based on these ids. I treat documentId and contextId as interchangeable identifiers, since most contexts are documents anyway (except for background service workers which don't really need these ids).

API proposal

Currently runtime.sendMessage has the following signature:

runtime.sendMessage(
  extensionId?: string,
  message: any,
  options?: object,
  callback?: function,
)

I believe it can be extended to replace extensionId with recipientId which is optional can can be a string (to denote extension ID) or a number (to denote documentId or contextId).

runtime.sendMessage(
  recipientId?: string | number,
  message: any,
  options?: object,
  callback?: function,
)

Note that this would still need some method of feature-detection for browsers not supporting this feature.

@carlosjeurissen carlosjeurissen added proposal Proposal for a change or new feature agenda Discuss in future meetings labels Oct 17, 2022
@bershanskiy
Copy link
Member Author

I just realized that Chromium 106+ already supports a variant of this feature but only for tabs via tabs.sendMessage: starting with Chromium 106, the third argument of tabs.sendMessage can take a documentId as an alternative to frameId. This is a great change which fixes problem 2, but there is currently no fix for problem 1. Still looking for similar feature for Safari and Firefox.

Updated post accordingly.

@tophf
Copy link

tophf commented Oct 18, 2022

recipientId?: string | number,

In Chrome documentId is a UUID string, not a number.

And what about the id for the background script as it doesn't have a documentId in Chrome? Maybe 'background'? Content scripts would greatly benefit from the ability to send messages only to the background script because chrome.runtime.sendMessage broadcasts to all chrome-extension:// contexts (in Chrome at least).

@carlosjeurissen
Copy link
Contributor

For additional clarity, if this is to be implemented, I would suggest to keep extensionId as separate target and not join it together with receipientId.

Are documentId and contextId referencing basically the same entities? Can we agree on a common name for them and use it instead of receipientId?

@Rob--W
Copy link
Member

Rob--W commented Nov 10, 2022

There is general agreement that this the ability to target one recipient with a message is useful. The specifics of the API have yet to be defined.

The ability to target one specific recipient is a prerequisite to optimize and improve the API to send messages within an extension, see #293 (comment)

@dotproto dotproto removed the agenda Discuss in future meetings label Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal Proposal for a change or new feature supportive: chrome Supportive from Chrome supportive: firefox Supportive from Firefox supportive: safari Supportive from Safari
Projects
None yet
Development

No branches or pull requests

6 participants