[network-manager-applet/dcbw/more-kill-dbus-glib: 1/3] editor: convert single-instance service to GDBus (bgo #760946)



commit f1de48be456817e2cd20573fab92518d625c304e
Author: Dan Williams <dcbw redhat com>
Date:   Thu Feb 18 12:11:39 2016 -0600

    editor: convert single-instance service to GDBus (bgo #760946)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=760946

 src/connection-editor/Makefile.am                  |   11 +-
 src/connection-editor/main.c                       |  378 +++++++++-----------
 .../nm-connection-editor-service.xml               |   10 -
 3 files changed, 164 insertions(+), 235 deletions(-)
---
diff --git a/src/connection-editor/Makefile.am b/src/connection-editor/Makefile.am
index 0d004ed..59681f3 100644
--- a/src/connection-editor/Makefile.am
+++ b/src/connection-editor/Makefile.am
@@ -13,7 +13,6 @@ nm_connection_editor_CPPFLAGS = \
        -DLIBDIR=\""$(libdir)"\" \
        -DDATADIR=\""$(datadir)"\" \
        -DNMALOCALEDIR=\"$(datadir)/locale\" \
-       $(DBUS_GLIB_CFLAGS) \
        "-I${top_srcdir}/shared/" \
        -I${top_srcdir}/src/utils \
        -I${top_srcdir}/src/wireless-security \
@@ -82,15 +81,11 @@ nm_connection_editor_SOURCES = \
        connection-helpers.c \
        connection-helpers.h
 
-nm-connection-editor-service-glue.h: $(top_srcdir)/src/connection-editor/nm-connection-editor-service.xml
-       $(AM_V_GEN) dbus-binding-tool --prefix=nm_connection_editor_service --mode=glib-server --output=$@ $<
-
 nm_connection_editor_LDADD = \
        ${top_builddir}/src/wireless-security/libwireless-security-libnm.la \
        ${top_builddir}/src/utils/libutils-libnm.la \
        ${top_builddir}/src/libnma/libnma.la \
        $(GTK_LIBS) \
-       $(DBUS_GLIB_LIBS) \
        $(LIBNM_LIBS) \
        -lm
 
@@ -120,9 +115,5 @@ ui_DATA = \
        ce-page-vlan.ui \
        ce-page-dcb.ui
 
-BUILT_SOURCES = nm-connection-editor-service-glue.h
-
-CLEANFILES = *.bak $(BUILT_SOURCES)
-
-EXTRA_DIST = $(ui_DATA) nm-connection-editor-service.xml
+EXTRA_DIST = $(ui_DATA)
 
diff --git a/src/connection-editor/main.c b/src/connection-editor/main.c
index 2864f8e..83b39cb 100644
--- a/src/connection-editor/main.c
+++ b/src/connection-editor/main.c
@@ -31,9 +31,8 @@
 #include <glib/gi18n-lib.h>
 #include <glib.h>
 #include <glib-object.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 
+#include "gsystem-local-alloc.h"
 #include "nm-connection-list.h"
 #include "nm-connection-editor.h"
 
@@ -46,89 +45,17 @@ static GMainLoop *loop = NULL;
 #define ARG_SHOW      "show"
 #define ARG_UUID      "uuid"
 
-#define DBUS_TYPE_G_MAP_OF_VARIANT    (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
+#define NM_CE_DBUS_SERVICE   "org.gnome.nm_connection_editor"
+#define NM_CE_DBUS_INTERFACE "org.gnome.nm_connection_editor"
 
-#define NM_CE_DBUS_SERVICE_NAME       "org.gnome.nm_connection_editor"
-
-/*************************************************/
-
-#define NM_TYPE_CE_SERVICE            (nm_ce_service_get_type ())
-#define NM_CE_SERVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CE_SERVICE, NMCEService))
-#define NM_CE_SERVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CE_SERVICE, 
NMCEServiceClass))
-#define NM_IS_CE_SERVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CE_SERVICE))
-#define NM_IS_CE_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CE_SERVICE))
-#define NM_CE_SERVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CE_SERVICE, 
NMCEServiceClass))
+static GDBusNodeInfo *introspection_data = NULL;
 
 typedef struct {
-       GObject parent;
-       NMConnectionList *list;
-} NMCEService;
-
-typedef struct {
-       GObjectClass parent;
-} NMCEServiceClass;
-
-GType nm_ce_service_get_type (void);
-
-G_DEFINE_TYPE (NMCEService, nm_ce_service, G_TYPE_OBJECT)
-
-static gboolean impl_start (NMCEService *self, GHashTable *args, GError **error);
-
-#include "nm-connection-editor-service-glue.h"
-
-static NMCEService *
-nm_ce_service_new (DBusGConnection *bus, DBusGProxy *proxy, NMConnectionList *list)
-{
-       GObject *object;
-       DBusConnection *connection;
-       GError *err = NULL;
-       guint32 result;
-
-       g_return_val_if_fail (bus != NULL, NULL);
-       g_return_val_if_fail (proxy != NULL, NULL);
-
-       object = g_object_new (NM_TYPE_CE_SERVICE, NULL);
-       if (!object)
-               return NULL;
-
-       NM_CE_SERVICE (object)->list = list;
-
-       dbus_connection_set_change_sigpipe (TRUE);
-       connection = dbus_g_connection_get_connection (bus);
-       dbus_connection_set_exit_on_disconnect (connection, FALSE);
-
-       /* Register our single-instance service.  Don't care if it fails. */
-       if (!dbus_g_proxy_call (proxy, "RequestName", &err,
-                               G_TYPE_STRING, NM_CE_DBUS_SERVICE_NAME,
-                               G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
-                               G_TYPE_INVALID,
-                               G_TYPE_UINT, &result,
-                               G_TYPE_INVALID)) {
-               g_warning ("Could not acquire the connection editor service.\n"
-                          "  Message: '%s'", err->message);
-               g_error_free (err);
-               return (NMCEService *) object;
-       }
-
-       if (result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
-               /* success; grab the bus name */
-               dbus_g_connection_register_g_object (bus, "/", object);
-       }
-
-       return (NMCEService *) object;
-}
-
-static void
-nm_ce_service_init (NMCEService *self)
-{
-}
-
-static void
-nm_ce_service_class_init (NMCEServiceClass *service_class)
-{
-       dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (service_class),
-                                        &dbus_glib_nm_connection_editor_service_object_info);
-}
+       char *type;      /* Type of connection to show or create */
+       gboolean create; /* Whether to create a connection of @type */
+       gboolean show;   /* Whether to show connections of @type */
+       char *uuid;      /* UUID of specific conneciton to show/edit */
+} EditorArgs;
 
 /*************************************************/
 
