UNPKG

@illgrenoble/ngx-remote-desktop

Version:

ngx-remote-desktop is an Angular2+ module for connecting to a remote desktop using the guacamole protocol

314 lines 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var http_1 = require("@angular/http"); var guacamole_common_js_1 = require("@illgrenoble/guacamole-common-js"); var rxjs_1 = require("rxjs"); /** * Manages the connection to the remote desktop */ var RemoteDesktopManager = /** @class */ (function () { /** * Set up the manager * @param tunnel WebsocketTunnel, HTTPTunnel or ChainedTunnel * @param parameters Query parameters to send to the tunnel url */ function RemoteDesktopManager(tunnel) { /** * Remote desktop connection state observable * Subscribe to this if you want to be notified when the connection state changes */ this.onStateChange = new rxjs_1.BehaviorSubject(RemoteDesktopManager.STATE.IDLE); /** * Remote desktop clipboard observable. * Subscribe to this if you want to be notified if text has been cut/copied within * the remote desktop. */ this.onRemoteClipboardData = new rxjs_1.ReplaySubject(1); this.onKeyboardReset = new rxjs_1.BehaviorSubject(true); this.onFocused = new rxjs_1.BehaviorSubject(true); this.onFullScreen = new rxjs_1.BehaviorSubject(false); this.onReconnect = new rxjs_1.Subject(); /** * When an instruction is received from the tunnel */ this.onTunnelInstruction = new rxjs_1.BehaviorSubject(null); this.tunnel = tunnel; this.client = new guacamole_common_js_1.Client(this.tunnel); } /** * Get the guacamole connection state */ RemoteDesktopManager.prototype.getState = function () { return this.onStateChange.getValue(); }; /** * Check to see if the given state equals the current state * @param state */ RemoteDesktopManager.prototype.isState = function (state) { return state === this.onStateChange.getValue(); }; /** * Set the display focus * @param newFocused */ RemoteDesktopManager.prototype.setFocused = function (newFocused) { this.onFocused.next(newFocused); }; /** * Set full screen * @param newFullScreen */ RemoteDesktopManager.prototype.setFullScreen = function (newFullScreen) { this.onFullScreen.next(newFullScreen); }; /** * Is the display full screen? */ RemoteDesktopManager.prototype.isFullScreen = function () { return this.onFullScreen.getValue(); }; /** * Is the tunnel connected? */ RemoteDesktopManager.prototype.isConnected = function () { return this.onStateChange.getValue() === RemoteDesktopManager.STATE.CONNECTED; }; /** * Get the guacamole client */ RemoteDesktopManager.prototype.getClient = function () { return this.client; }; /** * Get the guacamole tunnel */ RemoteDesktopManager.prototype.getTunnel = function () { return this.tunnel; }; /** * Generate a thumbnail * @param {number} width The width of the thumbnail * @param {number} height The height of the thumbnail * @returns {string} An image data url */ RemoteDesktopManager.prototype.createThumbnail = function (width, height) { if (width === void 0) { width = 340; } if (height === void 0) { height = 240; } var display = this.client.getDisplay(); if (display && display.getWidth() > 0 && display.getHeight() > 0) { // Get screenshot var canvas = display.flatten(); var scale = Math.min(width / canvas.width, height / canvas.height, 1); // Create thumbnail canvas var thumbnail = document.createElement('canvas'); thumbnail.width = canvas.width * scale; thumbnail.height = canvas.height * scale; // Scale screenshot to thumbnail var context = thumbnail.getContext('2d'); context.drawImage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, thumbnail.width, thumbnail.height); return thumbnail.toDataURL('image/png'); } return null; }; /** * Generate a screenshot * @param {blob} done Callback with the screenshot blob data */ RemoteDesktopManager.prototype.createScreenshot = function (done) { var display = this.client.getDisplay(); if (display && display.getWidth() > 0 && display.getHeight() > 0) { var canvas = display.flatten(); return canvas.toBlob(done); } done(null); }; /** * Send text to the remote clipboard * @param {string} text Clipboard text to send */ RemoteDesktopManager.prototype.sendRemoteClipboardData = function (text) { if (text) { this.onRemoteClipboardData.next(text); this.client.setClipboard(text); } }; /** * Reset the keyboard * This will release all keys */ RemoteDesktopManager.prototype.resetKeyboard = function () { this.onKeyboardReset.next(true); }; /** * Disconnect from the remote desktop */ RemoteDesktopManager.prototype.disconnect = function () { this.client.disconnect(); }; /** * Connect to the remote desktop */ RemoteDesktopManager.prototype.connect = function (parameters) { if (parameters === void 0) { parameters = {}; } var configuration = this.buildParameters(parameters); this.client.connect(configuration); this.bindEventHandlers(); }; /** * Set the connection state and emit the new state to any subscribers * @param state Connection state */ RemoteDesktopManager.prototype.setState = function (state) { this.onStateChange.next(state); }; /** * Receive clipboard data from the remote desktop and emit an event to the client * @param stream * @param mimetype */ RemoteDesktopManager.prototype.handleClipboard = function (stream, mimetype) { var _this = this; // If the received data is text, read it as a simple string if (/^text\//.exec(mimetype)) { var reader = new guacamole_common_js_1.StringReader(stream); // Assemble received data into a single string var data_1 = ''; reader.ontext = function (text) { return data_1 += text; }; // Set clipboard contents once stream is finished reader.onend = function () { return _this.onRemoteClipboardData.next(data_1); }; } }; /** * Build the URL query parameters to send to the tunnel connection */ RemoteDesktopManager.prototype.buildParameters = function (parameters) { if (parameters === void 0) { parameters = {}; } var params = new http_1.URLSearchParams(); for (var key in parameters) { if (parameters.hasOwnProperty(key)) { params.set(key, parameters[key]); } } return params.toString(); }; /** * Bind the client and tunnel event handlers */ RemoteDesktopManager.prototype.bindEventHandlers = function () { var _this = this; this.client.onerror = this.handleClientError.bind(this); this.client.onstatechange = this.handleClientStateChange.bind(this); this.client.onclipboard = this.handleClipboard.bind(this); this.tunnel.onerror = this.handleTunnelError.bind(this); this.tunnel.onstatechange = this.handleTunnelStateChange.bind(this); /* * Override tunnel instruction message */ this.tunnel.oninstruction = (function (oninstruction) { return function (opcode, parameters) { oninstruction(opcode, parameters); _this.onTunnelInstruction.next({ opcode: opcode, parameters: parameters }); }; })(this.tunnel.oninstruction); }; /** * Handle any client errors by disconnecting and updating the connection state * @param state State received from the client */ RemoteDesktopManager.prototype.handleClientError = function (status) { // Disconnect if connected this.disconnect(); this.setState(RemoteDesktopManager.STATE.CLIENT_ERROR); }; /** * Update the connection state when the client state changes * @param state State received from the client */ RemoteDesktopManager.prototype.handleClientStateChange = function (state) { switch (state) { // Idle case 0: this.setState(RemoteDesktopManager.STATE.IDLE); break; // Ignore "connecting" state case 1:// Connecting break; // Connected + waiting case 2: this.setState(RemoteDesktopManager.STATE.WAITING); break; // Connected case 3: this.setState(RemoteDesktopManager.STATE.CONNECTED); break; // Update history when disconnecting case 4: // Disconnecting case 5:// Disconnected break; } }; /** * Handle any tunnel errors by disconnecting and updating the connection state * @param status Status received from the tunnel */ RemoteDesktopManager.prototype.handleTunnelError = function (status) { this.disconnect(); this.setState(RemoteDesktopManager.STATE.TUNNEL_ERROR); }; /** * Update the connection state when the tunnel state changes * @param state State received from the tunnel */ RemoteDesktopManager.prototype.handleTunnelStateChange = function (state) { switch (state) { // Connection is being established case 1: this.setState(RemoteDesktopManager.STATE.CONNECTING); break; // Connection has closed case 2: this.setState(RemoteDesktopManager.STATE.DISCONNECTED); break; } }; RemoteDesktopManager.STATE = { /** * The machine connection has not yet been attempted. */ IDLE: 'IDLE', /** * The machine connection is being established. */ CONNECTING: 'CONNECTING', /** * The machine connection has been successfully established, and the * client is now waiting for receipt of initial graphical data. */ WAITING: 'WAITING', /** * The Guacamole connection has been successfully established, and * initial graphical data has been received. */ CONNECTED: 'CONNECTED', /** * The machine connection has terminated successfully. No errors are * indicated. */ DISCONNECTED: 'DISCONNECTED', /** * The machine connection has terminated due to an error reported by * the client. The associated error code is stored in statusCode. * */ CLIENT_ERROR: 'CLIENT_ERROR', /** * The machine connection has terminated due to an error reported by * the tunnel. The associated error code is stored in statusCode. */ TUNNEL_ERROR: 'TUNNEL_ERROR' }; return RemoteDesktopManager; }()); exports.RemoteDesktopManager = RemoteDesktopManager; //# sourceMappingURL=remote-desktop-manager.service.js.map