diff --git a/browserid/static/include.js b/browserid/static/include.js index 797e639a89ec7fad08e096e2b90fc4e61971fb77..dda4e98711b56c8bd343d81255c19a65c05d5304 100644 --- a/browserid/static/include.js +++ b/browserid/static/include.js @@ -35,15 +35,8 @@ // this is the file that the RP includes to shim in the // navigator.id.getVerifiedEmail() function - -if (!navigator.id) { - navigator.id = {}; -} - -if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) -{ - var ipServer = "https://browserid.org"; - var isMobile = navigator.userAgent.indexOf('Fennec/') != -1; +(function() { + "use strict"; // local embedded copy of jschannel: http://github.com/mozilla/jschannel var Channel = (function() { @@ -561,8 +554,41 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) }; })(); + function getInternetExplorerVersion() { + var rv = -1; // Return value assumes failure. + if (navigator.appName == 'Microsoft Internet Explorer') { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) + rv = parseFloat(RegExp.$1); + } + + return rv; + } + + function explicitNosupport() { + var ieVersion = getInternetExplorerVersion(); + var ieNosupport = ieVersion > -1 && ieVersion < 9; + + if(ieNosupport) { + alert("Unfortunately, your version of Internet Explorer is not supported.\n" + + 'Please upgrade to Internet Explorer 9 or turn off "Compatibility View".'); + } + + return ieNosupport; + } + + function checkRequirements() { + var localStorage = 'localStorage' in window && window['localStorage'] !== null; + var postMessage = !!window.postMessage; + var explicitNo = explicitNosupport() + + if(!explicitNo && !(localStorage && postMessage)) { + alert("Unfortunately, your browser does not meet the minimum HTML5 support required for BrowserID."); + } - var chan, w, iframe; + return localStorage && postMessage && !(explicitNo); + } // this is for calls that are non-interactive function _open_hidden_iframe(doc) { @@ -602,13 +628,7 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) return window.open( "about:blank", "_mozid_signin", - isMobile ? undefined : "menubar=0,location=0,resizable=0,scrollbars=0,status=0,dialog=1,width=700,height=375"); - } - - function _close_window() { - if (w) { - w.close(); - } + isFennec ? undefined : "menubar=0,location=0,resizable=0,scrollbars=0,status=0,dialog=1,width=700,height=375"); } function _attach_event(element, name, listener) { @@ -630,205 +650,226 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) } } - // keep track of these so that we can re-use/re-focus an already open window. - navigator.id.getVerifiedEmail = function(callback) { - if (w) { - // if there is already a window open, just focus the old window. - w.focus(); - return; - } + /** + * The meat and potatoes of the verified email protocol + */ - var frameid = _get_relayframe_id(); - var iframe = _open_relayframe("browserid_relay_" + frameid); - w = _open_window(); - - // if the RP window closes, close the dialog as well. - _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", - 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#" + frameid; - w.focus(); - } - }); - function cleanup() { - chan.destroy(); - chan = null; + if (!navigator.id) { + navigator.id = {}; + } - w.close(); - w = null; + if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed) { + var ipServer = "https://browserid.org"; + var isFennec = navigator.userAgent.indexOf('Fennec/') != -1; - iframe.parentNode.removeChild(iframe); - iframe = null; + var chan, w, iframe; - _detatch_event(window, 'unload', _close_window); - } + // keep track of these so that we can re-use/re-focus an already open window. + navigator.id.getVerifiedEmail = function(callback) { + if(!checkRequirements()) { + return; + } - chan.call({ - method: "getVerifiedEmail", - success: function(rv) { - if (callback) { - // return the string representation of the JWT, the client is responsible for unpacking it. - callback(rv); - } - cleanup(); - }, - error: function(code, msg) { - // XXX: we don't make the code and msg available to the user. - if (callback) callback(null); - cleanup(); + if (w) { + // if there is already a window open, just focus the old window. + w.focus(); + return; } - }); - }; - -/* - // preauthorize a particular email - // FIXME: lots of cut-and-paste code here, need to refactor - // not refactoring now because experimenting and don't want to break existing code - navigator.id.preauthEmail = function(email, onsuccess, onerror) { - var doc = window.document; - var iframe = _create_iframe(doc); - // clean up a previous channel that never was reaped - if (chan) chan.destroy(); - chan = Channel.build({window: iframe.contentWindow, origin: ipServer, scope: "mozid"}); + var frameid = _get_relayframe_id(); + var iframe = _open_relayframe("browserid_relay_" + frameid); + w = _open_window(); + + // if the RP window closes, close the dialog as well. + _attach_event(window, 'unload', cleanup); + + // clean up a previous channel that never was reaped + if (chan) chan.destroy(); + 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#" + frameid; + w.focus(); + } + }); + + function cleanup() { + chan.destroy(); + chan = null; - function cleanup() { - chan.destroy(); - chan = undefined; - doc.body.removeChild(iframe); - } + w.close(); + w = null; - chan.call({ - method: "preauthEmail", - params: email, - success: function(rv) { - onsuccess(rv); - cleanup(); - }, - error: function(code, msg) { - if (onerror) onerror(code, msg); - cleanup(); + iframe.parentNode.removeChild(iframe); + iframe = null; + + _detatch_event(window, 'unload', cleanup); } - }); - }; - */ - // get a particular verified email - // FIXME: needs to ditched for now until fixed + chan.call({ + method: "getVerifiedEmail", + success: function(rv) { + if (callback) { + // return the string representation of the JWT, the client is responsible for unpacking it. + callback(rv); + } + cleanup(); + }, + error: function(code, msg) { + // XXX: we don't make the code and msg available to the user. + if (callback) callback(null); + cleanup(); + } + }); + }; + /* - navigator.id.getSpecificVerifiedEmail = function(email, token, onsuccess, onerror) { - var doc = window.document; + // preauthorize a particular email + // FIXME: lots of cut-and-paste code here, need to refactor + // not refactoring now because experimenting and don't want to break existing code + navigator.id.preauthEmail = function(email, onsuccess, onerror) { + var doc = window.document; + var iframe = _create_iframe(doc); + + // clean up a previous channel that never was reaped + if (chan) chan.destroy(); + chan = Channel.build({window: iframe.contentWindow, origin: ipServer, scope: "mozid"}); + + function cleanup() { + chan.destroy(); + chan = undefined; + doc.body.removeChild(iframe); + } - // if we have a token, we should not be opening a window, rather we should be - // able to do this entirely through IFRAMEs - var w; - if (token) { - var iframe = _create_iframe(doc); - w = iframe.contentWindow; - } else { - _open_window(); - _open_relay_frame(doc); - } + chan.call({ + method: "preauthEmail", + params: email, + success: function(rv) { + onsuccess(rv); + cleanup(); + }, + error: function(code, msg) { + if (onerror) onerror(code, msg); + cleanup(); + } + }); + }; + */ - // clean up a previous channel that never was reaped - if (chan) chan.destroy(); - chan = Channel.build({window: w, origin: ipServer, scope: "mozid"}); + // get a particular verified email + // FIXME: needs to ditched for now until fixed + /* + navigator.id.getSpecificVerifiedEmail = function(email, token, onsuccess, onerror) { + var doc = window.document; - function cleanup() { - chan.destroy(); - chan = undefined; + // if we have a token, we should not be opening a window, rather we should be + // able to do this entirely through IFRAMEs + var w; if (token) { - // just remove the IFRAME - doc.body.removeChild(iframe); + var iframe = _create_iframe(doc); + w = iframe.contentWindow; } else { - w.close(); + _open_window(); + _open_relay_frame(doc); } - } - chan.call({ - method: "getSpecificVerifiedEmail", - params: [email, token], - success: function(rv) { - if (onsuccess) { - // return the string representation of the JWT, the client is responsible for unpacking it. - onsuccess(rv); + // clean up a previous channel that never was reaped + if (chan) chan.destroy(); + chan = Channel.build({window: w, origin: ipServer, scope: "mozid"}); + + function cleanup() { + chan.destroy(); + chan = undefined; + if (token) { + // just remove the IFRAME + doc.body.removeChild(iframe); + } else { + w.close(); } - cleanup(); - }, - error: function(code, msg) { - if (onerror) onerror(code, msg); - cleanup(); } - }); - }; - */ - function _noninteractiveCall(method, args, onsuccess, onerror) { - var doc = window.document; - iframe = _open_hidden_iframe(doc); + chan.call({ + method: "getSpecificVerifiedEmail", + params: [email, token], + success: function(rv) { + if (onsuccess) { + // return the string representation of the JWT, the client is responsible for unpacking it. + onsuccess(rv); + } + cleanup(); + }, + error: function(code, msg) { + if (onerror) onerror(code, msg); + cleanup(); + } + }); + }; + */ + + var _noninteractiveCall = function(method, args, onsuccess, onerror) { + var doc = window.document; + iframe = _open_hidden_iframe(doc); + + // clean up channel + if (chan) chan.destroy(); + chan = Channel.build({window: iframe.contentWindow, origin: ipServer, scope: "mozid"}); + + function cleanup() { + chan.destroy(); + chan = undefined; + doc.body.removeChild(iframe); + } + + chan.call({ + method: method, + params: args, + success: function(rv) { + if (onsuccess) { + onsuccess(rv); + } + cleanup(); + }, + error: function(code, msg) { + if (onerror) onerror(code, msg); + cleanup(); + } + }); + } + + // + // for now, disabling primary support. + // + + /* + // check if a valid cert exists for this verified email + // calls back with true or false + // FIXME: implement it for real, but + // be careful here because this needs to be limited + navigator.id.checkVerifiedEmail = function(email, onsuccess, onerror) { + onsuccess(false); + }; - // clean up channel - if (chan) chan.destroy(); - chan = Channel.build({window: iframe.contentWindow, origin: ipServer, scope: "mozid"}); + // generate a keypair + navigator.id.generateKey = function(onsuccess, onerror) { + _noninteractiveCall("generateKey", {}, + onsuccess, onerror); + }; - function cleanup() { - chan.destroy(); - chan = undefined; - doc.body.removeChild(iframe); - } + navigator.id.registerVerifiedEmailCertificate = function(certificate, updateURL, onsuccess, onerror) { + _noninteractiveCall("registerVerifiedEmailCertificate", + {cert:certificate, updateURL: updateURL}, + onsuccess, onerror); + }; + */ - chan.call({ - method: method, - params: args, - success: function(rv) { - if (onsuccess) { - onsuccess(rv); - } - cleanup(); - }, - error: function(code, msg) { - if (onerror) onerror(code, msg); - cleanup(); - } - }); + navigator.id._getVerifiedEmailIsShimmed = true; } +}()); - // - // for now, disabling primary support. - // - - /* - // check if a valid cert exists for this verified email - // calls back with true or false - // FIXME: implement it for real, but - // be careful here because this needs to be limited - navigator.id.checkVerifiedEmail = function(email, onsuccess, onerror) { - onsuccess(false); - }; - - // generate a keypair - navigator.id.generateKey = function(onsuccess, onerror) { - _noninteractiveCall("generateKey", {}, - onsuccess, onerror); - }; - - navigator.id.registerVerifiedEmailCertificate = function(certificate, updateURL, onsuccess, onerror) { - _noninteractiveCall("registerVerifiedEmailCertificate", - {cert:certificate, updateURL: updateURL}, - onsuccess, onerror); - }; - */ - - navigator.id._getVerifiedEmailIsShimmed = true; -}