From ca2b89077cddb34d9b02a532d64a40f404aa1164 Mon Sep 17 00:00:00 2001 From: Virtually Nick Date: Sat, 25 Dec 2021 21:15:59 -0500 Subject: [PATCH 01/11] GUACAMOLE-1293: Add common support for the msg instruction. --- .../src/main/webapp/modules/Client.js | 17 +++++++++++++++++ .../protocol/GuacamoleProtocolCapability.java | 7 +++++++ .../protocol/GuacamoleProtocolVersion.java | 9 ++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/guacamole-common-js/src/main/webapp/modules/Client.js b/guacamole-common-js/src/main/webapp/modules/Client.js index 83d89abaa..d30075d4f 100644 --- a/guacamole-common-js/src/main/webapp/modules/Client.js +++ b/guacamole-common-js/src/main/webapp/modules/Client.js @@ -687,6 +687,17 @@ Guacamole.Client = function(tunnel) { * A status object which describes the error. */ this.onerror = null; + + /** + * Fired when a message is received from the remote tunnel and needs to be + * displayed to the user. + * + * @event + * @param {String} message + * The message sent by the remote end of the tunnel that should be + * displayed for the user. + */ + this.onmsg = null; /** * Fired when a audio stream is created. The stream provided to this event @@ -1399,6 +1410,12 @@ Guacamole.Client = function(tunnel) { } }, + + "msg" : function(parameters) { + + if (guac_client.onmsg) guac_client.onmsg(parameters[0]); + + }, "name": function(parameters) { if (guac_client.onname) guac_client.onname(parameters[0]); diff --git a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolCapability.java b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolCapability.java index 5cad8a280..354bfc85d 100644 --- a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolCapability.java +++ b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolCapability.java @@ -33,6 +33,13 @@ public enum GuacamoleProtocolCapability { */ ARBITRARY_HANDSHAKE_ORDER(GuacamoleProtocolVersion.VERSION_1_1_0), + /** + * Support for the "msg" instruction. The "msg" instruction allows the + * server to send messages to the client. Support for this instruction was + * introduced in {@link GuacamoleProtocolVersion#VERSION_1_5_0}. + */ + MSG_INSTRUCTION(GuacamoleProtocolVersion.VERSION_1_5_0), + /** * Negotiation of Guacamole protocol version between client and server * during the protocol handshake. The ability to negotiate protocol diff --git a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolVersion.java b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolVersion.java index 3ceda3b1a..054334f65 100644 --- a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolVersion.java +++ b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolVersion.java @@ -53,11 +53,18 @@ public class GuacamoleProtocolVersion { */ public static final GuacamoleProtocolVersion VERSION_1_3_0 = new GuacamoleProtocolVersion(1, 3, 0); + /** + * Protocol version 1.5.0, which introduces the "msg" instruction, allowing + * the server to send message notifications that will be displayed on the + * client. + */ + public static final GuacamoleProtocolVersion VERSION_1_5_0 = new GuacamoleProtocolVersion(1, 5, 0); + /** * The most recent version of the Guacamole protocol at the time this * version of GuacamoleProtocolVersion was built. */ - public static final GuacamoleProtocolVersion LATEST = VERSION_1_3_0; + public static final GuacamoleProtocolVersion LATEST = VERSION_1_5_0; /** * A regular expression that matches the VERSION_X_Y_Z pattern, where From 33432c228c3f6ad6dca6c57145fc4a9f6f668a0f Mon Sep 17 00:00:00 2001 From: Virtually Nick Date: Sat, 25 Dec 2021 21:16:37 -0500 Subject: [PATCH 02/11] GUACAMOLE-1293: Add client-side support for join/leave notification. --- .../client/controllers/clientController.js | 18 +++ .../client/directives/guacClientMessage.js | 42 ++++++ .../client/directives/guacMessageDialog.js | 76 +++++++++++ .../src/app/client/styles/client-message.css | 23 ++++ .../src/app/client/styles/message-dialog.css | 122 ++++++++++++++++++ .../src/app/client/templates/client.html | 5 + .../client/templates/guacClientMessage.html | 6 + .../client/templates/guacMessageDialog.html | 21 +++ .../src/app/client/types/ManagedClient.js | 33 +++++ .../main/frontend/src/translations/en.json | 13 +- 10 files changed, 354 insertions(+), 5 deletions(-) create mode 100644 guacamole/src/main/frontend/src/app/client/directives/guacClientMessage.js create mode 100644 guacamole/src/main/frontend/src/app/client/directives/guacMessageDialog.js create mode 100644 guacamole/src/main/frontend/src/app/client/styles/client-message.css create mode 100644 guacamole/src/main/frontend/src/app/client/styles/message-dialog.css create mode 100644 guacamole/src/main/frontend/src/app/client/templates/guacClientMessage.html create mode 100644 guacamole/src/main/frontend/src/app/client/templates/guacMessageDialog.html diff --git a/guacamole/src/main/frontend/src/app/client/controllers/clientController.js b/guacamole/src/main/frontend/src/app/client/controllers/clientController.js index 89654b5d8..3a0df8c11 100644 --- a/guacamole/src/main/frontend/src/app/client/controllers/clientController.js +++ b/guacamole/src/main/frontend/src/app/client/controllers/clientController.js @@ -791,6 +791,24 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams ManagedClient.uploadFile($scope.filesystemMenuContents.client, files[i], $scope.filesystemMenuContents); }; + + /** + * Determines whether the attached client group has any associated client + * messages to display. + * + * @returns {Boolean} + * true if there are messages to display; otherwise false. + */ + $scope.hasMessages = function hasMessages() { + + // No client group means no messages + if (!$scope.clientGroup) + return false; + + // Otherwise, find messages within the clients in the group. + return _.findIndex($scope.clientGroup.clients, ManagedClient.hasMessages) !== -1; + + }; /** * Determines whether the attached client group has any associated file diff --git a/guacamole/src/main/frontend/src/app/client/directives/guacClientMessage.js b/guacamole/src/main/frontend/src/app/client/directives/guacClientMessage.js new file mode 100644 index 000000000..9e63edb18 --- /dev/null +++ b/guacamole/src/main/frontend/src/app/client/directives/guacClientMessage.js @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Directive which displays a message for the client. + */ +angular.module('client').directive('guacClientMessage', [function guacClientMessage() { + + return { + restrict: 'E', + replace: true, + scope: { + + /** + * The message to display. + * + * @type String + */ + message : '=' + + }, + + templateUrl: 'app/client/templates/guacClientMessage.html' + + }; +}]); diff --git a/guacamole/src/main/frontend/src/app/client/directives/guacMessageDialog.js b/guacamole/src/main/frontend/src/app/client/directives/guacMessageDialog.js new file mode 100644 index 000000000..16ca81d4a --- /dev/null +++ b/guacamole/src/main/frontend/src/app/client/directives/guacMessageDialog.js @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Directive which displays all client messages. + */ +angular.module('client').directive('guacMessageDialog', [function guacMessageDialog() { + + return { + restrict: 'E', + replace: true, + scope: { + + /** + * The client group whose messages should be managed by this + * directive. + * + * @type ManagedClientGroup + */ + clientGroup : '=' + + }, + + templateUrl: 'app/client/templates/guacMessageDialog.html', + controller: ['$scope', '$injector', function guacMessageDialogController($scope, $injector) { + + // Required types + const ManagedClient = $injector.get('ManagedClient'); + const ManagedClientGroup = $injector.get('ManagedClientGroup'); + + /** + * Removes all messages. + */ + $scope.clearAllMessages = function clearAllMessages() { + + // Nothing to clear if no client group attached + if (!$scope.clientGroup) + return; + + // Remove each client's messages + $scope.clientGroup.clients.forEach(client => { + client.messages = []; + }); + + }; + + /** + * @borrows ManagedClientGroup.hasMultipleClients + */ + $scope.hasMultipleClients = ManagedClientGroup.hasMultipleClients; + + /** + * @borrows ManagedClient.hasMessages + */ + $scope.hasMessages = ManagedClient.hasMessages; + + }] + + }; +}]); diff --git a/guacamole/src/main/frontend/src/app/client/styles/client-message.css b/guacamole/src/main/frontend/src/app/client/styles/client-message.css new file mode 100644 index 000000000..21b905672 --- /dev/null +++ b/guacamole/src/main/frontend/src/app/client/styles/client-message.css @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +p.client-message-text { + margin: 5px; +} + diff --git a/guacamole/src/main/frontend/src/app/client/styles/message-dialog.css b/guacamole/src/main/frontend/src/app/client/styles/message-dialog.css new file mode 100644 index 000000000..2a90c672d --- /dev/null +++ b/guacamole/src/main/frontend/src/app/client/styles/message-dialog.css @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#message-dialog { + + position: absolute; + right: 0; + bottom: 0; + z-index: 20; + + font-size: 0.8em; + + width: 3in; + max-width: 100%; + max-height: 3in; + + background: white; + opacity: 0.75; + +} + +#message-dialog .message-dialog-box { + + /* IE10 */ + display: -ms-flexbox; + -ms-flex-align: stretch; + -ms-flex-direction: column; + + /* Ancient Mozilla */ + display: -moz-box; + -moz-box-align: stretch; + -moz-box-orient: vertical; + + /* Ancient WebKit */ + display: -webkit-box; + -webkit-box-align: stretch; + -webkit-box-orient: vertical; + + /* Old WebKit */ + display: -webkit-flex; + -webkit-align-items: stretch; + -webkit-flex-direction: column; + + /* W3C */ + display: flex; + align-items: stretch; + flex-direction: column; + + max-width: inherit; + max-height: inherit; + + border: 1px solid rgba(0, 0, 0, 0.5); + box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.25); + +} + +#message-dialog .message-dialog-box .header { + -ms-flex: 0 0 auto; + -moz-box-flex: 0; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + flex: 0 0 auto; + margin-bottom: 5px; +} + +#message-dialog .message-dialog-box .client-message-body { + + -ms-flex: 1 1 auto; + -moz-box-flex: 1; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + + overflow: auto; + +} + +/* + * Shrink maximum height if viewport is too small for default 3in dialog. + */ +@media all and (max-height: 3in) { + + #message-dialog { + max-height: 1.5in; + } + +} + +/* + * If viewport is too small for even the 1.5in dialog, fit all available space. + */ +@media all and (max-height: 1.5in) { + + #message-dialog { + height: 100%; + } + + #message-dialog .message-dialog-box { + position: absolute; + left: 0.5em; + top: 0.5em; + right: 0.5em; + bottom: 0.5em; + } + +} diff --git a/guacamole/src/main/frontend/src/app/client/templates/client.html b/guacamole/src/main/frontend/src/app/client/templates/client.html index d9c6684cb..7cf976c0a 100644 --- a/guacamole/src/main/frontend/src/app/client/templates/client.html +++ b/guacamole/src/main/frontend/src/app/client/templates/client.html @@ -44,6 +44,11 @@
{{'CLIENT.TEXT_CLIENT_STATUS_UNSTABLE' | translate}}
+ + +
+ +