W3C

DataCache API

W3C Working Draft 29 October 2009

This Version:
http://www.w3.org/TR/2009/WD-DataCache-20091029/
Latest Published Version:
http://www.w3.org/TR/DataCache/
Latest Editor’s Draft:
http://dev.w3.org/2006/webapi/DataCache/
Editor:
Nikunj R. Mehta, Oracle Corp <nikunj.mehta@oracle.com>

Abstract

This document defines APIs for off-line serving of requests to HTTP resources using static and dynamic responses.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document is the 29 October 2009 First Public Working Draft of the DataCache API specification. If you wish to make comments regarding this document, please send them to public-webapps@w3.org (subscribe, archives) with “[DataCache]” at the start of the subject line, or submit them using our public bug database.

The latest stable version of the editor's draft of this specification is always available on the W3C CVS server. Change tracking for this document is available at the following location:

The Web Applications Working Group, is the W3C Working Group responsible for this specification's progress along the W3C Recommendation track.

Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Table of Contents

1. Introduction

This section is informative.

Web applications often encounter seemingly random disconnections or network slowdowns, which deteriorates application responsiveness and availability, and, therefore, user experience. Working around network issues entails specially written applications, synchronization programs, and data protocols for specific platforms.

The standard HTTP caches built in to existing user agents are under no obligation to locally store a cacheable resource and do not provide any guarantees about off-line serving of HTTP resources. An application cache [HTML5] can hold static representations of a set of pre-defined resources that can be served locally. However, applications cannot alter this set of resources programmatically. Moreover, an application cache cannot satisfy requests other than GET and HEAD.

To address this limitation, this specification introduces data caches. Instead of a static manifest resource listing the resources to be cached, a data cache can be modified programmatically. Web applications can add or remove resources in a data cache which can then be statically served by the user agent when that resource is requested. This specification also provides embedded local servers to dynamically serve off-line representations of resources such as in response to unsafe HTTP methods, e.g., POST.

Using data caches and embedded local servers, applications can obtain locally cached or served data and complete requests to resources whether or not the requests can be serviced immediately by a remote server. Applications can replay locally satisfied requests to the server thus enabling responsive and robust Web applications in the presence of low connectivity conditions.

This specification does not introduce a new programming model for Web applications as data caches and embedded local servers are transparently pressed into action by the user agent, depending on system conditions. This means that existing applications can be used unchanged in environments that are not affected by network unreliability. Applications can be altered to use APIs specified in this document, only if they require improved responsiveness. Such applications can seamlessly switch between on-line and off-line operation without needing explicit user action.

2. Conformance Requirements

Everything in this specification is normative except for diagrams, examples, notes and sections marked as being informative.

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “RECOMMENDED”, “MAY” and “OPTIONAL” in this document are to be interpreted as described in Key words for use in RFCs to Indicate Requirement Levels [RFC2119].

This specification defines one class of products:

Conforming user agent

A user agent must behave as described in this specification in order to be considered conformant.

User agents may implement algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.

A conforming DataCache user agent must also be a conforming implementation of the IDL fragments of this specification, as described in the “Web IDL” specification. [WEBIDL]

Note
This specification uses both the terms "conforming user agent(s)" and "user agent(s)" to refer to this product class.

2.1. Dependencies

This specification relies on several underlying specifications.

HTTP

A conforming user agent must support some version of the HTTP protocol [RFC2616].

In order to protect against attacks, the use of the following headers is prohibited using interfaces defined in this specification.

  • Accept
  • Accept-Charset
  • Accept-Encoding
  • Accept-Language
  • Authorization
  • Cache-Control
  • Connection
  • Content-Transfer-Encoding
  • Cookie
  • Date
  • Expect
  • Host
  • Keep-Alive
  • Origin
  • Range
  • Referer
  • Set-Cookie
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade
  • User-Agent
  • Via
HTTP State Management

A conforming conforming user agent must support storage and exchange of cookies as specified by HTTP State Management [RFC2965].

DOM

A conforming conforming user agent must define the exception codes defined in [DOM3Core] and referenced in this specification.

3. Terminology

A resource is captured when it is added to a data cache.

A resource is released when it is removed from a data cache.

A managed resource is one whose URI is captured.

A static representation is one that is generated directly by the user agent from its internal storage.

A dynamic representation is one that is generated programmatically by using application-supplied logic.

Transparent off-line data access and manipulation means to locally generate a static or a dynamic response for HTTP requests to captured resources.

Private resources are those that require explicit authorization.

4. Programmable HTTP Processing

Programmable HTTP processing enables applications to identify managed resources to a user agent and to produce static and dynamic representations for responding to requests on these resources.

4.1. Introduction

This section is non-normative.

A user agent processes network requests to managed resources in one of three ways:

  1. serve - respond with the static representation of the requested resource (for any safe HTTP methods) from a data cache.
  2. intercept - immediately invoke an embedded local server to obtain a dynamic representation (for any HTTP methods).
  3. review - relay the request to the server to obtain a dynamic representation and notify an embedded local server when that representation is available (only for unsafe HTTP methods).

The serve policy applies only to resources that do not require interception, whereas the intercept policy can only be used for resources that require interception. Both policies improve availability and responsiveness. However, both may affect data freshness. The review policy can only be used when the user agent is able to communicate with the server. This policy improves data freshness at the cost of reduced responsiveness. User agents may choose freely from among these options, e.g., using information about the system condition, network state or battery power level, or a user preference.

4.1.1. Examples

An application can use a data cache to capture the representation of a resource, i.e., cache an off-line representation in the data cache.

Example

Using a data cache, an application captures a resource as part of an atomic cache transaction. Once the resource is captured successfully, the application places the captured representation in to service.

ECMAScript
var uri = ...
var cache = window.openDataCache();
document.body.addEventListener('onready', function(event) {
  event.cache.swapCache();
  ... // take advantage of the new stuff in the cache
});

cache.transaction(function(txn) {
  txn.capture(uri);
  txn.finish();  
});

The user agent is able to then serve this off-line representation when an application issues a GET request for that resource either through page navigation or an XMLHttpRequest [XMLHttpRequest].

ECMAScript
var req = new XMLHttpRequest;
req.open('GET', uri);
...
req.send();

A dynamic representation is produced by using an embedded local server in conjunction with the data cache. An interceptor processes an HTTP request locally in an embedded local server without changing the network APIs used by applications. Thus even if a host is unreachable, applications can successfully make HTTP requests to managed resources.

Example

In this example, a local requst handler can produce a dynamic response to an application request when the network is not accessible. The response can be prepared using the data cache, for example. The benefit of this technique is that applications don't need to alter their applications to accommodate off-line use cases. Instead, user agents can transparently introduce an application-specific off-line handler to deal with situations when the network is not available.

ECMAScript
var uri = ...
var cache = window.openDataCache();
var local = function(request, response) {
  response.statusCode = 200;
  response.statusLine = 'HTTP/1.1 OK';
  response.bodyText = ...
  response.send();
};

window.navigator.registerOfflineHandler(uri, local);

var txn = cache.offlineTransaction(function(txn) {
  txn.capture(uri, '', null, ['GET']);
  txn.commit();
});

Later when that application issues a GET request for the cached resource either through page navigation or an XMLHttpRequest [XMLHttpRequest], and the user agent is off-line, it invokes the local off-line handler which produces a dynamic response.

ECMAScript
var req = new XMLHttpRequest;
req.open('GET', uri);
...
req.send();

Applications can also locally intercept requests that modify data, e.g., unsafe HTTP requests such as PUT in an off-line handler. Requests to resources that are managed in a data cache can be intercepted and served by an interceptor, when the user agent is off-line or by the server, when the user agent is online with a reviewer analyzing the result of the online request. A user agent can switch between these two behaviors automatically based on system conditions.

Example

For example, an application worker script that wishes to allow off-line updates to uri captures that resource in a data cache.

ECMAScript
var uri = ...
var cache = self.openDataCacheSync();
var txn = cache.transactionSync();
txn.capture(uri, ['PUT']);
txn.commit();

Another application in the same origin could then register an off-line handler for the same uri to serve off-line requests to that resource.

ECMAScript
cache = window.openDataCache();
var intercept = function(request, response) {
  if (...) {
    // validation fails
    response.setStatus(400, 'HTTP/1.1 Bad Request');
    response.send();
    return;
  } 
  cache.offlineTransaction(function(txn) {
    txn.oncommitted = function() {
      response.bodyText = request.bodyText;
      response.headers['Content-Type'] = type;
      response.statusCode = 200;
      response.statusLine = 'HTTP/1.1 OK';
      response.send();
    });
    txn.capture(request.targetURL, request.bodyText, request.headers['Content-Type']);
    txn.commit();    
  });
};
  
var review = function(request, response) {
  cache.offlineTransaction(function(txn) {
    txn.capture(request.targetURL, response.bodyText, response.headers['Content-Type']); 
    txn.commit();
  });
};

window.navigator.registerOfflineHandler(uri, intercept, review);

When the application makes a PUT request to uri and the user agent is off-line, the user agent asks the intercept function to process the request and respond to it. If the user agent is online when the request arrives, then it sends the request to a host and asks the review function to process the response received from it.

ECMAScript
var req = new XMLHttpRequest;
req.open('PUT', uri);
...
req.send(...);

If this application makes a GET request to uri, then its cached representation is returned as the response regardless of whether the user agent is off-line.

ECMAScript
var req = new XMLHttpRequest;
  req.open('GET', uri);
  ...
  req.send();

4.1.2. Event summary

This section is non-normative.

Application scripts may modify the managed resources of a data cache. The user agent will fetch the representations of newly added and modified managed resources and add the representations to the data cache.

A number of events are fired to keep the application updated as to the state of the cache, so that the user can be notified appropriately. The events are as follows:

Event nameOccasionNext events
off-line-updating A script has started an off-line transaction to modify the data cache. captured, released, ready
updating A script has started an online transaction to modify the data cache. fetching, released, ready
fetching The user agent has started fetching the representation of a managed resource. captured, obsolete, error
captured The user agent has finished fetching the representation of a managed resource and stored it. captured, fetching, ready,
released The user agent has released a managed resource and can no longer serve off-line requests to it. captured, fetching, ready,
ready All the managed resources have been cached for serving off-line requests to them, and the script can use swapCache() to switch to the new cache. (Last event in sequence.)
obsolete The server returned a 401 error in response to a request for fetching a managed resource's representation. (Last event in sequence.)
error A fatal error occurred while fetching a managed resource's representation. (Last event in sequence.)

4.2. Data Caches

Data cache is a programmable HTTP cache that can be manipulated by a Web application to serve off-line representations of resources.

A data cache is a set of managed resources consisting of the entity (i.e., headers and body) for each such resource that falls into one of the following categories:

