Push API

W3C Working Draft

This version:
https://www.w3.org/TR/2017/WD-push-api-20171215/
Latest published version:
https://www.w3.org/TR/push-api/
Latest editor's draft:
https://w3c.github.io/push-api/
Previous version:
https://www.w3.org/TR/2017/WD-push-api-20171026/
Editors:
Peter Beverloo, Google
Martin Thomson, Mozilla Foundation
Michaël van Ouwerkerk, Google (until 08 November 2016)
Bryan Sullivan, AT&T (until 01 May 2015)
Eduardo Fullea, Telefonica (until 01 May 2015)
Participate:
Mailing list
Browse open issues
File a bug

Abstract

The Push API enables sending of a push message to a webapp via a push service. An application server can send a push message at any time, even when a webapp or user agent is inactive. The push service ensures reliable and efficient delivery to the user agent. Push messages are delivered to a Service Worker that runs in the origin of the webapp, which can use the information in the message to update local state or display a notification to the user.

This specification is designed for use with the web push protocol, which describes how an application server or user agent interacts with a push service.

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 https://www.w3.org/TR/.

This document was published by the Web Platform Working Group as a Working Draft. This document is intended to become a W3C Recommendation. Comments regarding this document are welcome. Please send them to public-webapps@w3.org (subscribe, archives) with [Push API] at the start of your email's subject.

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 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 2017 W3C Process Document.

1. Introduction

This section is non-normative.

The Push API allows a webapp to communicate with a user agent asynchronously. This allows an application server to provide the user agent with time-sensitive information whenever that information becomes known, rather than waiting for a user to open the webapp.

As defined here, push services support delivery of push messages at any time.

In particular, a push message will be delivered to the webapp even if that webapp is not currently active in a browser window: this relates to use cases in which the user may close the webapp, but still benefits from the webapp being able to be restarted when a push message is received. For example, a push message might be used to inform the user of an incoming WebRTC call.

A push message can also be sent when the user agent is temporarily offline. In support of this, the push service stores messages for the user agent until the user agent becomes available. This supports use cases where a webapp learns of changes that occur while a user is offline and ensures that the user agent can be provided with relevant information in a timely fashion. Push messages are stored by the push service until the user agent becomes reachable and the message can be delivered.

The Push API will also ensure reliable delivery of push messages while a user agent is actively using a webapp, for instance if a user is actively using the webapp or the webapp is in active communication with an application server through an active worker, frame, or background window. This is not the primary use case for the Push API. A webapp might choose to use the Push API for infrequent messages to avoid having to maintain constant communications with the application server.

Push messaging is best suited to occasions where there is not already an active communications channel established between user agent and webapp. Sending push messages requires considerably more resources when compared with more direct methods of communication such as fetch() or websockets. Push messages usually have higher latency than direct communications and they can also be subject to restrictions on use. Most push services limit the size and quantity of push messages that can be sent.

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, SHOULD, and SHOULD NOT 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 current settings object, event handler, event handler event type, fire a simple event, queue a task and trusted event are defined in [HTML51].

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

EventInit, DOMException, AbortError, InvalidStateError, InvalidAccessError, InvalidCharacterError, SecurityError, event listener, 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, ExtendableEventInit, extend lifetime promises, the Clear Registration algorithm, and the Handle Functional Event algorithm are defined in [SERVICE-WORKERS].

The term secure context is defined in [POWERFUL-FEATURES].

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

Blob is defined in [FILEAPI].

Any, ArrayBuffer, BufferSource, DOMString, DOMTimeStamp, JSON type, NotAllowedError, NotSupportedError, USVString and get the underlying value are defined in [WEBIDL].

The web push protocol [RFC8030] 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.

The Content-Encoding HTTP header, described in Section 3.1.2.2 of [RFC7231], indicates the content coding applied to the payload of a push message.

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 service worker 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. Each push subscription is associated with a service worker registration and a service worker registration has at most one push subscription.

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

A push subscription MAY have an associated subscription expiration time. When set, it MUST be the time, in milliseconds since 00:00:00 UTC on 1 January 1970, at which the subscription will be deactivated. The user agent SHOULD attempt to refresh the push subscription before the subscription expires.

A push subscription has internal slots for a P-256 ECDH key pair and an authentication secret in accordance with [WEBPUSH-ENCRYPTION]. These slots MUST be populated when creating the push subscription.

