I’ve been playing with cross-domain (XD) data-pushing techniques lately and now I’ll try to compare each available technique. These techniques allows server to push messages to the client. A brief summary of comparison is available in the table below, following the table you can find more detailed explanation for each technique.

Technology Reading Data Writing Data (HTTP GET) Writing Data (HTTP POST) Advantages Disadvantages Conclusion
XHR No Yes No XHR is good at error handling
  • Only very recent browsers implementing access-control specs allow requests to be made.
  • Cannot read responses at all
  • Data writing is limited to 2kb

FAIL

Because: a cross browser method with XHR for XD communication does NOT exist.

Script Yes Yes No
  • Can read the responses
  • Easy to implement
  • Hard to detect connection problems
  • Data writing is limited to 2kb
  • Long-polling is required.
  • If remote site is not trusted, can run arbitrary code on your site.

Works

IFRAME + hack Yes Yes No
  • Can read responses
  • Remote sites response can be filtered by your proxy program (i.e. php) on the origin, hence a not trusted remote site can be used.
  • A relaying/proxying dynamic program (i.e. php) is necessary on the domain the request is originating from.
  • Long polling is required.

Works

IFRAME + form No Yes Yes Can send large data
  • Cannot read responses
  • “Start navigation” (aka click) sound of IE when you do form.submit() is really a sad deal breaker.

FAIL

Because: see Disadvantages

IFRAME + form + hack Yes Yes Yes
  • Can send large data
“Start navigation” (aka click) sound of IE when you do form.submit()
(NOTE: This really is a deal breaker, funny fun though)

FAIL

Because: see Disadvantages

Flash Yes Yes Yes
  • A true persistent TCP connection ready to be used.
  • Good error handling
  • Can deal with binary protocols, hence can save bandwidth around 90%
Note that I’ve tried very very hard to find disadvantages of this method.

  • Plug-in availability debate.
  • Not available in mobile platforms
  • Slim chance of network problems

Works

Yes: Able to send request and read the response. i.e. Being able to send a request to http://foo.com/write.php?data=bar, which writes data “bar”, and in return being able to read the response (such as “Write Successful” or “Write Fail”
Yes: Able to send request but cannot read the response
No: Cannot send request nor response.

Introduction

I’ve studied cross domain communication as it is two separate tasks; one is reading other one is writing.

Available Methods

1. XHR

XHR is the way to go with same-origin requests (i.e. non-XD), unfortunately it does not with with XD requests. So far browsers would simply throw an exception when you tried to do a XD request via XHR, which is defined by the standard.

If the origin of url is not same origin with the XMLHttpRequest origin the user agent should raise a SECURITY_ERR exception and terminate these steps.

A new standard is worked out called access-control which now enables you to do XD XHR requests. Essentially it is what Flash’s policy file is to the XHR. XHR is only allowed when the target domain explicitly allows your domain.

  1. Should not allow loading and exposing of resources from 3rd party servers without explicit consent of these servers as such resources can contain sensitive information.

You can find more detailed information about the reasons of these decisions in my previous post.

So what this means is;

  • Only if a very new browser with the new specs implement is being used,
    • and target domain explicitly allows the originating domain then XHR can be used for XD communication.
    • and if target domain does NOT explicitly allows the originating domain, only simple requests such as GET will be send to the target domain, and response will not be readable by the script.
  • If a browser with new specs implement is NOT being used, then a security exception will be thrown right away.

Conclusion: FAIL.

Because a cross browser method with XHR for XD communication does NOT exist.

2. Script

Script is one of the elements which are not restricted by the same-origin policy (SOP). Script is abused in such a manner that it allows us to do XD communication. Below figure demonstrates how script method works.

Script method workflow

Here’s what’s going on in the above figure:

  1. origin.com tries to load a JS script from remote.com/service.php
  2. as the script from remote.com loads, it immediately calls a message handler in origin.com
  3. hence remote.com passed information to origin.com which is an actual XD communication.

Here’s what the mysterious $.getScript does roughly;

  1. Create a <script> element in the origin.com
  2. Set src (source) property to “http://remote.com/service.php”.
  3. Adds the newly created script element to <head> element of the page.

Of course, in practice JQuery does a little bit more to ensure performance and browser compatibility.

Conclusion: Works but…

  • Data writing is handled with query parameters in the URL of the HTTP GET request. Such as http://remote.com/service.php?data=value. This comes with the restriction of the URL length. In practice, a 2kb of URL is said to be cross-browser compatible. So data writing is limited to 2kb.
  • Long-polling is required to get a persistent connection going. i.e. once the server gives the response, you need to re-establish the connection. This wastes resources such as bandwidth.
  • Error detection is not built-in. Browser does not tell if you if the server broke the ongoing TCP connection (which is the HTTP GET request). So you need to handle errors in your code.
  • remote.com should be trusted, as it will execute code on your page.

