| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * This class implements the functionality that is specific to desktop | 7 * This class implements the functionality that is specific to desktop |
| 8 * remoting ("Chromoting" or CRD). | 8 * remoting ("Chromoting" or CRD). |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 'use strict'; | 11 'use strict'; |
| 12 | 12 |
| 13 /** @suppress {duplicate} */ | 13 /** @suppress {duplicate} */ |
| 14 var remoting = remoting || {}; | 14 var remoting = remoting || {}; |
| 15 | 15 |
| 16 /** | 16 /** |
| 17 * @param {Array<string>} appCapabilities Array of application capabilities. | 17 * @param {Array<string>} appCapabilities Array of application capabilities. |
| 18 * @constructor | 18 * @constructor |
| 19 * @implements {remoting.ApplicationInterface} | 19 * @implements {remoting.ApplicationInterface} |
| 20 * @extends {remoting.Application} | 20 * @extends {remoting.Application} |
| 21 */ | 21 */ |
| 22 remoting.DesktopRemoting = function(appCapabilities) { | 22 remoting.DesktopRemoting = function(appCapabilities) { |
| 23 base.inherits(this, remoting.Application, appCapabilities); | 23 base.inherits(this, remoting.Application, appCapabilities); |
| 24 | 24 |
| 25 /** | 25 /** @private {remoting.DesktopConnectedView} */ |
| 26 * Whether to refresh the JID and retry the connection if the current JID | 26 this.connectedView_ = null; |
| 27 * is offline. | |
| 28 * | |
| 29 * @private {boolean} | |
| 30 */ | |
| 31 this.refreshHostJidIfOffline_ = true; | |
| 32 | 27 |
| 33 /** @private {remoting.DesktopConnectedView} */ | 28 /** @private {remoting.Activity} */ |
| 29 this.activity_ = null; |
| 30 }; |
| 31 |
| 32 /** @private */ |
| 33 remoting.DesktopRemoting.prototype.reset_ = function() { |
| 34 base.dispose(this.connectedView_); |
| 34 this.connectedView_ = null; | 35 this.connectedView_ = null; |
| 35 }; | 36 }; |
| 36 | 37 |
| 37 /** | 38 /** |
| 38 * @return {string} Application product name to be used in UI. | 39 * @return {string} Application product name to be used in UI. |
| 39 * @override {remoting.ApplicationInterface} | 40 * @override {remoting.ApplicationInterface} |
| 40 */ | 41 */ |
| 41 remoting.DesktopRemoting.prototype.getApplicationName = function() { | 42 remoting.DesktopRemoting.prototype.getApplicationName = function() { |
| 42 return chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME'); | 43 return chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME'); |
| 43 }; | 44 }; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 this.closeMainWindow_(); | 146 this.closeMainWindow_(); |
| 146 }; | 147 }; |
| 147 | 148 |
| 148 /** | 149 /** |
| 149 * @param {remoting.ConnectionInfo} connectionInfo | 150 * @param {remoting.ConnectionInfo} connectionInfo |
| 150 * @override {remoting.ApplicationInterface} | 151 * @override {remoting.ApplicationInterface} |
| 151 */ | 152 */ |
| 152 remoting.DesktopRemoting.prototype.onConnected_ = function(connectionInfo) { | 153 remoting.DesktopRemoting.prototype.onConnected_ = function(connectionInfo) { |
| 153 this.initSession_(connectionInfo); | 154 this.initSession_(connectionInfo); |
| 154 | 155 |
| 155 // Set the text on the buttons shown under the error message so that they are | |
| 156 // easy to understand in the case where a successful connection failed, as | |
| 157 // opposed to the case where a connection never succeeded. | |
| 158 // TODO(garykac): Investigate to see if these need to be reverted to their | |
| 159 // original values in the onDisconnected_ method. | |
| 160 var button1 = document.getElementById('client-reconnect-button'); | |
| 161 l10n.localizeElementFromTag(button1, /*i18n-content*/'RECONNECT'); | |
| 162 button1.removeAttribute('autofocus'); | |
| 163 var button2 = document.getElementById('client-finished-me2me-button'); | |
| 164 l10n.localizeElementFromTag(button2, /*i18n-content*/'OK'); | |
| 165 button2.setAttribute('autofocus', 'autofocus'); | |
| 166 | |
| 167 // Reset the refresh flag so that the next connection will retry if needed. | |
| 168 this.refreshHostJidIfOffline_ = true; | |
| 169 | |
| 170 document.getElementById('access-code-entry').value = ''; | |
| 171 remoting.setMode(remoting.AppMode.IN_SESSION); | 156 remoting.setMode(remoting.AppMode.IN_SESSION); |
| 172 if (!base.isAppsV2()) { | 157 if (!base.isAppsV2()) { |
| 173 remoting.toolbar.center(); | 158 remoting.toolbar.center(); |
| 174 remoting.toolbar.preview(); | 159 remoting.toolbar.preview(); |
| 175 } | 160 } |
| 176 | 161 |
| 177 this.connectedView_ = new remoting.DesktopConnectedView( | 162 this.connectedView_ = new remoting.DesktopConnectedView( |
| 178 document.getElementById('client-container'), connectionInfo); | 163 document.getElementById('client-container'), connectionInfo); |
| 179 | 164 |
| 180 // By default, under ChromeOS, remap the right Control key to the right | 165 // By default, under ChromeOS, remap the right Control key to the right |
| 181 // Win / Cmd key. | 166 // Win / Cmd key. |
| 182 if (remoting.platformIsChromeOS()) { | 167 if (remoting.platformIsChromeOS()) { |
| 183 connectionInfo.plugin().setRemapKeys('0x0700e4>0x0700e7'); | 168 connectionInfo.plugin().setRemapKeys('0x0700e4>0x0700e7'); |
| 184 } | 169 } |
| 185 | 170 |
| 186 if (remoting.app.getConnectionMode() === remoting.Application.Mode.ME2ME) { | |
| 187 if (remoting.app.hasCapability(remoting.ClientSession.Capability.CAST)) { | |
| 188 this.sessionConnector_.registerProtocolExtension( | |
| 189 new remoting.CastExtensionHandler()); | |
| 190 } | |
| 191 this.sessionConnector_.registerProtocolExtension( | |
| 192 new remoting.GnubbyAuthHandler()); | |
| 193 } | |
| 194 if (connectionInfo.session().hasCapability( | 171 if (connectionInfo.session().hasCapability( |
| 195 remoting.ClientSession.Capability.VIDEO_RECORDER)) { | 172 remoting.ClientSession.Capability.VIDEO_RECORDER)) { |
| 196 var recorder = new remoting.VideoFrameRecorder(); | 173 var recorder = new remoting.VideoFrameRecorder(); |
| 197 this.sessionConnector_.registerProtocolExtension(recorder); | 174 this.sessionConnector_.registerProtocolExtension(recorder); |
| 198 this.connectedView_.setVideoFrameRecorder(recorder); | 175 this.connectedView_.setVideoFrameRecorder(recorder); |
| 199 } | 176 } |
| 200 | 177 |
| 201 if (remoting.pairingRequested) { | 178 this.activity_.onConnected(connectionInfo); |
| 202 var that = this; | |
| 203 /** | |
| 204 * @param {string} clientId | |
| 205 * @param {string} sharedSecret | |
| 206 */ | |
| 207 var onPairingComplete = function(clientId, sharedSecret) { | |
| 208 var connector = that.sessionConnector_; | |
| 209 var host = remoting.hostList.getHostForId(connector.getHostId()); | |
| 210 host.options.pairingInfo.clientId = clientId; | |
| 211 host.options.pairingInfo.sharedSecret = sharedSecret; | |
| 212 host.options.save(); | |
| 213 connector.updatePairingInfo(clientId, sharedSecret); | |
| 214 }; | |
| 215 // Use the platform name as a proxy for the local computer name. | |
| 216 // TODO(jamiewalch): Use a descriptive name for the local computer, for | |
| 217 // example, its Chrome Sync name. | |
| 218 var clientName = ''; | |
| 219 if (remoting.platformIsMac()) { | |
| 220 clientName = 'Mac'; | |
| 221 } else if (remoting.platformIsWindows()) { | |
| 222 clientName = 'Windows'; | |
| 223 } else if (remoting.platformIsChromeOS()) { | |
| 224 clientName = 'ChromeOS'; | |
| 225 } else if (remoting.platformIsLinux()) { | |
| 226 clientName = 'Linux'; | |
| 227 } else { | |
| 228 console.log('Unrecognized client platform. Using navigator.platform.'); | |
| 229 clientName = navigator.platform; | |
| 230 } | |
| 231 connectionInfo.session().requestPairing(clientName, onPairingComplete); | |
| 232 } | |
| 233 }; | 179 }; |
| 234 | 180 |
| 235 /** | 181 /** |
| 236 * @override {remoting.ApplicationInterface} | 182 * @override {remoting.ApplicationInterface} |
| 237 */ | 183 */ |
| 238 remoting.DesktopRemoting.prototype.onDisconnected_ = function() { | 184 remoting.DesktopRemoting.prototype.onDisconnected_ = function() { |
| 239 var mode = this.getConnectionMode(); | 185 this.activity_.onDisconnected(); |
| 240 if (mode === remoting.Application.Mode.IT2ME) { | 186 this.reset_(); |
| 241 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME); | |
| 242 } else { | |
| 243 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME); | |
| 244 } | |
| 245 base.dispose(this.connectedView_); | |
| 246 this.connectedView_ = null; | |
| 247 }; | 187 }; |
| 248 | 188 |
| 249 /** | 189 /** |
| 250 * @param {!remoting.Error} error | 190 * @param {!remoting.Error} error |
| 251 * @override {remoting.ApplicationInterface} | 191 * @override {remoting.ApplicationInterface} |
| 252 */ | 192 */ |
| 253 remoting.DesktopRemoting.prototype.onConnectionFailed_ = function(error) { | 193 remoting.DesktopRemoting.prototype.onConnectionFailed_ = function(error) { |
| 254 var that = this; | 194 this.activity_.onConnectionFailed(error); |
| 255 var onHostListRefresh = function(/** boolean */ success) { | |
| 256 if (success) { | |
| 257 var connector = that.sessionConnector_; | |
| 258 var host = remoting.hostList.getHostForId(connector.getHostId()); | |
| 259 if (host) { | |
| 260 connector.retryConnectMe2Me(host); | |
| 261 return; | |
| 262 } | |
| 263 } | |
| 264 that.onError_(error); | |
| 265 }; | |
| 266 | |
| 267 var mode = this.getConnectionMode(); | |
| 268 if (error.hasTag(remoting.Error.Tag.HOST_IS_OFFLINE) && | |
| 269 mode === remoting.Application.Mode.ME2ME && | |
| 270 this.refreshHostJidIfOffline_) { | |
| 271 this.refreshHostJidIfOffline_ = false; | |
| 272 | |
| 273 // The plugin will be re-created when the host finished refreshing | |
| 274 remoting.hostList.refresh(onHostListRefresh); | |
| 275 } else { | |
| 276 this.onError_(error); | |
| 277 } | |
| 278 }; | 195 }; |
| 279 | 196 |
| 280 /** | 197 /** |
| 281 * @param {!remoting.Error} error The error to be localized and displayed. | 198 * @param {!remoting.Error} error The error to be localized and displayed. |
| 282 * @override {remoting.ApplicationInterface} | 199 * @override {remoting.ApplicationInterface} |
| 283 */ | 200 */ |
| 284 remoting.DesktopRemoting.prototype.onError_ = function(error) { | 201 remoting.DesktopRemoting.prototype.onError_ = function(error) { |
| 285 console.error('Connection failed: ' + error.toString()); | 202 console.error('Connection failed: ' + error.toString()); |
| 286 var mode = this.getConnectionMode(); | |
| 287 base.dispose(this.connectedView_); | |
| 288 this.connectedView_ = null; | |
| 289 | 203 |
| 290 if (error.hasTag(remoting.Error.Tag.AUTHENTICATION_FAILED)) { | 204 if (error.hasTag(remoting.Error.Tag.AUTHENTICATION_FAILED)) { |
| 291 remoting.setMode(remoting.AppMode.HOME); | 205 remoting.setMode(remoting.AppMode.HOME); |
| 292 remoting.handleAuthFailureAndRelaunch(); | 206 remoting.handleAuthFailureAndRelaunch(); |
| 293 return; | 207 return; |
| 294 } | 208 } |
| 295 | 209 |
| 296 // Reset the refresh flag so that the next connection will retry if needed. | 210 this.activity_.onError(error); |
| 297 this.refreshHostJidIfOffline_ = true; | 211 this.reset_(); |
| 298 | |
| 299 var errorDiv = document.getElementById('connect-error-message'); | |
| 300 l10n.localizeElementFromTag(errorDiv, error.getTag()); | |
| 301 | |
| 302 if (mode == remoting.Application.Mode.IT2ME) { | |
| 303 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME); | |
| 304 } else { | |
| 305 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME); | |
| 306 } | |
| 307 }; | 212 }; |
| 308 | 213 |
| 309 /** | 214 /** |
| 310 * Determine whether or not the app is running in a window. | 215 * Determine whether or not the app is running in a window. |
| 311 * @param {function(boolean):void} callback Callback to receive whether or not | 216 * @param {function(boolean):void} callback Callback to receive whether or not |
| 312 * the current tab is running in windowed mode. | 217 * the current tab is running in windowed mode. |
| 313 * @private | 218 * @private |
| 314 */ | 219 */ |
| 315 remoting.DesktopRemoting.prototype.isWindowed_ = function(callback) { | 220 remoting.DesktopRemoting.prototype.isWindowed_ = function(callback) { |
| 316 /** @param {chrome.Window} win The current window. */ | 221 /** @param {chrome.Window} win The current window. */ |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 | 265 |
| 361 /** | 266 /** |
| 362 * Entry-point for Me2Me connections. | 267 * Entry-point for Me2Me connections. |
| 363 * | 268 * |
| 364 * @param {string} hostId The unique id of the host. | 269 * @param {string} hostId The unique id of the host. |
| 365 * @return {void} Nothing. | 270 * @return {void} Nothing. |
| 366 * @private | 271 * @private |
| 367 */ | 272 */ |
| 368 remoting.DesktopRemoting.prototype.connectMe2Me_ = function(hostId) { | 273 remoting.DesktopRemoting.prototype.connectMe2Me_ = function(hostId) { |
| 369 var host = remoting.hostList.getHostForId(hostId); | 274 var host = remoting.hostList.getHostForId(hostId); |
| 370 var flow = new remoting.Me2MeConnectFlow(this.sessionConnector_, host); | 275 // The Me2MeActivity triggers a reconnect underneath the hood on connection |
| 371 flow.start(); | 276 // failure, but it won't notify the DesktopRemoting upon successful |
| 277 // re-connection. Therefore, we can't dispose the activity on connection |
| 278 // failure. Instead, the activity is only disposed when a new one is |
| 279 // created. This would be fixed once |sessionConnector| is moved out of the |
| 280 // application. |
| 281 base.dispose(this.activity_); |
| 282 this.activity_ = new remoting.Me2MeActivity(this.sessionConnector_, host); |
| 283 this.activity_.start(); |
| 372 }; | 284 }; |
| 373 | 285 |
| 374 /** | 286 /** |
| 375 * Entry-point for It2Me connections. | 287 * Entry-point for It2Me connections. |
| 376 * | 288 * |
| 377 * @private | 289 * @private |
| 378 */ | 290 */ |
| 379 remoting.DesktopRemoting.prototype.connectIt2Me_ = function() { | 291 remoting.DesktopRemoting.prototype.connectIt2Me_ = function() { |
| 380 var flow = new remoting.It2MeConnectFlow(this.sessionConnector_); | 292 base.dispose(this.activity_); |
| 381 flow.start(); | 293 this.activity_ = new remoting.It2MeActivity(this.sessionConnector_); |
| 294 this.activity_.start(); |
| 382 }; | 295 }; |
| OLD | NEW |