If the user agent has to change the keys for any reason, it MUST fire the pushsubscriptionchange event with the service worker registration associated with the push subscription as registration, a PushSubscription instance representing the push subscription having the old keys as oldSubscription and a PushSubscription instance representing the push subscription having the new keys as newSubscription.

To create a push subscription, given an PushSubscriptionOptions object of options, the user agent must run the following steps:

  1. Let subscription be a new push subscription.
  2. Set the options attribute of subscription to be a copy of options.
  3. Generate a new P-256 ECDH key pair [X9.62]. Store the private key in an internal slot on subscription; this value MUST NOT be made available to applications. The public key is also stored in an internal slot and can be retrieved by calling the getKey method of the PushSubscription with an argument of p256dh.
  4. Generate a new authentication secret, which is a sequence of octets as defined in [WEBPUSH-ENCRYPTION]. Store the authentication secret in an internal slot on subscription. This key can be retrieved by calling the getKey method of the PushSubscription with an argument of auth.
  5. Make a request to the push service to create a new push subscription. Include the applicationServerKey attribute of options when it has been set.
  6. When the request has completed, return subscription.

4.3.1 Subscription Refreshes

A user agent or push service MAY choose to refresh a push subscription at any time, for example because it has reached a certain age.

When this happens, the user agent MUST run the steps to create a push subscription given the PushSubscriptionOptions that were provided for creating the current push subscription. The new push subscription MUST have a key pair that's different from the original subscription.

When successful, user agent then MUST fire the pushsubscriptionchange event with the service worker registration associated with the push subscription as registration, a PushSubscription instance representing the initial push subscription as oldSubscription and a PushSubscription instance representing the new push subscription as newSubscription.

To allow for time to propagate changes to application servers, a user agent MAY continue to accept messages for an old push subscription for a brief time after a refresh. Once messages have been received for a refreshed push subscription, any old push subscriptions MUST be deactivated.

If the user agent is not able to refresh the push subscription, it SHOULD periodically retry the refresh. When the push subscription can no longer be used, for example because it has expired, the user agent MUST fire the pushsubscriptionchange event with the service worker registration associated with the push subscription as registration, a PushSubscription instance representing the deactivating push subscription as oldSubscription and null as the newSubscription.

4.3.2 Subscription Deactivation

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 is removed when the clear registration algorithm is run for the service worker registration.

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 push endpoint or endpoints for the push subscriptions it serves.

There is only one push service per user agent and it cannot be changed from the default value. This limitation is due to a variety of performance-related concerns, including the complexity of running reliable push services and the impact on battery lifetime if there were an unbounded set of push services to which a device could connect.

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 use of the Push API by the webapp.

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 Push API may have to wake up the Service Worker associated with the service worker registration in order to run the developer-provided event handlers. This can cause resource usage, such as network traffic, that the user agent SHOULD attribute to the webapp that created the push subscription.

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

When a permission is revoked, the user agent MAY fire the pushsubscriptionchange event for subscriptions created with that permission, with the service worker registration associated with the push subscription as registration, a PushSubscription instance representing the push subscription as oldSubscription, and null as newSubscription. The user agent MUST deactivate the affected subscriptions in parallel.

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

The push endpoint MUST NOT expose information about the user to be derived by actors other than the push service, such as the user's device, identity or location. See the Privacy Considerations in [RFC8030] for the exact requirements.

The push 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 only be available in secure contexts. This 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.

There is no guarantee that a push message was sent by an application server having the same origin as the webapp. The application server is able to share the details necessary to use a push subscription with a third party at its own discretion.

6. Push Framework

This section is non-normative.

A push message is sent from an application server to a webapp as follows:

This overall framework allows application servers to activate a Service Worker in response to events at the application server. Information about those events can be included in the push message, which allows the webapp to react appropriately to those events, potentially without needing to initiate network requests.

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);
        console.log(pushSubscription.getKey('p256dh'));
        console.log(pushSubscription.getKey('auth'));
        // 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
Figure 1 Example flow of events for subscription, push message delivery, and unsubscription

6.3 Push service use

The fields included in the PushSubscription is all the information needed for an application server to send a push message. Push services that are compatible with the Push API provide a push endpoint that conforms to the web push protocol. These parameters and attributes include:

7. Extensions to the ServiceWorkerRegistration Interface

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

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

[Exposed=(Window,Worker),
 SecureContext]
interface PushManager {
    [SameObject]
    static readonly attribute FrozenArray<DOMString> supportedContentEncodings;

