The Data Store API allows an application to manage a data store that can
be shared with other applications and provides a mechanism to allow
multiple applications to concurrently synchronize data from the data store
into the application-local cache.

Introduction

The Data Store API allows an application to create and maintain a data
store that can be shared with other applications. To make multiple
applications keep their local storages up-to-date with the data store,
this API supports a mechanism to allow an application to concurrently
synchronize data from the data store into the application-local storage
which can be indexed, grouped or sorted in whatever format the
application needs in order to support its UI.

Motivation

The Contacts Manager API and the Messaging API were originally
designed to support richer querying, like filtering, sorting and
grouping data. However, they both have the severe shortcoming that the
consumers are forced to live with the limitations of what querying
capabilities those APIs can have.

That's why we are constantly having to revise these APIs because it
turns out that the querying capabilities aren't matching what our
applications need, which is not a workable long-term solution. Also,
it's not even a workable short-term solution for third-party
applications since we cannot revise the APIs to support the
capabilities that every third-party application developer needs.

Therefore, we've been figuring out such a generic Data Store API to
allow applications to synchronize and save data into their own
application-local storages which can be managed in various formats
than we could think of and bake into APIs, thus supporting richer
querying capabilities that the application really needs.

Note that the Data Store API is still in charge of maintaining a
central storage to keep data which can be added, retrieved or deleted
by applications through a bunch of methods provided by the Data Store
API. This implies the application doesn't need to duplicate the whole
data in its own local storage. Instead, it can simply synchronize the
data that is actively required to construct the needed indexes for its
own querying purpose.

More than IndexedDB API

Similar to the IndexedDB API, the Data Store API provides some
database-like methods to add, retrieve and delete data records but it
doesn't expose methods for building indexes or searching data.
Instead, it provides a synchronizing mechanism for applications to
keep their local storages up-to-date and accordingly update the
local indexes needed for filtering data.

The other difference from the IndexedDB API is the Data Store API
provides a central data storage which can be concurrently accessed and
modified by multiple applications. Also, it provides a permission
model to allow different applications to have different types of
priviledges to change the data store or listen to the change of the
data store.

Examples

If an application has the privilege to modify the content of the data
store, it can use a bunch of basic methods defined in the
DataStore to manage the data records in the data store, which is
shown as the following example.

An application can call the sync() method defined in the
DataStore to keep its local storage synchronized with the data
store, which creates a DataStoreCursor to retrieve the change
history starting from a certain revision kept in the application to the
current revision of the data store, which is shown as the following
example.

This specification defines conformance criteria that apply to a single
product: the user agent that implements the interfaces that
it contains.

Implementations that use ECMAScript to implement the APIs defined in
this specification MUST implement them in a manner consistent with the
ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]], as
this specification uses that specification and terminology.

Terminology

The
EventHandler interface represents a callback used for event
handlers as defined in [[!HTML5]].

Security and privacy considerations

Application Manifest

For the application that provides the data store, its manifest MUST be
claimed to own the data store by datastores-owned, where
the JSON object can contain multiple properties representing different
names of data stores respectively. Each data store can use
readonly to specify whether the data store can be read by
other applications and description to describe the
purpose.

As shown as the following example, if a Facebook applicaton wants to
provide a read-only fb-contacts data store, its manifest MUST
be claimed to own the data store by setting the attribute
readonly to true.

For the application that wants to access the data store, its manifest
MUST be claimed to access the data store by
datastores-access, where the JSON object can contain
multiple properties representing different names of data stores
respectively. Each data store can use access to specify
the application's accessibility and description to
describe the purpose.

As shown as the following example, if the application wants to read or
modify (e.g., add, update, remove, clear... etc) the content of the
fb-contacts data store, its manifest MUST be claimed to access
the fb-contacts data store by setting the attribute
access to readwrite.

As shown as the following example, if the application simply wants to
read the content of the fb-contacts data store without the
need of modifying it, its manifest MUST be claimed to access the
fb-contacts data store by setting the attribute
access to readonly.

This method makes a request to retrieve the data stores by the
name parameter. It returns a new
Promise that will be used to notify the caller about
the result of the operation, which is an array of DataStore
elements to access the data stores which have the same name equal
to the name.

DOMString name

Specifies the name of the data store.

Steps

The getDataStores method when invoked MUST run
the following steps:

Let promise be a new Promise object and
resolver be its associated resolver.

Return promise to the caller.

Make a request to the system to retrieve the data store(s) with the
name equal to the name parameter passed in the
request, where the caller application has claimed the data store
access by datastores-access in its manifest.

If an error occurs invoke resolver's reject algorithm
with error as the value argument.

MUST return the name of the data store. Note that different data
stores can share the same name as long as they have the same
database schema/format.

readonly attribute DOMString owner

MUST return the owner of the data store, which can be the manifest
URL of the owner application.

readonly attribute boolean readOnly

