Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 * | 7 * |
| 8 * It2MeHelpeeChannel relays messages between the Hangouts web page (Hangouts) | 8 * It2MeHelpeeChannel relays messages between the Hangouts web page (Hangouts) |
| 9 * and the It2Me Native Messaging Host (It2MeHost) for the helpee (the Hangouts | 9 * and the It2Me Native Messaging Host (It2MeHost) for the helpee (the Hangouts |
| 10 * participant who is receiving remoting assistance). | 10 * participant who is receiving remoting assistance). |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 | 243 |
| 244 /** | 244 /** |
| 245 * Connects to the It2Me Native messaging Host and retrieves the access code. | 245 * Connects to the It2Me Native messaging Host and retrieves the access code. |
| 246 * | 246 * |
| 247 * @param {{method:string, data:Object.<string,*>}} message | 247 * @param {{method:string, data:Object.<string,*>}} message |
| 248 * @private | 248 * @private |
| 249 */ | 249 */ |
| 250 remoting.It2MeHelpeeChannel.prototype.handleConnect_ = | 250 remoting.It2MeHelpeeChannel.prototype.handleConnect_ = |
| 251 function(message) { | 251 function(message) { |
| 252 var email = getStringAttr(message, 'email'); | 252 var email = getStringAttr(message, 'email'); |
| 253 var bounds = /** @type {Bounds} */ (getObjectAttr(message, 'parentBounds')); | |
| 253 | 254 |
| 254 if (!email) { | 255 if (!email) { |
| 255 throw new Error('Missing required parameter: email'); | 256 throw new Error('Missing required parameter: email'); |
| 256 } | 257 } |
| 257 | 258 |
| 258 if (this.hostState_ !== remoting.HostSession.State.UNKNOWN) { | 259 if (this.hostState_ !== remoting.HostSession.State.UNKNOWN) { |
| 259 throw new Error('An existing connection is in progress.'); | 260 throw new Error('An existing connection is in progress.'); |
| 260 } | 261 } |
| 261 | 262 |
| 262 this.showConfirmDialog_().then( | 263 var that = this; |
| 264 this.showConfirmDialog_(bounds).then( | |
| 263 this.initializeHost_.bind(this) | 265 this.initializeHost_.bind(this) |
| 264 ).then( | 266 ).then( |
| 265 this.fetchOAuthToken_.bind(this) | 267 this.fetchOAuthToken_.bind(this) |
| 266 ).then( | 268 ).then( |
| 267 /** @type {function(*):void} */(this.connectToHost_.bind(this, email)), | 269 /** @type {function(*):void} */(this.connectToHost_.bind(this, email)) |
| 268 /** @type {function(*):void} */(this.sendErrorResponse_.bind(this, message)) | 270 ).catch( |
| 271 /** @param {*} reason */ | |
| 272 function(reason) { | |
| 273 var error = /** @type {Error} */ (reason); | |
| 274 that.sendErrorResponse_(message, error); | |
| 275 that.dispose(); | |
| 276 } | |
| 269 ); | 277 ); |
| 270 }; | 278 }; |
| 271 | 279 |
| 272 /** | 280 /** |
| 273 * Prompts the user before starting the It2Me Native Messaging Host. This | 281 * Prompts the user before starting the It2Me Native Messaging Host. This |
| 274 * ensures that even if Hangouts is compromised, an attacker cannot start the | 282 * ensures that even if Hangouts is compromised, an attacker cannot start the |
| 275 * host without explicit user confirmation. | 283 * host without explicit user confirmation. |
| 276 * | 284 * |
| 277 * @return {Promise} A promise that resolves to a boolean value, indicating | 285 * @param {Bounds} bounds Bounds of the hangout window |
| 278 * whether the user accepts the remote assistance or not. | 286 * @return {Promise} A promise that will resolve if the user accepts remote |
| 287 * assistance or reject otherwise. | |
| 279 * @private | 288 * @private |
| 280 */ | 289 */ |
| 281 remoting.It2MeHelpeeChannel.prototype.showConfirmDialog_ = function() { | 290 remoting.It2MeHelpeeChannel.prototype.showConfirmDialog_ = function(bounds) { |
| 282 if (base.isAppsV2()) { | 291 if (base.isAppsV2()) { |
| 283 return this.showConfirmDialogV2_(); | 292 return this.showConfirmDialogV2_(bounds); |
| 284 } else { | 293 } else { |
| 285 return this.showConfirmDialogV1_(); | 294 return this.showConfirmDialogV1_(); |
| 286 } | 295 } |
| 287 }; | 296 }; |
| 288 | 297 |
| 289 /** | 298 /** |
| 290 * @return {Promise} A promise that resolves to a boolean value, indicating | 299 * @return {Promise} A promise that will resolve if the user accepts remote |
| 291 * whether the user accepts the remote assistance or not. | 300 * assistance or reject otherwise. |
| 292 * @private | 301 * @private |
| 293 */ | 302 */ |
| 294 remoting.It2MeHelpeeChannel.prototype.showConfirmDialogV1_ = function() { | 303 remoting.It2MeHelpeeChannel.prototype.showConfirmDialogV1_ = function() { |
| 295 var messageHeader = l10n.getTranslationOrError( | 304 var messageHeader = l10n.getTranslationOrError( |
| 296 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_1'); | 305 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_1'); |
| 297 var message1 = l10n.getTranslationOrError( | 306 var message1 = l10n.getTranslationOrError( |
| 298 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_2'); | 307 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_2'); |
| 299 var message2 = l10n.getTranslationOrError( | 308 var message2 = l10n.getTranslationOrError( |
| 300 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_3'); | 309 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_3'); |
| 301 var message = base.escapeHTML(messageHeader) + '\n' + | 310 var message = base.escapeHTML(messageHeader) + '\n' + |
| 302 '- ' + base.escapeHTML(message1) + '\n' + | 311 '- ' + base.escapeHTML(message1) + '\n' + |
| 303 '- ' + base.escapeHTML(message2) + '\n'; | 312 '- ' + base.escapeHTML(message2) + '\n'; |
| 304 | 313 |
| 305 if(window.confirm(message)) { | 314 if(window.confirm(message)) { |
| 306 return Promise.resolve(); | 315 return Promise.resolve(); |
| 307 } else { | 316 } else { |
| 308 return Promise.reject(new Error(remoting.Error.CANCELLED)); | 317 return Promise.reject(new Error(remoting.Error.CANCELLED)); |
| 309 } | 318 } |
| 310 }; | 319 }; |
| 311 | 320 |
| 312 /** | 321 /** |
| 313 * @return {Promise} A promise that resolves to a boolean value, indicating | 322 * @param {Bounds} bounds the bounds of the Hangouts Window. If set, the |
| 314 * whether the user accepts the remote assistance or not. | 323 * confirm dialog will be centered within |bounds|. |
| 324 * @return {Promise} A promise that will resolve if the user accepts remote | |
| 325 * assistance or reject otherwise. | |
| 315 * @private | 326 * @private |
| 316 */ | 327 */ |
| 317 remoting.It2MeHelpeeChannel.prototype.showConfirmDialogV2_ = function() { | 328 remoting.It2MeHelpeeChannel.prototype.showConfirmDialogV2_ = function(bounds) { |
| 318 var messageHeader = l10n.getTranslationOrError( | 329 var getToken = |
| 319 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_1'); | 330 base.Promise.as(chrome.identity.getAuthToken, [{interactive: false}]); |
| 320 var message1 = l10n.getTranslationOrError( | 331 |
| 321 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_2'); | 332 return getToken.then( |
| 322 var message2 = l10n.getTranslationOrError( | 333 /** @param {string} token */ |
| 323 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_MESSAGE_3'); | 334 function(token) { |
| 324 var message = '<div>' + base.escapeHTML(messageHeader) + '</div>' + | 335 return remoting.HangoutConsentDialog.getInstance().show(Boolean(token), |
| 325 '<ul class="insetList">' + | 336 bounds); |
| 326 '<li>' + base.escapeHTML(message1) + '</li>' + | 337 }); |
| 327 '<li>' + base.escapeHTML(message2) + '</li>' + | |
| 328 '</ul>'; | |
| 329 /** | |
| 330 * @param {function(*=):void} resolve | |
| 331 * @param {function(*=):void} reject | |
| 332 */ | |
| 333 return new Promise(function(resolve, reject) { | |
| 334 /** @param {number} result */ | |
| 335 function confirmDialogCallback(result) { | |
| 336 if (result === 1) { | |
| 337 resolve(true); | |
| 338 } else { | |
| 339 reject(new Error(remoting.Error.CANCELLED)); | |
| 340 } | |
| 341 } | |
| 342 remoting.MessageWindow.showConfirmWindow( | |
| 343 '', // Empty string to use the package name as the dialog title. | |
| 344 message, | |
| 345 l10n.getTranslationOrError( | |
| 346 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_ACCEPT'), | |
| 347 l10n.getTranslationOrError( | |
| 348 /*i18n-content*/'HANGOUTS_CONFIRM_DIALOG_DECLINE'), | |
| 349 confirmDialogCallback | |
| 350 ); | |
| 351 }); | |
| 352 }; | 338 }; |
| 353 | 339 |
| 354 /** | 340 /** |
| 355 * @return {Promise} A promise that resolves when the host is initialized. | 341 * @return {Promise} A promise that resolves when the host is initialized. |
| 356 * @private | 342 * @private |
| 357 */ | 343 */ |
| 358 remoting.It2MeHelpeeChannel.prototype.initializeHost_ = function() { | 344 remoting.It2MeHelpeeChannel.prototype.initializeHost_ = function() { |
| 359 /** @type {remoting.It2MeHostFacade} */ | 345 /** @type {remoting.It2MeHostFacade} */ |
| 360 var host = this.host_; | 346 var host = this.host_; |
| 361 | 347 |
| 362 /** | 348 /** |
| 363 * @param {function(*=):void} resolve | 349 * @param {function(*=):void} resolve |
| 364 * @param {function(*=):void} reject | 350 * @param {function(*=):void} reject |
| 365 */ | 351 */ |
| 366 return new Promise(function(resolve, reject) { | 352 return new Promise(function(resolve, reject) { |
| 367 if (host.initialized()) { | 353 if (host.initialized()) { |
| 368 resolve(true); | 354 resolve(true); |
| 369 } else { | 355 } else { |
| 370 host.initialize(/** @type {function(*=):void} */ (resolve), | 356 host.initialize(/** @type {function(*=):void} */ (resolve), |
| 371 /** @type {function(*=):void} */ (reject)); | 357 /** @type {function(*=):void} */ (reject)); |
| 372 } | 358 } |
| 373 }); | 359 }); |
| 374 }; | 360 }; |
| 375 | 361 |
| 376 /** | 362 /** |
| 377 * @return {Promise} Promise that resolves with the OAuth token as the value. | 363 * @return {Promise<string>} Promise that resolves with the OAuth token as the |
|
Jamie
2015/02/03 18:22:44
I'm not familiar with this annotation. Does it mea
kelvinp
2015/02/03 19:31:46
Yes, it does. JSCompile will complain if you retur
| |
| 364 * value. | |
| 378 */ | 365 */ |
| 379 remoting.It2MeHelpeeChannel.prototype.fetchOAuthToken_ = function() { | 366 remoting.It2MeHelpeeChannel.prototype.fetchOAuthToken_ = function() { |
| 380 if (base.isAppsV2()) { | 367 if (base.isAppsV2()) { |
| 381 /** | 368 /** |
| 382 * @param {function(*=):void} resolve | 369 * @param {function(*=):void} resolve |
| 383 */ | 370 */ |
| 384 return new Promise(function(resolve){ | 371 return new Promise(function(resolve){ |
| 385 // TODO(jamiewalch): Make this work with {interactive: true} as well. | 372 chrome.identity.getAuthToken({'interactive': true}, resolve); |
| 386 chrome.identity.getAuthToken({ 'interactive': false }, resolve); | |
| 387 }); | 373 }); |
| 388 } else { | 374 } else { |
| 389 /** | 375 /** |
| 390 * @param {function(*=):void} resolve | 376 * @param {function(*=):void} resolve |
| 377 * @param {function(*=):void} reject | |
| 391 */ | 378 */ |
| 392 return new Promise(function(resolve) { | 379 return new Promise(function(resolve, reject) { |
| 393 /** @type {remoting.OAuth2} */ | 380 /** @type {remoting.OAuth2} */ |
| 394 var oauth2 = new remoting.OAuth2(); | 381 var oauth2 = new remoting.OAuth2(); |
| 395 var onAuthenticated = function() { | |
| 396 oauth2.callWithToken( | |
| 397 resolve, | |
| 398 function() { throw new Error('Authentication failed.'); }); | |
| 399 }; | |
| 400 /** @param {remoting.Error} error */ | 382 /** @param {remoting.Error} error */ |
| 401 var onError = function(error) { | 383 var onError = function(error) { |
| 402 if (error != remoting.Error.NOT_AUTHENTICATED) { | 384 if (error === remoting.Error.NOT_AUTHENTICATED) { |
| 403 throw new Error('Unexpected error fetch auth token: ' + error); | 385 oauth2.doAuthRedirect(function() { |
| 386 oauth2.callWithToken(resolve, reject); | |
| 387 }); | |
| 388 return; | |
| 404 } | 389 } |
| 405 oauth2.removeCachedAuthToken(); | 390 reject(new Error(remoting.Error.NOT_AUTHENTICATED)); |
| 406 }; | 391 }; |
| 407 oauth2.callWithToken(resolve, onError); | 392 oauth2.callWithToken(resolve, onError); |
| 408 }); | 393 }); |
| 409 } | 394 } |
| 410 }; | 395 }; |
| 411 | 396 |
| 412 /** | 397 /** |
| 413 * Connects to the It2Me Native Messaging Host and retrieves the access code | 398 * Connects to the It2Me Native Messaging Host and retrieves the access code |
| 414 * in the |onHostStateChanged_| callback. | 399 * in the |onHostStateChanged_| callback. |
| 415 * | 400 * |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 488 | 473 |
| 489 console.error('Error responding to message method:' + | 474 console.error('Error responding to message method:' + |
| 490 (incomingMessage ? incomingMessage.method : 'null') + | 475 (incomingMessage ? incomingMessage.method : 'null') + |
| 491 ' error:' + error); | 476 ' error:' + error); |
| 492 this.hangoutPort_.postMessage({ | 477 this.hangoutPort_.postMessage({ |
| 493 method: remoting.It2MeHelpeeChannel.HangoutMessageTypes.ERROR, | 478 method: remoting.It2MeHelpeeChannel.HangoutMessageTypes.ERROR, |
| 494 message: error, | 479 message: error, |
| 495 request: incomingMessage | 480 request: incomingMessage |
| 496 }); | 481 }); |
| 497 }; | 482 }; |
| OLD | NEW |