mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1150683 - Implement nsIPushNotificationService. r=dougt
--- b2g/installer/package-manifest.in | 2 +- browser/installer/package-manifest.in | 2 +- dom/push/Push.manifest | 11 +- dom/push/PushNotificationService.js | 81 +++++++++ dom/push/PushService.jsm | 324 ++++++++++++++++++++-------------- dom/push/PushServiceLauncher.js | 50 ------ dom/push/moz.build | 2 +- 7 files changed, 285 insertions(+), 187 deletions(-) create mode 100644 dom/push/PushNotificationService.js delete mode 100644 dom/push/PushServiceLauncher.js
This commit is contained in:
parent
6855cac604
commit
86e4e52d97
@ -630,7 +630,7 @@
|
|||||||
@RESPATH@/components/AppsService.manifest
|
@RESPATH@/components/AppsService.manifest
|
||||||
@RESPATH@/components/Push.js
|
@RESPATH@/components/Push.js
|
||||||
@RESPATH@/components/Push.manifest
|
@RESPATH@/components/Push.manifest
|
||||||
@RESPATH@/components/PushServiceLauncher.js
|
@RESPATH@/components/PushNotificationService.js
|
||||||
|
|
||||||
@RESPATH@/components/InterAppComm.manifest
|
@RESPATH@/components/InterAppComm.manifest
|
||||||
@RESPATH@/components/InterAppCommService.js
|
@RESPATH@/components/InterAppCommService.js
|
||||||
|
@ -557,7 +557,7 @@
|
|||||||
@RESPATH@/components/AlarmsManager.manifest
|
@RESPATH@/components/AlarmsManager.manifest
|
||||||
@RESPATH@/components/Push.js
|
@RESPATH@/components/Push.js
|
||||||
@RESPATH@/components/Push.manifest
|
@RESPATH@/components/Push.manifest
|
||||||
@RESPATH@/components/PushServiceLauncher.js
|
@RESPATH@/components/PushNotificationService.js
|
||||||
|
|
||||||
@RESPATH@/components/SlowScriptDebug.manifest
|
@RESPATH@/components/SlowScriptDebug.manifest
|
||||||
@RESPATH@/components/SlowScriptDebug.js
|
@RESPATH@/components/SlowScriptDebug.js
|
||||||
|
@ -5,7 +5,10 @@ contract @mozilla.org/push/PushManager;1 {cde1d019-fad8-4044-b141-65fb4fb7a245}
|
|||||||
component {CA86B665-BEDA-4212-8D0F-5C9F65270B58} Push.js
|
component {CA86B665-BEDA-4212-8D0F-5C9F65270B58} Push.js
|
||||||
contract @mozilla.org/push/PushSubscription;1 {CA86B665-BEDA-4212-8D0F-5C9F65270B58}
|
contract @mozilla.org/push/PushSubscription;1 {CA86B665-BEDA-4212-8D0F-5C9F65270B58}
|
||||||
|
|
||||||
# Component to initialize PushService on startup.
|
# XPCOM component; initializes the PushService on startup.
|
||||||
component {4b8caa3b-3c58-4f3c-a7f5-7bd9cb24c11d} PushServiceLauncher.js
|
component {32028e38-903b-4a64-a180-5857eb4cb3dd} PushNotificationService.js
|
||||||
contract @mozilla.org/push/ServiceLauncher;1 {4b8caa3b-3c58-4f3c-a7f5-7bd9cb24c11d}
|
contract @mozilla.org/push/NotificationService;1 {32028e38-903b-4a64-a180-5857eb4cb3dd}
|
||||||
category app-startup PushServiceLauncher @mozilla.org/push/ServiceLauncher;1
|
category app-startup PushNotificationService @mozilla.org/push/NotificationService;1
|
||||||
|
|
||||||
|
component {66a87970-6dc9-46e0-ac61-adb4a13791de} PushNotificationService.js
|
||||||
|
contract @mozilla.org/push/ObserverNotification;1 {66a87970-6dc9-46e0-ac61-adb4a13791de}
|
||||||
|
81
dom/push/PushNotificationService.js
Normal file
81
dom/push/PushNotificationService.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/* 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 Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
const Cr = Components.results;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
let isParent = Cc["@mozilla.org/xre/runtime;1"]
|
||||||
|
.getService(Ci.nsIXULRuntime)
|
||||||
|
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "PushService", function() {
|
||||||
|
// Lazily initialize the PushService on
|
||||||
|
// `sessionstore-windows-restored` or first use.
|
||||||
|
const {PushService} = Cu.import("resource://gre/modules/PushService.jsm", {});
|
||||||
|
if (isParent) {
|
||||||
|
PushService.init();
|
||||||
|
}
|
||||||
|
return PushService;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.PushNotificationService = function PushNotificationService() {};
|
||||||
|
|
||||||
|
PushNotificationService.prototype = {
|
||||||
|
classID: Components.ID("{32028e38-903b-4a64-a180-5857eb4cb3dd}"),
|
||||||
|
|
||||||
|
contractID: "@mozilla.org/push/NotificationService;1",
|
||||||
|
|
||||||
|
_xpcom_factory: XPCOMUtils.generateSingletonFactory(PushNotificationService),
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||||
|
Ci.nsISupportsWeakReference,
|
||||||
|
Ci.nsIPushNotificationService]),
|
||||||
|
|
||||||
|
register: function register(scope, pageURL) {
|
||||||
|
return PushService._register({scope, pageURL});
|
||||||
|
},
|
||||||
|
|
||||||
|
unregister: function unregister(scope) {
|
||||||
|
return PushService._unregister({scope});
|
||||||
|
},
|
||||||
|
|
||||||
|
registration: function registration(scope) {
|
||||||
|
return PushService._registration({scope});
|
||||||
|
},
|
||||||
|
|
||||||
|
observe: function observe(subject, topic, data) {
|
||||||
|
switch (topic) {
|
||||||
|
case "app-startup":
|
||||||
|
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
|
||||||
|
break;
|
||||||
|
case "sessionstore-windows-restored":
|
||||||
|
Services.obs.removeObserver(this, "sessionstore-windows-restored");
|
||||||
|
if (isParent) {
|
||||||
|
PushService.init();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.PushObserverNotification = function PushObserverNotification() {};
|
||||||
|
|
||||||
|
PushObserverNotification.prototype = {
|
||||||
|
classID: Components.ID("{66a87970-6dc9-46e0-ac61-adb4a13791de}"),
|
||||||
|
|
||||||
|
contractID: "@mozilla.org/push/ObserverNotification;1",
|
||||||
|
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPushObserverNotification])
|
||||||
|
};
|
||||||
|
|
||||||
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
|
||||||
|
PushNotificationService,
|
||||||
|
PushObserverNotification
|
||||||
|
]);
|
@ -294,6 +294,7 @@ this.PushService = {
|
|||||||
*/
|
*/
|
||||||
case "xpcom-shutdown":
|
case "xpcom-shutdown":
|
||||||
this.uninit();
|
this.uninit();
|
||||||
|
break;
|
||||||
case "network-active-changed": /* On B2G. */
|
case "network-active-changed": /* On B2G. */
|
||||||
case "network:offline-status-changed": /* On desktop. */
|
case "network:offline-status-changed": /* On desktop. */
|
||||||
// In case of network-active-changed, always disconnect existing
|
// In case of network-active-changed, always disconnect existing
|
||||||
@ -348,9 +349,12 @@ this.PushService = {
|
|||||||
.deferred.reject({status: 0, error: "TimeoutError"});
|
.deferred.reject({status: 0, error: "TimeoutError"});
|
||||||
|
|
||||||
delete this._pendingRequests[channelID];
|
delete this._pendingRequests[channelID];
|
||||||
for (let i = this._requestQueue.length - 1; i >= 0; --i)
|
for (let i = this._requestQueue.length - 1; i >= 0; --i) {
|
||||||
if (this._requestQueue[i].channelID == channelID)
|
let [, data] = this._requestQueue[i];
|
||||||
|
if (data && data.channelID == channelID) {
|
||||||
this._requestQueue.splice(i, 1);
|
this._requestQueue.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,6 +497,9 @@ this.PushService = {
|
|||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
debug("init()");
|
debug("init()");
|
||||||
|
if (this._started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
|
var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
|
||||||
.getService(Ci.nsIFrameScriptLoader);
|
.getService(Ci.nsIFrameScriptLoader);
|
||||||
@ -564,6 +571,7 @@ this.PushService = {
|
|||||||
|
|
||||||
this._waitingForPong = false;
|
this._waitingForPong = false;
|
||||||
this._stopAlarm();
|
this._stopAlarm();
|
||||||
|
this._cancelPendingRequests();
|
||||||
},
|
},
|
||||||
|
|
||||||
uninit: function() {
|
uninit: function() {
|
||||||
@ -603,6 +611,7 @@ this.PushService = {
|
|||||||
this._requestTimeoutTimer.cancel();
|
this._requestTimeoutTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._started = false;
|
||||||
debug("shutdown complete!");
|
debug("shutdown complete!");
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -880,6 +889,10 @@ this.PushService = {
|
|||||||
|
|
||||||
_startListeningIfChannelsPresent: function() {
|
_startListeningIfChannelsPresent: function() {
|
||||||
// Check to see if we need to do anything.
|
// Check to see if we need to do anything.
|
||||||
|
if (this._requestQueue.length > 0) {
|
||||||
|
this._beginWSSetup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._db.getAllChannelIDs(function(channelIDs) {
|
this._db.getAllChannelIDs(function(channelIDs) {
|
||||||
if (channelIDs.length > 0) {
|
if (channelIDs.length > 0) {
|
||||||
this._beginWSSetup();
|
this._beginWSSetup();
|
||||||
@ -1163,11 +1176,9 @@ this.PushService = {
|
|||||||
debug("sendRequest() " + action);
|
debug("sendRequest() " + action);
|
||||||
if (typeof data.channelID !== "string") {
|
if (typeof data.channelID !== "string") {
|
||||||
debug("Received non-string channelID");
|
debug("Received non-string channelID");
|
||||||
return Promise.reject("Received non-string channelID");
|
return Promise.reject({error: "Received non-string channelID"});
|
||||||
}
|
}
|
||||||
|
|
||||||
let deferred = Promise.defer();
|
|
||||||
|
|
||||||
if (Object.keys(this._pendingRequests).length == 0) {
|
if (Object.keys(this._pendingRequests).length == 0) {
|
||||||
// start the timer since we now have at least one request
|
// start the timer since we now have at least one request
|
||||||
if (!this._requestTimeoutTimer)
|
if (!this._requestTimeoutTimer)
|
||||||
@ -1178,8 +1189,18 @@ this.PushService = {
|
|||||||
Ci.nsITimer.TYPE_REPEATING_SLACK);
|
Ci.nsITimer.TYPE_REPEATING_SLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._pendingRequests[data.channelID] = { deferred: deferred,
|
let deferred;
|
||||||
ctime: Date.now() };
|
let request = this._pendingRequests[data.channelID];
|
||||||
|
if (request) {
|
||||||
|
// If a request is already pending for this channel ID, assume it's a
|
||||||
|
// retry. Use the existing deferred, but update the send time and re-send
|
||||||
|
// the request.
|
||||||
|
deferred = request.deferred;
|
||||||
|
} else {
|
||||||
|
deferred = Promise.defer();
|
||||||
|
request = this._pendingRequests[data.channelID] = {deferred};
|
||||||
|
}
|
||||||
|
request.ctime = Date.now();
|
||||||
|
|
||||||
this._send(action, data);
|
this._send(action, data);
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
@ -1201,6 +1222,11 @@ this.PushService = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this._currentState != STATE_READY) {
|
if (this._currentState != STATE_READY) {
|
||||||
|
if (!this._started) {
|
||||||
|
// The component hasn't been initialized yet. Return early; init()
|
||||||
|
// will dequeue all pending requests.
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!this._ws) {
|
if (!this._ws) {
|
||||||
// This will end up calling processNextRequestInQueue().
|
// This will end up calling processNextRequestInQueue().
|
||||||
this._beginWSSetup();
|
this._beginWSSetup();
|
||||||
@ -1269,52 +1295,49 @@ this.PushService = {
|
|||||||
// registration.
|
// registration.
|
||||||
_notifyAllAppsRegister: function() {
|
_notifyAllAppsRegister: function() {
|
||||||
debug("notifyAllAppsRegister()");
|
debug("notifyAllAppsRegister()");
|
||||||
let deferred = Promise.defer();
|
return new Promise((resolve, reject) => {
|
||||||
|
// records are objects describing the registration as stored in IndexedDB.
|
||||||
// records are objects describing the registration as stored in IndexedDB.
|
this._db.getAllChannelIDs(records => {
|
||||||
function wakeupRegisteredApps(records) {
|
let scopes = new Set();
|
||||||
// Pages to be notified.
|
for (let record of records) {
|
||||||
// wakeupTable[scope] -> [ pageURL ]
|
scopes.add(record.scope);
|
||||||
let wakeupTable = {};
|
}
|
||||||
for (let i = 0; i < records.length; i++) {
|
let globalMM = Cc['@mozilla.org/globalmessagemanager;1'].getService(Ci.nsIMessageListenerManager);
|
||||||
let record = records[i];
|
for (let scope of scopes) {
|
||||||
if (!(record.scope in wakeupTable))
|
// Notify XPCOM observers.
|
||||||
wakeupTable[record.scope] = [];
|
Services.obs.notifyObservers(
|
||||||
|
null,
|
||||||
wakeupTable[record.scope].push(record.pageURL);
|
"push-subscription-change",
|
||||||
}
|
scope
|
||||||
|
);
|
||||||
// TODO -- test needed. E10s support needed.
|
// TODO -- test needed. E10s support needed.
|
||||||
|
globalMM.broadcastAsyncMessage('pushsubscriptionchanged', scope);
|
||||||
let globalMM = Cc['@mozilla.org/globalmessagemanager;1'].getService(Ci.nsIMessageListenerManager);
|
}
|
||||||
for (let scope in wakeupTable) {
|
resolve();
|
||||||
wakeupTable[scope].forEach(function(pageURL) {
|
}, reject);
|
||||||
globalMM.broadcastAsyncMessage('pushsubscriptionchanged', aPushRecord.scope);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
deferred.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._db.getAllChannelIDs(wakeupRegisteredApps, deferred.reject);
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_notifyApp: function(aPushRecord) {
|
_notifyApp: function(aPushRecord) {
|
||||||
if (!aPushRecord || !aPushRecord.pageURL || !aPushRecord.scope) {
|
if (!aPushRecord || !aPushRecord.scope) {
|
||||||
debug("notifyApp() something is undefined. Dropping notification: "
|
debug("notifyApp() something is undefined. Dropping notification: "
|
||||||
+ JSON.stringify(aPushRecord) );
|
+ JSON.stringify(aPushRecord) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("notifyApp() " + aPushRecord.pageURL +
|
debug("notifyApp() " + aPushRecord.scope);
|
||||||
" " + aPushRecord.scope);
|
|
||||||
let pageURI = Services.io.newURI(aPushRecord.pageURL, null, null);
|
|
||||||
let scopeURI = Services.io.newURI(aPushRecord.scope, null, null);
|
let scopeURI = Services.io.newURI(aPushRecord.scope, null, null);
|
||||||
let message = {
|
// Notify XPCOM observers.
|
||||||
pushEndpoint: aPushRecord.pushEndpoint,
|
let notification = Cc["@mozilla.org/push/ObserverNotification;1"]
|
||||||
version: aPushRecord.version
|
.createInstance(Ci.nsIPushObserverNotification);
|
||||||
};
|
notification.pushEndpoint = aPushRecord.pushEndpoint;
|
||||||
|
notification.version = aPushRecord.version;
|
||||||
|
notification.data = "";
|
||||||
|
Services.obs.notifyObservers(
|
||||||
|
notification,
|
||||||
|
"push-notification",
|
||||||
|
aPushRecord.scope
|
||||||
|
);
|
||||||
|
|
||||||
// If permission has been revoked, trash the message.
|
// If permission has been revoked, trash the message.
|
||||||
if(Services.perms.testExactPermission(scopeURI, "push") != Ci.nsIPermissionManager.ALLOW_ACTION) {
|
if(Services.perms.testExactPermission(scopeURI, "push") != Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||||
@ -1363,24 +1386,38 @@ this.PushService = {
|
|||||||
* Called on message from the child process. aPageRecord is an object sent by
|
* Called on message from the child process. aPageRecord is an object sent by
|
||||||
* navigator.push, identifying the sending page and other fields.
|
* navigator.push, identifying the sending page and other fields.
|
||||||
*/
|
*/
|
||||||
|
_registerWithServer: function(channelID, aPageRecord) {
|
||||||
|
debug("registerWithServer()");
|
||||||
|
|
||||||
_registerWithServer: function(aPageRecord, aMessageManager) {
|
return this._sendRequest("register", {channelID: channelID})
|
||||||
|
.then(
|
||||||
|
this._onRegisterSuccess.bind(this, aPageRecord, channelID),
|
||||||
|
this._onRegisterError.bind(this)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
_generateID: function() {
|
||||||
let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
|
let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
|
||||||
.getService(Ci.nsIUUIDGenerator);
|
.getService(Ci.nsIUUIDGenerator);
|
||||||
// generateUUID() gives a UUID surrounded by {...}, slice them off.
|
// generateUUID() gives a UUID surrounded by {...}, slice them off.
|
||||||
let channelID = uuidGenerator.generateUUID().toString().slice(1, -1);
|
return uuidGenerator.generateUUID().toString().slice(1, -1);
|
||||||
|
},
|
||||||
|
|
||||||
this._sendRequest("register", {channelID: channelID})
|
_register: function(aPageRecord) {
|
||||||
.then(
|
let recordPromise = new Promise((resolve, reject) =>
|
||||||
this._onRegisterSuccess.bind(this, aPageRecord, channelID),
|
this._db.getByScope(aPageRecord.scope, resolve, reject));
|
||||||
this._onRegisterError.bind(this, aPageRecord, aMessageManager)
|
|
||||||
)
|
return recordPromise.then(
|
||||||
.then(
|
pushRecord => {
|
||||||
function(message) {
|
if (pushRecord == null) {
|
||||||
aMessageManager.sendAsyncMessage("PushService:Register:OK", message);
|
let channelID = this._generateID();
|
||||||
},
|
return this._registerWithServer(channelID, aPageRecord);
|
||||||
function(message) {
|
}
|
||||||
aMessageManager.sendAsyncMessage("PushService:Register:KO", message);
|
return pushRecord;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
debug("getByScope failed");
|
||||||
|
throw "Database error";
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -1388,17 +1425,20 @@ this.PushService = {
|
|||||||
register: function(aPageRecord, aMessageManager) {
|
register: function(aPageRecord, aMessageManager) {
|
||||||
debug("register(): " + JSON.stringify(aPageRecord));
|
debug("register(): " + JSON.stringify(aPageRecord));
|
||||||
|
|
||||||
this._db.getByScope(aPageRecord.scope,
|
this._register(aPageRecord).then(
|
||||||
function(aPageRecord, aMessageManager, pushRecord) {
|
function(aPageRecord, aMessageManager, pushRecord) {
|
||||||
if (pushRecord == null) {
|
let message = {
|
||||||
this._registerWithServer(aPageRecord, aMessageManager);
|
requestID: aPageRecord.requestID,
|
||||||
}
|
pushEndpoint: pushRecord.pushEndpoint
|
||||||
else {
|
};
|
||||||
this._onRegistrationSuccess(aPageRecord, aMessageManager, pushRecord);
|
aMessageManager.sendAsyncMessage("PushService:Register:OK", message);
|
||||||
}
|
|
||||||
}.bind(this, aPageRecord, aMessageManager),
|
}.bind(this, aPageRecord, aMessageManager),
|
||||||
function () {
|
function(error) {
|
||||||
debug("getByScope failed");
|
let message = {
|
||||||
|
requestID: aPageRecord.requestID,
|
||||||
|
error
|
||||||
|
};
|
||||||
|
aMessageManager.sendAsyncMessage("PushService:Register:KO", message);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -1409,19 +1449,15 @@ this.PushService = {
|
|||||||
*/
|
*/
|
||||||
_onRegisterSuccess: function(aPageRecord, generatedChannelID, data) {
|
_onRegisterSuccess: function(aPageRecord, generatedChannelID, data) {
|
||||||
debug("_onRegisterSuccess()");
|
debug("_onRegisterSuccess()");
|
||||||
let deferred = Promise.defer();
|
|
||||||
let message = { requestID: aPageRecord.requestID };
|
|
||||||
|
|
||||||
if (typeof data.channelID !== "string") {
|
if (typeof data.channelID !== "string") {
|
||||||
debug("Invalid channelID " + message);
|
debug("Invalid channelID " + data.channelID);
|
||||||
message["error"] = "Invalid channelID received";
|
throw "Invalid channelID received";
|
||||||
throw message;
|
|
||||||
}
|
}
|
||||||
else if (data.channelID != generatedChannelID) {
|
else if (data.channelID != generatedChannelID) {
|
||||||
debug("Server replied with different channelID " + data.channelID +
|
debug("Server replied with different channelID " + data.channelID +
|
||||||
" than what UA generated " + generatedChannelID);
|
" than what UA generated " + generatedChannelID);
|
||||||
message["error"] = "Server sent 200 status code but different channelID";
|
throw "Server sent 200 status code but different channelID";
|
||||||
throw message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -1429,8 +1465,7 @@ this.PushService = {
|
|||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
debug("Invalid pushEndpoint " + data.pushEndpoint);
|
debug("Invalid pushEndpoint " + data.pushEndpoint);
|
||||||
message["error"] = "Invalid pushEndpoint " + data.pushEndpoint;
|
throw "Invalid pushEndpoint " + data.pushEndpoint;
|
||||||
throw message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let record = {
|
let record = {
|
||||||
@ -1443,33 +1478,30 @@ this.PushService = {
|
|||||||
|
|
||||||
debug("scope in _onRegisterSuccess: " + aPageRecord.scope)
|
debug("scope in _onRegisterSuccess: " + aPageRecord.scope)
|
||||||
|
|
||||||
this._updatePushRecord(record)
|
return this._updatePushRecord(record)
|
||||||
.then(
|
.then(
|
||||||
function() {
|
function() {
|
||||||
message["pushEndpoint"] = data.pushEndpoint;
|
return record;
|
||||||
deferred.resolve(message);
|
|
||||||
},
|
},
|
||||||
function(error) {
|
function(error) {
|
||||||
// Unable to save.
|
// Unable to save.
|
||||||
this._send("unregister", {channelID: record.channelID});
|
this._send("unregister", {channelID: record.channelID});
|
||||||
message["error"] = error;
|
throw error;
|
||||||
deferred.reject(message);
|
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
);
|
);
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exceptions thrown in _onRegisterError are caught by the promise obtained
|
* Exceptions thrown in _onRegisterError are caught by the promise obtained
|
||||||
* from _sendRequest, causing the promise to be rejected instead.
|
* from _sendRequest, causing the promise to be rejected instead.
|
||||||
*/
|
*/
|
||||||
_onRegisterError: function(aPageRecord, aMessageManager, reply) {
|
_onRegisterError: function(reply) {
|
||||||
debug("_onRegisterError()");
|
debug("_onRegisterError()");
|
||||||
if (!reply.error) {
|
if (!reply.error) {
|
||||||
debug("Called without valid error message!");
|
debug("Called without valid error message!");
|
||||||
|
throw "Registration error";
|
||||||
}
|
}
|
||||||
throw { requestID: aPageRecord.requestID, error: reply.error };
|
throw reply.error;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1496,78 +1528,99 @@ this.PushService = {
|
|||||||
* messages from the server, and have the client acknowledge. On a server,
|
* messages from the server, and have the client acknowledge. On a server,
|
||||||
* data is cheap, reliable notification is not.
|
* data is cheap, reliable notification is not.
|
||||||
*/
|
*/
|
||||||
unregister: function(aPageRecord, aMessageManager) {
|
_unregister: function(aPageRecord) {
|
||||||
debug("unregister() " + JSON.stringify(aPageRecord));
|
debug("unregisterWithServer()");
|
||||||
|
|
||||||
|
let deferred = Promise.defer();
|
||||||
let fail = function(error) {
|
let fail = function(error) {
|
||||||
debug("unregister() fail() error " + error);
|
debug("unregister() fail() error " + error);
|
||||||
let message = {requestID: aPageRecord.requestID, error: error};
|
deferred.reject(error);
|
||||||
aMessageManager.sendAsyncMessage("PushService:Unregister:KO", message);
|
};
|
||||||
|
|
||||||
|
if (!aPageRecord.scope) {
|
||||||
|
fail("NotFoundError");
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._db.getByPushEndpoint(aPageRecord.pushEndpoint, function(record) {
|
this._db.getByScope(aPageRecord.scope, function(record) {
|
||||||
// If the endpoint didn't exist, let's just fail.
|
// If the endpoint didn't exist, let's just fail.
|
||||||
if (record === undefined) {
|
if (record === undefined) {
|
||||||
fail("NotFoundError");
|
fail("NotFoundError");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-owner tried to unregister, say success, but don't do anything.
|
|
||||||
if (record.scope !== aPageRecord.scope) {
|
|
||||||
aMessageManager.sendAsyncMessage("PushService:Unregister:OK", {
|
|
||||||
requestID: aPageRecord.requestID,
|
|
||||||
pushEndpoint: aPageRecord.pushEndpoint
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._db.delete(record.channelID, function() {
|
this._db.delete(record.channelID, function() {
|
||||||
// Let's be nice to the server and try to inform it, but we don't care
|
// Let's be nice to the server and try to inform it, but we don't care
|
||||||
// about the reply.
|
// about the reply.
|
||||||
this._send("unregister", {channelID: record.channelID});
|
this._send("unregister", {channelID: record.channelID});
|
||||||
|
deferred.resolve();
|
||||||
|
}.bind(this), fail);
|
||||||
|
}.bind(this), fail);
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
unregister: function(aPageRecord, aMessageManager) {
|
||||||
|
debug("unregister() " + JSON.stringify(aPageRecord));
|
||||||
|
|
||||||
|
this._unregister(aPageRecord).then(
|
||||||
|
() => {
|
||||||
aMessageManager.sendAsyncMessage("PushService:Unregister:OK", {
|
aMessageManager.sendAsyncMessage("PushService:Unregister:OK", {
|
||||||
requestID: aPageRecord.requestID,
|
requestID: aPageRecord.requestID,
|
||||||
pushEndpoint: aPageRecord.pushEndpoint
|
pushEndpoint: aPageRecord.pushEndpoint
|
||||||
});
|
});
|
||||||
}.bind(this), fail);
|
},
|
||||||
}.bind(this), fail);
|
error => {
|
||||||
|
aMessageManager.sendAsyncMessage("PushService:Unregister:KO", {
|
||||||
|
requestID: aPageRecord.requestID,
|
||||||
|
error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called on message from the child process
|
* Called on message from the child process
|
||||||
*/
|
*/
|
||||||
|
_registration: function(aPageRecord) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!aPageRecord.scope) {
|
||||||
|
reject("Database error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._db.getByScope(aPageRecord.scope,
|
||||||
|
pushRecord => {
|
||||||
|
let registration = null;
|
||||||
|
if (pushRecord) {
|
||||||
|
registration = {
|
||||||
|
pushEndpoint: pushRecord.pushEndpoint,
|
||||||
|
version: pushRecord.version
|
||||||
|
};
|
||||||
|
}
|
||||||
|
resolve(registration);
|
||||||
|
},
|
||||||
|
() => reject("Database error")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
registration: function(aPageRecord, aMessageManager) {
|
registration: function(aPageRecord, aMessageManager) {
|
||||||
debug("registration()");
|
debug("registration()");
|
||||||
this._db.getByScope(aPageRecord.scope,
|
|
||||||
this._onRegistrationSuccess.bind(this, aPageRecord, aMessageManager),
|
|
||||||
this._onRegistrationError.bind(this, aPageRecord, aMessageManager));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onRegistrationSuccess: function(aPageRecord,
|
return this._registration(aPageRecord).then(
|
||||||
aMessageManager,
|
registration => {
|
||||||
pushRecord) {
|
aMessageManager.sendAsyncMessage("PushService:Registration:OK", {
|
||||||
|
requestID: aPageRecord.requestID,
|
||||||
|
registration
|
||||||
let registration = null;
|
});
|
||||||
|
},
|
||||||
if (pushRecord) {
|
error => {
|
||||||
registration = {
|
aMessageManager.sendAsyncMessage("PushService:Registration:KO", {
|
||||||
pushEndpoint: pushRecord.pushEndpoint,
|
requestID: aPageRecord.requestID,
|
||||||
version: pushRecord.version
|
error
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
);
|
||||||
aMessageManager.sendAsyncMessage("PushService:Registration:OK", {
|
|
||||||
requestID: aPageRecord.requestID,
|
|
||||||
registration: registration
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_onRegistrationError: function(aPageRecord, aMessageManager) {
|
|
||||||
aMessageManager.sendAsyncMessage("PushService:Registration:KO", {
|
|
||||||
requestID: aPageRecord.requestID,
|
|
||||||
error: "Database error"
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// begin Push protocol handshake
|
// begin Push protocol handshake
|
||||||
@ -1730,6 +1783,17 @@ this.PushService = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rejects all pending requests with errors.
|
||||||
|
*/
|
||||||
|
_cancelPendingRequests: function() {
|
||||||
|
for (let channelID in this._pendingRequests) {
|
||||||
|
let request = this._pendingRequests[channelID];
|
||||||
|
delete this._pendingRequests[channelID];
|
||||||
|
request.deferred.reject({status: 0, error: "CancelledError"});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method should be called only if the device is on a mobile network!
|
* This method should be called only if the device is on a mobile network!
|
||||||
*/
|
*/
|
||||||
@ -1904,4 +1968,4 @@ this.PushService = {
|
|||||||
".mcc" + ("00" + networkInfo.mcc).slice(-3) + ".3gppnetwork.org";
|
".mcc" + ("00" + networkInfo.mcc).slice(-3) + ".3gppnetwork.org";
|
||||||
queryDNSForDomain(netidAddress, callback);
|
queryDNSForDomain(netidAddress, callback);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
/* 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 Cc = Components.classes;
|
|
||||||
const Ci = Components.interfaces;
|
|
||||||
const Cu = Components.utils;
|
|
||||||
const Cr = Components.results;
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
function PushServiceLauncher() {
|
|
||||||
};
|
|
||||||
|
|
||||||
PushServiceLauncher.prototype = {
|
|
||||||
classID: Components.ID("{4b8caa3b-3c58-4f3c-a7f5-7bd9cb24c11d}"),
|
|
||||||
|
|
||||||
contractID: "@mozilla.org/push/ServiceLauncher;1",
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
|
||||||
Ci.nsISupportsWeakReference]),
|
|
||||||
|
|
||||||
observe: function observe(subject, topic, data) {
|
|
||||||
switch (topic) {
|
|
||||||
case "app-startup":
|
|
||||||
Services.obs.addObserver(this, "final-ui-startup", true);
|
|
||||||
break;
|
|
||||||
case "final-ui-startup":
|
|
||||||
Services.obs.removeObserver(this, "final-ui-startup");
|
|
||||||
if (!Services.prefs.getBoolPref("dom.push.enabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isParent = Cc["@mozilla.org/xre/runtime;1"]
|
|
||||||
.getService(Ci.nsIXULRuntime)
|
|
||||||
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
|
||||||
|
|
||||||
if (isParent) {
|
|
||||||
Cu.import("resource://gre/modules/PushService.jsm");
|
|
||||||
PushService.init();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PushServiceLauncher]);
|
|
@ -6,7 +6,7 @@
|
|||||||
EXTRA_COMPONENTS += [
|
EXTRA_COMPONENTS += [
|
||||||
'Push.js',
|
'Push.js',
|
||||||
'Push.manifest',
|
'Push.manifest',
|
||||||
'PushServiceLauncher.js',
|
'PushNotificationService.js',
|
||||||
]
|
]
|
||||||
|
|
||||||
EXTRA_JS_MODULES += [
|
EXTRA_JS_MODULES += [
|
||||||
|
Loading…
Reference in New Issue
Block a user