Wednesday, October 11, 2006

IE 7 Breaks IFrame APIs that use parent.location

Update (Nov. 7, 2006): Microsoft provided more information. See Part 2.

Original post (Oct. 11, 2006):

One of my co-workers was recently testing IE 7 RC1 and found that using fragment identifier messaging (FIM) with IFrames did not work. When the content in the nested IFrame tried to set parent.location, IE 7 popped a new window instead. If you have an IFrame-based API that uses parent.location, then you might be affected by this change.

I would like Microsoft to reconsider the preference change in IE 7 that causes this issue, and this post describes why. Feel free to contact Microsoft if you feel likewise. More information below.

When I investigated the issue more, I found that IE 7 only popped a new window if there was a nested IFrame. If there was just an IFrame in the top level document/browser window, it did not pop a window.
We contacted Microsoft through our company's Microsoft channel, and found out the following:
  • There is a preference that was introduced in Windows XP SP2 that controls this behavior. You can find it by looking in the Internet Settings -> Security Tab -> Click on Custom Level button -> "Navigate sub-frames across different domains".
  • With IE 6, this is set to "Enable" by default.
  • When IE 7 installs, IE 7 automatically sets the preference to "Disable" by default.
I would prefer that they do not change the preference for the following reasons:
  1. There is no documentation about the change, and the change was done without checking with the web developer community.
  2. I think the behavior is buggy and could use refinement.
  3. Fragment identifier messaging (FIM) across IFrames is the best thing we have for allowing pure browser, cross-domain web APIs.
If you feel the same, or if you feel that your own IFrame-based web API that sets parent.location might be affected, then send feedback to Microsoft. I will try to find out where we can send feedback and update this post when I have the info.

More information on why I think IE 7 should keep the preference as "Enabled":

No public documentation of discussion

Our Microsoft contact did not provide any public info indicating this was documented or discussed publicly. When I asked for a description of the change, there was no documentation that was ready for public consumption yet. There might have been some public disclosure about it, but I am not aware of any. I apologize if there was something posted. I have been subscribed to the IEBlog for a while now, but none of the previous posts triggered any warning bells for me. But I could very well have missed it.

This page describes that security preference, but reading does not seem to be very helpful (and seems to discuss talking to sub-frames and not parent frames).

I do not mean to chastise Microsoft on this point. I can appreciate with such a large project as a browser, it might not always be evident what changes can have an adverse effect on people using your product. And even if they did note it somewhere, there are lots of changes, and it could very easily get lost. It has happened to me on my software projects.

I can also see that their answer could be "why don't you just test with the IE 7 betas and release candidates? If there is an issue, let us know". That is a fair and valid position to take. But just as it might be hard to document and message all the changes for a large product like IE 7, it can be hard for web developers to stay on top of everything. I can see many not taking IE 7 testing seriously until RC 1.

And given that the parent.location works as long as you are communicating with a browser window and not an IFrame, I can see for some developers using IFrame APIs, there might not appear to be an issue.

For my case, with the XHR IFrame Proxy, I just worked out that solution July 31st. I haven't done IE 7 testing because I have been busy, and I thought the big things for that release were CSS-related changes (from a web developer POV). There did not seem to be that many JavaScript changes (besides an apparent increase in the JS engine performance). But still, I feel bad getting around to this issue this late in the IE 7 cycle.

So, ideally both of us could have caught the issue sooner and talked about it, but it is understandable that it did not happen. And I hope that since it is a preference change, that changing the IE 7 behavior back to "Enable" is hopefully an easy thing to do even this late in the IE 7 cycle. This would give more time to discuss the issue.

Behavior is buggy and could use refinement

I am sure there is a good use case to justify having this preference, and perhaps it even describes the current behavior. However, from my outsider's point of view, it seems buggy.

Why is Test Case 1 allowed (setting parent.location on the top browser window), but setting the parent.location on an IFrame is not allowed? They both seem to be "cross frame" communication, and violate whatever security issue the preference tries to address.

