I’m trying to send a message from a content script to an injected iframe that’s located in the extension’s file tree (using the polyfill). This is the extension’s layout
content.js adds ui/bookpanel.html as an iframe and waits for it to load
bookpanel.html includes the browser polyfill js (dist/browser-polyfill.min.js) and starts listening for runtime messages once loaded (browser.runtime.onMessage.addListener(...)
content.js then sends data using browser.runtime.sendMessage to the iframe
Here’s where I get the error Error: Could not establish connection. Receiving end does not exist.
So it looks like the listener is unreachable. Funny thing is that it works in Chrome but not in Firefox. I’ve tried to add the page to the manifest as a background page, but is not a solution as all messages go to that instance instead of the ones loaded in the iframes.
Are both in the same tab? I think the source tab is excluded. What you can do is send it to the background script which will foward it back (since you have source tab in the callback).
Another thing that comes to mind is be aware of “async” callbacks or returning a Promise in the “onMessage” listener - because returning a Promise counts as “replying to message” so other listener won’t fire once one of them returns a Promise.
Thanks for the reply yes, you’re right, the iframe is in the same tab and the docs are clear about it event will be fired in each page in your extension, except for the frame that called runtime.sendMessage. I guess I was fooled by Chrome’s behavior. I’ll try to use a background script as a “message broker”
Actually it turned out there’s a simpler way to send data to the iframe, by iframeElement.contentWindow.postMessage(), especially when I don’t really need a background script for now
If you will be using postMessage on a 3rd party page, make sure to read Security concerns in the MDN and make sure to follow those bold statements there.