]> git.proxmox.com Git - mirror_novnc.git/blame - tests/playback.js
Merge branch 'png_cursor' of https://github.com/CendioOssman/noVNC
[mirror_novnc.git] / tests / playback.js
CommitLineData
d595e656
JM
1/*
2 * noVNC: HTML5 VNC client
d58f8b51 3 * Copyright (C) 2012 Joel Martin
1d728ace 4 * Licensed under MPL 2.0 (see LICENSE.txt)
d595e656
JM
5 */
6
d6c17390
SR
7import RFB from '../core/rfb.js';
8import * as Log from '../core/util/logging.js';
9import Base64 from '../core/base64.js';
b8bd88d0 10
e12e2759 11// Immediate polyfill
d6c17390 12if (setImmediate === undefined) {
e12e2759
PO
13 var _immediateIdCounter = 1;
14 var _immediateFuncs = {};
15
d6c17390
SR
16 var setImmediate = function (func) {
17 var index = _immediateIdCounter++;
e12e2759
PO
18 _immediateFuncs[index] = func;
19 window.postMessage("noVNC immediate trigger:" + index, "*");
20 return index;
21 };
22
23 window.clearImmediate = function (id) {
24 _immediateFuncs[id];
25 };
26
27 var _onMessage = function (event) {
28 if ((typeof event.data !== "string") ||
29 (event.data.indexOf("noVNC immediate trigger:") !== 0)) {
30 return;
31 }
32
33 var index = event.data.slice("noVNC immediate trigger:".length);
34
35 var callback = _immediateFuncs[index];
36 if (callback === undefined) {
37 return;
38 }
39
40 delete _immediateFuncs[index];
41
42 callback();
43 };
44 window.addEventListener("message", _onMessage);
45}
46
d6c17390
SR
47export default function RecordingPlayer (frames, encoding, disconnected, notification) {
48 this._frames = frames;
49 this._encoding = encoding;
efed2eea 50
d6c17390
SR
51 this._disconnected = disconnected;
52 this._notification = notification;
efed2eea 53
d6c17390
SR
54 if (this._encoding === undefined) {
55 let frame = this._frames[0];
56 let start = frame.indexOf('{', 1) + 1;
d951b409 57 if (frame.slice(start).startsWith('UkZC')) {
d6c17390 58 this._encoding = 'base64';
d951b409 59 } else {
d6c17390 60 this._encoding = 'binary';
d951b409 61 }
d951b409
PO
62 }
63
d6c17390
SR
64 this._rfb = undefined;
65 this._frame_length = this._frames.length;
b8bd88d0 66
d6c17390
SR
67 this._frame_index = 0;
68 this._start_time = undefined;
69 this._realtime = true;
70 this._trafficManagement = true;
b8bd88d0 71
d6c17390 72 this._running = false;
b8bd88d0 73
d6c17390
SR
74 this.onfinish = function () {};
75}
b8bd88d0 76
d6c17390
SR
77RecordingPlayer.prototype = {
78 run: function (realtime, trafficManagement) {
79 // initialize a new RFB
80 this._rfb = new RFB({'target': document.getElementById('VNC_canvas'),
81 'view_only': true,
82 'onDisconnected': this._handleDisconnect.bind(this),
83 'onNotification': this._notification});
84 this._enablePlaybackMode();
85
86 // reset the frame index and timer
87 this._frame_index = 0;
88 this._start_time = (new Date()).getTime();
89
90 this._realtime = realtime;
91 this._trafficManagement = (trafficManagement === undefined) ? !realtime : trafficManagement;
92
93 this._running = true;
94
95 // launch the tests
96 this._rfb.connect('test', 0, 'bogus');
97
98 this._queueNextPacket();
99 },
100
101 // _enablePlaybackMode mocks out things not required for running playback
102 _enablePlaybackMode: function () {
103 this._rfb._sock.send = function (arr) {};
104 this._rfb._sock.close = function () {};
105 this._rfb._sock.flush = function () {};
106 this._rfb._checkEvents = function () {};
107 this._rfb.connect = function (host, port, password, path) {
108 this._rfb_host = host;
109 this._rfb_port = port;
110 this._rfb_password = (password !== undefined) ? password : "";
111 this._rfb_path = (path !== undefined) ? path : "";
112 this._sock.init('binary', 'ws');
113 this._rfb_connection_state = 'connecting';
114 this._rfb_init_state = 'ProtocolVersion';
115 };
116 },
117
118 _queueNextPacket: function () {
119 if (!this._running) { return; }
120
121 var frame = this._frames[this._frame_index];
122
123 // skip send frames
124 while (this._frame_index < this._frame_length && frame.charAt(0) === "}") {
125 this._frame_index++;
126 frame = this._frames[this._frame_index];
127 }
18e96092 128
d6c17390
SR
129 if (frame === 'EOF') {
130 Log.Debug('Finished, found EOF');
131 this._finish();
132 return;
133 }
b8bd88d0 134
d6c17390
SR
135 if (this._frame_index >= this._frame_length) {
136 Log.Debug('Finished, no more frames');
137 this._finish();
138 return;
139 }
b8bd88d0 140
d6c17390
SR
141 if (this._realtime) {
142 let foffset = frame.slice(1, frame.indexOf('{', 1));
143 let toffset = (new Date()).getTime() - this._start_time;
144 let delay = foffset - toffset;
145 if (delay < 1) delay = 1;
b8bd88d0 146
d6c17390
SR
147 setTimeout(this._doPacket.bind(this), delay);
148 } else {
149 setImmediate(this._doPacket.bind(this));
150 }
151 },
152
153 _doPacket: function () {
154 // Avoid having excessive queue buildup in non-realtime mode
155 if (!this._trafficManagement && this._rfb._flushing) {
156 let player = this;
157 this._rfb.display.set_onFlush(function () {
158 this._rfb._display.set_onFlush(this._rfb._onFlush.bind(this._rfb));
159 this._rfb._onFlush();
160 player._doPacket();
161 });
162 return;
b8bd88d0
JM
163 }
164
d6c17390
SR
165 const frame = this._frames[this._frame_index];
166 var start = frame.indexOf('{', 1) + 1;
167 if (this._encoding === 'base64') {
168 var u8 = Base64.decode(frame.slice(start));
169 start = 0;
170 } else {
171 var u8 = new Uint8Array(frame.length - start);
172 for (let i = 0; i < frame.length - start; i++) {
173 u8[i] = frame.charCodeAt(start + i);
174 }
175 }
18e96092 176
d6c17390
SR
177 this._rfb._sock._recv_message({'data': u8});
178 this._frame_index++;
179
180 this._queueNextPacket();
181 },
182
183 _finish() {
184 if (this._rfb._display.pending()) {
185 var player = this;
186 this._rfb._display.set_onFlush(function () {
187 if (player._rfb._flushing) {
188 player._rfb._onFlush();
189 }
190 player._finish();
191 });
192 this._rfb._display.flush();
193 } else {
194 this._running = false;
195 this.onfinish((new Date()).getTime() - this._start_time);
e7e66602 196 }
d6c17390 197 },
b8bd88d0 198
d6c17390
SR
199 _handleDisconnect(rfb, reason) {
200 this._running = false;
201 this._disconnected(rfb, reason, this._frame_index);
202 }
d595e656 203};