    Promise<PushSubscription>    subscribe(optional PushSubscriptionOptionsInit options);
    Promise<PushSubscription?>   getSubscription();
    Promise<PushPermissionState> permissionState(optional PushSubscriptionOptionsInit options);
};

The supportedContentEncodings attribute exposes the sequence of supported content codings that can be used to encrypt the payload of a push message. A content coding is indicated using the Content-Encoding header field when requesting the sending of a push message from the push service.

User agents MUST support the aes128gcm content coding defined in [WEBPUSH-ENCRYPTION], and MAY support content codings defined in previous versions of the draft for compatibility reasons.

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 current settings object is not a secure context, reject promise with a DOMException whose name is "SecurityError" and terminate these steps.
  4. If the options argument includes a non-null value for the applicationServerKey attribute, run the following substeps:
    1. If the applicationServerKey is provided as a DOMString, set its value to a BufferSource containing the sequence of octets that result from decoding applicationServerKey using the base64url encoding [RFC7515]. If decoding fails, reject promise with a DOMException whose name is "InvalidCharacterError" and terminate these steps.
    2. Ensure that applicationServerKey describes a valid point on the P-256 curve. If the applicationServerKey value is invalid, reject promise with a DOMException whose name is "InvalidAccessError" and terminate these steps.
  5. If the options argument does not include a non-null value for the applicationServerKey attribute, and the push service requires one to be given, reject promise with a DOMException whose name is "NotSupportedError" and terminate these steps.
  6. Let registration be the PushManager's associated service worker registration.
  7. If registration's active worker is null, reject promise with a DOMException whose name is "InvalidStateError" and terminate these steps.
  8. 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. Note that a user agent that needs to request permission might be unable to do so if subscribe is invoked from a service worker, in which case permission will be denied automatically.
  9. If not granted, reject promise with a DOMException whose name is "NotAllowedError" and terminate these steps.
  10. If the Service Worker is already subscribed, run the following substeps:
    1. Retrieve the push subscription associated with the Service Worker.
    2. If there is an error, reject promise with a DOMException whose name is "AbortError" and terminate these steps.
    3. Let subscription be the retrieved subscription.
    4. Compare the options argument with the options attribute of subscription. If any attribute on options contains a different value to that stored for subscription, then reject promise with an InvalidStateError and terminate these steps. The contents of BufferSource values are compared for equality rather than references.
    5. When the request has been completed, resolve promise with subscription.
  11. Let subscription be the result of running the create a push subscription steps given options.
  12. If there is an error, reject promise with a DOMException whose name is "AbortError" and terminate these steps.
  13. Resolve promise with a PushSubscription providing the details of the new 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 Service Worker is not subscribed, resolve promise with null.
  4. Retrieve the push subscription associated with the Service Worker.
  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 Interface and Dictionary

A PushSubscriptionOptionsInit 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.

These options are optional, and user agents MAY choose to support only a subset of them. A user agent MUST NOT expose options that it does not support.

Once set, options for a push subscription cannot change. A pre-existing push subscription can be unsubscribed to create a push subscription with new options.

dictionary PushSubscriptionOptionsInit {
    boolean                      userVisibleOnly = false;
    (BufferSource or DOMString)? applicationServerKey = null;
};

[Exposed=(Window,Worker),
 SecureContext]
interface PushSubscriptionOptions {
    readonly attribute boolean      userVisibleOnly;
    [SameObject]
    readonly attribute ArrayBuffer? applicationServerKey;
};

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]

The applicationServerKey option is used by the user agent when establishing a push subscription with a push service. The applicationServerKey option includes an elliptic curve public key for an application server. This is the key that the application server will use to authenticate itself when sending push messages to this push subscription as defined in [WEBPUSH-VAPID]; the push service will reject any push message unless the corresponding private key is used to generate an authentication token.

If present, the value of applicationServerKey MUST include a point on the P-256 elliptic curve [DSS], encoded in the uncompressed form described in [X9.62] Annex A (that is, 65 octets, starting with an 0x04 octet). When provided as a DOMString, the value MUST be encoded using the base64url encoding [RFC7515].

User agents MAY reject a subscription attempt when applicationServerKey is not present and the push service requires one for operational reasons.

The applicationServerKey MUST be a different value to the one used for message encryption [WEBPUSH-ENCRYPTION].

9. PushSubscription interface

A PushSubscription object represents a push subscription.

[Exposed=(Window,Worker),
 SecureContext]
