Cross Domain Message Passing using Iframe
User Rating: / 3
PoorBest 
Written by Girish Singh   







javascript_img_for_intro.pngDue to security restrictions of a web browser, passing messages in a cross domain environment is not that straightforward as it is in a uni-domain environment. A browser will not let any AJAX requests to pass through between two different domains, similarly two frames, open on two different domains cannot communicate with each other, and cannot access the DOM, or the JavaScript or the Cookies. How then can you pass information between two different domains ?

There are two popular ways to do it. Firstly we can modify the normal AJAX request to go around the cross domain restrictions. I have shown this is in my article Pear HTTP Request - A Cross Domain AJAX focused tutorial . The second way is to pass messages between two iframes using the URL Hash. This technique has been used very popularly in many JavaScripts, a very famous example being Dojo Toolkit. It is also called fragment identifier messaging (FIM) with IFrames.

 

Outlining the Technique

An Iframe can be opened on page, either statically or dynamically. Refer to article: Creating, controlling and manipulating an Iframe through JavaScript. We will use the script for dynamic opening of the Iframe given on the previously mentioned article.

Now consider two domains exampleX.com and exampleY.com between which messages/data has to be passed. Suppose the browser URL currently pointing to a page on exampleX.com. Using the message passing technique we will open an Iframe inside this page. This Iframe will then inturn load a page from exampleX.com only which will then open another Iframe which points to exampleY.com. Lets call them Iframe1 and Iframe2. Let us suppose Iframe1 loads a page testX.html and Iframe2 will load a page testY.html. These two pages need to be anything more than just blank pages with JavaScript content. The whole structure would be something like. 

Parent Window - exampleX.com
---- Iframe 1  - exampleX.com/testX.html
-------- Iframe 2 - exampleY.com/testY.html

The technique that we will be using to pass messages between two Iframes is modifying there URL hash. A URL hash is the string which follows the '#' symbol in a URL for example in 'www.mabaloo.com#hello' the URL hash is '#hello'. For a browser the URL hash is just extra information on page and altering it does not amount to a page reload, or referesh. This means you can modify the hash of a URL without the page being reloaded. Modifying the hash does equal modifying the URL. Javascript can access the URL hash by calling 'location.hash'

 

Iframe 1 - testX.html

The code for testX.html would be something like given below. This is just a sample code ment only for displaying the method to pass messages.

<html><head></head><body>

<script>
function generate_iframe(id, url) {
var IFrameObj;
if (!document.createElement) {return true};
var IFrameDoc;
if (!IFrameObj && document.createElement) {
// create the IFrame and assign a reference to the
// object to our global variable IFrameObj.
// this will only happen the first time
// callToServer() is called
try {
var tempIFrame=document.createElement('iframe');
tempIFrame.setAttribute('id',id);
tempIFrame.setAttribute('name',id);
tempIFrame.style.border='0px';
tempIFrame.style.width='1px';
tempIFrame.style.height='1px';
tempIFrame.style.display='none';
IFrameObj = document.body.appendChild(tempIFrame);

if (document.frames) {
// this is for IE5 Mac, because it will only
// allow access to the document object
// of the IFrame if we access it through
// the document.frames array
IFrameObj = document.frames[id];
}
} catch(exception) {
// This is for IE5 PC, which does not allow dynamic creation
// and manipulation of an iframe object. Instead, we'll fake
// it up by creating our own objects.
iframeHTML='\<iframe id="RSIFrame" style="';
iframeHTML+='border:0px;';
iframeHTML+='width:0px;';
iframeHTML+='height:0px;';
iframeHTML+='"><\/iframe>';
document.body.innerHTML+=iframeHTML;
IFrameObj = new Object();
IFrameObj.document = new Object();
IFrameObj.document.location = new Object();
IFrameObj.document.location.iframe = document.getElementById(id);
IFrameObj.document.location.replace = function(location) {
this.iframe.src = location;
}
}
}


if (navigator.userAgent.indexOf('Gecko') !=-1 && !IFrameObj.contentDocument) {
// we have to give NS6 a fraction of a second
// to recognize the new IFrame
setTimeout('callToServer()',10);
return false;
}

if (IFrameObj.contentDocument) {
// For NS6
IFrameDoc = IFrameObj.contentDocument;
} else if (IFrameObj.contentWindow) {
// For IE5.5 and IE6
IFrameDoc = IFrameObj.contentWindow.document;
} else if (IFrameObj.document) {
// For IE5
IFrameDoc = IFrameObj.document;
} else {
return true;
}

IFrameDoc.location.replace(url);
return false;
}

////////////End of Function to generate Iframe/////////

