Abstract

The Push API provides webapps with scripted access to server-sent messages, for simplicity referred to here as push messages, as delivered by push services. A push service allows an application server to send messages to a webapp, regardless of whether the webapp is currently active on the user agent. The push message will be delivered to a Service Worker, which could then store the message's data or display a notification to the user.

This specification is designed to promote compatibility with any delivery method for push messages from push services to user agents.

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 was published by the Web Applications Working Group as a Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-webapps@w3.org (subscribe, archives) with [Push API] at the start of your email's subject. All comments are welcome.

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.

This document is governed by the 1 August 2014 W3C Process Document.

Table of Contents

1. Introduction

This section is non-normative.

As defined here, push services support delivery of application server messages in the following contexts and related use cases:

2. Conformance

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 words MAY, MUST, MUST NOT, and SHOULD are to be interpreted as described in [RFC2119].

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].

3. Dependencies

The terms event handler, event handler event type, queue a task, and fire a simple event are defined in [HTML5].

Promise, and JSON.parse are defined in [ECMASCRIPT].

EventInit, DOMException, AbortError, InvalidStateError, SecurityError, NetworkError, and steps for constructing events are defined in [DOM].

The terms service worker, service worker registration, installing worker, waiting worker, and active worker, and the types ServiceWorkerRegistration, ServiceWorkerGlobalScope, ExtendableEvent, and ExtendableEventInit are defined in [SERVICE-WORKERS].

The algorithms utf-8 encode, and utf-8 decode are defined in [ENCODING].

Blob is defined in [FILEAPI].

Any, ArrayBuffer, BufferSource, and USVString are defined in [WEBIDL].

The web push protocol describes a protocol that enables communication between a user agent or application server and a push service. Alternative protocols could be used in place of this protocol, but this specification assumes the use of this protocol; alternative protocols are expected to provide compatible semantics. Note: this is currently only a proposed protocol.

4. Concepts

4.1 Webapp

The term webapp refers to a Web application, i.e. an application implemented using Web technologies, and executing within the context of a Web user agent, e.g. a Web browser or other Web runtime environment.

The term application server refers to server-side components of a webapp.

4.2 Push message

A push message is data sent to a webapp from an application server.

A push message is delivered to the active worker associated with the push subscription to which the message was submitted. If the worker or its webapp is not currently running, the worker is started to enable delivery.

4.3 Push subscription

A push subscription is a message delivery context established between the user agent and the push service on behalf of a webapp, and associated with the webapp's service worker registration.

When a push subscription is deactivated, both the user agent and the push service MUST delete any stored copies of its details. Subsequent push messages for this push subscription MUST NOT be delivered.

A push subscription is deactivated when its associated service worker registration is unregistered, though a push subscription MAY be deactivated earlier.

A push subscription has an associated endpoint. It MUST be the absolute URL exposed by the push service where the application server can send push messages to. An endpoint MUST uniquely identify the push subscription.

4.4 Push service

The term push service refers to a system that allows application servers to send push messages to a webapp. A push service serves the endpoint or endpoints for the push subscriptions it serves.

4.5 Permission

The term express permission refers to an act by the user, e.g. via user interface or host device platform features, via which the user approves the permission of a webapp to access the Push API.

5. Security and privacy considerations

User agents MUST NOT provide Push API access to webapps without the express permission of the user. User agents MUST acquire consent for permission through a user interface for each call to the subscribe() method, unless a previous permission grant has been persisted, or a prearranged trust relationship applies. Permissions that are preserved beyond the current browsing session MUST be revocable.

The user agent MAY consider the PushSubscriptionOptions when acquiring permission or determining the permission status.

When a permission is revoked, all push subscriptions created with that permission MUST be deactivated.

When a service worker registration is unregistered, any associated push subscription MUST be deactivated.

The endpoint of a deactivated push subscription MUST NOT be reused for a new push subscription. This prevents the creation of a persistent identifier that the user cannot remove. This also prevents reuse of the details of one push subscription to send push messages to another push subscription.

User agents MUST implement the Push API to be HTTPS-only. SSL-only support provides better protection for the user against man-in-the-middle attacks intended to obtain push subscription data. Browsers may ignore this rule for development purposes only.

