Commit d9fc1c7b authored by Solly Ross's avatar Solly Ross

Throw exceptions from RFB constructor

Previously, if an error was thrown from the Display constructor
in the RFB constructor, we would attempt to use `RFB#updateState`
to handle this.  However, `RFB#updateState` attempts to close
the WebSocket connection, which doesn't exist at this point.

In the constructor, it's probably just better to raise an exception
instead (making sure to clean up anything relevant).

Fixes #460
parent 58ded70d
...@@ -159,11 +159,13 @@ var RFB; ...@@ -159,11 +159,13 @@ var RFB;
this._encStats[this._encodings[i][1]] = [0, 0]; 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 { try {
this._display = new Display({target: this._target}); this._display = new Display({target: this._target});
} catch (exc) { } catch (exc) {
Util.Error("Display exception: " + exc); Util.Error("Display exception: " + exc);
this._updateState('fatal', "No working Display"); throw exc;
} }
this._keyboard = new Keyboard({target: this._focusContainer, this._keyboard = new Keyboard({target: this._focusContainer,
...@@ -217,9 +219,11 @@ var RFB; ...@@ -217,9 +219,11 @@ var RFB;
} else { } else {
Util.Warn("Using web-socket-js bridge. Flash version: " + Util.Flash.version); Util.Warn("Using web-socket-js bridge. Flash version: " + Util.Flash.version);
if (!Util.Flash || Util.Flash.version < 9) { if (!Util.Flash || Util.Flash.version < 9) {
this._updateState('fatal', "WebSockets or <a href='http://get.adobe.com/flashplayer'>Adobe Flash</a> is required"); this._cleanupSocket('fatal');
throw new Exception("WebSockets or <a href='http://get.adobe.com/flashplayer'>Adobe Flash</a> is required");
} else if (document.location.href.substr(0, 7) === 'file://') { } 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 { } else {
this._updateState('loaded', 'noVNC ready: WebSockets emulation, ' + rmode); this._updateState('loaded', 'noVNC ready: WebSockets emulation, ' + rmode);
} }
...@@ -398,6 +402,32 @@ var RFB; ...@@ -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: * Page states:
...@@ -432,31 +462,7 @@ var RFB; ...@@ -432,31 +462,7 @@ var RFB;
*/ */
if (state in {'disconnected': 1, 'loaded': 1, 'connect': 1, if (state in {'disconnected': 1, 'loaded': 1, 'connect': 1,
'disconnect': 1, 'failed': 1, 'fatal': 1}) { 'disconnect': 1, 'failed': 1, 'fatal': 1}) {
this._cleanupSocket(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();
} }
if (oldstate === 'fatal') { if (oldstate === 'fatal') {
......
...@@ -159,13 +159,19 @@ var UI; ...@@ -159,13 +159,19 @@ var UI;
}, },
initRFB: function () { initRFB: function () {
UI.rfb = new RFB({'target': $D('noVNC_canvas'), try {
'onUpdateState': UI.updateState, UI.rfb = new RFB({'target': $D('noVNC_canvas'),
'onXvpInit': UI.updateXvpVisualState, 'onUpdateState': UI.updateState,
'onClipboard': UI.clipReceive, 'onXvpInit': UI.updateXvpVisualState,
'onFBUComplete': UI.FBUComplete, 'onClipboard': UI.clipReceive,
'onFBResize': UI.updateViewDragButton, 'onFBUComplete': UI.FBUComplete,
'onDesktopName': UI.updateDocumentTitle}); '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() { addMouseHandlers: function() {
...@@ -772,7 +778,7 @@ var UI; ...@@ -772,7 +778,7 @@ var UI;
throw new Error("Must set host and port"); throw new Error("Must set host and port");
} }
UI.initRFB(); if (!UI.initRFB()) return;
UI.rfb.set_encrypt(UI.getSetting('encrypt')); UI.rfb.set_encrypt(UI.getSetting('encrypt'));
UI.rfb.set_true_color(UI.getSetting('true_color')); UI.rfb.set_true_color(UI.getSetting('true_color'));
......
...@@ -216,18 +216,24 @@ ...@@ -216,18 +216,24 @@
return; return;
} }
rfb = new RFB({'target': $D('noVNC_canvas'), try {
'encrypt': WebUtil.getQueryVar('encrypt', rfb = new RFB({'target': $D('noVNC_canvas'),
(window.location.protocol === "https:")), 'encrypt': WebUtil.getQueryVar('encrypt',
'repeaterID': WebUtil.getQueryVar('repeaterID', ''), (window.location.protocol === "https:")),
'true_color': WebUtil.getQueryVar('true_color', true), 'repeaterID': WebUtil.getQueryVar('repeaterID', ''),
'local_cursor': WebUtil.getQueryVar('cursor', true), 'true_color': WebUtil.getQueryVar('true_color', true),
'shared': WebUtil.getQueryVar('shared', true), 'local_cursor': WebUtil.getQueryVar('cursor', true),
'view_only': WebUtil.getQueryVar('view_only', false), 'shared': WebUtil.getQueryVar('shared', true),
'onUpdateState': updateState, 'view_only': WebUtil.getQueryVar('view_only', false),
'onXvpInit': xvpInit, 'onUpdateState': updateState,
'onPasswordRequired': passwordRequired, 'onXvpInit': xvpInit,
'onFBUComplete': FBUComplete}); '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); rfb.connect(host, port, password, path);
}; };
</script> </script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment