summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2010-08-17 15:04:30 -0400
committerRay Strode <rstrode@redhat.com>2010-08-17 15:04:30 -0400
commit37a4edafbc79bbd76f49f4d3cdc1abffe062a511 (patch)
treeeece8388c8a577ffcc2f48f2a05d6cb0784f079f
parent9310418c63258dfd70cef46e2682cd9adc6c8f21 (diff)
downloadgdm-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.c53
-rw-r--r--gui/simple-greeter/gdm-user.c90
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