Tuesday, December 16, 2008

Exploring Cross Document Communication

One of the new features that HTML5 offers web developers is a way to send information between documents on different sites via Javascript. Currently for security and privacy reasons, browsers prevent cross site scripting but with HTML5's Cross Document Messaging, the intention is to allow documents to communicate with each other without sacrificing security.

To experiment with these methods and events, you'll need to be running either IE8, Firefox 3 or the WebKit Nightlies. Opera 9+ provides support as well, but they use an older version of the spec which required the postMessage method to be called from the document object instead of the window object.

There are two key steps involved with HTML5 Cross Document Messaging. The first is posting the message. You do this by calling the window's postMessage() function. The postMessage function takes two arguments: the message to be sent, and the target origin.

Then, to receive the message in the other window, you need to watch for the window's message event using window.addEventListener or something similar. To help show how this works, I've set up an example for you to see here. In my example, both the sending window and the receiving window are located within the same domain (timkadlec.com), but as long as you have a reference to a window, you can communicate cross domain the same way.

Walking the Code


Take a look at the source code and you'll see that I'm simply using one window (window A) to open the other (window B) so that I have a reference to it. Window B contains two buttons that when clicked, use the postMessage method to post a message back to window A, like so:

  • window.opener.postMessage('John Smith', 'http://www.timkadlec.com');


We use window.opener to get our reference to window a, and then call the postMessage function and send the message 'John Smith' back to it. We specify that the origin is timkadlec.com in the targetOrigin argument.

Now back in window A, we need to prepare to receive the message. To do so, we look for the message event.

  • window.addEventListener('message', receiver, false);


As you can see above, I'm using addEventListener to listen for the message event, and once the event occurs, we call the receiver function.

  1. function receiver(e){

  2. if (e.origin == 'http://www.timkadlec.com') {

  3. if (e.data == 'John Smith') {

  4. alert(e.data);

  5. e.source.postMessage('Valid User', e.origin);

  6. } else {

  7. alert(e.data);

  8. e.source.postMessage('FAIL', e.origin);

  9. }

  10. }

  11. }


In the receiver function, we verify that the origin of the event is timkadlec.com (line 2). This is highly encouraged, as it ensures that we only receive messages from domains we are expecting to hear from. If you skipped this step, any domain could freely affect your page, and that could get a bit messy.

Then, we use the event's data property to retrieve the message that was sent. Based on the message received, we then use the source property of the event to obtain a reference to the window that sent the message. Then, again using the postMessage method (lines 5 and 8), we send a message back to window A.

This is a pretty straightforward example, and is really just meant to demonstrate how easy it is to post messages back and forth between documents. There's another good example up that makes use of iframes if you want to see another example of cross document messaging.

Some Security Considerations


Hopefully you can see that cross document messaging is both simple, and potentially quite useful for things like widgets, or authentication. However, there are some security risks if you don't take the time to double check a few things. First, like mentioned before, you should always double check the origin of the sent message. You don't want to be just accepting messages from anyone...that's kind of the reason cross-site scripting isn't allowed in the first place.

Secondly, it is possible to use the asterisk in the targetOrigin argument to allow your message to be posted to any domain. However, you should be sure to never use the asterisk symbol when sending confidential information. In those cases, you should be specifying the targetOrigin specifically so that you can guarantee that only the intended recipient gets the information.

Tuesday, December 2, 2008

Manageable CSS with CSSDOC

I've been very interested in finding better ways to create CSS stylesheets that are easy to navigate, understand and maintain. After leaving a stylesheet alone for awhile, if you didn't take the time to organize the stylesheet originally, it's really easy to forget why certain rules are being used, or where you defined styles for an area. One way of managing your stylesheets that's got my attention is CSSDOC.

CSSDOC was an idea apparently conceived sometime in 2007, and the Second Public Draft of the spec was just released on November 16th. The intent behind CSSDOC is to provide a standardized way of commenting CSS making use of the very well known DocBlock way of commenting source-code.

DocBlock is a very common form of documenting source code in programming that has proven to be very popular for both PHP and Javascript. The beauty of the method is that it's so simple to use DocBlock to organize your code and since it's a standardized format, other developers will be familiar with it and tools can be developed to parse it and auto-generate documentation.

There are a great deal of tags being developed for CSSDOC that can provide a lot of great information. For example, here is a sample header from the CSSDOC draft:

  1. /**

  2. * Homepage Style

  3. *

  4. * Standard Layout (all parts) for Big Little Homepage

  5. *

  6. * This style has been designed by Mina Margin. It reflects

  7. * the composition of colors through the years of the

  8. * customers project as well as the boldness it implies.

  9. *

  10. * @project Big Little Homepage

  11. * @version 0.2.8

  12. * @package xhtml-css

  13. * @author Mina Margin

  14. * @copyright 2008 by the author

  15. * @cssdoc version 1.0-pre

  16. * @license GPL v3

  17. *

  18. * @colordef #fff; white

  19. * @colordef #808080; standard grey

  20. */


Just by this simple header, we've already provided a great deal of information to both future developers and to a documentation parser. In our header we've provided the project we're working on, a version number for the project, copyright and author information, and some definitions of recurring colors used in the project.

You then make use of the @section and @subsection comments to divide your CSS file into manageable sections of related styles. I'd love to see this implemented in editors like CSSEdit's @group comment. For those of you unfamiliar, the @group comment in CSSEdit is parsed out and made into easy to navigate folders in the sidebar (see the image below).

CSS Edit - Screenshot

I won't go through all the available comments (the draft can give you that and does a great job of explaining), but suffice it to say there's a lot of extremely useful comments available: @affected comment which describes what browsers are affected by a certain bug/workaround; @tested comments to specify what browsers a certain section has been tested on; @fontdef for font definitions, similar to the @colordef rule in the example above; etc.

I'm very excited by this project and think the team behind the spec has done a fantastic job thus far. The few concerns I had, they've either addressed, or are in the process of doing so. It's very easy to get involved with the project as they have been very transparent in the development of the specification.

In addition, if you want to start playing around with CSSDOC a bit on your own CSS, there are bundles made already for editors like Textmate, EditPlus, and KomodoEdit just to name a few. You can keep up to date on new bundles and snippets at http://cssdoc.net/wiki/EditorIntegration.