diff options
author | Ray Strode <rstrode@redhat.com> | 2010-08-17 15:04:30 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2010-08-17 15:04:30 -0400 |
commit | 37a4edafbc79bbd76f49f4d3cdc1abffe062a511 (patch) | |
tree | eece8388c8a577ffcc2f48f2a05d6cb0784f079f | |
parent | 9310418c63258dfd70cef46e2682cd9adc6c8f21 (diff) | |
download | gdm-37a4edafbc79bbd76f49f4d3cdc1abffe062a511.tar.gz |
Load user properties from account service asynchronously
Previously, we would do a blocking GetAll() call when a new
user was reported by the accounts daemon.
Now, we initiate a non-blocking GetAll() call defer processing
the user until the GetAll call finishes.
-rw-r--r-- | gui/simple-greeter/gdm-user-manager.c | 53 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-user.c | 90 |
2 files changed, 110 insertions, 33 deletions
diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c index 92a0421e..4dbfcbe3 100644 --- a/gui/simple-greeter/gdm-user-manager.c +++ b/gui/simple-greeter/gdm-user-manager.c @@ -144,6 +144,7 @@ struct GdmUserManagerPrivate GdmUserManagerSeat seat; GSList *new_sessions; + GSList *new_users; GFileMonitor *passwd_monitor; GFileMonitor *shells_monitor; @@ -757,22 +758,21 @@ remove_user (GdmUserManager *manager, } static void -add_new_user_for_object_path (const char *object_path, - GdmUserManager *manager) +on_new_user_changed (GdmUser *user, + GdmUserManager *manager) { - GdmUser *user; const char *username; - if (g_hash_table_lookup (manager->priv->users_by_object_path, object_path)) { - return; - } - user = gdm_user_new_from_object_path (object_path); + username = gdm_user_get_user_name (user); - if (user == NULL) { + if (username == NULL) { return; } - username = gdm_user_get_user_name (user); + g_signal_handlers_disconnect_by_func (user, on_new_user_changed, manager); + manager->priv->new_users = g_slist_remove (manager->priv->new_users, + user); + if (username_in_exclude_list (manager, username)) { g_debug ("GdmUserManager: excluding user '%s'", username); g_object_unref (user); @@ -784,6 +784,26 @@ add_new_user_for_object_path (const char *object_path, } static void +add_new_user_for_object_path (const char *object_path, + GdmUserManager *manager) +{ + GdmUser *user; + + if (g_hash_table_lookup (manager->priv->users_by_object_path, object_path)) { + return; + } + user = gdm_user_new_from_object_path (object_path); + + if (user == NULL) { + return; + } + + manager->priv->new_users = g_slist_prepend (manager->priv->new_users, user); + + g_signal_connect (user, "changed", G_CALLBACK (on_new_user_changed), manager); +} + +static void on_new_user_in_accounts_service (DBusGProxy *proxy, const char *object_path, gpointer user_data) @@ -2710,6 +2730,7 @@ static void gdm_user_manager_finalize (GObject *object) { GdmUserManager *manager; + GSList *node; g_return_if_fail (object != NULL); g_return_if_fail (GDM_IS_USER_MANAGER (object)); @@ -2727,6 +2748,20 @@ gdm_user_manager_finalize (GObject *object) (GFunc) unload_new_session, NULL); g_slist_free (manager->priv->new_sessions); + node = manager->priv->new_users; + while (node != NULL) { + GdmUser *user; + GSList *next_node; + + user = GDM_USER (node->data); + next_node = node->next; + + g_signal_handlers_disconnect_by_func (user, on_new_user_changed, manager); + g_object_unref (user); + manager->priv->new_users = g_slist_delete_link (manager->priv->new_users, node); + node = next_node; + } + unload_seat (manager); if (manager->priv->exclude_usernames != NULL) { diff --git a/gui/simple-greeter/gdm-user.c b/gui/simple-greeter/gdm-user.c index 8227ff8f..037b7e7f 100644 --- a/gui/simple-greeter/gdm-user.c +++ b/gui/simple-greeter/gdm-user.c @@ -56,6 +56,8 @@ struct _GdmUser { DBusGConnection *connection; DBusGProxy *accounts_proxy; + DBusGProxy *object_proxy; + DBusGProxyCall *get_all_call; char *object_path; uid_t uid; @@ -195,6 +197,10 @@ gdm_user_finalize (GObject *object) g_object_unref (user->accounts_proxy); } + if (user->object_proxy != NULL) { + g_object_unref (user->object_proxy); + } + if (user->connection != NULL) { dbus_g_connection_unref (user->connection); } @@ -840,41 +846,77 @@ collect_props (const gchar *key, } } -static gboolean -update_info (GdmUser *user) +static void +on_get_all_finished (DBusGProxy *proxy, + DBusGProxyCall *call, + GdmUser *user) { - GError *error; - DBusGProxy *proxy; - GHashTable *hash_table; - gboolean retval; + GError *error; + GHashTable *hash_table; + gboolean res; - proxy = dbus_g_proxy_new_for_name (user->connection, - USER_ACCOUNTS_NAME, - user->object_path, - DBUS_INTERFACE_PROPERTIES); + g_assert (user->get_all_call == call); + g_assert (user->object_proxy == proxy); error = NULL; - if (!dbus_g_proxy_call (proxy, - "GetAll", - &error, - G_TYPE_STRING, - USER_ACCOUNTS_INTERFACE, - G_TYPE_INVALID, - dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), - &hash_table, - G_TYPE_INVALID)) { - g_debug ("Error calling GetAll() when retrieving properties for %s: %s", user->object_path, error->message); + res = dbus_g_proxy_end_call (proxy, + call, + &error, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &hash_table, + G_TYPE_INVALID); + user->get_all_call = NULL; + user->object_proxy = NULL; + + if (! res) { + g_debug ("Error calling GetAll() when retrieving properties for %s: %s", + user->object_path, error->message); g_error_free (error); - retval = FALSE; goto out; } g_hash_table_foreach (hash_table, (GHFunc) collect_props, user); g_hash_table_unref (hash_table); - retval = TRUE; - out: +out: g_object_unref (proxy); - return retval; +} + +static gboolean +update_info (GdmUser *user) +{ + DBusGProxy *proxy; + DBusGProxyCall *call; + + proxy = dbus_g_proxy_new_for_name (user->connection, + USER_ACCOUNTS_NAME, + user->object_path, + DBUS_INTERFACE_PROPERTIES); + + call = dbus_g_proxy_begin_call (proxy, + "GetAll", + (DBusGProxyCallNotify) + on_get_all_finished, + user, + NULL, + G_TYPE_STRING, + USER_ACCOUNTS_INTERFACE, + G_TYPE_INVALID); + + if (call == NULL) { + g_warning ("GdmUser: failed to make GetAll call"); + goto failed; + } + + user->get_all_call = call; + user->object_proxy = proxy; + return TRUE; + +failed: + if (proxy != NULL) { + g_object_unref (proxy); + } + + return FALSE; } static void |