| 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 */ |
| 20 remoting.ClientPluginMessage = function() { |
| 21 /** @type {string} */ |
| 22 this.method = ''; |
| 23 |
| 24 /** @type {Object.<string,*>} */ |
| 25 this.data = {}; |
| 26 }; |
| 27 |
| 19 /** | 28 /** |
| 20 * @param {Element} container The container for the embed element. | 29 * @param {Element} container The container for the embed element. |
| 21 * @param {function(string, string):boolean} onExtensionMessage The handler for | 30 * @param {function(string, string):boolean} onExtensionMessage The handler for |
| 22 * protocol extension messages. Returns true if a message is recognized; | 31 * protocol extension messages. Returns true if a message is recognized; |
| 23 * false otherwise. | 32 * false otherwise. |
| 24 * @param {Array.<string>} requiredCapabilities The set of capabilties that the | 33 * @param {Array.<string>} requiredCapabilities The set of capabilties that the |
| 25 * session must support for this application. | 34 * session must support for this application. |
| 26 * @constructor | 35 * @constructor |
| 27 * @implements {remoting.ClientPlugin} | 36 * @implements {remoting.ClientPlugin} |
| 28 */ | 37 */ |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 /** | 166 /** |
| 158 * @type {remoting.ClientSession.PerfStats} | 167 * @type {remoting.ClientSession.PerfStats} |
| 159 * @private | 168 * @private |
| 160 */ | 169 */ |
| 161 this.perfStats_ = new remoting.ClientSession.PerfStats(); | 170 this.perfStats_ = new remoting.ClientSession.PerfStats(); |
| 162 | 171 |
| 163 /** @type {remoting.ClientPluginImpl} */ | 172 /** @type {remoting.ClientPluginImpl} */ |
| 164 var that = this; | 173 var that = this; |
| 165 /** @param {Event} event Message event from the plugin. */ | 174 /** @param {Event} event Message event from the plugin. */ |
| 166 this.plugin_.addEventListener('message', function(event) { | 175 this.plugin_.addEventListener('message', function(event) { |
| 167 that.handleMessage_(event.data); | 176 that.handleMessage_( |
| 177 /** @type {remoting.ClientPluginMessage} */ (event.data)); |
| 168 }, false); | 178 }, false); |
| 169 | 179 |
| 170 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'native') { | 180 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'native') { |
| 171 window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500); | 181 window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500); |
| 172 } | 182 } |
| 173 }; | 183 }; |
| 174 | 184 |
| 175 /** | 185 /** |
| 176 * Creates plugin element without adding it to a container. | 186 * Creates plugin element without adding it to a container. |
| 177 * | 187 * |
| 178 * @return {remoting.ViewerPlugin} Plugin element | 188 * @return {HTMLEmbedElement} Plugin element |
| 179 */ | 189 */ |
| 180 remoting.ClientPluginImpl.createPluginElement_ = function() { | 190 remoting.ClientPluginImpl.createPluginElement_ = function() { |
| 181 var plugin = /** @type {remoting.ViewerPlugin} */ | 191 var plugin = |
| 182 document.createElement('embed'); | 192 /** @type {HTMLEmbedElement} */ (document.createElement('embed')); |
| 183 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'pnacl') { | 193 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'pnacl') { |
| 184 plugin.src = 'remoting_client_pnacl.nmf'; | 194 plugin.src = 'remoting_client_pnacl.nmf'; |
| 185 plugin.type = 'application/x-pnacl'; | 195 plugin.type = 'application/x-pnacl'; |
| 186 } else if (remoting.settings.CLIENT_PLUGIN_TYPE == 'nacl') { | 196 } else if (remoting.settings.CLIENT_PLUGIN_TYPE == 'nacl') { |
| 187 plugin.src = 'remoting_client_nacl.nmf'; | 197 plugin.src = 'remoting_client_nacl.nmf'; |
| 188 plugin.type = 'application/x-nacl'; | 198 plugin.type = 'application/x-nacl'; |
| 189 } else { | 199 } else { |
| 190 plugin.src = 'about://none'; | 200 plugin.src = 'about://none'; |
| 191 plugin.type = 'application/vnd.chromium.remoting-viewer'; | 201 plugin.type = 'application/vnd.chromium.remoting-viewer'; |
| 192 } | 202 } |
| 193 plugin.width = 0; | 203 plugin.width = '0'; |
| 194 plugin.height = 0; | 204 plugin.height = '0'; |
| 195 plugin.tabIndex = 0; // Required, otherwise focus() doesn't work. | 205 plugin.tabIndex = 0; // Required, otherwise focus() doesn't work. |
| 196 return plugin; | 206 return plugin; |
| 197 } | 207 } |
| 198 | 208 |
| 199 /** | 209 /** |
| 200 * Chromoting session API version (for this javascript). | 210 * Chromoting session API version (for this javascript). |
| 201 * This is compared with the plugin API version to verify that they are | 211 * This is compared with the plugin API version to verify that they are |
| 202 * compatible. | 212 * compatible. |
| 203 * | 213 * |
| 204 * @const | 214 * @const |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 | 266 |
| 257 /** | 267 /** |
| 258 * @param {function():void} handler | 268 * @param {function():void} handler |
| 259 */ | 269 */ |
| 260 remoting.ClientPluginImpl.prototype.setDesktopSizeUpdateHandler = | 270 remoting.ClientPluginImpl.prototype.setDesktopSizeUpdateHandler = |
| 261 function(handler) { | 271 function(handler) { |
| 262 this.onDesktopSizeUpdateHandler_ = handler; | 272 this.onDesktopSizeUpdateHandler_ = handler; |
| 263 }; | 273 }; |
| 264 | 274 |
| 265 /** | 275 /** |
| 266 * @param {function():void} handler | 276 * @param {function(Array.<Array.<number>>):void} handler |
| 267 */ | 277 */ |
| 268 remoting.ClientPluginImpl.prototype.setDesktopShapeUpdateHandler = | 278 remoting.ClientPluginImpl.prototype.setDesktopShapeUpdateHandler = |
| 269 function(handler) { | 279 function(handler) { |
| 270 this.onDesktopShapeUpdateHandler_ = handler; | 280 this.onDesktopShapeUpdateHandler_ = handler; |
| 271 }; | 281 }; |
| 272 | 282 |
| 273 /** | 283 /** |
| 274 * @param {function(!Array.<string>):void} handler | 284 * @param {function(!Array.<string>):void} handler |
| 275 */ | 285 */ |
| 276 remoting.ClientPluginImpl.prototype.setCapabilitiesHandler = function(handler) { | 286 remoting.ClientPluginImpl.prototype.setCapabilitiesHandler = function(handler) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 }; | 318 }; |
| 309 | 319 |
| 310 /** | 320 /** |
| 311 * @param {function(boolean):void} handler | 321 * @param {function(boolean):void} handler |
| 312 */ | 322 */ |
| 313 remoting.ClientPluginImpl.prototype.setFetchPinHandler = function(handler) { | 323 remoting.ClientPluginImpl.prototype.setFetchPinHandler = function(handler) { |
| 314 this.fetchPinHandler_ = handler; | 324 this.fetchPinHandler_ = handler; |
| 315 }; | 325 }; |
| 316 | 326 |
| 317 /** | 327 /** |
| 318 * @param {string|{method:string, data:Object.<string,*>}} | 328 * @param {string|remoting.ClientPluginMessage} |
| 319 * rawMessage Message from the plugin. | 329 * rawMessage Message from the plugin. |
| 320 * @private | 330 * @private |
| 321 */ | 331 */ |
| 322 remoting.ClientPluginImpl.prototype.handleMessage_ = function(rawMessage) { | 332 remoting.ClientPluginImpl.prototype.handleMessage_ = function(rawMessage) { |
| 323 var message = | 333 var message = |
| 324 /** @type {{method:string, data:Object.<string,*>}} */ | 334 /** @type {remoting.ClientPluginMessage} */ |
| 325 ((typeof(rawMessage) == 'string') ? base.jsonParseSafe(rawMessage) | 335 ((typeof(rawMessage) == 'string') ? base.jsonParseSafe(rawMessage) |
| 326 : rawMessage); | 336 : rawMessage); |
| 327 if (!message || !('method' in message) || !('data' in message)) { | 337 if (!message || !('method' in message) || !('data' in message)) { |
| 328 console.error('Received invalid message from the plugin:', rawMessage); | 338 console.error('Received invalid message from the plugin:', rawMessage); |
| 329 return; | 339 return; |
| 330 } | 340 } |
| 331 | 341 |
| 332 try { | 342 try { |
| 333 this.handleMessageMethod_(message); | 343 this.handleMessageMethod_(message); |
| 334 } catch(e) { | 344 } catch(/** @type {*} */ e) { |
| 335 console.error(/** @type {*} */ (e)); | 345 console.error(e); |
| 336 } | 346 } |
| 337 } | 347 } |
| 338 | 348 |
| 339 /** | 349 /** |
| 340 * @param {{method:string, data:Object.<string,*>}} | 350 * @param {remoting.ClientPluginMessage} |
| 341 * message Parsed message from the plugin. | 351 * message Parsed message from the plugin. |
| 342 * @private | 352 * @private |
| 343 */ | 353 */ |
| 344 remoting.ClientPluginImpl.prototype.handleMessageMethod_ = function(message) { | 354 remoting.ClientPluginImpl.prototype.handleMessageMethod_ = function(message) { |
| 345 /** | 355 /** |
| 346 * Splits a string into a list of words delimited by spaces. | 356 * Splits a string into a list of words delimited by spaces. |
| 347 * @param {string} str String that should be split. | 357 * @param {string} str String that should be split. |
| 348 * @return {!Array.<string>} List of words. | 358 * @return {!Array.<string>} List of words. |
| 349 */ | 359 */ |
| 350 var tokenize = function(str) { | 360 var tokenize = function(str) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 // 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 |
| 437 // is not a number. | 447 // is not a number. |
| 438 getNumberAttr(message.data, 'videoBandwidth'); | 448 getNumberAttr(message.data, 'videoBandwidth'); |
| 439 getNumberAttr(message.data, 'videoFrameRate'); | 449 getNumberAttr(message.data, 'videoFrameRate'); |
| 440 getNumberAttr(message.data, 'captureLatency'); | 450 getNumberAttr(message.data, 'captureLatency'); |
| 441 getNumberAttr(message.data, 'encodeLatency'); | 451 getNumberAttr(message.data, 'encodeLatency'); |
| 442 getNumberAttr(message.data, 'decodeLatency'); | 452 getNumberAttr(message.data, 'decodeLatency'); |
| 443 getNumberAttr(message.data, 'renderLatency'); | 453 getNumberAttr(message.data, 'renderLatency'); |
| 444 getNumberAttr(message.data, 'roundtripLatency'); | 454 getNumberAttr(message.data, 'roundtripLatency'); |
| 445 this.perfStats_ = | 455 this.perfStats_ = |
| 446 /** @type {remoting.ClientSession.PerfStats} */ message.data; | 456 /** @type {remoting.ClientSession.PerfStats} */ (message.data); |
| 447 | 457 |
| 448 } else if (message.method == 'injectClipboardItem') { | 458 } else if (message.method == 'injectClipboardItem') { |
| 449 var mimetype = getStringAttr(message.data, 'mimeType'); | 459 var mimetype = getStringAttr(message.data, 'mimeType'); |
| 450 var item = getStringAttr(message.data, 'item'); | 460 var item = getStringAttr(message.data, 'item'); |
| 451 if (remoting.clipboard) { | 461 if (remoting.clipboard) { |
| 452 remoting.clipboard.fromHost(mimetype, item); | 462 remoting.clipboard.fromHost(mimetype, item); |
| 453 } | 463 } |
| 454 | 464 |
| 455 } else if (message.method == 'onFirstFrameReceived') { | 465 } else if (message.method == 'onFirstFrameReceived') { |
| 456 if (remoting.clientSession) { | 466 if (remoting.clientSession) { |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 remoting.DefaultClientPluginFactory.prototype.preloadPlugin = function() { | 971 remoting.DefaultClientPluginFactory.prototype.preloadPlugin = function() { |
| 962 if (remoting.settings.CLIENT_PLUGIN_TYPE != 'pnacl') { | 972 if (remoting.settings.CLIENT_PLUGIN_TYPE != 'pnacl') { |
| 963 return; | 973 return; |
| 964 } | 974 } |
| 965 | 975 |
| 966 var plugin = remoting.ClientPluginImpl.createPluginElement_(); | 976 var plugin = remoting.ClientPluginImpl.createPluginElement_(); |
| 967 plugin.addEventListener( | 977 plugin.addEventListener( |
| 968 'loadend', function() { document.body.removeChild(plugin); }, false); | 978 'loadend', function() { document.body.removeChild(plugin); }, false); |
| 969 document.body.appendChild(plugin); | 979 document.body.appendChild(plugin); |
| 970 }; | 980 }; |
| OLD | NEW |