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 * @param {HTMLElement} clientContainer Container element for the client view. | 16 * @param {HTMLElement} clientContainer Container element for the client view. |
17 * @param {function(remoting.ClientSession):void} onOk Callback on success. | 17 * @param {function(remoting.ClientSession):void} onConnected Callback on |
| 18 * success. |
18 * @param {function(remoting.Error):void} onError Callback on error. | 19 * @param {function(remoting.Error):void} onError Callback on error. |
19 * @param {function(string, string):boolean} onExtensionMessage The handler for | 20 * @param {function(string, string):boolean} onExtensionMessage The handler for |
20 * protocol extension messages. Returns true if a message is recognized; | 21 * protocol extension messages. Returns true if a message is recognized; |
21 * false otherwise. | 22 * false otherwise. |
22 * @constructor | 23 * @constructor |
23 */ | 24 */ |
24 remoting.SessionConnector = function(clientContainer, onOk, onError, | 25 remoting.SessionConnector = function(clientContainer, onConnected, onError, |
25 onExtensionMessage) { | 26 onExtensionMessage) { |
26 /** | 27 /** |
27 * @type {HTMLElement} | 28 * @type {HTMLElement} |
28 * @private | 29 * @private |
29 */ | 30 */ |
30 this.clientContainer_ = clientContainer; | 31 this.clientContainer_ = clientContainer; |
31 | 32 |
32 /** | 33 /** |
33 * @type {function(remoting.ClientSession):void} | 34 * @type {function(remoting.ClientSession):void} |
34 * @private | 35 * @private |
35 */ | 36 */ |
36 this.onOk_ = onOk; | 37 this.onConnected_ = onConnected; |
37 | 38 |
38 /** | 39 /** |
39 * @type {function(remoting.Error):void} | 40 * @type {function(remoting.Error):void} |
40 * @private | 41 * @private |
41 */ | 42 */ |
42 this.onError_ = onError; | 43 this.onError_ = onError; |
43 | 44 |
44 /** | 45 /** |
45 * @type {function(string, string):boolean} | 46 * @type {function(string, string):boolean} |
46 * @private | 47 * @private |
47 */ | 48 */ |
48 this.onExtensionMessage_ = onExtensionMessage; | 49 this.onExtensionMessage_ = onExtensionMessage; |
49 | 50 |
50 /** | 51 /** |
51 * @type {string} | 52 * @type {string} |
52 * @private | 53 * @private |
53 */ | 54 */ |
54 this.clientJid_ = ''; | 55 this.clientJid_ = ''; |
55 | 56 |
56 /** | 57 /** |
57 * @type {remoting.ClientSession.Mode} | 58 * @type {remoting.ClientSession.Mode} |
58 * @private | 59 * @private |
59 */ | 60 */ |
60 this.connectionMode_ = remoting.ClientSession.Mode.ME2ME; | 61 this.connectionMode_ = remoting.ClientSession.Mode.ME2ME; |
61 | 62 |
62 /** | 63 /** |
| 64 * @type {remoting.SignalStrategy} |
| 65 * @private |
| 66 */ |
| 67 this.signalStrategy_ = null; |
| 68 |
| 69 /** |
63 * @type {remoting.SmartReconnector} | 70 * @type {remoting.SmartReconnector} |
64 * @private | 71 * @private |
65 */ | 72 */ |
66 this.reconnector_ = null; | 73 this.reconnector_ = null; |
67 | 74 |
68 /** | 75 /** |
69 * @private | 76 * @private |
70 */ | 77 */ |
71 this.bound_ = { | 78 this.bound_ = { |
72 onStateChange : this.onStateChange_.bind(this) | 79 onStateChange : this.onStateChange_.bind(this) |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 | 256 |
250 this.hostId_ = hostId; | 257 this.hostId_ = hostId; |
251 this.hostJid_ = hostJid; | 258 this.hostJid_ = hostJid; |
252 this.hostPublicKey_ = hostPublicKey; | 259 this.hostPublicKey_ = hostPublicKey; |
253 this.fetchPin_ = fetchPin; | 260 this.fetchPin_ = fetchPin; |
254 this.fetchThirdPartyToken_ = fetchThirdPartyToken; | 261 this.fetchThirdPartyToken_ = fetchThirdPartyToken; |
255 this.hostDisplayName_ = hostDisplayName; | 262 this.hostDisplayName_ = hostDisplayName; |
256 this.connectionMode_ = remoting.ClientSession.Mode.ME2ME; | 263 this.connectionMode_ = remoting.ClientSession.Mode.ME2ME; |
257 this.refreshHostJidIfOffline_ = refreshHostJidIfOffline; | 264 this.refreshHostJidIfOffline_ = refreshHostJidIfOffline; |
258 this.updatePairingInfo(clientPairingId, clientPairedSecret); | 265 this.updatePairingInfo(clientPairingId, clientPairedSecret); |
259 this.createSession_(); | 266 |
260 }; | 267 this.connectSignaling_(); |
| 268 } |
261 | 269 |
262 /** | 270 /** |
263 * Initiate an IT2Me connection. | 271 * Initiate an IT2Me connection. |
264 * | 272 * |
265 * @param {string} accessCode The access code as entered by the user. | 273 * @param {string} accessCode The access code as entered by the user. |
266 * @return {void} Nothing. | 274 * @return {void} Nothing. |
267 */ | 275 */ |
268 remoting.SessionConnector.prototype.connectIT2Me = function(accessCode) { | 276 remoting.SessionConnector.prototype.connectIT2Me = function(accessCode) { |
269 var kSupportIdLen = 7; | 277 var kSupportIdLen = 7; |
270 var kHostSecretLen = 5; | 278 var kHostSecretLen = 5; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 /** | 337 /** |
330 * Get host ID. | 338 * Get host ID. |
331 * | 339 * |
332 * @return {string} | 340 * @return {string} |
333 */ | 341 */ |
334 remoting.SessionConnector.prototype.getHostId = function() { | 342 remoting.SessionConnector.prototype.getHostId = function() { |
335 return this.hostId_; | 343 return this.hostId_; |
336 }; | 344 }; |
337 | 345 |
338 /** | 346 /** |
| 347 * @private |
| 348 */ |
| 349 remoting.SessionConnector.prototype.connectSignaling_ = function() { |
| 350 base.dispose(this.signalStrategy_); |
| 351 this.signalStrategy_ = null; |
| 352 |
| 353 /** @type {remoting.SessionConnector} */ |
| 354 var that = this; |
| 355 |
| 356 /** @param {string} token */ |
| 357 function connectSignalingWithToken(token) { |
| 358 remoting.identity.getEmail( |
| 359 connectSignalingWithTokenAndEmail.bind(null, token), that.onError_); |
| 360 } |
| 361 |
| 362 /** |
| 363 * @param {string} token |
| 364 * @param {string} email |
| 365 */ |
| 366 function connectSignalingWithTokenAndEmail(token, email) { |
| 367 that.signalStrategy_.connect( |
| 368 remoting.settings.XMPP_SERVER_ADDRESS, email, token); |
| 369 } |
| 370 |
| 371 // Only use XMPP when TCP API is available and TLS support is enabled. That's |
| 372 // not the case for V1 app (socket API is available only to platform apps) |
| 373 // and for Chrome releases before 38. |
| 374 if (chrome.socket.secure) { |
| 375 this.signalStrategy_ = /** @type {remoting.SignalStrategy} */ |
| 376 (new remoting.XmppConnection(this.onSignalingState_.bind(this))); |
| 377 } else { |
| 378 this.signalStrategy_ = /** @type {remoting.SignalStrategy} */ |
| 379 (new remoting.WcsAdapter(this.onSignalingState_.bind(this))); |
| 380 } |
| 381 |
| 382 remoting.identity.callWithToken(connectSignalingWithToken, this.onError_); |
| 383 }; |
| 384 |
| 385 /** |
| 386 * @private |
| 387 * @param {remoting.SignalStrategy.State} state |
| 388 */ |
| 389 remoting.SessionConnector.prototype.onSignalingState_ = function(state) { |
| 390 switch (state) { |
| 391 case remoting.SignalStrategy.State.CONNECTED: |
| 392 // Proceed only if the connection hasn't been canceled. |
| 393 if (this.hostJid_) { |
| 394 this.createSession_(); |
| 395 } |
| 396 break; |
| 397 |
| 398 case remoting.SignalStrategy.State.FAILED: |
| 399 this.onError_(this.signalStrategy_.getError()); |
| 400 break; |
| 401 } |
| 402 }; |
| 403 |
| 404 /** |
339 * Continue an IT2Me connection once an access token has been obtained. | 405 * Continue an IT2Me connection once an access token has been obtained. |
340 * | 406 * |
341 * @param {string} token An OAuth2 access token. | 407 * @param {string} token An OAuth2 access token. |
342 * @return {void} Nothing. | 408 * @return {void} Nothing. |
343 * @private | 409 * @private |
344 */ | 410 */ |
345 remoting.SessionConnector.prototype.connectIT2MeWithToken_ = function(token) { | 411 remoting.SessionConnector.prototype.connectIT2MeWithToken_ = function(token) { |
346 // Resolve the host id to get the host JID. | 412 // Resolve the host id to get the host JID. |
347 this.pendingXhr_ = remoting.xhr.get( | 413 this.pendingXhr_ = remoting.xhr.get( |
348 remoting.settings.DIRECTORY_API_BASE_URL + '/support-hosts/' + | 414 remoting.settings.DIRECTORY_API_BASE_URL + '/support-hosts/' + |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 // in a new clientJid and a new callback. In this case, remove the old | 452 // in a new clientJid and a new callback. In this case, remove the old |
387 // client plugin before instantiating a new one. | 453 // client plugin before instantiating a new one. |
388 if (this.clientSession_) { | 454 if (this.clientSession_) { |
389 this.clientSession_.removePlugin(); | 455 this.clientSession_.removePlugin(); |
390 this.clientSession_ = null; | 456 this.clientSession_ = null; |
391 } | 457 } |
392 | 458 |
393 var authenticationMethods = | 459 var authenticationMethods = |
394 'third_party,spake2_pair,spake2_hmac,spake2_plain'; | 460 'third_party,spake2_pair,spake2_hmac,spake2_plain'; |
395 this.clientSession_ = new remoting.ClientSession( | 461 this.clientSession_ = new remoting.ClientSession( |
396 this.clientContainer_, this.hostDisplayName_, this.passPhrase_, | 462 this.signalStrategy_, this.clientContainer_, this.hostDisplayName_, |
397 this.fetchPin_, this.fetchThirdPartyToken_, authenticationMethods, | 463 this.passPhrase_, this.fetchPin_, this.fetchThirdPartyToken_, |
398 this.hostId_, this.hostJid_, this.hostPublicKey_, this.connectionMode_, | 464 authenticationMethods, this.hostId_, this.hostJid_, this.hostPublicKey_, |
399 this.clientPairingId_, this.clientPairedSecret_); | 465 this.connectionMode_, this.clientPairingId_, this.clientPairedSecret_); |
400 this.clientSession_.logHostOfflineErrors(!this.refreshHostJidIfOffline_); | 466 this.clientSession_.logHostOfflineErrors(!this.refreshHostJidIfOffline_); |
401 this.clientSession_.addEventListener( | 467 this.clientSession_.addEventListener( |
402 remoting.ClientSession.Events.stateChanged, | 468 remoting.ClientSession.Events.stateChanged, |
403 this.bound_.onStateChange); | 469 this.bound_.onStateChange); |
404 this.clientSession_.createPluginAndConnect(this.onExtensionMessage_); | 470 this.clientSession_.createPluginAndConnect(this.onExtensionMessage_); |
405 }; | 471 }; |
406 | 472 |
407 /** | 473 /** |
408 * Handle a change in the state of the client session prior to successful | 474 * Handle a change in the state of the client session prior to successful |
409 * connection (after connection, this class no longer handles state change | 475 * connection (after connection, this class no longer handles state change |
410 * events). Errors that occur while connecting either trigger a reconnect | 476 * events). Errors that occur while connecting either trigger a reconnect |
411 * or notify the onError handler. | 477 * or notify the onError handler. |
412 * | 478 * |
413 * @param {remoting.ClientSession.StateEvent} event | 479 * @param {remoting.ClientSession.StateEvent} event |
414 * @return {void} Nothing. | 480 * @return {void} Nothing. |
415 * @private | 481 * @private |
416 */ | 482 */ |
417 remoting.SessionConnector.prototype.onStateChange_ = function(event) { | 483 remoting.SessionConnector.prototype.onStateChange_ = function(event) { |
418 switch (event.current) { | 484 switch (event.current) { |
419 case remoting.ClientSession.State.CONNECTED: | 485 case remoting.ClientSession.State.CONNECTED: |
420 // When the connection succeeds, deregister for state-change callbacks | 486 // When the connection succeeds, deregister for state-change callbacks |
421 // and pass the session to the onOk callback. It is expected that it | 487 // and pass the session to the onConnected callback. It is expected that |
422 // will register a new state-change callback to handle disconnect | 488 // it will register a new state-change callback to handle disconnect |
423 // or error conditions. | 489 // or error conditions. |
424 this.clientSession_.removeEventListener( | 490 this.clientSession_.removeEventListener( |
425 remoting.ClientSession.Events.stateChanged, | 491 remoting.ClientSession.Events.stateChanged, |
426 this.bound_.onStateChange); | 492 this.bound_.onStateChange); |
427 | 493 |
428 base.dispose(this.reconnector_); | 494 base.dispose(this.reconnector_); |
429 if (this.connectionMode_ != remoting.ClientSession.Mode.IT2ME) { | 495 if (this.connectionMode_ != remoting.ClientSession.Mode.IT2ME) { |
430 this.reconnector_ = | 496 this.reconnector_ = |
431 new remoting.SmartReconnector(this, this.clientSession_); | 497 new remoting.SmartReconnector(this, this.clientSession_); |
432 } | 498 } |
433 this.onOk_(this.clientSession_); | 499 this.onConnected_(this.clientSession_); |
434 break; | 500 break; |
435 | 501 |
436 case remoting.ClientSession.State.CREATED: | 502 case remoting.ClientSession.State.CREATED: |
437 console.log('Created plugin'); | 503 console.log('Created plugin'); |
438 break; | 504 break; |
439 | 505 |
440 case remoting.ClientSession.State.CONNECTING: | 506 case remoting.ClientSession.State.CONNECTING: |
441 console.log('Connecting as ' + remoting.identity.getCachedEmail()); | 507 console.log('Connecting as ' + remoting.identity.getCachedEmail()); |
442 break; | 508 break; |
443 | 509 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 * Normalize the access code entered by the user. | 585 * Normalize the access code entered by the user. |
520 * | 586 * |
521 * @param {string} accessCode The access code, as entered by the user. | 587 * @param {string} accessCode The access code, as entered by the user. |
522 * @return {string} The normalized form of the code (whitespace removed). | 588 * @return {string} The normalized form of the code (whitespace removed). |
523 */ | 589 */ |
524 remoting.SessionConnector.prototype.normalizeAccessCode_ = | 590 remoting.SessionConnector.prototype.normalizeAccessCode_ = |
525 function(accessCode) { | 591 function(accessCode) { |
526 // Trim whitespace. | 592 // Trim whitespace. |
527 return accessCode.replace(/\s/g, ''); | 593 return accessCode.replace(/\s/g, ''); |
528 }; | 594 }; |
OLD | NEW |