Blame SOURCES/0013-lib-only-track-users-after-act_user_manager_list_use.patch

34a24a
From b1ec3114a49c9e5331a4f7c106a58867499ac1ce Mon Sep 17 00:00:00 2001
34a24a
From: Ray Strode <rstrode@redhat.com>
34a24a
Date: Wed, 4 Oct 2017 11:28:50 -0400
34a24a
Subject: [PATCH 13/13] lib: only track users after act_user_manager_list_users
34a24a
34a24a
At the moment, as soon as someone calls
34a24a
act_user_manager_get_default() we end up firing of an asynchronous
34a24a
call to get a list of all users. This is problematic since not all
34a24a
programs using accountsservice want a list of users.
34a24a
34a24a
This commit changes the code to only get a list of users when the
34a24a
caller invokes act_user_manager_list_users.  This does mean some calls
34a24a
that were async before are synchronous now, but user proxies were
34a24a
always obtained synchronously, and they're by far the slowest part
34a24a
of listing users, so I don't expect this introduce any noticeable
34a24a
blocking.
34a24a
34a24a
Longer term, to fix the sync i/o bits, I think we should
34a24a
probably ditch libaccountsservice and just make accountsservice use
34a24a
ObjectManager interfaces over d-bus.
34a24a
---
34a24a
 src/libaccountsservice/act-user-manager.c | 145 +++++++++++++++---------------
34a24a
 1 file changed, 75 insertions(+), 70 deletions(-)
34a24a
34a24a
diff --git a/src/libaccountsservice/act-user-manager.c b/src/libaccountsservice/act-user-manager.c
34a24a
index 11049e0..d0b38e2 100644
34a24a
--- a/src/libaccountsservice/act-user-manager.c
34a24a
+++ b/src/libaccountsservice/act-user-manager.c
34a24a
@@ -172,92 +172,93 @@ typedef struct
34a24a
         };
34a24a
         char                       *object_path;
34a24a
         char                       *description;
34a24a
 } ActUserManagerFetchUserRequest;
34a24a
 
34a24a
 struct ActUserManagerPrivate
34a24a
 {
34a24a
         GHashTable            *normal_users_by_name;
34a24a
         GHashTable            *system_users_by_name;
34a24a
         GHashTable            *users_by_object_path;
34a24a
         GHashTable            *sessions;
34a24a
         GDBusConnection       *connection;
34a24a
         AccountsAccounts      *accounts_proxy;
34a24a
         ConsoleKitManager     *ck_manager_proxy;
34a24a
 
34a24a
         ActUserManagerSeat     seat;
34a24a
 
34a24a
         GSList                *new_sessions;
34a24a
         GSList                *new_users;
34a24a
         GSList                *new_users_inhibiting_load;
34a24a
         GSList                *fetch_user_requests;
34a24a
 
34a24a
         GSList                *exclude_usernames;
34a24a
         GSList                *include_usernames;
34a24a
 
34a24a
         guint                  load_id;
34a24a
 
34a24a
         gboolean               is_loaded;
34a24a
         gboolean               has_multiple_users;
34a24a
         gboolean               getting_sessions;
34a24a
-        gboolean               listing_cached_users;
34a24a
         gboolean               list_cached_users_done;
34a24a
 };
34a24a
 
34a24a
 enum {
34a24a
         PROP_0,
34a24a
         PROP_INCLUDE_USERNAMES_LIST,
34a24a
         PROP_EXCLUDE_USERNAMES_LIST,
34a24a
         PROP_IS_LOADED,
34a24a
         PROP_HAS_MULTIPLE_USERS
34a24a
 };
34a24a
 
34a24a
 enum {
34a24a
         USER_ADDED,
34a24a
         USER_REMOVED,
34a24a
         USER_IS_LOGGED_IN_CHANGED,
34a24a
         USER_CHANGED,
34a24a
         LAST_SIGNAL
34a24a
 };
34a24a
 
34a24a
 static guint signals [LAST_SIGNAL] = { 0, };
34a24a
 
34a24a
 static void     act_user_manager_class_init (ActUserManagerClass *klass);
34a24a
 static void     act_user_manager_init       (ActUserManager      *user_manager);
