Chromium Code Reviews| 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 handling creation and teardown of a remoting client session. | 7 * Class handling creation and teardown of a remoting client session. |
| 8 * | 8 * |
| 9 * The ClientSession class controls lifetime of the client plugin | 9 * The ClientSession class controls lifetime of the client plugin |
| 10 * object and provides the plugin with the functionality it needs to | 10 * object and provides the plugin with the functionality it needs to |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 /** | 25 /** |
| 26 * Interval that determines how often the web-app should send a new access token | 26 * Interval that determines how often the web-app should send a new access token |
| 27 * to the host. | 27 * to the host. |
| 28 * | 28 * |
| 29 * @const | 29 * @const |
| 30 * @type {number} | 30 * @type {number} |
| 31 */ | 31 */ |
| 32 remoting.ACCESS_TOKEN_RESEND_INTERVAL_MS = 15 * 60 * 1000; | 32 remoting.ACCESS_TOKEN_RESEND_INTERVAL_MS = 15 * 60 * 1000; |
| 33 | 33 |
| 34 /** | 34 /** |
| 35 * @param {remoting.ClientPlugin} plugin | |
| 35 * @param {remoting.Host} host The host to connect to. | 36 * @param {remoting.Host} host The host to connect to. |
| 36 * @param {remoting.SignalStrategy} signalStrategy Signal strategy. | 37 * @param {remoting.SignalStrategy} signalStrategy Signal strategy. |
| 37 * @param {remoting.CredentialsProvider} credentialsProvider | |
| 38 * The credentialsProvider to authenticate the client with the host. | |
| 39 * @param {HTMLElement} container Container element for the client view. | |
| 40 * @param {remoting.DesktopConnectedView.Mode} mode The mode of this connection. | 38 * @param {remoting.DesktopConnectedView.Mode} mode The mode of this connection. |
| 41 * @param {string} defaultRemapKeys The default set of remap keys, to use | |
| 42 * when the client doesn't define any. | |
| 43 * @constructor | 39 * @constructor |
| 44 * @extends {base.EventSourceImpl} | 40 * @extends {base.EventSourceImpl} |
| 45 * @implements {base.Disposable} | 41 * @implements {base.Disposable} |
| 46 */ | 42 */ |
| 47 remoting.ClientSession = function(host, signalStrategy, credentialsProvider, | 43 remoting.ClientSession = function(plugin, host, signalStrategy, mode) { |
|
kelvinp
2015/03/07 00:09:28
Awesome, right now the host is only used in the di
garykac
2015/03/07 01:53:10
Acknowledged.
| |
| 48 container, mode, defaultRemapKeys) { | |
| 49 /** @private */ | 44 /** @private */ |
| 50 this.state_ = remoting.ClientSession.State.CREATED; | 45 this.state_ = remoting.ClientSession.State.CREATED; |
| 51 | 46 |
| 52 /** @private */ | 47 /** @private */ |
| 53 this.error_ = remoting.Error.NONE; | 48 this.error_ = remoting.Error.NONE; |
| 54 | 49 |
| 55 /** @private */ | 50 /** @private */ |
| 56 this.host_ = host; | 51 this.host_ = host; |
| 57 | 52 |
| 58 /** @private */ | 53 /** @private */ |
| 59 this.credentialsProvider_ = credentialsProvider; | 54 this.sessionId_ = ''; |
| 60 | 55 |
| 61 /** @private */ | 56 /** @private */ |
| 62 this.uiHandler_ = new remoting.DesktopConnectedView( | |
| 63 this, container, this.host_, mode, defaultRemapKeys, | |
| 64 this.onPluginInitialized_.bind(this)); | |
| 65 remoting.desktopConnectedView = this.uiHandler_; | |
| 66 | |
| 67 /** @private */ | |
| 68 this.sessionId_ = ''; | |
| 69 /** @type {remoting.ClientPlugin} | |
| 70 * @private */ | |
| 71 this.plugin_ = null; | |
| 72 /** @private */ | |
| 73 this.hasReceivedFrame_ = false; | 57 this.hasReceivedFrame_ = false; |
| 74 this.logToServer = new remoting.LogToServer(signalStrategy, mode); | 58 this.logToServer = new remoting.LogToServer(signalStrategy, mode); |
| 75 | 59 |
| 76 /** @private */ | 60 /** @private */ |
| 77 this.signalStrategy_ = signalStrategy; | 61 this.signalStrategy_ = signalStrategy; |
| 78 base.debug.assert(this.signalStrategy_.getState() == | 62 base.debug.assert(this.signalStrategy_.getState() == |
| 79 remoting.SignalStrategy.State.CONNECTED); | 63 remoting.SignalStrategy.State.CONNECTED); |
| 80 this.signalStrategy_.setIncomingStanzaCallback( | 64 this.signalStrategy_.setIncomingStanzaCallback( |
| 81 this.onIncomingMessage_.bind(this)); | 65 this.onIncomingMessage_.bind(this)); |
| 82 remoting.formatIq.setJids(this.signalStrategy_.getJid(), host.jabberId); | 66 remoting.formatIq.setJids(this.signalStrategy_.getJid(), host.jabberId); |
| 83 | 67 |
| 84 /** | 68 /** |
| 85 * Allow host-offline error reporting to be suppressed in situations where it | 69 * Allow host-offline error reporting to be suppressed in situations where it |
| 86 * would not be useful, for example, when using a cached host JID. | 70 * would not be useful, for example, when using a cached host JID. |
| 87 * | 71 * |
| 88 * @type {boolean} @private | 72 * @type {boolean} @private |
| 89 */ | 73 */ |
| 90 this.logHostOfflineErrors_ = true; | 74 this.logHostOfflineErrors_ = true; |
| 91 | 75 |
| 92 /** @type {remoting.GnubbyAuthHandler} @private */ | 76 /** @type {remoting.GnubbyAuthHandler} @private */ |
| 93 this.gnubbyAuthHandler_ = null; | 77 this.gnubbyAuthHandler_ = null; |
| 94 | 78 |
| 95 /** @type {remoting.CastExtensionHandler} @private */ | 79 /** @type {remoting.CastExtensionHandler} @private */ |
| 96 this.castExtensionHandler_ = null; | 80 this.castExtensionHandler_ = null; |
| 97 | 81 |
| 82 /** @private {remoting.ClientPlugin} */ | |
| 83 this.plugin_ = plugin; | |
| 84 plugin.setOnOutgoingIqHandler(this.sendIq_.bind(this)); | |
| 85 plugin.setOnDebugMessageHandler(this.onDebugMessage_.bind(this)); | |
| 86 plugin.setConnectionStatusUpdateHandler( | |
| 87 this.onConnectionStatusUpdate_.bind(this)); | |
| 88 plugin.setRouteChangedHandler(this.onRouteChanged_.bind(this)); | |
| 89 plugin.setConnectionReadyHandler(this.onConnectionReady_.bind(this)); | |
| 90 plugin.setCapabilitiesHandler(this.onSetCapabilities_.bind(this)); | |
| 91 plugin.setGnubbyAuthHandler( | |
| 92 this.processGnubbyAuthMessage_.bind(this)); | |
| 93 plugin.setCastExtensionHandler( | |
| 94 this.processCastExtensionMessage_.bind(this)); | |
| 95 | |
| 98 this.defineEvents(Object.keys(remoting.ClientSession.Events)); | 96 this.defineEvents(Object.keys(remoting.ClientSession.Events)); |
| 99 }; | 97 }; |
| 100 | 98 |
| 101 base.extend(remoting.ClientSession, base.EventSourceImpl); | 99 base.extend(remoting.ClientSession, base.EventSourceImpl); |
| 102 | 100 |
| 103 /** @enum {string} */ | 101 /** @enum {string} */ |
| 104 remoting.ClientSession.Events = { | 102 remoting.ClientSession.Events = { |
| 105 stateChanged: 'stateChanged', | 103 stateChanged: 'stateChanged', |
| 106 videoChannelStateChanged: 'videoChannelStateChanged', | 104 videoChannelStateChanged: 'videoChannelStateChanged', |
| 107 }; | 105 }; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 * the client and host. | 241 * the client and host. |
| 244 */ | 242 */ |
| 245 remoting.ClientSession.prototype.hasCapability = function(capability) { | 243 remoting.ClientSession.prototype.hasCapability = function(capability) { |
| 246 if (this.capabilities_ == null) | 244 if (this.capabilities_ == null) |
| 247 return false; | 245 return false; |
| 248 | 246 |
| 249 return this.capabilities_.indexOf(capability) > -1; | 247 return this.capabilities_.indexOf(capability) > -1; |
| 250 }; | 248 }; |
| 251 | 249 |
| 252 /** | 250 /** |
| 253 * Adds <embed> element to the UI container and readies the session object. | 251 * @return {void} Nothing. |
| 254 * | |
| 255 * @param {function(string, string):boolean} onExtensionMessage The handler for | |
| 256 * protocol extension messages. Returns true if a message is recognized; | |
| 257 * false otherwise. | |
| 258 * @param {Array<string>} requiredCapabilities A list of capabilities | |
| 259 * required by this application. | |
| 260 */ | 252 */ |
| 261 remoting.ClientSession.prototype.createPluginAndConnect = | 253 remoting.ClientSession.prototype.removePlugin = function() { |
| 262 function(onExtensionMessage, requiredCapabilities) { | 254 this.plugin_ = null; |
| 263 this.uiHandler_.createPluginAndConnect(onExtensionMessage, | |
| 264 requiredCapabilities); | |
| 265 }; | 255 }; |
| 266 | 256 |
| 267 /** | 257 /** |
| 268 * @param {remoting.Error} error | |
| 269 * @param {remoting.ClientPlugin} plugin | |
| 270 */ | |
| 271 remoting.ClientSession.prototype.onPluginInitialized_ = function( | |
| 272 error, plugin) { | |
| 273 if (error != remoting.Error.NONE) { | |
| 274 this.resetWithError_(error); | |
| 275 } | |
| 276 | |
| 277 this.plugin_ = plugin; | |
| 278 plugin.setOnOutgoingIqHandler(this.sendIq_.bind(this)); | |
| 279 plugin.setOnDebugMessageHandler(this.onDebugMessage_.bind(this)); | |
| 280 | |
| 281 plugin.setConnectionStatusUpdateHandler( | |
| 282 this.onConnectionStatusUpdate_.bind(this)); | |
| 283 plugin.setRouteChangedHandler(this.onRouteChanged_.bind(this)); | |
| 284 plugin.setConnectionReadyHandler(this.onConnectionReady_.bind(this)); | |
| 285 plugin.setCapabilitiesHandler(this.onSetCapabilities_.bind(this)); | |
| 286 plugin.setGnubbyAuthHandler( | |
| 287 this.processGnubbyAuthMessage_.bind(this)); | |
| 288 plugin.setCastExtensionHandler( | |
| 289 this.processCastExtensionMessage_.bind(this)); | |
| 290 | |
| 291 this.plugin_.connect( | |
| 292 this.host_, this.signalStrategy_.getJid(), this.credentialsProvider_); | |
| 293 }; | |
| 294 | |
| 295 /** | |
| 296 * @param {remoting.Error} error | |
| 297 */ | |
| 298 remoting.ClientSession.prototype.resetWithError_ = function(error) { | |
| 299 this.signalStrategy_.setIncomingStanzaCallback(null); | |
| 300 this.removePlugin(); | |
| 301 this.error_ = error; | |
| 302 this.setState_(remoting.ClientSession.State.FAILED); | |
| 303 }; | |
| 304 | |
| 305 /** | |
| 306 * Deletes the <embed> element from the container, without sending a | |
| 307 * session_terminate request. This is to be called when the session was | |
| 308 * disconnected by the Host. | |
| 309 * | |
| 310 * @return {void} Nothing. | |
| 311 */ | |
| 312 remoting.ClientSession.prototype.removePlugin = function() { | |
| 313 this.uiHandler_.removePlugin(); | |
| 314 this.plugin_ = null; | |
| 315 remoting.desktopConnectedView = null; | |
| 316 }; | |
| 317 | |
| 318 /** | |
| 319 * Disconnect the current session with a particular |error|. The session will | 258 * Disconnect the current session with a particular |error|. The session will |
| 320 * raise a |stateChanged| event in response to it. The caller should then call | 259 * raise a |stateChanged| event in response to it. The caller should then call |
| 321 * dispose() to remove and destroy the <embed> element. | 260 * dispose() to remove and destroy the <embed> element. |
| 322 * | 261 * |
| 323 * @param {remoting.Error} error The reason for the disconnection. Use | 262 * @param {remoting.Error} error The reason for the disconnection. Use |
| 324 * remoting.Error.NONE if there is no error. | 263 * remoting.Error.NONE if there is no error. |
| 325 * @return {void} Nothing. | 264 * @return {void} Nothing. |
| 326 */ | 265 */ |
| 327 remoting.ClientSession.prototype.disconnect = function(error) { | 266 remoting.ClientSession.prototype.disconnect = function(error) { |
| 328 var state = (error == remoting.Error.NONE) ? | 267 var state = (error == remoting.Error.NONE) ? |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 * Callback that the plugin invokes to indicate that the connection | 382 * Callback that the plugin invokes to indicate that the connection |
| 444 * status has changed. | 383 * status has changed. |
| 445 * | 384 * |
| 446 * @param {number} status The plugin's status. | 385 * @param {number} status The plugin's status. |
| 447 * @param {number} error The plugin's error state, if any. | 386 * @param {number} error The plugin's error state, if any. |
| 448 * @private | 387 * @private |
| 449 */ | 388 */ |
| 450 remoting.ClientSession.prototype.onConnectionStatusUpdate_ = | 389 remoting.ClientSession.prototype.onConnectionStatusUpdate_ = |
| 451 function(status, error) { | 390 function(status, error) { |
| 452 if (status == remoting.ClientSession.State.CONNECTED) { | 391 if (status == remoting.ClientSession.State.CONNECTED) { |
| 453 this.uiHandler_.updateClientSessionUi_(this); | 392 remoting.desktopConnectedView.updateClientSessionUi_(this); |
| 454 | 393 |
| 455 } else if (status == remoting.ClientSession.State.FAILED) { | 394 } else if (status == remoting.ClientSession.State.FAILED) { |
| 456 switch (error) { | 395 switch (error) { |
| 457 case remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE: | 396 case remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE: |
| 458 this.error_ = remoting.Error.HOST_IS_OFFLINE; | 397 this.error_ = remoting.Error.HOST_IS_OFFLINE; |
| 459 break; | 398 break; |
| 460 case remoting.ClientSession.ConnectionError.SESSION_REJECTED: | 399 case remoting.ClientSession.ConnectionError.SESSION_REJECTED: |
| 461 this.error_ = remoting.Error.INVALID_ACCESS_CODE; | 400 this.error_ = remoting.Error.INVALID_ACCESS_CODE; |
| 462 break; | 401 break; |
| 463 case remoting.ClientSession.ConnectionError.INCOMPATIBLE_PROTOCOL: | 402 case remoting.ClientSession.ConnectionError.INCOMPATIBLE_PROTOCOL: |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 502 // TODO(jamiewalch): Currently, the logic for determining whether or not the | 441 // TODO(jamiewalch): Currently, the logic for determining whether or not the |
| 503 // connection is available is based solely on whether or not any video frames | 442 // connection is available is based solely on whether or not any video frames |
| 504 // have been received recently. which leads to poor UX on slow connections. | 443 // have been received recently. which leads to poor UX on slow connections. |
| 505 // Re-enable this once crbug.com/435315 has been fixed. | 444 // Re-enable this once crbug.com/435315 has been fixed. |
| 506 var ignoreVideoChannelState = true; | 445 var ignoreVideoChannelState = true; |
| 507 if (ignoreVideoChannelState) { | 446 if (ignoreVideoChannelState) { |
| 508 console.log('Video channel ' + (ready ? '' : 'not ') + 'ready.'); | 447 console.log('Video channel ' + (ready ? '' : 'not ') + 'ready.'); |
| 509 return; | 448 return; |
| 510 } | 449 } |
| 511 | 450 |
| 512 this.uiHandler_.onConnectionReady(ready); | 451 remoting.desktopConnectedView.onConnectionReady(ready); |
| 513 | 452 |
| 514 this.raiseEvent(remoting.ClientSession.Events.videoChannelStateChanged, | 453 this.raiseEvent(remoting.ClientSession.Events.videoChannelStateChanged, |
| 515 ready); | 454 ready); |
| 516 }; | 455 }; |
| 517 | 456 |
| 518 /** | 457 /** |
| 519 * Called when the client-host capabilities negotiation is complete. | 458 * Called when the client-host capabilities negotiation is complete. |
| 520 * TODO(kelvinp): Move this function out of ClientSession. | 459 * TODO(kelvinp): Move this function out of ClientSession. |
| 521 * | 460 * |
| 522 * @param {!Array<string>} capabilities The set of capabilities negotiated | 461 * @param {!Array<string>} capabilities The set of capabilities negotiated |
| 523 * between the client and host. | 462 * between the client and host. |
| 524 * @return {void} Nothing. | 463 * @return {void} Nothing. |
| 525 * @private | 464 * @private |
| 526 */ | 465 */ |
| 527 remoting.ClientSession.prototype.onSetCapabilities_ = function(capabilities) { | 466 remoting.ClientSession.prototype.onSetCapabilities_ = function(capabilities) { |
| 528 if (this.capabilities_ != null) { | 467 if (this.capabilities_ != null) { |
| 529 console.error('onSetCapabilities_() is called more than once'); | 468 console.error('onSetCapabilities_() is called more than once'); |
| 530 return; | 469 return; |
| 531 } | 470 } |
| 532 | 471 |
| 533 this.capabilities_ = capabilities; | 472 this.capabilities_ = capabilities; |
| 534 if (this.hasCapability(remoting.ClientSession.Capability.GOOGLE_DRIVE)) { | 473 if (this.hasCapability(remoting.ClientSession.Capability.GOOGLE_DRIVE)) { |
| 535 this.sendGoogleDriveAccessToken_(); | 474 this.sendGoogleDriveAccessToken_(); |
| 536 } | 475 } |
| 537 if (this.hasCapability( | 476 if (this.hasCapability( |
| 538 remoting.ClientSession.Capability.VIDEO_RECORDER)) { | 477 remoting.ClientSession.Capability.VIDEO_RECORDER)) { |
| 539 this.uiHandler_.initVideoFrameRecorder(); | 478 remoting.desktopConnectedView.initVideoFrameRecorder(); |
| 540 } | 479 } |
| 541 }; | 480 }; |
| 542 | 481 |
| 543 /** | 482 /** |
| 544 * @param {remoting.ClientSession.State} newState The new state for the session. | 483 * @param {remoting.ClientSession.State} newState The new state for the session. |
| 545 * @return {void} Nothing. | 484 * @return {void} Nothing. |
| 546 * @private | 485 * @private |
| 547 */ | 486 */ |
| 548 remoting.ClientSession.prototype.setState_ = function(newState) { | 487 remoting.ClientSession.prototype.setState_ = function(newState) { |
| 549 var oldState = this.state_; | 488 var oldState = this.state_; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 668 console.error('Received unexpected gnubby message'); | 607 console.error('Received unexpected gnubby message'); |
| 669 } | 608 } |
| 670 }; | 609 }; |
| 671 | 610 |
| 672 /** | 611 /** |
| 673 * Create a gnubby auth handler and inform the host that gnubby auth is | 612 * Create a gnubby auth handler and inform the host that gnubby auth is |
| 674 * supported. | 613 * supported. |
| 675 * @private | 614 * @private |
| 676 */ | 615 */ |
| 677 remoting.ClientSession.prototype.createGnubbyAuthHandler_ = function() { | 616 remoting.ClientSession.prototype.createGnubbyAuthHandler_ = function() { |
| 678 if (this.uiHandler_.getMode() == remoting.DesktopConnectedView.Mode.ME2ME) { | 617 if (remoting.desktopConnectedView.getMode() == |
| 618 remoting.DesktopConnectedView.Mode.ME2ME) { | |
| 679 this.gnubbyAuthHandler_ = new remoting.GnubbyAuthHandler(this); | 619 this.gnubbyAuthHandler_ = new remoting.GnubbyAuthHandler(this); |
| 680 // TODO(psj): Move to more generic capabilities mechanism. | 620 // TODO(psj): Move to more generic capabilities mechanism. |
| 681 this.sendGnubbyAuthMessage({'type': 'control', 'option': 'auth-v1'}); | 621 this.sendGnubbyAuthMessage({'type': 'control', 'option': 'auth-v1'}); |
| 682 } | 622 } |
| 683 }; | 623 }; |
| 684 | 624 |
| 685 /** | 625 /** |
| 686 * Timer callback to send the access token to the host. | 626 * Timer callback to send the access token to the host. |
| 687 * @private | 627 * @private |
| 688 */ | 628 */ |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 735 } | 675 } |
| 736 }; | 676 }; |
| 737 | 677 |
| 738 /** | 678 /** |
| 739 * Create a CastExtensionHandler and inform the host that cast extension | 679 * Create a CastExtensionHandler and inform the host that cast extension |
| 740 * is supported. | 680 * is supported. |
| 741 * @private | 681 * @private |
| 742 */ | 682 */ |
| 743 remoting.ClientSession.prototype.createCastExtensionHandler_ = function() { | 683 remoting.ClientSession.prototype.createCastExtensionHandler_ = function() { |
| 744 if (remoting.app.hasCapability(remoting.ClientSession.Capability.CAST) && | 684 if (remoting.app.hasCapability(remoting.ClientSession.Capability.CAST) && |
| 745 this.uiHandler_.getMode() == remoting.DesktopConnectedView.Mode.ME2ME) { | 685 remoting.desktopConnectedView.getMode() == |
| 686 remoting.DesktopConnectedView.Mode.ME2ME) { | |
| 746 this.castExtensionHandler_ = new remoting.CastExtensionHandler(this); | 687 this.castExtensionHandler_ = new remoting.CastExtensionHandler(this); |
| 747 } | 688 } |
| 748 }; | 689 }; |
| 749 | 690 |
| 750 /** | 691 /** |
| 751 * Handles protocol extension messages. | 692 * Handles protocol extension messages. |
| 752 * @param {string} type Type of extension message. | 693 * @param {string} type Type of extension message. |
| 753 * @param {Object} message The parsed extension message data. | 694 * @param {Object} message The parsed extension message data. |
| 754 * @return {boolean} True if the message was recognized, false otherwise. | 695 * @return {boolean} True if the message was recognized, false otherwise. |
| 755 */ | 696 */ |
| 756 remoting.ClientSession.prototype.handleExtensionMessage = | 697 remoting.ClientSession.prototype.handleExtensionMessage = |
| 757 function(type, message) { | 698 function(type, message) { |
| 758 if (this.uiHandler_.handleExtensionMessage(type, message)) { | 699 if (remoting.desktopConnectedView.handleExtensionMessage(type, message)) { |
| 759 return true; | 700 return true; |
| 760 } | 701 } |
| 761 return false; | 702 return false; |
| 762 }; | 703 }; |
| 763 | 704 |
| 764 /** | 705 /** |
| 765 * Enables or disables rendering of dirty regions for debugging. | 706 * Enables or disables rendering of dirty regions for debugging. |
| 766 * @param {boolean} enable True to enable rendering. | 707 * @param {boolean} enable True to enable rendering. |
| 767 */ | 708 */ |
| 768 remoting.ClientSession.prototype.enableDebugRegion = function(enable) { | 709 remoting.ClientSession.prototype.enableDebugRegion = function(enable) { |
| 769 if (enable) { | 710 if (enable) { |
| 770 this.plugin_.setDebugDirtyRegionHandler( | 711 this.plugin_.setDebugDirtyRegionHandler( |
| 771 this.uiHandler_.handleDebugRegion.bind(this.uiHandler_)); | 712 remoting.desktopConnectedView.handleDebugRegion.bind( |
| 713 remoting.desktopConnectedView)); | |
| 772 } else { | 714 } else { |
| 773 this.plugin_.setDebugDirtyRegionHandler(null); | 715 this.plugin_.setDebugDirtyRegionHandler(null); |
| 774 } | 716 } |
| 775 } | 717 } |
| OLD | NEW |