In addition to addressing the apparent bug with the behavior, I think setting parent.location should be allowed if the new value for parent.location is the same protocol, domain, port and path, but just differ by fragment identifier. In those cases, the parent document is not destroyed or modified, so perhaps whatever security issue is being addressed with this preference does not apply? Allowing fragment identifier changes is important for the next point...

FIM is the best thing we have for allowing pure browser, cross-domain web APIs

There are other ways to do cross-domain communication in a browser, but they all suffer from some limitation that does not make them a good general purpose, pure browser solution.

I also believe Fragement Identifier Messaging (FIM) that is used as part of the XHR IFrame Proxy is the most secure cross-domain communication option, since it requires explicit action for a server to allow the cross-domain action, and it has very fine grain control on the types
of requests that are allowed. FIM also does not automatically "execute" the response as using dynamic script tags might. The receiving frame can choose to just ignore messages if it wants.

And with the exception of the current behavior in IE 7 RC 1, FIM works in all other (major) browsers: IE 6, Firefox 1.5 and 2.0, Safari 2.0, and Opera 9.

The real solution would be a native XMLHttpRequest that can do cross-domain requests, but even when that becomes available, it will take a couple of years at the least to be widespread enough that it is actually be usable by web developers for cross-browser solutions.

In Conclusion

Microsoft, please do not change the preference to "Disable" with IE 7. Keep the default "Enable" behavior of IE 6. If at some point you want to change the preference to "Disable" by default, consider a public discourse of the implementation issues discussed here and the impact on FIM.


Gideon Lee said...

I agree with your comments that this new default behavior will break a very useful browser behavior. They should at least give an HTML attribute or scripting option so that the site hosting the frameset can at least make the decision.

Anonymous said...

Absolutely agree with your comments, I have been generally disappoint by Microsoft with the release of IE7. Distinct lack of information with regards to changes likely to affect production websites. Although I agree that this setting should be left as it is - i don't see that happening any time soon and I need a solution now!

James said...

Anonymous: You can see the Part 2 entry for a workaround from Microsoft.

Jakob Flygare said...

I have a parent page that is UTF-8 encoded with an iframe that is ISO-8859-1 encoded. In the iframe the special characters æ, ø and å are rendered as boxes due to the encoding of the parent page. How do I solve this problem?

James said...

Jakob: I am not that good with encodings, and in particular how to switch encodings between two documents. If you find a solution, it would be good to know.

Anonymous said...

Totally agreed. This is nasty and terribly hard to deal with.

Anonymous said...

I support 13000 external web users and i can say for a fact this iframe issue is a biggy. Microsoft is so crap(as always) and im going to have to inform all these external people to move to firefox hence forth so that they dont encounter the 'microsoft' problem any more, ever.

Anonymous said...

I'm using a shopping cart that posts to a https page on another server for entering the Credit card info. Has anyone herre been successfull loading an https page into an iframe on an http page using this method? Any posts or examples you can send me to would be helpfull.

Ellen said...

I've posted a workaround that is working for me here:
IE 7 blocks communication between iframe and parent page in another domain

Shilpi Gupta said...

I ran into exactly same issue where setting parent.location used to open new windows. My site had nested iframes and I was doing quite some cross communication using fragments. It was completely messed up in IE7 SP2. If this blog was not there, I would have never figured out the root cause.

Thanks a ton!!!!!!

Microsoft people should have published it explicitly. Disabling a setting which was enabled in previous versions is not what is want.

Mehul said...

Non backward compatible change.. i should be paid back for investing my time & breaking my head on this

Shilpi Gupta said...

Moreover, Microsoft should write specially apologies to all the people who wasted their precious time figuring out this issue.

Rolling out a backward incompatible change is absolutely incorrect!!!

Mehul said...

I will forward this blog to my friends in Microsoft so that they can pass it on to people who were involved in the change