34a24a
 static void     act_user_manager_finalize   (GObject             *object);
34a24a
 
34a24a
 static gboolean ensure_accounts_proxy       (ActUserManager *manager);
34a24a
 static gboolean load_seat_incrementally     (ActUserManager *manager);
34a24a
 static void     unload_seat                 (ActUserManager *manager);
34a24a
 static void     load_users                  (ActUserManager *manager);
34a24a
+static void     load_user                   (ActUserManager *manager,
34a24a
+                                             const char     *username);
34a24a
 static void     act_user_manager_queue_load (ActUserManager *manager);
34a24a
-static void     queue_load_seat_and_users   (ActUserManager *manager);
34a24a
+static void     queue_load_seat             (ActUserManager *manager);
34a24a
 
34a24a
 static void     load_new_session_incrementally (ActUserManagerNewSession *new_session);
34a24a
 static void     set_is_loaded (ActUserManager *manager, gboolean is_loaded);
34a24a
 
34a24a
 static void     on_new_user_loaded (ActUser        *user,
34a24a
                                     GParamSpec     *pspec,
34a24a
                                     ActUserManager *manager);
34a24a
 static void     give_up (ActUserManager                 *manager,
34a24a
                          ActUserManagerFetchUserRequest *request);
34a24a
 static void     fetch_user_incrementally       (ActUserManagerFetchUserRequest *request);
34a24a
 
34a24a
 static void     maybe_set_is_loaded            (ActUserManager *manager);
34a24a
 static void     update_user                    (ActUserManager *manager,
34a24a
                                                 ActUser        *user);
34a24a
 static gpointer user_manager_object = NULL;
34a24a
 
34a24a
 G_DEFINE_TYPE (ActUserManager, act_user_manager, G_TYPE_OBJECT)
34a24a
 
