Include external Javascript and CSS files with a Google Wave Gadget

When deploying a Google Wave Gadget that depends on external resources such as images, javascript libraries and CSS stylesheets, resources referred to by relative paths do not load correctly.

The problem is as follows:

  • a gadget is deployed on a third party server
  • a gadget is loaded as a plugin of the Wave framework
  • to the client browser, the gadget appears to be loading from the Wave service URL
  • relative paths attempt to resolve to the Wave service domain, while the resources are sitting on the third party server

A naive solution would be to translate all relative paths to absolute paths that refers to the “real” location of the gadget, mainly URLs based on the third party server domain. However, this is not a workable solution. The problem with absolute URLs has to do with browser security, where certain resources can not be loaded from domains other than the domain of the original page. Since the resources associated with the gadget are not located in the same domain as the Wave service, then some resources will not load, depending on type and browser security enforcement.

The working solution is to proxy all resource requests via the Wave service. In this manner, all resources associated with the gadget appear to be served from the same domain as the original page.

This solution is based on the “Gadget libraries” and is not restricted to Google Wave Gadgets, per se. It might be applicable to other social gadgets as well.

The described solution is to:

  1. Insert “bootstrap” code in the gadget module XML file
  2. Use bootstrap code to load external resources

The bootstrap code is shown below:

getModuleBase()

This function retrieves the “real” URL of the gadget and returns the absolute path to the directory containing the gadget. This function computes the absolute path by retrieving the Gadget parameter called ‘url’. This information is provided by the gadget framework, which provide all gadget parameters via an associative array obtained with a call to _args()

rebaseRelativeUrl(relPath, shouldProxy)

This function accepts a path (relPath) relative to the gadget location and returns an equivalent absolute URL. This function uses the getModuleBase() to make this computation. If the flag ‘shouldProxy’ is set, then the returned URL is an equivalent URL, however it is proxied via the gadget framework. This conversion is possible because of the _IG_GetCachedUrl() available with the gadget libraries. Therefore, when the flag is set, a path relative to the location of the gadget is converted to an absolute URL proxied via the gadget framework, avoiding browser security issues.

addStylesheet() and addScript()

These utility functions add style sheets and external javascript by using the rebaseRelativeUrl() and adding the appropriate elements to the document. These functions are available at run-time and should probably not be used before the gadget is loaded.

gadgets.util.registerOnLoadHandler()

This function is often used in gadget development and generally well understood. It will not be covered here. The reason for inclusion in the post is that this is the location where the external resources should be loaded, as shown in the example above.

Example, please?

Sure. An example gadget is available here: http://owh01-ig.googlecode.com/svn/trunk/gadgets/counter2/counter2.xml

Leave a Reply

Your email address will not be published. Required fields are marked *