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

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