mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 04:27:37 +00:00
155 lines
5.2 KiB
JavaScript
155 lines
5.2 KiB
JavaScript
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||
|
|
||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||
|
|
||
|
this.EXPORTED_SYMBOLS = ["MozLoopPushHandler"];
|
||
|
|
||
|
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||
|
"resource://gre/modules/devtools/Console.jsm");
|
||
|
|
||
|
/**
|
||
|
* We don't have push notifications on desktop currently, so this is a
|
||
|
* workaround to get them going for us.
|
||
|
*
|
||
|
* XXX Handle auto-reconnections if connection fails for whatever reason
|
||
|
* (bug 1013248).
|
||
|
*/
|
||
|
let MozLoopPushHandler = {
|
||
|
// This is the uri of the push server.
|
||
|
pushServerUri: Services.prefs.getCharPref("services.push.serverURL"),
|
||
|
// This is the channel id we're using for notifications
|
||
|
channelID: "8b1081ce-9b35-42b5-b8f5-3ff8cb813a50",
|
||
|
// Stores the push url if we're registered and we have one.
|
||
|
pushUrl: undefined,
|
||
|
|
||
|
/**
|
||
|
* Starts a connection to the push socket server. On
|
||
|
* connection, it will automatically say hello and register the channel
|
||
|
* id with the server.
|
||
|
*
|
||
|
* Register callback parameters:
|
||
|
* - {String|null} err: Encountered error, if any
|
||
|
* - {String} url: The push url obtained from the server
|
||
|
*
|
||
|
* Callback parameters:
|
||
|
* - {String} version The version string received from the push server for
|
||
|
* the notification.
|
||
|
*
|
||
|
* @param {Function} registerCallback Callback to be called once we are
|
||
|
* registered.
|
||
|
* @param {Function} notificationCallback Callback to be called when a
|
||
|
* push notification is received (may be called multiple
|
||
|
* times).
|
||
|
* @param {Object} mockPushHandler Optional, test-only object, to allow
|
||
|
* the websocket to be mocked for tests.
|
||
|
*/
|
||
|
initialize: function(registerCallback, notificationCallback, mockPushHandler) {
|
||
|
if (Services.io.offline) {
|
||
|
registerCallback("offline");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this._registerCallback = registerCallback;
|
||
|
this._notificationCallback = notificationCallback;
|
||
|
|
||
|
if (mockPushHandler) {
|
||
|
// For tests, use the mock instance.
|
||
|
this._websocket = mockPushHandler;
|
||
|
} else {
|
||
|
this._websocket = Cc["@mozilla.org/network/protocol;1?name=wss"]
|
||
|
.createInstance(Ci.nsIWebSocketChannel);
|
||
|
}
|
||
|
this._websocket.protocol = "push-notification";
|
||
|
|
||
|
let pushURI = Services.io.newURI(this.pushServerUri, null, null);
|
||
|
this._websocket.asyncOpen(pushURI, this.pushServerUri, this, null);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Listener method, handles the start of the websocket stream.
|
||
|
* Sends a hello message to the server.
|
||
|
*
|
||
|
* @param {nsISupports} aContext Not used
|
||
|
*/
|
||
|
onStart: function() {
|
||
|
let helloMsg = { messageType: "hello", uaid: "", channelIDs: [] };
|
||
|
this._websocket.sendMsg(JSON.stringify(helloMsg));
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Listener method, called when the websocket is closed.
|
||
|
*
|
||
|
* @param {nsISupports} aContext Not used
|
||
|
* @param {nsresult} aStatusCode Reason for stopping (NS_OK = successful)
|
||
|
*/
|
||
|
onStop: function(aContext, aStatusCode) {
|
||
|
// XXX We really should be handling auto-reconnect here, this will be
|
||
|
// implemented in bug 994151. For now, just log a warning, so that a
|
||
|
// developer can find out it has happened and not get too confused.
|
||
|
Cu.reportError("Loop Push server web socket closed! Code: " + aStatusCode);
|
||
|
this.pushUrl = undefined;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Listener method, called when the websocket is closed by the server.
|
||
|
* If there are errors, onStop may be called without ever calling this
|
||
|
* method.
|
||
|
*
|
||
|
* @param {nsISupports} aContext Not used
|
||
|
* @param {integer} aCode the websocket closing handshake close code
|
||
|
* @param {String} aReason the websocket closing handshake close reason
|
||
|
*/
|
||
|
onServerClose: function(aContext, aCode) {
|
||
|
// XXX We really should be handling auto-reconnect here, this will be
|
||
|
// implemented in bug 994151. For now, just log a warning, so that a
|
||
|
// developer can find out it has happened and not get too confused.
|
||
|
Cu.reportError("Loop Push server web socket closed (server)! Code: " + aCode);
|
||
|
this.pushUrl = undefined;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Listener method, called when the websocket receives a message.
|
||
|
*
|
||
|
* @param {nsISupports} aContext Not used
|
||
|
* @param {String} aMsg The message data
|
||
|
*/
|
||
|
onMessageAvailable: function(aContext, aMsg) {
|
||
|
let msg = JSON.parse(aMsg);
|
||
|
|
||
|
switch(msg.messageType) {
|
||
|
case "hello":
|
||
|
this._registerChannel();
|
||
|
break;
|
||
|
case "register":
|
||
|
this.pushUrl = msg.pushEndpoint;
|
||
|
this._registerCallback(null, this.pushUrl);
|
||
|
break;
|
||
|
case "notification":
|
||
|
msg.updates.forEach(function(update) {
|
||
|
if (update.channelID === this.channelID) {
|
||
|
this._notificationCallback(update.version);
|
||
|
}
|
||
|
}.bind(this));
|
||
|
break;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Handles registering a service
|
||
|
*/
|
||
|
_registerChannel: function() {
|
||
|
this._websocket.sendMsg(JSON.stringify({
|
||
|
messageType: "register",
|
||
|
channelID: this.channelID
|
||
|
}));
|
||
|
}
|
||
|
};
|
||
|
|