6. Push Framework

This section is non-normative.

Although push services are expected to differ in deployment, a typical deployment is expected to have the following general entities and example operation for delivery of push messages:

This overall framework allows application servers to inform webapps that new data is available at the application server, or pass the new data directly to the webapp in the push message.

The push API enables delivery of arbitrary application data to webapps, and makes no assumptions about the over-the-air/wire protocol used by push services. As such, the details of what types of data flow through a push services for a particular webapp are specific to the push service and webapp. As needed, clarification about what data flows over-the-air/wire should be sought from push service operators or webapp developers.

The following code and diagram illustrate a hypothetical use of the push API.

6.1 Example

This section is non-normative.

Example 1
// https://example.com/serviceworker.js
this.onpush = function(event) {
  console.log(event.data);
  // From here we can write the data to IndexedDB, send it to any open
  // windows, display a notification, etc.
}

// https://example.com/webapp.js
navigator.serviceWorker.register('serviceworker.js').then(
  function(serviceWorkerRegistration) {
    serviceWorkerRegistration.pushManager.subscribe().then(
      function(pushSubscription) {
        console.log(pushSubscription.endpoint);
        // The push subscription details needed by the application
        // server are now available, and can be sent to it using,
        // for example, an XMLHttpRequest.
      }, function(error) {
        // During development it often helps to log errors to the
        // console. In a production environment it might make sense to
        // also report information about errors back to the
        // application server.
        console.log(error);
      }
    );
  });

6.2 Sequence diagram

This section is non-normative.

Example flow of events for subscription, push message delivery, and unsubscription
Fig. 1 Example flow of events for subscription, push message delivery, and unsubscription

6.3 Push service use

A PushSubscription contains all the information needed to send a push message. A push message can be delivered using the web push protocol.

The endpoint of a PushSubscription is a URI that allows an application server to request delivery of a push message to a push subscription.

7. Extensions to the ServiceWorkerRegistration interface

The Service Worker specification defines a ServiceWorkerRegistration interface [SERVICE-WORKERS], which this specification extends.

partial interface ServiceWorkerRegistration {
    readonly    attribute PushManager pushManager;
};

The pushManager attribute exposes a PushManager, which has an associated service worker registration represented by the ServiceWorkerRegistration on which the attribute is exposed.

8. PushManager interface

The PushManager interface defines the operations to access push services.

interface PushManager {
    Promise<PushSubscription>    subscribe (optional PushSubscriptionOptions options);
    Promise<PushSubscription?>   getSubscription ();
    Promise<PushPermissionState> permissionState (optional PushSubscriptionOptions options);
};

The subscribe method when invoked MUST run the following steps:

  1. Let promise be a new Promise.
  2. Return promise and continue the following steps asynchronously.
  3. If the scheme of the document url is not https, reject promise with a DOMException whose name is "SecurityError" and terminate these steps.
  4. Let registration be the PushManager's associated service worker registration.
  5. If registration has no active worker, run the following substeps:
    1. If registration has no installing worker and no waiting worker, reject promise with a DOMException whose name is "InvalidStateError" and terminate these steps.
    2. Wait for the installing worker or waiting worker of registration to become its active worker.
    3. If registration fails to activate either worker, reject promise with a DOMException whose name is "InvalidStateError" and terminate these steps.
    4. Once registration has an active worker, proceed with the steps below.
  6. Ask the user whether they allow the webapp to receive push messages, unless a prearranged trust relationship applies or the user has already granted or denied permission explicitly for this webapp.
  7. If not granted, reject promise with a DOMException whose name is "PermissionDeniedError" and terminate these steps.
  8. If the webapp is already subscribed, run the following substeps:
    1. Retrieve the push subscription associated with the webapp.
    2. If there is an error, reject promise with a DOMException whose name is "AbortError" and terminate these steps.
    3. When the request has been completed, resolve promise with a PushSubscription providing the details of the retrieved push subscription.
  9. Make a request to the push service to create a new push subscription for the webapp.
  10. If there is an error, reject promise with a DOMException whose name is "AbortError" and terminate these steps.
  11. When the request has been completed, resolve promise with a PushSubscription providing the details of the new push subscription.

