CloudServices/Notifications/Push/API

< CloudServices‎ | Notifications‎ | Push
Revision as of 23:30, 30 January 2012 by Jbalogh (talk | contribs) (Created page with "Push notifications are a way for websites to send small messages to users when the user is not on the site. iOS and Android devices already support their own push notification se...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Push notifications are a way for websites to send small messages to users when the user is not on the site. iOS and Android devices already support their own push notification services, but we want to make notifications available to the whole web.

Client API

The API will be an object at navigator.notification with this interface:

interface notification {
    DOMRequest requestRemotePermission();
    DOMRequest checkRemotePermission();
}

where DOMRequest is an interface that looks like this:

interface DOMRequest {
    readonly attribute any? result;
    readonly attribute DOMError error;
    readonly attribute DOMString readyState;
    attribute Function onsuccess;
    attribute Function onerror;
};

requestRemotePermission() asks the user if they'd like to allow this site to send notifications. When the success callback runs, request.result will be a URL where the site can send messages to this user. It's up to the site to send the URL to the backend for storage.

If the site has been granted permission already and is calling requestRemotePermission() again, we can return the push URL without bothering the user.

checkRemotePermission() lets the site ask Firefox if the site has a push URL without bothering the user. The success callback would be the same URL that requestRemotePermission received, but if the user has never allowed notifications for the site the error callback would run.

The error interface:

interface notificationError : nsISupports
{
  const unsigned short DENIED = 1;
  const unsigned short PERMISSION_DENIED = 2;
  const unsigned short NETWORK_ERROR = 3;
  readonly attribute short code;
};

Simple usage would look like this:

var notification = (navigator.notification ||
                    navigator.mozNotification ||
                    navigator.webkitNotification);
if (notification) {
  // Ask the user to allow notifications
  var request = notification.requestRemotePermission();
  request.onsuccess = function() {
    var url = request.result;
    console.log('New push URL: ' + url);
    // We got a new push URL, store it on the server.
    jQuery.post('/push-urls/', {url: url});
  };
}

More careful usage would use checkRemotePermission first:

var notification = (navigator.notification ||
                    navigator.mozNotification ||
                    navigator.webkitNotification);
if (notification) {
  // Check if we've asked for permission before without bothering the user.
  var check = notification.checkRemotePermission();
  check.onsuccess = function() {
    var url = request.result;
    console.log('Already have a URL: ' + url);
  };
  check.onerror = function() {
    // Request permission if we haven't been denied before.
    if (check.error.code != DENIED) {
      var request = notification.requestRemotePermission();
      request.onsuccess = function(url) {
        console.log('New push URL: ' + url);
        // We got a new push URL, store it on the server.
        jQuery.post('/push-urls/', {url: url});
      };
    }
  }
}

Server API

On the server side we're looking at an HTTP interface that accepts POSTs with these attributes:

  • iconUrl: URL of the icon to be shown with this notification.
  • title: Primary text of the notification.
  • body: Secondary text of the notification.
  • actionUrl: URL to be opened if the user clicks on the notification.
  • replaceId: A string which identifies a group of like messages. If the user is offline, only the last message with the same replaceId will be sent when the user comes back online.

The format of the payload is still TBD; it's a toss-up between JSON blobs and form-urlencoded parameters.

HTTP Status Codes:

  • 200: Notification accepted for delivery
  • 404: We don't have that URL in our database
  • 410: The user isn't receiving these notifications, e.g. access was revoked

To support bulk sends, we may be able to use SPDY to get longer-lived connections sending a bunch of requests while still keeping the same HTTP interface.