]> git.proxmox.com Git - mirror_novnc.git/commitdiff
Use standard EventTarget interface for events
authorPierre Ossman <ossman@cendio.se>
Fri, 27 Oct 2017 11:22:36 +0000 (13:22 +0200)
committerPierre Ossman <ossman@cendio.se>
Thu, 9 Nov 2017 12:14:16 +0000 (13:14 +0100)
app/ui.js
core/rfb.js
core/util/eventtarget.js [new file with mode: 0644]
core/util/polyfill.js [new file with mode: 0644]
docs/API.md
tests/test.rfb.js
vnc_lite.html

index 1202fe26bfb9e85e5696821b004824a7370205ac..877a72e80c08673466a8864149f50c5b4b92a5ff 100644 (file)
--- a/app/ui.js
+++ b/app/ui.js
@@ -390,7 +390,7 @@ var UI = {
  *     VISUAL
  * ------v------*/
 
-    updateState: function(rfb, state, oldstate) {
+    updateState: function(event) {
         var msg;
 
         document.documentElement.classList.remove("noVNC_connecting");
@@ -398,7 +398,7 @@ var UI = {
         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");
@@ -534,8 +534,8 @@ var UI = {
         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) {
@@ -966,9 +966,9 @@ var UI = {
         }
     },
 
-    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");
     },
 
@@ -1040,15 +1040,15 @@ var UI = {
                          { 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() {
@@ -1072,9 +1072,9 @@ var UI = {
         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");
@@ -1105,7 +1105,7 @@ var UI = {
  *   PASSWORD
  * ------v------*/
 
-    credentials: function(rfb, types) {
+    credentials: function(e) {
         // FIXME: handle more types
         document.getElementById('noVNC_password_dlg')
             .classList.add('noVNC_open');
@@ -1656,7 +1656,7 @@ var UI = {
         WebUtil.init_logging(UI.getSetting('logging'));
     },
 
-    updateSessionSize: function(rfb, width, height) {
+    updateSessionSize: function(e) {
         UI.updateViewClip();
         UI.updateScaling();
         UI.fixScrollbars();
@@ -1674,13 +1674,13 @@ var UI = {
         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
index 55d20995c66bc045c4fd28355be1f52acb99a0ad..a3546b0029c1fd80d656b9451f4d4b5632b158c7 100644 (file)
@@ -14,6 +14,7 @@ import * as Log from './util/logging.js';
 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";
@@ -24,6 +25,7 @@ import KeyTable from "./input/keysym.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 */
@@ -265,18 +267,6 @@ RFB.prototype = {
 
     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 () {
@@ -510,7 +500,8 @@ RFB.prototype = {
         // 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);
@@ -526,14 +517,16 @@ RFB.prototype = {
 
         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':
@@ -603,12 +596,16 @@ RFB.prototype = {
                 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 () {
@@ -818,7 +815,9 @@ RFB.prototype = {
         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;
         }
 
@@ -835,7 +834,9 @@ RFB.prototype = {
         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;
         }
 
@@ -1072,7 +1073,9 @@ RFB.prototype = {
         }
 
         // 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);
 
@@ -1189,7 +1192,9 @@ RFB.prototype = {
 
         if (this._viewOnly) { return true; }
 
-        this.onclipboard(this, text);
+        var event = new CustomEvent("clipboard",
+                                    { detail: { text: text } });
+        this.dispatchEvent(event);
 
         return true;
     },
@@ -1285,7 +1290,8 @@ RFB.prototype = {
 
             case 2:  // Bell
                 Log.Debug("Bell");
-                this.onbell(this);
+                var event = new CustomEvent("bell", { detail: {} });
+                this.dispatchEvent(event);
                 return true;
 
             case 3:  // ServerCutText
@@ -1437,7 +1443,11 @@ RFB.prototype = {
         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();
@@ -1450,6 +1460,8 @@ RFB.prototype = {
     },
 };
 
+Object.assign(RFB.prototype, EventTargetMixin);
+
 // Class Methods
 RFB.messages = {
     keyEvent: function (sock, keysym, down) {
diff --git a/core/util/eventtarget.js b/core/util/eventtarget.js
new file mode 100644 (file)
index 0000000..61bc7a1
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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;
diff --git a/core/util/polyfill.js b/core/util/polyfill.js
new file mode 100644 (file)
index 0000000..8c600e6
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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;
+    }
+})();
index 519d3bfea559cfec90e92be011e2adb1852b405d..983d73571b0483ac23a844207e3d03a7c83c699e 100644 (file)
@@ -56,39 +56,41 @@ protocol stream.
     | `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
 
@@ -96,9 +98,8 @@ protocol stream.
   - 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.
@@ -175,10 +176,13 @@ connection to a specified VNC server.
       - 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
 | ----------------- | ------------
@@ -191,91 +195,66 @@ Note that a `RFB` objects can not transition from the disconnected
 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()
 
@@ -289,7 +268,7 @@ connected server.
 #### 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
 
@@ -405,7 +384,7 @@ the framebuffer. The capability `resize` must be set for this method to
 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
index c218ae07e4099126fdde2e96dcf25cf226d90f9f..4dbe1840d921b1d61ac19f457729ee3e52568391 100644 (file)
@@ -68,10 +68,11 @@ describe('Remote Frame Buffer Protocol Client', function() {
         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 () {
@@ -90,11 +91,12 @@ describe('Remote Frame Buffer Protocol Client', 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 () {
@@ -319,10 +321,10 @@ describe('Remote Frame Buffer Protocol Client', 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 () {
@@ -338,19 +340,19 @@ describe('Remote Frame Buffer Protocol Client', 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;
             });
         });
@@ -389,13 +391,12 @@ describe('Remote Frame Buffer Protocol Client', function() {
 
             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');
             });
 
         });
@@ -405,18 +406,18 @@ describe('Remote Frame Buffer Protocol Client', function() {
             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;
             });
         });
@@ -459,40 +460,40 @@ describe('Remote Frame Buffer Protocol Client', function() {
             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;
             });
         });
@@ -715,18 +716,18 @@ describe('Remote Frame Buffer Protocol Client', function() {
                     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 () {
@@ -769,26 +770,26 @@ describe('Remote Frame Buffer Protocol Client', 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 () {
@@ -998,13 +999,13 @@ describe('Remote Frame Buffer Protocol Client', 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 () {
@@ -1027,16 +1028,16 @@ describe('Remote Frame Buffer Protocol Client', 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 () {
@@ -1436,13 +1437,14 @@ describe('Remote Frame Buffer Protocol Client', 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);
@@ -1452,6 +1454,8 @@ describe('Remote Frame Buffer Protocol Client', function() {
                 });
 
                 describe('the ExtendedDesktopSize pseudo-encoding handler', function () {
+                    var resizeSpy;
+
                     beforeEach(function () {
                         client._supportsSetDesktopSize = false;
                         // a really small frame
@@ -1459,7 +1463,8 @@ describe('Remote Frame Buffer Protocol Client', function() {
                         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) {
@@ -1479,7 +1484,8 @@ describe('Remote Frame Buffer Protocol Client', function() {
                     }
 
                     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;
@@ -1492,8 +1498,8 @@ describe('Remote Frame Buffer Protocol Client', function() {
                                      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;
                     }),
 
@@ -1511,9 +1517,9 @@ describe('Remote Frame Buffer Protocol 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 handle a resize requested by another client', function () {
@@ -1530,9 +1536,9 @@ describe('Remote Frame Buffer Protocol 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 () {
@@ -1549,9 +1555,9 @@ describe('Remote Frame Buffer Protocol Client', 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 () {
@@ -1567,8 +1573,7 @@ describe('Remote Frame Buffer Protocol Client', 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;
                     });
                 });
 
@@ -1585,19 +1590,20 @@ describe('Remote Frame Buffer Protocol Client', function() {
 
         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;
             });
 
@@ -1613,18 +1619,19 @@ describe('Remote Frame Buffer Protocol Client', function() {
             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 () {
@@ -1850,9 +1857,10 @@ describe('Remote Frame Buffer Protocol Client', 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
index 1a952f1b9b52366c404033df2fda7ecfd08490b9..6575b4631b34d2dfa168d73d7cb4e8bb92c71acb 100644 (file)
             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>