Copyright © 2012-2018 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and permissive document license rules apply.
This specification defines an API to manage usage and availability of local storage resources, and defines a means by which a user agent (UA) may grant Web applications permission to use more local space, temporarily or persistently, via various different storage APIs.
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 https://www.w3.org/TR/.
Beware. This specification is no longer in active maintenance and the Web Applications Working Group does not intend to maintain it further.
This document is a proposal that is being made available for public review in order to solicit feedback, particularly from implementors, with a goal of potential cross-browser implementation and standardization.
This document was published by the Web Platform Working Group as an Editor's Draft.
Comments regarding this document are welcome. Please send them to public-webapps@w3.org (archives).
Publication as an Editor's 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 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.
This document is governed by the 1 March 2019 W3C Process Document.
Today we have a variety of storage APIs that can store inherently complex or large data in order to satisfy offline data requirements of Web applications. Examples of these APIs include: Application Cache [OFFLINE-WEBAPPS], FileSystem API [FILE-SYSTEM][NEW-FILE-SYSTEM], Indexed Database [INDEXEDDB] and Web SQL Database [WEB-SQL].
These APIs may require larger local space than the conventional cookie storage or Web Storage [WEBSTORAGE], but they do not provide a means by which a Web application can query and manage how much data is currently stored and how much more can be stored.
This specification defines an API to query and manage usage and availability of a user's local storage. The storage space granted by the API is intended to be shared by different storage APIs, therefore a user and UA only need to manage a single upper limit for all storage per logical application unit, e.g. per origin or per browser (which is implementation specific).
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key word MUST in this document is to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
User agents 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.
The terms event handler, event handler event type, fires a simple event are defined in [HTML5].
The Event, EventTarget, EventListener interfaces are defined in [DOM4].
The DOMError and DOMException interfaces are defined in [DOM4].
The Promise interface is currently defined and discussed in the WHATWG DOM specification.
The terms
service worker and
scope url,
and the types
ServiceWorkerGlobalScope
,
ExtendableEvent,
and ExtendableEventInit
are defined in [SERVICE-WORKERS].
A Web application can request temporary or persistent local storage space depending on its purpose.
Temporary storage is especially useful if an application wants to cache data locally to improve its performance, but can fall back to fetching or recreating the same data in case of data loss from temporary storage.
Conversely, persistent storage is useful if an application wants to store critical offline data that is necessary for its function, or wants to manage the amount or lifecycle of local data on its own, rather than relying on the UA's default eviction policy for temporary storage.
Suppose there is a photo editing application. This application manages user photo data using Indexed Database [INDEXEDDB], stores photo images using the Filesystem API [FILE-SYSTEM] [NEW-FILE-SYSTEM] and optionally utilizes Application Cache [OFFLINE-WEBAPPS] to make it work offline.
The application needs to query how much data it can store in the temporary storage to determine its initial cache size.
// Query current usage and availability in Temporary storage: navigator.storageQuota.queryInfo("temporary").then( function(storageInfo) { // Continue to initialize local cache using the obtained // usage and remaining space (quota - usage) information. initializeCache(storageInfo.usage, storageInfo.quota - storageInfo.usage); });
Similarly, the application needs to request additional persistent storage to support offline mode when it is enabled by the user.
// A function which is to be called when 'offline-mode' is enabled // by the user. function onOfflineModeEnabled(amountOfSpaceNeeded) { // First check how much we can use in the Persistent storage. navigator.storageQuota.queryInfo("persistent").then( function (storageInfo) { var availableSpace = storageInfo.quota - storageInfo.usage; if (availableSpace >= amountOfSpaceNeeded) { // We're fine; just continue with the returned storage info. return storageInfo; } return navigator.storageQuota.requestPersistentQuota( amountOfSpaceNeeded + storageInfo.usage); } ).then( function (storageInfo) { // Prepare for offline mode using the current available // storage space. prepareForOfflineMode(storageInfo.quota - storageInfo.usage); }, function (error) { // Handle error. } ); }
StorageType
enumWebIDLenumStorageType
{ "temporary
", "persistent
" };
StorageInfo
dictionaryWebIDLdictionaryStorageInfo
{ unsigned long longusage
; unsigned long longquota
; };
usage
The total amount of data (in bytes) stored by the application for a given storage type. Depending on how the UA calculates data usage the returned value may differ from the exact real-time usage of the user's physical local storage.
quota
The current upper limit of the storage space that can be used by
the application for a given storage type.
This includes the storage area that is already used by the
application, so storageInfo.usage
needs to be
subtracted from storageInfo.quota
to get the
remaining available storage space.
For temporary storage
this value may reflect the actual storage space available
on the user's local device and may change from time to time.
For persistent storage this value must return the
consistent quota size that is granted to the
application by requestPersistentQuota
.
If the application does not have the associated persistent
quota yet the UA may return a UA-specific default quota value
(which could be 0).
StorageQuota
interface
The StorageQuota
interface provides means to query
and request storage usage and quota information.
The API provided by the interface is asynchronous since
querying or allocating space in a user's local storage may require
blocking I/O operations, e.g. examining the local disk status or
making changes in a local database.
WebIDL[NoInterfaceObject] interfaceStorageQuota
{ [SameObject] readonly attribute FrozenArray <StorageType>supportedTypes
; Promise <void>queryInfo
(StorageType type); Promise <void>requestPersistentQuota
([Clamp] unsigned long long newQuota); };
supportedTypes
queryInfo
This method queries the storage info of the given storage
type
.
This returns StorageInfo
that has the current data
usage and available quota information for the application.
When queryInfo
method is called, the UA must
run the following steps:
supportedTypes
array),
reject p with a "NotSupportedError" exception
and abort these steps.
StorageInfo
object, created with
the usage and quota values.
requestPersistentQuota
Requests a new quota in persistent storage
for the requesting application.
It is not guaranteed that the requested amount of space
is granted just by calling this API, and the UA
may return a new StorageInfo
object
(without rejecting the request) with a smaller quota value
than requested.
Calling this API may trigger user prompting to request
explicit user permission to proceed.
StorageInfo
object, created with
usage and grantedQuota.
WebIDL
storageQuota
StorageQuota
interface.
StorageEvent
interface
An event object implementing this interface is passed to
onstoragechange
event handler when storage information is updated.
WebIDL[Constructor(DOMString type, optional StorageEventInit eventInitDict)] interfaceStorageEvent
: Event { readonly attribute unsigned long longusage
; readonly attribute unsigned long longquota
; };
usage
quota
Events are constructed as defined in constructing events in [DOM4].
WebIDLdictionaryStorageEventInit
: EventInit { unsigned long longusage
= 0; unsigned long longquota
= 0; };
StorageWatcher
interface
StorageWatcher
interface is to watch real time
storage changes. This fires storagechange
event
every time a storage status change is detected by the UA,
or about every rate
millisecond(s),
whichever is least frequent.
If rate
is not given in the constructor, the UA
fires storagechange
event whenever it detects
the usage or quota changes in the backend, but no more frequent
than 50ms.
Regardless of the rate
value,
the UA must fire one storagechange
event
with the current storage status
immediately (but asynchronously) after a watcher is constructed,
unless close()
is called before the first
storagechange
event is dispatched.
WebIDL[Constructor(StorageType type, optional unsigned long rate)] interfaceStorageWatcher
: EventTarget { voidclose
(); readonly attribute StorageTypetype
; readonly attribute unsigned longrate
; attribute EventListeneronstoragechange
; };
close
type
type
which this
watcher is constructed with and is monitoring changes on.
rate
rate
value which this
watcher is constructed with.
onstoragechange
storagechange
event.
The space queried and granted by StorageQuota have the following properties:
The Service Worker specification [SERVICE-WORKERS] defines a
ServiceWorkerGlobalScope
interface,
which this specification extends.
WebIDLpartial interfaceServiceWorkerGlobalScope
{ attribute EventHandleronbeforeevicted
; attribute EventHandleronevicted
; };
onbeforeevicted
onbeforeevicted
attribute is an
event handler whose corresponding event handler type is
beforeevicted
.
onevicted
onevicted
attribute is an
event handler whose corresponding
event handler type is evicted
.
This event is going to be dispatched when the Quota Management API detects that there is a storage pressure. If the service worker that received this event did not give back enough space the UA may evict its content entirely.
BeforeEvictEvent
interfaceWebIDL[Constructor(DOMString type, optional BeforeEvictEventInit eventInitDict), Exposed = ServiceWorker] interfaceBeforeEvictEvent
: ExtendableEvent { readonly attribute unsigned long longrequestedBytes
; };
requestedBytes
EvictedEvent
interfaceWebIDL[Constructor(DOMString type, optional EvictedEventInit eventInitDict), Exposed = ServiceWorker]
interface EvictedEvent
: ExtendableEvent {};
This event is only going to be dispatched if there are foreground pages that are otherwise keep the service worker's script and registrations alive. It is thrown to let the service worker communicate to clients that the app has been removed and is unlikely to continue to work. The clients can show appropriate UI in response.
DOMError
or DOMException
(including when the granted quota is zero, i.e. the UA refuses
to grant any quota or the storage is disabled for the site).
As an exception, if the write is being made in the background where
it cannot throw
exception or return an error, the API may fail silently. For example, Application Cache may silently discard or fail to cache data when it is hitting quota limit.
Indexed Database [INDEXEDDB] is expected to have temporary and persistent storage types in its next version, and when that happens the UA should store data for temporary database in temporary storage and for persistent database in persistent storage, respectively.
Many thanks to Robin Berjon for making our lives so much easier with his cool tool.