Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Browser Cross Domain Explained

5.00/5 (2 votes)
27 Jun 2013CPOL8 min read 30.5K  
Consolidating all the information that I have found on cross domain interaction in the web world

Introduction

This is a resource to use for all the different aspects of cross domain concerns in a web page. As a web developer, you research this kind of thing all the time: Cross Domain iframe communication, JSONP, CORS, etc., but I wanted one resource to consolidate all the information that I find. Please do leave comments correcting anything in this tip or mentioning something I left out.

Frame Interaction on a Page

Using JavaScript to access the DOM of an iframe on another domain

In a web page, when the parent window contains a child iFrame that is pointing to another domain, there is absolutely no way to access the content of that child iframe. In turn, the child iframe cannot access any content of the parent window. By content, I mean using something like using document.getElementId('frameid').forms[0] to get a reference to an element such as a form. There is only one exception to this. If two different domains only differ by their sub- domain. You can use JavaScript to set the domains of the frames to the main domain and then the frames will be able to access each other's content.

If the frames are on the same domain, then the frames can access each others content. In order to do this, you must get a reference to the iframe element usually by way of getElementId('frameid'). Then, there are two ways to access the actual window object in the iframe. The pre IE8 way and the normal way. As such,

JavaScript
function getIframeWindow(iframeElement){
    return iframeElement.contentWindow || iframeElement.contentDocument.parentWindow;
} 

contentWindow is what is provided by pre IE8 browsers. contentDocument.parentWindow is what is provided by all modern browsers. You can then use that reference to manipulate the DOM of iframe just as you would the main window.

Communication between frames on different domains

So the only useful thing that really can occur between 2 frames on different domains is communication, one frame sending a message to another frame. There are many ways to do this but the one constant is that both domains have to be aware of the communication contract. Otherwise, one frame would send a message to another and it would be ignored. Or one frame would be listening for a message that will never get sent. You cannot instruct an iframe from one domain to send a message to an iframe on an arbitrary domain that isn't aware of the contract and expect that something is going to occur, it won't.

Modern browsers make this easy with HTML5 specific postMessage. I don't need to describe it here. It's a very simple concept clearly defined in this article.

Older browsers require using hacks that exploit some of the openings in cross domain frame restrictions. These techniques are based on the only properties that different domain frames can interact with.

  1. URL Polling - A frame can set another domain src property, but it cannot read it. One frame can change the other frames src to be a different hash(#) value. The target frame must then use a timer to poll its own url to see if a change has been made and then do something with that information if it has changed.
  2. Name - A frame can modify the Name property of a frame
  3. Resizing - You can resize a frame and the target frame can register its onresize event to know that it should check its url hash to get a message
  4. Proxy - You can have 2 child frames from a different domain, one is hidden and is used to register the resize event and read its new hash value for a message. It will then send this information to the other visible frame that is on its same domain.

There is no point in implementing any of these solutions yourself. There are many libraries out there that provide this functionality already.

What is the point of using iFrames?
  1. Embedding content in a sandbox. The parent frame cannot modify the content of another domain's frame.
  2. Setting cookies. A child frame is the only way you can set a cookie from Domain B, in a main page from Domain A . In contrast, a JavaScript file included in domain A from domain B cannot set a cookie for domain B. Extra work is needed in Internet Explorer. Read this.
  3. Sending cookies. Frames send cookies related to its domain by default, you don't have to specifically tell it to like with Ajax.
  4. Downloading other content such as PDFs or Excel spread sheets without the main window being affected.

Communication to Different Domain Servers

When making an http request from one domain in the main web page to a server on another domain, the rules still apply: both domains have to be aware of the communication contract. If both domains don't agree to send and accept a certain message format, nothing can happen. For example: it is not possible to make a request to http://www.google.com (home page) with any of the following techniques and use the information that is received because www.google.com is not programmed to know about any specific client making the request.

Form Posting

The most basic way to send a request to a server from within a web site is through a form post. It is possible with JavaScript for you to programmatically add an iframe to the current parent window. In that iframe, you can then add a form that points to another domain. In that form, you can then add a series of hidden inputs that represent the information you want posted to that domain. You can then submit the form which will make a post request to that domain.

There is one small problem with this. When the iframe receives the response from the other domain, cross site restrictions kick in and you can no longer access the frame to get any information that was sent back. If you simply need to send information, this is no problem. If you need use the information received back, you need to use one of the techniques described above in communication between iframes on different domains. But if the domain you just posted to is not aware of you as a client, none of these techniques will work and you are out of luck. Read this.

JavaScript (JSONP)

Image tags are allowed to make cross domain requests, but the problem is you cannot do anything with the response except for showing the image. A script tag is also one of the requests a browser can make that doesn't have cross domain restrictions, but luckily you can do something with the response. So what's so great about this ability? For one, it is constant and reliable across all browsers. Also, cookies are automatically sent with the request even if it is to another domain. You can observe this by going to any site and inspecting the requests of the script tags in webkit network tab. This is what I see when I make a request to codeproject.com (you might have to zoom in).

Click to enlarge image

The main request is to http://codeproject.com. This page includes a script to ad.doubleclick.net domain. You can see that the request header includes the cookies that have been set previously from who knows where.

How can this be used? You can use this to make request to other domains and receive information from them similar to a web service API. Again, the one constant is that both domains have to be aware of each other and agree on the format of the communication. This is done with a technique sometimes referred to as JSONP (P = padding). You can include a script tag in your domain such as:

JavaScript
<script src='http://www.otherdomain.com?getinformation=true&parameter=1&parameter=2></script>
<script>
function doSomethingWithResponse(data){
alert(data);
}
</script>   

Again, the remote server domain needs to be aware that it will be getting requests of this type so that it can send the appropriate response as JavaScript code, such as this (raw JavaScript):

JavaScript
doSomethingWithResponse({thing:"stuff",information:"importantinformation"}); 

Usually, there is no need for you to implement this yourself. Most JavaScript libraries provide functionality to do this for you. For example, with jquery, you would do:

JavaScript
 $.ajax({
   type: 'GET',
    url: url,
    async: false,
    jsonpCallback: 'jsonCallback',
    contentType: "application/json",
    dataType: 'jsonp',
    success: function(json) {
       console.dir(json.sites);
    },
    error: function(e) {
       console.log(e.message);
    }
}); 

http://www.jquery4u.com/json/jsonp-examples/
JSONP is limited in that it can only do GET requests, not posts. There is no way to get a browser to make a POST request for a script tag. Also, as mentioned above, script files from another domain cannot set cookies for that domain.

Ajax

Ajax allows you to make async http request from the browser. But this technique is the most picky to use when doing cross domain communication. By default, you cannot make an Ajax request to a different domain than the window it is made from. In order to do so, you must use a technique called CORS. This is an official standard that is becoming more consistent in all browsers. I won't describe it in depth, there are many articles about it such as this one.

Again, the same principle applies here. Both the client and server must be intimately aware of each other in order for the communication channel to be established. The client must be approved by the server, who can blanket approve all clients or only certain clients by way of the domain. And the server must provide a certain structured consistent response that the client is aware of in order to use it. A client cannot arbitrarily make a CORS Ajax request to a server and expect to get back a meaningful response. Ajax CORS has an advantage over JSONP, in that it CAN do POST requests. Also, Ajax Cors is able to send cookies from the domain that is requested, but this must be specifically turned on with a setting (described in the article).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)