summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Borges <felipeborges@gnome.org>2022-01-10 13:46:44 +0100
committerFelipe Borges <felipeborges@gnome.org>2022-01-14 11:47:40 +0100
commitc993f7b72ffd646fa59c0fa6bc944ebe65e80325 (patch)
tree8e301d7ad9fc4340eaae129ad2fbd85ef0a6a5b8
parent3622e967e3c2dc3f3991f0ea1fda46500e393504 (diff)
downloadgnome-control-center-wip/feborges/introduce-rdp-remote-desktop-panel.tar.gz
remote-desktop: Introduce new panel for configuring the RDP serverwip/feborges/introduce-rdp-remote-desktop-panel
Fixes #1413
-rw-r--r--panels/meson.build1
-rw-r--r--panels/remote-desktop/cc-remote-desktop-panel.c327
-rw-r--r--panels/remote-desktop/cc-remote-desktop-panel.h30
-rw-r--r--panels/remote-desktop/cc-remote-desktop-panel.ui96
-rw-r--r--panels/remote-desktop/gnome-remote-desktop-panel.desktop.in.in19
-rw-r--r--panels/remote-desktop/meson.build45
-rw-r--r--panels/remote-desktop/remote-desktop.gresource.xml6
-rw-r--r--shell/cc-panel-list.c1
-rw-r--r--shell/cc-panel-loader.c2
9 files changed, 527 insertions, 0 deletions
diff --git a/panels/meson.build b/panels/meson.build
index d379a9fb1..be84fa8a8 100644
--- a/panels/meson.build
+++ b/panels/meson.build
@@ -21,6 +21,7 @@ panels = [
'power',
'printers',
'region',
+ 'remote-desktop',
'removable-media',
'search',
'sharing',
diff --git a/panels/remote-desktop/cc-remote-desktop-panel.c b/panels/remote-desktop/cc-remote-desktop-panel.c
new file mode 100644
index 000000000..40267a665
--- /dev/null
+++ b/panels/remote-desktop/cc-remote-desktop-panel.c
@@ -0,0 +1,327 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2022 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges@redhat.com>
+ */
+
+#include "cc-remote-desktop-panel.h"
+#include "cc-remote-desktop-resources.h"
+#include "cc-util.h"
+
+#include <glib/gi18n.h>
+#include <libsecret/secret.h>
+
+struct _CcRemoteDesktopPanel
+{
+ CcPanel parent_instance;
+
+ GSettings *remote_desktop_settings;
+ GCancellable *cancellable;
+ guint remote_desktop_name_watch;
+
+ GtkStack *stack;
+ GtkWidget *remote_desktop_page;
+ GtkSwitch *view_only_switch;
+ GtkEntry *username_entry;
+ GtkPasswordEntry *password_entry;
+ GtkButton *tls_key_button;
+ GtkButton *tls_cert_button;
+};
+
+CC_PANEL_REGISTER (CcRemoteDesktopPanel, cc_remote_desktop_panel)
+
+#define GRD_RDP_SCHEMA_ID "org.gnome.desktop.remote-desktop"
+#define GRD_RDP_CREDENTIALS_SCHEMA grd_rdp_credentials_get_schema ()
+
+static const SecretSchema *
+grd_rdp_credentials_get_schema (void)
+{
+ static const SecretSchema grd_rdp_credentials_schema =
+ {
+ .name = "org.gnome.RemoteDesktop.RdpCredentials",
+ .flags = SECRET_SCHEMA_NONE,
+ .attributes =
+ {
+ { "credentials", SECRET_SCHEMA_ATTRIBUTE_STRING },
+ { "NULL", 0 },
+ },
+ };
+
+ return &grd_rdp_credentials_schema;
+}
+
+static void
+store_rdp_credentials (const char *username,
+ const char *password)
+{
+ GVariantBuilder builder;
+ char *credentials;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}", "username", g_variant_new_string (username));
+ g_variant_builder_add (&builder, "{sv}", "password", g_variant_new_string (password));
+ credentials = g_variant_print (g_variant_builder_end (&builder), TRUE);
+
+ secret_password_store_sync (GRD_RDP_CREDENTIALS_SCHEMA,
+ SECRET_COLLECTION_DEFAULT,
+ "GNOME Remote Desktop RDP credentials",
+ credentials,
+ NULL, NULL,
+ NULL);
+
+ g_free (credentials);
+}
+
+static void
+load_rdp_credentials (CcRemoteDesktopPanel *self)
+{
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *secret;
+ GVariant *variant = NULL;
+ const gchar *username = NULL;
+ const gchar *password = NULL;
+
+ secret = secret_password_lookup_sync (GRD_RDP_CREDENTIALS_SCHEMA,
+ self->cancellable,
+ &error,
+ NULL);
+ if (error) {
+ g_warning ("Failed to get password: %s", error->message);
+ return;
+ }
+
+ variant = g_variant_parse (NULL, secret, NULL, NULL, &error);
+ if (variant == NULL)
+ g_warning ("Invalid credentials format in the keyring: %s", error->message);
+
+ g_variant_lookup (variant, "username", "&s", &username);
+ g_variant_lookup (variant, "password", "&s", &password);
+
+ if (username != NULL)
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), username);
+ if (password != NULL)
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), password);
+}
+
+static void
+on_credential_entries_changed (CcRemoteDesktopPanel *self)
+{
+ const gchar *username = NULL;
+ const gchar *password = NULL;
+
+ username = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+
+ if (username != NULL && password != NULL)
+ store_rdp_credentials (username, password);
+}
+
+static void
+on_tls_key_file_selected (GtkDialog *filechooser,
+ gint response,
+ CcRemoteDesktopPanel *self)
+{
+ g_autoptr(GFile) tls_key_file = NULL;
+ const gchar *path;
+
+ if (response != GTK_RESPONSE_ACCEPT)
+ return;
+
+ tls_key_file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (filechooser));
+ path = g_file_get_path (tls_key_file);
+ g_settings_set_string (self->remote_desktop_settings,
+ "tls-key", path);
+ gtk_button_set_label (self->tls_key_button, path);
+ gtk_window_destroy (GTK_WINDOW (filechooser));
+}
+
+static void
+on_tls_key_button_clicked (GtkWidget *widget,
+ CcRemoteDesktopPanel *self)
+{
+ GtkWindow *toplevel;
+ GtkWidget *filechooser;
+
+ toplevel = (GtkWindow *) gtk_widget_get_native (GTK_WIDGET (self));
+ filechooser = gtk_file_chooser_dialog_new (_("Select a TLS Key file"),
+ toplevel,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_modal (GTK_WINDOW (filechooser), TRUE);
+
+ g_signal_connect_object (filechooser,
+ "response",
+ G_CALLBACK (on_tls_key_file_selected),
+ self,
+ 0);
+ gtk_window_present (GTK_WINDOW (filechooser));
+}
+
+static void
+on_tls_cert_file_selected (GtkDialog *filechooser,
+ gint response,
+ CcRemoteDesktopPanel *self)
+{
+ g_autoptr(GFile) tls_cert_file = NULL;
+ const gchar *path;
+
+ if (response != GTK_RESPONSE_ACCEPT)
+ return;
+
+ tls_cert_file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (filechooser));
+ path = g_file_get_path (tls_cert_file);
+ g_settings_set_string (self->remote_desktop_settings,
+ "tls-cert", path);
+ gtk_button_set_label (self->tls_cert_button, path);
+ gtk_window_destroy (GTK_WINDOW (filechooser));
+}
+
+static void
+on_tls_cert_button_clicked (GtkWidget *widget,
+ CcRemoteDesktopPanel *self)
+{
+ GtkWindow *toplevel;
+ GtkWidget *filechooser;
+
+ toplevel = (GtkWindow *) gtk_widget_get_native (GTK_WIDGET (self));
+ filechooser = gtk_file_chooser_dialog_new (_("Select a TLS Cert"),
+ toplevel,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_modal (GTK_WINDOW (filechooser), TRUE);
+
+ g_signal_connect_object (filechooser,
+ "response",
+ G_CALLBACK (on_tls_cert_file_selected),
+ self,
+ 0);
+ gtk_window_present (GTK_WINDOW (filechooser));
+}
+
+static void
+remote_desktop_name_appeared (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ CcRemoteDesktopPanel *self = CC_REMOTE_DESKTOP_PANEL (user_data);
+
+ g_bus_unwatch_name (self->remote_desktop_name_watch);
+ self->remote_desktop_name_watch = 0;
+
+ gtk_stack_set_visible_child (self->stack, self->remote_desktop_page);
+}
+
+static void
+check_remote_desktop_available (CcRemoteDesktopPanel *self)
+{
+ GSettingsSchemaSource *source;
+ g_autoptr(GSettingsSchema) schema = NULL;
+
+ source = g_settings_schema_source_get_default ();
+ if (!source)
+ return;
+
+ schema = g_settings_schema_source_lookup (source, GRD_RDP_SCHEMA_ID, TRUE);
+ if (!schema)
+ return;
+
+ self->remote_desktop_name_watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ "org.gnome.Mutter.RemoteDesktop",
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ remote_desktop_name_appeared,
+ NULL,
+ self,
+ NULL);
+}
+
+static void
+cc_remote_desktop_panel_finalize (GObject *object)
+{
+ CcRemoteDesktopPanel *self = CC_REMOTE_DESKTOP_PANEL (object);
+
+ if (self->remote_desktop_name_watch)
+ g_bus_unwatch_name (self->remote_desktop_name_watch);
+ self->remote_desktop_name_watch = 0;
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ g_clear_object (&self->remote_desktop_settings);
+
+ G_OBJECT_CLASS (cc_remote_desktop_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_remote_desktop_panel_class_init (CcRemoteDesktopPanelClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ oclass->finalize = cc_remote_desktop_panel_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/remote-desktop/cc-remote-desktop-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcRemoteDesktopPanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, CcRemoteDesktopPanel, remote_desktop_page);
+ gtk_widget_class_bind_template_child (widget_class, CcRemoteDesktopPanel, view_only_switch);
+ gtk_widget_class_bind_template_child (widget_class, CcRemoteDesktopPanel, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcRemoteDesktopPanel, username_entry);
+ gtk_widget_class_bind_template_child (widget_class, CcRemoteDesktopPanel, tls_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, CcRemoteDesktopPanel, tls_key_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_credential_entries_changed);
+ gtk_widget_class_bind_template_callback (widget_class, on_tls_cert_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, on_tls_key_button_clicked);
+}
+
+static void
+cc_remote_desktop_panel_init (CcRemoteDesktopPanel *self)
+{
+ g_resources_register (cc_remote_desktop_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ check_remote_desktop_available (self);
+
+ self->cancellable = g_cancellable_new ();
+
+ self->remote_desktop_settings = g_settings_new ("org.gnome.desktop.remote-desktop.rdp");
+
+ g_settings_bind (self->remote_desktop_settings,
+ "view-only",
+ self->view_only_switch,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->remote_desktop_settings,
+ "tls-cert",
+ self->tls_cert_button,
+ "label",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (self->remote_desktop_settings,
+ "tls-key",
+ self->tls_key_button,
+ "label",
+ G_SETTINGS_BIND_DEFAULT);
+
+ load_rdp_credentials (self);
+}
diff --git a/panels/remote-desktop/cc-remote-desktop-panel.h b/panels/remote-desktop/cc-remote-desktop-panel.h
new file mode 100644
index 000000000..daf39f9a9
--- /dev/null
+++ b/panels/remote-desktop/cc-remote-desktop-panel.h
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2022 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges@redhat.com>
+ */
+
+#pragma once
+
+#include <shell/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_LOCK_PANEL (cc_remote_desktop_panel_get_type ())
+G_DECLARE_FINAL_TYPE (CcRemoteDesktopPanel, cc_remote_desktop_panel, CC, REMOTE_DESKTOP_PANEL, CcPanel)
+
+G_END_DECLS
diff --git a/panels/remote-desktop/cc-remote-desktop-panel.ui b/panels/remote-desktop/cc-remote-desktop-panel.ui
new file mode 100644
index 000000000..b24c6d092
--- /dev/null
+++ b/panels/remote-desktop/cc-remote-desktop-panel.ui
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.1 -->
+<interface>
+ <template class="CcRemoteDesktopPanel" parent="CcPanel">
+ <child>
+ <object class="GtkStack" id="stack">
+ <child>
+ <object class="AdwStatusPage">
+ <property name="icon-name">preferences-desktop-remote-desktop-symbolic</property>
+ <property name="title">Remote desktop server not available</property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesPage" id="remote_desktop_page">
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="description" translatable="yes">Remote desktop makes it possible to view and control your desktop from other computers.</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Remote Control</property>
+ <property name="subtitle" translatable="yes">Allows control of the desktop as well as vieweing.</property>
+ <child>
+ <object class="GtkSwitch" id="view_only_switch">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Access Control</property>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Username</property>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="valign">center</property>
+ <signal name="changed" handler="on_credential_entries_changed" object="CcRemoteDesktopPanel" swapped="yes"/>/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Password</property>
+ <child>
+ <object class="GtkPasswordEntry" id="password_entry">
+ <property name="valign">center</property>
+ <signal name="changed" handler="on_credential_entries_changed" object="CcRemoteDesktopPanel" swapped="yes"/>/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">TLS Cert</property>
+ <child>
+ <object class="GtkButton" id="tls_cert_button">
+ <property name="label" translatable="yes">Select TLS Certificate file...</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="on_tls_cert_button_clicked"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">TLS Key</property>
+ <child>
+ <object class="GtkButton" id="tls_key_button">
+ <property name="label" translatable="yes">Select TLS Key file...</property>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="on_tls_key_button_clicked"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkSizeGroup">
+ <widgets>
+ <widget name="username_entry"/>
+ <widget name="password_entry"/>
+ <widget name="tls_cert_button"/>
+ <widget name="tls_key_button"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/panels/remote-desktop/gnome-remote-desktop-panel.desktop.in.in b/panels/remote-desktop/gnome-remote-desktop-panel.desktop.in.in
new file mode 100644
index 000000000..053c26043
--- /dev/null
+++ b/panels/remote-desktop/gnome-remote-desktop-panel.desktop.in.in
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Name=Remote Desktop
+Comment=Configure your desktop to be controlled by other computers
+Exec=gnome-control-center remote-desktop
+# FIXME
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=preferences-desktop-remote-desktop-symbolic
+Terminal=false
+Type=Application
+NoDisplay=true
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PrivacySettings;
+OnlyShowIn=GNOME;Unity;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=privacy
+X-GNOME-Bugzilla-Version=@VERSION@
+# Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
+Keywords=privacy;remote;rdp;vnc;sharing;
diff --git a/panels/remote-desktop/meson.build b/panels/remote-desktop/meson.build
new file mode 100644
index 000000000..ce84b0e95
--- /dev/null
+++ b/panels/remote-desktop/meson.build
@@ -0,0 +1,45 @@
+panels_list += cappletname
+desktop = 'gnome-@0@-panel.desktop'.format(cappletname)
+
+desktop_in = configure_file(
+ input: desktop + '.in.in',
+ output: desktop + '.in',
+ configuration: desktop_conf
+)
+
+i18n.merge_file(
+ desktop,
+ type: 'desktop',
+ input: desktop_in,
+ output: desktop,
+ po_dir: po_dir,
+ install: true,
+ install_dir: control_center_desktopdir
+)
+
+sources = files('cc-remote-desktop-panel.c')
+
+resource_data = files('cc-remote-desktop-panel.ui')
+
+sources += gnome.compile_resources(
+ 'cc-' + cappletname + '-resources',
+ cappletname + '.gresource.xml',
+ c_name: 'cc_' + cappletname.underscorify (),
+ dependencies: resource_data,
+ export: true
+)
+
+cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)
+
+deps = [
+ dependency('gcr-base-3'),
+ dependency('libsecret-1'),
+]
+
+panels_libs += static_library(
+ cappletname,
+ sources: sources,
+ include_directories: [top_inc, common_inc],
+ dependencies: common_deps + deps,
+ c_args: cflags
+)
diff --git a/panels/remote-desktop/remote-desktop.gresource.xml b/panels/remote-desktop/remote-desktop.gresource.xml
new file mode 100644
index 000000000..aaaf13480
--- /dev/null
+++ b/panels/remote-desktop/remote-desktop.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/remote-desktop">
+ <file preprocess="xml-stripblanks">cc-remote-desktop-panel.ui</file>
+ </gresource>
+</gresources>
diff --git a/shell/cc-panel-list.c b/shell/cc-panel-list.c
index 9ab6b7b80..b12cce131 100644
--- a/shell/cc-panel-list.c
+++ b/shell/cc-panel-list.c
@@ -398,6 +398,7 @@ static const gchar * const panel_order[] = {
"usage",
"lock",
"diagnostics",
+ "remote-desktop",
/* Devices page */
"sound",
diff --git a/shell/cc-panel-loader.c b/shell/cc-panel-loader.c
index 403a44267..b46284efd 100644
--- a/shell/cc-panel-loader.c
+++ b/shell/cc-panel-loader.c
@@ -53,6 +53,7 @@ extern GType cc_notifications_panel_get_type (void);
extern GType cc_power_panel_get_type (void);
extern GType cc_printers_panel_get_type (void);
extern GType cc_region_panel_get_type (void);
+extern GType cc_remote_desktop_panel_get_type (void);
extern GType cc_removable_media_panel_get_type (void);
extern GType cc_search_panel_get_type (void);
extern GType cc_sharing_panel_get_type (void);
@@ -124,6 +125,7 @@ static CcPanelLoaderVtable default_panels[] =
PANEL_TYPE("power", cc_power_panel_get_type, NULL),
PANEL_TYPE("printers", cc_printers_panel_get_type, NULL),
PANEL_TYPE("region", cc_region_panel_get_type, NULL),
+ PANEL_TYPE("remote-desktop", cc_remote_desktop_panel_get_type, NULL),
PANEL_TYPE("removable-media", cc_removable_media_panel_get_type, NULL),
PANEL_TYPE("search", cc_search_panel_get_type, NULL),
PANEL_TYPE("sharing", cc_sharing_panel_get_type, NULL),