* VISUAL
* ------v------*/
- updateState: function(rfb, state, oldstate) {
+ updateState: function(event) {
var msg;
document.documentElement.classList.remove("noVNC_connecting");
document.documentElement.classList.remove("noVNC_disconnecting");
document.documentElement.classList.remove("noVNC_reconnecting");
- switch (state) {
+ switch (event.detail.state) {
case 'connecting':
document.getElementById("noVNC_transition_text").textContent = _("Connecting...");
document.documentElement.classList.add("noVNC_connecting");
document.getElementById('noVNC_status').classList.remove("noVNC_open");
},
- notification: function (rfb, msg, level) {
- UI.showStatus(msg, level);
+ notification: function (e) {
+ UI.showStatus(e.detail.message, e.detail.level);
},
activateControlbar: function(event) {
}
},
- clipboardReceive: function(rfb, text) {
- Log.Debug(">> UI.clipboardReceive: " + text.substr(0,40) + "...");
- document.getElementById('noVNC_clipboard_text').value = text;
+ clipboardReceive: function(e) {
+ Log.Debug(">> UI.clipboardReceive: " + e.detail.text.substr(0,40) + "...");
+ document.getElementById('noVNC_clipboard_text').value = e.detail.text;
Log.Debug("<< UI.clipboardReceive");
},
{ shared: UI.getSetting('shared'),
repeaterID: UI.getSetting('repeaterID'),
credentials: { password: password } });
- UI.rfb.onnotification = UI.notification;
- UI.rfb.onupdatestate = UI.updateState;
- UI.rfb.ondisconnected = UI.disconnectFinished;
- UI.rfb.oncredentialsrequired = UI.credentials;
- UI.rfb.oncapabilities = function () { UI.updatePowerButton(); UI.initialResize(); };
- UI.rfb.onclipboard = UI.clipboardReceive;
- UI.rfb.onbell = UI.bell;
- UI.rfb.onfbresize = UI.updateSessionSize;
- UI.rfb.ondesktopname = UI.updateDesktopName;
+ UI.rfb.addEventListener("notification", UI.notification);
+ UI.rfb.addEventListener("updatestate", UI.updateState);
+ UI.rfb.addEventListener("disconnect", UI.disconnectFinished);
+ UI.rfb.addEventListener("credentialsrequired", UI.credentials);
+ UI.rfb.addEventListener("capabilities", function () { UI.updatePowerButton(); UI.initialResize(); });
+ UI.rfb.addEventListener("clipboard", UI.clipboardReceive);
+ UI.rfb.addEventListener("bell", UI.bell);
+ UI.rfb.addEventListener("fbresize", UI.updateSessionSize);
+ UI.rfb.addEventListener("desktopname", UI.updateDesktopName);
},
disconnect: function() {
UI.connect(null, UI.reconnect_password);
},
- disconnectFinished: function (rfb, reason) {
- if (typeof reason !== 'undefined') {
- UI.showStatus(reason, 'error');
+ disconnectFinished: function (e) {
+ if (typeof e.detail.reason !== 'undefined') {
+ UI.showStatus(e.detail.reason, 'error');
} else if (UI.getSetting('reconnect', false) === true && !UI.inhibit_reconnect) {
document.getElementById("noVNC_transition_text").textContent = _("Reconnecting...");
document.documentElement.classList.add("noVNC_reconnecting");
* PASSWORD
* ------v------*/
- credentials: function(rfb, types) {
+ credentials: function(e) {
// FIXME: handle more types
document.getElementById('noVNC_password_dlg')
.classList.add('noVNC_open');
WebUtil.init_logging(UI.getSetting('logging'));
},
- updateSessionSize: function(rfb, width, height) {
+ updateSessionSize: function(e) {
UI.updateViewClip();
UI.updateScaling();
UI.fixScrollbars();
screen.style.overflow = "";
},
- updateDesktopName: function(rfb, name) {
- UI.desktopName = name;
+ updateDesktopName: function(e) {
+ UI.desktopName = e.detail.name;
// Display the desktop name in the document title
- document.title = name + " - noVNC";
+ document.title = e.detail.name + " - noVNC";
},
- bell: function(rfb) {
+ bell: function(e) {
if (WebUtil.getConfigVar('bell', 'on') === 'on') {
var promise = document.getElementById('noVNC_bell').play();
// The standards disagree on the return value here
import _ from './util/localization.js';
import { decodeUTF8 } from './util/strings.js';
import { browserSupportsCursorURIs, isTouchDevice } from './util/browsers.js';
+import EventTargetMixin from './util/eventtarget.js';
import Display from "./display.js";
import Keyboard from "./input/keyboard.js";
import Mouse from "./input/mouse.js";
import XtScancode from "./input/xtscancodes.js";
import Inflator from "./inflator.js";
import { encodings, encodingName } from "./encodings.js";
+import "./util/polyfill.js";
/*jslint white: false, browser: true */
/*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES, KeyTable, Inflator, XtScancode */
get isClipped() { return this._display.isClipped; },
- // ===== EVENT HANDLERS =====
-
- onupdatestate: function () {}, // onupdatestate(rfb, state, oldstate): connection state change
- onnotification: function () {}, // onnotification(rfb, msg, level, options): notification for the UI
- ondisconnected: function () {}, // ondisconnected(rfb, reason): disconnection finished
- oncredentialsrequired: function () {}, // oncredentialsrequired(rfb, types): VNC credentials are required
- onclipboard: function () {}, // onclipboard(rfb, text): RFB clipboard contents received
- onbell: function () {}, // onbell(rfb): RFB Bell message received
- onfbresize: function () {}, // onfbresize(rfb, width, height): frame buffer resized
- ondesktopname: function () {}, // ondesktopname(rfb, name): desktop name received
- oncapabilities: function () {}, // oncapabilities(rfb, caps): the supported capabilities has changed
-
// ===== PUBLIC METHODS =====
disconnect: function () {
// State change actions
this._rfb_connection_state = state;
- this.onupdatestate(this, state, oldstate);
+ var event = new CustomEvent("updatestate", { detail: { state: state } });
+ this.dispatchEvent(event);
var smsg = "New state '" + state + "', was '" + oldstate + "'.";
Log.Debug(smsg);
switch (state) {
case 'disconnected':
- // Call ondisconnected callback after onupdatestate since
+ // Fire disconnected event after updatestate event since
// we don't know if the UI only displays the latest message
if (this._rfb_disconnect_reason !== "") {
- this.ondisconnected(this, this._rfb_disconnect_reason);
+ event = new CustomEvent("disconnect",
+ { detail: { reason: this._rfb_disconnect_reason } });
} else {
// No reason means clean disconnect
- this.ondisconnected(this);
+ event = new CustomEvent("disconnect", { detail: {} });
}
+ this.dispatchEvent(event);
break;
case 'connecting':
return;
}
- this.onnotification(this, msg, level);
+ var event = new CustomEvent("notification",
+ { detail: { message: msg, level: level } });
+ this.dispatchEvent(event);
},
_setCapability: function (cap, val) {
this._capabilities[cap] = val;
- this.oncapabilities(this, this._capabilities);
+ var event = new CustomEvent("capabilities",
+ { detail: { capabilities: this._capabilities } });
+ this.dispatchEvent(event);
},
_handle_message: function () {
if (!this._rfb_credentials.username ||
!this._rfb_credentials.password ||
!this._rfb_credentials.target) {
- this.oncredentialsrequired(this, ["username", "password", "target"]);
+ var event = new CustomEvent("credentialsrequired",
+ { detail: { types: ["username", "password", "target"] } });
+ this.dispatchEvent(event);
return false;
}
if (this._sock.rQwait("auth challenge", 16)) { return false; }
if (!this._rfb_credentials.password) {
- this.oncredentialsrequired(this, ["password"]);
+ var event = new CustomEvent("credentialsrequired",
+ { detail: { types: ["password"] } });
+ this.dispatchEvent(event);
return false;
}
}
// we're past the point where we could backtrack, so it's safe to call this
- this.ondesktopname(this, this._fb_name);
+ var event = new CustomEvent("desktopname",
+ { detail: { name: this._fb_name } });
+ this.dispatchEvent(event);
this._resize(width, height);
if (this._viewOnly) { return true; }
- this.onclipboard(this, text);
+ var event = new CustomEvent("clipboard",
+ { detail: { text: text } });
+ this.dispatchEvent(event);
return true;
},
case 2: // Bell
Log.Debug("Bell");
- this.onbell(this);
+ var event = new CustomEvent("bell", { detail: {} });
+ this.dispatchEvent(event);
return true;
case 3: // ServerCutText
this._destBuff = new Uint8Array(this._fb_width * this._fb_height * 4);
this._display.resize(this._fb_width, this._fb_height);
- this.onfbresize(this, this._fb_width, this._fb_height);
+
+ var event = new CustomEvent("fbresize",
+ { detail: { width: this._fb_width,
+ height: this._fb_height } });
+ this.dispatchEvent(event);
this._timing.fbu_rt_start = (new Date()).getTime();
this._updateContinuousUpdates();
},
};
+Object.assign(RFB.prototype, EventTargetMixin);
+
// Class Methods
RFB.messages = {
keyEvent: function (sock, keysym, down) {
--- /dev/null
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright 2017 Pierre Ossman for Cendio AB
+ * Licensed under MPL 2.0 (see LICENSE.txt)
+ *
+ * See README.md for usage and integration instructions.
+ */
+
+var EventTargetMixin = {
+ _listeners: null,
+
+ addEventListener: function(type, callback) {
+ if (!this._listeners) {
+ this._listeners = new Map();
+ }
+ if (!this._listeners.has(type)) {
+ this._listeners.set(type, new Set());
+ }
+ this._listeners.get(type).add(callback);
+ },
+
+ removeEventListener: function(type, callback) {
+ if (!this._listeners || !this._listeners.has(type)) {
+ return;
+ }
+ this._listeners.get(type).delete(callback);
+ },
+
+ dispatchEvent: function(event) {
+ if (!this._listeners || !this._listeners.has(event.type)) {
+ return true;
+ }
+ this._listeners.get(event.type).forEach(function (callback) {
+ callback.call(this, event);
+ }, this);
+ return !event.defaultPrevented;
+ },
+};
+
+export default EventTargetMixin;
--- /dev/null
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright 2017 Pierre Ossman for noVNC
+ * Licensed under MPL 2.0 or any later version (see LICENSE.txt)
+ */
+
+/* Polyfills to provide new APIs in old browsers */
+
+/* Object.assign() (taken from MDN) */
+if (typeof Object.assign != 'function') {
+ // Must be writable: true, enumerable: false, configurable: true
+ Object.defineProperty(Object, "assign", {
+ value: function assign(target, varArgs) { // .length of function is 2
+ 'use strict';
+ if (target == null) { // TypeError if undefined or null
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+
+ var to = Object(target);
+
+ for (var index = 1; index < arguments.length; index++) {
+ var nextSource = arguments[index];
+
+ if (nextSource != null) { // Skip over if undefined or null
+ for (var nextKey in nextSource) {
+ // Avoid bugs when hasOwnProperty is shadowed
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
+ to[nextKey] = nextSource[nextKey];
+ }
+ }
+ }
+ }
+ return to;
+ },
+ writable: true,
+ configurable: true
+ });
+}
+
+/* CustomEvent constructor (taken from MDN) */
+(function () {
+ function CustomEvent ( event, params ) {
+ params = params || { bubbles: false, cancelable: false, detail: undefined };
+ var evt = document.createEvent( 'CustomEvent' );
+ evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
+ return evt;
+ }
+
+ CustomEvent.prototype = window.Event.prototype;
+
+ if (typeof window.CustomEvent !== "function") {
+ window.CustomEvent = CustomEvent;
+ }
+})();
| `power` | `boolean` | Machine power control is available
| `resize` | `boolean` | The framebuffer can be resized
-### Event handlers
+### Events
-[`RFB.onupdatestate()`](#rfbonupdatestate)
- - An event handler called when the connection state of the `RFB`
- object changes.
+[`updatestate`](#updatestate)
+ - The `updatestate` event is fired when the connection state of the
+ `RFB` object changes.
-[`RFB.onnotification()`](#rfbonnotification)
- - An event handler called when the `RFB` usage has a message to
- display to the user.
+[`notification`](#notification)
+ - The `notification` event is fired when the `RFB` usage has a
+ message to display to the user.
-[`RFB.ondisconnected()`](#rfbondisconnected)
- - An event handler called when the `RFB` object disconnects.
+[`disconnect`](#disconnected)
+ - The `disconnect` event is fired when the `RFB` object disconnects.
-[`RFB.oncredentialsrequired()`](#rfboncredentialsrequired)
- - An event hander called when more credentials must be given to
- continue.
+[`credentialsrequired`](#credentialsrequired)
+ - The `credentialsrequired` event is fired when more credentials must
+ be given to continue.
-[`RFB.onclipboard()`](#rfbonclipboard)
- - An event handler called when clipboard data is received from the
- server.
+[`clipboard`](#clipboard)
+ - The `clipboard` event is fired when clipboard data is received from
+ the server.
-[`RFB.onbell()`](#rfbonbell)
- - An event handler called when a audible bell request is received
+[`bell`](#bell)
+ - The `bell` event is fired when a audible bell request is received
from the server.
-[`RFB.onfbresize()`](#rfbonfbresize)
- - An event handler called when the framebuffer size is changed.
+[`fbresize`](#fbresize)
+ - The `fbresize` event is fired when the framebuffer size is changed.
-[`RFB.ondesktopname()`](#rfbondesktopname)
- - An event handler called when the remote desktop name changes.
+[`desktopname`](#desktopname)
+ - The `desktopname` event is fired when the remote desktop name
+ changes.
-[`RFB.oncapabilities()`](#rfboncapabilities)
- - An event handler called when `RFB.capabilities` is updated.
+[`capabilities`](#capabilities)
+ - The `capabilities` event is fired when `RFB.capabilities` is
+ updated.
### Methods
- Disconnect from the server.
[`RFB.sendCredentials()`](#rfbsendcredentials)
- - Send credentials to server. Should be called after
- [`oncredentialsrequired`](#rfboncredentialsrequired) has been
- called.
+ - Send credentials to server. Should be called after the
+ [`credentialsrequired`](#credentialsrequired) event has fired.
[`RFB.sendKey()`](#rfbsendKey)
- Send a key event.
- A `DOMString` specifying the ID to provide to any VNC repeater
encountered.
-#### RFB.onupdatestate
+#### updatestate
-The `onupdatestate` event handler is fired after the noVNC connection
-state changes. Here is a list of the states that are reported:
+The `updatestate` event is fired after the noVNC connection state
+changes. The `detail` property is an `Object` containg the property
+`state` with the new connection state.
+
+Here is a list of the states that are reported:
| connection state | description
| ----------------- | ------------
state in any way, a new instance of the object has to be created for
new connections.
-##### Syntax
+#### notification
- RFB.onupdatestate = function(rfb, state) { ... }
+The `notification` event is fired when the `RFB` object wants a message
+displayed to the user. The `detail` property is an `Object` containing
+the following properties:
-#### RFB.onnotification
+| Property | Type | Description
+| --------- | ----------- | -----------
+| `message` | `DOMString` | The message to display
+| `level` | `DOMString` | The severity of the message
-The `onnotification` event handler is fired when the `RFB` object wants
-a message displayed to the user. **`msg`** is a `DOMString` specifying
-the actual message, and **`level`** is a `DOMString` indicating the
-severity of the message. The following levels are currently defined:
+The following levels are currently defined:
- `"normal"`
- `"warn"`
- `"error"`
-##### Syntax
-
- RFB.onnotification = function(rfb, msg, level) { ... }
-
-#### RFB.ondisconnected
-
-The `ondisconnected` event handler is fired when the connection has
-been terminated. **`reason`** is `undefined` for a clean termination
-and a `DOMString` specifying the reason in the event of an unexpected
-termination.
-
-##### Syntax
-
- RFB.ondisconnected = function(rfb, reason) { ... }
-
-#### RFB.oncredentialsrequired
-
-The `oncredentialsrequired` event handler is fired when the server
-requests more credentials than were specified to [`RFB()`](#rfb-1). The
-**`types`** argument is a list of all the credentials that are
-required.
-
-##### Syntax
-
- RFB.oncredentialsrequired = function(rfb, types) { ... }
-
-#### RFB.onclipboard
+#### disconnect
-The `onclipboard` event handler is fired when the server has sent
-clipboard data.
+The `disconnect` event is fired when the connection has been
+terminated. The `detail` property is an `Object` the optionally
+contains the property `reason`. `reason` is a `DOMString` specifying
+the reason in the event of an unexpected termination. `reason` will be
+omitted for a clean termination.
-##### Syntax
+#### credentialsrequired
- RFB.onclipboard = function(rfb, text) { ... }
+The `credentialsrequired` event is fired when the server requests more
+credentials than were specified to [`RFB()`](#rfb-1). The `detail`
+property is an `Object` containing the property `types` which is an
+`Array` of `DOMString` listing the credentials that are required.
-#### RFB.onbell
+#### clipboard
-The `onbell` event handler is fired when the server has requested an
-audible bell.
+The `clipboard` event is fired when the server has sent clipboard data.
+The `detail` property is an `Object` containing the property `text`
+which is a `DOMString` with the clipboard data.
-##### Syntax
+#### bell
- RFB.onbell = function(rfb) { ... }
+The `bell` event is fired when the server has requested an audible
+bell.
-#### RFB.onfbresize
-
-The `onfbresize` event handler is fired when the framebuffer has
-changed dimensions.
-
-##### Syntax
+#### fbresize
- RFB.onfbresize = function(rfb, width, height) { ... }
+The `fbresize` event is fired when the framebuffer has changed
+dimensions. The `detail` property is an `Object` with the properties
+`width` and `height` specifying the new dimensions.
-#### RFB.ondesktopname
+#### desktopname
-The `ondesktopname` event handler is fired when the name of the remote
-desktop changes.
+The `desktopname` event is fired when the name of the remote desktop
+changes. The `detail` property is an `Object` with the property `name`
+which is a `DOMString` specifying the new name.
-##### Syntax
-
- RFB.ondesktopname = function(rfb, name) { ... }
-
-#### RFB.oncapabilities
-
-The `oncapabilities` event handler is fired whenever an entry is added
-or removed from `RFB.capabilities`.
-
-##### Syntax
+#### capabilities
- RFB.oncapabilities = function(rfb, capabilites) { ... }
+The `capabilities` event is fired whenever an entry is added or removed
+from `RFB.capabilities`. The `detail` property is an `Object` with the
+property `capabilities` containing the new value of `RFB.capabilities`.
#### RFB.disconnect()
#### RFB.sendCredentials()
The `RFB.sendCredentials()` method is used to provide the missing
-credentials after `RFB.oncredentialsrequired` has been fired.
+credentials after a `credentialsrequired` event has been fired.
##### Syntax
have any effect.
Note that this is merely a request and the server may deny it.
-[`RFB.onfbresize`](#rfbonfbresize) will be called when the framebuffer
+The [`fbresize`](#fbresize) event will be fired when the framebuffer
actually changes dimensions.
##### Syntax
describe('#RFB', function () {
it('should set the current state to "connecting"', function () {
var client = new RFB(document.createElement('canvas'), 'wss://host:8675');
- client.onupdatestate = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("updatestate", spy);
this.clock.tick();
- expect(client.onupdatestate).to.have.been.calledOnce;
- expect(client.onupdatestate).to.have.been.calledWith(client, 'connecting');
+ expect(spy).to.have.been.calledOnce;
+ expect(spy.args[0][0].detail.state).to.equal('connecting');
});
it('should actually connect to the websocket', function () {
});
it('should set the current state to "disconnecting"', function () {
- client.onupdatestate = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("updatestate", spy);
client.disconnect();
- expect(client.onupdatestate).to.have.been.calledTwice;
- expect(client.onupdatestate).to.have.been.calledWith(client, 'disconnecting');
- expect(client.onupdatestate).to.have.been.calledWith(client, 'disconnected');
+ expect(spy).to.have.been.calledTwice;
+ expect(spy.args[0][0].detail.state).to.equal('disconnecting');
+ expect(spy.args[1][0].detail.state).to.equal('disconnected');
});
it('should unregister error event handler', function () {
});
it('should call the updateState callback', function () {
- client.onupdatestate = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("updatestate", spy);
client._updateConnectionState('disconnecting');
- var spy = client.onupdatestate;
- expect(spy.args[0][1]).to.equal('disconnecting');
+ expect(spy.args[0][0].detail.state).to.equal('disconnecting');
});
it('should set the rfb_connection_state', function () {
});
it('should ignore state changes to the same state', function () {
- client.onupdatestate = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("updatestate", spy);
client._rfb_connection_state = 'connecting';
client._updateConnectionState('connecting');
- var spy = client.onupdatestate;
expect(spy).to.not.have.been.called;
});
it('should ignore illegal state changes', function () {
- client.onupdatestate = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("updatestate", spy);
client._rfb_connection_state = 'connected';
client._updateConnectionState('disconnected');
expect(client._rfb_connection_state).to.not.equal('disconnected');
- var spy = client.onupdatestate;
expect(spy).to.not.have.been.called;
});
});
it('should result in disconnect callback with message when reason given', function () {
client._rfb_connection_state = 'connected';
- client.ondisconnected = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("disconnect", spy);
client._fail('a reason');
- var spy = client.ondisconnected;
this.clock.tick(2000);
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0].length).to.equal(2);
- expect(spy.args[0][1]).to.equal('a reason');
+ expect(spy.args[0][0].detail.reason).to.equal('a reason');
});
});
beforeEach(function () { client = make_rfb(); });
it('should call the notification callback', function () {
- client.onnotification = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("notification", spy);
client._notification('notify!', 'warn');
- var spy = client.onnotification;
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.equal('notify!');
- expect(spy.args[0][2]).to.equal('warn');
+ expect(spy.args[0][0].detail.message).to.equal('notify!');
+ expect(spy.args[0][0].detail.level).to.equal('warn');
});
it('should not call the notification callback when level is invalid', function () {
- client.onnotification = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("notification", spy);
client._notification('notify!', 'invalid');
- var spy = client.onnotification;
expect(spy).to.not.have.been.called;
});
});
beforeEach(function () { client = make_rfb(); });
it('should call the disconnect callback if the state is "disconnected"', function () {
- client.ondisconnected = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("disconnect", spy);
client._rfb_connection_state = 'disconnecting';
client._rfb_disconnect_reason = "error";
client._updateConnectionState('disconnected');
- var spy = client.ondisconnected;
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.equal("error");
+ expect(spy.args[0][0].detail.reason).to.equal("error");
});
it('should not call the disconnect callback if the state is not "disconnected"', function () {
- client.ondisconnected = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("disconnect", spy);
client._sock._websocket.close = function () {}; // explicitly don't call onclose
client._updateConnectionState('disconnecting');
- var spy = client.ondisconnected;
expect(spy).to.not.have.been.called;
});
it('should call the disconnect callback without msg when no reason given', function () {
- client.ondisconnected = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("disconnect", spy);
client._rfb_connection_state = 'disconnecting';
client._rfb_disconnect_reason = "";
client._updateConnectionState('disconnected');
- var spy = client.ondisconnected;
expect(spy).to.have.been.calledOnce;
expect(spy.args[0].length).to.equal(1);
});
it('should call the updateState callback before the disconnect callback', function () {
- client.ondisconnected = sinon.spy();
- client.onupdatestate = sinon.spy();
+ var updateStateSpy = sinon.spy();
+ var disconnectSpy = sinon.spy();
+ client.addEventListener("disconnect", disconnectSpy);
+ client.addEventListener("updatestate", updateStateSpy);
client._rfb_connection_state = 'disconnecting';
client._updateConnectionState('disconnected');
- var updateStateSpy = client.onupdatestate;
- var disconnectSpy = client.ondisconnected;
expect(updateStateSpy.calledBefore(disconnectSpy)).to.be.true;
});
});
client._rfb_version = 3.8;
});
- it('should call the onCredentialsRequired callback if missing a password', function () {
- client.oncredentialsrequired = sinon.spy();
+ it('should fire the credentialsrequired event if missing a password', function () {
+ var spy = sinon.spy();
+ client.addEventListener("credentialsrequired", spy);
send_security(2, client);
var challenge = [];
for (var i = 0; i < 16; i++) { challenge[i] = i; }
client._sock._websocket._receive_data(new Uint8Array(challenge));
- var spy = client.oncredentialsrequired;
expect(client._rfb_credentials).to.be.empty;
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.have.members(["password"]);
+ expect(spy.args[0][0].detail.types).to.have.members(["password"]);
});
it('should encrypt the password with DES and then send it back', function () {
expect(client._negotiate_std_vnc_auth).to.have.been.calledOnce;
});
- it('should call the onCredentialsRequired callback if all credentials are missing', function() {
- client.oncredentialsrequired = sinon.spy();
+ it('should fire the credentialsrequired event if all credentials are missing', function() {
+ var spy = sinon.spy();
+ client.addEventListener("credentialsrequired", spy);
client._rfb_credentials = {};
send_security(22, client);
- var spy = client.oncredentialsrequired;
expect(client._rfb_credentials).to.be.empty;
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.have.members(["username", "password", "target"]);
+ expect(spy.args[0][0].detail.types).to.have.members(["username", "password", "target"]);
});
- it('should call the onCredentialsRequired callback if some credentials are missing', function() {
- client.oncredentialsrequired = sinon.spy();
+ it('should fire the credentialsrequired event if some credentials are missing', function() {
+ var spy = sinon.spy();
+ client.addEventListener("credentialsrequired", spy);
client._rfb_credentials = { username: 'user',
target: 'target' };
send_security(22, client);
- var spy = client.oncredentialsrequired;
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.have.members(["username", "password", "target"]);
+ expect(spy.args[0][0].detail.types).to.have.members(["username", "password", "target"]);
});
it('should send user and target separately', function () {
// NB(sross): we just warn, not fail, for endian-ness and shifts, so we don't test them
it('should set the framebuffer name and call the callback', function () {
- client.ondesktopname = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("desktopname", spy);
send_server_init({ name: 'some name' }, client);
- var spy = client.ondesktopname;
expect(client._fb_name).to.equal('some name');
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.equal('some name');
+ expect(spy.args[0][0].detail.name).to.equal('some name');
});
it('should handle the extended init message of the tight encoding', function () {
});
it('should call the resize callback and resize the display', function () {
- client.onfbresize = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("fbresize", spy);
sinon.spy(client._display, 'resize');
send_server_init({ width: 27, height: 32 }, client);
- var spy = client.onfbresize;
expect(client._display.resize).to.have.been.calledOnce;
expect(client._display.resize).to.have.been.calledWith(27, 32);
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.equal(27);
- expect(spy.args[0][2]).to.equal(32);
+ expect(spy.args[0][0].detail.width).to.equal(27);
+ expect(spy.args[0][0].detail.height).to.equal(32);
});
it('should grab the mouse and keyboard', function () {
});
it('should handle the DesktopSize pseduo-encoding', function () {
- client.onfbresize = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("fbresize", spy);
sinon.spy(client._display, 'resize');
send_fbu_msg([{ x: 0, y: 0, width: 20, height: 50, encoding: -223 }], [[]], client);
- var spy = client.onfbresize;
expect(spy).to.have.been.calledOnce;
- expect(spy).to.have.been.calledWith(sinon.match.any, 20, 50);
+ expect(spy.args[0][0].detail.width).to.equal(20);
+ expect(spy.args[0][0].detail.height).to.equal(50);
expect(client._fb_width).to.equal(20);
expect(client._fb_height).to.equal(50);
});
describe('the ExtendedDesktopSize pseudo-encoding handler', function () {
+ var resizeSpy;
+
beforeEach(function () {
client._supportsSetDesktopSize = false;
// a really small frame
client._fb_height = 4;
client._display.resize(4, 4);
sinon.spy(client._display, 'resize');
- client.onfbresize = sinon.spy();
+ resizeSpy = sinon.spy();
+ client.addEventListener("fbresize", resizeSpy);
});
function make_screen_data (nr_of_screens) {
}
it('should call callback when resize is supported', function () {
- client.oncapabilities = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("capabilities", spy);
expect(client._supportsSetDesktopSize).to.be.false;
expect(client.capabilities.resize).to.be.false;
make_screen_data(1), client);
expect(client._supportsSetDesktopSize).to.be.true;
- expect(client.oncapabilities).to.have.been.calledOnce;
- expect(client.oncapabilities.args[0][1].resize).to.be.true;
+ expect(spy).to.have.been.calledOnce;
+ expect(spy.args[0][0].detail.capabilities.resize).to.be.true;
expect(client.capabilities.resize).to.be.true;
}),
expect(client._display.resize).to.have.been.calledOnce;
expect(client._display.resize).to.have.been.calledWith(20, 50);
- var spy = client.onfbresize;
- expect(spy).to.have.been.calledOnce;
- expect(spy).to.have.been.calledWith(sinon.match.any, 20, 50);
+ expect(resizeSpy).to.have.been.calledOnce;
+ expect(resizeSpy.args[0][0].detail.width).to.equal(20);
+ expect(resizeSpy.args[0][0].detail.height).to.equal(50);
});
it('should handle a resize requested by another client', function () {
expect(client._display.resize).to.have.been.calledOnce;
expect(client._display.resize).to.have.been.calledWith(20, 50);
- var spy = client.onfbresize;
- expect(spy).to.have.been.calledOnce;
- expect(spy).to.have.been.calledWith(sinon.match.any, 20, 50);
+ expect(resizeSpy).to.have.been.calledOnce;
+ expect(resizeSpy.args[0][0].detail.width).to.equal(20);
+ expect(resizeSpy.args[0][0].detail.height).to.equal(50);
});
it('should be able to recieve requests which contain data for multiple screens', function () {
expect(client._display.resize).to.have.been.calledOnce;
expect(client._display.resize).to.have.been.calledWith(60, 50);
- var spy = client.onfbresize;
- expect(spy).to.have.been.calledOnce;
- expect(spy).to.have.been.calledWith(sinon.match.any, 60, 50);
+ expect(resizeSpy).to.have.been.calledOnce;
+ expect(resizeSpy.args[0][0].detail.width).to.equal(60);
+ expect(resizeSpy.args[0][0].detail.height).to.equal(50);
});
it('should not handle a failed request', function () {
expect(client._display.resize).to.not.have.been.called;
- var spy = client.onfbresize;
- expect(spy).to.not.have.been.called;
+ expect(resizeSpy).to.not.have.been.called;
});
});
describe('XVP Message Handling', function () {
it('should send a notification on XVP_FAIL', function () {
- client.onnotification = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("notification", spy);
client._sock._websocket._receive_data(new Uint8Array([250, 0, 10, 0]));
- var spy = client.onnotification;
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.equal('XVP Operation Failed');
+ expect(spy.args[0][0].detail.message).to.equal('XVP Operation Failed');
});
it('should set the XVP version and fire the callback with the version on XVP_INIT', function () {
- client.oncapabilities = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("capabilities", spy);
client._sock._websocket._receive_data(new Uint8Array([250, 0, 10, 1]));
expect(client._rfb_xvp_ver).to.equal(10);
- expect(client.oncapabilities).to.have.been.calledOnce;
- expect(client.oncapabilities.args[0][1].power).to.be.true;
+ expect(spy).to.have.been.calledOnce;
+ expect(spy.args[0][0].detail.capabilities.power).to.be.true;
expect(client.capabilities.power).to.be.true;
});
var data = [3, 0, 0, 0];
push32(data, expected_str.length);
for (var i = 0; i < expected_str.length; i++) { data.push(expected_str.charCodeAt(i)); }
- client.onclipboard = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("clipboard", spy);
client._sock._websocket._receive_data(new Uint8Array(data));
- var spy = client.onclipboard;
expect(spy).to.have.been.calledOnce;
- expect(spy.args[0][1]).to.equal(expected_str);
+ expect(spy.args[0][0].detail.text).to.equal(expected_str);
});
it('should fire the bell callback on Bell', function () {
- client.onbell = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("bell", spy);
client._sock._websocket._receive_data(new Uint8Array([2]));
- expect(client.onbell).to.have.been.calledOnce;
+ expect(spy).to.have.been.calledOnce;
});
it('should respond correctly to ServerFence', function () {
});
it('should process all normal messages directly', function () {
- client.onbell = sinon.spy();
+ var spy = sinon.spy();
+ client.addEventListener("bell", spy);
client._sock._websocket._receive_data(new Uint8Array([0x02, 0x02]));
- expect(client.onbell).to.have.been.calledTwice;
+ expect(spy).to.have.been.calledTwice;
});
// open events
UIresize();
doneInitialResize = true;
}
- function updateDesktopName(rfb, name) {
- desktopName = name;
+ function updateDesktopName(e) {
+ desktopName = e.detail.name;
}
- function credentials(rfb, types) {
+ function credentials(e) {
var html;
var form = document.createElement('form');
document.getElementById('noVNC_status_bar').setAttribute("class", "noVNC_status_" + level);
document.getElementById('noVNC_status').textContent = text;
}
- function updateState(rfb, state, oldstate) {
+ function updateState(e) {
var cad = document.getElementById('sendCtrlAltDelButton');
- switch (state) {
+ switch (e.detail.state) {
case 'connecting':
status("Connecting", "normal");
break;
status("Disconnected", "normal");
break;
default:
- status(state, "warn");
+ status(e.detail.state, "warn");
break;
}
- if (state === 'connected') {
+ if (e.detail.state === 'connected') {
cad.disabled = false;
} else {
cad.disabled = true;
}
}
- function disconnected(rfb, reason) {
- if (typeof(reason) !== 'undefined') {
- status(reason, "error");
+ function disconnect(e) {
+ if (typeof(e.detail.reason) !== 'undefined') {
+ status(e.detail.reason, "error");
}
}
- function notification(rfb, msg, level) {
- status(msg, level);
+ function notification(e) {
+ status(e.detail.message, e.detail.level);
}
window.onresize = function () {
shared: WebUtil.getConfigVar('shared', true),
credentials: { password: password } });
rfb.viewOnly = WebUtil.getConfigVar('view_only', false);
- rfb.onnotification = notification;
- rfb.onupdatestate = updateState;
- rfb.ondisconnected = disconnected;
- rfb.oncapabilities = function () { updatePowerButtons(); initialResize(); };
- rfb.oncredentialsrequired = credentials;
- rfb.ondesktopname = updateDesktopName;
+ rfb.addEventListener("notification", notification);
+ rfb.addEventListener("updatestate", updateState);
+ rfb.addEventListener("disconnect", disconnect);
+ rfb.addEventListener("capabilities", function () { updatePowerButtons(); initialResize(); });
+ rfb.addEventListener("credentialsrequired", credentials);
+ rfb.addEventListener("desktopname", updateDesktopName);
})();
</script>
</head>