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 /** @suppress {duplicate} */ | 5 /** @suppress {duplicate} */ |
6 var remoting = remoting || {}; | 6 var remoting = remoting || {}; |
7 | 7 |
8 (function() { | |
9 'use strict'; | 8 'use strict'; |
10 | 9 |
11 window.addEventListener('blur', pluginLostFocus_, false); | 10 /** |
| 11 * Whether or not the plugin should scale itself. |
| 12 * @type {boolean} |
| 13 */ |
| 14 remoting.scaleToFit = false; |
12 | 15 |
13 function pluginLostFocus_() { | 16 /** @type {remoting.ClientSession} */ |
14 // If the plug loses input focus, release all keys as a precaution against | 17 remoting.session = null; |
15 // leaving them 'stuck down' on the host. | 18 |
16 if (remoting.session && remoting.session.plugin) { | 19 /** @type {string} */ remoting.accessCode = ''; |
17 remoting.session.plugin.releaseAllKeys(); | 20 /** @type {number} */ remoting.accessCodeTimerId = 0; |
18 } | 21 /** @type {number} */ remoting.accessCodeExpiresIn = 0; |
19 } | 22 /** @type {remoting.AppMode} */ remoting.currentMode; |
| 23 /** @type {string} */ remoting.hostJid = ''; |
| 24 /** @type {string} */ remoting.hostPublicKey = ''; |
| 25 /** @type {boolean} */ remoting.lastShareWasCancelled = false; |
| 26 /** @type {boolean} */ remoting.timerRunning = false; |
| 27 /** @type {string} */ remoting.username = ''; |
20 | 28 |
21 /** @enum {string} */ | 29 /** @enum {string} */ |
22 remoting.AppMode = { | 30 remoting.AppMode = { |
23 HOME: 'home', | 31 HOME: 'home', |
24 UNAUTHENTICATED: 'auth', | 32 UNAUTHENTICATED: 'auth', |
25 CLIENT: 'client', | 33 CLIENT: 'client', |
26 CLIENT_UNCONNECTED: 'client.unconnected', | 34 CLIENT_UNCONNECTED: 'client.unconnected', |
27 CLIENT_CONNECTING: 'client.connecting', | 35 CLIENT_CONNECTING: 'client.connecting', |
28 CLIENT_CONNECT_FAILED: 'client.connect-failed', | 36 CLIENT_CONNECT_FAILED: 'client.connect-failed', |
29 CLIENT_SESSION_FINISHED: 'client.session-finished', | 37 CLIENT_SESSION_FINISHED: 'client.session-finished', |
30 HOST: 'host', | 38 HOST: 'host', |
31 HOST_WAITING_FOR_CODE: 'host.waiting-for-code', | 39 HOST_WAITING_FOR_CODE: 'host.waiting-for-code', |
32 HOST_WAITING_FOR_CONNECTION: 'host.waiting-for-connection', | 40 HOST_WAITING_FOR_CONNECTION: 'host.waiting-for-connection', |
33 HOST_SHARED: 'host.shared', | 41 HOST_SHARED: 'host.shared', |
34 HOST_SHARE_FAILED: 'host.share-failed', | 42 HOST_SHARE_FAILED: 'host.share-failed', |
35 HOST_SHARE_FINISHED: 'host.share-finished', | 43 HOST_SHARE_FINISHED: 'host.share-finished', |
36 IN_SESSION: 'in-session' | 44 IN_SESSION: 'in-session' |
37 }; | 45 }; |
38 | 46 |
39 remoting.EMAIL = 'email'; | 47 (function() { |
| 48 |
| 49 window.addEventListener('blur', pluginLostFocus_, false); |
| 50 |
| 51 function pluginLostFocus_() { |
| 52 // If the plug loses input focus, release all keys as a precaution against |
| 53 // leaving them 'stuck down' on the host. |
| 54 if (remoting.session && remoting.session.plugin) { |
| 55 remoting.session.plugin.releaseAllKeys(); |
| 56 } |
| 57 } |
| 58 |
| 59 /** @type {string} */ |
40 remoting.HOST_PLUGIN_ID = 'host-plugin-id'; | 60 remoting.HOST_PLUGIN_ID = 'host-plugin-id'; |
41 | 61 |
42 /** @enum {string} */ | 62 /** @enum {string} */ |
43 remoting.ClientError = { | 63 remoting.ClientError = { |
44 NO_RESPONSE: /*i18n-content*/'ERROR_NO_RESPONSE', | 64 NO_RESPONSE: /*i18n-content*/'ERROR_NO_RESPONSE', |
45 INVALID_ACCESS_CODE: /*i18n-content*/'ERROR_INVALID_ACCESS_CODE', | 65 INVALID_ACCESS_CODE: /*i18n-content*/'ERROR_INVALID_ACCESS_CODE', |
46 MISSING_PLUGIN: /*i18n-content*/'ERROR_MISSING_PLUGIN', | 66 MISSING_PLUGIN: /*i18n-content*/'ERROR_MISSING_PLUGIN', |
47 OAUTH_FETCH_FAILED: /*i18n-content*/'ERROR_AUTHENTICATION_FAILED', | 67 OAUTH_FETCH_FAILED: /*i18n-content*/'ERROR_AUTHENTICATION_FAILED', |
48 HOST_IS_OFFLINE: /*i18n-content*/'ERROR_HOST_IS_OFFLINE', | 68 HOST_IS_OFFLINE: /*i18n-content*/'ERROR_HOST_IS_OFFLINE', |
49 INCOMPATIBLE_PROTOCOL: /*i18n-content*/'ERROR_INCOMPATIBLE_PROTOCOL', | 69 INCOMPATIBLE_PROTOCOL: /*i18n-content*/'ERROR_INCOMPATIBLE_PROTOCOL', |
50 BAD_PLUGIN_VERSION: /*i18n-content*/'ERROR_BAD_PLUGIN_VERSION', | 70 BAD_PLUGIN_VERSION: /*i18n-content*/'ERROR_BAD_PLUGIN_VERSION', |
51 OTHER_ERROR: /*i18n-content*/'ERROR_GENERIC' | 71 OTHER_ERROR: /*i18n-content*/'ERROR_GENERIC' |
52 }; | 72 }; |
53 | 73 |
54 /** | |
55 * Whether or not the plugin should scale itself. | |
56 * @type {boolean} | |
57 */ | |
58 remoting.scaleToFit = false; | |
59 | |
60 // Constants representing keys used for storing persistent application state. | 74 // Constants representing keys used for storing persistent application state. |
61 var KEY_APP_MODE_ = 'remoting-app-mode'; | 75 var KEY_APP_MODE_ = 'remoting-app-mode'; |
62 var KEY_EMAIL_ = 'remoting-email'; | 76 var KEY_EMAIL_ = 'remoting-email'; |
63 var KEY_USE_P2P_API_ = 'remoting-use-p2p-api'; | 77 var KEY_USE_P2P_API_ = 'remoting-use-p2p-api'; |
64 | 78 |
65 // Some constants for pretty-printing the access code. | 79 // Some constants for pretty-printing the access code. |
66 var kSupportIdLen = 7; | 80 /** @type {number} */ var kSupportIdLen = 7; |
67 var kHostSecretLen = 5; | 81 /** @type {number} */ var kHostSecretLen = 5; |
68 var kAccessCodeLen = kSupportIdLen + kHostSecretLen; | 82 /** @type {number} */ var kAccessCodeLen = kSupportIdLen + kHostSecretLen; |
69 var kDigitsPerGroup = 4; | 83 /** @type {number} */ var kDigitsPerGroup = 4; |
70 | 84 |
| 85 /** |
| 86 * @param {string} classes A space-separated list of classes. |
| 87 * @param {string} cls The class to check for. |
| 88 * @return {boolean} True if |cls| is found within |classes|. |
| 89 */ |
71 function hasClass(classes, cls) { | 90 function hasClass(classes, cls) { |
72 return classes.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); | 91 return classes.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) != null; |
73 } | 92 } |
74 | 93 |
| 94 /** |
| 95 * @param {Element} element The element to which to add the class. |
| 96 * @param {string} cls The new class. |
| 97 * @return {void} Nothing. |
| 98 */ |
75 function addClass(element, cls) { | 99 function addClass(element, cls) { |
76 if (!hasClass(element.className, cls)) { | 100 if (!hasClass(element.className, cls)) { |
77 var padded = element.className == '' ? '' : element.className + ' '; | 101 var padded = element.className == '' ? '' : element.className + ' '; |
78 element.className = padded + cls; | 102 element.className = padded + cls; |
79 } | 103 } |
80 } | 104 } |
81 | 105 |
| 106 /** |
| 107 * @param {Element} element The element from which to remove the class. |
| 108 * @param {string} cls The new class. |
| 109 * @return {void} Nothing. |
| 110 */ |
82 function removeClass(element, cls) { | 111 function removeClass(element, cls) { |
83 element.className = | 112 element.className = |
84 element.className.replace(new RegExp('\\b' + cls + '\\b', 'g'), '') | 113 element.className.replace(new RegExp('\\b' + cls + '\\b', 'g'), '') |
85 .replace(' ', ' '); | 114 .replace(' ', ' '); |
86 } | 115 } |
87 | 116 |
88 function retrieveEmail_(access_token) { | 117 function retrieveEmail_(access_token) { |
89 var headers = { | 118 var headers = { |
90 'Authorization': 'OAuth ' + remoting.oauth2.getAccessToken() | 119 'Authorization': 'OAuth ' + remoting.oauth2.getAccessToken() |
91 }; | 120 }; |
92 | 121 |
| 122 /** @param {XMLHttpRequest} xhr The XHR response. */ |
93 var onResponse = function(xhr) { | 123 var onResponse = function(xhr) { |
94 if (xhr.status != 200) { | 124 if (xhr.status != 200) { |
95 // TODO(ajwong): Have a better way of showing an error. | 125 // TODO(ajwong): Have a better way of showing an error. |
96 remoting.debug.log('Unable to get email'); | 126 remoting.debug.log('Unable to get email'); |
97 document.getElementById('current-email').innerText = '???'; | 127 document.getElementById('current-email').innerText = '???'; |
98 return; | 128 return; |
99 } | 129 } |
100 | 130 |
101 // TODO(ajwong): See if we can't find a JSON endpoint. | 131 // TODO(ajwong): See if we can't find a JSON endpoint. |
102 setEmail(xhr.responseText.split('&')[0].split('=')[1]); | 132 setEmail(xhr.responseText.split('&')[0].split('=')[1]); |
103 }; | 133 }; |
104 | 134 |
105 // TODO(ajwong): Update to new v2 API. | 135 // TODO(ajwong): Update to new v2 API. |
106 remoting.xhr.get('https://www.googleapis.com/userinfo/email', | 136 remoting.xhr.get('https://www.googleapis.com/userinfo/email', |
107 onResponse, '', headers); | 137 onResponse, '', headers); |
108 } | 138 } |
109 | 139 |
110 function refreshEmail_() { | 140 function refreshEmail_() { |
111 if (!getEmail() && remoting.oauth2.isAuthenticated()) { | 141 if (!getEmail() && remoting.oauth2.isAuthenticated()) { |
112 remoting.oauth2.callWithToken(retrieveEmail_); | 142 remoting.oauth2.callWithToken(retrieveEmail_); |
113 } | 143 } |
114 } | 144 } |
115 | 145 |
| 146 /** |
| 147 * @param {string} value The email address to place in local storage. |
| 148 * @return {void} Nothing. |
| 149 */ |
116 function setEmail(value) { | 150 function setEmail(value) { |
117 window.localStorage.setItem(KEY_EMAIL_, value); | 151 window.localStorage.setItem(KEY_EMAIL_, value); |
118 document.getElementById('current-email').innerText = value; | 152 document.getElementById('current-email').innerText = value; |
119 } | 153 } |
120 | 154 |
121 /** | 155 /** |
122 * @return {?string} The email address associated with the auth credentials. | 156 * @return {?string} The email address associated with the auth credentials. |
123 */ | 157 */ |
124 function getEmail() { | 158 function getEmail() { |
125 var result = window.localStorage.getItem(KEY_EMAIL_); | 159 var result = window.localStorage.getItem(KEY_EMAIL_); |
126 return typeof result == 'string' ? result : null; | 160 return typeof result == 'string' ? result : null; |
127 } | 161 } |
128 | 162 |
129 function exchangedCodeForToken_() { | 163 function exchangedCodeForToken_() { |
130 if (!remoting.oauth2.isAuthenticated()) { | 164 if (!remoting.oauth2.isAuthenticated()) { |
131 alert('Your OAuth2 token was invalid. Please try again.'); | 165 alert('Your OAuth2 token was invalid. Please try again.'); |
132 } | 166 } |
133 remoting.oauth2.callWithToken(function(token) { | 167 /** @param {string} token The auth token. */ |
134 retrieveEmail_(token); | 168 var retrieveEmail = function(token) { retrieveEmail_(token); } |
135 }); | 169 remoting.oauth2.callWithToken(retrieveEmail); |
136 } | 170 } |
137 | 171 |
138 remoting.clearOAuth2 = function() { | 172 remoting.clearOAuth2 = function() { |
139 remoting.oauth2.clear(); | 173 remoting.oauth2.clear(); |
140 window.localStorage.removeItem(KEY_EMAIL_); | 174 window.localStorage.removeItem(KEY_EMAIL_); |
141 remoting.setMode(remoting.AppMode.UNAUTHENTICATED); | 175 remoting.setMode(remoting.AppMode.UNAUTHENTICATED); |
142 } | 176 } |
143 | 177 |
144 remoting.toggleDebugLog = function() { | 178 remoting.toggleDebugLog = function() { |
145 var debugLog = document.getElementById('debug-log'); | 179 var debugLog = document.getElementById('debug-log'); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 * | 221 * |
188 * @param {remoting.AppMode} mode The new modal state, expressed as a dotted | 222 * @param {remoting.AppMode} mode The new modal state, expressed as a dotted |
189 * hiearchy. | 223 * hiearchy. |
190 */ | 224 */ |
191 remoting.setMode = function(mode) { | 225 remoting.setMode = function(mode) { |
192 var modes = mode.split('.'); | 226 var modes = mode.split('.'); |
193 for (var i = 1; i < modes.length; ++i) | 227 for (var i = 1; i < modes.length; ++i) |
194 modes[i] = modes[i - 1] + '.' + modes[i]; | 228 modes[i] = modes[i - 1] + '.' + modes[i]; |
195 var elements = document.querySelectorAll('[data-ui-mode]'); | 229 var elements = document.querySelectorAll('[data-ui-mode]'); |
196 for (var i = 0; i < elements.length; ++i) { | 230 for (var i = 0; i < elements.length; ++i) { |
197 var element = elements[i]; | 231 /** @type {Element} */ var element = elements[i]; |
198 var hidden = true; | 232 var hidden = true; |
199 for (var m = 0; m < modes.length; ++m) { | 233 for (var m = 0; m < modes.length; ++m) { |
200 if (hasClass(element.getAttribute('data-ui-mode'), modes[m])) { | 234 if (hasClass(element.getAttribute('data-ui-mode'), modes[m])) { |
201 hidden = false; | 235 hidden = false; |
202 break; | 236 break; |
203 } | 237 } |
204 } | 238 } |
205 element.hidden = hidden; | 239 element.hidden = hidden; |
206 } | 240 } |
207 remoting.debug.log('App mode: ' + mode); | 241 remoting.debug.log('App mode: ' + mode); |
208 remoting.currentMode = mode; | 242 remoting.currentMode = mode; |
209 if (mode == remoting.AppMode.IN_SESSION) { | 243 if (mode == remoting.AppMode.IN_SESSION) { |
210 document.removeEventListener('keydown', remoting.checkHotkeys, false); | 244 document.removeEventListener('keydown', remoting.checkHotkeys, false); |
211 } else { | 245 } else { |
212 document.addEventListener('keydown', remoting.checkHotkeys, false); | 246 document.addEventListener('keydown', remoting.checkHotkeys, false); |
213 } | 247 } |
214 } | 248 } |
215 | 249 |
216 /** | 250 /** |
217 * Get the major mode that the app is running in. | 251 * Get the major mode that the app is running in. |
218 * @return {remoting.AppMode} The app's current major mode. | 252 * @return {string} The app's current major mode. |
219 */ | 253 */ |
220 remoting.getMajorMode = function() { | 254 remoting.getMajorMode = function() { |
221 return remoting.currentMode.split('.')[0]; | 255 return remoting.currentMode.split('.')[0]; |
222 } | 256 } |
223 | 257 |
224 remoting.tryShare = function() { | 258 remoting.tryShare = function() { |
225 remoting.debug.log('Attempting to share...'); | 259 remoting.debug.log('Attempting to share...'); |
226 remoting.lastShareWasCancelled = false; | 260 remoting.lastShareWasCancelled = false; |
227 if (remoting.oauth2.needsNewAccessToken()) { | 261 if (remoting.oauth2.needsNewAccessToken()) { |
228 remoting.debug.log('Refreshing token...'); | 262 remoting.debug.log('Refreshing token...'); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 | 336 |
303 remoting.updateAccessCodeTimeoutElement_ = function() { | 337 remoting.updateAccessCodeTimeoutElement_ = function() { |
304 var pad = (remoting.accessCodeExpiresIn < 10) ? '0:0' : '0:'; | 338 var pad = (remoting.accessCodeExpiresIn < 10) ? '0:0' : '0:'; |
305 l10n.localizeElement(document.getElementById('seconds-remaining'), | 339 l10n.localizeElement(document.getElementById('seconds-remaining'), |
306 pad + remoting.accessCodeExpiresIn); | 340 pad + remoting.accessCodeExpiresIn); |
307 if (!updateTimeoutStyles_()) { | 341 if (!updateTimeoutStyles_()) { |
308 disableTimeoutCountdown_(); | 342 disableTimeoutCountdown_(); |
309 } | 343 } |
310 } | 344 } |
311 | 345 |
| 346 /** |
| 347 * Callback to show or hide the NAT traversal warning when the policy changes. |
| 348 * @param {boolean} enabled True if NAT traversal is enabled. |
| 349 * @return {void} Nothing. |
| 350 */ |
312 function onNatTraversalPolicyChanged_(enabled) { | 351 function onNatTraversalPolicyChanged_(enabled) { |
313 var container = document.getElementById('nat-box-container'); | 352 var container = document.getElementById('nat-box-container'); |
314 container.hidden = enabled; | 353 container.hidden = enabled; |
315 } | 354 } |
316 | 355 |
317 function onStateChanged_() { | 356 function onStateChanged_() { |
318 var plugin = /** @type {remoting.HostPlugin} */ | 357 var plugin = /** @type {remoting.HostPlugin} */ |
319 document.getElementById(remoting.HOST_PLUGIN_ID); | 358 document.getElementById(remoting.HOST_PLUGIN_ID); |
320 var state = plugin.state; | 359 var state = plugin.state; |
321 if (state == plugin.STARTING) { | 360 if (state == plugin.STARTING) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 * @return {void} Nothing. | 447 * @return {void} Nothing. |
409 */ | 448 */ |
410 remoting.cancelShare = function() { | 449 remoting.cancelShare = function() { |
411 remoting.debug.log('Canceling share...'); | 450 remoting.debug.log('Canceling share...'); |
412 remoting.lastShareWasCancelled = true; | 451 remoting.lastShareWasCancelled = true; |
413 var plugin = /** @type {remoting.HostPlugin} */ | 452 var plugin = /** @type {remoting.HostPlugin} */ |
414 document.getElementById(remoting.HOST_PLUGIN_ID); | 453 document.getElementById(remoting.HOST_PLUGIN_ID); |
415 try { | 454 try { |
416 plugin.disconnect(); | 455 plugin.disconnect(); |
417 } catch (error) { | 456 } catch (error) { |
418 remoting.debug.log('Error disconnecting: ' + error.description + | 457 // Hack to force JSCompiler type-safety. |
| 458 var errorTyped = /** @type {{description: string}} */ error; |
| 459 remoting.debug.log('Error disconnecting: ' + errorTyped.description + |
419 '. The host plugin probably crashed.'); | 460 '. The host plugin probably crashed.'); |
420 // TODO(jamiewalch): Clean this up. We should have a class representing | 461 // TODO(jamiewalch): Clean this up. We should have a class representing |
421 // the host plugin, like we do for the client, which should handle crash | 462 // the host plugin, like we do for the client, which should handle crash |
422 // reporting and it should use a more detailed error message than the | 463 // reporting and it should use a more detailed error message than the |
423 // default 'generic' one. See crbug.com/94624 | 464 // default 'generic' one. See crbug.com/94624 |
424 showShareError_(/*i18n-content*/'ERROR_GENERIC'); | 465 showShareError_(/*i18n-content*/'ERROR_GENERIC'); |
425 } | 466 } |
426 disableTimeoutCountdown_(); | 467 disableTimeoutCountdown_(); |
427 } | 468 } |
428 | 469 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 // Update the stats once per second. | 518 // Update the stats once per second. |
478 window.setTimeout(updateStatistics, 1000); | 519 window.setTimeout(updateStatistics, 1000); |
479 } | 520 } |
480 | 521 |
481 function showToolbarPreview_() { | 522 function showToolbarPreview_() { |
482 var toolbar = document.getElementById('session-toolbar'); | 523 var toolbar = document.getElementById('session-toolbar'); |
483 addClass(toolbar, 'toolbar-preview'); | 524 addClass(toolbar, 'toolbar-preview'); |
484 window.setTimeout(removeClass, 3000, toolbar, 'toolbar-preview'); | 525 window.setTimeout(removeClass, 3000, toolbar, 'toolbar-preview'); |
485 } | 526 } |
486 | 527 |
| 528 /** @param {number} oldState The previous state of the plugin. */ |
487 function onClientStateChange_(oldState) { | 529 function onClientStateChange_(oldState) { |
488 if (!remoting.session) { | 530 if (!remoting.session) { |
489 // If the connection has been cancelled, then we no longer have a reference | 531 // If the connection has been cancelled, then we no longer have a reference |
490 // to the session object and should ignore any state changes. | 532 // to the session object and should ignore any state changes. |
491 return; | 533 return; |
492 } | 534 } |
493 var state = remoting.session.state; | 535 var state = remoting.session.state; |
494 if (state == remoting.ClientSession.State.CREATED) { | 536 if (state == remoting.ClientSession.State.CREATED) { |
495 remoting.debug.log('Created plugin'); | 537 remoting.debug.log('Created plugin'); |
496 } else if (state == remoting.ClientSession.State.BAD_PLUGIN_VERSION) { | 538 } else if (state == remoting.ClientSession.State.BAD_PLUGIN_VERSION) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 function startSession_() { | 588 function startSession_() { |
547 remoting.debug.log('Starting session...'); | 589 remoting.debug.log('Starting session...'); |
548 var accessCode = document.getElementById('access-code-entry'); | 590 var accessCode = document.getElementById('access-code-entry'); |
549 accessCode.value = ''; // The code has been validated and won't work again. | 591 accessCode.value = ''; // The code has been validated and won't work again. |
550 remoting.username = | 592 remoting.username = |
551 /** @type {string} email must be non-NULL to get here */ getEmail(); | 593 /** @type {string} email must be non-NULL to get here */ getEmail(); |
552 remoting.session = | 594 remoting.session = |
553 new remoting.ClientSession(remoting.hostJid, remoting.hostPublicKey, | 595 new remoting.ClientSession(remoting.hostJid, remoting.hostPublicKey, |
554 remoting.accessCode, remoting.username, | 596 remoting.accessCode, remoting.username, |
555 onClientStateChange_); | 597 onClientStateChange_); |
556 remoting.oauth2.callWithToken(function(token) { | 598 /** @param {string} token The auth token. */ |
| 599 var createPluginAndConnect = function(token) { |
557 remoting.session.createPluginAndConnect( | 600 remoting.session.createPluginAndConnect( |
558 document.getElementById('session-mode'), | 601 document.getElementById('session-mode'), |
559 token); | 602 token); |
560 }); | 603 }; |
| 604 remoting.oauth2.callWithToken(createPluginAndConnect); |
561 } | 605 } |
562 | 606 |
563 /** | 607 /** |
564 * Show a client-side error message. | 608 * Show a client-side error message. |
565 * | 609 * |
566 * @param {remoting.ClientError} errorTag The error to be localized and | 610 * @param {remoting.ClientError} errorTag The error to be localized and |
567 * displayed. | 611 * displayed. |
568 * @return {void} Nothing. | 612 * @return {void} Nothing. |
569 */ | 613 */ |
570 function showConnectError_(errorTag) { | 614 function showConnectError_(errorTag) { |
571 remoting.debug.log('Connection failed: ' + errorTag); | 615 remoting.debug.log('Connection failed: ' + errorTag); |
572 var errorDiv = document.getElementById('connect-error-message'); | 616 var errorDiv = document.getElementById('connect-error-message'); |
573 l10n.localizeElementFromTag(errorDiv, /** @type {string} */ (errorTag)); | 617 l10n.localizeElementFromTag(errorDiv, /** @type {string} */ (errorTag)); |
574 remoting.accessCode = ''; | 618 remoting.accessCode = ''; |
575 if (remoting.session) { | 619 if (remoting.session) { |
576 remoting.session.disconnect(); | 620 remoting.session.disconnect(); |
577 remoting.session = null; | 621 remoting.session = null; |
578 } | 622 } |
579 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED); | 623 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED); |
580 } | 624 } |
581 | 625 |
582 /** | 626 /** |
583 * @param {XMLHttpRequest} xhr The XMLHttpRequest object. | 627 * @param {XMLHttpRequest} xhr The XMLHttpRequest object. |
584 * @return {void} Nothing. | 628 * @return {void} Nothing. |
585 */ | 629 */ |
586 function parseServerResponse_(xhr) { | 630 function parseServerResponse_(xhr) { |
587 remoting.supportHostsXhr = null; | 631 remoting.supportHostsXhr = null; |
588 remoting.debug.log('parseServerResponse: status = ' + xhr.status); | 632 remoting.debug.log('parseServerResponse: status = ' + xhr.status); |
589 if (xhr.status == 200) { | 633 if (xhr.status == 200) { |
590 var host = JSON.parse(xhr.responseText); | 634 var host = /** @type {{data: {jabberId: string, publicKey: string}}} */ |
591 if (host.data && host.data.jabberId) { | 635 JSON.parse(xhr.responseText); |
| 636 if (host.data && host.data.jabberId && host.data.publicKey) { |
592 remoting.hostJid = host.data.jabberId; | 637 remoting.hostJid = host.data.jabberId; |
593 remoting.hostPublicKey = host.data.publicKey; | 638 remoting.hostPublicKey = host.data.publicKey; |
594 var split = remoting.hostJid.split('/'); | 639 var split = remoting.hostJid.split('/'); |
595 document.getElementById('connected-to').innerText = split[0]; | 640 document.getElementById('connected-to').innerText = split[0]; |
596 startSession_(); | 641 startSession_(); |
597 return; | 642 return; |
598 } | 643 } |
599 } | 644 } |
600 var errorMsg = remoting.ClientError.OTHER_ERROR; | 645 var errorMsg = remoting.ClientError.OTHER_ERROR; |
601 if (xhr.status == 404) { | 646 if (xhr.status == 404) { |
602 errorMsg = remoting.ClientError.INVALID_ACCESS_CODE; | 647 errorMsg = remoting.ClientError.INVALID_ACCESS_CODE; |
603 } else if (xhr.status == 0) { | 648 } else if (xhr.status == 0) { |
604 errorMsg = remoting.ClientError.NO_RESPONSE; | 649 errorMsg = remoting.ClientError.NO_RESPONSE; |
605 } else { | 650 } else { |
606 remoting.debug.log('The server responded: ' + xhr.responseText); | 651 remoting.debug.log('The server responded: ' + xhr.responseText); |
607 } | 652 } |
608 showConnectError_(errorMsg); | 653 showConnectError_(errorMsg); |
609 } | 654 } |
610 | 655 |
| 656 /** @param {string} accessCode The access code, as entered by the user. |
| 657 * @return {string} The normalized form of the code (whitespace removed). */ |
611 function normalizeAccessCode_(accessCode) { | 658 function normalizeAccessCode_(accessCode) { |
612 // Trim whitespace. | 659 // Trim whitespace. |
613 // TODO(sergeyu): Do we need to do any other normalization here? | 660 // TODO(sergeyu): Do we need to do any other normalization here? |
614 return accessCode.replace(/\s/g, ''); | 661 return accessCode.replace(/\s/g, ''); |
615 } | 662 } |
616 | 663 |
| 664 /** @param {string} supportId The canonicalized support ID. */ |
617 function resolveSupportId(supportId) { | 665 function resolveSupportId(supportId) { |
618 var headers = { | 666 var headers = { |
619 'Authorization': 'OAuth ' + remoting.oauth2.getAccessToken() | 667 'Authorization': 'OAuth ' + remoting.oauth2.getAccessToken() |
620 }; | 668 }; |
621 | 669 |
622 remoting.supportHostsXhr = remoting.xhr.get( | 670 remoting.supportHostsXhr = remoting.xhr.get( |
623 'https://www.googleapis.com/chromoting/v1/support-hosts/' + | 671 'https://www.googleapis.com/chromoting/v1/support-hosts/' + |
624 encodeURIComponent(supportId), | 672 encodeURIComponent(supportId), |
625 parseServerResponse_, | 673 parseServerResponse_, |
626 '', | 674 '', |
(...skipping 14 matching lines...) Expand all Loading... |
641 }); | 689 }); |
642 } else { | 690 } else { |
643 remoting.tryConnectWithAccessToken(); | 691 remoting.tryConnectWithAccessToken(); |
644 } | 692 } |
645 } | 693 } |
646 | 694 |
647 remoting.tryConnectWithAccessToken = function() { | 695 remoting.tryConnectWithAccessToken = function() { |
648 if (!remoting.wcsLoader) { | 696 if (!remoting.wcsLoader) { |
649 remoting.wcsLoader = new remoting.WcsLoader(); | 697 remoting.wcsLoader = new remoting.WcsLoader(); |
650 } | 698 } |
| 699 /** @param {function(string):void} setToken The callback function. */ |
| 700 var callWithToken = function(setToken) { |
| 701 remoting.oauth2.callWithToken(setToken); |
| 702 }; |
651 remoting.wcsLoader.start( | 703 remoting.wcsLoader.start( |
652 remoting.oauth2.getAccessToken(), | 704 remoting.oauth2.getAccessToken(), |
653 function(setToken) { | 705 callWithToken, |
654 remoting.oauth2.callWithToken(setToken); | |
655 }, | |
656 remoting.tryConnectWithWcs); | 706 remoting.tryConnectWithWcs); |
657 } | 707 } |
658 | 708 |
659 remoting.tryConnectWithWcs = function() { | 709 remoting.tryConnectWithWcs = function() { |
660 var accessCode = document.getElementById('access-code-entry').value; | 710 var accessCode = document.getElementById('access-code-entry').value; |
661 remoting.accessCode = normalizeAccessCode_(accessCode); | 711 remoting.accessCode = normalizeAccessCode_(accessCode); |
662 // At present, only 12-digit access codes are supported, of which the first | 712 // At present, only 12-digit access codes are supported, of which the first |
663 // 7 characters are the supportId. | 713 // 7 characters are the supportId. |
664 if (remoting.accessCode.length != kAccessCodeLen) { | 714 if (remoting.accessCode.length != kAccessCodeLen) { |
665 remoting.debug.log('Bad access code length'); | 715 remoting.debug.log('Bad access code length'); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 case remoting.AppMode.HOST_WAITING_FOR_CONNECTION: | 813 case remoting.AppMode.HOST_WAITING_FOR_CONNECTION: |
764 case remoting.AppMode.HOST_SHARED: | 814 case remoting.AppMode.HOST_SHARED: |
765 case remoting.AppMode.IN_SESSION: | 815 case remoting.AppMode.IN_SESSION: |
766 var result = chrome.i18n.getMessage(/*i18n-content*/'CLOSE_PROMPT'); | 816 var result = chrome.i18n.getMessage(/*i18n-content*/'CLOSE_PROMPT'); |
767 return result; | 817 return result; |
768 default: | 818 default: |
769 return null; | 819 return null; |
770 } | 820 } |
771 } | 821 } |
772 | 822 |
| 823 /** |
| 824 * @param {Event} event The keyboard event. |
| 825 * @return {void} Nothing. |
| 826 */ |
773 remoting.checkHotkeys = function(event) { | 827 remoting.checkHotkeys = function(event) { |
774 if (String.fromCharCode(event.which) == 'D') { | 828 if (String.fromCharCode(event.which) == 'D') { |
775 remoting.toggleDebugLog(); | 829 remoting.toggleDebugLog(); |
776 } | 830 } |
777 } | 831 } |
778 | 832 |
779 function recenterToolbar_() { | 833 function recenterToolbar_() { |
780 var toolbar = document.getElementById('session-toolbar'); | 834 var toolbar = document.getElementById('session-toolbar'); |
781 var toolbarX = (window.innerWidth - toolbar.clientWidth) / 2; | 835 var toolbarX = (window.innerWidth - toolbar.clientWidth) / 2; |
782 toolbar.style['left'] = toolbarX + 'px'; | 836 toolbar.style['left'] = toolbarX + 'px'; |
783 } | 837 } |
784 | 838 |
785 }()); | 839 }()); |
OLD | NEW |