function checkForMessages()
{
if(location.hash != orig_hash)
{
message = location.hash;
window.clearInterval(intval);
//message now contains the message which has been passed from exampleY.com.
// You can do process it further. However I will just alert it.
alert("The message recieved is " + message);
}

var orig_hash = location.hash; //////saves the original hash of the page to compare for changes.
intval = setInterval(checkForMessages, 200); ////// sets an interval for the function which keeps checking for change in the URL hash
generate_iframe('Iframe2','http://exampleY.com/testY.html'); ////// opens another Iframe which points to exampleY.com
</script></body></html>

Now lets and stop and see what is happening on testX.html. Firstly the Iframe testX.html is blank it has absolutely no purpose besides recieving a message from exampleY.com. This need to be the case everywhere but since I m just showing how it works there is not much need for anything else. Now testX.html contains two JavaScript functions - generate_iframe() to generate an Iframe dynmically, checkForMessages() to check for messages. When the page testX.html is loaded it generates an Iframe which open the location of testY.html, it also  sets interval of 200ms to checkForMessages() to execute.

Let me explain how the function checkForMessages() works. Its actually very simple the function just compares the current URL hash with the original hash. If they are not same(means a message has been passed) it extracts the hash clears the interval (assuming only one message will be passed and checkForMessage() does need to be called again). You can then use the message which has been extracted further. (Remember location.hash start with the character '#'). I have just alerted the recieved message since it is a test script. 

 

Iframe 2 - testY.html

The code for testY.html would be something like given below. This is just a sample code ment only for displaying the method to pass messages.

<html><head></head><body>

<script>
var parent_location = 'http://exampleX.com/testX.html'; ////// Assuming Iframe1 has loaded this location. Please not the parent location needs to be correct else the function will not work.

function send_msg(msg)
{
parent.location = parent_location + '#' + msg;
}

send_msg('message');
</script></body></html>

This is relatively simple as compared to testX.html. However its just a demonstration, and so I have just assumed a fixed message to be sent. There is only one function called send_msg which takes the message as its parameter. It then sets the parent.location as the current location plus the message has the URL hash.

 

How it all Fits

I am sure by now you must have guessed it all. Iframe1 opens another Iframe2 inside it and keeps checking for changes in its URL hash. Iframe2 loads a page which modifies the URL hash of its parent or in this case Iframe1. Rest is almost too easy to explain. As soon as the URL hash is changed the function checkForMessage() in testX.html catches this change and extract the new URL hash(message). Thats it. We passed a message from one domain to another. WOW... Its very simple....

 

The Bigger Picture

1.) In real application you will almost never have Iframe1 and Iframe2 functioning just as plainly as shown. A simple scenario can be that when a user logs into one website, we can color the page in his favourite color which is fetched from lets say another website (Ya right, favourite color.... thats all I could think of). So for this it will proceed in this fashion. As soon as the user returns to the page after logging in, we can check a cookie or variable, which identifies if a user is logged in. Now if the user is logged in, then we can dynamically generate Iframe1 using the function generate_iframe() which will load the page testX.html. Now Iframe1 will now inturn open another Iframe2, which loads a page from another website. Here the Iframe2 makes an AJAX call to fetch the favourite color. When it gets the favourite color it passes the message to Iframe1 by modifying the URL hash, Now as soon as Iframe1 recieves the message it extracts the URL hash and then calls a function in the parent page which changes the background color (Refer to my article: Accessing parent function from Iframe)

2.) We can also send the URL of the parent page as GET parameter to the page on exampleY.com. Something like exampleY.com/testY.html?url=exampleX.com/testX.html.  This will remove the constraint of knowing the URL of parent page before hand. Refer to my article on accessing GET parameters with JavaScript. (DO Not forget the URLEncode the URL before sending it as a GET parameter. Refer to my article on URL Encoding and Decoding)

 

The Problem with this Technique

Although it works absolutely fine in all browsers, the recently released IE7 is by default set to consider cross domain nested Iframes as popups. Thus this technique will not work straight face in IE7.
Refer to my article http://www.mabaloo.com/Web-Development/IE7-Breaks-Fragment-identifier-messaging-FIM-with-IFrames.html for the solution.

 

 







 

Quote this article on your site

  Be first to comment this article

Only registered users can write comments.
Please login or register.


Powered by AkoComment Tweaked Special Edition v.1.4.6
AkoComment © Copyright 2004 by Arthur Konze - www.mamboportal.com. All right reserved

 
< Prev   Next >




Privacy Notice | Advertising Info | Feedback | Contact Us | Partners

The information and views presented above are by the author. Mabaloo.com does not take any gurantee of accuracy.
The views expressed above are that of the author and in no way related to mabaloo.com
Highlite It
© 2007 @ mabaloo.com.