Static entries
A resource whose representation is cached for off-line serving. A request to a static entry can only be used with the serve policy.
Dynamic entries
A resource whose representation is produced locally by an application upon request. Each dynamic entry identifies one or more dynamic protocol methods for which a response can be obtained locally using an interceptor.

Each data cache has a completeness flag, which is either incomplete or complete.

A data cache may have zero or one required authorization cookie.

A data cache group is a group of data caches identified by the origin in which it is created and its authorization cookie [RFC2965].

Each data cache whose completeness flag is complete has a version. No two data caches in a data cache group may have the same version. A data cache is newer than another if it's version is bigger than the other (in other words data caches in a data cache group have a chronological order).

Each data cache group has an update status, which is one of the following: idle or updating.

A relevant data cache is a data cache that is the newest in its group to be complete.

An unsecure data cache group is not secured with an authorization cookie and cannot serve private resources. A secure data cache group controls access to private resources using an authorization cookie.

A cache host is a Document or a SharedWorkerGlobalScope object [WebWorkers].

If a data cache group is available to a cache host, then it can be associated with the cache host. A secure data cache group is available to a cache host if its authorization cookie will be sent to an origin server for fetching that cache host [RFC2965]. An unsecure data cache group is available to a cache host if its origin is the same as its cache host's.

A data cache group can be marked as obsolete, meaning that it cannot be made available to a cache host.

When a SharedWorkerGlobalScope is created and when a Document is loaded, the relevant data cache of every available data cache group is associated with it as the effective data cache in that data cache group.

Multiple effective data caches may contain the representation of a given resource. If the user agent is to select a data cache from a list of relevant data caches that contain the representation of a required resource, then the user agent must use the data cache that the user most likely wants to see the representation from, taking into account the following:

4.2.1. Opening a cache

When the user agent is required to open a data cache, given a cache host, optionally the name of an authorization cookie the user agent must perform the following steps:

  1. Let cookie name be the name of an authorization cookie passed to these steps.
  2. Pick the appropriate substeps:
    If the cache host passed to these steps is a Window object
    Let origin be the origin of the active document of the browsing context of that Window object.
    If the cache host passed to these steps is a WorkerUtils object
    Let origin be the origin of the scripts in the worker.
  3. Atomically, so as to avoid race conditions, perform the following substeps
    If cookie name is empty, then perform the following steps:
    1. If there is an unsecure data cache group for origin origin, let data cache group be that existing data cache group.
    2. If data cache group does not exist, the perform the following substeps:
      1. Create a new data cache, called data cache, in a new unsecure data cache group for origin origin called data cache group.
      2. Set the completeness flag of data cache to incomplete.
      3. Set the update status of data cache group to idle.
    If cookie name is not empty, then perform the following steps:
    1. Let data cache group be an existing secure data cache group for origin origin, the name of whose authorization cookie case-insensitively matches cookie name.
    2. Obtain the storage mutex.
    3. Let cookie be the cookie in the current browsing context, whose name case-insensitively matches cookie name.
    4. If data cache group is defined and has an authorization cookie whose value doesn't match cookie's value then perform the following substeps:
      1. Mark data cache group obsolete.
      2. Create a new data cache, called data cache, in a new secure data cache group for origin origin called data cache group with its authorization cookie set to cookie.
      3. Set the completeness flag of data cache to incomplete.
      4. Set the update status of data cache group to idle.
    5. Release the storage mutex.
  4. Return data cache.

4.2.2. Constructing and modifying data caches

Application scripts identify the resources managed by a data cache during a cache transaction, when applications may either capture or release its resources.

Each cache transaction has a data cache group and a data cache.

A cache transaction can be marked as off-line.

Each cache transaction has a status, which can be either of pending, committed, or aborted.

When a cache transaction is started, the user agent must run the cache transaction creation process. When a resource is added to a transaction's list of captured resources, the user agent must run the resource capturing process. When a resource is added to a transaction's list of released resources, the user agent must run the resource release process. When the transaction is finished, the user agent must run the cache transaction finish process.

4.2.2.1. Starting a transaction

When the user agent is required to create a cache transaction given a data cache group and an off-line flag, the user agent must run the following steps:

  1. Let cache group be the data cache group passed to these steps.
  2. If cache group is marked obsolete, then raise an exception and abort these steps.
  3. Pick the appropriate steps:
    If the off-line flag passed to these steps is set.
    1. Create a new data cache, called data cache, in cache group.
    2. Set the completeness flag of data cache to incomplete.
    3. Mark transaction as off-line.
    4. Create a new cache transaction called transaction and set data cache to be its data cache.
    5. For each cache host associated with a data cache in cache group, queue a task to fire an event at the cache host with the name off-line-updating, which does not bubble, is not cancelable, and which uses the CacheEvent interface.
    6. Return transaction.
    If the off-line flag passed to these steps is not set.
    1. Atomically, so as to avoid race conditions, perform the following substeps
      1. If the status of cache group is updating, then raise an exception and abort these steps, as a cache transaction is already open on this data cache group.
      2. Set the status of cache group to updating.
    2. Create a new data cache, called data cache, in cache group which holds all the same resources as the relevant data cache of cache group.
    3. Set the completeness flag of data cache to incomplete.
    4. Mark transaction as not off-line.
    5. Create a new cache transaction called transaction and set data cache to be its data cache.
    6. For each cache host associated with a data cache in cache group, queue a task to fire an event at the cache host with the name updating, which does not bubble, is not cancelable, and which uses the CacheEvent interface.
  4. Set transaction's status to pending.
  5. Return transaction.
