Bug 1150683 - Add xpcshell test hooks to PushService.jsm. r=dougt

---
 dom/push/PushService.jsm | 156 ++++++++++++++++++++++++++++++++---------------
 dom/push/moz.build       |   2 +-
 2 files changed, 108 insertions(+), 50 deletions(-)
This commit is contained in:
Kit Cambridge 2015-04-21 20:10:50 +02:00
Родитель 1e06bb992c
Коммит c32f94ac3c
2 изменённых файлов: 108 добавлений и 50 удалений

Просмотреть файл

@ -33,9 +33,11 @@ XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
XPCOMUtils.defineLazyModuleGetter(this, "AlarmService",
"resource://gre/modules/AlarmService.jsm");
#ifdef MOZ_B2G
XPCOMUtils.defineLazyServiceGetter(this, "gPowerManagerService",
"@mozilla.org/power/powermanagerservice;1",
"nsIPowerManagerService");
#endif
var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
@ -217,8 +219,8 @@ this.PushDB.prototype = {
function txnCb(aTxn, aStore) {
aStore.clear();
},
aSuccessCb(),
aErrorCb()
aSuccessCb,
aErrorCb
);
}
};
@ -495,19 +497,42 @@ this.PushService = {
this._ws.sendMsg(msg);
},
init: function() {
init: function(options = {}) {
debug("init()");
if (this._started) {
return;
}
// Override the backing store for testing.
this._db = options.db;
if (!this._db) {
this._db = new PushDB();
}
// Override the default WebSocket factory function. The returned object
// must be null or satisfy the nsIWebSocketChannel interface. Used by
// the tests to provide a mock WebSocket implementation.
if (options.makeWebSocket) {
this._makeWebSocket = options.makeWebSocket;
}
// Override the default UDP socket factory function. The returned object
// must be null or satisfy the nsIUDPSocket interface. Used by the
// UDP tests.
if (options.makeUDPSocket) {
this._makeUDPSocket = options.makeUDPSocket;
}
this._networkInfo = options.networkInfo;
if (!this._networkInfo) {
this._networkInfo = PushNetworkInfo;
}
var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIFrameScriptLoader);
globalMM.loadFrameScript("chrome://global/content/PushServiceChildPreload.js", true);
this._db = new PushDB();
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
.getService(Ci.nsIMessageBroadcaster);
@ -544,7 +569,8 @@ this.PushService = {
// On B2G both events fire, one after the other, when the network goes
// online, so we explicitly check for the presence of NetworkManager and
// don't add an observer for offline-status-changed on B2G.
Services.obs.addObserver(this, this._getNetworkStateChangeEventName(), false);
this._networkStateChangeEventName = this._networkInfo.getNetworkStateChangeEventName();
Services.obs.addObserver(this, this._networkStateChangeEventName, false);
// This is only used for testing. Different tests require connecting to
// slightly different URLs.
@ -583,7 +609,7 @@ this.PushService = {
prefs.ignore("debug", this);
prefs.ignore("connection.enabled", this);
prefs.ignore("serverURL", this);
Services.obs.removeObserver(this, this._getNetworkStateChangeEventName());
Services.obs.removeObserver(this, this._networkStateChangeEventName);
Services.obs.removeObserver(this, "webapps-clear-data", false);
Services.obs.removeObserver(this, "xpcom-shutdown", false);
@ -697,7 +723,7 @@ this.PushService = {
}
// Save actual state of the network
let ns = this._getNetworkInformation();
let ns = this._networkInfo.getNetworkInformation();
if (ns.ip) {
// mobile
@ -815,27 +841,7 @@ this.PushService = {
}
},
_beginWSSetup: function() {
debug("beginWSSetup()");
if (this._currentState != STATE_SHUT_DOWN) {
debug("_beginWSSetup: Not in shutdown state! Current state " +
this._currentState);
return;
}
if (!prefs.get("connection.enabled")) {
debug("_beginWSSetup: connection.enabled is not set to true. Aborting.");
return;
}
// Stop any pending reconnects scheduled for the near future.
this._stopAlarm();
if (Services.io.offline) {
debug("Network is offline.");
return;
}
_getServerURI: function() {
let serverURL = prefs.get("serverURL");
if (!serverURL) {
debug("No dom.push.serverURL found!");
@ -850,26 +856,63 @@ this.PushService = {
serverURL + ")");
return;
}
return uri;
},
_makeWebSocket: function(uri) {
if (!prefs.get("connection.enabled")) {
debug("_makeWebSocket: connection.enabled is not set to true. Aborting.");
return null;
}
if (Services.io.offline) {
debug("Network is offline.");
return null;
}
let socket;
if (uri.scheme === "wss") {
this._ws = Cc["@mozilla.org/network/protocol;1?name=wss"]
.createInstance(Ci.nsIWebSocketChannel);
socket = Cc["@mozilla.org/network/protocol;1?name=wss"]
.createInstance(Ci.nsIWebSocketChannel);
this._ws.initLoadInfo(null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_WEBSOCKET);
socket.initLoadInfo(null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_WEBSOCKET);
}
else if (uri.scheme === "ws") {
debug("Push over an insecure connection (ws://) is not allowed!");
return;
return null;
}
else {
debug("Unsupported websocket scheme " + uri.scheme);
return null;
}
return socket;
},
_beginWSSetup: function() {
debug("beginWSSetup()");
if (this._currentState != STATE_SHUT_DOWN) {
debug("_beginWSSetup: Not in shutdown state! Current state " +
this._currentState);
return;
}
// Stop any pending reconnects scheduled for the near future.
this._stopAlarm();
let uri = this._getServerURI();
if (!uri) {
return;
}
let socket = this._makeWebSocket(uri);
if (!socket) {
return;
}
this._ws = socket.QueryInterface(Ci.nsIWebSocketChannel);
debug("serverURL: " + uri.spec);
this._wsListener = new PushWebSocketListener(this);
this._ws.protocol = "push-notification";
@ -877,7 +920,7 @@ this.PushService = {
try {
// Grab a wakelock before we open the socket to ensure we don't go to sleep
// before connection the is opened.
this._ws.asyncOpen(uri, serverURL, this._wsListener, null);
this._ws.asyncOpen(uri, uri.spec, this._wsListener, null);
this._acquireWakeLock();
this._currentState = STATE_WAITING_FOR_WS_START;
} catch(e) {
@ -1012,6 +1055,8 @@ this.PushService = {
},
_acquireWakeLock: function() {
#ifdef MOZ_B2G
// Disable the wake lock on non-B2G platforms to work around bug 1154492.
if (!this._socketWakeLock) {
debug("Acquiring Socket Wakelock");
this._socketWakeLock = gPowerManagerService.newWakeLock("cpu");
@ -1029,10 +1074,12 @@ this.PushService = {
// timers can be a little off and we don't want to go
// to sleep just as the socket connected.
this._requestTimeout + 1000,
Ci.nsITimer.ONE_SHOT);
Ci.nsITimer.TYPE_ONE_SHOT);
#endif
},
_releaseWakeLock: function() {
#ifdef MOZ_B2G
debug("Releasing Socket WakeLock");
if (this._socketWakeLockTimer) {
this._socketWakeLockTimer.cancel();
@ -1041,6 +1088,7 @@ this.PushService = {
this._socketWakeLock.unlock();
this._socketWakeLock = null;
}
#endif
},
/**
@ -1652,7 +1700,7 @@ this.PushService = {
this._currentState = STATE_WAITING_FOR_HELLO;
}
this._getNetworkState((networkState) => {
this._networkInfo.getNetworkState((networkState) => {
if (networkState.ip) {
// Opening an available UDP port.
this._listenForUDPWakeup();
@ -1790,10 +1838,15 @@ this.PushService = {
for (let channelID in this._pendingRequests) {
let request = this._pendingRequests[channelID];
delete this._pendingRequests[channelID];
request.deferred.reject({status: 0, error: "CancelledError"});
request.deferred.reject({status: 0, error: "AbortError"});
}
},
_makeUDPSocket: function() {
return Cc["@mozilla.org/network/udp-socket;1"]
.createInstance(Ci.nsIUDPSocket);
},
/**
* This method should be called only if the device is on a mobile network!
*/
@ -1810,9 +1863,12 @@ this.PushService = {
return;
}
this._udpServer = Cc["@mozilla.org/network/udp-socket;1"]
.createInstance(Ci.nsIUDPSocket);
this._udpServer.init(-1, false);
let socket = this._makeUDPSocket();
if (!socket) {
return;
}
this._udpServer = socket.QueryInterface(Ci.nsIUDPSocket);
this._udpServer.init(-1, false, Services.scriptSecurityManager.getSystemPrincipal());
this._udpServer.asyncListen(this);
debug("listenForUDPWakeup listening on " + this._udpServer.port);
@ -1838,12 +1894,14 @@ this.PushService = {
debug("UDP Server socket was shutdown. Status: " + aStatus);
this._udpServer = undefined;
this._beginWSSetup();
},
}
};
let PushNetworkInfo = {
/**
* Returns information about MCC-MNC and the IP of the current connection.
*/
_getNetworkInformation: function() {
getNetworkInformation: function() {
debug("getNetworkInformation()");
try {
@ -1894,14 +1952,14 @@ this.PushService = {
* woken up by UDP (which currently just means having an mcc and mnc along
* with an IP, and optionally a netid).
*/
_getNetworkState: function(callback) {
getNetworkState: function(callback) {
debug("getNetworkState()");
if (typeof callback !== 'function') {
throw new Error("No callback method. Aborting push agent !");
}
var networkInfo = this._getNetworkInformation();
var networkInfo = this.getNetworkInformation();
if (networkInfo.ip) {
this._getMobileNetworkId(networkInfo, function(netid) {
@ -1919,7 +1977,7 @@ this.PushService = {
},
// utility function used to add/remove observers in init() and shutdown()
_getNetworkStateChangeEventName: function() {
getNetworkStateChangeEventName: function() {
try {
Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
return "network-active-changed";

Просмотреть файл

@ -9,7 +9,7 @@ EXTRA_COMPONENTS += [
'PushNotificationService.js',
]
EXTRA_JS_MODULES += [
EXTRA_PP_JS_MODULES += [
'PushService.jsm',
]