GCC Code Coverage Report


Directory: ./
File: panels/system/remote-desktop/cc-remote-login-page.c
Date: 2024-05-03 09:46:52
Exec Total Coverage
Lines: 0 325 0.0%
Functions: 0 35 0.0%
Branches: 0 149 0.0%

Line Branch Exec Source
1 /*
2 * Copyright 2024 Red Hat Inc
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * SPDX-License-Identifier: GPL-3.0-or-later
18 */
19
20 #undef G_LOG_DOMAIN
21 #define G_LOG_DOMAIN "cc-remote-login-page"
22
23 #include <glib/gi18n.h>
24 #include <glib/gstdio.h>
25 #include <polkit/polkit.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28
29 #include "cc-remote-login-page.h"
30 #include "cc-encryption-fingerprint-dialog.h"
31 #include "cc-hostname.h"
32 #include "cc-password-utils.h"
33 #include "cc-permission-infobar.h"
34 #include "cc-tls-certificate.h"
35 #include "cc-systemd-service.h"
36
37 #include "org.gnome.RemoteDesktop.h"
38
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif
42
43 #define REMOTE_DESKTOP_STORE_CREDENTIALS_TIMEOUT_S 2
44 #define REMOTE_LOGIN_SYSTEMD_SERVICE "gnome-remote-desktop.service"
45 #define REMOTE_LOGIN_DBUS_SERVICE "org.gnome.RemoteDesktop"
46 #define REMOTE_LOGIN_OBJECT_PATH "/org/gnome/RemoteDesktop/Rdp/Server"
47 #define REMOTE_LOGIN_PERMISSION "org.gnome.controlcenter.remote-session-helper"
48
49 struct _CcRemoteLoginPage {
50 AdwBin parent_instance;
51
52 GsdRemoteDesktopRdpServer *rdp_server;
53
54 AdwSwitchRow *remote_login_row;
55 GtkWidget *toast_overlay;
56 CcPermissionInfobar *permission_infobar;
57 AdwActionRow *hostname_row;
58 AdwActionRow *port_row;
59 GtkWidget *credentials_group;
60 GtkWidget *username_entry;
61 GtkWidget *password_entry;
62 GtkWidget *generate_password_button;
63 GtkWidget *verify_encryption_button;
64
65 GTlsCertificate *certificate;
66
67 GCancellable *cancellable;
68 GPermission *permission;
69
70 char *temp_cert_dir;
71 const char *fingerprint;
72 guint store_credentials_id;
73
74 gboolean activating;
75 gboolean have_credentials;
76 };
77
78 G_DEFINE_TYPE (CcRemoteLoginPage, cc_remote_login_page, ADW_TYPE_BIN)
79 static void on_remote_login_active_changed (CcRemoteLoginPage *self);
80 static void enable_remote_login_service (CcRemoteLoginPage *self);
81 static void connect_to_remote_desktop_rdp_server (CcRemoteLoginPage *self);
82 static void fetch_credentials (CcRemoteLoginPage *self);
83
84 static void
85 add_toast (CcRemoteLoginPage *self,
86 const char *message)
87 {
88 adw_toast_overlay_add_toast (ADW_TOAST_OVERLAY (self->toast_overlay),
89 adw_toast_new (message));
90 }
91
92 static void
93 on_address_copy_clicked (CcRemoteLoginPage *self,
94 GtkButton *button)
95 {
96 gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (button)),
97 adw_action_row_get_subtitle (self->hostname_row));
98 add_toast (self, _("Device address copied to clipboard"));
99 }
100
101 static void
102 on_port_copy_clicked (CcRemoteLoginPage *self,
103 GtkButton *button)
104 {
105 gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (button)),
106 adw_action_row_get_subtitle (self->port_row));
107 add_toast (self, _("Port number copied to clipboard"));
108 }
109
110 static void
111 on_username_copy_clicked (CcRemoteLoginPage *self,
112 GtkButton *button)
113 {
114 GtkEditable *editable = GTK_EDITABLE (self->username_entry);
115
116 gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (button)),
117 gtk_editable_get_text (editable));
118 add_toast (self, _("Username copied to clipboard"));
119 }
120
121 static void
122 on_password_copy_clicked (CcRemoteLoginPage *self,
123 GtkButton *button)
124 {
125 GtkEditable *editable = GTK_EDITABLE (self->password_entry);
126
127 gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (button)),
128 gtk_editable_get_text (editable));
129 add_toast (self, _("Password copied to clipboard"));
130 }
131
132 static void
133 on_generate_password_button_clicked (CcRemoteLoginPage *self)
134 {
135 g_autofree char *new_password = cc_generate_password ();
136
137 gtk_editable_set_text (GTK_EDITABLE (self->password_entry), new_password);
138 }
139
140 static void
141 on_verify_encryption_button_clicked (CcRemoteLoginPage *self)
142 {
143 CcEncryptionFingerprintDialog *dialog;
144
145 g_return_if_fail (self->fingerprint);
146
147 dialog = g_object_new (CC_TYPE_ENCRYPTION_FINGERPRINT_DIALOG, NULL);
148 cc_encryption_fingerprint_dialog_set_fingerprint (dialog, self->fingerprint, ":");
149 adw_dialog_present (ADW_DIALOG (dialog), GTK_WIDGET (self));
150 }
151
152 static void
153 start_remote_login_row_activation (CcRemoteLoginPage *self)
154 {
155 gtk_widget_set_sensitive (GTK_WIDGET (self->remote_login_row), FALSE);
156 self->activating = TRUE;
157 }
158
159 static void
160 finish_remote_login_row_activation (CcRemoteLoginPage *self)
161 {
162 if (g_permission_get_allowed (self->permission))
163 gtk_widget_set_sensitive (GTK_WIDGET (self->remote_login_row), TRUE);
164 self->activating = FALSE;
165 }
166
167 static void
168 on_remote_login_enabled (GsdRemoteDesktopRdpServer *rdp_server,
169 GAsyncResult *result,
170 gpointer user_data)
171 {
172 CcRemoteLoginPage *self = user_data;
173 g_autoptr(GError) error = NULL;
174 gboolean success;
175
176 success = gsd_remote_desktop_rdp_server_call_enable_finish (rdp_server,
177 result,
178 &error);
179 if (!success)
180 {
181 g_warning ("Failed to enable RDP server: %s", error->message);
182 g_clear_error (&error);
183 }
184
185 finish_remote_login_row_activation (self);
186 }
187
188 static void
189 enable_remote_login_service (CcRemoteLoginPage *self)
190 {
191 g_autofree gchar *cmdline = NULL;
192 g_autoptr(GError) error = NULL;
193 gboolean success;
194
195 success = cc_enable_service (REMOTE_LOGIN_SYSTEMD_SERVICE, G_BUS_TYPE_SYSTEM, &error);
196
197 if (!success)
198 {
199 g_warning ("Failed to enable gnome-remote-desktop systemd service: %s", error->message);
200 g_clear_error (&error);
201 }
202
203 gsd_remote_desktop_rdp_server_call_enable (self->rdp_server,
204 self->cancellable,
205 (GAsyncReadyCallback)
206 on_remote_login_enabled,
207 self);
208 }
209
210 static void
211 on_certificate_imported (GsdRemoteDesktopRdpServer *rdp_server,
212 GAsyncResult *result,
213 gpointer user_data)
214 {
215 CcRemoteLoginPage *self = user_data;
216 g_autoptr(GError) error = NULL;
217 gboolean success;
218 g_autofree char *dir = g_steal_pointer (&self->temp_cert_dir);
219 g_autofree char *certificate_path = g_build_filename (dir, "rdp-tls.crt", NULL);
220 g_autofree char *key_path = g_build_filename (dir, "rdp-tls.key", NULL);
221
222 success = gsd_remote_desktop_rdp_server_call_import_certificate_finish (rdp_server,
223 NULL,
224 result,
225 &error);
226 if (!success)
227 {
228 g_warning ("Failed to import newly generated certificates: %s", error->message);
229 g_clear_error (&error);
230 }
231
232 if (g_remove (certificate_path) != 0)
233 g_warning ("Failed to remove generated certificate %s", certificate_path);
234
235 if (g_remove (key_path) != 0)
236 g_warning ("Failed to remove generated private key %s", key_path);
237
238 if (g_remove (dir) != 0)
239 g_warning ("Failed to remove temporary directory %s", dir);
240
241 enable_remote_login_service (self);
242 }
243
244 static void
245 on_tls_certificate_generated (GObject *source_object,
246 GAsyncResult *res,
247 gpointer user_data)
248 {
249 CcRemoteLoginPage *self = user_data;
250 g_autofree char *certificate_path = g_build_filename (self->temp_cert_dir, "rdp-tls.crt", NULL);
251 g_autofree char *key_path = g_build_filename (self->temp_cert_dir, "rdp-tls.key", NULL);
252 g_autoptr(GTlsCertificate) tls_certificate = NULL;
253 g_autoptr(GError) error = NULL;
254 g_autoptr(GUnixFDList) fd_list = NULL;
255 g_autofd int certificate_fd = -1;
256 g_autofd int key_fd = -1;
257 int certificate_fd_index = -1;
258 int key_fd_index = -1;
259
260 tls_certificate = bonsai_tls_certificate_new_generate_finish (res, &error);
261 if (!tls_certificate)
262 {
263 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
264 g_warning ("Failed to generate TLS certificate: %s", error->message);
265 goto fail;
266 }
267
268 fd_list = g_unix_fd_list_new ();
269
270 certificate_fd = open (certificate_path, O_RDONLY);
271 key_fd = open (key_path, O_RDONLY);
272
273 if (certificate_fd != -1 && key_fd != -1)
274 {
275 certificate_fd_index = g_unix_fd_list_append (fd_list, certificate_fd, &error);
276 if (certificate_fd_index == -1)
277 {
278 g_warning ("Failed to append certificate fd to list: %s", error->message);
279 goto fail;
280 }
281
282 key_fd_index = g_unix_fd_list_append (fd_list, key_fd, &error);
283 if (key_fd_index == -1)
284 {
285 g_warning ("Failed to append key fd to list: %s", error->message);
286 goto fail;
287 }
288
289 gsd_remote_desktop_rdp_server_call_import_certificate (self->rdp_server,
290 g_variant_new ("(sh)", certificate_path, certificate_fd_index),
291 g_variant_new ("(sh)", key_path, key_fd_index),
292 fd_list,
293 self->cancellable,
294 (GAsyncReadyCallback)
295 on_certificate_imported,
296 self);
297 return;
298 }
299
300 fail:
301 finish_remote_login_row_activation (self);
302 }
303
304 static void
305 enable_remote_login (CcRemoteLoginPage *self)
306 {
307 g_autoptr (GKeyFile) conf_file = NULL;
308 const gchar *cert_path = NULL;
309 const gchar *key_path = NULL;
310
311 if (gsd_remote_desktop_rdp_server_get_enabled (self->rdp_server))
312 return;
313
314 start_remote_login_row_activation (self);
315
316 cert_path = gsd_remote_desktop_rdp_server_get_tls_cert (self->rdp_server) ?: "";
317 key_path = gsd_remote_desktop_rdp_server_get_tls_key (self->rdp_server) ?: "";
318
319 if (*cert_path == '\0' || *key_path == '\0')
320 {
321 g_autofree char *temp_dir = g_dir_make_tmp ("gnome-remote-desktop-XXXXXX", NULL);
322 g_autofree char *cert_path_tmp = NULL;
323 g_autofree char *key_path_tmp = NULL;
324
325 if (!temp_dir)
326 {
327 g_warning ("Failed to create temporary directory");
328 finish_remote_login_row_activation (self);
329 return;
330 }
331
332 cert_path_tmp = g_build_filename (temp_dir, "rdp-tls.crt", NULL);
333 key_path_tmp = g_build_filename (temp_dir, "rdp-tls.key", NULL);
334
335 g_set_str (&self->temp_cert_dir, temp_dir);
336
337 bonsai_tls_certificate_new_generate_async (cert_path_tmp,
338 key_path_tmp,
339 "US", "GNOME",
340 self->cancellable,
341 on_tls_certificate_generated,
342 self);
343
344 return;
345 }
346
347 enable_remote_login_service (self);
348 }
349
350 static void
351 on_remote_login_disabled (GsdRemoteDesktopRdpServer *rdp_server,
352 GAsyncResult *result,
353 gpointer user_data)
354 {
355 CcRemoteLoginPage *self = user_data;
356 g_autoptr(GError) error = NULL;
357 gboolean success;
358
359 success = gsd_remote_desktop_rdp_server_call_disable_finish (rdp_server,
360 result,
361 &error);
362 if (!success)
363 {
364 g_warning ("Failed to disable RDP server: %s", error->message);
365 g_clear_error (&error);
366 }
367
368 success = cc_disable_service (REMOTE_LOGIN_SYSTEMD_SERVICE, G_BUS_TYPE_SYSTEM, &error);
369
370 if (!success)
371 {
372 g_warning ("Failed to disable gnome-remote-desktop systemd service: %s", error->message);
373 g_clear_error (&error);
374 }
375
376 connect_to_remote_desktop_rdp_server (self);
377 }
378
379 static void
380 disable_remote_login_service (CcRemoteLoginPage *self)
381 {
382 g_autofree gchar *cmdline = NULL;
383 g_autoptr(GError) error = NULL;
384
385 if (!gsd_remote_desktop_rdp_server_get_enabled (self->rdp_server))
386 return;
387
388 gsd_remote_desktop_rdp_server_call_disable (self->rdp_server,
389 self->cancellable,
390 (GAsyncReadyCallback)
391 on_remote_login_disabled,
392 self);
393
394 }
395
396 static void
397 on_remote_login_active_changed (CcRemoteLoginPage *self)
398 {
399 if (adw_switch_row_get_active (self->remote_login_row))
400 enable_remote_login (self);
401 else
402 disable_remote_login_service (self);
403 }
404
405 static gboolean
406 format_port_for_row (GBinding *binding,
407 const GValue *from_value,
408 GValue *to_value,
409 gpointer user_data)
410 {
411 int port = g_value_get_int (from_value);
412
413 if (port <= 0)
414 g_value_set_string (to_value, " ");
415 else
416 g_value_take_string (to_value, g_strdup_printf ("%u", port));
417
418 return TRUE;
419 }
420
421 static gboolean
422 sensitize_row_from_port (GBinding *binding,
423 const GValue *from_value,
424 GValue *to_value,
425 gpointer user_data)
426 {
427 int port = g_value_get_int (from_value);
428
429 g_value_set_boolean (to_value, port > 0);
430
431 return TRUE;
432 }
433
434 static void
435 on_set_rdp_credentials (GsdRemoteDesktopRdpServer *rdp_server,
436 GAsyncResult *result,
437 gpointer user_data)
438 {
439 CcRemoteLoginPage *self = user_data;
440 g_autoptr(GVariant) credentials = NULL;
441 g_autoptr(GError) error = NULL;
442
443 gsd_remote_desktop_rdp_server_call_set_credentials_finish (rdp_server,
444 result,
445 &error);
446
447 self->store_credentials_id = 0;
448
449 if (error)
450 {
451 g_debug ("Could not set credentials for remote session access: %s", error->message);
452 return;
453 }
454
455 /* Do a roundtrip to make sure it stuck and also so we repopulate the tls fingerprint */
456 fetch_credentials (self);
457 }
458
459 static gboolean
460 store_credentials_timeout (gpointer user_data)
461 {
462 CcRemoteLoginPage *self = (CcRemoteLoginPage *)user_data;
463 const char *username, *password;
464
465 if (!g_permission_get_allowed (self->permission))
466 return G_SOURCE_REMOVE;
467
468 username = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
469 password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
470
471 if (username && password)
472 {
473 GVariantBuilder credentials;
474
475 g_variant_builder_init (&credentials, G_VARIANT_TYPE ("a{sv}"));
476 g_variant_builder_add (&credentials, "{sv}", "username", g_variant_new_string (username));
477 g_variant_builder_add (&credentials, "{sv}", "password", g_variant_new_string (password));
478
479 gsd_remote_desktop_rdp_server_call_set_credentials (self->rdp_server,
480 g_variant_builder_end (&credentials),
481 self->cancellable,
482 (GAsyncReadyCallback)
483 on_set_rdp_credentials,
484 self);
485 }
486 else
487 {
488 self->store_credentials_id = 0;
489 }
490
491 return G_SOURCE_REMOVE;
492 }
493
494 static void
495 on_credentials_changed (CcRemoteLoginPage *self)
496 {
497 g_clear_handle_id (&self->store_credentials_id, g_source_remove);
498
499 self->store_credentials_id =
500 g_timeout_add_seconds (REMOTE_DESKTOP_STORE_CREDENTIALS_TIMEOUT_S,
501 store_credentials_timeout,
502 self);
503 }
504
505 static void
506 hide_password (CcRemoteLoginPage *self)
507 {
508 GtkEditable *text = gtk_editable_get_delegate (GTK_EDITABLE (self->password_entry));
509 gtk_text_set_visibility (GTK_TEXT (text), FALSE);
510 }
511
512 static void
513 sync_permissions (CcRemoteLoginPage *self)
514 {
515 if (!g_permission_get_allowed (self->permission))
516 {
517 hide_password (self);
518
519 g_clear_handle_id (&self->store_credentials_id, g_source_remove);
520 gtk_widget_set_sensitive (GTK_WIDGET (self->remote_login_row), FALSE);
521 gtk_widget_set_sensitive (self->credentials_group, FALSE);
522 }
523 else
524 {
525 if (!self->activating)
526 gtk_widget_set_sensitive (GTK_WIDGET (self->remote_login_row), TRUE);
527
528 if (self->have_credentials)
529 gtk_widget_set_sensitive (self->credentials_group, TRUE);
530 }
531 }
532
533 static void
534 cc_remote_login_page_dispose (GObject *object)
535 {
536 CcRemoteLoginPage *self = (CcRemoteLoginPage *)object;
537
538 g_cancellable_cancel (self->cancellable);
539 g_clear_object (&self->cancellable);
540 g_clear_object (&self->permission);
541
542 g_clear_object (&self->rdp_server);
543
544 G_OBJECT_CLASS (cc_remote_login_page_parent_class)->dispose (object);
545 }
546
547 static void
548 cc_remote_login_page_class_init (CcRemoteLoginPageClass * klass)
549 {
550 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
551 GObjectClass *object_class = G_OBJECT_CLASS (klass);
552
553 object_class->dispose = cc_remote_login_page_dispose;
554
555 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/system/remote-desktop/cc-remote-login-page.ui");
556
557 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, hostname_row);
558 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, port_row);
559 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, toast_overlay);
560 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, permission_infobar);
561 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, remote_login_row);
562 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, credentials_group);
563 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, username_entry);
564 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, password_entry);
565 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, generate_password_button);
566 gtk_widget_class_bind_template_child (widget_class, CcRemoteLoginPage, verify_encryption_button);
567
568 gtk_widget_class_bind_template_callback (widget_class, on_address_copy_clicked);
569 gtk_widget_class_bind_template_callback (widget_class, on_port_copy_clicked);
570 gtk_widget_class_bind_template_callback (widget_class, on_username_copy_clicked);
571 gtk_widget_class_bind_template_callback (widget_class, on_password_copy_clicked);
572 gtk_widget_class_bind_template_callback (widget_class, on_generate_password_button_clicked);
573 gtk_widget_class_bind_template_callback (widget_class, on_verify_encryption_button_clicked);
574 }
575
576 static void
577 on_got_rdp_credentials (GObject *source_object,
578 GAsyncResult *result,
579 gpointer user_data)
580 {
581 CcRemoteLoginPage *self = user_data;
582 gboolean got_credentials, has_fingerprint;
583 g_autoptr(GVariant) credentials = NULL;
584 g_autoptr(GError) error = NULL;
585
586 got_credentials = gsd_remote_desktop_rdp_server_call_get_credentials_finish (self->rdp_server,
587 &credentials,
588 result,
589 &error);
590
591 if (error)
592 {
593 g_debug ("Could not get credentials for remote session access: %s", error->message);
594 return;
595 }
596
597 if (got_credentials)
598 {
599 const char *username = NULL;
600 const char *password = NULL;
601
602 self->have_credentials = TRUE;
603
604 sync_permissions (self);
605
606 g_variant_lookup (credentials, "username", "&s", &username);
607 if (username)
608 gtk_editable_set_text (GTK_EDITABLE (self->username_entry), username);
609
610 g_variant_lookup (credentials, "password", "&s", &password);
611 if (password)
612 gtk_editable_set_text (GTK_EDITABLE (self->password_entry), password);
613 }
614
615 /* Fetch TLS certificate fingerprint */
616 self->fingerprint = gsd_remote_desktop_rdp_server_get_tls_fingerprint (self->rdp_server);
617
618 has_fingerprint = self->fingerprint && strlen (self->fingerprint) > 0;
619 gtk_widget_set_sensitive (self->verify_encryption_button, has_fingerprint);
620 }
621
622 static void
623 fetch_credentials (CcRemoteLoginPage *self)
624 {
625 g_autoptr(GError) error = NULL;
626 g_autofree gchar *username = NULL;
627 g_autofree gchar *password = NULL;
628
629 if (!g_permission_get_allowed (self->permission))
630 return;
631
632 gsd_remote_desktop_rdp_server_call_get_credentials (self->rdp_server,
633 self->cancellable,
634 (GAsyncReadyCallback)
635 on_got_rdp_credentials,
636 self);
637 }
638
639 static void
640 on_remote_desktop_rdp_server_owner_changed (CcRemoteLoginPage *self)
641 {
642 const char *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (self->rdp_server));
643
644 gtk_widget_set_sensitive (GTK_WIDGET (self->toast_overlay), name_owner != NULL);
645 }
646
647 static void
648 on_connected_to_remote_desktop_rdp_server (GObject *source_object,
649 GAsyncResult *result,
650 gpointer user_data)
651 {
652 CcRemoteLoginPage *self = user_data;
653 g_autoptr (GError) error = NULL;
654
655 g_clear_object (&self->rdp_server);
656 self->rdp_server = gsd_remote_desktop_rdp_server_proxy_new_finish (result, &error);
657
658 g_signal_connect_object (self->rdp_server,
659 "notify::g-name-owner",
660 G_CALLBACK (on_remote_desktop_rdp_server_owner_changed),
661 self, G_CONNECT_SWAPPED);
662
663 if (error)
664 {
665 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
666 g_warning ("Failed to create remote desktop proxy: %s", error->message);
667 return;
668 }
669
670 g_signal_handlers_block_by_func (self->remote_login_row, on_remote_login_active_changed, self);
671 g_object_bind_property (self->rdp_server, "enabled", self->remote_login_row, "active", G_BINDING_SYNC_CREATE);
672 g_signal_handlers_unblock_by_func (self->remote_login_row, on_remote_login_active_changed, self);
673
674 g_object_bind_property_full (self->rdp_server, "port",
675 self->port_row, "subtitle",
676 G_BINDING_SYNC_CREATE,
677 format_port_for_row,
678 NULL,
679 NULL,
680 NULL);
681 g_object_bind_property_full (self->rdp_server, "port",
682 self->port_row, "sensitive",
683 G_BINDING_SYNC_CREATE,
684 sensitize_row_from_port,
685 NULL,
686 NULL,
687 NULL);
688
689 if (g_permission_get_allowed (self->permission))
690 fetch_credentials (self);
691
692 g_signal_connect_object (self->permission, "notify::allowed",
693 G_CALLBACK (fetch_credentials),
694 self, G_CONNECT_SWAPPED);
695 }
696
697 static void
698 connect_to_remote_desktop_rdp_server (CcRemoteLoginPage *self)
699 {
700 g_autoptr (GError) error = NULL;
701 g_autoptr (GDBusConnection) connection = NULL;
702
703 connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, self->cancellable, &error);
704
705 if (error)
706 g_warning ("Could not connect to system message bus: %s", error->message);
707
708 if (!connection)
709 return;
710
711 gsd_remote_desktop_rdp_server_proxy_new (connection,
712 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION,
713 REMOTE_LOGIN_DBUS_SERVICE,
714 REMOTE_LOGIN_OBJECT_PATH,
715 self->cancellable,
716 (GAsyncReadyCallback)
717 on_connected_to_remote_desktop_rdp_server,
718 self);
719 }
720
721 static void
722 cc_remote_login_page_init (CcRemoteLoginPage *self)
723 {
724 g_autoptr(GtkCssProvider) provider = NULL;
725 g_autoptr(GVariant) credentials = NULL;
726 g_autoptr(GError) error = NULL;
727 g_autofree gchar *hostname = NULL;
728
729 gtk_widget_init_template (GTK_WIDGET (self));
730
731 self->cancellable = g_cancellable_new ();
732
733 hostname = cc_hostname_get_display_hostname (cc_hostname_get_default ());
734 adw_action_row_set_subtitle (self->hostname_row, hostname);
735
736 g_signal_connect_swapped (self->username_entry, "notify::text",
737 G_CALLBACK (on_credentials_changed),
738 self);
739 g_signal_connect_swapped (self->password_entry, "notify::text",
740 G_CALLBACK (on_credentials_changed),
741 self);
742
743 g_signal_connect_object (self->remote_login_row, "notify::active",
744 G_CALLBACK (on_remote_login_active_changed), self,
745 G_CONNECT_SWAPPED);
746
747 self->permission = (GPermission*) polkit_permission_new_sync (REMOTE_LOGIN_PERMISSION, NULL, self->cancellable, &error);
748
749 if (error != NULL)
750 {
751 g_warning ("Cannot create '%s' permission: %s", REMOTE_LOGIN_PERMISSION, error->message);
752 g_clear_error (&error);
753 }
754
755 sync_permissions (self);
756 g_signal_connect_swapped (self->permission, "notify::allowed",
757 G_CALLBACK (sync_permissions),
758 self);
759
760 g_object_bind_property (self->password_entry, "sensitive",
761 self->generate_password_button, "sensitive",
762 G_BINDING_SYNC_CREATE);
763 cc_permission_infobar_set_permission (self->permission_infobar, self->permission);
764 cc_permission_infobar_set_title (self->permission_infobar, _("Some settings are locked"));
765
766 connect_to_remote_desktop_rdp_server (self);
767 }
768