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

Inconsistency: runtime.onMessage listening for contentScript messages within extension popups #92

Open
carlosjeurissen opened this issue Oct 1, 2021 · 7 comments
Labels
inconsistency Inconsistent behavior across browsers

Comments

@carlosjeurissen
Copy link
Contributor

carlosjeurissen commented Oct 1, 2021

Setup

Having an extension popup containing an iframe. A contentscript is applied to this iframe which sends a message using runtime.sendMessage.

Behavior in Chrome and Firefox

Both the background and extension popup pages can listen for this message using runtime.onMessage

Behavior in Safari

Only the background page an listen for this message using runtime.onMessage

Wrapping up

As mentioned by @tophf Both Chrome's documentation and MDN say "event will be fired in every frame of your extension (except for the sender's frame)". The same is being mentioned as early as 2012 in https://crbug.com/136654.

An issue to sync the behavior in browsers has been reported for Safari under:
https://developer.apple.com/forums/thread/690249 and https://feedbackassistant.apple.com/feedback/9637664

A sample extension can be found here:
https://github.com/carlosjeurissen/webext-tech-demo-extensions/tree/main/issues/safari-9637664-messaging-api-from-content-script-frame

@carlosjeurissen carlosjeurissen changed the title Consistency: runtime.onMessage listening for contentScript messages within extension popups Inconsistency: runtime.onMessage listening for contentScript messages within extension popups Oct 2, 2021
@tophf
Copy link

tophf commented Oct 20, 2021

chrome.runtime.sendMessage by design sends the message to all pages/tabs/frames that have the extension's origin i.e. chrome-extension://id so the popup should receive it too. In the beginning sendMessage had a bug: it also delivered the message to its own context's onMessage listener, but it was fixed several years ago so that the message is delivered only to other contexts. I wonder if Safari mistakenly considers the embedded web iframe to have the same context as the popup?

@carlosjeurissen
Copy link
Contributor Author

@tophf Well, actually it's the reverse. The message is received in both Firefox and Chrome, but not in Safari. So not sure this is related.

@tophf
Copy link

tophf commented Oct 20, 2021

Well, actually it's the reverse. The message is received in both Firefox and Chrome, but not in Safari. So not sure this is related.

What's reverse? My comment above says that the message should be received by the popup and that it always worked like that in Chrome. Is there something I need to rephrase maybe?

@carlosjeurissen
Copy link
Contributor Author

@tophf Apologies. Misread your message. Indeed, Safari might potentially see the iframe as to have the same context as the page containing the iframe thus ignoring the message. So would love to hear about that from Apple.

Also would be good to hear from Google and Mozilla if sending a message like this should indeed be fetched by the popup or if this is unintentional.

@tophf
Copy link

tophf commented Oct 20, 2021

Both Chrome's documentation and Firefox's MDN say "event will be fired in every frame of your extension (except for the sender's frame)". I see the same being mentioned as early as 2012 in https://crbug.com/136654.


P.S. that said, extensions would benefit from having a way to change the broadcast behavior: imagine extensions like Vim shortcuts adding the chrome-extension:// iframe to each tab so they will all receive the message, which would be wasteful when the user has many tabs. What if the API allows an optional third parameter options conceptually similar to chrome.tabs.sendMessage:

await chrome.runtime.sendMessage(msg, { targets: ['background', 'parent', 'top', 'all'] });

or just one target so the extension makes several calls if necessary:

await Promise.all([
  chrome.runtime.sendMessage(msg, { target: 'background' }),
  chrome.runtime.sendMessage(msg, { target: 'parent' }),
]);

or a simpler alternative:

await chrome.runtime.sendMessage(msg, { broadcast: false });

@carlosjeurissen
Copy link
Contributor Author

carlosjeurissen commented Oct 20, 2021

Updated the main issue to embrace this! As for changing the broadcast behavior. That would be perfect.

Just like we did with scripting.executeScript we can introduce a target property as replacement for tabId.

So you would have an API like this:

browser.messaging.sendMessage(msg, {
  target: {
    tabIds: [],
    frameIds: [],
    extensionIds: []
  },
  includeTlsChannelIdOptional: false
});

Which could replace both browser.runtime.sendMessage and browser.tabs.sendMessage. If preferred I can create a separate issue for that. This issue kinda related to this: #77

@xeenon xeenon added the inconsistency Inconsistent behavior across browsers label Oct 25, 2021
@fregante
Copy link

fregante commented Aug 22, 2022

I'd love a better messaging API. The current "broadcast by default" behavior is extremely confusing. I had to discover this several times over the years of developing extensions.

I'm working on a clunky target-filtering logic to be able to make sure each context handles only its own messages. It's incredibly inefficient to have to "handle" these messages (i.e. ignore) in the option page when they're intended for the background page.

Targeting specific pages by URL/pattern would be incredibly helpful in order to message multiple tabs open at once or just an iframe (which currently requires a broadcast via tabs.sendMessage or runtime.sendMessage depending on the source of the iframe)

Also related:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
inconsistency Inconsistent behavior across browsers
Projects
None yet
Development

No branches or pull requests

4 participants