The getSubscription method when invoked MUST run the following steps:

  1. Let promise be a new Promise.
  2. Return promise and continue the following steps asynchronously.
  3. If the webapp is not subscribed, resolve promise with null.
  4. Retrieve the push subscription associated with the webapp.
  5. If there is an error, reject promise with a DOMException whose name is "AbortError" and terminate these steps.
  6. When the request has been completed, resolve promise with a PushSubscription providing the details of the retrieved push subscription.

The permissionState method when invoked MUST run the following steps:

  1. Let promise be a new Promise.
  2. Return promise and continue the following steps asynchronously.
  3. Retrieve the push permission status (PushPermissionState) of the requesting webapp.
  4. If there is an error, reject promise with no arguments and terminate these steps.
  5. When the request has been completed, resolve promise with PushPermissionState providing the push permission status.

Permission to use the push service can be persistent, that is, it does not need to be reconfirmed for subsequent subscriptions if a valid permission exists.

If there is a need to ask for permission, it needs to be done by invoking the subscribe method.

8.1 PushSubscriptionOptions dictionary

A PushSubscriptionOptions object represents additional options associated with a push subscription. The user agent MAY consider these options when requesting express permission from the user. When an option is considered, the user agent SHOULD enforce it on incoming push messages.

dictionary PushSubscriptionOptions {
    boolean userVisibleOnly = false;
};

The userVisibleOnly option, when set to true, indicates that the push subscription will only be used for push messages whose effect is made visible to the user, for example by displaying a Web Notification. [NOTIFICATIONS]

9. PushSubscription interface

A PushSubscription object represents a push subscription.

interface PushSubscription {
    readonly    attribute USVString endpoint;
    Promise<boolean> unsubscribe ();
    serializer = {attribute};
};

When getting the endpoint attribute, the user agent MUST return the endpoint associated with the push subscription.

The unsubscribe method when invoked MUST run the following steps:

  1. Let promise be a new Promise.
  2. Return promise and continue the following steps asynchronously.
  3. If the push subscription has already been deactivated, resolve promise with false and terminate these steps.
  4. Make a request to the push service to deactivate the push subscription.
  5. If it was not possible to access the push service, reject promise with a "NetworkError" exception and terminate these steps.
  6. When the request has been completed, resolve promise with true.

10. PushMessageData interface

interface PushMessageData {
    ArrayBuffer arrayBuffer ();
    Blob        blob ();
    Any         json ();
    USVString   text ();
};

PushMessageData objects have an associated bytes (a byte sequence) set on creation.

The arrayBuffer() method, when invoked, MUST return an ArrayBuffer whose contents are bytes.

The blob() method, when invoked, MUST return a Blob whose contents are bytes and type is not provided.

The json() method, when invoked, MUST return the result of invoking the initial value of JSON.parse with the result of running utf-8 decode on bytes as argument. Re-throw any exceptions thrown by JSON.parse.

The text() method, when invoked, MUST return the result of running utf-8 decode on bytes.

typedef USVString PushMessageDataInit;
Note

In future, PushMessageDataInit is likely to be a union type that includes types such as Blob and BufferSource. The algorithm below would be extended, rather like the Fetch standard's extract a byte stream algorithm.

To extract a byte sequence from object, run these steps:

  1. Let bytes be an empty byte sequence.
  2. Switch on object's type:
    USVString
    Set bytes to the result of running utf-8 encode on object.
  3. Return bytes.

11. Events

The Service Worker specification defines a ServiceWorkerGlobalScope interface [SERVICE-WORKERS], which this specification extends.

partial interface ServiceWorkerGlobalScope {
                attribute EventHandler onpush;
                attribute EventHandler onpushsubscriptionchange;
};

The onpush attribute is an event handler whose corresponding event handler event type is push.

The onpushsubscriptionchange attribute is an event handler whose corresponding event handler event type is pushsubscriptionchange.

11.1 The push event

The PushEvent interface represents a received push message.

