| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 * Connect set-up state machine for Me2Me and IT2Me | 7 * Connect set-up state machine for Me2Me and IT2Me |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 'use strict'; | 10 'use strict'; |
| 11 | 11 |
| 12 /** @suppress {duplicate} */ | 12 /** @suppress {duplicate} */ |
| 13 var remoting = remoting || {}; | 13 var remoting = remoting || {}; |
| 14 | 14 |
| 15 /** | 15 /** |
| 16 * @type {remoting.ClientSession} The client session object, set once the | 16 * @type {remoting.ClientSession} The client session object, set once the |
| 17 * connector has invoked its onOk callback. | 17 * connector has invoked its onOk callback. |
| 18 * TODO(garykac): Have this owned by someone instead of being global. | 18 * TODO(garykac): Have this owned by someone instead of being global. |
| 19 */ | 19 */ |
| 20 remoting.clientSession = null; | 20 remoting.clientSession = null; |
| 21 | 21 |
| 22 /** | 22 /** |
| 23 * @type {remoting.DesktopConnectedView} The client session view object, set | |
| 24 * once the connector has invoked its onOk callback. | |
| 25 * TODO(garykac): Have this owned by someone instead of being global. | |
| 26 */ | |
| 27 remoting.desktopConnectedView = null; | |
| 28 | |
| 29 /** | |
| 30 * @param {HTMLElement} clientContainer Container element for the client view. | 23 * @param {HTMLElement} clientContainer Container element for the client view. |
| 31 * @param {function(remoting.ConnectionInfo):void} onConnected Callback on | 24 * @param {function(remoting.ConnectionInfo):void} onConnected Callback on |
| 32 * success. | 25 * success. |
| 33 * @param {function(!remoting.Error):void} onError Callback on error. | 26 * @param {function(!remoting.Error):void} onError Callback on error. |
| 34 * @param {function(string, string):boolean} appProtocolExtensionHandler The | |
| 35 * handler for the application's protocol extension messages. Returns true | |
| 36 * if a message is recognized; false otherwise. | |
| 37 * @param {function(!remoting.Error):void} onConnectionFailed Callback for when | 27 * @param {function(!remoting.Error):void} onConnectionFailed Callback for when |
| 38 * the connection fails. | 28 * the connection fails. |
| 39 * @param {Array<string>} requiredCapabilities Connector capabilities | 29 * @param {Array<string>} requiredCapabilities Connector capabilities |
| 40 * required by this application. | 30 * required by this application. |
| 41 * @param {string} defaultRemapKeys The default set of key mappings for the | 31 * @param {string} defaultRemapKeys The default set of key mappings for the |
| 42 * client session to use. | 32 * client session to use. |
| 43 * @constructor | 33 * @constructor |
| 44 * @implements {remoting.SessionConnector} | 34 * @implements {remoting.SessionConnector} |
| 45 */ | 35 */ |
| 46 remoting.SessionConnectorImpl = function(clientContainer, onConnected, onError, | 36 remoting.SessionConnectorImpl = function(clientContainer, onConnected, onError, |
| 47 appProtocolExtensionHandler, | |
| 48 onConnectionFailed, | 37 onConnectionFailed, |
| 49 requiredCapabilities, | 38 requiredCapabilities, |
| 50 defaultRemapKeys) { | 39 defaultRemapKeys) { |
| 51 /** @private {HTMLElement} */ | 40 /** @private {HTMLElement} */ |
| 52 this.clientContainer_ = clientContainer; | 41 this.clientContainer_ = clientContainer; |
| 53 | 42 |
| 54 /** @private {function(remoting.ConnectionInfo):void} */ | 43 /** @private {function(remoting.ConnectionInfo):void} */ |
| 55 this.onConnected_ = onConnected; | 44 this.onConnected_ = onConnected; |
| 56 | 45 |
| 57 /** @private {function(!remoting.Error):void} */ | 46 /** @private {function(!remoting.Error):void} */ |
| 58 this.onError_ = onError; | 47 this.onError_ = onError; |
| 59 | 48 |
| 60 /** @private {function(string, string):boolean} */ | |
| 61 this.appProtocolExtensionHandler_ = appProtocolExtensionHandler; | |
| 62 | |
| 63 /** @private {function(!remoting.Error):void} */ | 49 /** @private {function(!remoting.Error):void} */ |
| 64 this.onConnectionFailed_ = onConnectionFailed; | 50 this.onConnectionFailed_ = onConnectionFailed; |
| 65 | 51 |
| 66 /** @private {Array<string>} */ | 52 /** @private {Array<string>} */ |
| 67 this.requiredCapabilities_ = requiredCapabilities; | 53 this.requiredCapabilities_ = requiredCapabilities; |
| 68 | 54 |
| 69 /** @private {string} */ | 55 /** @private {string} */ |
| 70 this.defaultRemapKeys_ = defaultRemapKeys; | 56 this.defaultRemapKeys_ = defaultRemapKeys; |
| 71 | 57 |
| 72 /** @private {remoting.DesktopConnectedView.Mode} */ | 58 /** @private {remoting.DesktopConnectedView.Mode} */ |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 this.connectedView_ = null; | 97 this.connectedView_ = null; |
| 112 | 98 |
| 113 /** @private {XMLHttpRequest} */ | 99 /** @private {XMLHttpRequest} */ |
| 114 this.pendingXhr_ = null; | 100 this.pendingXhr_ = null; |
| 115 | 101 |
| 116 /** @private {remoting.CredentialsProvider} */ | 102 /** @private {remoting.CredentialsProvider} */ |
| 117 this.credentialsProvider_ = null; | 103 this.credentialsProvider_ = null; |
| 118 | 104 |
| 119 /** @private {Object<string,remoting.ProtocolExtension>} */ | 105 /** @private {Object<string,remoting.ProtocolExtension>} */ |
| 120 this.protocolExtensions_ = {}; | 106 this.protocolExtensions_ = {}; |
| 107 |
| 108 /** |
| 109 * True once a session has been created and we've started the extensions. |
| 110 * This is used to immediately start any extensions that are registered |
| 111 * after the CONNECTED state change. |
| 112 * @private {boolean} |
| 113 */ |
| 114 this.protocolExtensionsStarted_ = false; |
| 121 }; | 115 }; |
| 122 | 116 |
| 123 /** | 117 /** |
| 124 * Initiate a Me2Me connection. | 118 * Initiate a Me2Me connection. |
| 125 * | 119 * |
| 126 * This doesn't report host-offline errors because the connection will | 120 * This doesn't report host-offline errors because the connection will |
| 127 * be retried and retryConnectMe2Me is responsible for reporting these errors. | 121 * be retried and retryConnectMe2Me is responsible for reporting these errors. |
| 128 * | 122 * |
| 129 * @param {remoting.Host} host The Me2Me host to which to connect. | 123 * @param {remoting.Host} host The Me2Me host to which to connect. |
| 130 * @param {function(boolean, function(string):void):void} fetchPin Function to | 124 * @param {function(boolean, function(string):void):void} fetchPin Function to |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 this.pluginError_(new remoting.Error( | 347 this.pluginError_(new remoting.Error( |
| 354 remoting.Error.Tag.BAD_PLUGIN_VERSION)); | 348 remoting.Error.Tag.BAD_PLUGIN_VERSION)); |
| 355 return; | 349 return; |
| 356 } | 350 } |
| 357 | 351 |
| 358 this.clientSession_ = new remoting.ClientSession( | 352 this.clientSession_ = new remoting.ClientSession( |
| 359 this.plugin_, this.host_, this.signalStrategy_, this.connectionMode_, | 353 this.plugin_, this.host_, this.signalStrategy_, this.connectionMode_, |
| 360 this.onProtocolExtensionMessage_.bind(this)); | 354 this.onProtocolExtensionMessage_.bind(this)); |
| 361 remoting.clientSession = this.clientSession_; | 355 remoting.clientSession = this.clientSession_; |
| 362 | 356 |
| 363 this.connectedView_ = new remoting.DesktopConnectedView( | |
| 364 this.plugin_, this.clientContainer_, this.host_, | |
| 365 this.connectionMode_, this.defaultRemapKeys_); | |
| 366 remoting.desktopConnectedView = this.connectedView_; | |
| 367 | |
| 368 this.clientSession_.logHostOfflineErrors(this.logHostOfflineErrors_); | 357 this.clientSession_.logHostOfflineErrors(this.logHostOfflineErrors_); |
| 369 this.clientSession_.addEventListener( | 358 this.clientSession_.addEventListener( |
| 370 remoting.ClientSession.Events.stateChanged, | 359 remoting.ClientSession.Events.stateChanged, |
| 371 this.bound_.onStateChange); | 360 this.bound_.onStateChange); |
| 372 | 361 |
| 373 this.plugin_.connect( | 362 this.plugin_.connect( |
| 374 this.host_, this.signalStrategy_.getJid(), this.credentialsProvider_); | 363 this.host_, this.signalStrategy_.getJid(), this.credentialsProvider_); |
| 375 }; | 364 }; |
| 376 | 365 |
| 377 /** | 366 /** |
| 378 * @param {!remoting.Error} error | 367 * @param {!remoting.Error} error |
| 379 * @private | 368 * @private |
| 380 */ | 369 */ |
| 381 remoting.SessionConnectorImpl.prototype.pluginError_ = function(error) { | 370 remoting.SessionConnectorImpl.prototype.pluginError_ = function(error) { |
| 382 this.signalStrategy_.setIncomingStanzaCallback(null); | 371 this.signalStrategy_.setIncomingStanzaCallback(null); |
| 383 this.clientSession_.disconnect(error); | 372 this.clientSession_.disconnect(error); |
| 384 this.removePlugin_(); | 373 this.removePlugin_(); |
| 385 }; | 374 }; |
| 386 | 375 |
| 387 /** @private */ | 376 /** @private */ |
| 388 remoting.SessionConnectorImpl.prototype.removePlugin_ = function() { | 377 remoting.SessionConnectorImpl.prototype.removePlugin_ = function() { |
| 389 if (this.clientSession_) { | 378 if (this.clientSession_) { |
| 390 this.clientSession_.removePlugin(); | 379 this.clientSession_.removePlugin(); |
| 391 } | 380 } |
| 392 this.clientSession_ = null; | 381 this.clientSession_ = null; |
| 393 remoting.clientSession = null; | 382 remoting.clientSession = null; |
| 394 | 383 |
| 395 base.dispose(this.connectedView_); | |
| 396 this.connectedView_ = null; | |
| 397 remoting.desktopConnectedView = null; | |
| 398 | |
| 399 base.dispose(this.plugin_); | 384 base.dispose(this.plugin_); |
| 400 this.plugin_ = null; | 385 this.plugin_ = null; |
| 401 }; | 386 }; |
| 402 | 387 |
| 403 /** | 388 /** |
| 404 * @param {remoting.ProtocolExtension} extension | 389 * @param {remoting.ProtocolExtension} extension |
| 405 */ | 390 */ |
| 406 remoting.SessionConnectorImpl.prototype.registerProtocolExtension = | 391 remoting.SessionConnectorImpl.prototype.registerProtocolExtension = |
| 407 function(extension) { | 392 function(extension) { |
| 408 var type = extension.getType(); | 393 var types = extension.getExtensionTypes(); |
| 409 if (type in this.protocolExtensions_) { | 394 |
| 410 console.error( | 395 // Make sure we don't have an extension of that type already registered. |
| 411 'Attempt to register multiple extensions with the same type: ', type); | 396 for (var i=0, len=types.length; i < len; i++) { |
| 412 return; | 397 if (types[i] in this.protocolExtensions_) { |
| 398 console.error( |
| 399 'Attempt to register multiple extensions of the same type: ', type); |
| 400 return; |
| 401 } |
| 413 } | 402 } |
| 414 this.protocolExtensions_[type] = extension; | 403 |
| 404 for (var i=0, len=types.length; i < len; i++) { |
| 405 var type = types[i]; |
| 406 this.protocolExtensions_[type] = extension; |
| 407 if (this.protocolExtensionsStarted_) { |
| 408 this.startProtocolExtension_(type); |
| 409 } |
| 410 } |
| 415 }; | 411 }; |
| 416 | 412 |
| 417 /** @private */ | 413 /** @private */ |
| 418 remoting.SessionConnectorImpl.prototype.initProtocolExtensions_ = function() { | 414 remoting.SessionConnectorImpl.prototype.initProtocolExtensions_ = function() { |
| 415 base.debug.assert(!this.protocolExtensionsStarted_); |
| 419 for (var type in this.protocolExtensions_) { | 416 for (var type in this.protocolExtensions_) { |
| 420 /** @type {remoting.ProtocolExtension} */ | 417 this.startProtocolExtension_(type); |
| 421 var extension = this.protocolExtensions_[type]; | |
| 422 extension.start(this.plugin_.sendClientMessage.bind(this.plugin_)); | |
| 423 } | 418 } |
| 419 this.protocolExtensionsStarted_ = true; |
| 424 }; | 420 }; |
| 425 | 421 |
| 426 /** | 422 /** |
| 423 * @param {string} type |
| 424 * @private |
| 425 */ |
| 426 remoting.SessionConnectorImpl.prototype.startProtocolExtension_ = |
| 427 function(type) { |
| 428 var extension = this.protocolExtensions_[type]; |
| 429 extension.startExtension(this.plugin_.sendClientMessage.bind(this.plugin_)); |
| 430 }; |
| 431 |
| 432 /** |
| 427 * Called when an extension message needs to be handled. | 433 * Called when an extension message needs to be handled. |
| 428 * | 434 * |
| 429 * @param {string} type The type of the extension message. | 435 * @param {string} type The type of the extension message. |
| 430 * @param {string} data The payload of the extension message. | 436 * @param {string} data The payload of the extension message. |
| 431 * @return {boolean} Return true if the extension message was recognized. | 437 * @return {boolean} Return true if the extension message was recognized. |
| 432 * @private | 438 * @private |
| 433 */ | 439 */ |
| 434 remoting.SessionConnectorImpl.prototype.onProtocolExtensionMessage_ = | 440 remoting.SessionConnectorImpl.prototype.onProtocolExtensionMessage_ = |
| 435 function(type, data) { | 441 function(type, data) { |
| 436 if (type == 'test-echo-reply') { | 442 if (type == 'test-echo-reply') { |
| 437 console.log('Got echo reply: ' + data); | 443 console.log('Got echo reply: ' + data); |
| 438 return true; | 444 return true; |
| 439 } | 445 } |
| 440 for (var type in this.protocolExtensions_) { | 446 |
| 447 var message = base.jsonParseSafe(data); |
| 448 if (typeof message != 'object') { |
| 449 console.error('Error parsing extension json data: ' + data); |
| 450 return false; |
| 451 } |
| 452 |
| 453 if (type in this.protocolExtensions_) { |
| 441 /** @type {remoting.ProtocolExtension} */ | 454 /** @type {remoting.ProtocolExtension} */ |
| 442 var extension = this.protocolExtensions_[type]; | 455 var extension = this.protocolExtensions_[type]; |
| 443 if (type == extension.getType()) { | 456 var handled = false; |
| 444 try { | 457 try { |
| 445 extension.onMessage(data); | 458 handled = extension.onExtensionMessage(type, message); |
| 446 } catch (/** @type {*} */ err) { | 459 } catch (/** @type {*} */ err) { |
| 447 console.error('Failed to process protocol extension ', type, | 460 console.error('Failed to process protocol extension ' + type + |
| 448 ' message: ', err); | 461 ' message: ' + err); |
| 449 } | 462 } |
| 463 if (handled) { |
| 450 return true; | 464 return true; |
| 451 } | 465 } |
| 452 } | 466 } |
| 453 return this.appProtocolExtensionHandler_(type, data); | 467 |
| 468 return false; |
| 454 }; | 469 }; |
| 455 | 470 |
| 456 /** | 471 /** |
| 457 * Handle a change in the state of the client session prior to successful | 472 * Handle a change in the state of the client session prior to successful |
| 458 * connection (after connection, this class no longer handles state change | 473 * connection (after connection, this class no longer handles state change |
| 459 * events). Errors that occur while connecting either trigger a reconnect | 474 * events). Errors that occur while connecting either trigger a reconnect |
| 460 * or notify the onError handler. | 475 * or notify the onError handler. |
| 461 * | 476 * |
| 462 * @param {remoting.ClientSession.StateEvent=} event | 477 * @param {remoting.ClientSession.StateEvent=} event |
| 463 * @return {void} Nothing. | 478 * @return {void} Nothing. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 * @constructor | 550 * @constructor |
| 536 * @implements {remoting.SessionConnectorFactory} | 551 * @implements {remoting.SessionConnectorFactory} |
| 537 */ | 552 */ |
| 538 remoting.DefaultSessionConnectorFactory = function() {}; | 553 remoting.DefaultSessionConnectorFactory = function() {}; |
| 539 | 554 |
| 540 /** | 555 /** |
| 541 * @param {HTMLElement} clientContainer Container element for the client view. | 556 * @param {HTMLElement} clientContainer Container element for the client view. |
| 542 * @param {function(remoting.ConnectionInfo):void} onConnected Callback on | 557 * @param {function(remoting.ConnectionInfo):void} onConnected Callback on |
| 543 * success. | 558 * success. |
| 544 * @param {function(!remoting.Error):void} onError Callback on error. | 559 * @param {function(!remoting.Error):void} onError Callback on error. |
| 545 * @param {function(string, string):boolean} appProtocolExtensionHandler The | |
| 546 * handler for the application's protocol extension messages. Returns true | |
| 547 * if a message is recognized; false otherwise. | |
| 548 * @param {function(!remoting.Error):void} onConnectionFailed Callback for when | 560 * @param {function(!remoting.Error):void} onConnectionFailed Callback for when |
| 549 * the connection fails. | 561 * the connection fails. |
| 550 * @param {Array<string>} requiredCapabilities Connector capabilities | 562 * @param {Array<string>} requiredCapabilities Connector capabilities |
| 551 * required by this application. | 563 * required by this application. |
| 552 * @param {string} defaultRemapKeys The default set of key mappings to use | 564 * @param {string} defaultRemapKeys The default set of key mappings to use |
| 553 * in the client session. | 565 * in the client session. |
| 554 * @return {remoting.SessionConnector} | 566 * @return {remoting.SessionConnector} |
| 555 */ | 567 */ |
| 556 remoting.DefaultSessionConnectorFactory.prototype.createConnector = | 568 remoting.DefaultSessionConnectorFactory.prototype.createConnector = |
| 557 function(clientContainer, onConnected, onError, | 569 function(clientContainer, onConnected, onError, |
| 558 appProtocolExtensionHandler, | |
| 559 onConnectionFailed, requiredCapabilities, defaultRemapKeys) { | 570 onConnectionFailed, requiredCapabilities, defaultRemapKeys) { |
| 560 return new remoting.SessionConnectorImpl(clientContainer, onConnected, | 571 return new remoting.SessionConnectorImpl(clientContainer, onConnected, |
| 561 onError, | 572 onError, |
| 562 appProtocolExtensionHandler, | |
| 563 onConnectionFailed, | 573 onConnectionFailed, |
| 564 requiredCapabilities, | 574 requiredCapabilities, |
| 565 defaultRemapKeys); | 575 defaultRemapKeys); |
| 566 }; | 576 }; |
| OLD | NEW |