From 4e6748707714f52457640a216e860ff87e373d47 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 16 Nov 2014 15:41:06 -0800 Subject: [PATCH] GUAC-605: Fix usage of scope within client and tunnel. --- .../app/client/directives/guacClient.js | 2 +- .../app/client/services/guacClientFactory.js | 149 +++++++++--------- .../app/client/services/guacTunnelFactory.js | 46 +++--- 3 files changed, 102 insertions(+), 95 deletions(-) diff --git a/guacamole/src/main/webapp/app/client/directives/guacClient.js b/guacamole/src/main/webapp/app/client/directives/guacClient.js index 5ca0850d9..169001720 100644 --- a/guacamole/src/main/webapp/app/client/directives/guacClient.js +++ b/guacamole/src/main/webapp/app/client/directives/guacClient.js @@ -312,7 +312,7 @@ angular.module('client').directive('guacClient', [function guacClient() { // Get new client instance var tunnel = guacTunnelFactory.getInstance($scope); - client = guacClientFactory.getInstance(tunnel, $scope); + client = guacClientFactory.getInstance($scope, tunnel); // Init display display = client.getDisplay(); diff --git a/guacamole/src/main/webapp/app/client/services/guacClientFactory.js b/guacamole/src/main/webapp/app/client/services/guacClientFactory.js index 4eb9f5cdc..835eb43e2 100644 --- a/guacamole/src/main/webapp/app/client/services/guacClientFactory.js +++ b/guacamole/src/main/webapp/app/client/services/guacClientFactory.js @@ -32,15 +32,11 @@ angular.module('client').factory('guacClientFactory', ['$rootScope', * Returns a new Guacamole client instance which connects using the * provided tunnel. * + * @param {Scope} $scope The current scope. * @param {Guacamole.Tunnel} tunnel The tunnel to connect through. - * @param {Scope} [$scope] The current scope. If ommitted, the root scope - * will be used. * @returns {Guacamole.Client} A new Guacamole client instance. */ - service.getInstance = function getClientInstance(tunnel, $scope) { - - // Use root scope if no other scope provided - $scope = $scope || $rootScope; + service.getInstance = function getClientInstance($scope, tunnel) { // Instantiate client var guacClient = new Guacamole.Client(tunnel); @@ -49,47 +45,52 @@ angular.module('client').factory('guacClientFactory', ['$rootScope', * Fire guacClientStateChange events when client state changes. */ guacClient.onstatechange = function onClientStateChange(clientState) { + $scope.safeApply(function() { - switch (clientState) { + switch (clientState) { - // Idle - case 0: - $rootScope.$broadcast('guacClientStateChange', guacClient, "idle"); - break; + // Idle + case 0: + $scope.$emit('guacClientStateChange', guacClient, "idle"); + break; - // Connecting - case 1: - $rootScope.$broadcast('guacClientStateChange', guacClient, "connecting"); - break; + // Connecting + case 1: + $scope.$emit('guacClientStateChange', guacClient, "connecting"); + break; - // Connected + waiting - case 2: - $rootScope.$broadcast('guacClientStateChange', guacClient, "waiting"); - break; + // Connected + waiting + case 2: + $scope.$emit('guacClientStateChange', guacClient, "waiting"); + break; - // Connected - case 3: - $rootScope.$broadcast('guacClientStateChange', guacClient, "connected"); + // Connected + case 3: + $scope.$emit('guacClientStateChange', guacClient, "connected"); - // Update server clipboard with current data - if ($rootScope.clipboard) - guacClient.setClipboard($rootScope.clipboard); + // Update server clipboard with current data + if ($scope.clipboard) + guacClient.setClipboard($scope.clipboard); - break; + break; - // Disconnecting / disconnected are handled by tunnel instead - case 4: - case 5: - break; + // Disconnecting / disconnected are handled by tunnel instead + case 4: + case 5: + break; - } + } + + }); }; /* * Fire guacClientName events when a new name is received. */ guacClient.onname = function onClientName(name) { - $rootScope.$broadcast('guacClientName', guacClient, name); + $scope.safeApply(function() { + $scope.$emit('guacClientName', guacClient, name); + }); }; /* @@ -97,39 +98,43 @@ angular.module('client').factory('guacClientFactory', ['$rootScope', * error. */ guacClient.onerror = function onClientError(status) { + $scope.safeApply(function() { - // Disconnect, if connected - guacClient.disconnect(); - - $rootScope.$broadcast('guacClientError', guacClient, status.code); + // Disconnect, if connected + guacClient.disconnect(); + + $scope.$emit('guacClientError', guacClient, status.code); + }); }; /* * Fire guacClientClipboard events after new clipboard data is received. */ guacClient.onclipboard = function onClientClipboard(stream, mimetype) { + $scope.safeApply(function() { - // Only text/plain is supported for now - if (mimetype !== "text/plain") { - stream.sendAck("Only text/plain supported", Guacamole.Status.Code.UNSUPPORTED); - return; - } + // Only text/plain is supported for now + if (mimetype !== "text/plain") { + stream.sendAck("Only text/plain supported", Guacamole.Status.Code.UNSUPPORTED); + return; + } - var reader = new Guacamole.StringReader(stream); - var data = ""; + var reader = new Guacamole.StringReader(stream); + var data = ""; - // Append any received data to buffer - reader.ontext = function clipboard_text_received(text) { - data += text; - stream.sendAck("Received", Guacamole.Status.Code.SUCCESS); - }; + // Append any received data to buffer + reader.ontext = function clipboard_text_received(text) { + data += text; + stream.sendAck("Received", Guacamole.Status.Code.SUCCESS); + }; - // Emit event when done - reader.onend = function clipboard_text_end() { - $rootScope.$broadcast('guacClientClipboard', guacClient, data); - }; + // Emit event when done + reader.onend = function clipboard_text_end() { + $scope.$emit('guacClientClipboard', guacClient, data); + }; + }); }; /* @@ -137,32 +142,34 @@ angular.module('client').factory('guacClientFactory', ['$rootScope', * the receipt of files. */ guacClient.onfile = function onClientFile(stream, mimetype, filename) { + $scope.safeApply(function() { - // Begin file download - var guacFileStartEvent = $rootScope.$broadcast('guacFileStart', guacClient, stream.index, mimetype, filename); - if (!guacFileStartEvent.defaultPrevented) { + // Begin file download + var guacFileStartEvent = $scope.$emit('guacFileStart', guacClient, stream.index, mimetype, filename); + if (!guacFileStartEvent.defaultPrevented) { - var blob_reader = new Guacamole.BlobReader(stream, mimetype); + var blob_reader = new Guacamole.BlobReader(stream, mimetype); - // Update progress as data is received - blob_reader.onprogress = function onprogress() { - $rootScope.$broadcast('guacFileProgress', guacClient, stream.index, mimetype, filename); - stream.sendAck("Received", Guacamole.Status.Code.SUCCESS); - }; + // Update progress as data is received + blob_reader.onprogress = function onprogress() { + $scope.$emit('guacFileProgress', guacClient, stream.index, mimetype, filename); + stream.sendAck("Received", Guacamole.Status.Code.SUCCESS); + }; - // When complete, prompt for download - blob_reader.onend = function onend() { - $rootScope.$broadcast('guacFileEnd', guacClient, stream.index, mimetype, filename); - }; + // When complete, prompt for download + blob_reader.onend = function onend() { + $scope.$emit('guacFileEnd', guacClient, stream.index, mimetype, filename); + }; - stream.sendAck("Ready", Guacamole.Status.Code.SUCCESS); + stream.sendAck("Ready", Guacamole.Status.Code.SUCCESS); + + } - } - - // Respond with UNSUPPORTED if download (default action) canceled within event handler - else - stream.sendAck("Download canceled", Guacamole.Status.Code.UNSUPPORTED); + // Respond with UNSUPPORTED if download (default action) canceled within event handler + else + stream.sendAck("Download canceled", Guacamole.Status.Code.UNSUPPORTED); + }); }; return guacClient; diff --git a/guacamole/src/main/webapp/app/client/services/guacTunnelFactory.js b/guacamole/src/main/webapp/app/client/services/guacTunnelFactory.js index 1ed476f3e..52e259be3 100644 --- a/guacamole/src/main/webapp/app/client/services/guacTunnelFactory.js +++ b/guacamole/src/main/webapp/app/client/services/guacTunnelFactory.js @@ -32,15 +32,11 @@ angular.module('client').factory('guacTunnelFactory', ['$rootScope', '$window', * Returns a new Guacamole tunnel instance, using an implementation that is * supported by the web browser. * - * @param {Scope} [$scope] The current scope. If ommitted, the root scope - * will be used. + * @param {Scope} $scope The current scope. * @returns {Guacamole.Tunnel} A new Guacamole tunnel instance. */ service.getInstance = function getTunnelInstance($scope) { - // Use root scope if no other scope provided - $scope = $scope || $rootScope; - var tunnel; // If WebSocket available, try to use it. @@ -56,32 +52,36 @@ angular.module('client').factory('guacTunnelFactory', ['$rootScope', '$window', // Fire events for tunnel errors tunnel.onerror = function onTunnelError(status) { - $rootScope.$broadcast('guacTunnelError', tunnel, status.code); + $scope.safeApply(function() { + $scope.$emit('guacTunnelError', tunnel, status.code); + }); }; // Fire events for tunnel state changes tunnel.onstatechange = function onTunnelStateChange(state) { + $scope.safeApply(function() { + + switch (state) { + + case Guacamole.Tunnel.State.CONNECTING: + $scope.$emit('guacTunnelStateChange', tunnel, 'connecting'); + break; + + case Guacamole.Tunnel.State.OPEN: + $scope.$emit('guacTunnelStateChange', tunnel, 'open'); + break; + + case Guacamole.Tunnel.State.CLOSED: + $scope.$emit('guacTunnelStateChange', tunnel, 'closed'); + break; + + } - switch (state) { - - case Guacamole.Tunnel.State.CONNECTING: - $rootScope.$broadcast('guacTunnelStateChange', tunnel, 'connecting'); - break; - - case Guacamole.Tunnel.State.OPEN: - $rootScope.$broadcast('guacTunnelStateChange', tunnel, 'open'); - break; - - case Guacamole.Tunnel.State.CLOSED: - $rootScope.$broadcast('guacTunnelStateChange', tunnel, 'closed'); - break; - - } - + }); }; return tunnel; - + }; return service;