On 23/06/17 12:30, marcandre.lureau@xxxxxxxxxx wrote: > From: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> > > 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() > Please consider spliting this patch, as I said on my comment on patch 3 of the series. > Signed-off-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> > --- > 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); > -- Eduardo de Barros Lima (Etrunko) Software Engineer - RedHat etrunko@xxxxxxxxxx _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list