From dc1fb9deaa6865e558a8fb868147d2b4186e8689 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Sep 2015 17:06:46 -0700 Subject: [PATCH] GUAC-1305: Send supported image formats within Guacamole protocol handshake. --- .../guacamole/net/basic/TunnelRequest.java | 19 ++++++++ .../net/basic/TunnelRequestService.java | 5 +++ .../webapp/app/client/types/ManagedClient.js | 45 ++++++++++++++----- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequest.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequest.java index a18375a71..bb4d4eb8b 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequest.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequest.java @@ -92,6 +92,13 @@ public abstract class TunnelRequest { */ public static final String VIDEO_PARAMETER = "GUAC_VIDEO"; + /** + * The name of the parameter specifying one supported image mimetype. This + * will normally appear multiple times within a single tunnel request - + * once for each mimetype. + */ + public static final String IMAGE_PARAMETER = "GUAC_IMAGE"; + /** * All supported object types that can be used as the destination of a * tunnel. @@ -350,4 +357,16 @@ public abstract class TunnelRequest { return getParameterValues(VIDEO_PARAMETER); } + /** + * Returns a list of all image mimetypes declared as supported within the + * tunnel request. + * + * @return + * A list of all image mimetypes declared as supported within the + * tunnel request, or null if no mimetypes were specified. + */ + public List getImageMimetypes() { + return getParameterValues(IMAGE_PARAMETER); + } + } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java index 5953a31ed..9f8fde40b 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java @@ -114,6 +114,11 @@ public class TunnelRequestService { if (videoMimetypes != null) info.getVideoMimetypes().addAll(videoMimetypes); + // Add image mimetypes + List imageMimetypes = request.getImageMimetypes(); + if (imageMimetypes != null) + info.getImageMimetypes().addAll(imageMimetypes); + return info; } diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClient.js b/guacamole/src/main/webapp/app/client/types/ManagedClient.js index c2a3bf035..a518ca88a 100644 --- a/guacamole/src/main/webapp/app/client/types/ManagedClient.js +++ b/guacamole/src/main/webapp/app/client/types/ManagedClient.js @@ -36,13 +36,15 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', var ManagedFileUpload = $injector.get('ManagedFileUpload'); // Required services - var $window = $injector.get('$window'); var $document = $injector.get('$document'); + var $q = $injector.get('$q'); + var $window = $injector.get('$window'); var authenticationService = $injector.get('authenticationService'); var connectionGroupService = $injector.get('connectionGroupService'); var connectionService = $injector.get('connectionService'); var guacAudio = $injector.get('guacAudio'); var guacHistory = $injector.get('guacHistory'); + var guacImage = $injector.get('guacImage'); var guacVideo = $injector.get('guacVideo'); /** @@ -149,10 +151,11 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', }; /** - * Returns the string of connection parameters to be passed to the - * Guacamole client during connection. This string generally contains the - * desired connection ID, display resolution, and supported audio/video - * codecs. + * Returns a promise which resolves with the string of connection + * parameters to be passed to the Guacamole client during connection. This + * string generally contains the desired connection ID, display resolution, + * and supported audio/video/image formats. The returned promise is + * guaranteed to resolve successfully. * * @param {ClientIdentifier} identifier * The identifier representing the connection or group to connect to. @@ -160,12 +163,14 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', * @param {String} [connectionParameters] * Any additional HTTP parameters to pass while connecting. * - * @returns {String} - * The string of connection parameters to be passed to the Guacamole - * client. + * @returns {Promise.} + * A promise which resolves with the string of connection parameters to + * be passed to the Guacamole client, once the string is ready. */ var getConnectString = function getConnectString(identifier, connectionParameters) { + var deferred = $q.defer(); + // Calculate optimal width/height for display var pixel_density = $window.devicePixelRatio || 1; var optimal_dpi = pixel_density * 96; @@ -183,17 +188,30 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', + "&GUAC_DPI=" + Math.floor(optimal_dpi) + (connectionParameters ? '&' + connectionParameters : ''); - // Add audio mimetypes to connect_string + // Add audio mimetypes to connect string guacAudio.supported.forEach(function(mimetype) { connectString += "&GUAC_AUDIO=" + encodeURIComponent(mimetype); }); - // Add video mimetypes to connect_string + // Add video mimetypes to connect string guacVideo.supported.forEach(function(mimetype) { connectString += "&GUAC_VIDEO=" + encodeURIComponent(mimetype); }); - return connectString; + // Add image mimetypes to connect string + guacImage.getSupportedMimetypes().then(function supportedMimetypesKnown(mimetypes) { + + // Add each image mimetype + angular.forEach(mimetypes, function addImageMimetype(mimetype) { + connectString += "&GUAC_IMAGE=" + encodeURIComponent(mimetype); + }); + + // Connect string is now ready - nothing else is deferred + deferred.resolve(connectString); + + }); + + return deferred.promise; }; @@ -411,7 +429,10 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', var clientIdentifier = ClientIdentifier.fromString(id); // Connect the Guacamole client - client.connect(getConnectString(clientIdentifier, connectionParameters)); + getConnectString(clientIdentifier, connectionParameters) + .then(function connectClient(connectString) { + client.connect(connectString); + }); // If using a connection, pull connection name if (clientIdentifier.type === ClientIdentifier.Types.CONNECTION) {