Files
noVNC/tests/playback.js
T

172 lines
4.5 KiB
JavaScript
Raw Normal View History

2010-09-08 10:11:11 -05:00
/*
* noVNC: HTML5 VNC client
2018-10-09 06:15:35 -04:00
* Copyright (C) 2018 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
2010-09-08 10:11:11 -05:00
*/
2017-03-01 21:10:09 -05:00
import RFB from '../core/rfb.js';
import * as Log from '../core/util/logging.js';
2016-10-24 17:37:21 +02:00
// Immediate polyfill
2018-05-24 00:27:09 +03:00
if (window.setImmediate === undefined) {
let _immediateIdCounter = 1;
const _immediateFuncs = {};
2016-10-24 17:37:21 +02:00
window.setImmediate = (func) => {
2018-05-24 00:27:09 +03:00
const index = _immediateIdCounter++;
2016-10-24 17:37:21 +02:00
_immediateFuncs[index] = func;
window.postMessage("noVNC immediate trigger:" + index, "*");
return index;
};
window.clearImmediate = (id) => {
2016-10-24 17:37:21 +02:00
_immediateFuncs[id];
};
window.addEventListener("message", (event) => {
2016-10-24 17:37:21 +02:00
if ((typeof event.data !== "string") ||
(event.data.indexOf("noVNC immediate trigger:") !== 0)) {
return;
}
2018-05-24 00:27:09 +03:00
const index = event.data.slice("noVNC immediate trigger:".length);
2016-10-24 17:37:21 +02:00
2018-05-24 00:27:09 +03:00
const callback = _immediateFuncs[index];
2016-10-24 17:37:21 +02:00
if (callback === undefined) {
return;
}
delete _immediateFuncs[index];
callback();
});
2016-10-24 17:37:21 +02:00
}
2021-07-22 16:56:49 +02:00
class FakeWebSocket {
constructor() {
this.binaryType = "arraybuffer";
this.protocol = "";
this.readyState = "open";
this.onerror = () => {};
this.onmessage = () => {};
this.onopen = () => {};
}
send() {
}
close() {
}
}
2018-07-05 21:31:56 +02:00
export default class RecordingPlayer {
2019-01-08 11:05:05 +01:00
constructor(frames, disconnected) {
2018-07-05 21:31:56 +02:00
this._frames = frames;
2015-05-15 14:27:23 -04:00
2018-07-05 21:31:56 +02:00
this._disconnected = disconnected;
2015-05-15 14:27:23 -04:00
2018-07-05 21:31:56 +02:00
this._rfb = undefined;
2020-05-31 21:03:38 +02:00
this._frameLength = this._frames.length;
2020-05-31 21:03:38 +02:00
this._frameIndex = 0;
this._startTime = undefined;
2018-07-05 21:31:56 +02:00
this._realtime = true;
this._trafficManagement = true;
2018-07-05 21:31:56 +02:00
this._running = false;
this.onfinish = () => {};
2018-07-05 21:31:56 +02:00
}
2018-07-05 21:31:56 +02:00
run(realtime, trafficManagement) {
2017-03-01 21:10:09 -05:00
// initialize a new RFB
2021-07-22 16:56:49 +02:00
this._ws = new FakeWebSocket();
this._rfb = new RFB(document.getElementById('VNC_screen'), this._ws);
2017-10-14 15:39:56 +02:00
this._rfb.viewOnly = true;
this._rfb.addEventListener("disconnect",
this._handleDisconnect.bind(this));
this._rfb.addEventListener("credentialsrequired",
this._handleCredentials.bind(this));
2017-03-01 21:10:09 -05:00
// reset the frame index and timer
2020-05-31 21:03:38 +02:00
this._frameIndex = 0;
this._startTime = (new Date()).getTime();
2017-03-01 21:10:09 -05:00
this._realtime = realtime;
this._trafficManagement = (trafficManagement === undefined) ? !realtime : trafficManagement;
this._running = true;
2021-07-22 16:56:49 +02:00
this._queueNextPacket();
2018-07-05 21:31:56 +02:00
}
2017-03-01 21:10:09 -05:00
2018-07-05 21:31:56 +02:00
_queueNextPacket() {
2017-03-01 21:10:09 -05:00
if (!this._running) { return; }
2020-05-31 21:03:38 +02:00
let frame = this._frames[this._frameIndex];
2017-03-01 21:10:09 -05:00
// skip send frames
2020-05-31 21:03:38 +02:00
while (this._frameIndex < this._frameLength && frame.fromClient) {
this._frameIndex++;
frame = this._frames[this._frameIndex];
2017-03-01 21:10:09 -05:00
}
2020-05-31 21:03:38 +02:00
if (this._frameIndex >= this._frameLength) {
2017-03-01 21:10:09 -05:00
Log.Debug('Finished, no more frames');
this._finish();
return;
}
2017-03-01 21:10:09 -05:00
if (this._realtime) {
2020-05-31 21:03:38 +02:00
const toffset = (new Date()).getTime() - this._startTime;
2019-01-08 11:05:05 +01:00
let delay = frame.timestamp - toffset;
2017-03-01 21:10:09 -05:00
if (delay < 1) delay = 1;
2017-03-01 21:10:09 -05:00
setTimeout(this._doPacket.bind(this), delay);
} else {
setImmediate(this._doPacket.bind(this));
}
2018-07-05 21:31:56 +02:00
}
2017-03-01 21:10:09 -05:00
2018-07-05 21:31:56 +02:00
_doPacket() {
2017-03-01 21:10:09 -05:00
// Avoid having excessive queue buildup in non-realtime mode
2017-06-01 12:50:00 +02:00
if (this._trafficManagement && this._rfb._flushing) {
2023-05-11 22:32:13 +02:00
this._rfb.flush()
.then(() => {
this._doPacket();
});
2017-03-01 21:10:09 -05:00
return;
}
2020-05-31 21:03:38 +02:00
const frame = this._frames[this._frameIndex];
2021-07-22 16:56:49 +02:00
this._ws.onmessage({'data': frame.data});
2020-05-31 21:03:38 +02:00
this._frameIndex++;
2017-03-01 21:10:09 -05:00
this._queueNextPacket();
2018-07-05 21:31:56 +02:00
}
2017-03-01 21:10:09 -05:00
_finish() {
if (this._rfb._display.pending()) {
2023-05-11 22:32:13 +02:00
this._rfb._display.flush()
.then(() => { this._finish(); });
2017-03-01 21:10:09 -05:00
} else {
this._running = false;
2021-07-22 16:56:49 +02:00
this._ws.onclose({code: 1000, reason: ""});
2018-01-26 11:07:58 +01:00
delete this._rfb;
2020-05-31 21:03:38 +02:00
this.onfinish((new Date()).getTime() - this._startTime);
}
2018-07-05 21:31:56 +02:00
}
_handleDisconnect(evt) {
2017-03-01 21:10:09 -05:00
this._running = false;
2020-05-31 21:03:38 +02:00
this._disconnected(evt.detail.clean, this._frameIndex);
2017-03-01 21:10:09 -05:00
}
_handleCredentials(evt) {
this._rfb.sendCredentials({"username": "Foo",
"password": "Bar",
"target": "Baz"});
}
2018-07-05 21:31:56 +02:00
}