dictionary PushEventInit : ExtendableEventInit {
    PushMessageDataInit data;
};

[Constructor(DOMString type, optional PushEventInit eventInitDict), Exposed=ServiceWorker] interface PushEvent : ExtendableEvent { readonly attribute PushMessageData data; };

Upon receiving a push message for a push subscription from the push service the user agent MUST run the following steps:

  1. If the Service Worker associated with the webapp is not running, start it.
  2. Let scope be the ServiceWorkerGlobalScope of the Service Worker associated with the webapp.
  3. Let event be a new PushEvent, whose data attribute is a new PushMessageData with bytes set to the binary message data received by the user agent in the push message, or an empty byte sequence if no data was received.
  4. Queue a task to fire event as a simple event named push at scope.

When a constructor of the PushEvent interface, or of an interface that inherits from the PushEvent interface, is invoked, the usual steps for constructing events MUST be modified as follows: instead of setting the data attribute of the event to the value of the eventInitDict's "data" member, set the data attribute to a new PushMessageData with bytes set to the result of extracting a byte sequence from that dictionary member, or an empty byte sequence if eventInitDict is not provided or has no "data" member.

11.2 The pushsubscriptionchange event

The pushsubscriptionchange event indicates that a push subscription has been invalidated, or will soon be invalidated. For example, the push service MAY set an expiration time. A webapp SHOULD attempt to resubscribe while handling this event, in order to continue receiving push messages.

To fire a pushsubscriptionchange event, the user agent MUST run the following steps:

  1. If the Service Worker associated with the webapp is not running, start it.
  2. Let scope be the ServiceWorkerGlobalScope of the Service Worker associated with the webapp.
  3. Queue a task to fire a simple event named pushsubscriptionchange at scope.

12. Enumerations

enum PushPermissionState {
    "granted",
    "denied",
    "prompt"
};
Enumeration Description
granted The webapp has permission to use the Push API.
denied The webapp has been denied permission to use the Push API.
prompt The webapp needs to ask for permission in order to use the Push API.

13. Exceptions

The Push API uses the following new DOMException names.

Name Description
PermissionDeniedError The operation failed because the user denied permission to use the API.

A. Acknowledgements

The editors would like to express their gratitude to the Mozilla and Telefónica Digital teams implementing the Firefox OS Push message solution and specially to Doug Turner, Nikhil Marathe, Fernando R. Sela, Guillermo López, Antonio Amaya, José Manuel Cantera and Albert Crespell, for their technical guidance, implementation work and support.

B. References

B.1 Normative references

[DOM]
Anne van Kesteren; Aryeh Gregor; Ms2ger; Alex Russell; Robin Berjon. W3C DOM4. 10 July 2014. W3C Last Call Working Draft. URL: http://www.w3.org/TR/dom/
[ECMASCRIPT]
Allen Wirfs-Brock. ECMAScript 2015 Language Specification. Draft. URL: https://people.mozilla.org/~jorendorff/es6-draft.html
[ENCODING]
Anne van Kesteren; Joshua Bell; Addison Phillips. Encoding. 16 September 2014. W3C Candidate Recommendation. URL: http://www.w3.org/TR/encoding/
[FILEAPI]
Arun Ranganathan; Jonas Sicking. File API. 21 April 2015. W3C Working Draft. URL: http://www.w3.org/TR/FileAPI/
[HTML5]
Ian Hickson; Robin Berjon; Steve Faulkner; Travis Leithead; Erika Doyle Navara; Edward O'Connor; Silvia Pfeiffer. HTML5. 28 October 2014. W3C Recommendation. URL: http://www.w3.org/TR/html5/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[SERVICE-WORKERS]
Alex Russell; Jungkee Song; Jake Archibald. Service Workers. 5 February 2015. W3C Working Draft. URL: http://www.w3.org/TR/service-workers/
[WEBIDL]
Cameron McCormack. Web IDL. 19 April 2012. W3C Candidate Recommendation. URL: http://www.w3.org/TR/WebIDL/

B.2 Informative references

[NOTIFICATIONS]
Anne van Kesteren. Notifications API. Living Standard. URL: https://notifications.spec.whatwg.org/