4.2.2.2. Capturing resources

When the user agent is required to add a resource to be captured, given the URI of the resource to capture, a cache host, a cache transaction, optionally a list of dynamic methods, optionally content to serve as the static representation of the resource, and optionally content type for the representation, the user agent must perform the following steps:

  1. Let transaction be the cache transaction passed to these steps.
  2. If transaction's status is not pending, then raise an exception and abort these steps.
  3. Pick the appropriate substeps:
    If the cache host passed to these steps is a Window object
    Let base URI be the location of the active document of the browsing context of that Window object.
    If the cache host passed to these steps is a WorkerUtils object
    Let base URI be the location of the worker.
  4. Resolve the URI passed to these steps relative to base URI.
  5. If the resulting absolute URI has a different <scheme> component than the base URI (compared in an ASCII case-insensitive manner), then throw an exception and abort these steps.
  6. If the resulting absolute URI does not have the same origin as base URI, then throw an exception and abort these steps.
  7. Drop the <fragment> component of the resulting absolute URI, if it has one.
  8. Let cache be transaction's data cache.
  9. If the resulting absolute URI identifies a managed resource that is already in cache, then remove that managed resource from cache.
  10. Pick the appropriate substeps:
    If transaction's is not marked as off-line
    1. Let cache group be the data cache group containing cache.
    2. For each cache host associated with a data cache in cache group, queue a task to fire an event with the name fetching, which does not bubble, is not cancelable, and which uses the CacheEvent interface at the cache host.
    3. Fetch the representation of the resource identified by the absolute URI. Use the transaction's data cache as an HTTP cache, and honor HTTP caching semantics (such as expiration, ETags, and so forth) with respect to that cache. User agents may also have other caches in place that are also honored.
      Note
      If the resource in question is already being fetched for other reasons, then the existing download process can sometimes be used for the purposes of this step.
    4. If the previous step fails (e.g. the server returns a 4xx or 5xx response or equivalent, or there is a DNS error, or the connection times out, or the user cancels the download), or if the server returned a redirect, then run the capture failure steps.
      Note
      Redirects are fatal because they are either indicative of a network problem (e.g. a captive portal); or would allow resources to be added to the cache under URIs that differ from any URI that the networking model will allow access to, leaving orphan entries; or would allow resources to be stored under URIs different than their true URIs. All of these situations are bad.
    5. Otherwise, the fetching succeeded. Store in cache a managed resource comprising the resulting absolute URI, its fetched representation, and the list of dynamic methods passed to these steps.
    6. For each cache host associated with a data cache in cache group, queue a task to fire an event at the cache host with the name captured, which does not bubble, is not cancelable, and which uses the CacheEvent interface.
    If transaction is marked as off-line.
    1. Let representation be the content passed to these steps.
    2. Let type be the content type passed to these steps.
    3. If type is empty or null, set it to text/plain.
    4. Store in cache a managed resource comprising the resulting absolute URI, representation, and the list of dynamic methods passed to these steps.
    5. For each cache host associated with a data cache in cache group, queue a task to fire an event at the cache host with the name captured, which does not bubble, is not cancelable, and which uses the CacheEvent interface.

The capture failure steps are as follows:

  1. Discard cache.
  2. Set cache group's status to idle.
  3. Pick the appropriate substeps:
    If the failure was not caused by a 401 response, then
    1. For each cache host associated with a data cache in cache group, queue a task to fire an event at the cache host with the name error, which does not bubble, is not cancelable, and which uses the CacheEvent interface.
    If the failure was not caused by a 401 response, then
    1. Mark cache group as obsolete.
    2. For each cache host associated with a data cache in cache group, queue a task to fire an event at the cache host with the name obsolete, which does not bubble, is not cancelable, and which uses the CacheEvent interface.
  4. Mark transaction's status as aborted.

Attempts to fetch resources as part of the adding resource for capturing process may be done with cache-defeating semantics, to avoid problems with stale or inconsistent intermediary caches.

4.2.2.3. Releasing resources

When the user agent is required to add a resource to be released, given the URI of the resource to release, a cache host, and a cache transaction, the user agent must perform the following steps:

  1. Let transaction be the cache transaction passed to these steps.
  2. If transaction's status is not pending, then raise an exception and abort these steps.
  3. Pick the appropriate substeps:
    If the cache host passed to these steps is a Window object
    Let base URI be the location of the active document of the browsing context of that Window object.
    If the cache host passed to these steps is a WorkerUtils object
    Let base URI be the location of the worker.
  4. Resolve the URI passed to these steps relative to base URI.
  5. If the resulting absolute URI has a different <scheme> component than the base URI (compared in an ASCII case-insensitive manner), then throw an exception and abort these steps.
  6. If the resulting absolute URI does not have the same origin as base URI, then throw an exception and abort these steps.
  7. Drop the <fragment> component of the resulting absolute URI, if it has one.
  8. Let cache be transaction's data cache.
  9. If the resulting absolute URI does not identify a managed resource that is already in cache, then raise an exception and abort these steps.
  10. Remove the managed resource for the resulting absolute URI from cache.
  11. For each cache host associated with a data cache in cache group, queue a task to fire an event at the cache host with the name released, which does not bubble, is not cancelable, and which uses the CacheEvent interface.
4.2.2.4. Completing a transaction