interface PushSubscription {
    readonly attribute USVString               endpoint;
    readonly attribute DOMTimeStamp?           expirationTime;
    [SameObject]
    readonly attribute PushSubscriptionOptions options;
    ArrayBuffer?         getKey(PushEncryptionKeyName name);
    Promise<boolean>     unsubscribe();

    PushSubscriptionJSON toJSON();
};

dictionary PushSubscriptionJSON {
    USVString                    endpoint;
    DOMTimeStamp?                expirationTime;
    record<DOMString, USVString> keys;
};

When getting the endpoint attribute, the user agent MUST return the push endpoint associated with the push subscription. The user agent MUST use a serialization method that does not contain input-dependent branchs (that is, one that is constant time).

When getting the expirationTime attribute, the user agent MUST return the subscription expiration time associated with the push subscription if there is one, or null otherwise.

When getting the options attribute, the user agent MUST return a PushSubscriptionOptions object representing the options associated with the push subscription.

The getKey method retrieves keying material that can be used for encrypting and authenticating messages. When getKey is invoked the following process is followed:

  1. Find the internal slot corresponding to the key named by the name argument.
  2. If a slot was not found, return null.
  3. Initialize a variable key with a newly instantiated ArrayBuffer instance.
  4. If the internal slot contains an asymmetric key pair, set the contents of key to the serialized value of the public key from the key pair. This uses the serialization format described in the specification that defines the name. For example, [WEBPUSH-ENCRYPTION] specifies that the p256dh public key is encoded using the uncompressed format defined in [X9.62] Annex A (that is, a 65 octet sequence that starts with a 0x04 octet).
  5. Otherwise, if the internal slot contains a symmetric key, set the contents of key to a copy of the value from the internal slot. For example, the auth parameter contains an octet sequence used by the user agent to authenticate messages sent by an application server.
  6. Return key.

Keys named p256dh and auth MUST be supported, and their values MUST correspond to those necessary for the user agent to decrypt received push messages in accordance with [WEBPUSH-ENCRYPTION].

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. Run the following step in parallel:
    1. Deactivate the push subscription. The user agent MUST NOT deliver any further push messages for the push subscription.

      If the user agent failed to request the push service to deactivate the push subscription, for example because of network failures, it SHOULD retry the request to the push service for a reasonable amount of time.

  5. Resolve promise with true.

The toJSON method when invoked MUST run the following steps:

  1. Let json be a new PushSubscriptionJSON dictionary.
  2. Set json["endpoint"] to the result of getting the underlying value of the endpoint attribute given this PushSubscription object.
  3. Set json["expirationTime"] to the result of getting the underlying value of the expirationTime attribute given this PushSubscription object.
  4. Let keys be a new empty instance of record<DOMString, USVString> .
  5. For each identifier i corresponding to keys in internal slots on the PushSubscription, ordered by the name of the key:
    1. If the internal slot corresponds to an asymmetric key pair, let b be the encoded value of the public key corresponding to the key name i, using the encoding defined for the key name (see getKey).
    2. Otherwise, let b be the value as returned by getKey.
    3. Let s be the URL-safe base64 encoding without padding [RFC4648] of b as a USVString. The user agent MUST use a serialization method that does not branch based on the value of b.
    4. Set keys[i] to s.
  6. Set json["keys"] to keys.
  7. Return json.

A PushSubscriptionJSON dictionary represents the JSON type of a PushSubscription. In ECMAScript this can be converted into a JSON string through the JSON.stringify function.

The endpoint contains the underlying value of the endpoint attribute.

The expirationTime contains the underlying value of the expirationTime attribute.

The keys record contains an entry for each of the supported PushEncryptionKeyName entries to the URL-safe base64 encoded representation [RFC4648] of its value.

Note that the options to a PushSubscription are not serialized.

9.1 PushEncryptionKeyName enumeration

Encryption keys used for push message encryption are provided to a webapp through the getKey method or the serializer of PushSubscription. Each key is named using a value from the PushEncryptionKeyName enumeration.

enum PushEncryptionKeyName {
    "p256dh",
    "auth"
};

The p256dh value is used to retrieve the P-256 ECDH Diffie-Hellman public key described in [WEBPUSH-ENCRYPTION].

The auth value is used to retrieve the authentication secret described in [WEBPUSH-ENCRYPTION].

10. PushMessageData interface

[Exposed=ServiceWorker,
 SecureContext]
