|
|
Line 1: |
Line 1: |
| Push notifications are a way for websites to send small messages to users when
| | Updated version at [[WebAPI/PushAPI]] |
| 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 <tt>navigator.notification</tt> 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;
| |
| | |
| <tt>requestRemotePermission()</tt> asks the user if they'd like to allow this site
| |
| to send notifications. When the success callback runs, <tt>request.result</tt> 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
| |
| <tt>requestRemotePermission()</tt> again, we can return the push URL without
| |
| bothering the user.
| |
| | |
| <tt>checkRemotePermission()</tt> 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 <tt>checkRemotePermission</tt> 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 <tt>replaceId</tt> 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.
| |
| | |
| = Feedback =
| |
| | |
| (No feedback mechanism is listed, so I'm putting it here; feel free to point me elsewhere :-)
| |
| <i>
| |
| | |
| <blockquote>
| |
| * Is the "body" plain text or HTML, or something else?
| |
| * Are clients forced to support actionURL (the notification system currently used in Ubuntu, for example, specifically removed support for clicking on a notification to take an action)?
| |
| * What are the rules, if any, about cookie-sending and Referer and Origin when the actionURL is accessed?
| |
| * Are there maximum lengths for any of the fields?
| |
| * What about icons of multiple sizes?
| |
| * Does iconURL lead to a privacy issue because the site can see if the user has read the notification? Can we allow, or require, inline icons?
| |
| * Are there rules or guidelines to avoid accidentally clashing replaceIDs, such as a "org.mozilla.notification-somerandomstring" convention?
| |
| * How can we mitigate the problem of one (authorized) site spoofing notifications that look like those from another site? Will the in-browser UI show the origin of the notification?
| |
| | |
| -- Gerv
| |
| </blockquote>
| |
| | |
| <blockquote>
| |
| Responses
| |
| * plain text
| |
| * We can definitely make it optional. I wonder if we should return a set of capabilities along with the URL to let the page know what parts are supported. This will work well when we expand the API to support things like setting "badge numbers" for apps etc.
| |
| * Setting the Referer to the origin of the site making the request seems like a good idea. Cookies and Origin would be sent as normal (which means that no Origin header is sent).
| |
| * Yes, we should impose some limit to be determined.
| |
| * Good question, I don't have a good answer.
| |
| * Inline icons would be too expensive to push for each notification. One option would be to require that icons are provided when the notification URL is originally requested. That way we could handle multiple sizes too.
| |
| * replaceIDs are scoped to within the origin, so sites can use whatever scheme they want.
| |
| * How do we handle this for the Notification API?
| |
| -- Sicking
| |
| </blockquote>
| |
| | |
| | |
| <blockquote>
| |
| * How does this handle a user who uses two different Web browsers? (e.g. IE at work and Firefox at home)
| |
| -- Hixie
| |
| </blockquote>
| |
| | |
| <blockquote>
| |
| Responses
| |
| * UAs should allow setting custom notification services. For example, in Firefox we would by default deliver messages through a Mozilla server, but allow users to choose other notification delivery providers. By choosing the same delivery provider in all browsers, it should be quite possible to make it work. The main problem would be making sure that the delivery provider knows your identity in all browsers, possibly by making you log in when you first set up the service.
| |
| -- Sicking
| |
| </blockquote>
| |
| | |
| | |
| <blockquote>
| |
| * How is the privacy impact of following the user (IP addresses, usage times) reduced to the absolute minimum possible?
| |
| * Why the middle man Mozilla? Decentralization is a core principle of the Internet.
| |
| -- Ben Bucksch
| |
| </blockquote>
| |
| | |
| <blockquote>
| |
| * We "only" leak that information to the delivery service. I can't think of a way to allow the delivery service to send messages to the client without knowing the clients address. Suggestions welcome.
| |
| * Nothing in the API or protocol forces this to go through Mozilla. We can easily let the user choose any delivery service. However we need to go through a delivery service rather than having each website send messages to the device directly in order to reduce IP address/phone number/usage time leakage.
| |
| -- Sicking
| |
| | |
| * We don't "need" to go through Mozilla or anybody. When I browse the web, I already contact servers directly and they already see my IP address. Moreover, the server sees every webpage I visit and when. I can only prevent that by using a proxy all the time, but then the proxy can monitor me, and I'd rather avoid that. We have a similar tradeoff here. I argue the sensibility of my Internet usage times is less sensitive than the information which concrete webpages I visit, and the latter already leaks.
| |
| * This is changing core principles ("decentralization") of the Internet, and I don't see a good justification for that. You are basically forcing a proxy on everybody. If we wanted that, we'd all use HTTP proxies already.
| |
| | |
| -- Ben Bucksch
| |
| </blockquote>
| |
| | |
| | |
| <blockquote>
| |
| * From a security viewpoint, the obvious choice to prevent spoofing is digital signatures. However, client-side (in this case the notifying website) developers who aren't familiar with PKI often find it too complex, resulting in a lack of third-party API implementations (see OAuth!). If Mozilla intends to develop, distribute and support the client API themselves, this is less of an issue. If this is not the case, OAuth 2.0 has some non-PKI options. Implementing all of the OAuth 2.0 protocol may be too heavyweight, but it would at least offer some inspiration.
| |
| * The designers should also consider verifying the integrity and source of notifications received by the browser.
| |
| | |
| -- Ryan Schipper
| |
| </blockquote>
| |
| | |
| </i>
| |