Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

postMessage Source IFrame

Tags:

I'm working on a website with cross-domain iframes that are resized to the correct height using postMessage. The only problem I'm having is identifying which iframe has which height. The way I've currently got it set up is that when one iframe sends its height to the parent, all the iframes' heights are changed.

Parent:

var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; var eventer = window[eventMethod]; var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";  eventer(messageEvent, function(e) {     $('iframe').height(e.data); }, false); 

Iframe:

var updateHeight = function() {     if(window.parent) {         window.parent.postMessage($('.widget').outerHeight(), '*');     } }; 

Is there some way to identify which iframe sent the message event?

like image 381
skimberk1 Avatar asked Mar 11 '13 01:03

skimberk1


People also ask

How do you communicate between two iframes?

Communicating directly between iframes is also possible by combining window. parent with target as defined above. In conclusion, the postMessage method is a more dynamic alternative to the single DOM, better suited if you load multiple pages in one iframe, but not always easier and it still requires the use of the DOM.

What is postMessage in Javascript?

postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.


1 Answers

Yes, you can identify the IFRAME which did the postMessage. There are different situations:

  • the source IFRAME has the same-origin URL (e.g. http://example.com/) as the Window which receives the message: the IFRAME is identified using

    myIFRAME.contentWindow == event.source

  • the source IFRAME has a same-origin but relative URL (e.g. /myApp/myPage.html) to the parent HTML page: the IFRAME is identified using

    myIFRAME.contentWindow == event.source.parent

  • the source IFRAME has a cross-origin URL (e.g. http://example.com/) different of the page which receives the message (e.g http://example.org/): the above methods do not work (the comparison is always false and accessing properties of event.source lead to Access Deniederrors) and the IFRAME must be identified based on its origin domain;

    myIFRAME.src.indexOf(event.origin)==0

In order to manage these three different situations, I'm using the following:

var sourceFrame = null; // this is the IFRAME which send the postMessage var myFrames = document.getElementsByTagName("IFRAME"); var eventSource = event.source; // event is the event raised by the postMessage var eventOrigin = event.origin; // origin domain, e.g. http://example.com  // detect the source for IFRAMEs with same-origin URL for (var i=0; i<myFrames.length; i++) {     var f = myFrames[i];     if (f.contentWindow==eventSource || // for absolute URLs         f.contentWindow==eventSource.parent) { // for relative URLs         sourceFrame = f;         break;     } }  // detect the source for IFRAMEs with cross-origin URL (because accessing/comparing event.source properties is not allowed for cross-origin URL) if (sourceFrame==null) {     for (var i=0; i<myFrames.length; i++) {         if (myFrames[i].src.indexOf(eventOrigin)==0) {             sourceFrame = myFrames[i];             break;         }     } } 

For cross-domain URLs, note that we cannot differentiate the true source if event.origin is a domain common to more than one IFRAMEs.

Some people use === instead of == but I did not found any difference in this context, so I'm using the shortest comparator.

This implementation has been tested and works under:

  • MSIE 9
  • Firefox 17

As an alternative (suggested by Griffin), you could use a IFRAME src with an unique idenfitier (e.g. timestamp), and the IFRAME'd web application will send back the this unique identifier in the posted messages. While the IFRAME identification would be simpler, this approach requires to modify the IFRAME'd web application (which is not always possible). This also may lead to security issues (e.g. the IFRAME'd web application tries to guess the unique identifier of other IFRAMEs applications).

like image 187
Julien Kronegg Avatar answered Nov 24 '22 01:11

Julien Kronegg