1 // Copyright 2014 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 * This class implements the functionality that is specific to desktop
8 * remoting ("Chromoting" or CRD).
13 /** @suppress {duplicate} */
14 var remoting = remoting || {};
17 * @param {remoting.Application} app The main app that owns this delegate.
19 * @implements {remoting.Application.Delegate}
21 remoting.DesktopRemoting = function(app) {
23 * TODO(garykac): Remove this reference to the Application. It's only
24 * needed to get the current mode when reporting errors. So we should be
25 * able to refactor and remove this reference cycle.
27 * @type {remoting.Application}
31 app.setDelegate(this);
34 * Whether to refresh the JID and retry the connection if the current JID
40 this.refreshHostJidIfOffline_ = true;
44 * Display the user's email address and allow access to the rest of the app,
45 * including parsing URL parameters.
47 * @param {string} email The user's email address.
48 * @param {string} fullName The user's full name. This is always null since
49 * CRD doesn't request userinfo.profile permission.
50 * @return {void} Nothing.
52 remoting.onUserInfoAvailable = function(email, fullName) {
53 document.getElementById('current-email').innerText = email;
54 document.getElementById('get-started-it2me').disabled = false;
55 document.getElementById('get-started-me2me').disabled = false;
59 * Initialize the application and register all event handlers. After this
60 * is called, the app is running and waiting for user events.
62 * @return {void} Nothing.
64 remoting.DesktopRemoting.prototype.init = function() {
65 remoting.initGlobalObjects();
66 remoting.initIdentity(remoting.onUserInfoAvailable);
68 remoting.initElementEventHandlers();
69 remoting.initGlobalEventHandlers();
71 if (base.isAppsV2()) {
72 remoting.fullscreen = new remoting.FullscreenAppsV2();
73 remoting.windowFrame = new remoting.WindowFrame(
74 document.getElementById('title-bar'));
75 remoting.optionsMenu = remoting.windowFrame.createOptionsMenu();
77 remoting.fullscreen = new remoting.FullscreenAppsV1();
78 remoting.toolbar = new remoting.Toolbar(
79 document.getElementById('session-toolbar'));
80 remoting.optionsMenu = remoting.toolbar.createOptionsMenu();
83 remoting.initHostlist_();
85 var homeFeedback = new remoting.MenuButton(
86 document.getElementById('help-feedback-main'));
87 var toolbarFeedback = new remoting.MenuButton(
88 document.getElementById('help-feedback-toolbar'));
89 remoting.manageHelpAndFeedback(
90 document.getElementById('title-bar'));
91 remoting.manageHelpAndFeedback(
92 document.getElementById('help-feedback-toolbar'));
93 remoting.manageHelpAndFeedback(
94 document.getElementById('help-feedback-main'));
96 remoting.windowShape.updateClientWindowShape();
98 remoting.showOrHideIT2MeUi();
99 remoting.showOrHideMe2MeUi();
101 // For Apps v1, check the tab type to warn the user if they are not getting
102 // the best keyboard experience.
103 if (!base.isAppsV2() && !remoting.platformIsMac()) {
104 /** @param {boolean} isWindowed */
105 var onIsWindowed = function(isWindowed) {
107 document.getElementById('startup-mode-box-me2me').hidden = false;
108 document.getElementById('startup-mode-box-it2me').hidden = false;
111 isWindowed_(onIsWindowed);
114 remoting.ClientPlugin.factory.preloadPlugin();
118 * @return {string} The default remap keys for the current platform.
120 remoting.DesktopRemoting.prototype.getDefaultRemapKeys = function() {
122 // By default, under ChromeOS, remap the right Control key to the right
124 if (remoting.platformIsChromeOS()) {
125 remapKeys = '0x0700e4>0x0700e7';
131 * @return {Array.<string>} A list of |ClientSession.Capability|s required
132 * by this application.
134 remoting.DesktopRemoting.prototype.getRequiredCapabilities = function() {
136 remoting.ClientSession.Capability.SEND_INITIAL_RESOLUTION,
137 remoting.ClientSession.Capability.RATE_LIMIT_RESIZE_REQUESTS,
138 remoting.ClientSession.Capability.VIDEO_RECORDER,
139 // TODO(aiguha): Add this capability based on a gyp/command-line flag,
140 // rather than by default.
141 remoting.ClientSession.Capability.CAST,
142 remoting.ClientSession.Capability.GNUBBY_AUTH
147 * Called when a new session has been connected.
149 * @param {remoting.ClientSession} clientSession
150 * @return {void} Nothing.
152 remoting.DesktopRemoting.prototype.handleConnected = function(clientSession) {
153 // Set the text on the buttons shown under the error message so that they are
154 // easy to understand in the case where a successful connection failed, as
155 // opposed to the case where a connection never succeeded.
156 // TODO(garykac): Investigate to see if these need to be reverted to their
157 // original values in the onDisconnected method.
158 var button1 = document.getElementById('client-reconnect-button');
159 l10n.localizeElementFromTag(button1, /*i18n-content*/'RECONNECT');
160 button1.removeAttribute('autofocus');
161 var button2 = document.getElementById('client-finished-me2me-button');
162 l10n.localizeElementFromTag(button2, /*i18n-content*/'OK');
163 button2.setAttribute('autofocus', 'autofocus');
165 // Reset the refresh flag so that the next connection will retry if needed.
166 this.refreshHostJidIfOffline_ = true;
168 document.getElementById('access-code-entry').value = '';
169 remoting.setMode(remoting.AppMode.IN_SESSION);
170 if (!base.isAppsV2()) {
171 remoting.toolbar.center();
172 remoting.toolbar.preview();
175 if (remoting.pairingRequested) {
177 * @param {string} clientId
178 * @param {string} sharedSecret
180 var onPairingComplete = function(clientId, sharedSecret) {
184 sharedSecret: sharedSecret
187 var connector = remoting.app.getSessionConnector();
188 remoting.HostSettings.save(connector.getHostId(), pairingInfo);
189 connector.updatePairingInfo(clientId, sharedSecret);
191 // Use the platform name as a proxy for the local computer name.
192 // TODO(jamiewalch): Use a descriptive name for the local computer, for
193 // example, its Chrome Sync name.
195 if (remoting.platformIsMac()) {
197 } else if (remoting.platformIsWindows()) {
198 clientName = 'Windows';
199 } else if (remoting.platformIsChromeOS()) {
200 clientName = 'ChromeOS';
201 } else if (remoting.platformIsLinux()) {
202 clientName = 'Linux';
204 console.log('Unrecognized client platform. Using navigator.platform.');
205 clientName = navigator.platform;
207 clientSession.requestPairing(clientName, onPairingComplete);
212 * Called when the current session has been disconnected.
214 * @return {void} Nothing.
216 remoting.DesktopRemoting.prototype.handleDisconnected = function() {
220 * Called when the current session's connection has failed.
222 * @param {remoting.SessionConnector} connector
223 * @param {remoting.Error} error
224 * @return {void} Nothing.
226 remoting.DesktopRemoting.prototype.handleConnectionFailed = function(
228 /** @type {remoting.DesktopRemoting} */
231 /** @param {boolean} success */
232 var onHostListRefresh = function(success) {
234 var host = remoting.hostList.getHostForId(connector.getHostId());
236 connector.retryConnectMe2Me(host);
240 that.handleError(error);
243 if (error == remoting.Error.HOST_IS_OFFLINE &&
244 that.refreshHostJidIfOffline_) {
245 that.refreshHostJidIfOffline_ = false;
246 // The plugin will be re-created when the host finished refreshing
247 remoting.hostList.refresh(onHostListRefresh);
249 this.handleError(error);
254 * Called when the current session has reached the point where the host has
255 * started streaming video frames to the client.
257 * @return {void} Nothing.
259 remoting.DesktopRemoting.prototype.handleVideoStreamingStarted = function() {
263 * @param {string} type The type of the extension message.
264 * @param {string} data The payload of the extension message.
265 * @return {boolean} Return true if the extension message was recognized.
267 remoting.DesktopRemoting.prototype.handleExtensionMessage = function(
273 * Called when an error needs to be displayed to the user.
275 * @param {remoting.Error} errorTag The error to be localized and displayed.
276 * @return {void} Nothing.
278 remoting.DesktopRemoting.prototype.handleError = function(errorTag) {
279 console.error('Connection failed: ' + errorTag);
280 remoting.accessCode = '';
282 // Reset the refresh flag so that the next connection will retry if needed.
283 this.refreshHostJidIfOffline_ = true;
285 var errorDiv = document.getElementById('connect-error-message');
286 l10n.localizeElementFromTag(errorDiv, /** @type {string} */ (errorTag));
288 var mode = remoting.clientSession ? remoting.clientSession.getMode()
289 : this.app_.getSessionConnector().getConnectionMode();
290 if (mode == remoting.ClientSession.Mode.IT2ME) {
291 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME);
292 remoting.hangoutSessionEvents.raiseEvent(
293 remoting.hangoutSessionEvents.sessionStateChanged,
294 remoting.ClientSession.State.FAILED
297 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME);