|
|
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 |
|