diff --git a/browserid/static/dialog/resources/channel.js b/browserid/static/dialog/resources/channel.js index b926fd948830f397ef3c24ba878bf546a94af246..db44e0818b55467c16b1665be7aa47a0c908d4e4 100644 --- a/browserid/static/dialog/resources/channel.js +++ b/browserid/static/dialog/resources/channel.js @@ -52,8 +52,26 @@ (function() { + function getUrlVars() { + var hashes = window.location.href.slice( + window.location.href.indexOf('#') + 1).split('&'); + vars = {}; + + for(var i = 0, item, hash; item=hashes[i]; ++i) { + hash = hashes[i].split('='); + vars[hash[0]] = hash[1]; + } + + return vars; + } + + function getRelayName() { + var vars = getUrlVars(); + return vars.relay; + } + function getRelayWindow() { - var frameWindow = window.opener.frames['browserid_relay']; + var frameWindow = window.opener.frames[getRelayName()]; return frameWindow; } diff --git a/browserid/static/include.js b/browserid/static/include.js index 3ac3ee2e7f68a22d8d12a185509e2149b02b087a..1abf127ab87f7c0bb7526c611c7dd25748420a51 100644 --- a/browserid/static/include.js +++ b/browserid/static/include.js @@ -562,7 +562,7 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) })(); - var chan, w, iframe; + var chan, w, iframe, relayframe_opencount=0; // this is for calls that are non-interactive function _open_hidden_iframe(doc) { @@ -573,20 +573,32 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) return iframe; } - function _open_relay_frame(doc) { + function _get_relayframe_name() { + var framename = 'browserid_relay' + relayframe_opencount; + relayframe_opencount++; + return framename; + } + + function _open_relayframe(framename) { + var doc = window.document; var iframe = doc.createElement("iframe"); - iframe.setAttribute('name', 'browserid_relay'); + iframe.setAttribute('name', framename); iframe.setAttribute('src', ipServer + "/relay"); iframe.style.display = "none"; doc.body.appendChild(iframe); + return iframe; } - function _open_window() { - // FIXME: need to pass the location in a more trustworthy fashion - // HOW? set up a direct reference to the open window + function _open_window(framename) { + // we open the window initially blank, and only after our relay frame has + // been constructed do we update the location. This is done because we + // must launch the window inside a click handler, but we should wait to + // start loading it until our relay iframe is instantiated and ready. + // see issue #287 & #286 return window.open( - ipServer + "/sign_in", "_mozid_signin", + "about:blank", + "_mozid_signin", isMobile ? undefined : "menubar=0,location=0,resizable=0,scrollbars=0,status=0,dialog=1,width=520,height=350"); } @@ -596,6 +608,25 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) } } + function _attach_event(element, name, listener) { + if (element.addEventListener) { + element.addEventListener(name, listener, false); + } + else if(element.attachEvent) { + // IE < 9 + element.attachEvent(name, listener); + } + } + + function _detatch_event(element, name, listener) { + if (element.removeEventListener) { + element.removeEventListener(name, listener, false); + } + else if(element.detachEvent) { + element.detachEvent(name, listener); + } + } + // keep track of these so that we can re-use/re-focus an already open window. navigator.id.getVerifiedEmail = function(callback) { if (w) { @@ -604,23 +635,29 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) return; } - var doc = window.document; - w = _open_window(); - iframe = _open_relay_frame(doc); + var framename = _get_relayframe_name(); + var iframe = _open_relayframe(framename); + w = _open_window(framename); // if the RP window closes, close the dialog as well. - if (window.addEventListener) { - window.addEventListener('unload', _close_window, false); - } - else if(window.attachEvent) { - // IE < 9 - window.attachEvent('unload', _close_window); - } + _attach_event(window, 'unload', _close_window); // clean up a previous channel that never was reaped if (chan) chan.destroy(); - chan = Channel.build({window: iframe.contentWindow, origin: ipServer, scope: "mozid"}); - + chan = Channel.build({ + window: iframe.contentWindow, + origin: ipServer, + scope: "mozid", + onReady: function() { + // We have to change the name of the relay frame every time or else Firefox + // has a problem re-attaching new iframes with the same name. Code inside + // of frames with the same name sometimes does not get run. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=350023 + w.location = ipServer + "/sign_in#relay=" + framename; + w.focus(); + } + }); + function cleanup() { chan.destroy(); chan = null; @@ -631,13 +668,7 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) iframe.parentNode.removeChild(iframe); iframe = null; - - if (window.removeEventListener) { - window.removeEventListener('unload', _close_window, false); - } - else if(window.detachEvent) { - window.detachEvent('unload', _close_window); - } + _detatch_event(window, 'unload', _close_window); } chan.call({ @@ -758,7 +789,6 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) method: method, params: args, success: function(rv) { - console.log(method + " channel returned: rv is " + rv); if (onsuccess) { onsuccess(rv); } diff --git a/browserid/static/relay/relay.js b/browserid/static/relay/relay.js index 962d2c311cf7cdf8ef5ea7f89bf3b508437874aa..46212cc2479faef04dc09da5e978b792bbc7c67a 100644 --- a/browserid/static/relay/relay.js +++ b/browserid/static/relay/relay.js @@ -44,20 +44,14 @@ }; var ipServer = "https://browserid.org", + transaction, + origin, chan = Channel.build( { window: window.parent, origin: "*", scope: "mozid" - } ), - transaction, - origin; - - chan.bind("getVerifiedEmail", function(trans, s) { - origin = trans.origin; - trans.delayReturn(true); + } ); - transaction = trans; - }); window.register_dialog = function(callback) { // register the dialog, tell the dialog what the origin is. @@ -78,4 +72,12 @@ } } }; + + chan.bind("getVerifiedEmail", function(trans, s) { + origin = trans.origin; + trans.delayReturn(true); + + transaction = trans; + }); + }());