OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 that wraps low-level details of interacting with the client plugin. | 7 * Class that wraps low-level details of interacting with the client plugin. |
8 * | 8 * |
9 * This abstracts a <embed> element and controls the plugin which does | 9 * This abstracts a <embed> element and controls the plugin which does |
10 * the actual remoting work. It also handles differences between | 10 * the actual remoting work. It also handles differences between |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 * @param {string} connectionType The connection type. | 70 * @param {string} connectionType The connection type. |
71 * @private | 71 * @private |
72 */ | 72 */ |
73 this.onRouteChangedHandler_ = function(channel, connectionType) {}; | 73 this.onRouteChangedHandler_ = function(channel, connectionType) {}; |
74 | 74 |
75 /** | 75 /** |
76 * @param {boolean} ready Connection ready state. | 76 * @param {boolean} ready Connection ready state. |
77 * @private | 77 * @private |
78 */ | 78 */ |
79 this.onConnectionReadyHandler_ = function(ready) {}; | 79 this.onConnectionReadyHandler_ = function(ready) {}; |
80 | |
81 /** | |
82 * @param {string} tokenUrl Token-request URL, received from the host. | |
83 * @param {string} hostPublicKey Public key for the host. | |
84 * @param {string} scope OAuth scope to request the token for. | |
85 * @private | |
86 */ | |
87 this.fetchThirdPartyTokenHandler_ = function( | |
88 tokenUrl, hostPublicKey, scope) {}; | |
89 /** | 80 /** |
90 * @param {!Array<string>} capabilities The negotiated capabilities. | 81 * @param {!Array<string>} capabilities The negotiated capabilities. |
91 * @private | 82 * @private |
92 */ | 83 */ |
93 this.onSetCapabilitiesHandler_ = function (capabilities) {}; | 84 this.onSetCapabilitiesHandler_ = function (capabilities) {}; |
94 /** @private */ | |
95 this.fetchPinHandler_ = function (supportsPairing) {}; | |
96 /** | 85 /** |
97 * @param {string} data Remote gnubbyd data. | 86 * @param {string} data Remote gnubbyd data. |
98 * @private | 87 * @private |
99 */ | 88 */ |
100 this.onGnubbyAuthHandler_ = function(data) {}; | 89 this.onGnubbyAuthHandler_ = function(data) {}; |
101 /** | 90 /** |
102 * @param {string} url | 91 * @param {string} url |
103 * @param {number} hotspotX | 92 * @param {number} hotspotX |
104 * @param {number} hotspotY | 93 * @param {number} hotspotY |
105 * @private | 94 * @private |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 that.handleMessage_( | 150 that.handleMessage_( |
162 /** @type {remoting.ClientPluginMessage} */ (event.data)); | 151 /** @type {remoting.ClientPluginMessage} */ (event.data)); |
163 }, false); | 152 }, false); |
164 | 153 |
165 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'native') { | 154 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'native') { |
166 window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500); | 155 window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500); |
167 } | 156 } |
168 | 157 |
169 this.hostDesktop_ = new remoting.ClientPlugin.HostDesktopImpl( | 158 this.hostDesktop_ = new remoting.ClientPlugin.HostDesktopImpl( |
170 this, this.postMessage_.bind(this)); | 159 this, this.postMessage_.bind(this)); |
| 160 |
| 161 /** @private {remoting.CredentialsProvider} */ |
| 162 this.credentials_ = null; |
171 }; | 163 }; |
172 | 164 |
173 /** | 165 /** |
174 * Creates plugin element without adding it to a container. | 166 * Creates plugin element without adding it to a container. |
175 * | 167 * |
176 * @return {HTMLEmbedElement} Plugin element | 168 * @return {HTMLEmbedElement} Plugin element |
177 */ | 169 */ |
178 remoting.ClientPluginImpl.createPluginElement_ = function() { | 170 remoting.ClientPluginImpl.createPluginElement_ = function() { |
179 var plugin = | 171 var plugin = |
180 /** @type {HTMLEmbedElement} */ (document.createElement('embed')); | 172 /** @type {HTMLEmbedElement} */ (document.createElement('embed')); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 }; | 267 }; |
276 | 268 |
277 /** | 269 /** |
278 * @param {function(string, number, number):void} handler | 270 * @param {function(string, number, number):void} handler |
279 */ | 271 */ |
280 remoting.ClientPluginImpl.prototype.setMouseCursorHandler = function(handler) { | 272 remoting.ClientPluginImpl.prototype.setMouseCursorHandler = function(handler) { |
281 this.updateMouseCursorImage_ = handler; | 273 this.updateMouseCursorImage_ = handler; |
282 }; | 274 }; |
283 | 275 |
284 /** | 276 /** |
285 * @param {function(string, string, string):void} handler | |
286 */ | |
287 remoting.ClientPluginImpl.prototype.setFetchThirdPartyTokenHandler = | |
288 function(handler) { | |
289 this.fetchThirdPartyTokenHandler_ = handler; | |
290 }; | |
291 | |
292 /** | |
293 * @param {function(boolean):void} handler | |
294 */ | |
295 remoting.ClientPluginImpl.prototype.setFetchPinHandler = function(handler) { | |
296 this.fetchPinHandler_ = handler; | |
297 }; | |
298 | |
299 /** | |
300 * @param {?function({rects:Array<Array<number>>}):void} handler | 277 * @param {?function({rects:Array<Array<number>>}):void} handler |
301 */ | 278 */ |
302 remoting.ClientPluginImpl.prototype.setDebugDirtyRegionHandler = | 279 remoting.ClientPluginImpl.prototype.setDebugDirtyRegionHandler = |
303 function(handler) { | 280 function(handler) { |
304 this.debugRegionHandler_ = handler; | 281 this.debugRegionHandler_ = handler; |
305 this.plugin_.postMessage(JSON.stringify( | 282 this.plugin_.postMessage(JSON.stringify( |
306 { method: 'enableDebugRegion', data: { enable: handler != null } })); | 283 { method: 'enableDebugRegion', data: { enable: handler != null } })); |
307 }; | 284 }; |
308 | 285 |
309 /** | 286 /** |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 | 406 |
430 } else if (message.method == 'onConnectionReady') { | 407 } else if (message.method == 'onConnectionReady') { |
431 var ready = getBooleanAttr(message.data, 'ready'); | 408 var ready = getBooleanAttr(message.data, 'ready'); |
432 this.onConnectionReadyHandler_(ready); | 409 this.onConnectionReadyHandler_(ready); |
433 | 410 |
434 } else if (message.method == 'fetchPin') { | 411 } else if (message.method == 'fetchPin') { |
435 // The pairingSupported value in the dictionary indicates whether both | 412 // The pairingSupported value in the dictionary indicates whether both |
436 // client and host support pairing. If the client doesn't support pairing, | 413 // client and host support pairing. If the client doesn't support pairing, |
437 // then the value won't be there at all, so give it a default of false. | 414 // then the value won't be there at all, so give it a default of false. |
438 var pairingSupported = getBooleanAttr(message.data, 'pairingSupported', | 415 var pairingSupported = getBooleanAttr(message.data, 'pairingSupported', |
439 false) | 416 false); |
440 this.fetchPinHandler_(pairingSupported); | 417 this.credentials_.getPIN(pairingSupported).then( |
441 | 418 this.onPinFetched_.bind(this) |
| 419 ); |
442 } else if (message.method == 'setCapabilities') { | 420 } else if (message.method == 'setCapabilities') { |
443 /** @type {!Array<string>} */ | 421 /** @type {!Array<string>} */ |
444 var capabilities = tokenize(getStringAttr(message.data, 'capabilities')); | 422 var capabilities = tokenize(getStringAttr(message.data, 'capabilities')); |
445 this.onSetCapabilitiesHandler_(capabilities); | 423 this.onSetCapabilitiesHandler_(capabilities); |
446 | 424 |
447 } else if (message.method == 'fetchThirdPartyToken') { | 425 } else if (message.method == 'fetchThirdPartyToken') { |
448 var tokenUrl = getStringAttr(message.data, 'tokenUrl'); | 426 var tokenUrl = getStringAttr(message.data, 'tokenUrl'); |
449 var hostPublicKey = getStringAttr(message.data, 'hostPublicKey'); | 427 var hostPublicKey = getStringAttr(message.data, 'hostPublicKey'); |
450 var scope = getStringAttr(message.data, 'scope'); | 428 var scope = getStringAttr(message.data, 'scope'); |
451 this.fetchThirdPartyTokenHandler_(tokenUrl, hostPublicKey, scope); | 429 this.credentials_.getThirdPartyToken(tokenUrl, hostPublicKey, scope).then( |
452 | 430 this.onThirdPartyTokenFetched_.bind(this) |
| 431 ); |
453 } else if (message.method == 'pairingResponse') { | 432 } else if (message.method == 'pairingResponse') { |
454 var clientId = getStringAttr(message.data, 'clientId'); | 433 var clientId = getStringAttr(message.data, 'clientId'); |
455 var sharedSecret = getStringAttr(message.data, 'sharedSecret'); | 434 var sharedSecret = getStringAttr(message.data, 'sharedSecret'); |
456 this.onPairingComplete_(clientId, sharedSecret); | 435 this.onPairingComplete_(clientId, sharedSecret); |
457 | 436 |
458 } else if (message.method == 'extensionMessage') { | 437 } else if (message.method == 'extensionMessage') { |
459 var extMsgType = getStringAttr(message.data, 'type'); | 438 var extMsgType = getStringAttr(message.data, 'type'); |
460 var extMsgData = getStringAttr(message.data, 'data'); | 439 var extMsgData = getStringAttr(message.data, 'data'); |
461 switch (extMsgType) { | 440 switch (extMsgType) { |
462 case 'gnubby-auth': | 441 case 'gnubby-auth': |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 { method: 'incomingIq', data: { iq: iq } })); | 562 { method: 'incomingIq', data: { iq: iq } })); |
584 } else { | 563 } else { |
585 // plugin.onIq may not be set after the plugin has been shut | 564 // plugin.onIq may not be set after the plugin has been shut |
586 // down. Particularly this happens when we receive response to | 565 // down. Particularly this happens when we receive response to |
587 // session-terminate stanza. | 566 // session-terminate stanza. |
588 console.warn('plugin.onIq is not set so dropping incoming message.'); | 567 console.warn('plugin.onIq is not set so dropping incoming message.'); |
589 } | 568 } |
590 }; | 569 }; |
591 | 570 |
592 /** | 571 /** |
593 * @param {string} hostJid The jid of the host to connect to. | 572 * @param {remoting.Host} host The host to connect to. |
594 * @param {string} hostPublicKey The base64 encoded version of the host's | |
595 * public key. | |
596 * @param {string} localJid Local jid. | 573 * @param {string} localJid Local jid. |
597 * @param {string} sharedSecret The access code for IT2Me or the PIN | 574 * @param {remoting.CredentialsProvider} credentialsProvider |
598 * for Me2Me. | |
599 * @param {string} authenticationMethods Comma-separated list of | |
600 * authentication methods the client should attempt to use. | |
601 * @param {string} authenticationTag A host-specific tag to mix into | |
602 * authentication hashes. | |
603 * @param {string} clientPairingId For paired Me2Me connections, the | |
604 * pairing id for this client, as issued by the host. | |
605 * @param {string} clientPairedSecret For paired Me2Me connections, the | |
606 * paired secret for this client, as issued by the host. | |
607 */ | 575 */ |
608 remoting.ClientPluginImpl.prototype.connect = function( | 576 remoting.ClientPluginImpl.prototype.connect = |
609 hostJid, hostPublicKey, localJid, sharedSecret, | 577 function(host, localJid, credentialsProvider) { |
610 authenticationMethods, authenticationTag, | |
611 clientPairingId, clientPairedSecret) { | |
612 var keyFilter = ''; | 578 var keyFilter = ''; |
613 if (remoting.platformIsMac()) { | 579 if (remoting.platformIsMac()) { |
614 keyFilter = 'mac'; | 580 keyFilter = 'mac'; |
615 } else if (remoting.platformIsChromeOS()) { | 581 } else if (remoting.platformIsChromeOS()) { |
616 keyFilter = 'cros'; | 582 keyFilter = 'cros'; |
617 } | 583 } |
618 // Use PPB_VideoDecoder API only in Chrome 42 and above. It is broken in | 584 // Use PPB_VideoDecoder API only in Chrome 42 and above. It is broken in |
619 // previous versions of Chrome, see http://crbug.com/447403 . | 585 // previous versions of Chrome, see http://crbug.com/447403 . |
620 // Currently PPAPI doesn't provide a way for plugins to check the Chrome | 586 // Currently PPAPI doesn't provide a way for plugins to check the Chrome |
621 // version, so this check needs to be in the webapp. | 587 // version, so this check needs to be in the webapp. |
622 var enableVideoDecodeRenderer = | 588 var enableVideoDecodeRenderer = |
623 parseInt((remoting.getChromeVersion() || '0').split('.')[0], 10) >= 42; | 589 parseInt((remoting.getChromeVersion() || '0').split('.')[0], 10) >= 42; |
624 this.plugin_.postMessage(JSON.stringify( | 590 this.plugin_.postMessage(JSON.stringify( |
625 { method: 'delegateLargeCursors', data: {} })); | 591 { method: 'delegateLargeCursors', data: {} })); |
| 592 var methods = 'third_party,spake2_pair,spake2_hmac,spake2_plain'; |
| 593 this.credentials_ = credentialsProvider; |
| 594 this.useAsyncPinDialog_(); |
626 this.plugin_.postMessage(JSON.stringify( | 595 this.plugin_.postMessage(JSON.stringify( |
627 { method: 'connect', data: { | 596 { method: 'connect', data: { |
628 hostJid: hostJid, | 597 hostJid: host.jabberId, |
629 hostPublicKey: hostPublicKey, | 598 hostPublicKey: host.publicKey, |
630 localJid: localJid, | 599 localJid: localJid, |
631 sharedSecret: sharedSecret, | 600 sharedSecret: '', |
632 authenticationMethods: authenticationMethods, | 601 authenticationMethods: methods, |
633 authenticationTag: authenticationTag, | 602 authenticationTag: host.hostId, |
634 capabilities: this.capabilities_.join(" "), | 603 capabilities: this.capabilities_.join(" "), |
635 clientPairingId: clientPairingId, | 604 clientPairingId: credentialsProvider.getPairingInfo().id, |
636 clientPairedSecret: clientPairedSecret, | 605 clientPairedSecret: credentialsProvider.getPairingInfo().secret, |
637 keyFilter: keyFilter, | 606 keyFilter: keyFilter, |
638 enableVideoDecodeRenderer: enableVideoDecodeRenderer | 607 enableVideoDecodeRenderer: enableVideoDecodeRenderer |
639 } | 608 } |
640 })); | 609 })); |
641 }; | 610 }; |
642 | 611 |
643 /** | 612 /** |
644 * Release all currently pressed keys. | 613 * Release all currently pressed keys. |
645 */ | 614 */ |
646 remoting.ClientPluginImpl.prototype.releaseAllKeys = function() { | 615 remoting.ClientPluginImpl.prototype.releaseAllKeys = function() { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 return; | 752 return; |
784 } | 753 } |
785 this.plugin_.postMessage(JSON.stringify( | 754 this.plugin_.postMessage(JSON.stringify( |
786 { method: 'videoControl', data: { losslessColor: wantLossless }})); | 755 { method: 'videoControl', data: { losslessColor: wantLossless }})); |
787 }; | 756 }; |
788 | 757 |
789 /** | 758 /** |
790 * Called when a PIN is obtained from the user. | 759 * Called when a PIN is obtained from the user. |
791 * | 760 * |
792 * @param {string} pin The PIN. | 761 * @param {string} pin The PIN. |
| 762 * @private |
793 */ | 763 */ |
794 remoting.ClientPluginImpl.prototype.onPinFetched = | 764 remoting.ClientPluginImpl.prototype.onPinFetched_ = |
795 function(pin) { | 765 function(pin) { |
796 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) { | 766 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) { |
797 return; | 767 return; |
798 } | 768 } |
799 this.plugin_.postMessage(JSON.stringify( | 769 this.plugin_.postMessage(JSON.stringify( |
800 { method: 'onPinFetched', data: { pin: pin }})); | 770 { method: 'onPinFetched', data: { pin: pin }})); |
801 }; | 771 }; |
802 | 772 |
803 /** | 773 /** |
804 * Tells the plugin to ask for the PIN asynchronously. | 774 * Tells the plugin to ask for the PIN asynchronously. |
| 775 * @private |
805 */ | 776 */ |
806 remoting.ClientPluginImpl.prototype.useAsyncPinDialog = | 777 remoting.ClientPluginImpl.prototype.useAsyncPinDialog_ = |
807 function() { | 778 function() { |
808 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) { | 779 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) { |
809 return; | 780 return; |
810 } | 781 } |
811 this.plugin_.postMessage(JSON.stringify( | 782 this.plugin_.postMessage(JSON.stringify( |
812 { method: 'useAsyncPinDialog', data: {} })); | 783 { method: 'useAsyncPinDialog', data: {} })); |
813 }; | 784 }; |
814 | 785 |
815 /** | 786 /** |
816 * Allows automatic mouse-lock. | 787 * Allows automatic mouse-lock. |
817 */ | 788 */ |
818 remoting.ClientPluginImpl.prototype.allowMouseLock = function() { | 789 remoting.ClientPluginImpl.prototype.allowMouseLock = function() { |
819 this.plugin_.postMessage(JSON.stringify( | 790 this.plugin_.postMessage(JSON.stringify( |
820 { method: 'allowMouseLock', data: {} })); | 791 { method: 'allowMouseLock', data: {} })); |
821 }; | 792 }; |
822 | 793 |
823 /** | 794 /** |
824 * Sets the third party authentication token and shared secret. | 795 * Sets the third party authentication token and shared secret. |
825 * | 796 * |
826 * @param {string} token The token received from the token URL. | 797 * @param {remoting.ThirdPartyToken} token |
827 * @param {string} sharedSecret Shared secret received from the token URL. | 798 * @private |
828 */ | 799 */ |
829 remoting.ClientPluginImpl.prototype.onThirdPartyTokenFetched = function( | 800 remoting.ClientPluginImpl.prototype.onThirdPartyTokenFetched_ = function( |
830 token, sharedSecret) { | 801 token) { |
831 this.plugin_.postMessage(JSON.stringify( | 802 this.plugin_.postMessage(JSON.stringify( |
832 { method: 'onThirdPartyTokenFetched', | 803 { method: 'onThirdPartyTokenFetched', |
833 data: { token: token, sharedSecret: sharedSecret}})); | 804 data: { token: token.token, sharedSecret: token.secret}})); |
834 }; | 805 }; |
835 | 806 |
836 /** | 807 /** |
837 * Request pairing with the host for PIN-less authentication. | 808 * Request pairing with the host for PIN-less authentication. |
838 * | 809 * |
839 * @param {string} clientName The human-readable name of the client. | 810 * @param {string} clientName The human-readable name of the client. |
840 * @param {function(string, string):void} onDone, Callback to receive the | 811 * @param {function(string, string):void} onDone, Callback to receive the |
841 * client id and shared secret when they are available. | 812 * client id and shared secret when they are available. |
842 */ | 813 */ |
843 remoting.ClientPluginImpl.prototype.requestPairing = | 814 remoting.ClientPluginImpl.prototype.requestPairing = |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 remoting.DefaultClientPluginFactory.prototype.preloadPlugin = function() { | 908 remoting.DefaultClientPluginFactory.prototype.preloadPlugin = function() { |
938 if (remoting.settings.CLIENT_PLUGIN_TYPE != 'pnacl') { | 909 if (remoting.settings.CLIENT_PLUGIN_TYPE != 'pnacl') { |
939 return; | 910 return; |
940 } | 911 } |
941 | 912 |
942 var plugin = remoting.ClientPluginImpl.createPluginElement_(); | 913 var plugin = remoting.ClientPluginImpl.createPluginElement_(); |
943 plugin.addEventListener( | 914 plugin.addEventListener( |
944 'loadend', function() { document.body.removeChild(plugin); }, false); | 915 'loadend', function() { document.body.removeChild(plugin); }, false); |
945 document.body.appendChild(plugin); | 916 document.body.appendChild(plugin); |
946 }; | 917 }; |
OLD | NEW |