Version: Smart Feature Phone 2.5

Data Store

Description#

The Data Store API provides a powerful, flexible storage mechanism for KaiOS applications to use to store and share data. It is basically an intermediary store to allow multiple applications to share data between one another quickly, efficiently, and securely, in spite of differences between API data structures, formats, etc. Data Store API concepts and usage

The Data Store API was created to allow multiple KaiOS apps, with potentially different data structures and storage mechanisms, to create, maintain and share the same data objects efficiently between one another. Each app can then import the data into its own local IndexedDB to index according to their specific query needs. This is not necessary however, and you can just write directly to the Data Store API data store.

Note: The Data Store API is available in Web Workers

There are several possible reasons to use this API, including:

  • It lets an application create data that it can then share with other applications.
  • It lets multiple applications supply data to the same data store.
  • It supports read-only data stores such as Facebook contacts (that is, it lets one app create and maintain the data while other apps can read the data from the store).
  • It supports read/write data stores, so that multiple applications can contribute data to the same data store. An example would be the device's standard contacts, which can be updated by both the built-in Contacts app and third-party apps.
  • It supports keeping an application-locale cache of a data store, with notifications to let the app know when there have been changes to the master data store so that the cache can be updated.

This Data Store API datastore is owned by a specific app (as specified by the datastores-owned field in the app's manifest โ€” see Manifest_fields, below), and this ownership gives the app the right to populate the data store and declare whether the data store is readonly (meaning other apps can only read the data) or readwrite (meaning other apps can modify the data as well as read it.) Other apps can gain access to a datastore by naming it in the datastores-access field of their app manifest.

When an app wants to access a datastore, it has to call Navigator.getDataStores(); The result value of this method is a Promise object that will resolve with an array of DataStore objects. From these DataStore objects, the app can read and modify values using various methods of the DataStore such as DataStore.get() and DataStore.insert().

Note: The Data Store API currently has no imposed limitations on storage space. This is likely to be updated in the near future.

Change management and conflict resolution#

When multiple apps make changes to a Data Store, it could create conflicts. However, any change you make (using DataStore.update(), DataStore.add(), etc.) is given a revisionId, a UUID received in the change event fired whenever a operation is performed on the Data Store by any app with access to it. This can be read from the DataStore.revisionId property.

The revisionId property can be included as an optional parameter in the DataStore.add(), DataStore.put(), DataStore.remove(), DataStore.clear(), and DataStore.sync() methods. Doing so basically uses that revisionId as a conflict avoider โ€” the operation is aborted if that revisionId is not the last one known by the Data Store (i.e. if another app has made a more recent change).

When the change event is fired, it receives a DataStoreChangeEvent object, giving the app access to:

  • DataStoreChangeEvent.revisionId: The last known revisionId.
  • DataStoreChangeEvent.id: The key of the changed object, which can be null if the operation was a clear().
  • DataStoreChangeEvent.operation: The operation that was performed โ€” add(), remove(), etc.
  • DataStoreChangeEvent.owner: The manifest URL of the app that performed this operation.

When an app wants to see what has changed, it can do it by asking for the โ€˜deltaโ€™ between the last known revisionId and the current one. This is done using the DataStore.sync() method. You can allow your apps to deal with data changes by running a sync() on application startup and onchange, passing it the current revisionId to check against.

Filtering data#

As hinted at above, the Data Store API is not responsible for filtering data or building indexes; instead it leaves this up to the the app's local storage mechanism (usually an IndexedDB); The Data Store API simply allows the local indexes to be kept up to date, via the DataStoreCursor object, created when sync() is invoked.

Properties#

Manifest fields#

The data store owner's manifest MUST include the datastores-owned field to claim ownership, for example:

"datastores-owned": {
"myData": {
"access": "readwrite",
"description": "my data store"
}
}

You can include multiple properties to represent different data stores, and each one can use readonly/readwrite to specify whether the data store can be read/modified by other applications. A description is also included to describe the purpose of the data store.

Other applications that want to access (not own) the data store must include the datastores-access field, for example:

"datastores-access": {
"myData": {
"access": "readonly",
"description": "Read and modify my data store"
}
}

Without this field being specified, the default behavior is "no access". Again, multiple properties can be included if you want to access multiple data stores, and an access of readonly or readwrite can be set to declare what access type is needed by the app.

In terms of permissions, the Data Store owner always wins against the 3rd party apps. if the owner declares "readonly": true in its manifest, any 3rd party app will be in readonly mode also, even if they declare "access": "readwrite" in their manifests. Of course, this isnโ€™t much use if the owner allows the Data Store to be modified by third party apps, so for the moment, Data Store is a certified API. It is likely to come down to privileged when the security model is finalized.

Note: Remember also that in such cases you need to use the type field in your manifest to explicitly declare that your app is an internal/certified app: "type": "certified".

DataStore API Interfaces#

The Data Store API contains the following interfaces:

  • DataStore
    The DataStore interface represents a retrieved set of data, and includes standard properties for accessing the store's name, owner, etc., methods for reading, modifying and syncing the data, and the onchange event handler for reacting to changes to the data.
  • DataStoreCursor
    This interface allows the app to iterate through a list of DataStoreTask objects representing the change history of the data store, for use when synchronising the data.
  • DataStoreChangeEvent
    This interface represents the event related to a record changed in the data store, i.e. this is returned once a change is made and the change event is fired (see DataStore.onchange for the handler), for use when synchronizing individual changes.
  • DataStoreTask
    This interface represents a record changed in the data store when a DataStoreCursor is used to iterate through the data store's change history.

Methods#

Examples#

We have written a couple of examples that go together, to explain how different apps can make different use of the same data store:

  • The Data Store Contacts Editor creates a data store called 'contacts' on the device it is installed on, adds some default data to it, and allows the user to add new contacts to the store and delete contacts.
  • The Data Store Contacts Viewer has readonly access to the 'contacts' data store; it grabs data from it and displays it in a user interface, along with a Google map of the selected user's location, displayed in an <iframe> to get around certified app CSP restrictions.

Keep referring to these examples and read Using the Data Store API for explanations and code samples.

Note: Be aware that to test data store examples you need to make sure your apps are internal/certified (see above for manifest fields needed), and use App Manager or WebIDE to simulate an environment where a internal/certified app can be run. Follow these links to find out how to do this using each tool: App Manager: Debugging Certified Apps and WebIDE: Debugging Certified Apps.