From 238e83de720760afc3614128c175927a2e525a3b Mon Sep 17 00:00:00 2001 From: Lloyd Hilaiel <lloyd@hilaiel.com> Date: Fri, 16 Mar 2012 18:35:33 -0600 Subject: [PATCH] ensure login/logout events are not erroneously sent multiple times. --- example/rp/index.html | 9 ++++++++ .../static/communication_iframe/start.js | 19 ++++++++++++++- .../static/dialog/controllers/actions.js | 4 ++-- resources/static/dialog/resources/state.js | 2 +- resources/static/include_js/include.js | 23 +++++++++++++++---- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/example/rp/index.html b/example/rp/index.html index 17270fcb0..924e8f350 100644 --- a/example/rp/index.html +++ b/example/rp/index.html @@ -97,6 +97,12 @@ pre { <script src="https://browserid.org/include.js"></script> <script> +function loggit() { + try { + console.log.apply(console, arguments); + } catch(e) {} +} + // a function to check an assertion against the server function checkAssertion(assertion) { $.ajax({ @@ -118,15 +124,18 @@ function checkAssertion(assertion) { }; navigator.id.addEventListener('login', function(event) { + loggit("login event"); checkAssertion(event.assertion); }); navigator.id.addEventListener('logout', function(event) { + loggit("logout event"); var txt = 'got event at ' + (new Date).toString(); $(".logoutEvents > pre").text(txt); }); navigator.id.addEventListener('loginCanceled', function(event) { + loggit("loginCanceled"); var txt = 'got event at ' + (new Date).toString(); $(".loginCanceledEvents > pre").text(txt); }); diff --git a/resources/static/communication_iframe/start.js b/resources/static/communication_iframe/start.js index e213d0261..2c87525c6 100644 --- a/resources/static/communication_iframe/start.js +++ b/resources/static/communication_iframe/start.js @@ -28,9 +28,17 @@ var loggedInUser = undefined; + // the controlling page may "pause" the iframe when someone else (the dialog) + // is supposed to emit events + var pause = false; + function checkAndEmit(oncomplete) { - // XXX: seemless re-certification! + console.log('checking', pause, localStorage.loggedIn); + if (pause) return; + + // this will re-certify the user if neccesary user.getSilentAssertion(loggedInUser, function(email, assertion) { + console.log(email, assertion); if (email) { // only send login events when the assertion is defined - when // the 'loggedInUser' is already logged in, it's false - that is @@ -75,4 +83,13 @@ chan.notify({ method: 'logout' }); } }); + + chan.bind("dialog_running", function(trans, params) { + pause = true; + }); + + chan.bind("dialog_complete", function(trans, params) { + pause = false; + checkAndEmit(); + }); }()); diff --git a/resources/static/dialog/controllers/actions.js b/resources/static/dialog/controllers/actions.js index 334bcbd15..98876183f 100644 --- a/resources/static/dialog/controllers/actions.js +++ b/resources/static/dialog/controllers/actions.js @@ -113,12 +113,12 @@ BrowserID.Modules.Actions = (function() { }, self.getErrorDialog(errors.getAssertion)); }, - doAssertionGenerated: function(assertion) { + doAssertionGenerated: function(o) { // Clear onerror before the call to onsuccess - the code to onsuccess // calls window.close, which would trigger the onerror callback if we // tried this afterwards. onerror = null; - if(onsuccess) onsuccess(assertion); + if(onsuccess) onsuccess(o); }, doNotMe: function() { diff --git a/resources/static/dialog/resources/state.js b/resources/static/dialog/resources/state.js index 11ebf81e0..7a3e7d1d5 100644 --- a/resources/static/dialog/resources/state.js +++ b/resources/static/dialog/resources/state.js @@ -260,7 +260,7 @@ BrowserID.State = (function() { } else { storage.setLoggedIn(user.getOrigin(), self.email); - startAction("doAssertionGenerated", info.assertion); + startAction("doAssertionGenerated", { assertion: info.assertion, email: self.email }); } } else { diff --git a/resources/static/include_js/include.js b/resources/static/include_js/include.js index d9dfc7821..01a67fe39 100644 --- a/resources/static/include_js/include.js +++ b/resources/static/include_js/include.js @@ -918,10 +918,6 @@ }; }()); - /** - * The meat and potatoes of the verified email protocol - */ - if (!navigator.id) { navigator.id = {}; } @@ -1123,6 +1119,10 @@ return; } + // notify the iframe that the dialog is running so we + // don't do duplicative work + if (commChan) commChan.notify({ method: 'dialog_running' }); + w = WinChan.open({ url: ipServer + '/sign_in', relay_url: ipServer + '/relay', @@ -1132,9 +1132,22 @@ params: options } }, function(err, r) { + // unpause the iframe to detect future changes in login state + if (commChan) { + // update the loggedInUser in the case that an assertion was generated, as + // this will prevent the comm iframe from thinking that state has changed + // and generating a new assertion. IF, however, this request is not a success, + // then we do not change the loggedInUser - and we will let the comm frame determine + // if generating a logout event is the right thing to do + if (!err && r && r.email) { + commChan.notify({ method: 'loggedInUser', params: r.email }); + } + commChan.notify({ method: 'dialog_complete' }); + } + // clear the window handle w = undefined; - if (!err && r) emitEvent('login', { assertion: r }); + if (!err && r && r.assertion) emitEvent('login', { assertion: r.assertion }); else emitEvent('loginCanceled'); }); }; -- GitLab