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);
};