| 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 |
| 11 * client plugins versions when it is necessary. | 11 * client plugins versions when it is necessary. |
| 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 /** @constructor */ | 19 /** @constructor */ |
| 20 remoting.ClientPluginMessage = function() { | 20 remoting.ClientPluginMessage = function() { |
| 21 /** @type {string} */ | 21 /** @type {string} */ |
| 22 this.method = ''; | 22 this.method = ''; |
| 23 | 23 |
| 24 /** @type {Object.<string,*>} */ | 24 /** @type {Object<string,*>} */ |
| 25 this.data = {}; | 25 this.data = {}; |
| 26 }; | 26 }; |
| 27 | 27 |
| 28 /** | 28 /** |
| 29 * @param {Element} container The container for the embed element. | 29 * @param {Element} container The container for the embed element. |
| 30 * @param {function(string, string):boolean} onExtensionMessage The handler for | 30 * @param {function(string, string):boolean} onExtensionMessage The handler for |
| 31 * protocol extension messages. Returns true if a message is recognized; | 31 * protocol extension messages. Returns true if a message is recognized; |
| 32 * false otherwise. | 32 * false otherwise. |
| 33 * @param {Array.<string>} requiredCapabilities The set of capabilties that the | 33 * @param {Array<string>} requiredCapabilities The set of capabilties that the |
| 34 * session must support for this application. | 34 * session must support for this application. |
| 35 * @constructor | 35 * @constructor |
| 36 * @implements {remoting.ClientPlugin} | 36 * @implements {remoting.ClientPlugin} |
| 37 */ | 37 */ |
| 38 remoting.ClientPluginImpl = function(container, onExtensionMessage, | 38 remoting.ClientPluginImpl = function(container, onExtensionMessage, |
| 39 requiredCapabilities) { | 39 requiredCapabilities) { |
| 40 this.plugin_ = remoting.ClientPluginImpl.createPluginElement_(); | 40 this.plugin_ = remoting.ClientPluginImpl.createPluginElement_(); |
| 41 this.plugin_.id = 'session-client-plugin'; | 41 this.plugin_.id = 'session-client-plugin'; |
| 42 container.appendChild(this.plugin_); | 42 container.appendChild(this.plugin_); |
| 43 | 43 |
| 44 this.onExtensionMessage_ = onExtensionMessage; | 44 this.onExtensionMessage_ = onExtensionMessage; |
| 45 /** | 45 /** |
| 46 * @type {Array.<string>} | 46 * @type {Array<string>} |
| 47 * @private | 47 * @private |
| 48 */ | 48 */ |
| 49 this.requiredCapabilities_ = requiredCapabilities; | 49 this.requiredCapabilities_ = requiredCapabilities; |
| 50 | 50 |
| 51 /** @private */ | 51 /** @private */ |
| 52 this.desktopWidth_ = 0; | 52 this.desktopWidth_ = 0; |
| 53 /** @private */ | 53 /** @private */ |
| 54 this.desktopHeight_ = 0; | 54 this.desktopHeight_ = 0; |
| 55 /** @private */ | 55 /** @private */ |
| 56 this.desktopXDpi_ = 96; | 56 this.desktopXDpi_ = 96; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 * @param {string} tokenUrl Token-request URL, received from the host. | 91 * @param {string} tokenUrl Token-request URL, received from the host. |
| 92 * @param {string} hostPublicKey Public key for the host. | 92 * @param {string} hostPublicKey Public key for the host. |
| 93 * @param {string} scope OAuth scope to request the token for. | 93 * @param {string} scope OAuth scope to request the token for. |
| 94 * @private | 94 * @private |
| 95 */ | 95 */ |
| 96 this.fetchThirdPartyTokenHandler_ = function( | 96 this.fetchThirdPartyTokenHandler_ = function( |
| 97 tokenUrl, hostPublicKey, scope) {}; | 97 tokenUrl, hostPublicKey, scope) {}; |
| 98 /** @private */ | 98 /** @private */ |
| 99 this.onDesktopSizeUpdateHandler_ = function () {}; | 99 this.onDesktopSizeUpdateHandler_ = function () {}; |
| 100 /** | 100 /** |
| 101 * @param {Array.<Array.<number>>} rects | 101 * @param {Array<Array<number>>} rects |
| 102 * @private | 102 * @private |
| 103 */ | 103 */ |
| 104 this.onDesktopShapeUpdateHandler_ = function (rects) {}; | 104 this.onDesktopShapeUpdateHandler_ = function (rects) {}; |
| 105 /** | 105 /** |
| 106 * @param {!Array.<string>} capabilities The negotiated capabilities. | 106 * @param {!Array<string>} capabilities The negotiated capabilities. |
| 107 * @private | 107 * @private |
| 108 */ | 108 */ |
| 109 this.onSetCapabilitiesHandler_ = function (capabilities) {}; | 109 this.onSetCapabilitiesHandler_ = function (capabilities) {}; |
| 110 /** @private */ | 110 /** @private */ |
| 111 this.fetchPinHandler_ = function (supportsPairing) {}; | 111 this.fetchPinHandler_ = function (supportsPairing) {}; |
| 112 /** | 112 /** |
| 113 * @param {string} data Remote gnubbyd data. | 113 * @param {string} data Remote gnubbyd data. |
| 114 * @private | 114 * @private |
| 115 */ | 115 */ |
| 116 this.onGnubbyAuthHandler_ = function(data) {}; | 116 this.onGnubbyAuthHandler_ = function(data) {}; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 127 * @private | 127 * @private |
| 128 */ | 128 */ |
| 129 this.onCastExtensionHandler_ = function(data) {}; | 129 this.onCastExtensionHandler_ = function(data) {}; |
| 130 | 130 |
| 131 /** | 131 /** |
| 132 * @type {number} | 132 * @type {number} |
| 133 * @private | 133 * @private |
| 134 */ | 134 */ |
| 135 this.pluginApiVersion_ = -1; | 135 this.pluginApiVersion_ = -1; |
| 136 /** | 136 /** |
| 137 * @type {Array.<string>} | 137 * @type {Array<string>} |
| 138 * @private | 138 * @private |
| 139 */ | 139 */ |
| 140 this.pluginApiFeatures_ = []; | 140 this.pluginApiFeatures_ = []; |
| 141 /** | 141 /** |
| 142 * @type {number} | 142 * @type {number} |
| 143 * @private | 143 * @private |
| 144 */ | 144 */ |
| 145 this.pluginApiMinVersion_ = -1; | 145 this.pluginApiMinVersion_ = -1; |
| 146 /** | 146 /** |
| 147 * @type {!Array.<string>} | 147 * @type {!Array<string>} |
| 148 * @private | 148 * @private |
| 149 */ | 149 */ |
| 150 this.capabilities_ = []; | 150 this.capabilities_ = []; |
| 151 /** | 151 /** |
| 152 * @type {boolean} | 152 * @type {boolean} |
| 153 * @private | 153 * @private |
| 154 */ | 154 */ |
| 155 this.helloReceived_ = false; | 155 this.helloReceived_ = false; |
| 156 /** | 156 /** |
| 157 * @type {function(boolean)|null} | 157 * @type {function(boolean)|null} |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 | 266 |
| 267 /** | 267 /** |
| 268 * @param {function():void} handler | 268 * @param {function():void} handler |
| 269 */ | 269 */ |
| 270 remoting.ClientPluginImpl.prototype.setDesktopSizeUpdateHandler = | 270 remoting.ClientPluginImpl.prototype.setDesktopSizeUpdateHandler = |
| 271 function(handler) { | 271 function(handler) { |
| 272 this.onDesktopSizeUpdateHandler_ = handler; | 272 this.onDesktopSizeUpdateHandler_ = handler; |
| 273 }; | 273 }; |
| 274 | 274 |
| 275 /** | 275 /** |
| 276 * @param {function(Array.<Array.<number>>):void} handler | 276 * @param {function(Array<Array<number>>):void} handler |
| 277 */ | 277 */ |
| 278 remoting.ClientPluginImpl.prototype.setDesktopShapeUpdateHandler = | 278 remoting.ClientPluginImpl.prototype.setDesktopShapeUpdateHandler = |
| 279 function(handler) { | 279 function(handler) { |
| 280 this.onDesktopShapeUpdateHandler_ = handler; | 280 this.onDesktopShapeUpdateHandler_ = handler; |
| 281 }; | 281 }; |
| 282 | 282 |
| 283 /** | 283 /** |
| 284 * @param {function(!Array.<string>):void} handler | 284 * @param {function(!Array<string>):void} handler |
| 285 */ | 285 */ |
| 286 remoting.ClientPluginImpl.prototype.setCapabilitiesHandler = function(handler) { | 286 remoting.ClientPluginImpl.prototype.setCapabilitiesHandler = function(handler) { |
| 287 this.onSetCapabilitiesHandler_ = handler; | 287 this.onSetCapabilitiesHandler_ = handler; |
| 288 }; | 288 }; |
| 289 | 289 |
| 290 /** | 290 /** |
| 291 * @param {function(string):void} handler | 291 * @param {function(string):void} handler |
| 292 */ | 292 */ |
| 293 remoting.ClientPluginImpl.prototype.setGnubbyAuthHandler = function(handler) { | 293 remoting.ClientPluginImpl.prototype.setGnubbyAuthHandler = function(handler) { |
| 294 this.onGnubbyAuthHandler_ = handler; | 294 this.onGnubbyAuthHandler_ = handler; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 | 348 |
| 349 /** | 349 /** |
| 350 * @param {remoting.ClientPluginMessage} | 350 * @param {remoting.ClientPluginMessage} |
| 351 * message Parsed message from the plugin. | 351 * message Parsed message from the plugin. |
| 352 * @private | 352 * @private |
| 353 */ | 353 */ |
| 354 remoting.ClientPluginImpl.prototype.handleMessageMethod_ = function(message) { | 354 remoting.ClientPluginImpl.prototype.handleMessageMethod_ = function(message) { |
| 355 /** | 355 /** |
| 356 * Splits a string into a list of words delimited by spaces. | 356 * Splits a string into a list of words delimited by spaces. |
| 357 * @param {string} str String that should be split. | 357 * @param {string} str String that should be split. |
| 358 * @return {!Array.<string>} List of words. | 358 * @return {!Array<string>} List of words. |
| 359 */ | 359 */ |
| 360 var tokenize = function(str) { | 360 var tokenize = function(str) { |
| 361 /** @type {Array.<string>} */ | 361 /** @type {Array<string>} */ |
| 362 var tokens = str.match(/\S+/g); | 362 var tokens = str.match(/\S+/g); |
| 363 return tokens ? tokens : []; | 363 return tokens ? tokens : []; |
| 364 }; | 364 }; |
| 365 | 365 |
| 366 if (message.method == 'hello') { | 366 if (message.method == 'hello') { |
| 367 // Resize in case we had to enlarge it to support click-to-play. | 367 // Resize in case we had to enlarge it to support click-to-play. |
| 368 this.hidePluginForClickToPlay_(); | 368 this.hidePluginForClickToPlay_(); |
| 369 this.pluginApiVersion_ = getNumberAttr(message.data, 'apiVersion'); | 369 this.pluginApiVersion_ = getNumberAttr(message.data, 'apiVersion'); |
| 370 this.pluginApiMinVersion_ = getNumberAttr(message.data, 'apiMinVersion'); | 370 this.pluginApiMinVersion_ = getNumberAttr(message.data, 'apiMinVersion'); |
| 371 | 371 |
| 372 if (this.pluginApiVersion_ >= 7) { | 372 if (this.pluginApiVersion_ >= 7) { |
| 373 this.pluginApiFeatures_ = | 373 this.pluginApiFeatures_ = |
| 374 tokenize(getStringAttr(message.data, 'apiFeatures')); | 374 tokenize(getStringAttr(message.data, 'apiFeatures')); |
| 375 | 375 |
| 376 // Negotiate capabilities. | 376 // Negotiate capabilities. |
| 377 | 377 |
| 378 /** @type {!Array.<string>} */ | 378 /** @type {!Array<string>} */ |
| 379 var requestedCapabilities = []; | 379 var requestedCapabilities = []; |
| 380 if ('requestedCapabilities' in message.data) { | 380 if ('requestedCapabilities' in message.data) { |
| 381 requestedCapabilities = | 381 requestedCapabilities = |
| 382 tokenize(getStringAttr(message.data, 'requestedCapabilities')); | 382 tokenize(getStringAttr(message.data, 'requestedCapabilities')); |
| 383 } | 383 } |
| 384 | 384 |
| 385 /** @type {!Array.<string>} */ | 385 /** @type {!Array<string>} */ |
| 386 var supportedCapabilities = []; | 386 var supportedCapabilities = []; |
| 387 if ('supportedCapabilities' in message.data) { | 387 if ('supportedCapabilities' in message.data) { |
| 388 supportedCapabilities = | 388 supportedCapabilities = |
| 389 tokenize(getStringAttr(message.data, 'supportedCapabilities')); | 389 tokenize(getStringAttr(message.data, 'supportedCapabilities')); |
| 390 } | 390 } |
| 391 // At the moment the webapp does not recognize any of | 391 // At the moment the webapp does not recognize any of |
| 392 // 'requestedCapabilities' capabilities (so they all should be disabled) | 392 // 'requestedCapabilities' capabilities (so they all should be disabled) |
| 393 // and do not care about any of 'supportedCapabilities' capabilities (so | 393 // and do not care about any of 'supportedCapabilities' capabilities (so |
| 394 // they all can be enabled). | 394 // they all can be enabled). |
| 395 // All the required capabilities (specified by the app) are added to this. | 395 // All the required capabilities (specified by the app) are added to this. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 } else if (message.method == 'onDesktopSize') { | 427 } else if (message.method == 'onDesktopSize') { |
| 428 this.desktopWidth_ = getNumberAttr(message.data, 'width'); | 428 this.desktopWidth_ = getNumberAttr(message.data, 'width'); |
| 429 this.desktopHeight_ = getNumberAttr(message.data, 'height'); | 429 this.desktopHeight_ = getNumberAttr(message.data, 'height'); |
| 430 this.desktopXDpi_ = getNumberAttr(message.data, 'x_dpi', 96); | 430 this.desktopXDpi_ = getNumberAttr(message.data, 'x_dpi', 96); |
| 431 this.desktopYDpi_ = getNumberAttr(message.data, 'y_dpi', 96); | 431 this.desktopYDpi_ = getNumberAttr(message.data, 'y_dpi', 96); |
| 432 this.onDesktopSizeUpdateHandler_(); | 432 this.onDesktopSizeUpdateHandler_(); |
| 433 | 433 |
| 434 } else if (message.method == 'onDesktopShape') { | 434 } else if (message.method == 'onDesktopShape') { |
| 435 var rects = getArrayAttr(message.data, 'rects'); | 435 var rects = getArrayAttr(message.data, 'rects'); |
| 436 for (var i = 0; i < rects.length; ++i) { | 436 for (var i = 0; i < rects.length; ++i) { |
| 437 /** @type {Array.<number>} */ | 437 /** @type {Array<number>} */ |
| 438 var rect = rects[i]; | 438 var rect = rects[i]; |
| 439 if (typeof rect != 'object' || rect.length != 4) { | 439 if (typeof rect != 'object' || rect.length != 4) { |
| 440 throw 'Received invalid onDesktopShape message'; | 440 throw 'Received invalid onDesktopShape message'; |
| 441 } | 441 } |
| 442 } | 442 } |
| 443 this.onDesktopShapeUpdateHandler_(rects); | 443 this.onDesktopShapeUpdateHandler_(rects); |
| 444 | 444 |
| 445 } else if (message.method == 'onPerfStats') { | 445 } else if (message.method == 'onPerfStats') { |
| 446 // Return value is ignored. These calls will throw an error if the value | 446 // Return value is ignored. These calls will throw an error if the value |
| 447 // is not a number. | 447 // is not a number. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 473 | 473 |
| 474 } else if (message.method == 'fetchPin') { | 474 } else if (message.method == 'fetchPin') { |
| 475 // The pairingSupported value in the dictionary indicates whether both | 475 // The pairingSupported value in the dictionary indicates whether both |
| 476 // client and host support pairing. If the client doesn't support pairing, | 476 // client and host support pairing. If the client doesn't support pairing, |
| 477 // then the value won't be there at all, so give it a default of false. | 477 // then the value won't be there at all, so give it a default of false. |
| 478 var pairingSupported = getBooleanAttr(message.data, 'pairingSupported', | 478 var pairingSupported = getBooleanAttr(message.data, 'pairingSupported', |
| 479 false) | 479 false) |
| 480 this.fetchPinHandler_(pairingSupported); | 480 this.fetchPinHandler_(pairingSupported); |
| 481 | 481 |
| 482 } else if (message.method == 'setCapabilities') { | 482 } else if (message.method == 'setCapabilities') { |
| 483 /** @type {!Array.<string>} */ | 483 /** @type {!Array<string>} */ |
| 484 var capabilities = tokenize(getStringAttr(message.data, 'capabilities')); | 484 var capabilities = tokenize(getStringAttr(message.data, 'capabilities')); |
| 485 this.onSetCapabilitiesHandler_(capabilities); | 485 this.onSetCapabilitiesHandler_(capabilities); |
| 486 | 486 |
| 487 } else if (message.method == 'fetchThirdPartyToken') { | 487 } else if (message.method == 'fetchThirdPartyToken') { |
| 488 var tokenUrl = getStringAttr(message.data, 'tokenUrl'); | 488 var tokenUrl = getStringAttr(message.data, 'tokenUrl'); |
| 489 var hostPublicKey = getStringAttr(message.data, 'hostPublicKey'); | 489 var hostPublicKey = getStringAttr(message.data, 'hostPublicKey'); |
| 490 var scope = getStringAttr(message.data, 'scope'); | 490 var scope = getStringAttr(message.data, 'scope'); |
| 491 this.fetchThirdPartyTokenHandler_(tokenUrl, hostPublicKey, scope); | 491 this.fetchThirdPartyTokenHandler_(tokenUrl, hostPublicKey, scope); |
| 492 | 492 |
| 493 } else if (message.method == 'pairingResponse') { | 493 } else if (message.method == 'pairingResponse') { |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 | 959 |
| 960 /** | 960 /** |
| 961 * @constructor | 961 * @constructor |
| 962 * @implements {remoting.ClientPluginFactory} | 962 * @implements {remoting.ClientPluginFactory} |
| 963 */ | 963 */ |
| 964 remoting.DefaultClientPluginFactory = function() {}; | 964 remoting.DefaultClientPluginFactory = function() {}; |
| 965 | 965 |
| 966 /** | 966 /** |
| 967 * @param {Element} container | 967 * @param {Element} container |
| 968 * @param {function(string, string):boolean} onExtensionMessage | 968 * @param {function(string, string):boolean} onExtensionMessage |
| 969 * @param {Array.<string>} requiredCapabilities | 969 * @param {Array<string>} requiredCapabilities |
| 970 * @return {remoting.ClientPlugin} | 970 * @return {remoting.ClientPlugin} |
| 971 */ | 971 */ |
| 972 remoting.DefaultClientPluginFactory.prototype.createPlugin = | 972 remoting.DefaultClientPluginFactory.prototype.createPlugin = |
| 973 function(container, onExtensionMessage, requiredCapabilities) { | 973 function(container, onExtensionMessage, requiredCapabilities) { |
| 974 return new remoting.ClientPluginImpl(container, onExtensionMessage, | 974 return new remoting.ClientPluginImpl(container, onExtensionMessage, |
| 975 requiredCapabilities); | 975 requiredCapabilities); |
| 976 }; | 976 }; |
| 977 | 977 |
| 978 remoting.DefaultClientPluginFactory.prototype.preloadPlugin = function() { | 978 remoting.DefaultClientPluginFactory.prototype.preloadPlugin = function() { |
| 979 if (remoting.settings.CLIENT_PLUGIN_TYPE != 'pnacl') { | 979 if (remoting.settings.CLIENT_PLUGIN_TYPE != 'pnacl') { |
| 980 return; | 980 return; |
| 981 } | 981 } |
| 982 | 982 |
| 983 var plugin = remoting.ClientPluginImpl.createPluginElement_(); | 983 var plugin = remoting.ClientPluginImpl.createPluginElement_(); |
| 984 plugin.addEventListener( | 984 plugin.addEventListener( |
| 985 'loadend', function() { document.body.removeChild(plugin); }, false); | 985 'loadend', function() { document.body.removeChild(plugin); }, false); |
| 986 document.body.appendChild(plugin); | 986 document.body.appendChild(plugin); |
| 987 }; | 987 }; |
| OLD | NEW |