Gmail for mobile HTML5 Series - Part 2: Using AppCache to Launch Offline

MAY 07, 2009
On April 7th, Google launched a new version of Gmail for mobile for iPhone and Android-powered devices built on HTML5. We shared the behind-the-scenes story through this blog and decided to share more of our learnings in a brief series of follow up blog posts. Last week we explained how to go about creating a simple manifest file, and how the browser uses it to load a page. This week we will go a bit more in-depth about the subject.

One of the problems we faced in creating our manifest file, was how to update it when our javascript changes. At first we thought that we might have to change one of the URLs each time we wanted to push an update. As it turns out, the URLs listed in the manifest do not have to change at all in order cause an update, changing the whitespace or a comment will also do the trick. For Gmail, we a comment in the manifest that contains a hash of all of the resources listed in the manifest. That way, if any of the resources change, the manifest will also change and cause a background update to occur for all of our clients. An example of what this looks like is shown below.

CACHE MANIFEST
# version: 3f1b9s84
jsfile1.js
... other URLs ...

There are other types of entries that are possible in a manifest, but that the iPhone does not currently support. According to the spec, there are 3 categories of URLs that can be listed in a manifest:Although fallback and network URLs are not yet supported on the iPhone, they are mostly supported in the Webkit Nightly builds. Network URLs are those that are never cached by AppCache, and that are allowed to be satisfied by the network. Fallback URLs are those that are attempted, and then satisfied by by AppCache only if the network attempt fails. Both Network and Fallback URLs are prefix matches. An example of what this looks like is shown below.

CACHE MANIFEST
jsfile1.js

NETWORK:
/images/

FALLBACK:
/thumbnails/ images/missing_thumb.jpg

This manifest tells the browser that GET requests to any URL under /images/ are allowed to hit the server. Without this being listed, GET requests for it would fail immediately. This manifest also tells the browser that URLs under /thumbnails/ are allowed to hit the server, but if they fail, satisfy the request by server missing_thumb.jpg, which will be stored in AppCache.

So far all of the features we've covered about AppCache have not needed any Javascript to use them. This is undoubtedly by design, as it makes it extremely easy to use. However, it is always useful to know what advanced functionality can be unlocked using Javascript. The Application Cache is exposed as a singleton through window.applicationCache. It provides events that can be used to indicate when updates are happening and a status property that can be one of:In Gmail, we use the status property to determine if the page was loaded out of AppCache, or if it was loaded from the network. In order to do this, we have the following code run at the very start of page load:

if (window.applicationCache.status == 0) {
// Page was loaded from the Network.
} else {
// Page was loaded from AppCache
}

There are also a couple of functions available, swapCache and updateCache, which we'll not go into detail on since we have not found any use for them yet.

Stay tuned for the next post where we will explore how to use the sqlite3 command-line tool to inspect the iPhone Simulator's AppCache database. And just another reminder that we'll be at Google I/O, May 27-28 in San Francisco presenting a session on how we use HTML5. We'll also be available at the Developer Sandbox, looking forward to meeting you in person.

References

The HTML5 working draft:
http://dev.w3.org/html5/spec/Overview.html

WHATWG working draft:
http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#appcache

Apple's MobileSafari documentation:
http://developer.apple.com/webapps/docs/documentation/AppleApplications/Reference/SafariJSRef/DOMApplicationCache/DOMApplicationCache.html

Webkit Source Code:
http://trac.webkit.org/browser/trunk/WebCore/loader/appcache


By Andrew Grieve, Software Engineer, Google Mobile