When the user agent is required to commit a cache transaction, given a cache transaction, and a cache host, it means that the user agent must run the following steps:

  1. Let transaction be the cache transaction passed to these steps.
  2. If transaction's status is not pending, then raise an exception and abort these steps.
  3. Let cache be transaction's data cache.
  4. Let cache group be the data cache group containing cache.
  5. Atomically, so as to avoid race conditions, perform the following substeps:
    1. Let cache group version be the version of the relevant data cache of cache group.
    2. Set cache's version to be higher than cache group version.
    3. Set the cache's completeness flag to complete.
    4. Obtain the storage mutex
    5. If the host sets cookies in response to such a request, the user agent should update its cookie store accordingly.
    6. Release the storage mutex.
  6. Pick the appropriate substeps:
    If transaction is not marked as off-line,
    1. Set the status of cache group to idle.
    If transaction is marked as off-line
    1. Make cache the effective cache for cache group to the cache host passed to these steps.
  7. For each cache host associated with a data cache in cache group, except for the cache host passed to these steps, queue a task to fire an event at the cache host with the name ready, which does not bubble, is not cancelable, and which uses the CacheEvent interface.
4.2.2.5. Aborting a transaction

When the user agent is required to abort a cache transaction, given a cache transaction, and a cache host, it means that the user agent must run the following steps:

  1. Let transaction be the cache transaction passed to these steps.
  2. If transaction's status is not pending, then raise an exception and abort these steps.
  3. Discard transaction's data cache.
  4. Set transaction's status as aborted.
  5. For each cache host associated with a data cache in cache group, queue a task to fire an event at the cache host with the name error, which does not bubble, is not cancelable, and which uses the CacheEvent interface.
4.2.2.6. Activating updates

Once a cache host picks an effective data cache in a data cache group, an application script can use its representations. However, once update transactions are completed on that data cache group, the effective data cache is no longer the relevant data cache.

When a user agent is required to activate updates for a given data cache group and a cache host, the user agent must run the steps below:

  1. Let cache be the relevant data cache for the data cache group passed to these steps.
  2. If cache is the same as the effective data cache for the data cache group in the cache host passed to these steps, then terminate these steps.
  3. Set cache to be the effective data cache for the data cache group to the cache host passed to these steps.

4.2.3. Expiring data caches

As a general rule, user agents should not expire data caches, except on request from the user, or after having been left unused for an extended period of time.

Implementors are encouraged to expose data caches in a manner related to HTTP cookies, allowing caches to be expired together with cookies and other origin-specific data. Data caches and cookies have similar implications with respect to privacy (e.g. if the site can identify the user when providing the cache, it can store data in the cache that can be used for cookie resurrection).

4.2.4. The API

IDL
[Supplemental] 
  interface CacheUtil {
    DataCache openDataCache([optional in] DOMString cookieName);
  };
    
  Window implements CacheUtil;
  
  [Supplemental]
  interface CacheUtilSync {
    DataCacheSync openDataCacheSync([optional in] DOMString cookieName);
  };
    
  WorkerUtils implements CacheUtilSync;
window.openDataCache()
(In a window) Returns a DataCache object that represents the data cache obtained from cache opening steps using window as the cache host and cookieName as the name of an authorization cookie.
self.openDataCacheSync()
(In a shared worker) Returns a DataCacheSync object that represents the data cache obtained from cache opening steps using worker as the cache host and cookieName as the name of an authorization cookie.
Example

Here's how a shared worker opens an unsecure data cache. Representations cached in unsecure data caches are available regardless of authorization.

ECMAScript
var cache = self.openDataCacheSync();

If an application were to use a cookie named 'SSID' to secure access to private resources, then it would need to use a secure cache for accessing those resources off-line.

ECMAScript
var cache = window.openDataCache('SSID');

4.2.5. Asynchronous Data Cache API

IDL
interface DataCache { 
  const unsigned short IDLE = 0;
  const unsigned short READY = 1;
  const unsigned short OBSOLETE = 2;
  readonly attribute unsigned short status;
  readonly attribute DOMString requiredCookie;
  readonly attribute long version;
  
