From 5efc993ee40b4fb326a8b5bc9c1180eaef0a2469 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Tue, 5 Jul 2011 16:10:58 +1000 Subject: Integrate with LightDM --- src/users-service-dbus.c | 561 +++++++++++------------------------------------ 1 file changed, 132 insertions(+), 429 deletions(-) (limited to 'src/users-service-dbus.c') diff --git a/src/users-service-dbus.c b/src/users-service-dbus.c index 11ee497..e232b37 100644 --- a/src/users-service-dbus.c +++ b/src/users-service-dbus.c @@ -31,10 +31,9 @@ #include #include "dbus-shared-names.h" -#include "gdm-local-display-factory-client.h" +#include "display-manager-client.h" #include "users-service-dbus.h" -#include "users-service-client.h" -#include "users-service-marshal.h" +#include "accounts-service-client.h" #include "consolekit-manager-client.h" #include "consolekit-session-client.h" @@ -46,21 +45,17 @@ static void users_service_dbus_class_init (UsersServiceDbusClass *kl static void users_service_dbus_init (UsersServiceDbus *self); static void users_service_dbus_dispose (GObject *object); static void users_service_dbus_finalize (GObject *object); -static void create_gdm_proxy (UsersServiceDbus *self); +static void create_display_manager_proxy (UsersServiceDbus *self); +static void create_accounts_service_proxy (UsersServiceDbus *self); static void create_seat_proxy (UsersServiceDbus *self); static void create_ck_proxy (UsersServiceDbus *self); static void create_cksession_proxy (UsersServiceDbus *self); static gchar *get_seat (UsersServiceDbus *service); -static void users_loaded (DBusGProxy *proxy, - gpointer user_data); static void user_added (DBusGProxy *proxy, - gint64 uid, - gpointer user_data); -static void user_removed (DBusGProxy *proxy, - gint64 uid, + const gchar *user_id, gpointer user_data); -static void user_updated (DBusGProxy *proxy, - guint uid, +static void user_deleted (DBusGProxy *proxy, + const gchar *user_id, gpointer user_data); static void seat_proxy_session_added (DBusGProxy *seat_proxy, const gchar *session_id, @@ -68,6 +63,7 @@ static void seat_proxy_session_added (DBusGProxy *seat_ static void seat_proxy_session_removed (DBusGProxy *seat_proxy, const gchar *session_id, UsersServiceDbus *service); +static void sync_users (UsersServiceDbus *self); static gboolean do_add_session (UsersServiceDbus *service, UserData *user, const gchar *ssid); @@ -85,8 +81,8 @@ struct _UsersServiceDbusPrivate DBusGConnection *system_bus; - DBusGProxy *gdm_proxy; - DBusGProxy *gdm_local_proxy; + DBusGProxy *accounts_service_proxy; + DBusGProxy *display_manager_proxy; DBusGProxy *ck_proxy; DBusGProxy *seat_proxy; DBusGProxy *session_proxy; @@ -102,10 +98,8 @@ struct _UsersServiceDbusPrivate /* Signals */ enum { - USERS_LOADED, USER_ADDED, - USER_REMOVED, - USER_UPDATED, + USER_DELETED, LAST_SIGNAL }; @@ -124,37 +118,21 @@ users_service_dbus_class_init (UsersServiceDbusClass *klass) object_class->dispose = users_service_dbus_dispose; object_class->finalize = users_service_dbus_finalize; - signals[USERS_LOADED] = g_signal_new ("users-loaded", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (UsersServiceDbusClass, users_loaded), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[USER_ADDED] = g_signal_new ("user-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (UsersServiceDbusClass, user_added), NULL, NULL, - _users_service_marshal_VOID__INT64, - G_TYPE_NONE, 1, G_TYPE_INT64); + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); - signals[USER_REMOVED] = g_signal_new ("user-removed", + signals[USER_DELETED] = g_signal_new ("user-deleted", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (UsersServiceDbusClass, user_removed), + G_STRUCT_OFFSET (UsersServiceDbusClass, user_deleted), NULL, NULL, - _users_service_marshal_VOID__INT64, - G_TYPE_NONE, 1, G_TYPE_INT64); - - signals[USER_UPDATED] = g_signal_new ("user-updated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (UsersServiceDbusClass, user_updated), - NULL, NULL, - _users_service_marshal_VOID__INT64, - G_TYPE_NONE, 1, G_TYPE_INT64); + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); } static void @@ -188,17 +166,10 @@ users_service_dbus_init (UsersServiceDbus *self) g_free, NULL); - dbus_g_object_register_marshaller (_users_service_marshal_VOID__INT64, - G_TYPE_NONE, - G_TYPE_INT64, - G_TYPE_INVALID); - - create_gdm_proxy (self); create_ck_proxy (self); create_seat_proxy (self); - - if (priv->gdm_proxy) - users_loaded (priv->gdm_proxy, self); + create_display_manager_proxy (self); + create_accounts_service_proxy (self); } static void @@ -221,75 +192,75 @@ users_service_dbus_finalize (GObject *object) } static void -create_gdm_proxy (UsersServiceDbus *self) +create_display_manager_proxy (UsersServiceDbus *self) { UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GError *error = NULL; - priv->gdm_proxy = dbus_g_proxy_new_for_name_owner (priv->system_bus, - "org.gnome.DisplayManager", - "/org/gnome/DisplayManager/UserManager", - "org.gnome.DisplayManager.UserManager", - &error); + priv->display_manager_proxy = dbus_g_proxy_new_for_name (priv->system_bus, + "org.freedesktop.DisplayManager", + "/org/freedesktop/DisplayManager", + "org.freedesktop.DisplayManager"); - if (!priv->gdm_proxy) + if (!priv->display_manager_proxy) { - if (error != NULL) - { - g_warning ("Unable to get DisplayManager proxy on system bus: %s", error->message); - g_error_free (error); - } - + g_warning ("Failed to get DisplayManager proxy."); return; } +} - dbus_g_proxy_add_signal (priv->gdm_proxy, - "UsersLoaded", - G_TYPE_INVALID); +static void +create_accounts_service_proxy (UsersServiceDbus *self) +{ + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + GPtrArray *users = g_ptr_array_new (); + GError *error = NULL; + + priv->accounts_service_proxy = dbus_g_proxy_new_for_name (priv->system_bus, + "org.freedesktop.Accounts", + "/org/freedesktop/Accounts", + "org.freedesktop.Accounts"); - dbus_g_proxy_add_signal (priv->gdm_proxy, + dbus_g_proxy_add_signal (priv->accounts_service_proxy, "UserAdded", - G_TYPE_INT64, + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->gdm_proxy, - "UserRemoved", - G_TYPE_INT64, + dbus_g_proxy_add_signal (priv->accounts_service_proxy, + "UserChanged", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->gdm_proxy, - "UserUpdated", - G_TYPE_INT64, + dbus_g_proxy_add_signal (priv->accounts_service_proxy, + "UserDeleted", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->gdm_proxy, - "UsersLoaded", - G_CALLBACK (users_loaded), - self, - NULL); - - dbus_g_proxy_connect_signal (priv->gdm_proxy, + dbus_g_proxy_connect_signal (priv->accounts_service_proxy, "UserAdded", G_CALLBACK (user_added), self, NULL); - dbus_g_proxy_connect_signal (priv->gdm_proxy, - "UserRemoved", - G_CALLBACK (user_removed), + dbus_g_proxy_connect_signal (priv->accounts_service_proxy, + "UserDeleted", + G_CALLBACK (user_deleted), self, NULL); - dbus_g_proxy_connect_signal (priv->gdm_proxy, - "UserUpdated", - G_CALLBACK (user_updated), - self, - NULL); + if (!org_freedesktop_Accounts_list_cached_users (priv->accounts_service_proxy, + &users, + &error)) + { + g_warning ("failed to retrieve user count: %s", error->message); + g_error_free (error); - priv->gdm_local_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.gnome.DisplayManager", - "/org/gnome/DisplayManager/LocalDisplayFactory", - "org.gnome.DisplayManager.LocalDisplayFactory"); + return; + } + + priv->count = users->len; + g_ptr_array_free (users, TRUE); + + sync_users (self); } static void @@ -615,11 +586,9 @@ seat_proxy_session_added (DBusGProxy *seat_proxy, return; } - user = g_hash_table_lookup (priv->users, pwent->pw_name); + user = users_service_dbus_get_user_by_username (service, pwent->pw_name); if (!user) - { - return; - } + return; res = do_add_session (service, user, session_id); } @@ -648,7 +617,7 @@ seat_proxy_session_removed (DBusGProxy *seat_proxy, return; } - user = g_hash_table_lookup (priv->users, username); + user = users_service_dbus_get_user_by_username (service, username); if (!user) return; @@ -684,16 +653,15 @@ sync_users (UsersServiceDbus *self) if (priv->count > MINIMUM_USERS && priv->count < MAXIMUM_USERS) { - GArray *uids = NULL; - GPtrArray *users_info = NULL; + GPtrArray *users = NULL; GError *error = NULL; gint i; - uids = g_array_new (FALSE, FALSE, sizeof (gint64)); + users = g_ptr_array_new (); - if (!org_gnome_DisplayManager_UserManager_get_user_list (priv->gdm_proxy, - &uids, - &error)) + if (!org_freedesktop_Accounts_list_cached_users (priv->accounts_service_proxy, + &users, + &error)) { g_warning ("failed to retrieve user list: %s", error->message); g_error_free (error); @@ -701,374 +669,101 @@ sync_users (UsersServiceDbus *self) return; } - users_info = g_ptr_array_new (); - - if (!org_gnome_DisplayManager_UserManager_get_users_info (priv->gdm_proxy, - uids, - &users_info, - &error)) + for (i = 0; i < users->len; i++) { - g_warning ("failed to retrieve user info: %s", error->message); - g_error_free (error); + gchar *id; + DBusGProxy *proxy; + UserData *user; + GError *error = NULL; - return; - } + id = g_ptr_array_index (users, i); - for (i = 0; i < users_info->len; i++) - { - GValueArray *values; - UserData *user; + proxy = dbus_g_proxy_new_for_name (priv->system_bus, + "org.freedesktop.Accounts", + id, + "org.freedesktop.DBus.Properties"); - values = g_ptr_array_index (users_info, i); + GHashTable *properties; + if (!dbus_g_proxy_call (proxy, "GetAll", &error, + G_TYPE_STRING, "org.freedesktop.Accounts.User", G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &properties, G_TYPE_INVALID)) + { + g_warning ("unable to retrieve user info: %s", error->message); + g_error_free (error); + + continue; + } user = g_new0 (UserData, 1); - user->uid = g_value_get_int64 (g_value_array_get_nth (values, 0)); - user->user_name = g_strdup (g_value_get_string (g_value_array_get_nth (values, 1))); - user->real_name = g_strdup (g_value_get_string (g_value_array_get_nth (values, 2))); - user->shell = g_strdup (g_value_get_string (g_value_array_get_nth (values, 3))); - user->login_count = g_value_get_int (g_value_array_get_nth (values, 4)); - user->icon_url = g_strdup (g_value_get_string (g_value_array_get_nth (values, 5))); + user->uid = g_value_get_uint64 (g_hash_table_lookup (properties, "Uid")); + user->user_name = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "UserName"))); + user->real_name = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "RealName"))); + user->icon_file = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "IconFile"))); user->real_name_conflict = FALSE; user->menuitem = NULL; + g_hash_table_unref (properties); + g_hash_table_insert (priv->users, - g_strdup (user->user_name), + g_strdup (id), user); add_sessions_for_user (self, user); } - } -} - -static void -users_loaded (DBusGProxy *proxy, - gpointer user_data) -{ - UsersServiceDbus *service; - UsersServiceDbusPrivate *priv; - GError *error = NULL; - gint count; - - g_return_if_fail (proxy != NULL); - - service = (UsersServiceDbus *)user_data; - priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - - if (!org_gnome_DisplayManager_UserManager_count_users (proxy, - &count, - &error)) - { - g_warning ("failed to retrieve user count: %s", error->message); - g_error_free (error); - - return; - } - - priv->count = count; - - sync_users (service); -} - -static gboolean -session_is_login_window (UsersServiceDbus *self, - const char *ssid) -{ - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - DBusGProxy *proxy = NULL; - GError *error = NULL; - char *type = NULL; - - if (!(proxy = dbus_g_proxy_new_for_name (priv->system_bus, - CK_ADDR, - ssid, - CK_SESSION_IFACE))) - { - g_warning ("Failed to get ConsoleKit proxy"); - - return FALSE; - } - - if (!org_freedesktop_ConsoleKit_Session_get_session_type (proxy, &type, &error)) - { - g_warning ("Can't call GetSessionType: %s", error->message); - g_error_free (error); - - if (proxy) - g_object_unref (proxy); - - return FALSE; - } - - if (proxy) - g_object_unref (proxy); - - return (type && type[0] != '\0' && strcmp (type, "LoginWindow") == 0); -} - -static char * -get_login_session (UsersServiceDbus *self) -{ - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), NULL); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - gboolean can_activate; - GError *error = NULL; - GPtrArray *sessions = NULL; - char *ssid = NULL; - int i; - - if (!priv->seat || priv->seat[0] == '\0') - { - return NULL; - } - - if (!dbus_g_proxy_call (priv->seat_proxy, - "CanActivateSessions", - &error, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &can_activate, - G_TYPE_INVALID)) - { - g_warning ("Failed to call CanActivateSessions: %s", error->message); - g_error_free (error); - - return NULL; - } - - if (!can_activate) - { - return NULL; - } - - error = NULL; - if (!dbus_g_proxy_call (priv->seat_proxy, - "GetSessions", - &error, - G_TYPE_INVALID, - dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions, - G_TYPE_INVALID)) - { - g_warning ("Failed to call GetSessions: %s", error->message); - g_error_free (error); - - return NULL; - } - - for (i = 0; i < sessions->len; i++) - { - char *s = g_ptr_array_index (sessions, i); - - if (session_is_login_window (self, s)) - { - ssid = g_strdup (s); - break; - } - } - - g_ptr_array_foreach (sessions, (GFunc)g_free, NULL); - g_ptr_array_free (sessions, TRUE); - - return ssid; -} - -static gboolean -activate_user_session (UsersServiceDbus *self, - const char *seat, - const char *ssid) -{ - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - DBusMessage *message = NULL; - DBusMessage *reply = NULL; - DBusError error; - - if (!(message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", - seat, - "org.freedesktop.ConsoleKit.Seat", - "ActivateSession"))) - { - return FALSE; - } - - if (!dbus_message_append_args (message, - DBUS_TYPE_OBJECT_PATH, &ssid, - DBUS_TYPE_INVALID)) - { - return FALSE; - } - - dbus_error_init (&error); - if (!(reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (priv->system_bus), - message, - -1, - &error))) - { - if (dbus_error_is_set (&error)) - { - g_warning ("Can't activate session: %s", error.message); - dbus_error_free (&error); - - return FALSE; - } - } - - if (message) - { - dbus_message_unref (message); - } - if (reply) - { - dbus_message_unref (reply); + g_ptr_array_free (users, TRUE); } - - return TRUE; -} - -gboolean -start_new_user_session (UsersServiceDbus *self, - UserData *user) -{ - g_return_val_if_fail (IS_USERS_SERVICE_DBUS (self), FALSE); - - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GError *error = NULL; - char *ssid; - - ssid = get_login_session (self); - if (ssid) - { - if (!activate_user_session (self, priv->seat, ssid)) - { - return FALSE; - } - } - - if (!g_spawn_command_line_async ("gdmflexiserver -s", &error)) - { - g_warning ("Failed to start new login session: %s", error->message); - g_error_free (error); - - return FALSE; - } - - return TRUE; } static void -user_added (DBusGProxy *proxy, - gint64 uid, - gpointer user_data) +user_added (DBusGProxy *proxy, + const gchar *user_id, + gpointer user_data) { UsersServiceDbus *service = (UsersServiceDbus *)user_data; UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - UserData *user = g_new0 (UserData, 1); - GError *error = NULL; priv->count++; if (priv->count < MAXIMUM_USERS) { - if ((priv->count - g_hash_table_size (priv->users)) > 1) - { - sync_users (service); - } - else - { - if (!org_gnome_DisplayManager_UserManager_get_user_info (proxy, - uid, - &user->user_name, - &user->real_name, - &user->shell, - &user->login_count, - &user->icon_url, - &error)) - { - g_warning ("unable to retrieve user info: %s", error->message); - g_error_free (error); - - g_free (user); - - return; - } - - user->uid = uid; - - g_hash_table_insert (priv->users, - g_strdup (user->user_name), - user); - - g_signal_emit (G_OBJECT (service), signals[USER_ADDED], 0, user, TRUE); - } + sync_users (service); } } -static gboolean -compare_users_by_uid (gpointer key, - gpointer value, - gpointer user_data) -{ - return (GPOINTER_TO_UINT (value) == GPOINTER_TO_UINT (user_data)); -} - static void -user_removed (DBusGProxy *proxy, - gint64 uid, - gpointer user_data) +user_deleted (DBusGProxy *proxy, + const gchar *user_id, + gpointer user_data) { UsersServiceDbus *service = (UsersServiceDbus *)user_data; UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - UserData *user; - gint size; - - size = g_hash_table_size (priv->users); priv->count--; - - if (size == 0 || (size - priv->count) > 1) - { - sync_users (service); - } - else - { - user = g_hash_table_find (priv->users, - compare_users_by_uid, - GUINT_TO_POINTER ((gint)uid)); - - if (user != NULL) - { - g_hash_table_remove (priv->users, - user->user_name); - } - } + g_hash_table_remove (priv->users, user_id); } -static void -user_updated (DBusGProxy *proxy, - guint uid, - gpointer user_data) +UserData * +users_service_dbus_get_user_by_username (UsersServiceDbus *self, + const gchar *username) { -#if 0 - // XXX - TODO - UsersServiceDbus *service = (UsersServiceDbus *)user_data; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - UserData *user; + GHashTableIter iter; + gpointer value; - user = g_hash_table_find (priv->users, - compare_users_by_uid, - GUINT_TO_POINTER (uid)); -#endif -} - -gint -users_service_dbus_get_user_count (UsersServiceDbus *self) -{ - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), 0); + g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), NULL); UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return priv->count; + g_hash_table_iter_init (&iter, priv->users); + while (g_hash_table_iter_next (&iter, NULL, &value)) + { + UserData *user = value; + if (strcmp (user->user_name, username) == 0) + return user; + } + + return NULL; } GList * @@ -1081,13 +776,21 @@ users_service_dbus_get_user_list (UsersServiceDbus *self) return g_hash_table_get_values (priv->users); } +gboolean +users_service_dbus_show_greeter (UsersServiceDbus *self) +{ + g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); + UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + return org_freedesktop_DisplayManager_show_greeter(priv->display_manager_proxy, NULL); +} + /* Activates the guest account if it can. */ gboolean users_service_dbus_activate_guest_session (UsersServiceDbus *self) { g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return org_gnome_DisplayManager_LocalDisplayFactory_switch_to_user(priv->gdm_local_proxy, "guest", NULL, NULL); + return org_freedesktop_DisplayManager_switch_to_guest(priv->display_manager_proxy, NULL); } /* Activates a specific user */ @@ -1097,7 +800,7 @@ users_service_dbus_activate_user_session (UsersServiceDbus *self, { g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return org_gnome_DisplayManager_LocalDisplayFactory_switch_to_user(priv->gdm_local_proxy, user->user_name, NULL, NULL); + return org_freedesktop_DisplayManager_switch_to_user(priv->display_manager_proxy, user->user_name, NULL); } gboolean -- cgit v1.2.3