interface PushMessageData {
    ArrayBuffer arrayBuffer();
    Blob        blob();
    any         json();
    USVString   text();
};

PushMessageData objects have an associated bytes (a byte sequence) set on creation, which is null if there was no data in the push message.

The arrayBuffer method, when invoked, MUST return an ArrayBuffer whose contents are bytes. Exceptions thrown during the creation of the ArrayBuffer object are re-thrown.

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.

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

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

11. Events

11.1 Extensions to the ServiceWorkerGlobalScope interface

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

[Exposed=ServiceWorker,
 SecureContext]
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.2 The push Event

The push event indicates that a push message has been received for a push subscription.

To fire the push event given a service worker registration of registration and a PushMessageData of data, the user agent must run the following steps:

  1. Create a trusted event, event, that uses the PushEvent interface, with the event type pushevent, which does not bubble, is not cancelable, and has no default action.
  2. Set the data attribute of event to data.
  3. Invoke the Handle Functional Event algorithm with event and registration, and callbackSteps set to the following steps:
    1. Set global to the global object associated with the registration.
    2. Dispatch event to global.
  4. Return event.

11.2.1 PushEvent Interface

typedef (BufferSource or USVString) PushMessageDataInit;

dictionary PushEventInit : ExtendableEventInit {
    PushMessageDataInit data;
};

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

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 are extended to include the following steps:

  1. If eventInitDict's data member is not present, set the data attribute of the event to null and terminate these steps.
  2. Set b to the result of extracting a byte sequence from the "data" member of eventInitDict.
  3. Set the data attribute of the event to a new PushMessageData instance with bytes set to b.

The data attribute contains the data included in the push message when included and the user agent verified its authenticity. The value will be set to null in all other cases.

11.2.2 Receiving a Push Message

When the user agent receives a push message from the push service, it MUST run the following steps.

  1. Let registration be the service worker registration corresponding to the push message.
  2. If registration is not found, abort these steps.
  3. Let subscription be the active push subscription for registration.
  4. Initialize data to a value of null.
  5. If the push message contains a payload, perform the following steps:
    1. Decrypt the push message using the private key from the key pair associated with subscription and the process described in [WEBPUSH-ENCRYPTION]. This produces the plain text of the message.
    2. If the push message could not be decrypted for any reason, perform the following steps:
      1. Acknowledge the receipt of the push message according to [RFC8030]. Though the message was not successfully received and processed, this prevents the push service from attempting to retransmit the message; a badly encrypted message is not recoverable.
      2. Discard the push message.
      3. Terminate this process.
      A push event MUST NOT be fired for a push message that was not successfully decrypted using the key pair associated with the push subscription.
    3. Let data be a new PushMessageData instance with the decrypted plain text of the push message.
  6. Fire the push event with registration and data, and set event to the returned trusted event.
  7. Run the following steps in parallel:
    1. Wait for all of the promises in the extend lifetime promises of event to resolve.
    2. If all the promises resolve successfully, acknowledge the receipt of the push message according to [RFC8030] and abort these steps.
    3. If the same push message has been delivered to a service worker registration multiple times unsuccessfully, acknowledge the receipt of the push message according to [RFC8030].

      Acknowledging the push message causes the push service to stop delivering the message and to report success to the application server. This prevents the same push message from being retried by the push service indefinitely.

      Acknowledging also means that an application server could incorrectly receive a delivery receipt indicating successful delivery of the push message. Therefore, multiple rejections SHOULD be permitted before acknowledging; allowing at least three attempts is recommended.

11.3 The pushsubscriptionchange Event

The pushsubscriptionchange event indicates a change in a push subscription that was triggered outside of the application's control, for example because it has been refreshed, revoked or lost.

To fire the pushsubscriptionchange event given a service worker registration of registration, newSubscription and oldSubscription, the user agent must run the following steps:

  1. Create a trusted event, event, that uses the PushSubscriptionChangeEvent interface, with the event type pushsubscriptionchange, which does not bubble, is not cancelable, and has no default action.
  2. Set the newSubscription attribute of event to newSubscription.
  3. Set the oldSubscription attribute of event to oldSubscription.
  4. Invoke the Handle Functional Event algorithm with event and registration, and callbackSteps set to the following steps:
    1. Set global to the global object associated with the registration.
    2. Dispatch event to global.
Note

Consider using a more reliable synchronization mechanism such as [WEB-BACKGROUND-SYNC] when sending the details of the new push subscription to your application server. The user might be subject to unreliable network conditions that could cause a fetch to fail.

