W3C Push API Crash Course

W3C’s Push API is exciting. Almost as exciting as all the possibilities that arise from having a persistent presence in your users’ browser. At Zumba, we already have ideas for it, and I was in charge of doing the gritty work of getting notifications to show up in the browser, but also developing a way to manage who gets those notifications. I had a lot of questions along the way that I will lay out and give you straight answers. Let’s get pushing already!

The ServiceWorker

The ServiceWorker is where the Push API lives. A ServiceWorker is a JavaScript file that defines activities that are allowed to run continuously, well after the life-cycle of a web-page. If you have heard of WebWorkers, ServiceWorkers are quite similar, but they will continue to work in the background even after a user has closed the web-page, which is key to being available to show notifications.

ServiceWorker Registration

Before we get started with registering, you need to set up a Google Application that can be used with Google Cloud Messaging to actually send the notifications; it is free for development and takes about 2-3 minutes.

Google Application Setup

  1. Go to Google Developer Console and create a new application.
  2. Note your new applications Project Number: Google API Project Number
  3. Go to the new application and under APIs & auth click APIs and look for “messaging” and enable:
    • Google Cloud Messaging for Chrome
    • Google Cloud Messaging for Android
  4. Under the same sidebar menu, go to Credentials and generate new Public API access keys for server. Keep them handy for a little later on.

manifest.json

Google Chrome relies on a simple JSON file to detect your websites Google Cloud app. It is placed in the root of your website and it goes a little something like this:

Replace application_project_number with the project number of your Google App from the steps above. Moving on!


ServiceWorker Life-Cycle

ServiceWorkers have a registration process that goes through the following steps:

  • install: currently being installed
  • waiting: waiting on registration
  • active: registered and running

Scope

ServiceWorkers also have a scope which is set to the directory under which it can be found. For example, if your service worker script is located at /static/js/muh/scripts/ServiceWorker.js Then its scope will be: /static/js/muh/scripts/. This will not work; your users will not be doing their browsing in your static assets, so placing this script further up the directory tree is highly recommended. Service Workers also will not install if not served over HTTPS.

Registering

Now that you know what to expect with setting up a suitable environment for your service worker let’s get it installed.

A good installation script should also consider that their might be a service worker already in place and running. To check for that let’s do the following:

Now that we have the installation status: we know if registration of the service worker is necessary. Assuming registration is necessary:

ServiceWorkerRegistrations are important to push because they hold the key to our next step which is the PushManager. Once we have a reliable way to either register a ServiceWorker or retrieve an existing ServiceWorker’s registration, we can continue to…

The PushManager

The PushManager is a creatively named API that manages our push subscriptions. The entry point for it can be found on that ServiceWorkerRegistration I mentioned above. You should take the same approach with this as with service worker registrations. The functions you should know about are: getSubscription and subscribe.

As you can see here, we check for an existing push subscription, then if one is not found we attempt to get permission for one. This attempt is when the user is prompted to approve notifications.

Putting It Together

So, putting the two together, you probably end up with something like this:

This will auto-register a service-worker and will subscribe your website to push notifications and send the push subscription to your server.

PushSubscription

Providing that everything went well, and the user agreed to be notified, you will be given a PushSubscription object that will contain details about how to execute a push notification. (PushSubscription) This object contains an endpoint attribute which is the entry point for push notifications. (The Push API is still in flux, but I would recommend keeping the endpoint; Google is the only one running a W3C compliant push server but I am sure there will be more to come and this will be what distinguishes them.)

What distinguishes this user is the subscriptionId, which is like a device ID and will be how you reach this particular user with your push notifications.

Using the PushSubscription

Once you have the subscriptionId, you can send it to Google Cloud Messaging endpoint like so:

Put your Google Cloud project API key next to key= and put the users subscriptionId in registration_ids and this will send notifications but we need to tell the service worker how to receive them, and what to do with them.

Receiving Notifications with ServiceWorker

ServiceWorkers run in a completely different global context than a DOMWindow. The global object in a ServiceWorker is self, and the event to look out for is onpush. A very simple notifier service worker will look something like this:

This will extract that push data out of the event and show it as a notification.

The Bad News

W3C’s Push API is very new. Google Chrome is the only browser to begin working on implementation and it still isn’t finished. With that in mind, the Chromium development team has intentionally blocked arbitrary data from being sent through the Push API for now (chromium issue #449184). The reason stated is that as of right now, the API does not mandate encryption of incoming push messages. Without mandatory encryption, anyone can easily use a Man-in-the-middle attack to put bad data into push messages.

As stated in the linked chromium issue, push messages are really just fancy pings at this point. But those pings can be used to tell clients to fetch the latest data from your servers.


I will continue to follow the Push API and keep this article updated if any important developments occur. Drop me a line on twitter if you have any questions. Happy pushing!

Other Helpful Resources:


« Relational Database Design |  »

Comments

comments powered by Disqus