nsIPushService

A service for components to subscribe and receive push messages from remote servers.
Inherits from: nsISupports Last changed in Gecko 46.0 (Firefox 46.0 / Thunderbird 46.0 / SeaMonkey 2.43)

Push lets a remote server send payloads to a web site, add-on, or component running in the browser. nsIPushService supports the Push API implementation in Firefox, and can be used directly from privileged code to create system subscriptions.

Implemented by @mozilla.org/push/Service;1 as a service:

const pushService = Components.classes["@mozilla.org/push/Service;1"]
                              .getService(Components.interfaces.nsIPushService);

Method overview

void subscribe(in DOMString scope, in nsIPrincipal principal, in nsIPushSubscriptionCallback callback);
void getSubscription(in DOMString scope, in nsIPrincipal principal, in nsIPushSubscriptionCallback callback);
void unsubscribe(in DOMString scope, in nsIPrincipal principal, in nsIUnsubscribeResultCallback callback);

Methods

subscribe()

Creates a push subscription.

void subscribe(
  in DOMString scope,
  in nsIPrincipal principal,
  in nsIPushSubscriptionCallback callback
);

Parameters

scope
The ServiceWorkerRegistration.scope for a service worker subscription, or a unique URL (for example, chrome://my-module/push) for a system subscription.
principal
The nsIPrincipal to associate with the subscription. Privileged code should pass the system principal.
callback
The callback to call when the nsIPushSubscription is created.

Passing the system principal exempts the subscription from permission checks and background messages quotas, which are enforced for service worker subscriptions.

Example

const { classes: Cc, interfaces: Ci, utils: Cu } = Components;

const scriptSecurityManager = Cc["@mozilla.org/scriptsecuritymanager;1"]
                                .getService(Ci.nsIScriptSecurityManager);
const pushService = Cc["@mozilla.org/push/Service;1"]
                      .getService(Ci.nsIPushService);

pushService.subscribe(
  "chrome://my-module/push",
  scriptSecurityManager.getSystemPrincipal(),
  (code, subscription) => {
    if (!Components.isSuccessCode(code)) {
      Cu.reportError("Error creating subscription: " + code);
      return;
    }
    // `subscription` implements `nsIPushSubscription`.
    subscription.endpoint;
    subscription.getKey("p256dh");
    subscription.getKey("auth");
  }
);

getSubscription()

Fetches an existing subscription.

void getSubscription(
  in DOMString scope,
  in nsIPrincipal principal,
  in nsIPushSubscriptionCallback callback
);

Parameters

scope
The unique scope URL, as passed to nsIPushService.subscribe().
principal
The subscription nsIPrincipal, as passed to nsIPushService.subscribe().
callback
The callback to call with the fetched nsIPushSubscription.

Example

pushService.getSubscription(
  "chrome://my-module/push",
  scriptSecurityManager.getSystemPrincipal(),
  (code, subscription) => {
    if (!Components.isSuccessCode(code)) {
      Cu.reportError("Error fetching subscription: " + code);
      return;
    }
    // `subscription == null` if the `(scope, principal)` pair doesn't have a
    // push subscription. Otherwise, it's an instance of `nsIPushSubscription`.
  }
);

unsubscribe()

Drops an existing push subscription.

void unsubscribe(
  in DOMString scope,
  in nsIPrincipal principal,
  in nsIUnsubscribeResultCallback callback
);

Parameters

scope
The unique scope URL, as passed to nsIPushService.subscribe().
principal
The subscription nsIPrincipal, as passed to nsIPushService.subscribe().
callback
The callback to call when the nsIPushSubscription is dropped.

Example

pushService.unsubscribe(
  "chrome://my-module/push",
  scriptSecurityManager.getSystemPrincipal(),
  (code, ok) => {
    if (!Components.isSuccessCode(code)) {
      Cu.reportError("Error unsubscribing: " + code);
      return;
    }
    // `ok === true` if the subscription was removed, or `false` if the
    // `(scope, principal)` pair didn't have a subscription.
  }
);

Receiving Push Messages

Subscriptions created from privileged code use XPCOM observer notifications instead of service worker events. You can use the global nsIObserverService to listen for these notifications.

Messages sent to system subscriptions are broadcasted to all push-message observers. Your nsIObserver should ensure the data parameter matches your subscription scope. Otherwise, your code may try to handle messages meant for other subscriptions.

Topic Subject Data Description Push API Counterpart
push-message nsIPushMessage if the message has a payload; null for blank messages. Scope Fired when a push message is sent to a system subscription. ServiceWorkerGlobalScope.onpush
push-subscription-change null Scope Fired when the Push server drops a subscription, or the subscription identifier changes. ServiceWorkerGlobalScope.onpushsubscriptionchange

Please make sure you listen for push-subscription-change. If the subscription is lost, and your code isn't listening for this notification, you won't be able to receive messages until you create a new subscription.

Example

const obsService = Cc["@mozilla.org/observer-service;1"]
                     .getService(Ci.nsIObserverService);

let pushObserver = {
  scope: "chrome://my-module/push",

  observe(subject, topic, data) {
    // The scope is passed as the `data` argument for `push-message` and
    // `push-subscription-change` observers. Make sure the message is meant
    // for us.
    if (data == this.scope) {
      if (topic == "push-message") {
        this.onPushMessage(subject);
      } else if (topic == "push-subscription-change") {
        this.onPushSubscriptionChange();
      }
    }
  },

  onPushMessage(maybeMessage) {
    if (!maybeMesssage) {
      // The subject will be `null` for messages without data.
      return;
    }
    let message = maybeMesssage.QueryInterface(Ci.nsIPushMessage);
    message.text(); // Returns the message contents as a UTF-8 string.
    message.json(); // Parses the message as JSON.
    message.binary(); // Returns a byte array.
  },

  onPushSubscriptionChange() {
    // Re-subscribe if the subscription was dropped.
    pushService.subscribe(
      this.scope,
      scriptSecurityManager.getSystemPrincipal(),
      (code, subscription) => {
        // ...
    });
  }
};

obsService.addObserver(pushObserver, "push-message", false);
obsService.addObserver(pushObserver, "push-subscription-change", false);

See also