1 /*
2  * Virt Viewer: A virtual machine console viewer
3  *
4  * Copyright (C) 2007-2012 Red Hat, Inc.
5  * Copyright (C) 2009-2012 Daniel P. Berrange
6  * Copyright (C) 2010 Marc-André Lureau
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * Author: Daniel P. Berrange <berrange@redhat.com>
23  */
24 
25 #include <config.h>
26 
27 #include <locale.h>
28 #include <math.h>
29 
30 #include "virt-viewer-session.h"
31 #include "virt-viewer-util.h"
32 #include "virt-viewer-display-vte.h"
33 
34 typedef struct _VirtViewerSessionPrivate VirtViewerSessionPrivate;
35 struct _VirtViewerSessionPrivate
36 {
37     GList *displays;
38     VirtViewerApp *app;
39     gboolean auto_usbredir;
40     gboolean has_usbredir;
41     gchar *uri;
42     VirtViewerFile *file;
43     gboolean share_folder;
44     gchar *shared_folder;
45     gboolean share_folder_ro;
46 };
47 
48 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(VirtViewerSession, virt_viewer_session, G_TYPE_OBJECT)
49 
50 enum {
51     PROP_0,
52 
53     PROP_APP,
54     PROP_AUTO_USBREDIR,
55     PROP_HAS_USBREDIR,
56     PROP_FILE,
57     PROP_SW_SMARTCARD_READER,
58     PROP_SHARE_FOLDER,
59     PROP_SHARED_FOLDER,
60     PROP_SHARE_FOLDER_RO,
61 };
62 
63 static void
virt_viewer_session_finalize(GObject * obj)64 virt_viewer_session_finalize(GObject *obj)
65 {
66     VirtViewerSession *session = VIRT_VIEWER_SESSION(obj);
67     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(session);
68     GList *tmp = priv->displays;
69 
70     while (tmp) {
71         g_object_unref(tmp->data);
72         tmp = tmp->next;
73     }
74     g_list_free(priv->displays);
75 
76     g_free(priv->uri);
77     g_clear_object(&priv->file);
78     g_free(priv->shared_folder);
79 
80     G_OBJECT_CLASS(virt_viewer_session_parent_class)->finalize(obj);
81 }
82 
83 static void
virt_viewer_session_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)84 virt_viewer_session_set_property(GObject *object,
85                                  guint prop_id,
86                                  const GValue *value,
87                                  GParamSpec *pspec)
88 {
89     VirtViewerSession *self = VIRT_VIEWER_SESSION(object);
90     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
91 
92     switch (prop_id) {
93     case PROP_AUTO_USBREDIR:
94         virt_viewer_session_set_auto_usbredir(self, g_value_get_boolean(value));
95         break;
96 
97     case PROP_HAS_USBREDIR:
98         priv->has_usbredir = g_value_get_boolean(value);
99         break;
100 
101     case PROP_APP:
102         priv->app = g_value_get_object(value);
103         break;
104 
105     case PROP_FILE:
106         virt_viewer_session_set_file(self, g_value_get_object(value));
107         break;
108 
109     case PROP_SHARE_FOLDER:
110         priv->share_folder = g_value_get_boolean(value);
111         break;
112 
113     case PROP_SHARED_FOLDER:
114         g_free(priv->shared_folder);
115         priv->shared_folder = g_value_dup_string(value);
116         break;
117 
118     case PROP_SHARE_FOLDER_RO:
119         priv->share_folder_ro = g_value_get_boolean(value);
120         break;
121 
122     default:
123         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
124         break;
125     }
126 }
127 
128 static void
virt_viewer_session_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)129 virt_viewer_session_get_property(GObject *object,
130                                  guint prop_id,
131                                  GValue *value,
132                                  GParamSpec *pspec)
133 {
134     VirtViewerSession *self = VIRT_VIEWER_SESSION(object);
135     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
136 
137     switch (prop_id) {
138     case PROP_AUTO_USBREDIR:
139         g_value_set_boolean(value, virt_viewer_session_get_auto_usbredir(self));
140         break;
141 
142     case PROP_HAS_USBREDIR:
143         g_value_set_boolean(value, priv->has_usbredir);
144         break;
145 
146     case PROP_APP:
147         g_value_set_object(value, priv->app);
148         break;
149 
150     case PROP_FILE:
151         g_value_set_object(value, priv->file);
152         break;
153 
154     case PROP_SW_SMARTCARD_READER:
155         g_value_set_boolean(value, FALSE);
156         break;
157 
158     case PROP_SHARE_FOLDER:
159         g_value_set_boolean(value, priv->share_folder);
160         break;
161 
162     case PROP_SHARED_FOLDER:
163         g_value_set_string(value, priv->shared_folder);
164         break;
165 
166     case PROP_SHARE_FOLDER_RO:
167         g_value_set_boolean(value, priv->share_folder_ro);
168         break;
169 
170     default:
171         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
172         break;
173     }
174 }
175 
176 static void
virt_viewer_session_class_init(VirtViewerSessionClass * class)177 virt_viewer_session_class_init(VirtViewerSessionClass *class)
178 {
179     GObjectClass *object_class = G_OBJECT_CLASS(class);
180 
181     object_class->set_property = virt_viewer_session_set_property;
182     object_class->get_property = virt_viewer_session_get_property;
183     object_class->finalize = virt_viewer_session_finalize;
184 
185     g_object_class_install_property(object_class,
186                                     PROP_AUTO_USBREDIR,
187                                     g_param_spec_boolean("auto-usbredir",
188                                                          "USB redirection",
189                                                          "USB redirection",
190                                                          TRUE,
191                                                          G_PARAM_READWRITE |
192                                                          G_PARAM_CONSTRUCT |
193                                                          G_PARAM_STATIC_STRINGS));
194 
195     g_object_class_install_property(object_class,
196                                     PROP_HAS_USBREDIR,
197                                     g_param_spec_boolean("has-usbredir",
198                                                          "has USB redirection",
199                                                          "has USB redirection",
200                                                          FALSE,
201                                                          G_PARAM_READWRITE |
202                                                          G_PARAM_CONSTRUCT |
203                                                          G_PARAM_STATIC_STRINGS));
204 
205     g_object_class_install_property(object_class,
206                                     PROP_APP,
207                                     g_param_spec_object("app",
208                                                          "VirtViewerApp",
209                                                          "VirtViewerApp",
210                                                          VIRT_VIEWER_TYPE_APP,
211                                                          G_PARAM_READWRITE |
212                                                          G_PARAM_CONSTRUCT |
213                                                          G_PARAM_STATIC_STRINGS));
214 
215     g_object_class_install_property(object_class,
216                                     PROP_FILE,
217                                     g_param_spec_object("file",
218                                                          "VirtViewerFile",
219                                                          "VirtViewerFile",
220                                                          VIRT_VIEWER_TYPE_FILE,
221                                                          G_PARAM_READWRITE |
222                                                          G_PARAM_CONSTRUCT |
223                                                          G_PARAM_STATIC_STRINGS));
224 
225     g_object_class_install_property(object_class,
226                                     PROP_SW_SMARTCARD_READER,
227                                     g_param_spec_boolean("software-smartcard-reader",
228                                                          "Software smartcard reader",
229                                                          "Indicates whether a software smartcard reader is available",
230                                                          FALSE,
231                                                          G_PARAM_READABLE |
232                                                          G_PARAM_STATIC_STRINGS));
233 
234     g_object_class_install_property(object_class,
235                                     PROP_SHARE_FOLDER,
236                                     g_param_spec_boolean("share-folder",
237                                                          "Share folder",
238                                                          "Indicates whether to share folder",
239                                                          FALSE,
240                                                          G_PARAM_READWRITE |
241                                                          G_PARAM_STATIC_STRINGS));
242 
243     g_object_class_install_property(object_class,
244                                     PROP_SHARED_FOLDER,
245                                     g_param_spec_string("shared-folder",
246                                                         "Shared folder",
247                                                         "Indicates the shared folder",
248                                                         g_get_user_special_dir(G_USER_DIRECTORY_PUBLIC_SHARE),
249                                                         G_PARAM_READWRITE |
250                                                         G_PARAM_STATIC_STRINGS));
251 
252     g_object_class_install_property(object_class,
253                                     PROP_SHARE_FOLDER_RO,
254                                     g_param_spec_boolean("share-folder-ro",
255                                                          "Share folder read-only",
256                                                          "Indicates whether to share folder in read-only",
257                                                          FALSE,
258                                                          G_PARAM_READWRITE |
259                                                          G_PARAM_STATIC_STRINGS));
260 
261     g_signal_new("session-connected",
262                  G_OBJECT_CLASS_TYPE(object_class),
263                  G_SIGNAL_RUN_FIRST,
264                  0,
265                  NULL, NULL,
266                  g_cclosure_marshal_VOID__VOID,
267                  G_TYPE_NONE,
268                  0);
269 
270     g_signal_new("session-initialized",
271                  G_OBJECT_CLASS_TYPE(object_class),
272                  G_SIGNAL_RUN_FIRST,
273                  0,
274                  NULL, NULL,
275                  g_cclosure_marshal_VOID__VOID,
276                  G_TYPE_NONE,
277                  0);
278 
279     g_signal_new("session-disconnected",
280                  G_OBJECT_CLASS_TYPE(object_class),
281                  G_SIGNAL_RUN_FIRST,
282                  0,
283                  NULL, NULL,
284                  g_cclosure_marshal_VOID__STRING,
285                  G_TYPE_NONE,
286                  1,
287                  G_TYPE_STRING);
288 
289     g_signal_new("session-channel-open",
290                  G_OBJECT_CLASS_TYPE(object_class),
291                  G_SIGNAL_RUN_FIRST,
292                  0,
293                  NULL, NULL,
294                  g_cclosure_marshal_VOID__OBJECT,
295                  G_TYPE_NONE,
296                  1,
297                  G_TYPE_OBJECT);
298 
299     g_signal_new("session-auth-refused",
300                  G_OBJECT_CLASS_TYPE(object_class),
301                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
302                  0,
303                  NULL,
304                  NULL,
305                  g_cclosure_marshal_VOID__STRING,
306                  G_TYPE_NONE,
307                  1,
308                  G_TYPE_STRING);
309 
310     g_signal_new("session-auth-unsupported",
311                  G_OBJECT_CLASS_TYPE(object_class),
312                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
313                  0,
314                  NULL,
315                  NULL,
316                  g_cclosure_marshal_VOID__STRING,
317                  G_TYPE_NONE,
318                  1,
319                  G_TYPE_STRING);
320 
321     g_signal_new("session-usb-failed",
322                  G_OBJECT_CLASS_TYPE(object_class),
323                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
324                  0,
325                  NULL,
326                  NULL,
327                  g_cclosure_marshal_VOID__STRING,
328                  G_TYPE_NONE,
329                  1,
330                  G_TYPE_STRING);
331 
332     g_signal_new("session-display-added",
333                  G_OBJECT_CLASS_TYPE(object_class),
334                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
335                  0,
336                  NULL,
337                  NULL,
338                  g_cclosure_marshal_VOID__OBJECT,
339                  G_TYPE_NONE,
340                  1,
341                  VIRT_VIEWER_TYPE_DISPLAY);
342 
343     g_signal_new("session-display-removed",
344                  G_OBJECT_CLASS_TYPE(object_class),
345                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
346                  0,
347                  NULL,
348                  NULL,
349                  g_cclosure_marshal_VOID__OBJECT,
350                  G_TYPE_NONE,
351                  1,
352                  VIRT_VIEWER_TYPE_DISPLAY);
353 
354     g_signal_new("session-display-updated",
355                  G_OBJECT_CLASS_TYPE(object_class),
356                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
357                  0,
358                  NULL,
359                  NULL,
360                  g_cclosure_marshal_VOID__VOID,
361                  G_TYPE_NONE,
362                  0);
363 
364     g_signal_new("session-cut-text",
365                  G_OBJECT_CLASS_TYPE(object_class),
366                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
367                  0,
368                  NULL,
369                  NULL,
370                  g_cclosure_marshal_VOID__STRING,
371                  G_TYPE_NONE,
372                  1,
373                  G_TYPE_STRING);
374 
375     g_signal_new("session-bell",
376                  G_OBJECT_CLASS_TYPE(object_class),
377                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
378                  0,
379                  NULL,
380                  NULL,
381                  g_cclosure_marshal_VOID__VOID,
382                  G_TYPE_NONE,
383                  0);
384 
385     g_signal_new("session-cancelled",
386                  G_OBJECT_CLASS_TYPE(object_class),
387                  G_SIGNAL_RUN_FIRST,
388                  0,
389                  NULL, NULL,
390                  g_cclosure_marshal_VOID__VOID,
391                  G_TYPE_NONE,
392                  0);
393 }
394 
395 static void
virt_viewer_session_init(VirtViewerSession * session G_GNUC_UNUSED)396 virt_viewer_session_init(VirtViewerSession *session G_GNUC_UNUSED)
397 {
398 }
399 
400 static void
virt_viewer_session_on_monitor_geometry_changed(VirtViewerSession * self,VirtViewerDisplay * display G_GNUC_UNUSED)401 virt_viewer_session_on_monitor_geometry_changed(VirtViewerSession* self,
402                                                 VirtViewerDisplay* display G_GNUC_UNUSED)
403 {
404     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
405     VirtViewerSessionClass *klass;
406     gboolean all_fullscreen = TRUE;
407     /* GHashTable<gint, GdkRectangle*> */
408     GHashTable *monitors;
409     gint n_sized_monitors = 0;
410     GList *l;
411 
412     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
413     if (!klass->apply_monitor_geometry)
414         return;
415 
416     monitors = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
417 
418     for (l = priv->displays; l; l = l->next) {
419         VirtViewerDisplay *d = VIRT_VIEWER_DISPLAY(l->data);
420 
421         if (VIRT_VIEWER_IS_DISPLAY_VTE(d))
422             continue;
423 
424         guint nth = 0;
425         GdkRectangle *rect = g_new0(GdkRectangle, 1);
426 
427         g_object_get(d, "nth-display", &nth, NULL);
428         virt_viewer_display_get_preferred_monitor_geometry(d, rect);
429         if (rect->width > 0 && rect->height > 0)
430             n_sized_monitors++;
431 
432         if (virt_viewer_display_get_enabled(d) &&
433             !virt_viewer_display_get_fullscreen(d))
434             all_fullscreen = FALSE;
435         g_hash_table_insert(monitors, GINT_TO_POINTER(nth), rect);
436     }
437 
438     if (n_sized_monitors == 0) {
439         goto cleanup;
440     }
441 
442     if (!all_fullscreen)
443         virt_viewer_align_monitors_linear(monitors);
444 
445     virt_viewer_shift_monitors_to_origin(monitors);
446 
447     klass->apply_monitor_geometry(self, monitors);
448 
449 cleanup:
450     g_hash_table_unref(monitors);
451 }
452 
virt_viewer_session_add_display(VirtViewerSession * session,VirtViewerDisplay * display)453 void virt_viewer_session_add_display(VirtViewerSession *session,
454                                      VirtViewerDisplay *display)
455 {
456     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(session);
457 
458     if (g_list_find(priv->displays, display))
459         return;
460 
461     priv->displays = g_list_append(priv->displays, display);
462     g_object_ref(display);
463     g_signal_emit_by_name(session, "session-display-added", display);
464 
465     virt_viewer_signal_connect_object(display, "monitor-geometry-changed",
466                                       G_CALLBACK(virt_viewer_session_on_monitor_geometry_changed), session,
467                                       G_CONNECT_SWAPPED);
468 }
469 
470 
virt_viewer_session_remove_display(VirtViewerSession * session,VirtViewerDisplay * display)471 void virt_viewer_session_remove_display(VirtViewerSession *session,
472                                         VirtViewerDisplay *display)
473 {
474     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(session);
475 
476     if (!g_list_find(priv->displays, display))
477         return;
478 
479     priv->displays = g_list_remove(priv->displays, display);
480     g_signal_emit_by_name(session, "session-display-removed", display);
481     g_object_unref(display);
482 }
483 
virt_viewer_session_clear_displays(VirtViewerSession * session)484 void virt_viewer_session_clear_displays(VirtViewerSession *session)
485 {
486     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(session);
487     GList *tmp = priv->displays;
488 
489     while (tmp) {
490         VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(tmp->data);
491         g_signal_emit_by_name(session, "session-display-removed", display);
492         virt_viewer_display_close(display);
493         g_object_unref(display);
494         tmp = tmp->next;
495     }
496     g_list_free(priv->displays);
497     priv->displays = NULL;
498 }
499 
virt_viewer_session_update_displays_geometry(VirtViewerSession * session)500 void virt_viewer_session_update_displays_geometry(VirtViewerSession *session)
501 {
502     virt_viewer_session_on_monitor_geometry_changed(session, NULL);
503 }
504 
505 
virt_viewer_session_close(VirtViewerSession * session)506 void virt_viewer_session_close(VirtViewerSession *session)
507 {
508     g_return_if_fail(VIRT_VIEWER_IS_SESSION(session));
509 
510     VIRT_VIEWER_SESSION_GET_CLASS(session)->close(session);
511 }
512 
virt_viewer_session_open_fd(VirtViewerSession * session,int fd)513 gboolean virt_viewer_session_open_fd(VirtViewerSession *session, int fd)
514 {
515     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(session), FALSE);
516 
517     return VIRT_VIEWER_SESSION_GET_CLASS(session)->open_fd(session, fd);
518 }
519 
virt_viewer_session_open_host(VirtViewerSession * session,const gchar * host,const gchar * port,const gchar * tlsport)520 gboolean virt_viewer_session_open_host(VirtViewerSession *session, const gchar *host, const gchar *port, const gchar *tlsport)
521 {
522     VirtViewerSessionClass *klass;
523 
524     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(session), FALSE);
525 
526     klass = VIRT_VIEWER_SESSION_GET_CLASS(session);
527     return klass->open_host(session, host, port, tlsport);
528 }
529 
virt_viewer_session_open_uri(VirtViewerSession * session,const gchar * uri,GError ** error)530 gboolean virt_viewer_session_open_uri(VirtViewerSession *session, const gchar *uri, GError **error)
531 {
532     VirtViewerSessionClass *klass;
533 
534     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(session), FALSE);
535 
536     klass = VIRT_VIEWER_SESSION_GET_CLASS(session);
537     g_return_val_if_fail(klass->open_uri != NULL, FALSE);
538 
539     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(session);
540     priv->uri = g_strdup(uri);
541 
542     return klass->open_uri(session, uri, error);
543 }
544 
virt_viewer_session_mime_type(VirtViewerSession * self)545 const gchar* virt_viewer_session_mime_type(VirtViewerSession *self)
546 {
547     VirtViewerSessionClass *klass;
548 
549     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), FALSE);
550 
551     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
552     if (priv->file)
553         return "application/x-virt-viewer";
554 
555     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
556     g_return_val_if_fail(klass->mime_type != NULL, FALSE);
557 
558     return klass->mime_type(self);
559 }
560 
virt_viewer_session_channel_open_fd(VirtViewerSession * session,VirtViewerSessionChannel * channel,int fd)561 gboolean virt_viewer_session_channel_open_fd(VirtViewerSession *session,
562                                              VirtViewerSessionChannel *channel, int fd)
563 {
564     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(session), FALSE);
565 
566     return VIRT_VIEWER_SESSION_GET_CLASS(session)->channel_open_fd(session, channel, fd);
567 }
568 
virt_viewer_session_set_auto_usbredir(VirtViewerSession * self,gboolean auto_usbredir)569 void virt_viewer_session_set_auto_usbredir(VirtViewerSession *self, gboolean auto_usbredir)
570 {
571     g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
572 
573     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
574     if (priv->auto_usbredir == auto_usbredir)
575         return;
576 
577     priv->auto_usbredir = auto_usbredir;
578     g_object_notify(G_OBJECT(self), "auto-usbredir");
579 }
580 
virt_viewer_session_get_auto_usbredir(VirtViewerSession * self)581 gboolean virt_viewer_session_get_auto_usbredir(VirtViewerSession *self)
582 {
583     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), FALSE);
584 
585     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
586     return priv->auto_usbredir;
587 }
588 
virt_viewer_session_set_has_usbredir(VirtViewerSession * self,gboolean has_usbredir)589 void virt_viewer_session_set_has_usbredir(VirtViewerSession *self, gboolean has_usbredir)
590 {
591     g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
592 
593     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
594     if (priv->has_usbredir == has_usbredir)
595         return;
596 
597     priv->has_usbredir = has_usbredir;
598     g_object_notify(G_OBJECT(self), "has-usbredir");
599 }
600 
virt_viewer_session_get_has_usbredir(VirtViewerSession * self)601 gboolean virt_viewer_session_get_has_usbredir(VirtViewerSession *self)
602 {
603     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), FALSE);
604 
605     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
606     return priv->has_usbredir;
607 }
608 
virt_viewer_session_usb_device_selection(VirtViewerSession * self,GtkWindow * parent)609 void virt_viewer_session_usb_device_selection(VirtViewerSession   *self,
610                                               GtkWindow           *parent)
611 {
612     VirtViewerSessionClass *klass;
613 
614     g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
615 
616     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
617     g_return_if_fail(klass->usb_device_selection != NULL);
618 
619     klass->usb_device_selection(self, parent);
620 }
621 
virt_viewer_session_usb_device_reset(VirtViewerSession * self)622 void virt_viewer_session_usb_device_reset(VirtViewerSession *self)
623 {
624     VirtViewerSessionClass *klass;
625 
626     g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
627 
628     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
629     if (klass->usb_device_reset == NULL) {
630         g_debug("No session usbredir support");
631         return;
632     }
633 
634     klass->usb_device_reset(self);
635 }
636 
virt_viewer_session_smartcard_insert(VirtViewerSession * self)637 void virt_viewer_session_smartcard_insert(VirtViewerSession *self)
638 {
639     VirtViewerSessionClass *klass;
640 
641     g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
642 
643     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
644     if (klass->smartcard_insert == NULL) {
645         g_debug("No session smartcard support");
646         return;
647     }
648 
649     klass->smartcard_insert(self);
650 }
651 
virt_viewer_session_smartcard_remove(VirtViewerSession * self)652 void virt_viewer_session_smartcard_remove(VirtViewerSession *self)
653 {
654     VirtViewerSessionClass *klass;
655 
656     g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
657 
658     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
659     if (klass->smartcard_remove == NULL) {
660         g_debug("No session smartcard support");
661         return;
662     }
663 
664     klass->smartcard_remove(self);
665 }
666 
virt_viewer_session_get_app(VirtViewerSession * self)667 VirtViewerApp* virt_viewer_session_get_app(VirtViewerSession *self)
668 {
669     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), NULL);
670 
671     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
672     return priv->app;
673 }
674 
virt_viewer_session_get_uri(VirtViewerSession * self)675 gchar* virt_viewer_session_get_uri(VirtViewerSession *self)
676 {
677     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), FALSE);
678 
679     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
680     return g_strdup(priv->uri);
681 }
682 
virt_viewer_session_set_file(VirtViewerSession * self,VirtViewerFile * file)683 void virt_viewer_session_set_file(VirtViewerSession *self, VirtViewerFile *file)
684 {
685     g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
686 
687     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
688     g_clear_object(&priv->file);
689     if (file)
690         priv->file = g_object_ref(file);
691 }
692 
virt_viewer_session_get_file(VirtViewerSession * self)693 VirtViewerFile* virt_viewer_session_get_file(VirtViewerSession *self)
694 {
695     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), NULL);
696 
697     VirtViewerSessionPrivate *priv = virt_viewer_session_get_instance_private(self);
698     return priv->file;
699 }
700 
virt_viewer_session_can_share_folder(VirtViewerSession * self)701 gboolean virt_viewer_session_can_share_folder(VirtViewerSession *self)
702 {
703     VirtViewerSessionClass *klass;
704 
705     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), FALSE);
706 
707     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
708 
709     return klass->can_share_folder ? klass->can_share_folder(self) : FALSE;
710 }
711 
virt_viewer_session_can_retry_auth(VirtViewerSession * self)712 gboolean virt_viewer_session_can_retry_auth(VirtViewerSession *self)
713 {
714     VirtViewerSessionClass *klass;
715 
716     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), FALSE);
717 
718     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
719 
720     return klass->can_retry_auth ? klass->can_retry_auth(self) : FALSE;
721 }
722 
virt_viewer_session_vm_action(VirtViewerSession * self,gint action)723 void virt_viewer_session_vm_action(VirtViewerSession *self, gint action)
724 {
725     VirtViewerSessionClass *klass;
726 
727     g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
728 
729     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
730 
731     if (klass->vm_action)
732         klass->vm_action(self, action);
733 }
734 
virt_viewer_session_has_vm_action(VirtViewerSession * self,gint action)735 gboolean virt_viewer_session_has_vm_action(VirtViewerSession *self, gint action)
736 {
737     VirtViewerSessionClass *klass;
738 
739     g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), FALSE);
740 
741     klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
742 
743     if (klass->has_vm_action)
744         return klass->has_vm_action(self, action);
745     return FALSE;
746 }
747