11.3.1 PushSubscriptionChangeEvent Interface

dictionary PushSubscriptionChangeInit : ExtendableEventInit {
    PushSubscription newSubscription = null;
    PushSubscription oldSubscription = null;
};

[Constructor(DOMString type, optional PushSubscriptionChangeInit eventInitDict),
 Exposed=ServiceWorker,
 SecureContext]
interface PushSubscriptionChangeEvent : ExtendableEvent {
    readonly attribute PushSubscription? newSubscription;
    readonly attribute PushSubscription? oldSubscription;
};

The newSubscription attribute contains the details of the push subscription that is valid per invocation of the pushsubscriptionchange event. The value will be null when no new push subscription could be established, for example because the webapp has lost express permission.

The oldSubscription attribute contains the details of the push subscription that SHOULD NOT be used anymore. The value will be null when the user agent is not able to provide the full set of details, for example because of partial database corruption.

12. PushPermissionState Enumeration

enum PushPermissionState {
    "denied",
    "granted",
    "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.

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, as well as to the following people who provided significant technical input to this document: Antonio Amaya, Miguel García Arribas, Ben Bangert, Kit Cambridge, José Manuel Cantera, JR Conlin, Albert Crespell, Matt Gaunt, Phil Jenvey, Guillermo López, Nikhil Marathe, John Mellor, Pınar Özlen, Fernando R. Sela, Shijun Sun and Doug Turner.

B. References

B.1 Normative references

[DOM]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[DSS]
FIPS PUB 186-4: Digital Signature Standard (DSS). U.S. Department of Commerce/National Institute of Standards and Technology. July 2013. URL: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.github.io/ecma262/
[ENCODING]
Encoding Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://encoding.spec.whatwg.org/
[FILEAPI]
File API. Marijn Kruisselbrink. W3C. 26 October 2017. W3C Working Draft. URL: https://www.w3.org/TR/FileAPI/
[HTML51]
HTML 5.1 2nd Edition. Steve Faulkner; Arron Eicholz; Travis Leithead; Alex Danilo. W3C. 3 October 2017. W3C Recommendation. URL: https://www.w3.org/TR/html51/
[POWERFUL-FEATURES]
Secure Contexts. Mike West. W3C. 15 September 2016. W3C Candidate Recommendation. URL: https://www.w3.org/TR/secure-contexts/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC4648]
The Base16, Base32, and Base64 Data Encodings. S. Josefsson. IETF. October 2006. Proposed Standard. URL: https://tools.ietf.org/html/rfc4648
[RFC7231]
Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content. R. Fielding, Ed.; J. Reschke, Ed.. IETF. June 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7231
[RFC7515]
JSON Web Signature (JWS). M. Jones; J. Bradley; N. Sakimura. IETF. May 2015. Proposed Standard. URL: https://tools.ietf.org/html/rfc7515
[RFC8030]
Generic Event Delivery Using HTTP Push. M. Thomson; E. Damaggio; B. Raymor, Ed.. IETF. December 2016. Proposed Standard. URL: https://tools.ietf.org/html/rfc8030
[SERVICE-WORKERS]
Service Workers 1. Alex Russell; Jungkee Song; Jake Archibald; Marijn Kruisselbrink. W3C. 2 November 2017. W3C Working Draft. URL: https://www.w3.org/TR/service-workers-1/
[WEBIDL]
Web IDL. Cameron McCormack; Boris Zbarsky; Tobie Langel. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/
[WEBPUSH-ENCRYPTION]
Message Encryption for Web Push. Martin Thomson. IETF. Internet-Draft. URL: https://tools.ietf.org/html/draft-ietf-webpush-encryption
[WEBPUSH-VAPID]
Voluntary Application Server Identification for Web Push. Martin Thomson; Peter Beverloo. IETF. Internet-Draft. URL: https://tools.ietf.org/html/draft-ietf-webpush-vapid
[X9.62]
Public Key Cryptography for the Financial Services Industry, The Elliptic Curve Digital Signature Algorithm (ECDSA) ANSI. ANS X9.62–2005.

B.2 Informative references

[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[NOTIFICATIONS]
Notifications API. Anne van Kesteren. WHATWG. Living Standard. URL: https://notifications.spec.whatwg.org/
[WEB-BACKGROUND-SYNC]
Web Background Synchronization. WICG. Living Standard. URL: https://wicg.github.io/BackgroundSync/spec/