3. IFRAME hack

This is a hack which is explained quite well in Facebook wiki.

Different from script method, this hack requires a proxy program (xd_receiver.php in the figure above). This has the advantage of you can filter the data coming from remote.com (facebook.com in the figure). But this is also has the disadvantage of adding another layer of maintenance in the chain.

Conclusion: Works but…

  • All the problems with the script methods applies to this method, except the lust one, the remote.com trust issue.

4. IFRAME + form

This technique enables you to post data to remote.com, without apparent reload of the page (i.e. AJAX-ish).

Here’s how:

  1. You create a <form> element, set it’s .method to “POST” and .action to “http://remote.com/service.php”
  2. Create an <iframe> and insert the <form> element you’ve just craeted
  3. Call form.submit();

From my tests with Chrome and Firefox I’ve seen that this actually posts the data (I can see it on my server) but cannot read the returned result from the server. Which means you cannot see if the result of POSTing actually did something on the server. You just POST it.

Another deal breaker is the “click” sound Internet Explorer makes each time you call submit(). This practically renders this method useless itself.

Conclusion: FAILS because…

  • You cannot read the response from the server from Javascript.
  • Each time you call submit() method, Internet Explorer makes the click noise (which is called “Start Navigation”)

5. IFRAME + form + hack

I haven’t tested this technique in theory you should be able to merge the technique 3 and 4 together to form this. To make this happen, http://remote.com/service.php should make a HTTP redirect to http://origin.com/xc_receiver.php?data=response.

Though the “click” sound of Internet Explorer practically renders this solution useless too.

Conclusion: FAILS because…

  • Each time you call submit() method, Internet Explorer makes the click noise (which is called “Start Navigation”)

6. Flash

This method has so much advantages that I’m very surprised that it is so rarely used. i.e. it is not used for Facebook chat.

In this method you use an invisible Flash object which provides an interface to the Javascript code via ExternalInterface.addCallback, and access to Javascript code via ExternalInterface.call(). It works like a charm and TCP connection capabilities of the Flash is naturally much much more robust than the above hacks. Flash also provides very good error handling.

Plus you can use binary protocols with this, which can reduce bandwidth from 10x to x easily. You can upload any amount of data and receive any amount of data. You can a real TCP connection ready for your command for all times. Spectacular!

As an example a sample Facebook chat packet is 686 bytes including HTTP headers but the actual data is only 179 bytes. Facebook uses long polling, so every packet must be wrapped in a HTTP packet, hence the overhead is quite significant. Also this data is packed in rather verbose JSON format. If it was also a binary format the savings would be more, such as 80 bytes instead of 686 bytes. Rationally speaking though, packing data in binary for WEB might not be very wise and might not just worth the effort. Just getting rid of off HTTP overhead saves %73 bandwidth. On the other hand a hypothetical binary protocol could have save 88%. While that little %15 bandwidth could mean a lot for high scale web sites, it might well not worth the effort since it complicates things and adds other layers to design. Anyways…

Flash is so good that it is hard to find an argument against it. I’ve tried really hard;

Flash is a plug-in!

Availability of Flash can be questioned. According to http://www.adobe.com/products/player_census/flashplayer/version_penetration.html, market penetration of Flash 9 is 99%. I think, this makes Flash a even more portable way than above solutions. And according to google-analytics of our site which receives 30k visits (I know not very big), 100% of the users have Flash.

Not available in mobile platforms!

True. Currently Flash support on mobile devices are limited. Though there’s this fact that, each mobile device inevitably requires its very own UI design. For instance, Facebook’s mobile HTML page dose not offer Chat functionality at all. Though other native applications for iPhone and Windows Mobile offers this service.

That’s to say, each mobile device will inevitably has its own UI anyway (which doesn’t use Flash). So this argument is not very sound neither.

Flash’s TCP connection could be blocked!

Common firewall set ups do not block outgoing TCP connections. And if you use a known port for your remote.com such as 80 or 443, your Firewall most likely can’t tell the difference. To tell the difference a statefull Firewall is required, and if a network has those firewalls most likely most of the sites (such as Facebook) are blocked anyway.

Another network problem could be that, all TCP connections are blocked and only HTTP Proxy is allowed, so that your browser is configured to use that HTTP Proxy by default. In this case Flash will fail. Though other methods mentioned above could also fail when a proxy is present. i.e. a long persistent connection which long polls use are not what HTTP Proxies are designed for.

Conclusion: Works

Finally

As you might have already noticed my personal bias is towards Flash, though I’m not sure why it isn’t wildly deployed as I’d imagine. I have successfully implemented the <script> and Flash methods myself, and I believe Flash is superior. I think only time can tell which is the best solution :)

Cheers.