Bug 1243856 - Remove alarms from the Push H2 backend. r?dragana
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -19,19 +19,16 @@ Cu.import("resource://gre/modules/Promis
const {PushServiceWebSocket} = Cu.import("resource://gre/modules/PushServiceWebSocket.jsm");
const {PushServiceHttp2} = Cu.import("resource://gre/modules/PushServiceHttp2.jsm");
const {PushCrypto} = Cu.import("resource://gre/modules/PushCrypto.jsm");
// Currently supported protocols: WebSocket.
const CONNECTION_PROTOCOLS = [PushServiceWebSocket, PushServiceHttp2];
-XPCOMUtils.defineLazyModuleGetter(this, "AlarmService",
- "resource://gre/modules/AlarmService.jsm");
-
XPCOMUtils.defineLazyServiceGetter(this, "gContentSecurityManager",
"@mozilla.org/contentsecuritymanager;1",
"nsIContentSecurityManager");
XPCOMUtils.defineLazyServiceGetter(this, "gPushNotifier",
"@mozilla.org/push/Notifier;1",
"nsIPushNotifier");
@@ -91,17 +88,16 @@ const UNINIT_EVENT = 3;
* (PushServiceWebSocket) to communicate with the server and PushDB (IndexedDB)
* for persistence.
*/
this.PushService = {
_service: null,
_state: PUSH_SERVICE_UNINIT,
_db: null,
_options: null,
- _alarmID: null,
_visibleNotifications: new Map(),
// Callback that is called after attempting to
// reduce the quota for a record. Used for testing purposes.
_updateQuotaTestCallback: null,
// When serverURI changes (this is used for testing), db is cleaned up and a
// a new db is started. This events must be sequential.
@@ -543,23 +539,21 @@ this.PushService = {
*/
_stopService: function(event) {
console.debug("stopService()");
if (this._state < PUSH_SERVICE_ACTIVATING) {
return;
}
- this.stopAlarm();
this._stopObservers();
this._service.disconnect();
this._service.uninit();
this._service = null;
- this.stopAlarm();
if (!this._db) {
return Promise.resolve();
}
if (event == UNINIT_EVENT) {
// If it is uninitialized just close db.
this._db.close();
this._db = null;
@@ -603,67 +597,16 @@ this.PushService = {
prefs.ignore("serverURL", this);
Services.obs.removeObserver(this, "xpcom-shutdown");
this._stateChangeProcessEnqueue(_ =>
this._changeServerURL("", UNINIT_EVENT));
console.debug("uninit: shutdown complete!");
},
- /** |delay| should be in milliseconds. */
- setAlarm: function(delay) {
- if (this._state <= PUSH_SERVICE_ACTIVATING) {
- return;
- }
-
- // Bug 909270: Since calls to AlarmService.add() are async, calls must be
- // 'queued' to ensure only one alarm is ever active.
- if (this._settingAlarm) {
- // onSuccess will handle the set. Overwriting the variable enforces the
- // last-writer-wins semantics.
- this._queuedAlarmDelay = delay;
- this._waitingForAlarmSet = true;
- return;
- }
-
- // Stop any existing alarm.
- this.stopAlarm();
-
- this._settingAlarm = true;
- AlarmService.add(
- {
- date: new Date(Date.now() + delay),
- ignoreTimezone: true
- },
- () => {
- if (this._state > PUSH_SERVICE_ACTIVATING) {
- this._service.onAlarmFired();
- }
- }, (alarmID) => {
- this._alarmID = alarmID;
- console.debug("setAlarm: Set alarm", delay, "in the future",
- this._alarmID);
- this._settingAlarm = false;
-
- if (this._waitingForAlarmSet) {
- this._waitingForAlarmSet = false;
- this.setAlarm(this._queuedAlarmDelay);
- }
- }
- );
- },
-
- stopAlarm: function() {
- if (this._alarmID !== null) {
- console.debug("stopAlarm: Stopped existing alarm", this._alarmID);
- AlarmService.remove(this._alarmID);
- this._alarmID = null;
- }
- },
-
/**
* Drops all active registrations and notifies the associated service
* workers. This function is called when the user switches Push servers,
* or when the server invalidates all existing registrations.
*
* We ignore expired registrations because they're already handled in other
* code paths. Registrations that expired after exceeding their quotas are
* evicted at startup, or on the next `idle-daily` event. Registrations that
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -460,17 +460,17 @@ this.PushServiceHttp2 = {
result.p256dhPublicKey = publicKey;
result.p256dhPrivateKey = privateKey;
result.authenticationSecret = PushCrypto.generateAuthenticationSecret();
this._conns[result.subscriptionUri] = {
channel: null,
listener: null,
countUnableToConnect: 0,
lastStartListening: 0,
- waitingForAlarm: false
+ retryTimerID: 0,
};
this._listenForMsgs(result.subscriptionUri);
return result;
})
);
},
_subscribeResourceInternal: function(aSubInfo) {
@@ -580,38 +580,30 @@ this.PushServiceHttp2 = {
if (this._conns[aSubscriptionUri].countUnableToConnect >= maxRetries) {
this._shutdownSubscription(aSubscriptionUri);
this._resubscribe(aSubscriptionUri);
return;
}
if (retryAfter !== -1) {
// This is a 5xx response.
- // To respect RetryAfter header, setTimeout is used. setAlarm sets a
- // cumulative alarm so it will not always respect RetryAfter header.
this._conns[aSubscriptionUri].countUnableToConnect++;
- setTimeout(_ => this._listenForMsgs(aSubscriptionUri), retryAfter);
+ this._conns[aSubscriptionUri].retryTimerID =
+ setTimeout(_ => this._listenForMsgs(aSubscriptionUri), retryAfter);
return;
}
- // we set just one alarm because most probably all connection will go over
- // a single TCP connection.
retryAfter = prefs.get("http2.retryInterval") *
Math.pow(2, this._conns[aSubscriptionUri].countUnableToConnect);
retryAfter = retryAfter * (0.8 + Math.random() * 0.4); // add +/-20%.
this._conns[aSubscriptionUri].countUnableToConnect++;
-
- if (retryAfter === 0) {
- setTimeout(_ => this._listenForMsgs(aSubscriptionUri), 0);
- } else {
- this._conns[aSubscriptionUri].waitingForAlarm = true;
- this._mainPushService.setAlarm(retryAfter);
- }
+ this._conns[aSubscriptionUri].retryTimerID =
+ setTimeout(_ => this._listenForMsgs(aSubscriptionUri), retryAfter);
console.debug("retryAfterBackoff: Retry in", retryAfter);
},
// Close connections.
_shutdownConnections: function(deleteInfo) {
console.debug("shutdownConnections()");
@@ -621,19 +613,23 @@ this.PushServiceHttp2 = {
this._conns[subscriptionUri].listener._pushService = null;
}
if (this._conns[subscriptionUri].channel) {
try {
this._conns[subscriptionUri].channel.cancel(Cr.NS_ERROR_ABORT);
} catch (e) {}
}
- this._conns[subscriptionUri].listener = null;
+
+ if (this._conns[subscriptionUri].retryTimerID > 0) {
+ clearTimeout(this._conns[subscriptionUri].retryTimerID);
+ }
+
+ this._conns[subscriptionUri].channel.listener = null;
this._conns[subscriptionUri].channel = null;
- this._conns[subscriptionUri].waitingForAlarm = false;
if (deleteInfo) {
delete this._conns[subscriptionUri];
}
}
}
},
// Start listening if subscriptions present.
@@ -652,37 +648,23 @@ this.PushServiceHttp2 = {
},
_startSingleConnection: function(record) {
console.debug("_startSingleConnection()");
if (typeof this._conns[record.subscriptionUri] != "object") {
this._conns[record.subscriptionUri] = {channel: null,
listener: null,
countUnableToConnect: 0,
- waitingForAlarm: false};
+ retryTimerID: 0};
}
if (!this._conns[record.subscriptionUri].conn) {
- this._conns[record.subscriptionUri].waitingForAlarm = false;
this._listenForMsgs(record.subscriptionUri);
}
},
- // Start listening if subscriptions present.
- _startConnectionsWaitingForAlarm: function() {
- console.debug("startConnectionsWaitingForAlarm()");
- for (let subscriptionUri in this._conns) {
- if ((this._conns[subscriptionUri]) &&
- !this._conns[subscriptionUri].conn &&
- this._conns[subscriptionUri].waitingForAlarm) {
- this._conns[subscriptionUri].waitingForAlarm = false;
- this._listenForMsgs(subscriptionUri);
- }
- }
- },
-
// Close connection and notify apps that subscription are gone.
_shutdownSubscription: function(aSubscriptionUri) {
console.debug("shutdownSubscriptions()");
if (typeof this._conns[aSubscriptionUri] == "object") {
if (this._conns[aSubscriptionUri].listener) {
this._conns[aSubscriptionUri].listener._pushService = null;
}
@@ -779,20 +761,16 @@ this.PushServiceHttp2 = {
}
)
.then(_ => this._ackMsgRecv(aAckUri))
.catch(err => {
console.error("pushChannelOnStop: Error receiving message",
err);
});
},
-
- onAlarmFired: function() {
- this._startConnectionsWaitingForAlarm();
- },
};
function PushRecordHttp2(record) {
PushRecord.call(this, record);
this.subscriptionUri = record.subscriptionUri;
this.pushReceiptEndpoint = record.pushReceiptEndpoint;
}