@@ -207,109 +134,143 @@ handle_arguments (NMConnectionList *list,
        return show_list;
 }
 
-static gboolean
-impl_start (NMCEService *self, GHashTable *table, GError **error)
+static void
+handle_method_call (GDBusConnection       *connection,
+                    const gchar           *sender,
+                    const gchar           *object_path,
+                    const gchar           *interface_name,
+                    const gchar           *method_name,
+                    GVariant              *parameters,
+                    GDBusMethodInvocation *invocation,
+                    gpointer               user_data)
 {
-       GValue *value;
-       const char *type = NULL;
-       const char *uuid = NULL;
-       gboolean create = FALSE;
-       gboolean show = FALSE;
-       gboolean show_list;
-
-       value = g_hash_table_lookup (table, ARG_TYPE);
-       if (value && G_VALUE_HOLDS_STRING (value)) {
-               type = g_value_get_string (value);
-               g_assert (type);
-       }
-
-       value = g_hash_table_lookup (table, ARG_UUID);
-       if (value && G_VALUE_HOLDS_STRING (value)) {
-               uuid = g_value_get_string (value);
-               g_assert (uuid);
+       NMConnectionList *list = NM_CONNECTION_LIST (user_data);
+       char *type = NULL, *uuid = NULL;
+       gboolean create = FALSE, show = FALSE;
+
+       if (g_strcmp0 (method_name, "Start") == 0) {
+               if (g_variant_is_of_type (parameters, (const GVariantType *) "(a{sv})")) {
+                       gs_unref_variant GVariant *dict = NULL;
+
+                       g_variant_get (parameters, "(@a{sv})", &dict);
+                       g_variant_lookup (dict, ARG_TYPE, "s", &type);
+                       g_variant_lookup (dict, ARG_UUID, "s", &uuid);
+                       g_variant_lookup (dict, ARG_CREATE, "b", &create);
+                       g_variant_lookup (dict, ARG_SHOW, "b", &show);
+                       if (handle_arguments (list, type, create, show, uuid, FALSE))
+                               nm_connection_list_present (list);
+
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               } else {
+                       g_dbus_method_invocation_return_error (invocation,
+                                                              G_DBUS_ERROR,
+                                                              G_DBUS_ERROR_INVALID_ARGS,
+                                                              "Invalid argument type (not a dict)");
+               }
        }
+}
 
-       value = g_hash_table_lookup (table, ARG_CREATE);
-       if (value && G_VALUE_HOLDS_BOOLEAN (value))
-               create = g_value_get_boolean (value);
-
-       value = g_hash_table_lookup (table, ARG_SHOW);
-       if (value && G_VALUE_HOLDS_BOOLEAN (value))
-               show = g_value_get_boolean (value);
-
-       show_list = handle_arguments (self->list, type, create, show, uuid, FALSE);
-       if (show_list)
-               nm_connection_list_present (self->list);
+static const GDBusInterfaceVTable interface_vtable = {
+       handle_method_call, NULL, NULL
+};
 
-       return TRUE;
+static guint
+start_service (GDBusConnection *bus, NMConnectionList *list)
+{
+       static const gchar introspection_xml[] =
+               "<node>"
+               "  <interface name='org.gnome.nm_connection_editor'>"
+               "    <method name='Start'>"
+               "      <arg type='a{sv}' name='args' direction='in'/>"
+               "    </method>"
+               "  </interface>"
+               "</node>";
+       guint registration_id;
+
+       introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+       g_assert (introspection_data != NULL);
+
+       registration_id = g_dbus_connection_register_object (bus,
+                                                            "/",
+                                                            introspection_data->interfaces[0],
+                                                            &interface_vtable,
+                                                            list,  /* user_data */
+                                                            NULL,  /* user_data_free_func */
+                                                            NULL); /* GError** */
+
+       return g_bus_own_name_on_connection (bus,
+                                            NM_CE_DBUS_SERVICE,
+                                            G_BUS_NAME_OWNER_FLAGS_NONE,
+                                            NULL,
+                                            NULL,
+                                            NULL,
+                                            NULL);
 }
 
 static gboolean
-try_existing_instance (DBusGConnection *bus,
-                       DBusGProxy *proxy,
+try_existing_instance (GDBusConnection *bus,
                        const char *type,
                        gboolean create,
                        gboolean show,
                        const char *uuid)
 {
-       gboolean has_owner = FALSE;
-       DBusGProxy *instance;
-       GHashTable *args;
-       GValue type_value = { 0, };
-       GValue create_value = { 0, };
-       GValue show_value = { 0, };
-       GValue uuid_value = { 0, };
-       gboolean success = FALSE;
-       GError *error = NULL;
-
-       if (!dbus_g_proxy_call (proxy, "NameHasOwner", NULL,
-                               G_TYPE_STRING, NM_CE_DBUS_SERVICE_NAME, G_TYPE_INVALID,
-                               G_TYPE_BOOLEAN, &has_owner, G_TYPE_INVALID))
+       gs_free char *owner = NULL;
+       gs_free_error GError *error = NULL;
+       gs_unref_variant GVariant *reply = NULL, *args = NULL;
+       GVariantBuilder builder;
+
+       g_assert (bus);
+
+       reply = g_dbus_connection_call_sync (bus,
+                                            DBUS_SERVICE_DBUS,
+                                            DBUS_PATH_DBUS,
+                                            DBUS_INTERFACE_DBUS,
+                                            "GetNameOwner",
+                                            g_variant_new ("(s)", NM_CE_DBUS_SERVICE),
+                                            G_VARIANT_TYPE ("(s)"),
+                                            G_DBUS_CALL_FLAGS_NONE,
+                                            -1,           /* timeout */
+                                            NULL,
+                                            &error);
+       if (!reply) {
+               if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
+                       g_warning ("Failed to get editor name owner: %s", error->message);
                return FALSE;
+       }
 
-       if (!has_owner)
+       g_variant_get (reply, "(s)", &owner);
+       if (!owner)
                return FALSE;
 
-       /* Send arguments to existing process */
-       instance = dbus_g_proxy_new_for_name (bus,
-                                             NM_CE_DBUS_SERVICE_NAME,
-                                             "/",
-                                             NM_CE_DBUS_SERVICE_NAME);
-       if (!instance)
+       g_variant_unref (reply);
+
+       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+       if (type)
+               g_variant_builder_add (&builder, "{sv}", ARG_TYPE, g_variant_new_string (type));
+       if (create)
+               g_variant_builder_add (&builder, "{sv}", ARG_CREATE, g_variant_new_boolean (TRUE));
+       if (show)
+               g_variant_builder_add (&builder, "{sv}", ARG_SHOW, g_variant_new_boolean (TRUE));
+       if (uuid)
+               g_variant_builder_add (&builder, "{sv}", ARG_UUID, g_variant_new_string (uuid));
+
+       reply = g_dbus_connection_call_sync (bus,
+                                            NM_CE_DBUS_SERVICE,
+                                            "/",
+                                            NM_CE_DBUS_INTERFACE,
+                                            "Start",
+                                            g_variant_new ("(@a{sv})", g_variant_builder_end (&builder)),
+                                            NULL,
+                                            G_DBUS_CALL_FLAGS_NONE,
+                                            -1,           /* timeout */
+                                            NULL,
+                                            &error);
+       if (!reply) {
+               g_warning ("Failed to send arguments to existing editor instance: %s", error->message);
                return FALSE;
-
-       args = g_hash_table_new (g_str_hash, g_str_equal);
-       if (type) {
-               g_value_init (&type_value, G_TYPE_STRING);
-               g_value_set_static_string (&type_value, type);
-               g_hash_table_insert (args, ARG_TYPE, &type_value);
-       }
-       if (create) {
-               g_value_init (&create_value, G_TYPE_BOOLEAN);
-               g_value_set_boolean (&create_value, TRUE);
-               g_hash_table_insert (args, ARG_CREATE, &create_value);
-       }
-       if (show) {
-               g_value_init (&show_value, G_TYPE_BOOLEAN);
-               g_value_set_boolean (&show_value, TRUE);
-               g_hash_table_insert (args, ARG_SHOW, &show_value);
-       }
-       if (uuid) {
-               g_value_init (&uuid_value, G_TYPE_STRING);
-               g_value_set_static_string (&uuid_value, uuid);
-               g_hash_table_insert (args, ARG_UUID, &uuid_value);
        }
 
-       if (dbus_g_proxy_call (instance, "Start", &error,
-                              DBUS_TYPE_G_MAP_OF_VARIANT, args, G_TYPE_INVALID,
-                              G_TYPE_INVALID))
-               success = TRUE;
-       else
-               g_warning ("%s: error calling start: %s", __func__, error->message);
-
-       g_hash_table_destroy (args);
-       g_object_unref (instance);
-       return success;
+       return TRUE;
 }
 
 static void
@@ -336,18 +297,14 @@ setup_signals (void)
 int
 main (int argc, char *argv[])
 {
-       GOptionContext *opt_ctx;
+       GOptionContext *opt_ctx = NULL;
        GError *error = NULL;
-       NMConnectionList *list;
-       DBusGConnection *bus;
-       char *type = NULL;
-       gboolean create = FALSE;
-       gboolean show = FALSE;
-       gboolean success;
-       char *uuid = NULL;
-       NMCEService *service = NULL;
-       DBusGProxy *proxy = NULL;
-       gboolean show_list;
+       NMConnectionList *list = NULL;
+       guint owner_id = 0;
+       GDBusConnection *bus = NULL;
+       gs_free char *type = NULL, *uuid = NULL;
+       gboolean create = FALSE, show = FALSE;
+       int ret = 1;
 
        GOptionEntry entries[] = {
                { ARG_TYPE,   't', 0, G_OPTION_ARG_STRING, &type,   "Type of connection to show or create", 
NM_SETTING_WIRED_SETTING_NAME },
@@ -368,34 +325,28 @@ main (int argc, char *argv[])
        opt_ctx = g_option_context_new (NULL);
        g_option_context_set_summary (opt_ctx, "Allows users to view and edit network connection settings");
        g_option_context_add_main_entries (opt_ctx, entries, NULL);
-       success = g_option_context_parse (opt_ctx, &argc, &argv, &error);
-       g_option_context_free (opt_ctx);
-
-       if (!success) {
-               g_warning ("%s\n", error->message);
-               g_error_free (error);
-               return 1;
+       if (!g_option_context_parse (opt_ctx, &argc, &argv, &error)) {
+               g_warning ("Failed to parse options: %s", error->message);
+               goto out;
        }
 
        /* Just one page for both CDMA & GSM, handle that here */
-       if (type && g_strcmp0 (type, NM_SETTING_CDMA_SETTING_NAME) == 0)
-               type = (char *) NM_SETTING_GSM_SETTING_NAME;
+       if (g_strcmp0 (type, NM_SETTING_CDMA_SETTING_NAME) == 0) {
+               g_free (type);
+               type = g_strdup (NM_SETTING_GSM_SETTING_NAME);
+       }
 
-       /* Inits the dbus-glib type system too */
-       bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+       bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
        if (bus) {
-               proxy = dbus_g_proxy_new_for_name (bus,
-                                                  "org.freedesktop.DBus",
-                                                  "/org/freedesktop/DBus",
-                                                  "org.freedesktop.DBus");
-               g_assert (proxy);
-
                /* Check for an existing instance on the bus, and if there
                 * is one, send the arguments to it and exit instead of opening
                 * a second instance of the connection editor.
                 */
-               if (try_existing_instance (bus, proxy, type, create, show, uuid))
-                       return 0;
+               if (try_existing_instance (bus, type, create, show, uuid)) {
+                       /* success */
+                       ret = 0;
+                       goto out;
+               }
        }
 
        loop = g_main_loop_new (NULL, FALSE);
@@ -403,33 +354,30 @@ main (int argc, char *argv[])
        list = nm_connection_list_new ();
        if (!list) {
                g_warning ("Failed to initialize the UI, exiting...");
-               return 1;
+               goto out;
        }
        g_signal_connect_swapped (list, "done", G_CALLBACK (g_main_loop_quit), loop);
 
-       /* Create our single-instance-app service if we can */
-       if (proxy)
-               service = nm_ce_service_new (bus, proxy, list);
-
-       /* Show the dialog */
-       g_signal_connect_swapped (list, "done", G_CALLBACK (g_main_loop_quit), loop);
+       start_service (bus, list);
 
        /* Figure out what page or editor window we'll show initially */
-       show_list = handle_arguments (list, type, create, show, uuid, (create || show || uuid));
-       if (show_list)
+       if (handle_arguments (list, type, create, show, uuid, (create || show || uuid)))
                nm_connection_list_present (list);
 
        setup_signals ();
        g_main_loop_run (loop);
-
-       /* Cleanup */
-       g_object_unref (list);
-       if (service)
-               g_object_unref (service);
-       if (proxy)
-               g_object_unref (proxy);
-       if (bus)
-               dbus_g_connection_unref (bus);
-       return 0;
+       ret = 0;
+
+out:
+       if (owner_id)
+               g_bus_unown_name (owner_id);
+       if (introspection_data)
+               g_dbus_node_info_unref (introspection_data);
+       g_clear_error (&error);
+       if (opt_ctx)
+               g_option_context_free (opt_ctx);
+       g_clear_object (&list);
+       g_clear_object (&bus);
+       return ret;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]