diff options
author | Ray Strode <rstrode@redhat.com> | 2024-04-19 13:43:15 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2024-04-19 13:45:12 -0400 |
commit | 2aaac4b3ce14aecc042d865b956160b43d8dec4d (patch) | |
tree | ec0d55b12b4f1de1bf45a89c621715abc33064d1 | |
parent | 546445d4310f9feb85e89926bbd925cdb375b554 (diff) |
wip! user: Use D-Bus Object Managerobject-manager
AccountsService is really the posterboy for the type of service that
should use D-Bus Object Manager, but for weird historical reasons it
doesn't.
This commit begins to sketch out how a minimally bolted on object
manager implementation might look.
-rw-r--r-- | src/daemon.c | 10 | ||||
-rw-r--r-- | src/user.c | 105 | ||||
-rw-r--r-- | src/user.h | 3 |
3 files changed, 76 insertions, 42 deletions
diff --git a/src/daemon.c b/src/daemon.c index 188ddcb..3243955 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -83,6 +83,7 @@ typedef enum typedef struct { GDBusConnection *bus_connection; + GDBusObjectManagerServer *object_manager; GHashTable *users; gsize number_of_normal_users; @@ -642,7 +643,7 @@ reload_users (Daemon *daemon) stale_user = g_hash_table_lookup (old_users, name); if (!stale_user || (!user_get_cached (stale_user) && user_get_cached (user))) { - user_register (user); + user_register (user, priv->object_manager); accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon), user_get_object_path (user)); } @@ -919,6 +920,8 @@ daemon_finalize (GObject *object) if (priv->bus_connection != NULL) g_object_unref (priv->bus_connection); + g_clear_object (&priv->object_manager); + g_queue_free_full (priv->pending_list_cached_users, (GDestroyNotify) list_user_data_free); @@ -961,6 +964,9 @@ register_accounts_daemon (Daemon *daemon) return FALSE; } + priv->object_manager = g_dbus_object_manager_server_new ("/org/freedesktop/Accounts/UserManager"); + g_dbus_object_manager_server_set_connection (priv->object_manager, priv->bus_connection); + return TRUE; } @@ -1009,7 +1015,7 @@ add_new_user_for_pwent (Daemon *daemon, user = user_new (daemon, pwent->pw_uid); user_update_from_pwent (user, pwent, spent); - user_register (user); + user_register (user, priv->object_manager); g_hash_table_insert (priv->users, g_strdup (user_get_user_name (user)), @@ -77,8 +77,7 @@ struct User gboolean template_loaded; gboolean local_account_overridden; - guint *extension_ids; - guint n_extension_ids; + GDBusObjectManager *object_manager; guint changed_timeout_id; }; @@ -88,11 +87,24 @@ typedef struct UserClass AccountsUserSkeletonClass parent_class; } UserClass; +typedef struct +{ + GDBusInterfaceSkeleton parent; +} UserExtensionSkeleton; + +typedef struct +{ + GDBusInterfaceSkeletonClass parent_class; +} UserExtensionSkeletonClass; + +GType user_extension_skeleton_get_type (void); + static void user_accounts_user_iface_init (AccountsUserIface *iface); static void user_update_from_keyfile (User *user, GKeyFile *keyfile); G_DEFINE_TYPE_WITH_CODE (User, user, ACCOUNTS_TYPE_USER_SKELETON, G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_USER, user_accounts_user_iface_init)); +G_DEFINE_TYPE (UserExtensionSkeleton, user_extension_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON); static gint account_type_from_pwent (struct passwd *pwent) @@ -936,35 +948,50 @@ user_extension_method_call (GDBusConnection *connection, } } -static void -user_register_extensions (User *user) +static GDBusInterfaceVTable * +user_extension_get_vtable (GDBusInterfaceSkeleton *skeleton) { static const GDBusInterfaceVTable vtable = { user_extension_method_call, NULL /* get_property */, NULL /* set_property */ }; + + return (GDBusInterfaceVTable *) &vtable; +} + +static void +user_extension_skeleton_init (UserExtensionSkeleton *object) +{ +} + +static void +user_extension_skeleton_class_init (UserExtensionSkeletonClass *klass) +{ + GDBusInterfaceSkeletonClass *skeleton_class; + + skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skeleton_class->get_vtable = user_extension_get_vtable; +} +static void +user_register_extensions (User *user, + GDBusObjectSkeleton *object) +{ GHashTable *extensions; GHashTableIter iter; - gpointer iface; - gint i = 0; - - g_assert (user->extension_ids == NULL); - g_assert (user->n_extension_ids == 0); + char *interface_name; + GDBusInterfaceInfo *iface; extensions = daemon_get_extension_ifaces (user->daemon); - user->n_extension_ids = g_hash_table_size (extensions); - user->extension_ids = g_new (guint, user->n_extension_ids); g_hash_table_iter_init (&iter, extensions); /* Ignore errors when registering more interfaces because (a) * they won't happen and (b) even if they do, we still want to * publish the main user interface. */ - while (g_hash_table_iter_next (&iter, NULL, &iface)) { - user->extension_ids[i++] = g_dbus_connection_register_object (user->system_bus_connection, - g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (user)), iface, - &vtable, user, NULL, NULL); + while (g_hash_table_iter_next (&iter, (gpointer) &interface_name, (gpointer) &iface)) { + GDBusInterfaceSkeleton *interface_skeleton = g_object_new (user_extension_skeleton_get_type (), NULL); + g_dbus_object_skeleton_add_interface (object, interface_skeleton); } } @@ -998,10 +1025,12 @@ on_user_property_notify (User *user) } void -user_register (User *user) +user_register (User *user, + GDBusObjectManagerServer *object_manager) { g_autoptr (GError) error = NULL; g_autofree gchar *object_path = NULL; + g_autoptr (GDBusObjectSkeleton) object = NULL; user->system_bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (user->system_bus_connection == NULL) { @@ -1011,17 +1040,13 @@ user_register (User *user) } object_path = compute_object_path (user); + object = g_dbus_object_skeleton_new (object_path); - if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (user), - user->system_bus_connection, - object_path, - &error)) { - if (error != NULL) - g_critical ("error exporting user object: %s", error->message); - return; - } + g_dbus_object_skeleton_add_interface (object, G_DBUS_INTERFACE_SKELETON (user)); + g_dbus_object_manager_server_export (object_manager, object); + user->object_manager = g_object_ref (G_DBUS_OBJECT_MANAGER (object_manager)); - user_register_extensions (user); + user_register_extensions (user, object); g_signal_connect (G_OBJECT (user), "notify", G_CALLBACK (on_user_property_notify), NULL); } @@ -1035,24 +1060,26 @@ user_save (User *user) void user_unregister (User *user) { - g_signal_handlers_disconnect_by_func (G_OBJECT (user), G_CALLBACK (on_user_property_notify), NULL); - - g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (user)); - - if (user->extension_ids) { - guint i; + GHashTable *extensions; + GHashTableIter iter; + g_autofree gchar *object_path = NULL; + g_autoptr (GDBusObjectSkeleton) object = NULL; - for (i = 0; i < user->n_extension_ids; i++) { - /* In theory, if an error happened during registration, we could have 0 here. */ - if (user->extension_ids[i] == 0) - continue; + g_signal_handlers_disconnect_by_func (G_OBJECT (user), G_CALLBACK (on_user_property_notify), NULL); + extensions = daemon_get_extension_ifaces (user->daemon); - g_dbus_connection_unregister_object (user->system_bus_connection, user->extension_ids[i]); - } + object_path = compute_object_path (user); + object = G_DBUS_OBJECT_SKELETON (g_dbus_object_manager_get_object (user->object_manager, object_path)); + if (object) { + const char *interface_name; + g_hash_table_iter_init (&iter, extensions); + while (g_hash_table_iter_next (&iter, (gpointer) &interface_name, NULL)) + g_dbus_object_skeleton_remove_interface_by_name (object, interface_name); - g_clear_pointer (&user->extension_ids, g_free); - user->n_extension_ids = 0; + g_dbus_object_manager_server_unexport (G_DBUS_OBJECT_MANAGER_SERVER (user->object_manager), object_path); } + + g_clear_object (&user->object_manager); } void @@ -71,7 +71,8 @@ void user_set_cached (User *user, void user_set_saved (User *user, gboolean saved); -void user_register (User *user); +void user_register (User *user, + GDBusObjectManagerServer *manager); void user_unregister (User *user); void user_changed (User *user); |