communication between two iframe children using postMessage

10,748

Why do you say that the child iframes can't communicate directly? Actually, they can. What you can do within a child iframe is use the window.parent property to get a reference to the parent window, and then use the parent's frames property to get references to all child iframes (the frames property gives you an array of such references). After that, you can use postMessage on each of those references, and set the required origin restrictoin in the postMessage call so that you are sure only the right iframe gets the message.

Notice that this will work even when all three windows (iframe1, parent window and iframe2) are on different domains because iframe1 is not doing anything with the parent window (which would violate SOP), it is only fetching references to nested iframes.

Links:

https://developer.mozilla.org/en-US/docs/DOM/window.parent

https://developer.mozilla.org/en-US/docs/DOM/window.frames

Share:
10,748
Mindey I.
Author by

Mindey I.

Co-founder and CEO of https://coinbase.com Personal blog at http://brianarmstrong.org Lover of software engineering.

Updated on June 14, 2022

Comments

  • Mindey I.
    Mindey I. almost 2 years

    I have some embed code that users can put on their sites. It creates two children iframes on the page. I'd like to have those children be able to communicate.

    I'm using javascript's window.postMessage https://developer.mozilla.org/en-US/docs/DOM/window.postMessage

    Since the two iframe children can't communicate directly, I'm using the parent as a relay for messages. However the parent can be on a different domain since it's embeddable code.

    When all three (parent and two children) are on the same domain, it's pretty easy and I have this working with the security check checking the e.origin is my own site

    # coffeescript
    # host = "http://www.mysite.com"
    host = "http://localhost"
    
    receive_message = (e) ->
      console.log("received message from " + e.origin + ": " + e.data)
      return if e.origin != host
    
      if e.data == "show"
        ...
      else if e.data == "hide"
        ...
    
    window.addEventListener("message", receive_message, false)
    

    What is an elegant way to check the origin when the parent can be on any domain?

    What is a good way to allow debugging of the script where the origin can be localhost?

    Is it sufficient to just check the data param if there are non destructive/changing messages being passed across?

    Thanks!

  • Mindey I.
    Mindey I. over 11 years
    Wow - you are right! Can't believe I missed this, had no idea child iframes can communicate. Worked great, thanks for the help!
  • wengeezhang
    wengeezhang over 8 years
    @IvanZuzak,(iframe1, parent window and iframe2) are on different domains.How can i assure iframe2 is loaded when i use parent.frames[1].postMessage() in iframe1's code.Because if iframe2 isn't loaded,calling postMessage() will result error
  • Ivan Zuzak
    Ivan Zuzak over 8 years
    @wengeezhang I don't think you can. You can only send a message and receive messages back. So, what you could do try to send a message, and if you don't receive a response within some period of time, you can conclude that the receiver wasn't ready for it and then try again. For example, iframe2 might be in the middle of loading when you send the message, and the required handlers haven't been set up yet. A long time ago I worked on a library which tries to handle such things for you: github.com/izuzak/pmrpc