Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 * Class handling creation and teardown of a remoting client session. | 7 * Class handling creation and teardown of a remoting client session. |
| 8 * | 8 * |
| 9 * This abstracts a <embed> element and controls the plugin which does the | 9 * This abstracts a <embed> element and controls the plugin which does the |
| 10 * actual remoting work. There should be no UI code inside this class. It | 10 * actual remoting work. There should be no UI code inside this class. It |
| 11 * should be purely thought of as a controller of sorts. | 11 * should be purely thought of as a controller of sorts. |
| 12 */ | 12 */ |
| 13 | 13 |
| 14 'use strict'; | 14 'use strict'; |
| 15 | 15 |
| 16 /** @suppress {duplicate} */ | 16 /** @suppress {duplicate} */ |
| 17 var remoting = remoting || {}; | 17 var remoting = remoting || {}; |
| 18 | 18 |
| 19 /** | 19 /** |
| 20 * @param {string} hostJid The jid of the host to connect to. | 20 * @param {string} hostJid The jid of the host to connect to. |
| 21 * @param {string} hostPublicKey The base64 encoded version of the host's | 21 * @param {string} hostPublicKey The base64 encoded version of the host's |
| 22 * public key. | 22 * public key. |
| 23 * @param {string} accessCode The access code for the IT2Me connection. | 23 * @param {string} accessCode The access code for the IT2Me connection. |
| 24 * @param {string} email The username for the talk network. | 24 * @param {string} email The username for the talk network. |
| 25 * @param {function(remoting.ClientSession.State):void} onStateChange | 25 * @param {function(remoting.ClientSession.State, |
| 26 * The callback to invoke when the session changes state. This callback | 26 remoting.ClientSession.State):void} onStateChange |
| 27 * occurs after the state changes and is passed the previous state; the | 27 * The callback to invoke when the session changes state. |
| 28 * new state is accessible via ClientSession's |state| property. | |
| 29 * @constructor | 28 * @constructor |
| 30 */ | 29 */ |
| 31 remoting.ClientSession = function(hostJid, hostPublicKey, accessCode, email, | 30 remoting.ClientSession = function(hostJid, hostPublicKey, accessCode, email, |
| 32 onStateChange) { | 31 onStateChange) { |
| 33 this.state = remoting.ClientSession.State.CREATED; | 32 this.state = remoting.ClientSession.State.CREATED; |
| 34 | 33 |
| 35 this.hostJid = hostJid; | 34 this.hostJid = hostJid; |
| 36 this.hostPublicKey = hostPublicKey; | 35 this.hostPublicKey = hostPublicKey; |
| 37 this.accessCode = accessCode; | 36 this.accessCode = accessCode; |
| 38 this.email = email; | 37 this.email = email; |
| 39 this.clientJid = ''; | 38 this.clientJid = ''; |
| 40 this.sessionId = ''; | 39 this.sessionId = ''; |
| 41 /** @type {remoting.ViewerPlugin} */ this.plugin = null; | 40 /** @type {remoting.ViewerPlugin} */ this.plugin = null; |
| 42 this.logToServer = new remoting.LogToServer(); | 41 this.logToServer = new remoting.LogToServer(); |
| 43 this.onStateChange = onStateChange; | 42 this.onStateChange = onStateChange; |
| 44 }; | 43 }; |
| 45 | 44 |
| 45 // Note that the (positive) values in both of these enums are copied directly | |
|
Wez
2011/11/16 21:58:26
Why is positive in brackets? Are the negative val
Jamie
2011/11/17 22:06:18
No. I've removed the brackets and expanded a bit.
| |
| 46 // from chromoting_scriptable_object.h and must be kept in sync. | |
| 46 /** @enum {number} */ | 47 /** @enum {number} */ |
| 47 remoting.ClientSession.State = { | 48 remoting.ClientSession.State = { |
| 49 CREATED: -3, | |
| 50 BAD_PLUGIN_VERSION: -2, | |
| 51 UNKNOWN_PLUGIN_ERROR: -1, | |
| 48 UNKNOWN: 0, | 52 UNKNOWN: 0, |
| 49 CREATED: 1, | 53 CONNECTING: 1, |
| 50 BAD_PLUGIN_VERSION: 2, | 54 INITIALIZING: 2, |
| 51 UNKNOWN_PLUGIN_ERROR: 3, | 55 CONNECTED: 3, |
| 52 CONNECTING: 4, | 56 CLOSED: 4, |
| 53 INITIALIZING: 5, | 57 CONNECTION_FAILED: 5 |
| 54 CONNECTED: 6, | |
| 55 CLOSED: 7, | |
| 56 CONNECTION_FAILED: 8 | |
| 57 }; | 58 }; |
| 58 | 59 |
| 59 /** @enum {number} */ | 60 /** @enum {number} */ |
| 60 remoting.ClientSession.ConnectionError = { | 61 remoting.ClientSession.ConnectionError = { |
| 61 NONE: 0, | 62 NONE: 0, |
| 62 HOST_IS_OFFLINE: 1, | 63 HOST_IS_OFFLINE: 1, |
| 63 SESSION_REJECTED: 2, | 64 SESSION_REJECTED: 2, |
| 64 INCOMPATIBLE_PROTOCOL: 3, | 65 INCOMPATIBLE_PROTOCOL: 3, |
| 65 NETWORK_FAILURE: 4, | 66 NETWORK_FAILURE: 4 |
| 66 OTHER: 5 | |
| 67 }; | 67 }; |
| 68 | 68 |
| 69 /** | 69 /** |
| 70 * The current state of the session. | 70 * The current state of the session. |
| 71 * @type {remoting.ClientSession.State} | 71 * @type {remoting.ClientSession.State} |
| 72 */ | 72 */ |
| 73 remoting.ClientSession.prototype.state = remoting.ClientSession.State.UNKNOWN; | 73 remoting.ClientSession.prototype.state = remoting.ClientSession.State.UNKNOWN; |
| 74 | 74 |
| 75 /** | 75 /** |
| 76 * The last connection error. Set when state is set to CONNECTION_FAILED. | 76 * The last connection error. Set when state is set to CONNECTION_FAILED. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 /** | 112 /** |
| 113 * The id of the client plugin | 113 * The id of the client plugin |
| 114 * | 114 * |
| 115 * @const | 115 * @const |
| 116 */ | 116 */ |
| 117 remoting.ClientSession.prototype.PLUGIN_ID = 'session-client-plugin'; | 117 remoting.ClientSession.prototype.PLUGIN_ID = 'session-client-plugin'; |
| 118 | 118 |
| 119 /** | 119 /** |
| 120 * Callback to invoke when the state is changed. | 120 * Callback to invoke when the state is changed. |
| 121 * | 121 * |
| 122 * @param {remoting.ClientSession.State} state The previous state. | 122 * @param {remoting.ClientSession.State} oldState The previous state. |
| 123 * @param {remoting.ClientSession.State} newState The current state. | |
| 123 */ | 124 */ |
| 124 remoting.ClientSession.prototype.onStateChange = function(state) { }; | 125 remoting.ClientSession.prototype.onStateChange = |
| 126 function(oldState, newState) { }; | |
| 125 | 127 |
| 126 /** | 128 /** |
| 127 * Adds <embed> element to |container| and readies the sesion object. | 129 * Adds <embed> element to |container| and readies the sesion object. |
| 128 * | 130 * |
| 129 * @param {Element} container The element to add the plugin to. | 131 * @param {Element} container The element to add the plugin to. |
| 130 * @param {string} oauth2AccessToken A valid OAuth2 access token. | 132 * @param {string} oauth2AccessToken A valid OAuth2 access token. |
| 131 * @return {void} Nothing. | 133 * @return {void} Nothing. |
| 132 */ | 134 */ |
| 133 remoting.ClientSession.prototype.createPluginAndConnect = | 135 remoting.ClientSession.prototype.createPluginAndConnect = |
| 134 function(container, oauth2AccessToken) { | 136 function(container, oauth2AccessToken) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 152 /** @param {string} msg The IQ stanza to send. */ | 154 /** @param {string} msg The IQ stanza to send. */ |
| 153 this.plugin.sendIq = function(msg) { that.sendIq_(msg); }; | 155 this.plugin.sendIq = function(msg) { that.sendIq_(msg); }; |
| 154 /** @param {string} msg The message to log. */ | 156 /** @param {string} msg The message to log. */ |
| 155 this.plugin.debugInfo = function(msg) { | 157 this.plugin.debugInfo = function(msg) { |
| 156 remoting.debug.log('plugin: ' + msg); | 158 remoting.debug.log('plugin: ' + msg); |
| 157 }; | 159 }; |
| 158 | 160 |
| 159 // TODO(ajwong): Is it even worth having this class handle these events? | 161 // TODO(ajwong): Is it even worth having this class handle these events? |
| 160 // Or would it be better to just allow users to pass in their own handlers | 162 // Or would it be better to just allow users to pass in their own handlers |
| 161 // and leave these blank by default? | 163 // and leave these blank by default? |
| 162 this.plugin.connectionInfoUpdate = function() { | 164 /** |
| 163 that.connectionInfoUpdateCallback(); | 165 * @param {number} status The plugin status. |
| 166 * @param {number} error The plugin error status, if any. | |
| 167 */ | |
| 168 this.plugin.connectionInfoUpdate = function(status, error) { | |
| 169 that.connectionInfoUpdateCallback(status, error); | |
| 164 }; | 170 }; |
| 165 this.plugin.desktopSizeUpdate = function() { that.onDesktopSizeChanged_(); }; | 171 this.plugin.desktopSizeUpdate = function() { that.onDesktopSizeChanged_(); }; |
| 166 | 172 |
| 167 // TODO(garykac): Clean exit if |connect| isn't a function. | 173 // TODO(garykac): Clean exit if |connect| isn't a function. |
| 168 if (typeof this.plugin.connect === 'function') { | 174 if (typeof this.plugin.connect === 'function') { |
| 169 this.connectPluginToWcs_(oauth2AccessToken); | 175 this.connectPluginToWcs_(oauth2AccessToken); |
| 170 } else { | 176 } else { |
| 171 remoting.debug.log('ERROR: remoting plugin not loaded'); | 177 remoting.debug.log('ERROR: remoting plugin not loaded'); |
| 172 this.setState_(remoting.ClientSession.State.UNKNOWN_PLUGIN_ERROR); | 178 this.setState_(remoting.ClientSession.State.UNKNOWN_PLUGIN_ERROR); |
| 173 } | 179 } |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 that.plugin.onIq(stanza); | 281 that.plugin.onIq(stanza); |
| 276 } | 282 } |
| 277 remoting.wcs.setOnIq(onIq); | 283 remoting.wcs.setOnIq(onIq); |
| 278 that.plugin.connect(this.hostJid, this.hostPublicKey, this.clientJid, | 284 that.plugin.connect(this.hostJid, this.hostPublicKey, this.clientJid, |
| 279 this.accessCode); | 285 this.accessCode); |
| 280 }; | 286 }; |
| 281 | 287 |
| 282 /** | 288 /** |
| 283 * Callback that the plugin invokes to indicate that the connection | 289 * Callback that the plugin invokes to indicate that the connection |
| 284 * status has changed. | 290 * status has changed. |
| 291 * | |
| 292 * @param {number} status The plugin's status. | |
| 293 * @param {number} error The plugin's error state, if any. | |
| 285 */ | 294 */ |
| 286 remoting.ClientSession.prototype.connectionInfoUpdateCallback = function() { | 295 remoting.ClientSession.prototype.connectionInfoUpdateCallback = |
| 287 var state = this.plugin.status; | 296 function(status, error) { |
| 297 // Old plugins didn't pass the status and error values, so get them directly. | |
| 298 // Note that there is a race condition inherent in this approach. | |
| 299 if (typeof(status) == 'undefined') { | |
| 300 status = this.plugin.status; | |
| 301 } | |
| 302 if (typeof(error) == 'undefined') { | |
| 303 error = this.plugin.error; | |
| 304 } | |
| 288 | 305 |
| 289 // TODO(ajwong): We're doing silly type translation here. Any way to avoid? | 306 if (status == this.plugin.STATUS_CONNECTED) { |
| 290 if (state == this.plugin.STATUS_UNKNOWN) { | |
| 291 this.setState_(remoting.ClientSession.State.UNKNOWN); | |
| 292 } else if (state == this.plugin.STATUS_CONNECTING) { | |
| 293 this.setState_(remoting.ClientSession.State.CONNECTING); | |
| 294 } else if (state == this.plugin.STATUS_INITIALIZING) { | |
| 295 this.setState_(remoting.ClientSession.State.INITIALIZING); | |
| 296 } else if (state == this.plugin.STATUS_CONNECTED) { | |
| 297 this.onDesktopSizeChanged_(); | 307 this.onDesktopSizeChanged_(); |
| 298 this.setState_(remoting.ClientSession.State.CONNECTED); | 308 } else if (status == this.plugin.STATUS_FAILED) { |
| 299 } else if (state == this.plugin.STATUS_CLOSED) { | 309 this.error = /** @type {remoting.ClientSession.ConnectionError} */ (error); |
| 300 this.setState_(remoting.ClientSession.State.CLOSED); | |
| 301 } else if (state == this.plugin.STATUS_FAILED) { | |
| 302 var error = this.plugin.error; | |
| 303 if (error == this.plugin.ERROR_HOST_IS_OFFLINE) { | |
| 304 this.error = remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE; | |
| 305 } else if (error == this.plugin.ERROR_SESSION_REJECTED) { | |
| 306 this.error = remoting.ClientSession.ConnectionError.SESSION_REJECTED; | |
| 307 } else if (error == this.plugin.ERROR_INCOMPATIBLE_PROTOCOL) { | |
| 308 this.error = remoting.ClientSession.ConnectionError.INCOMPATIBLE_PROTOCOL; | |
| 309 } else if (error == this.plugin.ERROR_NETWORK_FAILURE) { | |
| 310 this.error = remoting.ClientSession.ConnectionError.NETWORK_FAILURE; | |
| 311 } else { | |
| 312 this.error = remoting.ClientSession.ConnectionError.OTHER; | |
| 313 } | |
| 314 this.setState_(remoting.ClientSession.State.CONNECTION_FAILED); | |
| 315 } | 310 } |
| 311 this.setState_(/** @type {remoting.ClientSession.State} */ (status)); | |
| 316 }; | 312 }; |
| 317 | 313 |
| 318 /** | 314 /** |
| 319 * @private | 315 * @private |
| 320 * @param {remoting.ClientSession.State} state The new state for the session. | 316 * @param {remoting.ClientSession.State} newState The new state for the session. |
| 321 * @return {void} Nothing. | 317 * @return {void} Nothing. |
| 322 */ | 318 */ |
| 323 remoting.ClientSession.prototype.setState_ = function(state) { | 319 remoting.ClientSession.prototype.setState_ = function(newState) { |
| 324 var oldState = this.state; | 320 var oldState = this.state; |
| 325 this.state = state; | 321 this.state = newState; |
| 326 if (this.onStateChange) { | 322 if (this.onStateChange) { |
| 327 this.onStateChange(oldState); | 323 this.onStateChange(oldState, newState); |
| 328 } | 324 } |
| 329 this.logToServer.logClientSessionStateChange(this.state, this.error); | 325 this.logToServer.logClientSessionStateChange(this.state, this.error); |
| 330 }; | 326 }; |
| 331 | 327 |
| 332 /** | 328 /** |
| 333 * This is a callback that gets called when the window is resized. | 329 * This is a callback that gets called when the window is resized. |
| 334 * | 330 * |
| 335 * @return {void} Nothing. | 331 * @return {void} Nothing. |
| 336 */ | 332 */ |
| 337 remoting.ClientSession.prototype.onWindowSizeChanged = function() { | 333 remoting.ClientSession.prototype.onWindowSizeChanged = function() { |
| 338 remoting.debug.log('window size changed: ' + | |
| 339 window.innerWidth + 'x' + | |
| 340 window.innerHeight); | |
|
Jamie
2011/11/16 00:17:13
Unrelated to this CL; it was just bugging me.
| |
| 341 this.updateDimensions(); | 334 this.updateDimensions(); |
| 342 }; | 335 }; |
| 343 | 336 |
| 344 /** | 337 /** |
| 345 * This is a callback that gets called when the plugin notifies us of a change | 338 * This is a callback that gets called when the plugin notifies us of a change |
| 346 * in the size of the remote desktop. | 339 * in the size of the remote desktop. |
| 347 * | 340 * |
| 348 * @private | 341 * @private |
| 349 * @return {void} Nothing. | 342 * @return {void} Nothing. |
| 350 */ | 343 */ |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 return { | 401 return { |
| 409 'video_bandwidth': this.plugin.videoBandwidth, | 402 'video_bandwidth': this.plugin.videoBandwidth, |
| 410 'video_frame_rate': this.plugin.videoFrameRate, | 403 'video_frame_rate': this.plugin.videoFrameRate, |
| 411 'capture_latency': this.plugin.videoCaptureLatency, | 404 'capture_latency': this.plugin.videoCaptureLatency, |
| 412 'encode_latency': this.plugin.videoEncodeLatency, | 405 'encode_latency': this.plugin.videoEncodeLatency, |
| 413 'decode_latency': this.plugin.videoDecodeLatency, | 406 'decode_latency': this.plugin.videoDecodeLatency, |
| 414 'render_latency': this.plugin.videoRenderLatency, | 407 'render_latency': this.plugin.videoRenderLatency, |
| 415 'roundtrip_latency': this.plugin.roundTripLatency | 408 'roundtrip_latency': this.plugin.roundTripLatency |
| 416 }; | 409 }; |
| 417 }; | 410 }; |
| OLD | NEW |