зеркало из https://github.com/mozilla/gecko-dev.git
328 строки
9.5 KiB
JavaScript
328 строки
9.5 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";
|
|
|
|
// Don't modify this, instead set dom.push.debug.
|
|
let gDebuggingEnabled = true;
|
|
|
|
function debug(s) {
|
|
if (gDebuggingEnabled)
|
|
dump("-*- Push.js: " + s + "\n");
|
|
}
|
|
|
|
const Cc = Components.classes;
|
|
const Ci = Components.interfaces;
|
|
const Cu = Components.utils;
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
|
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
|
|
|
const PUSH_SUBSCRIPTION_CID = Components.ID("{CA86B665-BEDA-4212-8D0F-5C9F65270B58}");
|
|
|
|
function PushSubscription(pushEndpoint, scope, principal) {
|
|
debug("PushSubscription Constructor");
|
|
this._pushEndpoint = pushEndpoint;
|
|
this._scope = scope;
|
|
this._principal = principal;
|
|
}
|
|
|
|
PushSubscription.prototype = {
|
|
__proto__: DOMRequestIpcHelper.prototype,
|
|
|
|
contractID: "@mozilla.org/push/PushSubscription;1",
|
|
|
|
classID : PUSH_SUBSCRIPTION_CID,
|
|
|
|
QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
|
|
Ci.nsISupportsWeakReference,
|
|
Ci.nsIObserver]),
|
|
|
|
init: function(aWindow) {
|
|
debug("PushSubscription init()");
|
|
|
|
this.initDOMRequestHelper(aWindow, [
|
|
"PushService:Unregister:OK",
|
|
"PushService:Unregister:KO",
|
|
]);
|
|
|
|
this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
|
|
.getService(Ci.nsISyncMessageSender);
|
|
},
|
|
|
|
__init: function(endpoint, scope, principal) {
|
|
this._pushEndpoint = endpoint;
|
|
this._scope = scope;
|
|
this._principal = principal;
|
|
},
|
|
|
|
get endpoint() {
|
|
return this._pushEndpoint;
|
|
},
|
|
|
|
unsubscribe: function() {
|
|
debug("unsubscribe! ")
|
|
|
|
let promiseInit = function(resolve, reject) {
|
|
let resolverId = this.getPromiseResolverId({resolve: resolve,
|
|
reject: reject });
|
|
|
|
this._cpmm.sendAsyncMessage("Push:Unregister", {
|
|
scope: this._scope,
|
|
pushEndpoint: this._pushEndpoint,
|
|
requestID: resolverId
|
|
}, null, this._principal);
|
|
}.bind(this);
|
|
|
|
return this.createPromise(promiseInit);
|
|
},
|
|
|
|
receiveMessage: function(aMessage) {
|
|
debug("push subscription receiveMessage(): " + JSON.stringify(aMessage))
|
|
|
|
let json = aMessage.data;
|
|
let resolver = this.takePromiseResolver(json.requestID);
|
|
if (resolver == null) {
|
|
return;
|
|
}
|
|
|
|
switch (aMessage.name) {
|
|
case "PushService:Unregister:OK":
|
|
if (typeof json.result !== "boolean") {
|
|
debug("Expected boolean result from PushService!");
|
|
resolve.reject("NetworkError");
|
|
return;
|
|
}
|
|
|
|
resolver.resolve(json.result);
|
|
break;
|
|
case "PushService:Unregister:KO":
|
|
resolver.reject("NetworkError");
|
|
break;
|
|
default:
|
|
debug("NOT IMPLEMENTED! receiveMessage for " + aMessage.name);
|
|
}
|
|
},
|
|
|
|
};
|
|
|
|
const PUSH_CID = Components.ID("{cde1d019-fad8-4044-b141-65fb4fb7a245}");
|
|
|
|
/**
|
|
* The Push component runs in the child process and exposes the SimplePush API
|
|
* to the web application. The PushService running in the parent process is the
|
|
* one actually performing all operations.
|
|
*/
|
|
function Push() {
|
|
debug("Push Constructor");
|
|
}
|
|
|
|
Push.prototype = {
|
|
__proto__: DOMRequestIpcHelper.prototype,
|
|
|
|
contractID: "@mozilla.org/push/PushManager;1",
|
|
|
|
classID : PUSH_CID,
|
|
|
|
QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
|
|
Ci.nsISupportsWeakReference,
|
|
Ci.nsIObserver]),
|
|
|
|
init: function(aWindow) {
|
|
// Set debug first so that all debugging actually works.
|
|
// NOTE: We don't add an observer here like in PushService. Flipping the
|
|
// pref will require a reload of the app/page, which seems acceptable.
|
|
gDebuggingEnabled = Services.prefs.getBoolPref("dom.push.debug");
|
|
debug("init()");
|
|
|
|
this._window = aWindow;
|
|
|
|
this.initDOMRequestHelper(aWindow, [
|
|
"PushService:Register:OK",
|
|
"PushService:Register:KO",
|
|
"PushService:Registration:OK",
|
|
"PushService:Registration:KO"
|
|
]);
|
|
|
|
this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
|
|
.getService(Ci.nsISyncMessageSender);
|
|
this._principal = aWindow.document.nodePrincipal;
|
|
},
|
|
|
|
setScope: function(scope){
|
|
debug('setScope ' + scope);
|
|
this._scope = scope;
|
|
},
|
|
|
|
askPermission: function (aAllowCallback, aCancelCallback) {
|
|
debug("askPermission");
|
|
|
|
let principal = this._window.document.nodePrincipal;
|
|
let type = "push";
|
|
let permValue =
|
|
Services.perms.testExactPermissionFromPrincipal(principal, type);
|
|
|
|
if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
|
aAllowCallback();
|
|
return;
|
|
}
|
|
|
|
if (permValue == Ci.nsIPermissionManager.DENY_ACTION) {
|
|
aCancelCallback();
|
|
return;
|
|
}
|
|
|
|
// Create an array with a single nsIContentPermissionType element.
|
|
type = {
|
|
type: "push",
|
|
access: null,
|
|
options: [],
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionType])
|
|
};
|
|
let typeArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
|
typeArray.appendElement(type, false);
|
|
|
|
// create a nsIContentPermissionRequest
|
|
let request = {
|
|
types: typeArray,
|
|
principal: principal,
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]),
|
|
allow: function() {
|
|
aAllowCallback();
|
|
},
|
|
cancel: function() {
|
|
aCancelCallback();
|
|
},
|
|
window: this._window
|
|
};
|
|
|
|
debug("asking the window utils about permission...")
|
|
// Using askPermission from nsIDOMWindowUtils that takes care of the
|
|
// remoting if needed.
|
|
let windowUtils = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
.getInterface(Ci.nsIDOMWindowUtils);
|
|
windowUtils.askPermission(request);
|
|
},
|
|
|
|
|
|
|
|
receiveMessage: function(aMessage) {
|
|
debug("push receiveMessage(): " + JSON.stringify(aMessage))
|
|
|
|
let json = aMessage.data;
|
|
let resolver = this.takePromiseResolver(json.requestID);
|
|
|
|
if (!resolver) {
|
|
return;
|
|
}
|
|
|
|
switch (aMessage.name) {
|
|
case "PushService:Register:OK":
|
|
{
|
|
let subscription =
|
|
new this._window.PushSubscription(json.pushEndpoint, this._scope,
|
|
this._principal);
|
|
resolver.resolve(subscription);
|
|
break;
|
|
}
|
|
case "PushService:Register:KO":
|
|
resolver.reject(null);
|
|
break;
|
|
case "PushService:Registration:OK":
|
|
{
|
|
let subscription = null;
|
|
try {
|
|
subscription =
|
|
new this._window.PushSubscription(json.registration.pushEndpoint,
|
|
this._scope, this._principal);
|
|
} catch(error) {
|
|
}
|
|
resolver.resolve(subscription);
|
|
break;
|
|
}
|
|
case "PushService:Registration:KO":
|
|
resolver.reject(null);
|
|
break;
|
|
default:
|
|
debug("NOT IMPLEMENTED! receiveMessage for " + aMessage.name);
|
|
}
|
|
},
|
|
|
|
subscribe: function() {
|
|
debug("subscribe()");
|
|
let p = this.createPromise(function(resolve, reject) {
|
|
let resolverId = this.getPromiseResolverId({ resolve: resolve, reject: reject });
|
|
|
|
this.askPermission(
|
|
function() {
|
|
this._cpmm.sendAsyncMessage("Push:Register", {
|
|
scope: this._scope,
|
|
requestID: resolverId
|
|
}, null, this._principal);
|
|
}.bind(this),
|
|
|
|
function() {
|
|
reject("PermissionDeniedError");
|
|
}
|
|
);
|
|
}.bind(this));
|
|
return p;
|
|
},
|
|
|
|
getSubscription: function() {
|
|
debug("getSubscription()" + this._scope);
|
|
|
|
let p = this.createPromise(function(resolve, reject) {
|
|
|
|
let resolverId = this.getPromiseResolverId({ resolve: resolve, reject: reject });
|
|
|
|
this.askPermission(
|
|
function() {
|
|
this._cpmm.sendAsyncMessage("Push:Registration", {
|
|
scope: this._scope,
|
|
requestID: resolverId
|
|
}, null, this._principal);
|
|
}.bind(this),
|
|
|
|
function() {
|
|
reject("PermissionDeniedError");
|
|
}
|
|
);
|
|
}.bind(this));
|
|
return p;
|
|
},
|
|
|
|
permissionState: function() {
|
|
debug("permissionState()" + this._scope);
|
|
|
|
let p = this.createPromise((resolve, reject) => {
|
|
let permission = Ci.nsIPermissionManager.DENY_ACTION;
|
|
|
|
try {
|
|
let permissionManager = Cc["@mozilla.org/permissionmanager;1"]
|
|
.getService(Ci.nsIPermissionManager);
|
|
permission =
|
|
permissionManager.testExactPermissionFromPrincipal(this._principal,
|
|
"push");
|
|
} catch(e) {
|
|
reject();
|
|
return;
|
|
}
|
|
|
|
let pushPermissionStatus = "prompt";
|
|
if (permission == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
|
pushPermissionStatus = "granted";
|
|
} else if (permission == Ci.nsIPermissionManager.DENY_ACTION) {
|
|
pushPermissionStatus = "denied";
|
|
}
|
|
resolve(pushPermissionStatus);
|
|
});
|
|
return p;
|
|
},
|
|
}
|
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Push, PushSubscription]);
|