34a24a
 static const GDBusErrorEntry error_entries[] = {
34a24a
         { ACT_USER_MANAGER_ERROR_FAILED,              "org.freedesktop.Accounts.Error.Failed" },
34a24a
         { ACT_USER_MANAGER_ERROR_USER_EXISTS,         "org.freedesktop.Accounts.Error.UserExists" },
34a24a
         { ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" },
34a24a
         { ACT_USER_MANAGER_ERROR_PERMISSION_DENIED,   "org.freedesktop.Accounts.Error.PermissionDenied" },
34a24a
         { ACT_USER_MANAGER_ERROR_NOT_SUPPORTED,       "org.freedesktop.Accounts.Error.NotSupported" }
34a24a
 };
34a24a
 
34a24a
 GQuark
34a24a
 act_user_manager_error_quark (void)
34a24a
 {
34a24a
         static volatile gsize ret = 0;
34a24a
@@ -711,91 +712,87 @@ on_get_seat_id_finished (GObject        *object,
34a24a
                          GAsyncResult   *result,
34a24a
                          gpointer        data)
34a24a
 {
34a24a
         ConsoleKitSession *proxy = CONSOLE_KIT_SESSION (object);
34a24a
         ActUserManager    *manager = data;
34a24a
         GError            *error = NULL;
34a24a
         char              *seat_id;
34a24a
 
34a24a
         if (!console_kit_session_call_get_seat_id_finish (proxy, &seat_id, result, &error)) {
34a24a
                 if (error != NULL) {
34a24a
                         g_debug ("Failed to identify the seat of the "
34a24a
                                  "current session: %s",
34a24a
                                  error->message);
34a24a
                         g_error_free (error);
34a24a
                 } else {
34a24a
                         g_debug ("Failed to identify the seat of the "
34a24a
                                  "current session");
34a24a
                 }
34a24a
 
34a24a
                 g_debug ("ActUserManager: GetSeatId call failed, so unloading seat");
34a24a
                 unload_seat (manager);
34a24a
 
34a24a
                 goto out;
34a24a
         }
34a24a
 
34a24a
         g_debug ("ActUserManager: Found current seat: %s", seat_id);
34a24a
 
34a24a
         manager->priv->seat.id = seat_id;
34a24a
         manager->priv->seat.state++;
34a24a
 
34a24a
-        load_seat_incrementally (manager);
34a24a
-
34a24a
  out:
34a24a
         g_debug ("ActUserManager: unrefing manager owned by GetSeatId request");
34a24a
         g_object_unref (manager);
34a24a
 }
34a24a
 
34a24a
 #ifdef WITH_SYSTEMD
34a24a
 static void
34a24a
 _get_systemd_seat_id (ActUserManager *manager)
34a24a
 {
34a24a
         int   res;
34a24a
         char *seat_id;
34a24a
 
34a24a
         res = sd_session_get_seat (NULL, &seat_id);
34a24a
 
34a24a
         if (res == -ENOENT) {
34a24a
                 seat_id = NULL;
34a24a
         } else if (res < 0) {
34a24a
                 g_warning ("Could not get current seat: %s",
34a24a
                            strerror (-res));
34a24a
                 unload_seat (manager);
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
         manager->priv->seat.id = g_strdup (seat_id);
34a24a
         free (seat_id);
34a24a
 
34a24a
         manager->priv->seat.state++;
34a24a
-
34a24a
-        queue_load_seat_incrementally (manager);
34a24a
 }
34a24a
 #endif
34a24a
 
34a24a
 static void
34a24a
 get_seat_id_for_current_session (ActUserManager *manager)
34a24a
 {
34a24a
 #ifdef WITH_SYSTEMD
34a24a
         if (LOGIND_RUNNING()) {
34a24a
                 _get_systemd_seat_id (manager);
34a24a
                 return;
34a24a
         }
34a24a
 #endif
34a24a
         console_kit_session_call_get_seat_id (manager->priv->seat.session_proxy,
34a24a
                                               NULL,
34a24a
                                               on_get_seat_id_finished,
34a24a
                                               g_object_ref (manager));
34a24a
 }
34a24a
 
34a24a
 static gint
34a24a
 match_name_cmpfunc (gconstpointer a,
34a24a
                     gconstpointer b)
34a24a
 {
34a24a
         return g_strcmp0 ((char *) a,
34a24a
                           (char *) b);
34a24a
 }
34a24a
 
34a24a
 static gboolean
34a24a
 username_in_exclude_list (ActUserManager *manager,
34a24a
                           const char     *username)
34a24a
 {
34a24a
@@ -1520,106 +1517,64 @@ load_user_paths (ActUserManager       *manager,
34a24a
         /* We now have a batch of unloaded users that we know about. Once that initial
34a24a
          * batch is loaded up, we can mark the manager as loaded.
34a24a
          *
34a24a
          * (see on_new_user_loaded)
34a24a
          */
34a24a
         if (g_strv_length ((char **) user_paths) > 0) {
34a24a
                 int i;
34a24a
 
34a24a
                 g_debug ("ActUserManager: ListCachedUsers finished, will set loaded property after list is fully loaded");
34a24a
                 for (i = 0; user_paths[i] != NULL; i++) {
34a24a
                         ActUser *user;
34a24a
 
34a24a
                         user = add_new_user_for_object_path (user_paths[i], manager);
34a24a
                         if (!manager->priv->is_loaded) {
34a24a
                                 manager->priv->new_users_inhibiting_load = g_slist_prepend (manager->priv->new_users_inhibiting_load, user);
34a24a
                         }
34a24a
                 }
34a24a
         } else {
34a24a
                 g_debug ("ActUserManager: ListCachedUsers finished with empty list, maybe setting loaded property now");
34a24a
                 maybe_set_is_loaded (manager);
34a24a
         }
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
 load_included_usernames (ActUserManager *manager)
34a24a
 {
34a24a
         GSList *l;
34a24a
 
34a24a
         /* Add users who are specifically included */
34a24a
         for (l = manager->priv->include_usernames; l != NULL; l = l->next) {
34a24a
-                ActUser *user;
34a24a
-
34a24a
                 g_debug ("ActUserManager: Adding included user %s", (char *)l->data);
34a24a
-                /*
34a24a
-                 * The call to act_user_manager_get_user will add the user if it is
34a24a
-                 * valid and not already in the hash.
34a24a
-                 */
34a24a
-                user = act_user_manager_get_user (manager, l->data);
34a24a
-                if (user == NULL) {
34a24a
-                        g_debug ("ActUserManager: unable to lookup user '%s'", (char *)l->data);
34a24a
-                }
34a24a
-        }
34a24a
-}
34a24a
-
34a24a
-static void
34a24a
-on_list_cached_users_finished (GObject      *object,
34a24a
-                               GAsyncResult *result,
34a24a
-                               gpointer      data)
34a24a
-{
34a24a
-        AccountsAccounts *proxy = ACCOUNTS_ACCOUNTS (object);
34a24a
-        ActUserManager   *manager = data;
34a24a
-        gchar           **user_paths;
34a24a
-        GError           *error = NULL;
34a24a
-
34a24a
-        manager->priv->listing_cached_users = FALSE;
34a24a
-        manager->priv->list_cached_users_done = TRUE;
34a24a
-
34a24a
-        if (!accounts_accounts_call_list_cached_users_finish (proxy, &user_paths, result, &error)) {
34a24a
-                g_debug ("ActUserManager: ListCachedUsers failed: %s", error->message);
34a24a
-                g_error_free (error);
34a24a
-
34a24a
-                g_object_unref (manager->priv->accounts_proxy);
34a24a
-                manager->priv->accounts_proxy = NULL;
34a24a
 
34a24a
-                g_debug ("ActUserManager: unrefing manager owned by failed ListCachedUsers call");
34a24a
-                g_object_unref (manager);
34a24a
-                return;
34a24a
+                load_user (manager, l->data);
34a24a
         }
34a24a
-
34a24a
-        load_user_paths (manager, (const char * const *) user_paths);
34a24a
-        g_strfreev (user_paths);
34a24a
-
34a24a
-        load_included_usernames (manager);
34a24a
-
34a24a
-        g_debug ("ActUserManager: unrefing manager owned by finished ListCachedUsers call");
34a24a
-        g_object_unref (manager);
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
 on_get_x11_display_finished (GObject      *object,
34a24a
                              GAsyncResult *result,
34a24a
                              gpointer      data)
34a24a
 {
34a24a
         ConsoleKitSession *proxy = CONSOLE_KIT_SESSION (object);
34a24a
         ActUserManagerNewSession *new_session = data;
34a24a
         GError            *error = NULL;
34a24a
         char              *x11_display;
34a24a
 
34a24a
         new_session->pending_calls--;
34a24a
 
34a24a
         if (new_session->cancellable == NULL || g_cancellable_is_cancelled (new_session->cancellable)) {
34a24a
                 unload_new_session (new_session);
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
         if (!console_kit_session_call_get_x11_display_finish (proxy, &x11_display, result, &error)) {
34a24a
                 if (error != NULL) {
34a24a
                         g_debug ("Failed to get the x11 display of session '%s': %s",
34a24a
                                  new_session->id, error->message);
34a24a
                         g_error_free (error);
34a24a
                 } else {
34a24a
                         g_debug ("Failed to get the x11 display of session '%s'",
34a24a
                                  new_session->id);
34a24a
                 }
34a24a
                 unload_new_session (new_session);
34a24a
                 return;
34a24a
@@ -2361,60 +2316,99 @@ fetch_user_with_id_from_accounts_service (ActUserManager *manager,
34a24a
  * from @manager. Trying to use this object before its
34a24a
  * #ActUser:is-loaded property is %TRUE will result in undefined
34a24a
  * behavior.
34a24a
  *
34a24a
  * Returns: (transfer none): #ActUser object
34a24a
  **/
34a24a
 ActUser *
34a24a
 act_user_manager_get_user (ActUserManager *manager,
34a24a
                            const char     *username)
34a24a
 {
34a24a
         ActUser *user;
34a24a
 
34a24a
         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), NULL);
34a24a
         g_return_val_if_fail (username != NULL && username[0] != '\0', NULL);
34a24a
 
34a24a
         user = lookup_user_by_name (manager, username);
34a24a
 
34a24a
         /* if we don't have it loaded try to load it now */
34a24a
         if (user == NULL) {
34a24a
                 g_debug ("ActUserManager: trying to track new user with username %s", username);
34a24a
                 user = create_new_user (manager);
34a24a
 
34a24a
                 if (manager->priv->accounts_proxy != NULL) {
34a24a
                         fetch_user_with_username_from_accounts_service (manager, user, username);
34a24a
                 }
34a24a
         }
34a24a
 
34a24a
         return user;
34a24a
 }
34a24a
 
34a24a
+static void
34a24a
+load_user (ActUserManager *manager,
34a24a
+           const char     *username)
34a24a
+{
34a24a
+        ActUser *user;
34a24a
+        GError *error = NULL;
34a24a
+        char *object_path = NULL;
34a24a
+        gboolean user_found;
34a24a
+
34a24a
+        g_return_if_fail (ACT_IS_USER_MANAGER (manager));
34a24a
+        g_return_if_fail (username != NULL && username[0] != '\0');
34a24a
+
34a24a
+        user = lookup_user_by_name (manager, username);
34a24a
+
34a24a
+        if (user == NULL) {
34a24a
+                g_debug ("ActUserManager: trying to track new user with username %s", username);
34a24a
+                user = create_new_user (manager);
34a24a
+        }
34a24a
+
34a24a
+        user_found = accounts_accounts_call_find_user_by_name_sync (manager->priv->accounts_proxy,
34a24a
+                                                                    username,
34a24a
+                                                                    &object_path,
34a24a
+                                                                    NULL,
34a24a
+                                                                    &error);
34a24a
+
34a24a
+        if (!user_found) {
34a24a
+                if (error != NULL) {
34a24a
+                        g_debug ("ActUserManager: Failed to find user '%s': %s",
34a24a
+                                 username, error->message);
34a24a
+                        g_clear_error (&error);
34a24a
+                } else {
34a24a
+                        g_debug ("ActUserManager: Failed to find user '%s'",
34a24a
+                                 username);
34a24a
+                }
34a24a
+        }
34a24a
+
34a24a
+        _act_user_update_from_object_path (user, object_path);
34a24a
+}
34a24a
+
34a24a
 /**
34a24a
  * act_user_manager_get_user_by_id:
34a24a
  * @manager: the manager to query.
34a24a
  * @id: the uid of the user to get.
34a24a
  *
34a24a
  * Retrieves a pointer to the #ActUser object for the user with the
34a24a
  * given uid from @manager. Trying to use this object before its
34a24a
  * #ActUser:is-loaded property is %TRUE will result in undefined
34a24a
  * behavior.
34a24a
  *
34a24a
  * Returns: (transfer none): #ActUser object
34a24a
  */
34a24a
 ActUser *
34a24a
 act_user_manager_get_user_by_id (ActUserManager *manager,
34a24a
                                  uid_t           id)
34a24a
 {
34a24a
         ActUser *user;
34a24a
         gchar  *object_path;
34a24a
 
34a24a
         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), NULL);
34a24a
 
34a24a
         object_path = g_strdup_printf ("/org/freedesktop/Accounts/User%lu", (gulong) id);
34a24a
         user = g_hash_table_lookup (manager->priv->users_by_object_path, object_path);
34a24a
         g_free (object_path);
34a24a
 
34a24a
         if (user != NULL) {
34a24a
                 return g_object_ref (user);
34a24a
         } else {
34a24a
                 g_debug ("ActUserManager: trying to track new user with uid %lu", (gulong) id);
34a24a
                 user = create_new_user (manager);
34a24a
@@ -2425,93 +2419,95 @@ act_user_manager_get_user_by_id (ActUserManager *manager,
34a24a
         }
34a24a
 
34a24a
         return user;
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
 listify_hash_values_hfunc (gpointer key,
34a24a
                            gpointer value,
34a24a
                            gpointer user_data)
34a24a
 {
34a24a
         GSList **list = user_data;
34a24a
 
34a24a
         *list = g_slist_prepend (*list, value);
34a24a
 }
34a24a
 
34a24a
 /**
34a24a
  * act_user_manager_list_users:
34a24a
  * @manager: a #ActUserManager
34a24a
  *
34a24a
  * Get a list of system user accounts
34a24a
  *
34a24a
  * Returns: (element-type ActUser) (transfer container): List of #ActUser objects
34a24a
  */
34a24a
 GSList *
34a24a
 act_user_manager_list_users (ActUserManager *manager)
34a24a
 {
34a24a
         GSList *retval;
34a24a
 
34a24a
         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), NULL);
34a24a
 
34a24a
+        if (!manager->priv->list_cached_users_done) {
34a24a
+                load_users (manager);
34a24a
+
34a24a
+                if (manager->priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_GET_SEAT_PROXY)
34a24a
+                        queue_load_seat_incrementally (manager);
34a24a
+        }
34a24a
+
34a24a
         retval = NULL;
34a24a
         g_hash_table_foreach (manager->priv->normal_users_by_name, listify_hash_values_hfunc, &retval);
34a24a
 
34a24a
         return g_slist_sort (retval, (GCompareFunc) act_user_collate);
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
 maybe_set_is_loaded (ActUserManager *manager)
34a24a
 {
34a24a
         if (manager->priv->is_loaded) {
34a24a
                 g_debug ("ActUserManager: already loaded, so not setting loaded property");
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
         if (manager->priv->getting_sessions) {
34a24a
                 g_debug ("ActUserManager: GetSessions call pending, so not setting loaded property");
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
-        if (manager->priv->listing_cached_users) {
34a24a
-                g_debug ("ActUserManager: Listing cached users, so not setting loaded property");
34a24a
-                return;
34a24a
-        }
34a24a
-
34a24a
         if (manager->priv->new_users_inhibiting_load != NULL) {
34a24a
                 g_debug ("ActUserManager: Loading new users, so not setting loaded property");
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
-        /* Don't set is_loaded yet unless the seat is already loaded
34a24a
+        /* Don't set is_loaded yet unless the seat is already loaded enough
34a24a
          * or failed to load.
34a24a
          */
34a24a
-        if (manager->priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_LOADED) {
34a24a
+        if (manager->priv->seat.state >= ACT_USER_MANAGER_SEAT_STATE_GET_ID) {
34a24a
                 g_debug ("ActUserManager: Seat loaded, so now setting loaded property");
34a24a
         } else if (manager->priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_UNLOADED) {
34a24a
                 g_debug ("ActUserManager: Seat wouldn't load, so giving up on it and setting loaded property");
34a24a
         } else {
34a24a
                 g_debug ("ActUserManager: Seat still actively loading, so not setting loaded property");
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
         set_is_loaded (manager, TRUE);
34a24a
 }
34a24a
 
34a24a
 
34a24a
 static GSList *
34a24a
 slist_deep_copy (const GSList *list)
34a24a
 {
34a24a
         GSList *retval;
34a24a
         GSList *l;
34a24a
 
34a24a
         if (list == NULL)
34a24a
                 return NULL;
34a24a
 
34a24a
         retval = g_slist_copy ((GSList *) list);
34a24a
         for (l = retval; l != NULL; l = l->next) {
34a24a
                 l->data = g_strdup (l->data);
34a24a
         }
34a24a
 
34a24a
         return retval;
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
@@ -2555,125 +2551,134 @@ static void
34a24a
 load_console_kit_sessions (ActUserManager *manager)
34a24a
 {
34a24a
         if (manager->priv->seat.seat_proxy == NULL) {
34a24a
                 g_debug ("ActUserManager: no seat proxy; can't load sessions");
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
         manager->priv->getting_sessions = TRUE;
34a24a
         console_kit_seat_call_get_sessions (manager->priv->seat.seat_proxy,
34a24a
                                             NULL,
34a24a
                                             on_get_sessions_finished,
34a24a
                                             g_object_ref (manager));
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
 load_sessions (ActUserManager *manager)
34a24a
 {
34a24a
 #ifdef WITH_SYSTEMD
34a24a
         if (LOGIND_RUNNING()) {
34a24a
                 reload_systemd_sessions (manager);
34a24a
                 maybe_set_is_loaded (manager);
34a24a
                 return;
34a24a
         }
34a24a
 #endif
34a24a
         load_console_kit_sessions (manager);
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
 load_users (ActUserManager *manager)
34a24a
 {
34a24a
-        g_assert (manager->priv->accounts_proxy != NULL);
34a24a
-        g_debug ("ActUserManager: calling 'ListCachedUsers'");
34a24a
+        GError *error = NULL;
34a24a
+        char **user_paths = NULL;
34a24a
+        gboolean could_list = FALSE;
34a24a
 
34a24a
         if (!ensure_accounts_proxy (manager)) {
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
-        accounts_accounts_call_list_cached_users (manager->priv->accounts_proxy,
34a24a
-                                                  NULL,
34a24a
-                                                  on_list_cached_users_finished,
34a24a
-                                                  g_object_ref (manager));
34a24a
-        manager->priv->listing_cached_users = TRUE;
34a24a
+        g_debug ("ActUserManager: calling 'ListCachedUsers'");
34a24a
+
34a24a
+        could_list = accounts_accounts_call_list_cached_users_sync (manager->priv->accounts_proxy,
34a24a
+                                                                    &user_paths,
34a24a
+                                                                    NULL, &error);
34a24a
+
34a24a
+        if (!could_list) {
34a24a
+                g_debug ("ActUserManager: ListCachedUsers failed: %s", error->message);
34a24a
+                g_clear_error (&error);
34a24a
+                return;
34a24a
+        }
34a24a
+
34a24a
+        load_user_paths (manager, (const char * const *) user_paths);
34a24a
+        g_strfreev (user_paths);
34a24a
+
34a24a
+        load_included_usernames (manager);
34a24a
+
34a24a
+        manager->priv->list_cached_users_done = TRUE;
34a24a
 }
34a24a
 
34a24a
 static gboolean
34a24a
 load_seat_incrementally (ActUserManager *manager)
34a24a
 {
34a24a
         manager->priv->seat.load_idle_id = 0;
34a24a
 
34a24a
         switch (manager->priv->seat.state) {
34a24a
         case ACT_USER_MANAGER_SEAT_STATE_GET_SESSION_ID:
34a24a
                 get_current_session_id (manager);
34a24a
                 break;
34a24a
         case ACT_USER_MANAGER_SEAT_STATE_GET_SESSION_PROXY:
34a24a
                 get_session_proxy (manager);
34a24a
                 break;
34a24a
         case ACT_USER_MANAGER_SEAT_STATE_GET_ID:
34a24a
                 get_seat_id_for_current_session (manager);
34a24a
                 break;
34a24a
         case ACT_USER_MANAGER_SEAT_STATE_GET_SEAT_PROXY:
34a24a
                 get_seat_proxy (manager);
34a24a
                 break;
34a24a
         case ACT_USER_MANAGER_SEAT_STATE_LOADED:
34a24a
                 g_debug ("ActUserManager: Seat loading sequence complete");
34a24a
                 break;
34a24a
         default:
34a24a
                 g_assert_not_reached ();
34a24a
         }
34a24a
 
34a24a
         if (manager->priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_LOADED) {
34a24a
                 load_sessions (manager);
34a24a
         }
34a24a
 
34a24a
         maybe_set_is_loaded (manager);
34a24a
 
34a24a
         return FALSE;
34a24a
 }
34a24a
 
34a24a
 static gboolean
34a24a
 load_idle (ActUserManager *manager)
34a24a
 {
34a24a
-        /* The order below is important: load_seat_incrementally might
34a24a
-           set "is-loaded" immediately and we thus need to call
34a24a
-           load_users before it.
34a24a
-        */
34a24a
-        load_users (manager);
34a24a
         manager->priv->seat.state = ACT_USER_MANAGER_SEAT_STATE_UNLOADED + 1;
34a24a
         load_seat_incrementally (manager);
34a24a
         manager->priv->load_id = 0;
34a24a
 
34a24a
         return FALSE;
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
-queue_load_seat_and_users (ActUserManager *manager)
34a24a
+queue_load_seat (ActUserManager *manager)
34a24a
 {
34a24a
         if (manager->priv->load_id > 0) {
34a24a
                 return;
34a24a
         }
34a24a
 
34a24a
         manager->priv->load_id = g_idle_add ((GSourceFunc)load_idle, manager);
34a24a
 }
34a24a
 
34a24a
 static void
34a24a
 act_user_manager_get_property (GObject        *object,
34a24a
                                guint           prop_id,
34a24a
                                GValue         *value,
34a24a
                                GParamSpec     *pspec)
34a24a
 {
34a24a
         ActUserManager *manager;
34a24a
 
34a24a
         manager = ACT_USER_MANAGER (object);
34a24a
 
34a24a
         switch (prop_id) {
34a24a
         case PROP_IS_LOADED:
34a24a
                 g_value_set_boolean (value, manager->priv->is_loaded);
34a24a
                 break;
34a24a
         case PROP_HAS_MULTIPLE_USERS:
34a24a
                 g_value_set_boolean (value, manager->priv->has_multiple_users);
34a24a
                 break;
34a24a
         case PROP_INCLUDE_USERNAMES_LIST:
34a24a
                 g_value_set_pointer (value, manager->priv->include_usernames);
34a24a
                 break;
34a24a
         case PROP_EXCLUDE_USERNAMES_LIST:
34a24a
                 g_value_set_pointer (value, manager->priv->exclude_usernames);
34a24a
@@ -2820,61 +2825,61 @@ act_user_manager_class_init (ActUserManagerClass *klass)
34a24a
          * @user: the #ActUser that changed
34a24a
          *
34a24a
          * One of the users has changed
34a24a
          */
34a24a
         signals [USER_CHANGED] =
34a24a
                 g_signal_new ("user-changed",
34a24a
                               G_TYPE_FROM_CLASS (klass),
34a24a
                               G_SIGNAL_RUN_LAST,
34a24a
                               G_STRUCT_OFFSET (ActUserManagerClass, user_changed),
34a24a
                               NULL, NULL,
34a24a
                               g_cclosure_marshal_VOID__OBJECT,
34a24a
                               G_TYPE_NONE, 1, ACT_TYPE_USER);
34a24a
 
34a24a
         g_type_class_add_private (klass, sizeof (ActUserManagerPrivate));
34a24a
 }
34a24a
 
34a24a
 /**
34a24a
  * act_user_manager_queue_load:
34a24a
  * @manager: a #ActUserManager
34a24a
  *
34a24a
  * Queue loading users into user manager. This must be called, and the
34a24a
  * #ActUserManager:is-loaded property must be %TRUE before calling
34a24a
  * act_user_manager_list_users()
34a24a
  */
34a24a
 static void
34a24a
 act_user_manager_queue_load (ActUserManager *manager)
34a24a
 {
34a24a
         g_return_if_fail (ACT_IS_USER_MANAGER (manager));
34a24a
 
34a24a
         if (! manager->priv->is_loaded) {
34a24a
-                queue_load_seat_and_users (manager);
34a24a
+                queue_load_seat (manager);
34a24a
         }
34a24a
 }
34a24a
 
34a24a
 static gboolean
34a24a
 ensure_accounts_proxy (ActUserManager *manager)
34a24a
 {
34a24a
         GError *error = NULL;
34a24a
 
34a24a
         if (manager->priv->accounts_proxy != NULL) {
34a24a
                 return TRUE;
34a24a
         }
34a24a
 
34a24a
         manager->priv->accounts_proxy = accounts_accounts_proxy_new_sync (manager->priv->connection,
34a24a
                                                                           G_DBUS_PROXY_FLAGS_NONE,
34a24a
                                                                           ACCOUNTS_NAME,
34a24a
                                                                           ACCOUNTS_PATH,
34a24a
                                                                           NULL,
34a24a
                                                                           &error);
34a24a
         if (error != NULL) {
34a24a
                 g_debug ("ActUserManager: getting account proxy failed: %s", error->message);
34a24a
                 g_clear_error (&error);
34a24a
                 return FALSE;
34a24a
         }
34a24a
 
34a24a
         g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (manager->priv->accounts_proxy), G_MAXINT);
34a24a
 
34a24a
         g_object_bind_property (G_OBJECT (manager->priv->accounts_proxy),
34a24a
                                 "has-multiple-users",
34a24a
                                 G_OBJECT (manager),
34a24a
                                 "has-multiple-users",
34a24a
-- 
34a24a
2.14.1
34a24a