Bug 790141 - Native implementation of browserid get() and getVerifiedEmail(). r=benadida

This commit is contained in:
Jed Parsons 2012-11-20 20:28:34 -05:00
parent 9c9fa33efb
commit 6cc0782ec9
5 changed files with 109 additions and 17 deletions

View File

@ -55,6 +55,9 @@ var func = null;
* assertion: optional assertion
*/
function identityCall(message) {
if (options._internal) {
message._internal = options._internal;
}
sendAsyncMessage(kIdentityControllerDoMethod, message);
}
@ -78,7 +81,7 @@ function doInternalWatch() {
log("doInternalWatch:", options, isLoaded);
if (options && isLoaded) {
let BrowserID = content.wrappedJSObject.BrowserID;
BrowserID.internal.watch(function(aParams) {
BrowserID.internal.watch(function(aParams, aInternalParams) {
identityCall(aParams);
if (aParams.method === "ready") {
closeIdentityDialog();
@ -86,7 +89,7 @@ function doInternalWatch() {
},
JSON.stringify(options),
function(...things) {
log("internal: ", things);
log("(watch) internal: ", things);
}
);
}
@ -97,9 +100,13 @@ function doInternalRequest() {
if (options && isLoaded) {
content.wrappedJSObject.BrowserID.internal.get(
options.origin,
function(assertion) {
function(assertion, internalParams) {
internalParams = internalParams || {};
if (assertion) {
identityCall({method: 'login', assertion: assertion});
identityCall({
method: 'login',
assertion: assertion,
_internalParams: internalParams});
}
closeIdentityDialog();
},

View File

@ -305,7 +305,11 @@ this.SignInToWebsiteController = {
break;
case "login":
IdentityService.doLogin(aRpId, message.assertion);
if (message._internalParams) {
IdentityService.doLogin(aRpId, message.assertion, message._internalParams);
} else {
IdentityService.doLogin(aRpId, message.assertion);
}
break;
case "logout":

View File

@ -99,14 +99,19 @@ function RPWatchContext(aOptions, aTargetMM) {
// default for no loggedInUser is undefined, not null
this.loggedInUser = aOptions.loggedInUser;
// Maybe internal
this._internal = aOptions._internal;
this._mm = aTargetMM;
}
RPWatchContext.prototype = {
doLogin: function RPWatchContext_onlogin(aAssertion) {
doLogin: function RPWatchContext_onlogin(aAssertion, aMaybeInternalParams) {
log("doLogin: " + this.id);
let message = new IDDOMMessage({id: this.id});
message.assertion = aAssertion;
let message = new IDDOMMessage({id: this.id, assertion: aAssertion});
if (aMaybeInternalParams) {
message._internalParams = aMaybeInternalParams;
}
this._mm.sendAsyncMessage("Identity:RP:Watch:OnLogin", message);
},

View File

@ -32,6 +32,8 @@ nsDOMIdentity.prototype = {
watch: 'r',
request: 'r',
logout: 'r',
get: 'r',
getVerifiedEmail: 'r',
// Provisioning
beginProvisioning: 'r',
@ -51,7 +53,6 @@ nsDOMIdentity.prototype = {
*/
watch: function nsDOMIdentity_watch(aOptions) {
this._log("watch");
if (this._rpWatcher) {
throw new Error("navigator.id.watch was already called");
}
@ -110,8 +111,11 @@ nsDOMIdentity.prototype = {
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
// Do not allow call of request() outside of a user input handler.
if (!util.isHandlingUserInput) {
// The only time we permit calling of request() outside of a user
// input handler is when we are handling the (deprecated) get() or
// getVerifiedEmail() calls, which make use of an RP context
// marked as _internal.
if (!util.isHandlingUserInput && !aOptions._internal) {
return;
}
@ -166,6 +170,70 @@ nsDOMIdentity.prototype = {
this._identityInternal._mm.sendAsyncMessage("Identity:RP:Logout", message);
},
/*
* Get an assertion. This function is deprecated. RPs are
* encouraged to use the observer API instead (watch + request).
*/
get: function nsDOMIdentity_get(aCallback, aOptions) {
var opts = {};
aOptions = aOptions || {};
// We use the observer API (watch + request) to implement get().
// Because the caller can call get() and getVerifiedEmail() as
// many times as they want, we lift the restriction that watch() can
// only be called once.
this._rpWatcher = null;
// This flag tells internal_api.js (in the shim) to record in the
// login parameters whether the assertion was acquired silently or
// with user interaction.
opts._internal = true;
opts.privacyPolicy = aOptions.privacyPolicy || undefined;
opts.termsOfService = aOptions.termsOfService || undefined;
opts.privacyURL = aOptions.privacyURL || undefined;
opts.tosURL = aOptions.tosURL || undefined;
opts.siteName = aOptions.siteName || undefined;
opts.siteLogo = aOptions.siteLogo || undefined;
if (checkDeprecated(aOptions, "silent")) {
// Silent has been deprecated, do nothing. Placing the check here
// prevents the callback from being called twice, once with null and
// once after internalWatch has been called. See issue #1532:
// https://github.com/mozilla/browserid/issues/1532
if (aCallback) {
setTimeout(function() { aCallback(null); }, 0);
}
return;
}
// Get an assertion by using our observer api: watch + request.
var self = this;
this.watch({
oncancel: function get_oncancel() {
if (aCallback) {
aCallback(null);
aCallback = null;
}
},
onlogin: function get_onlogin(assertion, internalParams) {
if (assertion && aCallback && internalParams && !internalParams.silent) {
aCallback(assertion);
aCallback = null;
}
},
onlogout: function get_onlogout() {},
onready: function get_onready() {
self.request(opts);
}
});
},
getVerifiedEmail: function nsDOMIdentity_getVerifiedEmail(aCallback) {
Cu.reportError("WARNING: getVerifiedEmail has been deprecated");
this.get(aCallback, {});
},
/**
* Identity Provider (IDP) Provisioning APIs
*/
@ -324,16 +392,22 @@ nsDOMIdentity.prototype = {
case "Identity:RP:Watch:OnLogin":
// Do we have a watcher?
if (!this._rpWatcher) {
dump("WARNING: Received OnLogin message, but there is no RP watcher\n");
return;
}
if (this._rpWatcher.onlogin) {
this._rpWatcher.onlogin(msg.assertion);
if (this._rpWatcher._internal) {
this._rpWatcher.onlogin(msg.assertion, msg._internalParams);
} else {
this._rpWatcher.onlogin(msg.assertion);
}
}
break;
case "Identity:RP:Watch:OnLogout":
// Do we have a watcher?
if (!this._rpWatcher) {
dump("WARNING: Received OnLogout message, but there is no RP watcher\n");
return;
}
@ -344,6 +418,7 @@ nsDOMIdentity.prototype = {
case "Identity:RP:Watch:OnReady":
// Do we have a watcher?
if (!this._rpWatcher) {
dump("WARNING: Received OnReady message, but there is no RP watcher\n");
return;
}
@ -354,6 +429,7 @@ nsDOMIdentity.prototype = {
case "Identity:RP:Request:OnCancel":
// Do we have a watcher?
if (!this._rpWatcher) {
dump("WARNING: Received OnCancel message, but there is no RP watcher\n");
return;
}
@ -432,7 +508,6 @@ nsDOMIdentity.prototype = {
// window origin
message.origin = this._origin;
dump("nsDOM message: " + JSON.stringify(message) + "\n");
return message;
},

View File

@ -47,6 +47,9 @@ function makeMessageObject(aRpCaller) {
// loggedInUser can be undefined, null, or a string
options.loggedInUser = aRpCaller.loggedInUser;
// Special flag for internal calls
options._internal = aRpCaller._internal;
Object.keys(aRpCaller).forEach(function(option) {
// Duplicate the callerobject, scrubbing out functions and other
// internal variables (like _mm, the message manager object)
@ -63,7 +66,6 @@ function makeMessageObject(aRpCaller) {
throw new Error(err);
}
dump("message object is: " + JSON.stringify(options) + "\n");
return options;
}
@ -128,7 +130,6 @@ IDService.prototype = {
*/
watch: function watch(aRpCaller) {
// store the caller structure and notify the UI observers
dump("RP - watch: " + JSON.stringify(aRpCaller) + "\n");
this._rpFlows[aRpCaller.id] = aRpCaller;
let options = makeMessageObject(aRpCaller);
@ -177,14 +178,14 @@ IDService.prototype = {
* following functions (doLogin, doLogout, or doReady)
*/
doLogin: function doLogin(aRpCallerId, aAssertion) {
doLogin: function doLogin(aRpCallerId, aAssertion, aInternalParams) {
let rp = this._rpFlows[aRpCallerId];
if (!rp) {
dump("WARNING: doLogin found no rp to go with callerId " + aRpCallerId + "\n");
return;
}
rp.doLogin(aAssertion);
rp.doLogin(aAssertion, aInternalParams);
},
doLogout: function doLogout(aRpCallerId) {