Files
noVNC/tests/playback.js
Pierre Ossman 747b462337 Use standard JavaScript properties
Use normal properties with JavaScript setters and getters instead of
our homegrown stuff.

This also changes the properties to follow normal naming conventions.
2017-11-09 13:03:32 +01:00

203 lines
5.9 KiB
JavaScript

/*
* noVNC: HTML5 VNC client
* Copyright (C) 2012 Joel Martin
* Licensed under MPL 2.0 (see LICENSE.txt)
*/
import RFB from '../core/rfb.js';
import * as Log from '../core/util/logging.js';
import Base64 from '../core/base64.js';
// Immediate polyfill
if (setImmediate === undefined) {
var _immediateIdCounter = 1;
var _immediateFuncs = {};
var setImmediate = function (func) {
var index = _immediateIdCounter++;
_immediateFuncs[index] = func;
window.postMessage("noVNC immediate trigger:" + index, "*");
return index;
};
window.clearImmediate = function (id) {
_immediateFuncs[id];
};
var _onMessage = function (event) {
if ((typeof event.data !== "string") ||
(event.data.indexOf("noVNC immediate trigger:") !== 0)) {
return;
}
var index = event.data.slice("noVNC immediate trigger:".length);
var callback = _immediateFuncs[index];
if (callback === undefined) {
return;
}
delete _immediateFuncs[index];
callback();
};
window.addEventListener("message", _onMessage);
}
export default function RecordingPlayer (frames, encoding, disconnected, notification) {
this._frames = frames;
this._encoding = encoding;
this._disconnected = disconnected;
this._notification = notification;
if (this._encoding === undefined) {
let frame = this._frames[0];
let start = frame.indexOf('{', 1) + 1;
if (frame.slice(start).startsWith('UkZC')) {
this._encoding = 'base64';
} else {
this._encoding = 'binary';
}
}
this._rfb = undefined;
this._frame_length = this._frames.length;
this._frame_index = 0;
this._start_time = undefined;
this._realtime = true;
this._trafficManagement = true;
this._running = false;
this.onfinish = function () {};
}
RecordingPlayer.prototype = {
run: function (realtime, trafficManagement) {
// initialize a new RFB
this._rfb = new RFB(document.getElementById('VNC_canvas'));
this._rfb.viewOnly = true;
this._rfb.ondisconnected = this._handleDisconnect.bind(this);
this._rfb.onnotification = this._notification;
this._enablePlaybackMode();
// reset the frame index and timer
this._frame_index = 0;
this._start_time = (new Date()).getTime();
this._realtime = realtime;
this._trafficManagement = (trafficManagement === undefined) ? !realtime : trafficManagement;
this._running = true;
// launch the tests
this._rfb.connect('wss://test');
this._queueNextPacket();
},
// _enablePlaybackMode mocks out things not required for running playback
_enablePlaybackMode: function () {
this._rfb._sock.send = function (arr) {};
this._rfb._sock.close = function () {};
this._rfb._sock.flush = function () {};
this._rfb._checkEvents = function () {};
this._rfb.connect = function (url) {
this._url = url;
this._rfb_credentials = {};
this._sock.init('binary', 'ws');
this._rfb_connection_state = 'connecting';
this._rfb_init_state = 'ProtocolVersion';
};
},
_queueNextPacket: function () {
if (!this._running) { return; }
var frame = this._frames[this._frame_index];
// skip send frames
while (this._frame_index < this._frame_length && frame.charAt(0) === "}") {
this._frame_index++;
frame = this._frames[this._frame_index];
}
if (frame === 'EOF') {
Log.Debug('Finished, found EOF');
this._finish();
return;
}
if (this._frame_index >= this._frame_length) {
Log.Debug('Finished, no more frames');
this._finish();
return;
}
if (this._realtime) {
let foffset = frame.slice(1, frame.indexOf('{', 1));
let toffset = (new Date()).getTime() - this._start_time;
let delay = foffset - toffset;
if (delay < 1) delay = 1;
setTimeout(this._doPacket.bind(this), delay);
} else {
setImmediate(this._doPacket.bind(this));
}
},
_doPacket: function () {
// Avoid having excessive queue buildup in non-realtime mode
if (this._trafficManagement && this._rfb._flushing) {
let player = this;
let orig = this._rfb._display.onflush;
this._rfb._display.onflush = function () {
player._rfb._display.onflush = orig;
player._rfb._onFlush();
player._doPacket();
};
return;
}
const frame = this._frames[this._frame_index];
var start = frame.indexOf('{', 1) + 1;
if (this._encoding === 'base64') {
var u8 = Base64.decode(frame.slice(start));
start = 0;
} else {
var u8 = new Uint8Array(frame.length - start);
for (let i = 0; i < frame.length - start; i++) {
u8[i] = frame.charCodeAt(start + i);
}
}
this._rfb._sock._recv_message({'data': u8});
this._frame_index++;
this._queueNextPacket();
},
_finish() {
if (this._rfb._display.pending()) {
var player = this;
this._rfb._display.onflush = function () {
if (player._rfb._flushing) {
player._rfb._onFlush();
}
player._finish();
};
this._rfb._display.flush();
} else {
this._running = false;
this.onfinish((new Date()).getTime() - this._start_time);
}
},
_handleDisconnect(rfb, reason) {
this._running = false;
this._disconnected(rfb, reason, this._frame_index);
}
};