Bug 823751 - When persona login in the Trusty UI is canceled, fire the RP's oncancel() callback; r=benadida, a=bb+

This commit is contained in:
Jed Parsons 2013-01-10 09:56:10 +01:00
parent 5d94d28846
commit 56eb53bf49
4 changed files with 97 additions and 58 deletions

View File

@ -158,6 +158,8 @@ let Pipe = {
// kIdentityShimFile, where it is used to access the BrowserID object
// and its internal API.
let content = GaiaInterface.getContent();
let mm = null;
let uuid = getRandomId();
if (!content) {
log("ERROR: what the what? no content window?");
@ -165,73 +167,90 @@ let Pipe = {
return;
}
// Prepare a message for gaia. The parameter showUI signals
// whether user interaction is needed. If it is, gaia will open a
// dialog; if not, a hidden iframe. In each case, BrowserID is
// available in the context.
let id = kOpenIdentityDialog + "-" + getRandomId();
let detail = {
type: kOpenIdentityDialog,
showUI: aGaiaOptions.showUI || false,
id: id
};
function removeMessageListeners() {
if (mm) {
mm.removeMessageListener(kIdentityDelegateFinished, identityDelegateFinished);
mm.removeMessageListener(kIdentityControllerDoMethod, aMessageCallback);
}
}
function identityDelegateFinished() {
removeMessageListeners();
let detail = {
type: kReceivedIdentityAssertion,
showUI: aGaiaOptions.showUI || false,
id: kReceivedIdentityAssertion + "-" + uuid
};
log('telling gaia to close the dialog');
// tell gaia to close the dialog
GaiaInterface.sendChromeEvent(detail);
}
// When gaia signals back with a mozContentEvent containing the
// unique id we created, we know the window is ready. We then inject
// the magic javascript (kIdentityShimFile) that will give the content
// the superpowers it needs to communicate back with this code.
content.addEventListener("mozContentEvent", function getAssertion(evt) {
// Make sure the message is really for us
let msg = evt.detail;
if (msg.id != id) {
if (!msg.id.match(uuid)) {
return;
}
// We only need to catch the first mozContentEvent from the
// iframe or popup, so we remove the listener right away.
content.removeEventListener("mozContentEvent", getAssertion);
switch (msg.id) {
case kOpenIdentityDialog + '-' + uuid:
if (msg.type === 'cancel') {
// The user closed the dialog. Clean up and call cancel.
content.removeEventListener("mozContentEvent", getAssertion);
removeMessageListeners();
aMessageCallback({json: {method: "cancel"}});
} else {
// The window has opened. Inject the identity shim file containing
// the callbacks in the content script. This could be either the
// visible popup that the user interacts with, or it could be an
// invisible frame.
let frame = evt.detail.frame;
let frameLoader = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
mm = frameLoader.messageManager;
try {
mm.loadFrameScript(kIdentityShimFile, true);
log("Loaded shim " + kIdentityShimFile + "\n");
} catch (e) {
log("Error loading ", kIdentityShimFile, " as a frame script: ", e);
}
// Try to load the identity shim file containing the callbacks
// in the content script. This could be either the visible
// popup that the user interacts with, or it could be an invisible
// frame.
let frame = evt.detail.frame;
let frameLoader = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
let mm = frameLoader.messageManager;
try {
mm.loadFrameScript(kIdentityShimFile, true);
log("Loaded shim " + kIdentityShimFile + "\n");
} catch (e) {
log("Error loading ", kIdentityShimFile, " as a frame script: ", e);
// There are two messages that the delegate can send back: a "do
// method" event, and a "finished" event. We pass the do-method
// events straight to the caller for interpretation and handling.
// If we receive a "finished" event, then the delegate is done, so
// we shut down the pipe and clean up.
mm.addMessageListener(kIdentityControllerDoMethod, aMessageCallback);
mm.addMessageListener(kIdentityDelegateFinished, identityDelegateFinished);
mm.sendAsyncMessage(aGaiaOptions.message, aRpOptions);
}
break;
case kReceivedIdentityAssertion + '-' + uuid:
// Received our assertion. The message manager callbacks will handle
// communicating back to the IDService. All we have to do is remove
// this listener.
content.removeEventListener("mozContentEvent", getAssertion);
break;
default:
log("ERROR - Unexpected message: id=" + msg.id + ", type=" + msg.type + ", errorMsg=" + msg.errorMsg);
break;
}
// There are two messages that the delegate can send back: a "do
// method" event, and a "finished" event. We pass the do-method
// events straight to the caller for interpretation and handling.
// If we receive a "finished" event, then the delegate is done, so
// we shut down the pipe and clean up.
mm.addMessageListener(kIdentityControllerDoMethod, aMessageCallback);
mm.addMessageListener(kIdentityDelegateFinished, function identityDelegateFinished() {
// clean up listeners
mm.removeMessageListener(kIdentityDelegateFinished, identityDelegateFinished);
mm.removeMessageListener(kIdentityControllerDoMethod, aMessageCallback);
let id = kReceivedIdentityAssertion + "-" + getRandomId();
let detail = {
type: kReceivedIdentityAssertion,
showUI: aGaiaOptions.showUI || false,
id: id
};
log('telling gaia to close the dialog');
// tell gaia to close the dialog
GaiaInterface.sendChromeEvent(detail);
});
mm.sendAsyncMessage(aGaiaOptions.message, aRpOptions);
});
// Tell gaia to open the identity iframe or trusty popup
// Tell gaia to open the identity iframe or trusty popup. The parameter
// showUI signals whether user interaction is needed. If it is, gaia will
// open a dialog; if not, a hidden iframe. In each case, BrowserID is
// available in the context.
let detail = {
type: kOpenIdentityDialog,
showUI: aGaiaOptions.showUI || false,
id: kOpenIdentityDialog + "-" + uuid
};
GaiaInterface.sendChromeEvent(detail);
}
@ -316,6 +335,10 @@ this.SignInToWebsiteController = {
IdentityService.doLogout(aRpId);
break;
case "cancel":
IdentityService.doCancel(aRpId);
break;
default:
log("WARNING: wonky method call:", message.method);
break;

View File

@ -127,6 +127,12 @@ RPWatchContext.prototype = {
this._mm.sendAsyncMessage("Identity:RP:Watch:OnReady", message);
},
doCancel: function RPWatchContext_oncancel() {
log("doCancel: " + this.id);
let message = new IDDOMMessage({id: this.id});
this._mm.sendAsyncMessage("Identity:RP:Watch:OnCancel", message);
},
doError: function RPWatchContext_onerror(aMessage) {
log("doError: " + aMessage);
}

View File

@ -439,7 +439,7 @@ nsDOMIdentity.prototype = {
this._rpWatcher.onready();
}
break;
case "Identity:RP:Request:OnCancel":
case "Identity:RP:Watch:OnCancel":
// Do we have a watcher?
if (!this._rpWatcher) {
dump("WARNING: Received OnCancel message, but there is no RP watcher\n");
@ -598,7 +598,7 @@ nsDOMIdentityInternal.prototype = {
"Identity:RP:Watch:OnLogin",
"Identity:RP:Watch:OnLogout",
"Identity:RP:Watch:OnReady",
"Identity:RP:Request:OnCancel",
"Identity:RP:Watch:OnCancel",
"Identity:IDP:CallBeginProvisioningCallback",
"Identity:IDP:CallGenKeyPairCallback",
"Identity:IDP:CallBeginAuthenticationCallback",

View File

@ -208,6 +208,16 @@ IDService.prototype = {
rp.doReady();
},
doCancel: function doCancel(aRpCallerId) {
let rp = this._rpFlows[aRpCallerId];
if (!rp) {
dump("WARNING: doCancel found no rp to go with callerId " + aRpCallerId + "\n");
return;
}
rp.doCancel();
},
/*
* XXX Bug 804229: Implement Identity Provider Functions