# browser.runtime.sendMessage not working for injected iframe

**URL:** <https://discourse.mozilla.org/t/browser-runtime-sendmessage-not-working-for-injected-iframe/90854>\
**Category:** Development\
**Created:** [December 29, 2021, 9:37am UTC](https://discourse.mozilla.org/t/browser-runtime-sendmessage-not-working-for-injected-iframe/90854 "2021-12-29T09:37:48Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![tim17d](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/tim17d/32/53877_2.png) [@tim17d](https://discourse.mozilla.org/u/tim17d)\
**Post date:** [December 29, 2021, 9:37am UTC](https://discourse.mozilla.org/t/browser-runtime-sendmessage-not-working-for-injected-iframe/90854/1 "2021-12-29T09:37:48Z")

</div>

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

 ![image](https://us1.discourse-cdn.com/flex001/uploads/mozilla/original/3X/a/3/a3f0b2d3c000510022e55ed275d031c48d2b0e15.png)  
It goes like this:

- `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.

---

<div class="post-metadata">

**Author:** ![juraj.masiar](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/juraj.masiar/32/30587_2.png) [@juraj.masiar](https://discourse.mozilla.org/u/juraj.masiar)\
**Post date:** [December 29, 2021, 12:49pm UTC](https://discourse.mozilla.org/t/browser-runtime-sendmessage-not-working-for-injected-iframe/90854/2 "2021-12-29T12:49:10Z")

</div>

> [@tim17d](#):
>
> from a content script to an injected iframe

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.

---

<div class="post-metadata">

**Author:** ![tim17d](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/tim17d/32/53877_2.png) [@tim17d](https://discourse.mozilla.org/u/tim17d)\
**Post date:** [December 29, 2021, 3:05pm UTC](https://discourse.mozilla.org/t/browser-runtime-sendmessage-not-working-for-injected-iframe/90854/3 "2021-12-29T15:05:41Z")

</div>

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”

---

<div class="post-metadata">

**Author:** ![juraj.masiar](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/juraj.masiar/32/30587_2.png) [@juraj.masiar](https://discourse.mozilla.org/u/juraj.masiar)\
**Post date:** [December 29, 2021, 3:15pm UTC](https://discourse.mozilla.org/t/browser-runtime-sendmessage-not-working-for-injected-iframe/90854/4 "2021-12-29T15:15:10Z")

</div>

You can also specify target frame ID.  
I use something like this in one of my projects background script:

```javascript
browser.runtime.onMessage.addListener((data, sender): RuntimeMessageResult => {
  switch (data.type) {
    // from IFRAME to parent ONLY:
    case 'forwardToParent': return browser.tabs.sendMessage(sender.tab.id, data.data, {frameId: 0});
    // from parent to all frames (including parent):
    case 'forwardToChildren': return browser.tabs.sendMessage(sender.tab.id, data.data);
  }
});

```

---

<div class="post-metadata">

**Author:** ![tim17d](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/tim17d/32/53877_2.png) [@tim17d](https://discourse.mozilla.org/u/tim17d)\
**Post date:** [December 29, 2021, 3:59pm UTC](https://discourse.mozilla.org/t/browser-runtime-sendmessage-not-working-for-injected-iframe/90854/5 "2021-12-29T15:59:02Z")

</div>

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 🕺

---

<div class="post-metadata">

**Author:** ![juraj.masiar](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/juraj.masiar/32/30587_2.png) [@juraj.masiar](https://discourse.mozilla.org/u/juraj.masiar)\
**Post date:** [December 30, 2021, 8:22am UTC](https://discourse.mozilla.org/t/browser-runtime-sendmessage-not-working-for-injected-iframe/90854/6 "2021-12-30T08:22:29Z")

</div>

If you will be using `postMessage` on a 3rd party page, make sure to read [Security concerns](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#security_concerns) in the MDN and make sure to follow those bold statements there.

Otherwise you may have issues with reviewer 🙂.
