Marking Resources for Offline Use

New stuff marked with yellow

Listing Offline Resources

To work offline, a web application must list the static resources (images, scripts, etc) it will need. The browser can then ensure that all listed resources are available, and that resources which are no longer needed are evicted. The application can list these resources in link tags of type offline-resource, or maintain a list in the navigator.offlineResources attribute.

interface ClientInformation {
  // defined in this section
  readonly attribute OfflineResourceList offlineResources;
  readonly attribute LoadStatusList pendingOfflineLoads;

  // more...
};

Link type "offine-resource"

The offline-resource keyword may be used with link elements, for which it creates an external resource link.

The offline-resource link type can be used when an application knows beforehand what resources will be needed offline. Immediately after the body.onload event has fired, all offline-resource links currently in the DOM are recorded as the offline resources required by this page. Those resources may then by loaded by the user agent for offline use.

The following snippet marks three resources for offline use:
  ... 
  <head>
    <link rel="offline-resource" href="/a.png">
    <link rel="offline-resource" href="/b.js">
    <link rel="stylesheet offline-resource" href="/stylesheet" type="text/css">
    <script type="text/javascript" src="/b.js>
  </head>
  <body>
    <img src="/a.png">
  </body>
  ...

The offlineResources attribute

The offlineResources DOM attribute is a list of absolute URIs that the application wants available offline. It implements the OfflineResourceList interface. The value of the offlineResources attribute is persistent, and shared across a domain.
interface OfflineResourceList {
  readonly attribute unsigned long length;
  DOMString item(in unsigned long index);
  void add(in DOMString uri);
  void remove(in DOMString uri);
  boolean has(in DOMString uri);
  void clear();
};
The browser may choose not to allow saving of a given resource, or may limit the total number of items. In this case, the add method will raise an exception.

In the ECMAScript DOM binding, objects implementing the OfflineResourceList interface must support being dereferenced using the square bracket notation, such that dereferencing with an integer index is equivalent to invoking the item() method with that index.

This snippet marks a resource for offline use before using it:
  <script>
    navigator.offlineResources.add("http://example.com/a.png");
  </script>  
  <img src="http://www.example.com/a.png">

The pendingOfflineLoads attribute

The pendingOfflineLoads attribute lets applications watch the progress of resources being loaded for offline use. The application will be notified of any offline loads that affect it - all offline-resource links in the page and any entries in the domain's offlineResources list.

When the browser decides to fetch a resource that affects the page, an item is added to the pendingOfflineLoads attribute, and a loadrequested event is fired on the LoadStatusList object. When the load is complete and the resource is available for offline use, the item is removed from the list and a loadcompleted event is fired on the LoadStatusList object. The loadrequested and loadcompleted events are in no namespace, bubble, are not cancellable, have no default action, and use the LoadStatusEvent interface described below.

Some loads may not appear in pendingOfflineLoads for security reasons. For example, resources requested from another domain should not appear in pendingOfflineLoads.

interface LoadStatus {
  readonly attribute DOMNode source;
  readonly attribute DOMString uri;
  readonly attribute long totalSize;
  readonly attribute long loadedSize;
  readonly attribute unsigned short readyState;
  readonly attribute unsigned short status;

  const unsigned short UNINITIALIZED = 0;
  const unsigned short REQUESTED     = 1;
  const unsigned short RECEIVING     = 2;
  const unsigned short LOADED        = 3;

};
The totalSize and loadedSize attributes may be -1 if their value is not known. The source attribute will point to the link tag that requested the resource, or null if the resource was specified in offlineResources.

The readyState attribute holds the state of the object. The attribute must be one of the following values:

UNINITIALIZED
The initial value.
REQUESTED
The user agent has requested the resource.
RECEIVING
Immediately before receiving the message body (if any). All HTTP headers have been received.
LOADED
The data transfer has been completed.
FIXME: do we want to deal with events for status change like xmlhttprequest does?

The status attribute, if available, must be the HTTP status code returned by the server. If the HTTP status code is not available, its value should be 0.
interface LoadStatusList {
  readonly attribute unsigned long length;
  LoadStatus item(in unsigned long index);
};
LoadStatusList objects must also implement the EventTarget interface.
interface LoadStatusEvent : Event {
  readonly attribute LoadStatus status;
  void initLoadStatusEvent(in DOMString typeArg, 
                           in boolean canBubbleArg, 
                           in boolean cancellableArg,
                           in LoadStatus status);
  void initLoadStatusEventNS(in DOMString namespaceURIArg,
                             in DOMString typeArg,
                             in boolean canBubbleArg,
                             in boolean cancellableArg,
                             in LoadStatus status);
};

Cache Status

interface ClientInformation {
  // defined in this section
  boolean isLocallyAvailable(in DOMString uri, in boolean ifOffline);

  // more...
};
The isLocallyAvailable() method will return true if the user agent can satisfy a request for that URL without using the network. Some queries may raise a security exception.

When true is returned, the application can expect that immediate requests for that URI will be satisfied relatively quickly and without error.

Verifying the Offline State

To make sure that it is ready to be used offline, an application should:
  1. Make sure that the pendingOfflineResources list is empty.
  2. Check each uri listed in offline-resource links and the offlineResources list using isLocallyAvailable() with ifOffline set to true.

Implementation Notes

User agents will have have some implementation-specific way to decide whether a given domain or page will be available offline. If the application will not be available offline, operations on the offlineResources object will raise an exception.

TODO

Quota handling

There needs to be some way to give an application some idea of how much space it has to work with.