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 |