MUST return whether the content of the data store can be changed or
not by the caller.

readonly attribute DOMString revisionId

MUST return the current revision of the data store, which can be a
UUID string.

Promise get ()

This method makes a request to retrieve the data record(s) by the
id parameter. It returns a new Promise
that will be used to notify the caller about the result of the
operation, which is an arbitrary object to represent the data
record if id is a single value, or a set of data
records if id is an array of values.

DataStoreKey... id

Identifies the data record(s) that is requested to be
retrieved.

Promise update ()

This method makes a request to update the existing data record by
the id and the data parameters. It returns
a new Promise that will be used to notify the caller
about the result of the operation.

DataStoreKey id

Identifies the data record that is requested to be updated.

any data

Specifies the content of the data record to update.

Promise insert ()

This method makes a request to add a new data record by the
data parameter. It returns a new Promise
that will be used to notify the caller about the result of the
operation, which is an identifier to access the data record that is
added.

any data

Specifies the content of the data record to add.

Promise remove ()

This method makes a request to delete the data record(s) by the
id parameter. It returns a new Promise
that will be used to notify the caller about the result of the
operation, which is a boolean value to indicate whether the data
record(s) is successfully deleted or not.

DataStoreKey... id

Identifies the data record(s) that is requested to be deleted.

Promise clear ()

This method makes a request to clear all the data records in the
data store. It returns a new Promise that will be used
to notify the caller about the result of the operation.

Promise getLength ()

This method makes a request to retrieve the total number of data
records saved in the data store. It returns a new
Promise that will be used to notify the caller about
the result of the operation, which is a numeric value to indicate
the total number of data records saved in the data store.

DataStoreCursor sync ()

This method makes a request to retrieve the change history between a
particular revision and the current revision of the data store by the
revisionId parameter. It returns a new
DataStoreCursor that will be used to iteratively access a set
of DataStoreTask elements.

optional DOMString revisionId

Identifies the revision of the data store that the application
currently keeps. If this parameter is absent or cannot be
identified, this method will return a DataStoreCursor
iterating through all the existing data records currently
saved in the data store.

attribute EventHandler onchange

Handles the change event of type
DataStoreChangeEvent, fired when a data record is added,
updated or deleted in the data store. Note that if some data change
in the data store when the DataStoreCursor is still
synchronizing data and the cursor's close method
has not yet been called, all the change events will not be
dispatched to the application's onchange event handler.
Instead, all the changes will be managed by the cursor's
next method as additional operations.

Steps

The get method when invoked MUST run the
following steps:

Let promise be a new Promise object and
resolver be its associated resolver.

Return promise to the caller.

Make a request to the data store to retrieve the data record(s) with
the identifier equal to the id parameter passed in the
request.

If an error occurs invoke resolver's reject algorithm
with error as the value argument.

The DataStoreCursor interface allows the application to iterate
through a list of DataStoreTask elements that represents the
change history of the data store.

readonly attribute DataStore store

MUST return the data store that is currently iterated by the cursor.

Promise next ()

This method makes a request to retrieve the information of the next
operation that changes a data record in the data store. It returns a
new Promise that will be used to notify the caller
about the result of the operation, which is a DataStoreTask
to represent the information of the change operation.

void close ()

This method makes a request to terminate the cursor iterating
through the change history of the data store. Note that this method
has to be explicitly called when the cursor completes its tasks.
Otherwise, if some data changes in the data store when the cursor is
still synchronizing data, all the changes will be managed by the
cursor's next method as additional operations,
which means when the cursor completes its tasks, the application
will be in synchronization with the current revision of the data
store.

Steps

The next method when invoked MUST run the
following steps:

Let promise be a new Promise object and
resolver be its associated resolver.

Return promise to the caller.

Make a request to the system to retrieve the information of the next
operation that changes a data record in the data store.

If an error occurs invoke resolver's reject algorithm
with error as the value argument.

The DataStoreChangeEvent interface represents the event related
to a date record changed in the data store.

readonly attribute DOMString revisionId

MUST return the identifier of the revision of the data store, which
changes a data record.

readonly attribute DataStoreOperation operation

MUST return the type of operation that changes the data record in
the data store.

readonly attribute DataStoreKey? id

MUST return the identifier of the changed data record in the data
store. MUST return null if the operation is
clear or done.

readonly attribute DOMString owner

MUST return the manifest URL of the application which changes the
data record in the data store. Note that the owner here
is not the owner application of the data store. Instead, it's the
application making the change in the data store.

Acknowledgements

The editors would like to express their gratitude to the Mozilla Firefox
OS Team and specially to Jonas Sicking, Mounir Lamouri, Ehsan Akhgari,
Thinker Lee and Hsin-Yi Tsai for their technical guidance, as well as to
Andrea Marchesini for his implementation work and support. Also, huge
thanks to Zoltan Kis (Intel) and Christophe Dumez (Samsung) for their
suggestions and contributions to this specification.