1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * Class handling user-facing aspects of the client session.
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
16 * @param {HTMLElement} container
17 * @param {remoting.ConnectionInfo} connectionInfo
19 * @extends {base.EventSourceImpl}
20 * @implements {base.Disposable}
22 remoting.DesktopConnectedView = function(container, connectionInfo) {
24 /** @private {HTMLElement} */
25 this.container_ = container;
27 /** @private {remoting.ClientPlugin} */
28 this.plugin_ = connectionInfo.plugin();
30 /** @private {remoting.ClientSession} */
31 this.session_ = connectionInfo.session();
34 this.host_ = connectionInfo.host();
36 /** @private {remoting.DesktopViewport} */
37 this.viewport_ = null;
39 /** private {remoting.ConnectedView} */
42 /** @private {remoting.VideoFrameRecorder} */
43 this.videoFrameRecorder_ = null;
45 /** private {base.Disposable} */
46 this.eventHooks_ = null;
49 this.stats_ = new remoting.ConnectionStats(
50 document.getElementById('statistics'), connectionInfo.plugin());
56 /** @return {void} Nothing. */
57 remoting.DesktopConnectedView.prototype.dispose = function() {
58 if (remoting.windowFrame) {
59 remoting.windowFrame.setDesktopConnectedView(null);
61 if (remoting.toolbar) {
62 remoting.toolbar.setDesktopConnectedView(null);
64 if (remoting.optionsMenu) {
65 remoting.optionsMenu.setDesktopConnectedView(null);
68 document.body.classList.remove('connected');
70 base.dispose(this.eventHooks_);
71 this.eventHooks_ = null;
73 base.dispose(this.viewport_);
74 this.viewport_ = null;
76 base.dispose(this.stats_);
81 * Get host display name.
85 remoting.DesktopConnectedView.prototype.getHostDisplayName = function() {
86 return this.host_.hostName;
90 * @return {boolean} True if shrink-to-fit is enabled; false otherwise.
92 remoting.DesktopConnectedView.prototype.getShrinkToFit = function() {
94 return this.viewport_.getShrinkToFit();
100 * @return {boolean} True if resize-to-client is enabled; false otherwise.
102 remoting.DesktopConnectedView.prototype.getResizeToClient = function() {
103 if (this.viewport_) {
104 return this.viewport_.getResizeToClient();
110 * @return {boolean} True if the right-hand Ctrl key is mapped to the Meta
111 * (Windows, Command) key.
113 remoting.DesktopConnectedView.prototype.getMapRightCtrl = function() {
114 return this.host_.options.remapKeys[0x0700e4] === 0x0700e7;
117 remoting.DesktopConnectedView.prototype.toggleStats = function() {
118 this.stats_.toggle();
122 * @return {boolean} True if the connection stats is visible; false otherwise.
124 remoting.DesktopConnectedView.prototype.isStatsVisible = function() {
125 return this.stats_.isVisible();
129 * @return {Element} The element that should host the plugin.
132 remoting.DesktopConnectedView.prototype.getPluginContainer_ = function() {
133 return this.container_.querySelector('.client-plugin-container');
136 /** @return {remoting.DesktopViewport} */
137 remoting.DesktopConnectedView.prototype.getViewportForTesting = function() {
138 return this.viewport_;
142 remoting.DesktopConnectedView.prototype.initPlugin_ = function() {
143 console.assert(remoting.app instanceof remoting.DesktopRemoting,
144 '|remoting.app| is not an instance of DesktopRemoting.');
145 var drApp = /** @type {remoting.DesktopRemoting} */ (remoting.app);
146 var mode = drApp.getConnectionMode();
148 // Show the Send Keys menu only if the plugin has the injectKeyEvent feature,
149 // and the Ctrl-Alt-Del button only in Me2Me mode.
150 if (!this.plugin_.hasFeature(
151 remoting.ClientPlugin.Feature.INJECT_KEY_EVENT)) {
152 var sendKeysElement = document.getElementById('send-keys-menu');
153 sendKeysElement.hidden = true;
154 } else if (mode == remoting.DesktopRemoting.Mode.IT2ME) {
155 var sendCadElement = document.getElementById('send-ctrl-alt-del');
156 sendCadElement.hidden = true;
161 * This is a callback that gets called when the window is resized.
163 * @return {void} Nothing.
166 remoting.DesktopConnectedView.prototype.onResize_ = function() {
167 if (this.viewport_) {
168 this.viewport_.onResize();
173 remoting.DesktopConnectedView.prototype.initUI_ = function() {
174 document.body.classList.add('connected');
176 this.view_ = new remoting.ConnectedView(
177 this.plugin_, this.container_,
178 this.container_.querySelector('.mouse-cursor-overlay'));
180 var scrollerElement = document.getElementById('scroller');
181 this.viewport_ = new remoting.DesktopViewport(
182 scrollerElement || document.body,
183 this.plugin_.hostDesktop(),
186 if (remoting.windowFrame) {
187 remoting.windowFrame.setDesktopConnectedView(this);
189 if (remoting.toolbar) {
190 remoting.toolbar.setDesktopConnectedView(this);
192 if (remoting.optionsMenu) {
193 remoting.optionsMenu.setDesktopConnectedView(this);
196 // Activate full-screen related UX.
197 this.eventHooks_ = new base.Disposables(
199 new base.EventHook(this.session_,
200 remoting.ClientSession.Events.videoChannelStateChanged,
201 this.view_.onConnectionReady.bind(this.view_)),
202 new base.DomEventHook(window, 'resize', this.onResize_.bind(this), false),
203 new remoting.Fullscreen.EventHook(this.onFullScreenChanged_.bind(this)));
204 this.onFullScreenChanged_(remoting.fullscreen.isActive());
208 * Set the shrink-to-fit and resize-to-client flags and save them if this is
209 * a Me2Me connection.
211 * @param {boolean} shrinkToFit True if the remote desktop should be scaled
212 * down if it is larger than the client window; false if scroll-bars
213 * should be added in this case.
214 * @param {boolean} resizeToClient True if window resizes should cause the
215 * host to attempt to resize its desktop to match the client window size;
216 * false to disable this behaviour for subsequent window resizes--the
217 * current host desktop size is not restored in this case.
218 * @return {void} Nothing.
220 remoting.DesktopConnectedView.prototype.setScreenMode =
221 function(shrinkToFit, resizeToClient) {
222 this.viewport_.setScreenMode(shrinkToFit, resizeToClient);
226 * Called when the full-screen status has changed, either via the
227 * remoting.Fullscreen class, or via a system event such as the Escape key
229 * @param {boolean=} fullscreen True if the app is entering full-screen mode;
230 * false if it is leaving it.
233 remoting.DesktopConnectedView.prototype.onFullScreenChanged_ = function (
235 if (this.viewport_) {
236 // When a window goes full-screen, a resize event is triggered, but the
237 // Fullscreen.isActive call is not guaranteed to return true until the
238 // full-screen event is triggered. In apps v2, the size of the window's
239 // client area is calculated differently in full-screen mode, so register
241 this.viewport_.onResize();
242 this.viewport_.enableBumpScroll(Boolean(fullscreen));
247 * Set whether or not the right-hand Ctrl key should send the Meta (Windows,
250 * @param {boolean} enable True to enable the mapping; false to disable.
252 remoting.DesktopConnectedView.prototype.setMapRightCtrl = function(enable) {
253 if (enable === this.getMapRightCtrl()) {
254 return; // In case right Ctrl is mapped, but not to right Meta.
258 this.host_.options.remapKeys[0x0700e4] = 0x0700e7;
260 delete this.host_.options.remapKeys[0x0700e4]
262 this.setRemapKeys(this.host_.options.remapKeys);
266 * Sends a Ctrl-Alt-Del sequence to the remoting client.
268 * @return {void} Nothing.
270 remoting.DesktopConnectedView.prototype.sendCtrlAltDel = function() {
271 console.log('Sending Ctrl-Alt-Del.');
272 this.plugin_.injectKeyCombination([0x0700e0, 0x0700e2, 0x07004c]);
276 * Sends a Print Screen keypress to the remoting client.
278 * @return {void} Nothing.
280 remoting.DesktopConnectedView.prototype.sendPrintScreen = function() {
281 console.log('Sending Print Screen.');
282 this.plugin_.injectKeyCombination([0x070046]);
286 * Sets and stores the key remapping setting for the current host. If set,
287 * these mappings override the defaults for the client platform.
289 * @param {!Object} remappings
291 remoting.DesktopConnectedView.prototype.setRemapKeys = function(remappings) {
292 this.plugin_.setRemapKeys(remappings);
293 // Save the new remapping setting.
294 this.host_.options.remapKeys =
295 /** @type {!Object} */ (base.deepCopy(remappings));
296 this.host_.options.save();
299 /** @param {remoting.VideoFrameRecorder} recorder */
300 remoting.DesktopConnectedView.prototype.setVideoFrameRecorder =
302 this.videoFrameRecorder_ = recorder;
306 * Returns true if the ClientSession can record video frames to a file.
309 remoting.DesktopConnectedView.prototype.canRecordVideo = function() {
310 return !!this.videoFrameRecorder_;
314 * Returns true if the ClientSession is currently recording video frames.
317 remoting.DesktopConnectedView.prototype.isRecordingVideo = function() {
318 if (!this.videoFrameRecorder_) {
321 return this.videoFrameRecorder_.isRecording();
325 * Starts or stops recording of video frames.
327 remoting.DesktopConnectedView.prototype.startStopRecording = function() {
328 if (this.videoFrameRecorder_) {
329 this.videoFrameRecorder_.startStopRecording();