| 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 /** | 19 /** |
| 20 * @param {Element} container The container for the embed element. | 20 * @param {Element} container The container for the embed element. |
| 21 * @param {function(string, string):boolean} onExtensionMessage The handler for | 21 * @param {function(string, string):boolean} onExtensionMessage The handler for |
| 22 * protocol extension messages. Returns true if a message is recognized; | 22 * protocol extension messages. Returns true if a message is recognized; |
| 23 * false otherwise. | 23 * false otherwise. |
| 24 * @constructor | 24 * @constructor |
| 25 * @implements {remoting.ClientPluginInterface} |
| 25 */ | 26 */ |
| 26 remoting.ClientPlugin = function(container, onExtensionMessage) { | 27 remoting.ClientPlugin = function(container, onExtensionMessage) { |
| 27 this.plugin_ = remoting.ClientPlugin.createPluginElement_(); | 28 this.plugin_ = remoting.ClientPlugin.createPluginElement_(); |
| 28 this.plugin_.id = 'session-client-plugin'; | 29 this.plugin_.id = 'session-client-plugin'; |
| 29 container.appendChild(this.plugin_); | 30 container.appendChild(this.plugin_); |
| 30 | 31 |
| 31 this.onExtensionMessage_ = onExtensionMessage; | 32 this.onExtensionMessage_ = onExtensionMessage; |
| 32 | 33 |
| 33 this.desktopWidth = 0; | 34 /** @private */ |
| 34 this.desktopHeight = 0; | 35 this.desktopWidth_ = 0; |
| 35 this.desktopXDpi = 96; | 36 /** @private */ |
| 36 this.desktopYDpi = 96; | 37 this.desktopHeight_ = 0; |
| 38 /** @private */ |
| 39 this.desktopXDpi_ = 96; |
| 40 /** @private */ |
| 41 this.desktopYDpi_ = 96; |
| 37 | 42 |
| 38 /** @param {string} iq The Iq stanza received from the host. */ | 43 /** |
| 39 this.onOutgoingIqHandler = function (iq) {}; | 44 * @param {string} iq The Iq stanza received from the host. |
| 40 /** @param {string} message Log message. */ | 45 * @private |
| 41 this.onDebugMessageHandler = function (message) {}; | 46 */ |
| 47 this.onOutgoingIqHandler_ = function (iq) {}; |
| 48 /** |
| 49 * @param {string} message Log message. |
| 50 * @private |
| 51 */ |
| 52 this.onDebugMessageHandler_ = function (message) {}; |
| 42 /** | 53 /** |
| 43 * @param {number} state The connection state. | 54 * @param {number} state The connection state. |
| 44 * @param {number} error The error code, if any. | 55 * @param {number} error The error code, if any. |
| 56 * @private |
| 45 */ | 57 */ |
| 46 this.onConnectionStatusUpdateHandler = function(state, error) {}; | 58 this.onConnectionStatusUpdateHandler_ = function(state, error) {}; |
| 47 /** @param {boolean} ready Connection ready state. */ | 59 /** |
| 48 this.onConnectionReadyHandler = function(ready) {}; | 60 * @param {boolean} ready Connection ready state. |
| 61 * @private |
| 62 */ |
| 63 this.onConnectionReadyHandler_ = function(ready) {}; |
| 49 | 64 |
| 50 /** | 65 /** |
| 51 * @param {string} tokenUrl Token-request URL, received from the host. | 66 * @param {string} tokenUrl Token-request URL, received from the host. |
| 52 * @param {string} hostPublicKey Public key for the host. | 67 * @param {string} hostPublicKey Public key for the host. |
| 53 * @param {string} scope OAuth scope to request the token for. | 68 * @param {string} scope OAuth scope to request the token for. |
| 69 * @private |
| 54 */ | 70 */ |
| 55 this.fetchThirdPartyTokenHandler = function( | 71 this.fetchThirdPartyTokenHandler_ = function( |
| 56 tokenUrl, hostPublicKey, scope) {}; | 72 tokenUrl, hostPublicKey, scope) {}; |
| 57 this.onDesktopSizeUpdateHandler = function () {}; | 73 /** @private */ |
| 58 /** @param {!Array.<string>} capabilities The negotiated capabilities. */ | 74 this.onDesktopSizeUpdateHandler_ = function () {}; |
| 59 this.onSetCapabilitiesHandler = function (capabilities) {}; | 75 /** |
| 60 this.fetchPinHandler = function (supportsPairing) {}; | 76 * @param {!Array.<string>} capabilities The negotiated capabilities. |
| 61 /** @param {string} data Remote gnubbyd data. */ | 77 * @private |
| 62 this.onGnubbyAuthHandler = function(data) {}; | 78 */ |
| 79 this.onSetCapabilitiesHandler_ = function (capabilities) {}; |
| 80 /** @private */ |
| 81 this.fetchPinHandler_ = function (supportsPairing) {}; |
| 82 /** |
| 83 * @param {string} data Remote gnubbyd data. |
| 84 * @private |
| 85 */ |
| 86 this.onGnubbyAuthHandler_ = function(data) {}; |
| 63 /** | 87 /** |
| 64 * @param {string} url | 88 * @param {string} url |
| 65 * @param {number} hotspotX | 89 * @param {number} hotspotX |
| 66 * @param {number} hotspotY | 90 * @param {number} hotspotY |
| 91 * @private |
| 67 */ | 92 */ |
| 68 this.updateMouseCursorImage = function(url, hotspotX, hotspotY) {}; | 93 this.updateMouseCursorImage_ = function(url, hotspotX, hotspotY) {}; |
| 69 | 94 |
| 70 /** @param {string} data Remote cast extension message. */ | 95 /** |
| 71 this.onCastExtensionHandler = function(data) {}; | 96 * @param {string} data Remote cast extension message. |
| 97 * @private |
| 98 */ |
| 99 this.onCastExtensionHandler_ = function(data) {}; |
| 72 | 100 |
| 73 /** @type {remoting.MediaSourceRenderer} */ | 101 /** |
| 102 * @type {remoting.MediaSourceRenderer} |
| 103 * @private |
| 104 */ |
| 74 this.mediaSourceRenderer_ = null; | 105 this.mediaSourceRenderer_ = null; |
| 75 | 106 |
| 76 /** @type {number} */ | 107 /** |
| 108 * @type {number} |
| 109 * @private |
| 110 */ |
| 77 this.pluginApiVersion_ = -1; | 111 this.pluginApiVersion_ = -1; |
| 78 /** @type {Array.<string>} */ | 112 /** |
| 113 * @type {Array.<string>} |
| 114 * @private |
| 115 */ |
| 79 this.pluginApiFeatures_ = []; | 116 this.pluginApiFeatures_ = []; |
| 80 /** @type {number} */ | 117 /** |
| 118 * @type {number} |
| 119 * @private |
| 120 */ |
| 81 this.pluginApiMinVersion_ = -1; | 121 this.pluginApiMinVersion_ = -1; |
| 82 /** @type {!Array.<string>} */ | 122 /** |
| 123 * @type {!Array.<string>} |
| 124 * @private |
| 125 */ |
| 83 this.capabilities_ = []; | 126 this.capabilities_ = []; |
| 84 /** @type {boolean} */ | 127 /** |
| 128 * @type {boolean} |
| 129 * @private |
| 130 */ |
| 85 this.helloReceived_ = false; | 131 this.helloReceived_ = false; |
| 86 /** @type {function(boolean)|null} */ | 132 /** |
| 133 * @type {function(boolean)|null} |
| 134 * @private |
| 135 */ |
| 87 this.onInitializedCallback_ = null; | 136 this.onInitializedCallback_ = null; |
| 88 /** @type {function(string, string):void} */ | 137 /** |
| 138 * @type {function(string, string):void} |
| 139 * @private |
| 140 */ |
| 89 this.onPairingComplete_ = function(clientId, sharedSecret) {}; | 141 this.onPairingComplete_ = function(clientId, sharedSecret) {}; |
| 90 /** @type {remoting.ClientSession.PerfStats} */ | 142 /** |
| 143 * @type {remoting.ClientSession.PerfStats} |
| 144 * @private |
| 145 */ |
| 91 this.perfStats_ = new remoting.ClientSession.PerfStats(); | 146 this.perfStats_ = new remoting.ClientSession.PerfStats(); |
| 92 | 147 |
| 93 /** @type {remoting.ClientPlugin} */ | 148 /** @type {remoting.ClientPlugin} */ |
| 94 var that = this; | 149 var that = this; |
| 95 /** @param {Event} event Message event from the plugin. */ | 150 /** @param {Event} event Message event from the plugin. */ |
| 96 this.plugin_.addEventListener('message', function(event) { | 151 this.plugin_.addEventListener('message', function(event) { |
| 97 that.handleMessage_(event.data); | 152 that.handleMessage_(event.data); |
| 98 }, false); | 153 }, false); |
| 99 | 154 |
| 100 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'native') { | 155 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'native') { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 * The oldest API version that we support. | 231 * The oldest API version that we support. |
| 177 * This will differ from the |API_VERSION_| if we maintain backward | 232 * This will differ from the |API_VERSION_| if we maintain backward |
| 178 * compatibility with older API versions. | 233 * compatibility with older API versions. |
| 179 * | 234 * |
| 180 * @const | 235 * @const |
| 181 * @private | 236 * @private |
| 182 */ | 237 */ |
| 183 remoting.ClientPlugin.prototype.API_MIN_VERSION_ = 5; | 238 remoting.ClientPlugin.prototype.API_MIN_VERSION_ = 5; |
| 184 | 239 |
| 185 /** | 240 /** |
| 241 * @param {function(string):void} handler |
| 242 */ |
| 243 remoting.ClientPlugin.prototype.setOnOutgoingIqHandler = function(handler) { |
| 244 this.onOutgoingIqHandler_ = handler; |
| 245 }; |
| 246 |
| 247 /** |
| 248 * @param {function(string):void} handler |
| 249 */ |
| 250 remoting.ClientPlugin.prototype.setOnDebugMessageHandler = function(handler) { |
| 251 this.onDebugMessageHandler_ = handler; |
| 252 }; |
| 253 |
| 254 /** |
| 255 * @param {function(number, number):void} handler |
| 256 */ |
| 257 remoting.ClientPlugin.prototype.setConnectionStatusUpdateHandler = |
| 258 function(handler) { |
| 259 this.onConnectionStatusUpdateHandler_ = handler; |
| 260 }; |
| 261 |
| 262 /** |
| 263 * @param {function(boolean):void} handler |
| 264 */ |
| 265 remoting.ClientPlugin.prototype.setConnectionReadyHandler = function(handler) { |
| 266 this.onConnectionReadyHandler_ = handler; |
| 267 }; |
| 268 |
| 269 /** |
| 270 * @param {function():void} handler |
| 271 */ |
| 272 remoting.ClientPlugin.prototype.setDesktopSizeUpdateHandler = |
| 273 function(handler) { |
| 274 this.onDesktopSizeUpdateHandler_ = handler; |
| 275 }; |
| 276 |
| 277 /** |
| 278 * @param {function(!Array.<string>):void} handler |
| 279 */ |
| 280 remoting.ClientPlugin.prototype.setCapabilitiesHandler = function(handler) { |
| 281 this.onSetCapabilitiesHandler_ = handler; |
| 282 }; |
| 283 |
| 284 /** |
| 285 * @param {function(string):void} handler |
| 286 */ |
| 287 remoting.ClientPlugin.prototype.setGnubbyAuthHandler = function(handler) { |
| 288 this.onGnubbyAuthHandler_ = handler; |
| 289 }; |
| 290 |
| 291 /** |
| 292 * @param {function(string):void} handler |
| 293 */ |
| 294 remoting.ClientPlugin.prototype.setCastExtensionHandler = function(handler) { |
| 295 this.onCastExtensionHandler_ = handler; |
| 296 }; |
| 297 |
| 298 /** |
| 299 * @param {function(string, number, number):void} handler |
| 300 */ |
| 301 remoting.ClientPlugin.prototype.setMouseCursorHandler = function(handler) { |
| 302 this.updateMouseCursorImage_ = handler; |
| 303 }; |
| 304 |
| 305 /** |
| 306 * @param {function(string, string, string):void} handler |
| 307 */ |
| 308 remoting.ClientPlugin.prototype.setFetchThirdPartyTokenHandler = |
| 309 function(handler) { |
| 310 this.fetchThirdPartyTokenHandler_ = handler; |
| 311 }; |
| 312 |
| 313 /** |
| 314 * @param {function(boolean):void} handler |
| 315 */ |
| 316 remoting.ClientPlugin.prototype.setFetchPinHandler = function(handler) { |
| 317 this.fetchPinHandler_ = handler; |
| 318 }; |
| 319 |
| 320 /** |
| 186 * @param {string|{method:string, data:Object.<string,*>}} | 321 * @param {string|{method:string, data:Object.<string,*>}} |
| 187 * rawMessage Message from the plugin. | 322 * rawMessage Message from the plugin. |
| 188 * @private | 323 * @private |
| 189 */ | 324 */ |
| 190 remoting.ClientPlugin.prototype.handleMessage_ = function(rawMessage) { | 325 remoting.ClientPlugin.prototype.handleMessage_ = function(rawMessage) { |
| 191 var message = | 326 var message = |
| 192 /** @type {{method:string, data:Object.<string,*>}} */ | 327 /** @type {{method:string, data:Object.<string,*>}} */ |
| 193 ((typeof(rawMessage) == 'string') ? jsonParseSafe(rawMessage) | 328 ((typeof(rawMessage) == 'string') ? jsonParseSafe(rawMessage) |
| 194 : rawMessage); | 329 : rawMessage); |
| 195 if (!message || !('method' in message) || !('data' in message)) { | 330 if (!message || !('method' in message) || !('data' in message)) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 } else { | 413 } else { |
| 279 this.pluginApiFeatures_ = ['highQualityScaling']; | 414 this.pluginApiFeatures_ = ['highQualityScaling']; |
| 280 } | 415 } |
| 281 this.helloReceived_ = true; | 416 this.helloReceived_ = true; |
| 282 if (this.onInitializedCallback_ != null) { | 417 if (this.onInitializedCallback_ != null) { |
| 283 this.onInitializedCallback_(true); | 418 this.onInitializedCallback_(true); |
| 284 this.onInitializedCallback_ = null; | 419 this.onInitializedCallback_ = null; |
| 285 } | 420 } |
| 286 | 421 |
| 287 } else if (message.method == 'sendOutgoingIq') { | 422 } else if (message.method == 'sendOutgoingIq') { |
| 288 this.onOutgoingIqHandler(getStringAttr(message.data, 'iq')); | 423 this.onOutgoingIqHandler_(getStringAttr(message.data, 'iq')); |
| 289 | 424 |
| 290 } else if (message.method == 'logDebugMessage') { | 425 } else if (message.method == 'logDebugMessage') { |
| 291 this.onDebugMessageHandler(getStringAttr(message.data, 'message')); | 426 this.onDebugMessageHandler_(getStringAttr(message.data, 'message')); |
| 292 | 427 |
| 293 } else if (message.method == 'onConnectionStatus') { | 428 } else if (message.method == 'onConnectionStatus') { |
| 294 var state = remoting.ClientSession.State.fromString( | 429 var state = remoting.ClientSession.State.fromString( |
| 295 getStringAttr(message.data, 'state')) | 430 getStringAttr(message.data, 'state')) |
| 296 var error = remoting.ClientSession.ConnectionError.fromString( | 431 var error = remoting.ClientSession.ConnectionError.fromString( |
| 297 getStringAttr(message.data, 'error')); | 432 getStringAttr(message.data, 'error')); |
| 298 this.onConnectionStatusUpdateHandler(state, error); | 433 this.onConnectionStatusUpdateHandler_(state, error); |
| 299 | 434 |
| 300 } else if (message.method == 'onDesktopSize') { | 435 } else if (message.method == 'onDesktopSize') { |
| 301 this.desktopWidth = getNumberAttr(message.data, 'width'); | 436 this.desktopWidth_ = getNumberAttr(message.data, 'width'); |
| 302 this.desktopHeight = getNumberAttr(message.data, 'height'); | 437 this.desktopHeight_ = getNumberAttr(message.data, 'height'); |
| 303 this.desktopXDpi = getNumberAttr(message.data, 'x_dpi', 96); | 438 this.desktopXDpi_ = getNumberAttr(message.data, 'x_dpi', 96); |
| 304 this.desktopYDpi = getNumberAttr(message.data, 'y_dpi', 96); | 439 this.desktopYDpi_ = getNumberAttr(message.data, 'y_dpi', 96); |
| 305 this.onDesktopSizeUpdateHandler(); | 440 this.onDesktopSizeUpdateHandler_(); |
| 306 | 441 |
| 307 } else if (message.method == 'onPerfStats') { | 442 } else if (message.method == 'onPerfStats') { |
| 308 // Return value is ignored. These calls will throw an error if the value | 443 // Return value is ignored. These calls will throw an error if the value |
| 309 // is not a number. | 444 // is not a number. |
| 310 getNumberAttr(message.data, 'videoBandwidth'); | 445 getNumberAttr(message.data, 'videoBandwidth'); |
| 311 getNumberAttr(message.data, 'videoFrameRate'); | 446 getNumberAttr(message.data, 'videoFrameRate'); |
| 312 getNumberAttr(message.data, 'captureLatency'); | 447 getNumberAttr(message.data, 'captureLatency'); |
| 313 getNumberAttr(message.data, 'encodeLatency'); | 448 getNumberAttr(message.data, 'encodeLatency'); |
| 314 getNumberAttr(message.data, 'decodeLatency'); | 449 getNumberAttr(message.data, 'decodeLatency'); |
| 315 getNumberAttr(message.data, 'renderLatency'); | 450 getNumberAttr(message.data, 'renderLatency'); |
| 316 getNumberAttr(message.data, 'roundtripLatency'); | 451 getNumberAttr(message.data, 'roundtripLatency'); |
| 317 this.perfStats_ = | 452 this.perfStats_ = |
| 318 /** @type {remoting.ClientSession.PerfStats} */ message.data; | 453 /** @type {remoting.ClientSession.PerfStats} */ message.data; |
| 319 | 454 |
| 320 } else if (message.method == 'injectClipboardItem') { | 455 } else if (message.method == 'injectClipboardItem') { |
| 321 var mimetype = getStringAttr(message.data, 'mimeType'); | 456 var mimetype = getStringAttr(message.data, 'mimeType'); |
| 322 var item = getStringAttr(message.data, 'item'); | 457 var item = getStringAttr(message.data, 'item'); |
| 323 if (remoting.clipboard) { | 458 if (remoting.clipboard) { |
| 324 remoting.clipboard.fromHost(mimetype, item); | 459 remoting.clipboard.fromHost(mimetype, item); |
| 325 } | 460 } |
| 326 | 461 |
| 327 } else if (message.method == 'onFirstFrameReceived') { | 462 } else if (message.method == 'onFirstFrameReceived') { |
| 328 if (remoting.clientSession) { | 463 if (remoting.clientSession) { |
| 329 remoting.clientSession.onFirstFrameReceived(); | 464 remoting.clientSession.onFirstFrameReceived(); |
| 330 } | 465 } |
| 331 | 466 |
| 332 } else if (message.method == 'onConnectionReady') { | 467 } else if (message.method == 'onConnectionReady') { |
| 333 var ready = getBooleanAttr(message.data, 'ready'); | 468 var ready = getBooleanAttr(message.data, 'ready'); |
| 334 this.onConnectionReadyHandler(ready); | 469 this.onConnectionReadyHandler_(ready); |
| 335 | 470 |
| 336 } else if (message.method == 'fetchPin') { | 471 } else if (message.method == 'fetchPin') { |
| 337 // The pairingSupported value in the dictionary indicates whether both | 472 // The pairingSupported value in the dictionary indicates whether both |
| 338 // client and host support pairing. If the client doesn't support pairing, | 473 // client and host support pairing. If the client doesn't support pairing, |
| 339 // then the value won't be there at all, so give it a default of false. | 474 // then the value won't be there at all, so give it a default of false. |
| 340 var pairingSupported = getBooleanAttr(message.data, 'pairingSupported', | 475 var pairingSupported = getBooleanAttr(message.data, 'pairingSupported', |
| 341 false) | 476 false) |
| 342 this.fetchPinHandler(pairingSupported); | 477 this.fetchPinHandler_(pairingSupported); |
| 343 | 478 |
| 344 } else if (message.method == 'setCapabilities') { | 479 } else if (message.method == 'setCapabilities') { |
| 345 /** @type {!Array.<string>} */ | 480 /** @type {!Array.<string>} */ |
| 346 var capabilities = tokenize(getStringAttr(message.data, 'capabilities')); | 481 var capabilities = tokenize(getStringAttr(message.data, 'capabilities')); |
| 347 this.onSetCapabilitiesHandler(capabilities); | 482 this.onSetCapabilitiesHandler_(capabilities); |
| 348 | 483 |
| 349 } else if (message.method == 'fetchThirdPartyToken') { | 484 } else if (message.method == 'fetchThirdPartyToken') { |
| 350 var tokenUrl = getStringAttr(message.data, 'tokenUrl'); | 485 var tokenUrl = getStringAttr(message.data, 'tokenUrl'); |
| 351 var hostPublicKey = getStringAttr(message.data, 'hostPublicKey'); | 486 var hostPublicKey = getStringAttr(message.data, 'hostPublicKey'); |
| 352 var scope = getStringAttr(message.data, 'scope'); | 487 var scope = getStringAttr(message.data, 'scope'); |
| 353 this.fetchThirdPartyTokenHandler(tokenUrl, hostPublicKey, scope); | 488 this.fetchThirdPartyTokenHandler_(tokenUrl, hostPublicKey, scope); |
| 354 | 489 |
| 355 } else if (message.method == 'pairingResponse') { | 490 } else if (message.method == 'pairingResponse') { |
| 356 var clientId = getStringAttr(message.data, 'clientId'); | 491 var clientId = getStringAttr(message.data, 'clientId'); |
| 357 var sharedSecret = getStringAttr(message.data, 'sharedSecret'); | 492 var sharedSecret = getStringAttr(message.data, 'sharedSecret'); |
| 358 this.onPairingComplete_(clientId, sharedSecret); | 493 this.onPairingComplete_(clientId, sharedSecret); |
| 359 | 494 |
| 360 } else if (message.method == 'extensionMessage') { | 495 } else if (message.method == 'extensionMessage') { |
| 361 var extMsgType = getStringAttr(message.data, 'type'); | 496 var extMsgType = getStringAttr(message.data, 'type'); |
| 362 var extMsgData = getStringAttr(message.data, 'data'); | 497 var extMsgData = getStringAttr(message.data, 'data'); |
| 363 switch (extMsgType) { | 498 switch (extMsgType) { |
| 364 case 'gnubby-auth': | 499 case 'gnubby-auth': |
| 365 this.onGnubbyAuthHandler(extMsgData); | 500 this.onGnubbyAuthHandler_(extMsgData); |
| 366 break; | 501 break; |
| 367 case 'test-echo-reply': | 502 case 'test-echo-reply': |
| 368 console.log('Got echo reply: ' + extMsgData); | 503 console.log('Got echo reply: ' + extMsgData); |
| 369 break; | 504 break; |
| 370 case 'cast_message': | 505 case 'cast_message': |
| 371 this.onCastExtensionHandler(extMsgData); | 506 this.onCastExtensionHandler_(extMsgData); |
| 372 break; | 507 break; |
| 373 default: | 508 default: |
| 374 this.onExtensionMessage_(extMsgType, extMsgData); | 509 this.onExtensionMessage_(extMsgType, extMsgData); |
| 375 break; | 510 break; |
| 376 } | 511 } |
| 377 | 512 |
| 378 } else if (message.method == 'mediaSourceReset') { | 513 } else if (message.method == 'mediaSourceReset') { |
| 379 if (!this.mediaSourceRenderer_) { | 514 if (!this.mediaSourceRenderer_) { |
| 380 console.error('Unexpected mediaSourceReset.'); | 515 console.error('Unexpected mediaSourceReset.'); |
| 381 return; | 516 return; |
| 382 } | 517 } |
| 383 this.mediaSourceRenderer_.reset(getStringAttr(message.data, 'format')) | 518 this.mediaSourceRenderer_.reset(getStringAttr(message.data, 'format')) |
| 384 | 519 |
| 385 } else if (message.method == 'mediaSourceData') { | 520 } else if (message.method == 'mediaSourceData') { |
| 386 if (!(message.data['buffer'] instanceof ArrayBuffer)) { | 521 if (!(message.data['buffer'] instanceof ArrayBuffer)) { |
| 387 console.error('Invalid mediaSourceData message:', message.data); | 522 console.error('Invalid mediaSourceData message:', message.data); |
| 388 return; | 523 return; |
| 389 } | 524 } |
| 390 if (!this.mediaSourceRenderer_) { | 525 if (!this.mediaSourceRenderer_) { |
| 391 console.error('Unexpected mediaSourceData.'); | 526 console.error('Unexpected mediaSourceData.'); |
| 392 return; | 527 return; |
| 393 } | 528 } |
| 394 // keyframe flag may be absent from the message. | 529 // keyframe flag may be absent from the message. |
| 395 var keyframe = !!message.data['keyframe']; | 530 var keyframe = !!message.data['keyframe']; |
| 396 this.mediaSourceRenderer_.onIncomingData( | 531 this.mediaSourceRenderer_.onIncomingData( |
| 397 (/** @type {ArrayBuffer} */ message.data['buffer']), keyframe); | 532 (/** @type {ArrayBuffer} */ message.data['buffer']), keyframe); |
| 398 | 533 |
| 399 } else if (message.method == 'unsetCursorShape') { | 534 } else if (message.method == 'unsetCursorShape') { |
| 400 this.updateMouseCursorImage('', 0, 0); | 535 this.updateMouseCursorImage_('', 0, 0); |
| 401 | 536 |
| 402 } else if (message.method == 'setCursorShape') { | 537 } else if (message.method == 'setCursorShape') { |
| 403 var width = getNumberAttr(message.data, 'width'); | 538 var width = getNumberAttr(message.data, 'width'); |
| 404 var height = getNumberAttr(message.data, 'height'); | 539 var height = getNumberAttr(message.data, 'height'); |
| 405 var hotspotX = getNumberAttr(message.data, 'hotspotX'); | 540 var hotspotX = getNumberAttr(message.data, 'hotspotX'); |
| 406 var hotspotY = getNumberAttr(message.data, 'hotspotY'); | 541 var hotspotY = getNumberAttr(message.data, 'hotspotY'); |
| 407 var srcArrayBuffer = getObjectAttr(message.data, 'data'); | 542 var srcArrayBuffer = getObjectAttr(message.data, 'data'); |
| 408 | 543 |
| 409 var canvas = | 544 var canvas = |
| 410 /** @type {HTMLCanvasElement} */ (document.createElement('canvas')); | 545 /** @type {HTMLCanvasElement} */ (document.createElement('canvas')); |
| 411 canvas.width = width; | 546 canvas.width = width; |
| 412 canvas.height = height; | 547 canvas.height = height; |
| 413 | 548 |
| 414 var context = | 549 var context = |
| 415 /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); | 550 /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); |
| 416 var imageData = context.getImageData(0, 0, width, height); | 551 var imageData = context.getImageData(0, 0, width, height); |
| 417 base.debug.assert(srcArrayBuffer instanceof ArrayBuffer); | 552 base.debug.assert(srcArrayBuffer instanceof ArrayBuffer); |
| 418 var src = new Uint8Array(/** @type {ArrayBuffer} */(srcArrayBuffer)); | 553 var src = new Uint8Array(/** @type {ArrayBuffer} */(srcArrayBuffer)); |
| 419 var dest = imageData.data; | 554 var dest = imageData.data; |
| 420 for (var i = 0; i < /** @type {number} */(dest.length); i += 4) { | 555 for (var i = 0; i < /** @type {number} */(dest.length); i += 4) { |
| 421 dest[i] = src[i + 2]; | 556 dest[i] = src[i + 2]; |
| 422 dest[i + 1] = src[i + 1]; | 557 dest[i + 1] = src[i + 1]; |
| 423 dest[i + 2] = src[i]; | 558 dest[i + 2] = src[i]; |
| 424 dest[i + 3] = src[i + 3]; | 559 dest[i + 3] = src[i + 3]; |
| 425 } | 560 } |
| 426 | 561 |
| 427 context.putImageData(imageData, 0, 0); | 562 context.putImageData(imageData, 0, 0); |
| 428 this.updateMouseCursorImage(canvas.toDataURL(), hotspotX, hotspotY); | 563 this.updateMouseCursorImage_(canvas.toDataURL(), hotspotX, hotspotY); |
| 429 } | 564 } |
| 430 }; | 565 }; |
| 431 | 566 |
| 432 /** | 567 /** |
| 433 * Deletes the plugin. | 568 * Deletes the plugin. |
| 434 */ | 569 */ |
| 435 remoting.ClientPlugin.prototype.cleanup = function() { | 570 remoting.ClientPlugin.prototype.dispose = function() { |
| 436 if (this.plugin_) { | 571 if (this.plugin_) { |
| 437 this.plugin_.parentNode.removeChild(this.plugin_); | 572 this.plugin_.parentNode.removeChild(this.plugin_); |
| 438 this.plugin_ = null; | 573 this.plugin_ = null; |
| 439 } | 574 } |
| 440 }; | 575 }; |
| 441 | 576 |
| 442 /** | 577 /** |
| 443 * @return {HTMLEmbedElement} HTML element that corresponds to the plugin. | 578 * @return {HTMLEmbedElement} HTML element that corresponds to the plugin. |
| 444 */ | 579 */ |
| 445 remoting.ClientPlugin.prototype.element = function() { | 580 remoting.ClientPlugin.prototype.element = function() { |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 remoting.ClientPlugin.prototype.enableMediaSourceRendering = | 918 remoting.ClientPlugin.prototype.enableMediaSourceRendering = |
| 784 function(mediaSourceRenderer) { | 919 function(mediaSourceRenderer) { |
| 785 if (!this.hasFeature(remoting.ClientPlugin.Feature.MEDIA_SOURCE_RENDERING)) { | 920 if (!this.hasFeature(remoting.ClientPlugin.Feature.MEDIA_SOURCE_RENDERING)) { |
| 786 return; | 921 return; |
| 787 } | 922 } |
| 788 this.mediaSourceRenderer_ = mediaSourceRenderer; | 923 this.mediaSourceRenderer_ = mediaSourceRenderer; |
| 789 this.plugin_.postMessage(JSON.stringify( | 924 this.plugin_.postMessage(JSON.stringify( |
| 790 { method: 'enableMediaSourceRendering', data: {} })); | 925 { method: 'enableMediaSourceRendering', data: {} })); |
| 791 }; | 926 }; |
| 792 | 927 |
| 928 remoting.ClientPlugin.prototype.getDesktopWidth = function() { |
| 929 return this.desktopWidth_; |
| 930 } |
| 931 |
| 932 remoting.ClientPlugin.prototype.getDesktopHeight = function() { |
| 933 return this.desktopHeight_; |
| 934 } |
| 935 |
| 936 remoting.ClientPlugin.prototype.getDesktopXDpi = function() { |
| 937 return this.desktopXDpi_; |
| 938 } |
| 939 |
| 940 remoting.ClientPlugin.prototype.getDesktopYDpi = function() { |
| 941 return this.desktopYDpi_; |
| 942 } |
| 943 |
| 793 /** | 944 /** |
| 794 * If we haven't yet received a "hello" message from the plugin, change its | 945 * If we haven't yet received a "hello" message from the plugin, change its |
| 795 * size so that the user can confirm it if click-to-play is enabled, or can | 946 * size so that the user can confirm it if click-to-play is enabled, or can |
| 796 * see the "this plugin is disabled" message if it is actually disabled. | 947 * see the "this plugin is disabled" message if it is actually disabled. |
| 797 * @private | 948 * @private |
| 798 */ | 949 */ |
| 799 remoting.ClientPlugin.prototype.showPluginForClickToPlay_ = function() { | 950 remoting.ClientPlugin.prototype.showPluginForClickToPlay_ = function() { |
| 800 if (!this.helloReceived_) { | 951 if (!this.helloReceived_) { |
| 801 var width = 200; | 952 var width = 200; |
| 802 var height = 200; | 953 var height = 200; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 815 * Undo the CSS rules needed to make the plugin clickable for click-to-play. | 966 * Undo the CSS rules needed to make the plugin clickable for click-to-play. |
| 816 * @private | 967 * @private |
| 817 */ | 968 */ |
| 818 remoting.ClientPlugin.prototype.hidePluginForClickToPlay_ = function() { | 969 remoting.ClientPlugin.prototype.hidePluginForClickToPlay_ = function() { |
| 819 this.plugin_.style.width = ''; | 970 this.plugin_.style.width = ''; |
| 820 this.plugin_.style.height = ''; | 971 this.plugin_.style.height = ''; |
| 821 this.plugin_.style.top = ''; | 972 this.plugin_.style.top = ''; |
| 822 this.plugin_.style.left = ''; | 973 this.plugin_.style.left = ''; |
| 823 this.plugin_.style.position = ''; | 974 this.plugin_.style.position = ''; |
| 824 }; | 975 }; |
| 976 |
| 977 |
| 978 /** |
| 979 * @constructor |
| 980 * @implements {remoting.ClientPluginFactory} |
| 981 */ |
| 982 remoting.DefaultClientPluginFactory = function() {}; |
| 983 |
| 984 /** |
| 985 * @param {Element} container |
| 986 * @param {function(string, string):boolean} onExtensionMessage |
| 987 * @return {remoting.ClientPluginInterface} |
| 988 */ |
| 989 remoting.DefaultClientPluginFactory.prototype.createPlugin = |
| 990 function(container, onExtensionMessage) { |
| 991 return new remoting.ClientPlugin(container, onExtensionMessage); |
| 992 } |
| 993 |
| 994 /** |
| 995 * @type {remoting.ClientPluginFactory} |
| 996 */ |
| 997 remoting.ClientPlugin.factory = new remoting.DefaultClientPluginFactory(); |
| OLD | NEW |