[virt-tools-list] [PATCH virt-viewer 5/6] remote-viewer: add a --dbus-controller
marcandre.lureau at redhat.com
marcandre.lureau at redhat.com
Fri Jun 23 15:30:57 UTC 2017
From: Marc-André Lureau <marcandre.lureau at redhat.com>
Allow to set connection details via DBus, and add a Connect method.
This is intended to replace the Spice controller.
Sample usage:
DEST=`remote-viewer --dbus-controller`
gdbus call --session --dest $DEST --object-path /org/virt_manager/remote_viewer \
--method org.freedesktop.DBus.Properties.Set org.VirtManager.RemoteViewer.Controller \
host '<string "localhost">'
gdbus call --session --dest $DEST --object-path /org/virt_manager/remote_viewer \
--method org.freedesktop.DBus.Properties.Set org.VirtManager.RemoteViewer.Controller \
port '<int32 5900>'
gdbus call --session --dest $DEST --object-path /org/virt_manager/remote_viewer \
--method org.freedesktop.DBus.Properties.Set org.VirtManager.RemoteViewer.Controller \
type '<string "spice">'()
gdbus call --session --dest $DEST --object-path /org/virt_manager/remote_viewer \
--method org.VirtManager.RemoteViewer.Controller.Connect()
Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
---
src/remote-viewer.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++-
src/remote-viewer.h | 1 +
2 files changed, 196 insertions(+), 3 deletions(-)
diff --git a/src/remote-viewer.c b/src/remote-viewer.c
index fb5376c..f0f9531 100644
--- a/src/remote-viewer.c
+++ b/src/remote-viewer.c
@@ -57,6 +57,7 @@ struct _RemoteViewerPrivate {
OvirtForeignMenu *ovirt_foreign_menu;
#endif
gboolean open_recent_dialog;
+ VirtViewerFile *dbus_file;
};
G_DEFINE_TYPE (RemoteViewer, remote_viewer, VIRT_VIEWER_TYPE_APP)
@@ -137,6 +138,7 @@ remote_viewer_deactivated(VirtViewerApp *app, gboolean connect_error)
static gchar **opt_args = NULL;
static char *opt_title = NULL;
static gboolean opt_controller = FALSE;
+static gboolean opt_dbus_ctrl = FALSE;
static void
remote_viewer_add_option_entries(VirtViewerApp *self, GOptionContext *context, GOptionGroup *group)
@@ -144,6 +146,8 @@ remote_viewer_add_option_entries(VirtViewerApp *self, GOptionContext *context, G
static const GOptionEntry options[] = {
{ "title", 't', 0, G_OPTION_ARG_STRING, &opt_title,
N_("Set window title"), NULL },
+ { "dbus-controller", '\0', 0, G_OPTION_ARG_NONE, &opt_dbus_ctrl,
+ N_("Open connection using DBus controller"), NULL },
#ifdef HAVE_SPICE_GTK
{ "spice-controller", '\0', 0, G_OPTION_ARG_NONE, &opt_controller,
N_("Open connection using Spice controller communication"), NULL },
@@ -175,7 +179,17 @@ remote_viewer_local_command_line (GApplication *gapp,
if (ret)
goto end;
- if (!opt_args) {
+ if (opt_dbus_ctrl) {
+ if (opt_args || opt_controller) {
+ g_printerr(_("\nError: extra arguments given while using --dbus\n\n"));
+ ret = TRUE;
+ *status = 1;
+ goto end;
+ }
+ self->priv->dbus_file = virt_viewer_file_new(NULL, NULL);
+ virt_viewer_app_set_dbus_ctrl(app, TRUE);
+ return FALSE;
+ } else if (!opt_args) {
self->priv->open_recent_dialog = TRUE;
} else {
if (g_strv_length(opt_args) > 1) {
@@ -190,7 +204,7 @@ remote_viewer_local_command_line (GApplication *gapp,
#ifdef HAVE_SPICE_GTK
if (opt_controller) {
- if (opt_args) {
+ if (opt_args || opt_dbus_ctrl) {
g_printerr(_("\nError: extra arguments given while using Spice controller\n\n"));
ret = TRUE;
*status = 1;
@@ -241,6 +255,180 @@ remote_viewer_get_property(GObject *object, guint property_id,
}
}
+static void
+handle_method_call (GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *sender G_GNUC_UNUSED,
+ const gchar *object_path G_GNUC_UNUSED,
+ const gchar *interface_name G_GNUC_UNUSED,
+ const gchar *method_name,
+ GVariant *parameters G_GNUC_UNUSED,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ RemoteViewer *self = REMOTE_VIEWER(user_data);
+
+ if (g_str_equal(method_name, "Connect")) {
+ GError *error = NULL;
+ char *type = virt_viewer_file_get_file_type(self->priv->dbus_file);
+ g_debug("Connect! %s", type);
+ if (!remote_viewer_initial_connect(self, type, self->priv->dbus_file, &error)) {
+ g_dbus_method_invocation_return_gerror(invocation, error);
+ g_clear_error(&error);
+ } else {
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ }
+ }
+}
+
+
+static GVariant *
+handle_get_property (GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *sender G_GNUC_UNUSED,
+ const gchar *object_path G_GNUC_UNUSED,
+ const gchar *interface_name G_GNUC_UNUSED,
+ const gchar *property_name,
+ GError **error G_GNUC_UNUSED,
+ gpointer user_data)
+{
+ RemoteViewer *self = REMOTE_VIEWER(user_data);
+ GParamSpec *pspec;
+ GValue value = G_VALUE_INIT;
+ GVariant *ret;
+ const GVariantType *type = NULL;
+
+ pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->priv->dbus_file),
+ property_name);
+ if (!pspec) {
+ g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown property %s", property_name);
+ return NULL;
+ }
+ if (g_type_is_a(pspec->value_type, G_TYPE_STRING))
+ type = G_VARIANT_TYPE_STRING;
+ else if (g_type_is_a(pspec->value_type, G_TYPE_INT))
+ type = G_VARIANT_TYPE_INT32;
+ else if (g_type_is_a(pspec->value_type, G_TYPE_BOXED)) {
+ type = G_VARIANT_TYPE_STRING_ARRAY; /* only type as of writing this */
+ } else {
+ g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unhandled type for %s", property_name);
+ g_return_val_if_reached(NULL);
+ }
+
+ g_value_init(&value, pspec->value_type);
+ g_object_get_property(G_OBJECT(self->priv->dbus_file), property_name, &value);
+ ret = g_dbus_gvalue_to_gvariant(&value, type);
+ g_value_unset(&value);
+
+ return ret;
+}
+
+static gboolean
+handle_set_property (GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *sender G_GNUC_UNUSED,
+ const gchar *object_path G_GNUC_UNUSED,
+ const gchar *interface_name G_GNUC_UNUSED,
+ const gchar *property_name,
+ GVariant *variant,
+ GError **error,
+ gpointer user_data)
+{
+ RemoteViewer *self = REMOTE_VIEWER(user_data);
+ GValue value;
+
+ g_dbus_gvariant_to_gvalue(variant, &value);
+ g_object_set_property(G_OBJECT(self->priv->dbus_file), property_name, &value);
+ g_value_unset(&value);
+
+ return *error == NULL; /* error is always non-null */
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ handle_method_call,
+ handle_get_property,
+ handle_set_property,
+ { 0, } /* padding, hmm sucks */
+};
+
+static gboolean
+remote_viewer_dbus_register (GApplication *application,
+ GDBusConnection *connection,
+ const gchar *object_path,
+ GError **error)
+{
+ RemoteViewer *self = REMOTE_VIEWER(application);
+ RemoteViewerClass *klass = REMOTE_VIEWER_GET_CLASS(REMOTE_VIEWER(application));
+ guint registration_id;
+
+ if (!G_APPLICATION_CLASS(remote_viewer_parent_class)->dbus_register (application,
+ connection,
+ object_path,
+ error))
+ return FALSE;
+
+ if (!klass->introspection_data) {
+ /* keep in sync with virt-viewer-file */
+ /* voluntarily removed: color-depth, disable-effects, delete-this-file */
+ /* TODO: versions - uses a hashtable (replace it with strv?) */
+ static const gchar introspection_xml[] =
+ "<node>"
+ " <interface name='org.VirtManager.RemoteViewer.Controller'>"
+ " <method name='Connect'/>"
+ " <property type='s' name='version' access='readwrite'/>"
+ " <property type='s' name='newer-version-url' access='readwrite'/>"
+ " <property type='s' name='type' access='readwrite'/>"
+ " <property type='s' name='host' access='readwrite'/>"
+ " <property type='i' name='port' access='readwrite'/>"
+ " <property type='i' name='tls-port' access='readwrite'/>"
+ " <property type='s' name='username' access='readwrite'/>"
+ " <property type='s' name='password' access='readwrite'/>"
+ " <property type='as' name='disable-channels' access='readwrite'/>"
+ " <property type='s' name='tls-ciphers' access='readwrite'/>"
+ " <property type='s' name='ca' access='readwrite'/>"
+ " <property type='s' name='host-subject' access='readwrite'/>"
+ " <property type='i' name='fullscreen' access='readwrite'/>"
+ " <property type='s' name='title' access='readwrite'/>"
+ " <property type='s' name='toggle-fullscreen' access='readwrite'/>"
+ " <property type='s' name='release-cursor' access='readwrite'/>"
+ " <property type='s' name='smartcard-insert' access='readwrite'/>"
+ " <property type='s' name='smartcard-remove' access='readwrite'/>"
+ " <property type='s' name='secure-attention' access='readwrite'/>"
+ " <property type='i' name='enable-smartcard' access='readwrite'/>"
+ " <property type='i' name='enable-usbredir' access='readwrite'/>"
+ " <property type='i' name='enable-usb-autoshare' access='readwrite'/>"
+ " <property type='s' name='usb-filter' access='readwrite'/>"
+ " <property type='as' name='secure-channels' access='readwrite'/>"
+ " <property type='s' name='proxy' access='readwrite'/>"
+ " </interface>"
+ "</node>";
+
+ klass->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+ g_assert (klass->introspection_data);
+ }
+ registration_id = g_dbus_connection_register_object (connection,
+ object_path,
+ klass->introspection_data->interfaces[0],
+ &interface_vtable,
+ self, /* user_data */
+ NULL, /* user_data_free_func */
+ NULL); /* GError** */
+ g_assert (registration_id > 0);
+
+ g_print ("%s", g_dbus_connection_get_unique_name(connection));
+
+ return TRUE;
+}
+
+static void
+remote_viewer_dbus_unregister (GApplication *application,
+ GDBusConnection *connection,
+ const gchar *object_path)
+{
+ G_APPLICATION_CLASS(remote_viewer_parent_class)->dbus_unregister (application,
+ connection,
+ object_path);
+}
+
+
static void
remote_viewer_class_init (RemoteViewerClass *klass)
{
@@ -255,6 +443,8 @@ remote_viewer_class_init (RemoteViewerClass *klass)
object_class->dispose = remote_viewer_dispose;
g_app_class->local_command_line = remote_viewer_local_command_line;
+ g_app_class->dbus_register = remote_viewer_dbus_register;
+ g_app_class->dbus_unregister = remote_viewer_dbus_unregister;
app_class->start = remote_viewer_start;
app_class->deactivated = remote_viewer_deactivated;
@@ -1155,7 +1345,9 @@ remote_viewer_start(VirtViewerApp *app, GError **err)
virt_viewer_app_show_status(VIRT_VIEWER_APP(self), _("Setting up Spice session..."));
} else
#endif
- {
+ if (opt_dbus_ctrl) {
+ virt_viewer_app_show_status(VIRT_VIEWER_APP(self), _("Waiting on DBus controller..."));
+ } else {
retry_dialog:
if (priv->open_recent_dialog) {
VirtViewerWindow *main_window = virt_viewer_app_get_main_window(app);
diff --git a/src/remote-viewer.h b/src/remote-viewer.h
index 53566fc..09f10c1 100644
--- a/src/remote-viewer.h
+++ b/src/remote-viewer.h
@@ -44,6 +44,7 @@ typedef struct {
typedef struct {
VirtViewerAppClass parent_class;
+ GDBusNodeInfo *introspection_data;
} RemoteViewerClass;
GType remote_viewer_get_type (void);
--
2.13.1.395.gf7b71de06
More information about the virt-tools-list
mailing list