diff --git a/include/rfb.js b/include/rfb.js index 6fcdab6f..b9db39c4 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -159,11 +159,13 @@ var RFB; this._encStats[this._encodings[i][1]] = [0, 0]; } + // NB: nothing that needs explicit teardown should be done + // before this point, since this can throw an exception try { this._display = new Display({target: this._target}); } catch (exc) { Util.Error("Display exception: " + exc); - this._updateState('fatal', "No working Display"); + throw exc; } this._keyboard = new Keyboard({target: this._focusContainer, @@ -217,9 +219,11 @@ var RFB; } else { Util.Warn("Using web-socket-js bridge. Flash version: " + Util.Flash.version); if (!Util.Flash || Util.Flash.version < 9) { - this._updateState('fatal', "WebSockets or Adobe Flash is required"); + this._cleanupSocket('fatal'); + throw new Exception("WebSockets or Adobe Flash is required"); } else if (document.location.href.substr(0, 7) === 'file://') { - this._updateState('fatal', "'file://' URL is incompatible with Adobe Flash"); + this._cleanupSocket('fatal'); + throw new Exception("'file://' URL is incompatible with Adobe Flash"); } else { this._updateState('loaded', 'noVNC ready: WebSockets emulation, ' + rmode); } @@ -398,6 +402,32 @@ var RFB; } }, + _cleanupSocket: function (state) { + if (this._sendTimer) { + clearInterval(this._sendTimer); + this._sendTimer = null; + } + + if (this._msgTimer) { + clearInterval(this._msgTimer); + this._msgTimer = null; + } + + if (this._display && this._display.get_context()) { + this._keyboard.ungrab(); + this._mouse.ungrab(); + if (state !== 'connect' && state !== 'loaded') { + this._display.defaultCursor(); + } + if (Util.get_logging() !== 'debug' || state === 'loaded') { + // Show noVNC logo on load and when disconnected, unless in + // debug mode + this._display.clear(); + } + } + + this._sock.close(); + }, /* * Page states: @@ -432,31 +462,7 @@ var RFB; */ if (state in {'disconnected': 1, 'loaded': 1, 'connect': 1, 'disconnect': 1, 'failed': 1, 'fatal': 1}) { - - if (this._sendTimer) { - clearInterval(this._sendTimer); - this._sendTimer = null; - } - - if (this._msgTimer) { - clearInterval(this._msgTimer); - this._msgTimer = null; - } - - if (this._display && this._display.get_context()) { - this._keyboard.ungrab(); - this._mouse.ungrab(); - if (state !== 'connect' && state !== 'loaded') { - this._display.defaultCursor(); - } - if (Util.get_logging() !== 'debug' || state === 'loaded') { - // Show noVNC logo on load and when disconnected, unless in - // debug mode - this._display.clear(); - } - } - - this._sock.close(); + this._cleanupSocket(state); } if (oldstate === 'fatal') { diff --git a/include/ui.js b/include/ui.js index a72d5fa9..93550780 100644 --- a/include/ui.js +++ b/include/ui.js @@ -159,13 +159,19 @@ var UI; }, initRFB: function () { - UI.rfb = new RFB({'target': $D('noVNC_canvas'), - 'onUpdateState': UI.updateState, - 'onXvpInit': UI.updateXvpVisualState, - 'onClipboard': UI.clipReceive, - 'onFBUComplete': UI.FBUComplete, - 'onFBResize': UI.updateViewDragButton, - 'onDesktopName': UI.updateDocumentTitle}); + try { + UI.rfb = new RFB({'target': $D('noVNC_canvas'), + 'onUpdateState': UI.updateState, + 'onXvpInit': UI.updateXvpVisualState, + 'onClipboard': UI.clipReceive, + 'onFBUComplete': UI.FBUComplete, + 'onFBResize': UI.updateViewDragButton, + 'onDesktopName': UI.updateDocumentTitle}); + return true; + } catch (exc) { + UI.updateState(null, 'fatal', null, 'Unable to create RFB client -- ' + exc); + return false; + } }, addMouseHandlers: function() { @@ -772,7 +778,7 @@ var UI; throw new Error("Must set host and port"); } - UI.initRFB(); + if (!UI.initRFB()) return; UI.rfb.set_encrypt(UI.getSetting('encrypt')); UI.rfb.set_true_color(UI.getSetting('true_color')); diff --git a/vnc_auto.html b/vnc_auto.html index 9fd2272a..ec18ab84 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -216,18 +216,24 @@ return; } - rfb = new RFB({'target': $D('noVNC_canvas'), - 'encrypt': WebUtil.getQueryVar('encrypt', - (window.location.protocol === "https:")), - 'repeaterID': WebUtil.getQueryVar('repeaterID', ''), - 'true_color': WebUtil.getQueryVar('true_color', true), - 'local_cursor': WebUtil.getQueryVar('cursor', true), - 'shared': WebUtil.getQueryVar('shared', true), - 'view_only': WebUtil.getQueryVar('view_only', false), - 'onUpdateState': updateState, - 'onXvpInit': xvpInit, - 'onPasswordRequired': passwordRequired, - 'onFBUComplete': FBUComplete}); + try { + rfb = new RFB({'target': $D('noVNC_canvas'), + 'encrypt': WebUtil.getQueryVar('encrypt', + (window.location.protocol === "https:")), + 'repeaterID': WebUtil.getQueryVar('repeaterID', ''), + 'true_color': WebUtil.getQueryVar('true_color', true), + 'local_cursor': WebUtil.getQueryVar('cursor', true), + 'shared': WebUtil.getQueryVar('shared', true), + 'view_only': WebUtil.getQueryVar('view_only', false), + 'onUpdateState': updateState, + 'onXvpInit': xvpInit, + 'onPasswordRequired': passwordRequired, + 'onFBUComplete': FBUComplete}); + } catch (exc) { + UI.updateState(null, 'fatal', null, 'Unable to create RFB client -- ' + exc); + return; // don't continue trying to connect + } + rfb.connect(host, port, password, path); };