mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Back out changeset d4f14f6dd401 (bug 863732) on a CLOSED TREE for being half of the problem causing all debug builds to leak as a result of merging mozilla-central and mozilla-inbound.
This commit is contained in:
parent
c3ad278e44
commit
5304e2aebf
@ -394,13 +394,12 @@ pref("services.push.enabled", true);
|
||||
// serverURL to be assigned by services team
|
||||
pref("services.push.serverURL", "");
|
||||
pref("services.push.userAgentID", "");
|
||||
// Exponential back-off start is 5 seconds like in HTTP/1.1.
|
||||
// Maximum back-off is pingInterval.
|
||||
// exponential back-off start is 5 seconds like in HTTP/1.1
|
||||
pref("services.push.retryBaseInterval", 5000);
|
||||
// Interval at which to ping PushServer to check connection status. In
|
||||
// milliseconds. If no reply is received within requestTimeout, the connection
|
||||
// is considered closed.
|
||||
pref("services.push.pingInterval", 1800000); // 30 minutes
|
||||
// WebSocket level ping transmit interval in seconds.
|
||||
pref("services.push.websocketPingInterval", 55);
|
||||
// exponential back-off end is 20 minutes
|
||||
pref("services.push.maxRetryInterval", 1200000);
|
||||
// How long before a DOMRequest errors as timeout
|
||||
pref("services.push.requestTimeout", 10000);
|
||||
// enable udp wakeup support
|
||||
|
@ -19,7 +19,6 @@ Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
Cu.import("resource://gre/modules/AlarmService.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["PushService"];
|
||||
|
||||
@ -88,8 +87,7 @@ this.PushDB.prototype = {
|
||||
function txnCb(aTxn, aStore) {
|
||||
debug("Going to put " + aChannelRecord.channelID);
|
||||
aStore.put(aChannelRecord).onsuccess = function setTxnResult(aEvent) {
|
||||
debug("Request successful. Updated record ID: " +
|
||||
aEvent.target.result);
|
||||
debug("Request successful. Updated record ID: " + aEvent.target.result);
|
||||
};
|
||||
},
|
||||
aSuccessCb,
|
||||
@ -269,12 +267,12 @@ this.PushWebSocketListener.prototype = {
|
||||
// websocket states
|
||||
// websocket is off
|
||||
const STATE_SHUT_DOWN = 0;
|
||||
// Websocket has been opened on client side, waiting for successful open.
|
||||
// websocket has been opened on client side, waiting for successful open
|
||||
// (_wsOnStart)
|
||||
const STATE_WAITING_FOR_WS_START = 1;
|
||||
// Websocket opened, hello sent, waiting for server reply (_handleHelloReply).
|
||||
// websocket opened, hello sent, waiting for server reply (_handleHelloReply)
|
||||
const STATE_WAITING_FOR_HELLO = 2;
|
||||
// Websocket operational, handshake completed, begin protocol messaging.
|
||||
// websocket operational, handshake completed, begin protocol messaging
|
||||
const STATE_READY = 3;
|
||||
|
||||
/**
|
||||
@ -335,6 +333,9 @@ this.PushService = {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (aSubject == this._retryTimeoutTimer) {
|
||||
this._beginWSSetup();
|
||||
}
|
||||
break;
|
||||
case "webapps-uninstall":
|
||||
debug("webapps-uninstall");
|
||||
@ -350,8 +351,7 @@ this.PushService = {
|
||||
debug("Got " + records.length);
|
||||
for (var i = 0; i < records.length; i++) {
|
||||
this._db.delete(records[i].channelID, null, function() {
|
||||
debug("app uninstall: " + app.manifestURL +
|
||||
" Could not delete entry " + records[i].channelID);
|
||||
debug("app uninstall: " + app.manifestURL + " Could not delete entry " + records[i].channelID);
|
||||
});
|
||||
// courtesy, but don't establish a connection
|
||||
// just for it
|
||||
@ -389,6 +389,25 @@ this.PushService = {
|
||||
_currentState: STATE_SHUT_DOWN,
|
||||
_requestTimeout: 0,
|
||||
_requestTimeoutTimer: null,
|
||||
|
||||
/**
|
||||
* How retries work: The goal is to ensure websocket is always up on
|
||||
* networks not supporting UDP. So the websocket should only be shutdown if
|
||||
* onServerClose indicates UDP wakeup. If WS is closed due to socket error,
|
||||
* _socketError() is called. The retry timer is started and when it times
|
||||
* out, beginWSSetup() is called again.
|
||||
*
|
||||
* On a successful connection, the timer is cancelled if it is running and
|
||||
* the values are reset to defaults.
|
||||
*
|
||||
* If we are in the middle of a timeout (i.e. waiting), but
|
||||
* a register/unregister is called, we don't want to wait around anymore.
|
||||
* _sendRequest will automatically call beginWSSetup(), which will cancel the
|
||||
* timer. In addition since the state will have changed, even if a pending
|
||||
* timer event comes in (because the timer fired the event before it was
|
||||
* cancelled), so the connection won't be reset.
|
||||
*/
|
||||
_retryTimeoutTimer: null,
|
||||
_retryFailCount: 0,
|
||||
|
||||
/**
|
||||
@ -421,8 +440,6 @@ this.PushService = {
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
}.bind(this));
|
||||
|
||||
this._alarmID = null;
|
||||
|
||||
this._requestTimeout = prefs.get("requestTimeout");
|
||||
|
||||
this._udpPort = prefs.get("udp.port");
|
||||
@ -449,16 +466,12 @@ this.PushService = {
|
||||
debug("shutdownWS()");
|
||||
this._currentState = STATE_SHUT_DOWN;
|
||||
this._willBeWokenUpByUDP = false;
|
||||
|
||||
if (this._wsListener)
|
||||
this._wsListener._pushService = null;
|
||||
try {
|
||||
this._ws.close(0, null);
|
||||
} catch (e) {}
|
||||
this._ws = null;
|
||||
|
||||
this._waitingForPong = false;
|
||||
this._stopAlarm();
|
||||
},
|
||||
|
||||
_shutdown: function() {
|
||||
@ -485,7 +498,8 @@ this.PushService = {
|
||||
// At this point, profile-change-net-teardown has already fired, so the
|
||||
// WebSocket has been closed with NS_ERROR_ABORT (if it was up) and will
|
||||
// try to reconnect. Stop the timer.
|
||||
this._stopAlarm();
|
||||
if (this._retryTimeoutTimer)
|
||||
this._retryTimeoutTimer.cancel();
|
||||
|
||||
if (this._requestTimeoutTimer)
|
||||
this._requestTimeoutTimer.cancel();
|
||||
@ -493,35 +507,31 @@ this.PushService = {
|
||||
debug("shutdown complete!");
|
||||
},
|
||||
|
||||
/**
|
||||
* How retries work: The goal is to ensure websocket is always up on
|
||||
* networks not supporting UDP. So the websocket should only be shutdown if
|
||||
* onServerClose indicates UDP wakeup. If WS is closed due to socket error,
|
||||
* _reconnectAfterBackoff() is called. The retry alarm is started and when
|
||||
* it times out, beginWSSetup() is called again.
|
||||
*
|
||||
* On a successful connection, the alarm is cancelled in
|
||||
* wsOnMessageAvailable() when the ping alarm is started.
|
||||
*
|
||||
* If we are in the middle of a timeout (i.e. waiting), but
|
||||
* a register/unregister is called, we don't want to wait around anymore.
|
||||
* _sendRequest will automatically call beginWSSetup(), which will cancel the
|
||||
* timer. In addition since the state will have changed, even if a pending
|
||||
* timer event comes in (because the timer fired the event before it was
|
||||
* cancelled), so the connection won't be reset.
|
||||
*/
|
||||
_reconnectAfterBackoff: function() {
|
||||
debug("reconnectAfterBackoff()");
|
||||
// aStatusCode is an NS error from Components.results
|
||||
_socketError: function(aStatusCode) {
|
||||
debug("socketError()");
|
||||
|
||||
// Calculate new timeout, but cap it to pingInterval.
|
||||
// Calculate new timeout, but cap it to
|
||||
var retryTimeout = prefs.get("retryBaseInterval") *
|
||||
Math.pow(2, this._retryFailCount);
|
||||
retryTimeout = Math.min(retryTimeout, prefs.get("pingInterval"));
|
||||
|
||||
// It is easier to express the max interval as a pref in milliseconds,
|
||||
// rather than have it as a number and make people do the calculation of
|
||||
// retryBaseInterval * 2^maxRetryFailCount.
|
||||
retryTimeout = Math.min(retryTimeout, prefs.get("maxRetryInterval"));
|
||||
|
||||
this._retryFailCount++;
|
||||
|
||||
debug("Retry in " + retryTimeout + " Try number " + this._retryFailCount);
|
||||
this._setAlarm(retryTimeout);
|
||||
|
||||
if (!this._retryTimeoutTimer) {
|
||||
this._retryTimeoutTimer = Cc["@mozilla.org/timer;1"]
|
||||
.createInstance(Ci.nsITimer);
|
||||
}
|
||||
|
||||
this._retryTimeoutTimer.init(this,
|
||||
retryTimeout,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
_beginWSSetup: function() {
|
||||
@ -532,9 +542,6 @@ this.PushService = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop any pending reconnects scheduled for the near future.
|
||||
this._stopAlarm();
|
||||
|
||||
var serverURL = prefs.get("serverURL");
|
||||
if (!serverURL) {
|
||||
debug("No services.push.serverURL found!");
|
||||
@ -563,101 +570,14 @@ this.PushService = {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
debug("serverURL: " + uri.spec);
|
||||
this._wsListener = new PushWebSocketListener(this);
|
||||
this._ws.protocol = "push-notification";
|
||||
this._ws.pingInterval = prefs.get("websocketPingInterval");
|
||||
this._ws.asyncOpen(uri, serverURL, this._wsListener, null);
|
||||
this._currentState = STATE_WAITING_FOR_WS_START;
|
||||
},
|
||||
|
||||
/** |delay| should be in milliseconds. */
|
||||
_setAlarm: function(delay) {
|
||||
// Stop any existing alarm.
|
||||
this._stopAlarm();
|
||||
|
||||
AlarmService.add(
|
||||
{
|
||||
date: new Date(Date.now() + delay),
|
||||
ignoreTimezone: true
|
||||
},
|
||||
this._onAlarmFired.bind(this),
|
||||
function onSuccess(alarmID) {
|
||||
this._alarmID = alarmID;
|
||||
debug("Set alarm " + delay + " in the future " + this._alarmID);
|
||||
}.bind(this)
|
||||
)
|
||||
},
|
||||
|
||||
_stopAlarm: function() {
|
||||
if (this._alarmID !== null) {
|
||||
debug("Stopped existing alarm " + this._alarmID);
|
||||
AlarmService.remove(this._alarmID);
|
||||
this._alarmID = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* There is only one alarm active at any time. This alarm has 3 intervals
|
||||
* corresponding to 3 tasks.
|
||||
*
|
||||
* 1) Reconnect on ping timeout.
|
||||
* If we haven't received any messages from the server by the time this
|
||||
* alarm fires, the connection is closed and PushService tries to
|
||||
* reconnect, repurposing the alarm for (3).
|
||||
*
|
||||
* 2) Send a ping.
|
||||
* The protocol sends a ping ({}) on the wire every pingInterval ms. Once
|
||||
* it sends the ping, the alarm goes to task (1) which is waiting for
|
||||
* a pong. If data is received after the ping is sent,
|
||||
* _wsOnMessageAvailable() will reset the ping alarm (which cancels
|
||||
* waiting for the pong). So as long as the connection is fine, pong alarm
|
||||
* never fires.
|
||||
*
|
||||
* 3) Reconnect after backoff.
|
||||
* The alarm is set by _reconnectAfterBackoff() and increases in duration
|
||||
* every time we try and fail to connect. When it triggers, websocket
|
||||
* setup begins again. On successful socket setup, the socket starts
|
||||
* receiving messages. The alarm now goes to (2) where it monitors the
|
||||
* WebSocket by sending a ping. Since incoming data is a sign of the
|
||||
* connection being up, the ping alarm is reset every time data is
|
||||
* received.
|
||||
*/
|
||||
_onAlarmFired: function() {
|
||||
// Conditions are arranged in decreasing specificity.
|
||||
// i.e. when _waitingForPong is true, other conditions are also true.
|
||||
if (this._waitingForPong) {
|
||||
debug("Did not receive pong in time. Reconnecting WebSocket.");
|
||||
this._shutdownWS();
|
||||
this._reconnectAfterBackoff();
|
||||
}
|
||||
else if (this._currentState == STATE_READY) {
|
||||
// Send a ping.
|
||||
// Bypass the queue; we don't want this to be kept pending.
|
||||
this._ws.sendMsg('{}');
|
||||
debug("Sent ping.");
|
||||
this._waitingForPong = true;
|
||||
this._setAlarm(prefs.get("requestTimeout"));
|
||||
}
|
||||
else if (this._alarmID !== null) {
|
||||
debug("reconnect alarm fired.");
|
||||
// Reconnect after back-off.
|
||||
// The check for a non-null _alarmID prevents a situation where the alarm
|
||||
// fires, but _shutdownWS() is called from another code-path (e.g.
|
||||
// network state change) and we don't want to reconnect.
|
||||
//
|
||||
// It also handles the case where _beginWSSetup() is called from another
|
||||
// code-path.
|
||||
//
|
||||
// alarmID will be non-null only when no shutdown/connect is
|
||||
// called between _reconnectAfterBackoff() setting the alarm and the
|
||||
// alarm firing.
|
||||
|
||||
// Websocket is shut down. Backoff interval expired, try to connect.
|
||||
this._beginWSSetup();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Protocol handler invoked by server message.
|
||||
*/
|
||||
@ -1208,6 +1128,9 @@ this.PushService = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._retryTimeoutTimer)
|
||||
this._retryTimeoutTimer.cancel();
|
||||
|
||||
// Since we've had a successful connection reset the retry fail count.
|
||||
this._retryFailCount = 0;
|
||||
|
||||
@ -1254,25 +1177,17 @@ this.PushService = {
|
||||
_wsOnStop: function(context, statusCode) {
|
||||
debug("wsOnStop()");
|
||||
|
||||
this._shutdownWS();
|
||||
|
||||
if (statusCode != Cr.NS_OK &&
|
||||
!(statusCode == Cr.NS_BASE_STREAM_CLOSED && this._willBeWokenUpByUDP)) {
|
||||
debug("Socket error " + statusCode);
|
||||
this._reconnectAfterBackoff();
|
||||
this._socketError(statusCode);
|
||||
}
|
||||
|
||||
this._shutdownWS();
|
||||
},
|
||||
|
||||
_wsOnMessageAvailable: function(context, message) {
|
||||
debug("wsOnMessageAvailable() " + message);
|
||||
|
||||
this._waitingForPong = false;
|
||||
|
||||
// Reset the ping timer. Note: This path is executed at every step of the
|
||||
// handshake, so this alarm does not need to be set explicitly at startup.
|
||||
this._setAlarm(prefs.get("pingInterval"));
|
||||
|
||||
var reply = undefined;
|
||||
try {
|
||||
reply = JSON.parse(message);
|
||||
@ -1314,7 +1229,7 @@ this.PushService = {
|
||||
/**
|
||||
* The websocket should never be closed. Since we don't call ws.close(),
|
||||
* _wsOnStop() receives error code NS_BASE_STREAM_CLOSED (see comment in that
|
||||
* function), which calls reconnect and re-establishes the WebSocket
|
||||
* function), which calls socketError and re-establishes the WebSocket
|
||||
* connection.
|
||||
*
|
||||
* If the server said it'll use UDP for wakeup, we set _willBeWokenUpByUDP
|
||||
@ -1378,9 +1293,9 @@ this.PushService = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Get mobile network information to decide if the client is capable of being
|
||||
* woken up by UDP (which currently just means having an mcc and mnc along
|
||||
* with an IP).
|
||||
* Get mobile network information to decide if the client is capable of being woken
|
||||
* up by UDP (which currently just means having an mcc and mnc along with an
|
||||
* IP).
|
||||
*/
|
||||
_getNetworkState: function() {
|
||||
debug("getNetworkState()");
|
||||
|
Loading…
Reference in New Issue
Block a user