  // updates
  void transaction(in TransactionCallback callback,
                   [optional in] VoidCallback errorCallback);
  void offlineTransaction(in TransactionCallback callback,
                          [optional in] VoidCallback errorCallback);
  void swapCache();
  void eachModificationSince(in long version, 
                             in ItemCallback callback,
                             [optional in] VoidCallback successCallback);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface TransactionCallback {
  void callback(in CacheTransaction txn);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface VoidCallback {
  void callback();
};
transaction() and offlineTransaction()
Both methods take one or two arguments - a transaction callback and optionally an error callback. When called, this method must immediately return and asynchronously perform the following steps:
  1. Set off-line to false if offlineTransaction() was called, and true otherwise.
  2. Execute the steps to create a cache transaction with the first argument being the data cache group of this DataCache object and the second argument being off-line.
  3. Let result be a new CacheTransaction object for the transaction returned from the previous step.
  4. If transaction callback is not null, queue a task to invoke the transaction callback with the aforementioned CacheTransaction object as its only argument, and wait for that task to be run.
  5. If transaction callback raised an exception, jump to the last step.
  6. End these steps. The next step is only used when something goes wrong.
  7. Queue a task to invoke the error callback, if it is not null.
swapCache()
Perform the steps to activate updates with the data cache group of this DataCache object.
eachModificationSince()
This method takes one to three parameters - low watermark version and item callback, and an optional success callback. When called, this method must immediately return and asynchronously perform the following steps:
  1. Let additions be a list of entities with their URIs and let removals be a list of URIs.
  2. Let cache be the data cache represented by this DataCache object.
  3. For each data cache belonging to cache's data cache group, starting from cache's version down to low watermark version, perform the following substeps:
    1. Let old cache be the data cache.
    2. Let old version be old cache's version.
    3. For the entity entityof each managed resource of old cache that was added in the old version, perform the following steps:
      1. Let id be the URI of the managed resource.
      2. If neither additions nor removals already includes id, then add id with entity to additions.
    4. For each managed resource of old cache that was removed in the old version, perform the following steps:
      1. Let id be the URI of the managed resource.
      2. If neither additions nor removals already includes id, then add id to removals.
  4. If item callback is not null, then for each item item in additions, perform the following steps:
    1. For each item item in additions, queue a task to invoke the item callback with item.
    2. For each item item in removals, queue a task to invoke the item callback with item.
  5. If success callback is not null, then queue a task to invoke the success callback
version
This attribute, on getting, must return the version of the data cache of this DataCache object.
requiredCookie
This attribute, on getting, must return the name of the authorization cookie of the data cache group of this DataCache object.
status
This attribute, on getting, must return the current state of the data cache of this DataCache object. This must be the appropriate value from the following list:
IDLE
This DataCache object's cache host is aassociated with a data cache whose data cache group's update status is idle and that data cache is the newest cache in its data cache group, and the data cache group is not marked obsolete.
READY
This DataCache object's cache host is aassociated with a data cache whose data cache group's update status is idle, and whose data cache group is not marked as obsolete, but that data cache is not the newest cache in its data cache group.
OBSOLETE
This DataCache object's cache host is aassociated with a data cache whose data cache group is marked as obsolete.

4.2.6. Synchronous Data Cache API

IDL
interface DataCacheSync : DataCache {
  OnlineTransaction transactionSync();
};

The transactionSync method must perform the following steps:

  1. Execute the steps to create a cache transaction with the first argument being the data cache group of this DataCache object and the second argument being false.
  2. Let result be a new CacheTransaction object for the transaction returned from the previous step.
  3. Return result.

4.2.7. Transaction API

IDL
interface CacheTransaction {
  void getItem(in DOMString uri, ItemCallback callback);
  void release(in DOMString uri);
  void commit();
  
  // events
           attribute Function oncommitted;
};

interface OnlineTransaction : CacheTransaction {
  void capture(in DOMString uri, [optional in] DOMStringList dynamicMethods);
  void abort();
};

interface OfflineTransaction : CacheTransaction {
  void capture(in DOMString uri, 
               in DOMString body, 
               [optional in] DOMString contentType, 
               [optional in] DOMStringList dynamicMethods);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface ItemCallback {
  void callback(in CacheItem item);
};

interface CacheItem {
  const unsigned short UNCACHED = 0;
  const unsigned short FETCHING = 1;
  const unsigned short CACHED = 2;
  const unsigned short GONE = 3;
  
  readonly attribute unsigned short readyState;
  readonly attribute FileData body;
  readonly attribute DOMStringList dynamicMethods; 
  readonly attribute any headers;
};
capture()
This method takes one or two arguments - a uri of the resource to capture and an optional list of dynamic methods. When called, this method must immediately return and asynchronously perform the steps in the resource capturing process with the first argument being uri, second being the current window or worker object, the third being this CacheTransaction object's associated cache transaction, the fourth being dynamic methods.
capture()
This method takes two to four arguments - a uri of the resource to capture, an entity body, optionally a content type, and an optional list of dynamic methods. When called, this method must immediately return and asynchronously perform the steps in the resource capturing process with the first argument being uri, second being the current window or worker object, the third being this CacheTransaction object's associated cache transaction, the fourth being dynamic methods, the fifth being entity body, and the sixth being content type.
release()
This method takes one argument - uri of the resource to release. When called, this method must immediately return and asynchronously perform the steps in the resource releasing process with the first argument being uri, second being the current window or worker object, and the third being this CacheTransaction object's associated cache transaction.
abort()
When called, this method must immediately return and asynchronously perform the steps in the cache transaction abort process with the first argument being this CacheTransaction object's associated cache transaction, and the second being the window or worker object.
commit()
When called, this method must immediately return and asynchronously perform the following steps:
  1. Execute the cache transaction commit process with the first argument being this CacheTransaction object's associated cache transaction, and the second being the current window or worker object.
  2. If oncommitted attribute on this CacheTransaction object is not null, queue a task to invoke the function identified by oncommitted .
getItem()
This method takes two arguments - a uri and an item callback. When called, this method must immediately return and asynchronously perform the following steps:
  1. If the resource identified by uri does not exist in this CacheTransaction object's associated data cache, then the method must raise data cache object, then the method must raise the NOT_FOUND_ERR exception and terminate these steps.
  2. Let item be the entity in this CacheTransaction object's associated data cache.
  3. Create object, a new CacheItem object with the associated item.
  4. Queue a task to invoke item callback with the aforementioned CacheItem object as its only argument.
oncommitted

This attribute, on getting, must return the function to be invoked when this CacheTransaction object has been committed.

This attribute, on setting, must store the function to be invoked when this CacheTransaction object has been committed.

body
This attribute, on getting, must return the entity body, if any, as a FileData object [FileAPI], of the managed resource associated with this CacheItem object.
dynamicMethods
This attribute, on getting, must return the list of protocol methods, if any, of the managed resource associated with this CacheItem object.
headers
This attribute, on getting, must return the headers as a native ordered dictionary data type from the managed resource associated with this CacheItem object. In the JavaScript binding, this must be Object. Each header must have one property (or dictionary entry), with those properties enumerating in the order that the headers were recorded in the managed resource. Each property must have the name of the header and its value as recorded in the managed resource.
readyState
This attribute, on getting, must return the current state of the managed resource. This must be the appropriate value from the following list:
UNCACHED
This CacheItem object is associated with a managed resource which has been added for capturing but has not yet been cached. There is no value available in body or headers.
FETCHING
This CacheItem object is associated with a managed resource which is currently being fetched. There is no value available in body or headers.
CACHED
This CacheItem object is associated with a managed resource which has been cached.
GONE
This CacheItem object is associated with a managed resource which has been released. There is no value available in body, headers, or dynamicMethods.

For both capture() methods, dynamic methods is a comma separated list of protocol methods that can be intercepted for local processing. An empty string is allowed for this parameter.

4.2.8. The CacheEvent

The task source for this task is the networking task source.

If the event being fired is fetching, captured, or released, then the event must have its uri attribute set to the URI of the affected managed resource.

Otherwise, if the event being fired is off-line-updating, updating, error, obsolete, or ready, then the event must have its uri attribute set to null.

IDL
interface CacheEvent : Event {
  readonly attribute DataCache cache;
  readonly attribute DOMString uri;
  
  void initCacheEvent(DataCache cache,
                      in DOMString uri);  
  void initCacheEventNS(in DOMString namespaceURI,
                        DataCache cache,
                        in DOMString uri);
};            
            
cache
This attribute, on getting, must return a DataCache object representing the data cache on which this event is fired.
uri
This attribute, on getting, must return the URI of the managed resource for which this event is fired.
initCacheEvent and initCacheEventNS
These methods must initialize the event in a manner analogous to the similarly named methods in the DOM Events interfaces. [DOM3Events]

4.3. Embedded Local Server

Embedded local server is an application script that generates dynamic responses to resource requests without making those requests to the resource host.

An embedded local server consists of an interceptor function and zero or one reviewer function.

An embedded local server serves requests to resources in its interception namespace.

A cache host can be associated with zero or more embedded local servers.

An resource request issued in a cache host can be intercepted if the resource is in the interception namespace of an embedded local server registered in the browsing context of the cache host and the resource is a dynamic entry in the effective data cache of some data cache group associated with the cache host and the request method is identified as a dynamic method in the dynamic entry.

If an embedded local server can intercept a resource request, then it is called a candidate local server for that request.

Multiple embedded local servers can be the candidate local server for a given resource request. If a user agent is to select an embedded local server from a list of candidate local servers that can produce a dynamic representation of the requested resource, then the user agent must use the embedded local server that has the most specific interception namespace.

4.3.1. Local Server API

IDL
[Supplemental, NoInterfaceObject]
interface NavigatorLocalServer {
  void registerOfflineHandler(in DOMString namespace, 
                       InterceptHandler intercept, 
                       ReviewHandler review);
};

Navigator implements NavigatorLocalServer;

[Callback=FunctionOnly, NoInterfaceObject]
interface InterceptHandler {
  void callback(in HttpRequest request,
                in MutableHttpResponse response);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface ReviewHandler {
  void callback(in HttpRequest request,
                in HttpResponse response);
};

interface HttpRequest {
  // properties
  readonly attribute DOMString method;
  readonly attribute DOMString target;
  readonly attribute DOMString bodyText;
  readonly attribute any headers;
};

interface MutableHttpResponse {
  void setStatus(in unsigned short code, in DOMString message);
  void setResponseText(in DOMString text);
  void setResponseHeader(in DOMString name, in DOMString value);
  void send();
};

interface HttpResponse {
  // properties
  readonly attribute unsigned short statusCode;
  readonly attribute DOMString statusMessage;
  readonly attribute DOMString bodyText;
  readonly attribute any headers;
};

The navigator.registerOfflineHandler() method takes two or three arguments - a uri for identifying the namespace of resources that are to be intercepted, an intercept handler function, and an optional review handler function. This method allows applications to register themselves as possible handlers for particular URI namespaces. Upon being invoked, this method should create a new embedded local server called server with its interceptor function set to intercept handler and its reviewer function set to review handler and add server to the cache host.

The user agent must invoke the InterceptHandler, with an HttpRequest object request based on the application's resource request and an MutableHttpResponse object response. When the send() method is invoked on response, the user agent must respond to request with the headers, body, and status specified in response.

The user agent must invoke the ReviewHandler, with an HttpRequest object request based on the application's resource request and an HttpResponse object response based on the host's response to that request.

The following attributes are available on the HttpRequest object:

method
This attribute, on getting, must return the HTTP method, in upper-case characters, present on this HttpRequest object.
target
This attribute, on getting, must return the URI of this HttpRequest object.
bodyText
This attribute, on getting, must return the entity body of this HttpRequest object, if the body has a Content-Type of either text/* or application/xml.
headers
This attribute, on getting, must return the headers as a native ordered dictionary data type from this HttpRequest object. In the JavaScript binding, this must be Object. Each header must have one property (or dictionary entry), with those properties enumerating in the order that the headers were present in the request. Each property must have the name of the header and its value as present in the request.

The following methods are available on the MutableHttpResponse object:

setResponseHeader()
This method takes two arguments - name and value of a response header. Upon calling, this method must store the header with name and value in this MutableHttpResponse object. If a value is already associated with this header, then this method must append value to it.
setStatus()
This method takes two arguments - code and message of the response status. Upon calling, this method must store the status with code and message in this MutableHttpResponse object, replacing any previous values for both.
setResponseText()
This method takes a single arguments - body of the response entity. Upon calling, this method must store the entity body in this MutableHttpResponse object, replacing any previous value.
send()
Upon calling, this method must dispatch this MutableHttpResponse object. No further changes must be allowed to it.

The following attributes are available on the HttpResponse object:

statusCode
This attribute, on getting, must return the status code of this HttpResponse object.
statusMessage
This attribute, on getting, must return the status message of this HttpResponse object.
bodyText
This attribute, on getting, must return the entity body of this HttpResponse object, if the body has a Content-Type of either text/* or application/xml.
headers
This attribute, on getting, must return the headers as a native ordered dictionary data type from this HttpResponse object. In the JavaScript binding, this must be Object. Each header must have one property (or dictionary entry), with those properties enumerating in the order that the headers were present in the response. Each property must have the name of the header and its value as present in the response.

4.3.2. Changes to the networking model

When a cache host is associated with one or more effective data caches, any and all loads for resources related to that cache host other than those for child browsing contexts must go through the following steps instead of immediately invoking the mechanisms appropriate to that resource's scheme:

  1. Let request be the resource request for fetching the resource.
  2. If request includes the HTTP header X-Bypass-DataCache and the value of that header is true, then fetch the resource normally, and abort these steps.
  3. Let caches be the set of all effective data caches for the cache host.
  4. Let resource be the resource to be fetched.
  5. If resource is not managed in caches, then fetch a representation of resource normally and abort these steps.
  6. Select a data cache cache from caches.
  7. If request is using the HTTP GET mechanism and resource is not defined in cache with a dynamic GET method, then get the entity for resource from the cache (instead of fetching it), and abort these steps.
  8. If request is using the HTTP HEAD mechanism and resource is not defined in cache with a dynamic HEAD method, then get the entity headers for resource from the cache (instead of fetching it), and abort these steps.
  9. If resource is not defined in cache with the dynamic method that request is using, then fetch a representation of resource normally and abort these steps.
  10. Pick the appropriate steps:
    If the user agent is off-line
    1. Select an embedded server server to produce an off-line response.
    2. Create a new response object to hold the dynamic response to request.
    3. Call the interception function of server passing as arguments request and response.
    4. Wait for the interception function to dispatch the dynamic response.
    5. Handle response as the dynamic response, and abort these steps.
    If the user agent is online
    1. Select an embedded server server to review the online response.
    2. Fetch a representation of resource normally and call it response.
    3. Call the reviewer function of server passing as arguments request and response.
    4. Handle response as the dynamic response, and abort these steps.
  11. Fail the resource load.

5. Security Considerations

Apart from requirements affecting security made throughout this specification implementations may, at their discretion, not expose certain headers, such as HttpOnly cookies.

Applications need to verify the identity of their users before allowing access to private resources they manage. Typically a host verifies the identity of its users by checking whether the user possesses valid credentials including a shared secret, e.g., a password. Applications design their own user interface to provide a means for users to supply their credentials for authentication. In Web applications, this is typically performed using HTML forms and it provides applications with a great deal of control over the authentication user interface. Also, applications typically do not verify the user's credentials for every request. Instead, applications verify a token stored on the client as a result of authentication. This token is a session identifier often stored in an HTTP cookie [RFC2965]. This approach is highly scalable since just the session identifier and not credentials are validated for every HTTP request. Use of session identifiers gives the data source wide latitude over terminating the authorization and restricting access to certain scopes. It also allows users to share authorization but not their credentials with a variety of less-trustworthy applications.

The token approach also enables off-line authentication without storing any credentials locally. The token produced by the host is used by BITSY to authenticate requests served locally and for capturing resources from the host. If a data cache is to store private resources, it must be created with a cookie name. Once such a data cache is created, the user agent must serve or intercept requests to its captured resources only if the cookie used to secure the cache is still present in the current browsing context.

Failing this, the user agent must make the request to the host as would be the case if the resource were not captured locally. If the user agent receives an HTTP 401 status from a host while capturing a resource using a required cookie, then it must automatically destroy the data cache originating that capture attempt.

A. References

A.1. Normative references

[DOM3Core]
Document Object Model (DOM) Level 3 Core Specification, A. Le Hors (eds.), et al. W3C, April 2004.
[DOM3Events]
Document Object Model (DOM) Level 3 Events Specification, D. Schepers. W3C, July 2009.
[FileAPI]
File API, Arun Ranganathan, editor. W3C Editor's Draft, August 2009.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, S. Bradner. IETF, March 1997.
[RFC2616]
Hypertext transfer protocol -- HTTP 1.1, R. Fielding et al. IETF RFC 2616, June 1999.
[RFC2965]
HTTP State Management Mechanism, D. Kristol and L. Montulli. IETF, October 2000.
[WebIDL]
Web IDL, Cameron McCormack, editor. W3C Working Draft, December 2008.
[WebWorkers]
Web Workers, Ian Hickson, editor. W3C Working Draft, April 2009.

A.2. Informative references

[XMLHttpRequest]
The XMLHttpRequest Object, A. van Kesteren. W3C Working Draft, 15 April 2008.
[HTML5]
HTML5: A vocabulary and associated APIs for HTML and XHTML, Ian Hickson, editor, W3C Working Draft, April 2009.

B. Acknowledgements

Thanks to Garret Swart, Colm Divilly, Ashish Motivala for their useful comments that have led to improvements to this specification over time.