Thursday, January 31, 2008

Browser and Dojo updates on Fragment ID messaging

Some browsers have changed how they deal with fragment ID messaging:

Safari 3 throws an error if a child frame tries to change a parent frame's location, but only if the parent frame is not the top-most frame. So, this test works, but this one fails. Parent frames are allowed to change a child frame's location.

Opera 9.25 has locked down cross-frame access to some frame properties. As Julien LeComte pointed out, Opera supports the HTML5 cross-document messaging API, so that is a viable alternative.

I have updated dojo.io.proxy so that it now works in these browsers: IE 6 and 7, Firefox 2 and 3beta2, Safari 3 and Opera 9.25. You can get it from the Dojo development trunk, or wait for Dojo 1.1. The new dojo.io.proxy code works with Dojo 1.0, and there are no API or usage changes.

This new code also improves the IE7 codepath: before the code used to use 3 frames to do the transport, but now it only uses 2 frames, like the rest of the browsers. I was not being very smart about the ordering of the frames in the old code.

Thanks go to Julien LeComte for pointing out the Opera cross-document API and for diagramming another way to do fragment ID messaging.

dojo.io.proxy differs from Julien's CrossFrame approach:
  • it allows very large messaging (it supports fragment ID chunking)
  • it is focused on providing a data transport -- it provides an XMLHttpRequest facade. It is not a communication transport for UI widgets.
Julien did not want to use location polling, since it increases CPU usage. dojo.io.proxy does use polling to do the communication (this allows for chunking to support large messages), but polling is active only while the message is in transport. I consider the window.location polling less resource-intensive than doing a DOM animation. CPU usage could be tuned by slightly extending polling interval if it is a concern.

dojo.io.proxy creates the frames only when the request starts, then it destroys the frames when the response finishes. This preserves the history stack in all browsers except Opera.

There is a very primitive test page if you want to see the latest code in action.

2 comments:

Andrés Testi said...

I've discovered that Firefox allows to invoke cross site functions setted at window.location. For example:

// Domain A page:
....
window.location.crossdomain = function(arg){
alert("received: " + arg);
};
....
<iframe src="http://domainb.com/domainb.html" />


// Domain B page
...
window.parent.location.crossdomain("hello");
...

James said...

Andrés Testi: Interesting trick! I think Firefox 3's support for the cross document messaging API will be a more robust solution for the future, but maybe using your location approach might work for older Firefox browsers. Although I'm hoping that older Firefox versions quickly go out of rotation and we can just rely on the Firefox 3 behavior.