diff --git a/resources/static/dialog/controllers/dialog_controller.js b/resources/static/dialog/controllers/dialog_controller.js index 6a16e5af9f9a6f76bbc9d23982b07304e60ca208..88fede3a584dc58aa186569188c3b234d146880e 100644 --- a/resources/static/dialog/controllers/dialog_controller.js +++ b/resources/static/dialog/controllers/dialog_controller.js @@ -65,8 +65,14 @@ self.onsuccess = null; self.onerror = null; - win.setupChannel(self); - self.stateMachine(); + try { + win.setupChannel(self); + self.stateMachine(); + } catch (e) { + self.renderError("error.ejs", { + action: errors.relaySetup + }); + } }, getVerifiedEmail: function(origin_url, onsuccess, onerror) { diff --git a/resources/static/dialog/resources/channel.js b/resources/static/dialog/resources/channel.js index eb235bd41bab1dd453d4de17eb167e2325956637..859d641b8b266a4bb6a9c5719c1cc3af5b893030 100644 --- a/resources/static/dialog/resources/channel.js +++ b/resources/static/dialog/resources/channel.js @@ -1,5 +1,5 @@ /*jshint browsers:true, forin: true, laxbreak: true */ -/*global alert:true, setupNativeChannel:true, setupIFrameChannel:true*/ +/*global BrowserID: true*/ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -68,7 +68,7 @@ function setupNativeChannel(controller) { nav.id.channel.registerController(controller); - }; + } function setupIFrameChannel(controller) { // TODO - Add a check for whether the dialog was opened by another window @@ -91,17 +91,19 @@ onCompleteCallback = onComplete; controller.getVerifiedEmail(origin, onsuccess, onerror); }); + win.location.hash = ''; } - - win.location.hash = ''; - }; + else { + throw "relay frame not found"; + } + } function open(controller) { if (nav.id && nav.id.channel) setupNativeChannel(controller); else setupIFrameChannel(controller); - }; + } function init(options) { @@ -125,9 +127,12 @@ * @method init */ init: init, + /** * Open the channel. * @method open + * @param {object} options - contains: + * * options.getVerifiedEmail {function} - function to /get */ open: open }; diff --git a/resources/static/dialog/resources/error-messages.js b/resources/static/dialog/resources/error-messages.js index a35b91a18c869844e0aae0fbb8f186b1b402a7c7..3f6aeefc37aaea3b8209523edef1df81bd182377 100644 --- a/resources/static/dialog/resources/error-messages.js +++ b/resources/static/dialog/resources/error-messages.js @@ -1,3 +1,4 @@ +/*global BrowserID: true*/ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -73,6 +74,11 @@ BrowserID.Errors = (function(){ title: "Registration Failed" }, + relaySetup: { + title: "Establishing Relay", + message: "Relay frame could not be found" + }, + requestPasswordReset: { title: "Resetting Password" }, diff --git a/resources/static/dialog/test/qunit/controllers/dialog_controller_unit_test.js b/resources/static/dialog/test/qunit/controllers/dialog_controller_unit_test.js index de0ce24219bcbf41bc3b679e3cc0924d90c6dc79..47be43214a20d1386b239295b1d27d35b7305928 100644 --- a/resources/static/dialog/test/qunit/controllers/dialog_controller_unit_test.js +++ b/resources/static/dialog/test/qunit/controllers/dialog_controller_unit_test.js @@ -37,24 +37,33 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/controllers/dialog_controller", function() { "use strict"; - var controller, el + var controller, + el, + channelError = false; function reset() { el = $("#controller_head"); el.find("#formWrap .contents").html(""); el.find("#wait .contents").html(""); el.find("#error .contents").html(""); + + channelError = false; + } + + function initController() { + controller = el.dialog({ + window: { + setupChannel: function() { + if (channelError) throw "Channel error"; + } + } + }).controller(); } module("controllers/dialog_controller", { setup: function() { reset(); - - controller = el.dialog({ - window: { - setupChannel: function() {} - } - }).controller(); + initController(); }, teardown: function() { @@ -63,17 +72,27 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con } }); + test("initialization with channel error", function() { + controller.destroy(); + reset(); + channelError = true; + + initController(); + + ok($("#error .contents").text().length, "contents have been written"); + }); + test("doOffline", function() { controller.doOffline(); - ok($("#error .contents").length, "contents have been written"); - ok($("#error #offline").length, "offline error message has been written"); + ok($("#error .contents").text().length, "contents have been written"); + ok($("#error #offline").text().length, "offline error message has been written"); }); test("doXHRError while online, no network info given", function() { controller.doXHRError(); - ok($("#error .contents").length, "contents have been written"); - ok($("#error #action").length, "action contents have been written"); - equal($("#error #network").length, 0, "no network contents to be written"); + ok($("#error .contents").text().length, "contents have been written"); + ok($("#error #action").text().length, "action contents have been written"); + equal($("#error #network").text().length, 0, "no network contents to be written"); }); test("doXHRError while online, network info given", function() { @@ -83,9 +102,9 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con url: "browserid.org/verify" } }); - ok($("#error .contents").length, "contents have been written"); - ok($("#error #action").length, "action contents have been written"); - ok($("#error #network").length, "network contents have been written"); + ok($("#error .contents").text().length, "contents have been written"); + ok($("#error #action").text().length, "action contents have been written"); + ok($("#error #network").text().length, "network contents have been written"); }); test("doXHRError while offline does not update contents", function() { @@ -93,7 +112,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con $("#error #action").remove(); controller.doXHRError(); - ok(!$("#error #action").length, "XHR error is not reported if the user is offline."); + ok(!$("#error #action").text().length, "XHR error is not reported if the user is offline."); }); test("window.unload causes setStagedOnBehalfOf data to be cleared", function() { diff --git a/resources/static/dialog/test/qunit/resources/channel_unit_test.js b/resources/static/dialog/test/qunit/resources/channel_unit_test.js index da72df2344699d499d668ad582b1640bd98c6c5a..cd9621638a5b131270a3296f3455fd7b18fa7f1b 100644 --- a/resources/static/dialog/test/qunit/resources/channel_unit_test.js +++ b/resources/static/dialog/test/qunit/resources/channel_unit_test.js @@ -116,7 +116,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/channel", func stop(); }); - test("IFRAME channel with error", function() { + test("IFRAME channel relaying error", function() { channel.init({ window: winMock, navigator: navMock @@ -133,5 +133,30 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/channel", func stop(); }); + test("IFRAME channel with error on open", function() { + var winMockWithoutRelay = $.extend(true, {}, winMock); + delete winMockWithoutRelay.opener.frames.browserid_relay_1234; + + channel.init({ + window: winMockWithoutRelay, + navigator: navMock + }); + + // Do this manually so we can test if getVerifiedEmail gets called. + try { + channel.open({ + getVerifiedEmail: function(origin, onsuccess, onerror) { + ok(false, "getVerifiedEmail should never be called on channel error"); + start(); + } + }); + } catch(e) { + equal(e.toString(), "relay frame not found", "exception caught when trying to open channel that does not exist"); + start(); + } + + stop(); + }); + });