summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2010-06-23 23:05:21 -0400
committerRay Strode <rstrode@redhat.com>2010-06-24 19:12:43 -0400
commit18735c4bbf4c1e5df571f1d97283a55147a8fa47 (patch)
treead176abf5b0605ea2d772cf8278033795390b8ce
parent6379bd161eb7806c3e3815d74aa7166ebf78ab5b (diff)
downloadgdm-18735c4bbf4c1e5df571f1d97283a55147a8fa47.tar.gz
Set up seat proxy asynchronously with users
We don't actually need the proxy right away, we only need it before doing other things that use ConsoleKit so blocking other parts of initialization for it is wrong. This commit makes it run asynchronously with everything else. https://bugzilla.gnome.org/show_bug.cgi?id=622639
-rw-r--r--gui/simple-greeter/gdm-user-manager.c313
1 files changed, 222 insertions, 91 deletions
diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index ede66b7b..d6c6ce5d 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -77,12 +77,25 @@
#define RELOAD_PASSWD_THROTTLE_SECS 5
+typedef enum {
+ GDM_USER_MANAGER_SEAT_STATE_UNLOADED = 0,
+ GDM_USER_MANAGER_SEAT_STATE_GET_SESSION_ID,
+ GDM_USER_MANAGER_SEAT_STATE_GET_ID,
+ GDM_USER_MANAGER_SEAT_STATE_GET_PROXY,
+ GDM_USER_MANAGER_SEAT_STATE_LOADED,
+} GdmUserManagerSeatState;
+
typedef struct
{
- char *id;
- char *session_id;
+ GdmUserManagerSeatState state;
+ char *id;
+ char *session_id;
+ union {
+ DBusGProxyCall *get_current_session_call;
+ DBusGProxyCall *get_seat_id_call;
+ };
- DBusGProxy *proxy;
+ DBusGProxy *proxy;
} GdmUserManagerSeat;
struct GdmUserManagerPrivate
@@ -138,8 +151,11 @@ static void gdm_user_manager_class_init (GdmUserManagerClass *klass);
static void gdm_user_manager_init (GdmUserManager *user_manager);
static void gdm_user_manager_finalize (GObject *object);
-static void load_users (GdmUserManager *manager);
-static void monitor_local_users (GdmUserManager *manager);
+static void load_seat_incrementally (GdmUserManager *manager);
+static void unload_seat (GdmUserManager *manager);
+static void load_users (GdmUserManager *manager);
+static void queue_load_seat_and_users (GdmUserManager *manager);
+static void monitor_local_users (GdmUserManager *manager);
static gpointer user_manager_object = NULL;
@@ -351,6 +367,7 @@ gdm_user_manager_goto_login_session (GdmUserManager *manager)
char *ssid;
g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), FALSE);
+ g_return_val_if_fail (manager->priv->is_loaded, FALSE);
ret = FALSE;
@@ -382,6 +399,11 @@ gdm_user_manager_can_switch (GdmUserManager *manager)
gboolean can_activate_sessions;
GError *error;
+ if (!manager->priv->is_loaded) {
+ g_debug ("GdmUserManager: Unable to switch sessions until fully loaded");
+ return FALSE;
+ }
+
if (manager->priv->seat.id == NULL || manager->priv->seat.id[0] == '\0') {
g_debug ("GdmUserManager: display seat ID is not set; can't switch sessions");
return FALSE;
@@ -421,6 +443,7 @@ gdm_user_manager_activate_user_session (GdmUserManager *manager,
gboolean can_activate_sessions;
g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), FALSE);
g_return_val_if_fail (GDM_IS_USER (user), FALSE);
+ g_return_val_if_fail (manager->priv->is_loaded, FALSE);
ret = FALSE;
@@ -481,48 +504,87 @@ on_user_changed (GdmUser *user,
}
}
-static char *
-get_seat_id_for_session (DBusGConnection *connection,
- const char *session_id)
+static void
+on_get_seat_id_finished (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ GdmUserManager *manager)
{
- DBusGProxy *proxy;
- GError *error;
- char *seat_id;
- gboolean res;
+ GError *error;
+ char *seat_id;
+ gboolean res;
- proxy = NULL;
+ g_assert (manager->priv->seat.get_seat_id_call == call);
+
+ error = NULL;
seat_id = NULL;
+ res = dbus_g_proxy_end_call (proxy,
+ call,
+ &error,
+ DBUS_TYPE_G_OBJECT_PATH,
+ &seat_id,
+ G_TYPE_INVALID);
+ manager->priv->seat.get_seat_id_call = NULL;
+ g_object_unref (proxy);
- proxy = dbus_g_proxy_new_for_name (connection,
+ if (! res) {
+ if (error != NULL) {
+ g_debug ("Failed to identify the seat of the "
+ "current session: %s",
+ error->message);
+ g_error_free (error);
+ } else {
+ g_debug ("Failed to identify the seat of the "
+ "current session");
+ }
+ unload_seat (manager);
+ return;
+ }
+
+ g_debug ("GdmUserManager: Found current seat: %s", seat_id);
+
+ manager->priv->seat.id = seat_id;
+ manager->priv->seat.state++;
+
+ load_seat_incrementally (manager);
+}
+
+static void
+get_seat_id_for_current_session (GdmUserManager *manager)
+{
+ DBusGProxy *proxy;
+ DBusGProxyCall *call;
+
+ proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
CK_NAME,
- session_id,
+ manager->priv->seat.session_id,
CK_SESSION_INTERFACE);
if (proxy == NULL) {
g_warning ("Failed to connect to the ConsoleKit session object");
- goto out;
+ goto failed;
}
- error = NULL;
- res = dbus_g_proxy_call (proxy,
- "GetSeatId",
- &error,
- G_TYPE_INVALID,
- DBUS_TYPE_G_OBJECT_PATH, &seat_id,
- G_TYPE_INVALID);
- if (! res) {
- if (error != NULL) {
- g_debug ("Failed to identify the current seat: %s", error->message);
- g_error_free (error);
- } else {
- g_debug ("Failed to identify the current seat");
- }
+ call = dbus_g_proxy_begin_call (proxy,
+ "GetSeatId",
+ (DBusGProxyCallNotify)
+ on_get_seat_id_finished,
+ manager,
+ NULL,
+ G_TYPE_INVALID);
+ if (call == NULL) {
+ g_warning ("GdmUserManager: failed to make GetSeatId call");
+ goto failed;
}
- out:
+
+ manager->priv->seat.get_seat_id_call = call;
+
+ return;
+
+failed:
if (proxy != NULL) {
g_object_unref (proxy);
}
- return seat_id;
+ unload_seat (manager);
}
static char *
@@ -686,55 +748,84 @@ remove_user (GdmUserManager *manager,
}
}
-static char *
-get_current_seat_id (DBusGConnection *connection)
+static void
+on_get_current_session_finished (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ GdmUserManager *manager)
{
- DBusGProxy *proxy;
- GError *error;
- char *session_id;
- char *seat_id;
- gboolean res;
+ GError *error;
+ char *session_id;
+ gboolean res;
- proxy = NULL;
+ g_assert (manager->priv->seat.get_current_session_call == call);
+ g_assert (manager->priv->seat.state == GDM_USER_MANAGER_SEAT_STATE_GET_SESSION_ID);
+
+ error = NULL;
session_id = NULL;
- seat_id = NULL;
+ res = dbus_g_proxy_end_call (proxy,
+ call,
+ &error,
+ DBUS_TYPE_G_OBJECT_PATH,
+ &session_id,
+ G_TYPE_INVALID);
+ manager->priv->seat.get_current_session_call = NULL;
+ g_object_unref (proxy);
- proxy = dbus_g_proxy_new_for_name (connection,
+ if (! res) {
+ if (error != NULL) {
+ g_debug ("Failed to identify the current session: %s",
+ error->message);
+ g_error_free (error);
+ } else {
+ g_debug ("Failed to identify the current session");
+ }
+ unload_seat (manager);
+ return;
+ }
+
+ manager->priv->seat.session_id = session_id;
+ manager->priv->seat.state++;
+
+ load_seat_incrementally (manager);
+}
+
+static void
+get_current_session_id (GdmUserManager *manager)
+{
+ DBusGProxy *proxy;
+ DBusGProxyCall *call;
+
+ proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
CK_NAME,
CK_MANAGER_PATH,
CK_MANAGER_INTERFACE);
if (proxy == NULL) {
g_warning ("Failed to connect to the ConsoleKit manager object");
- goto out;
+ goto failed;
}
- error = NULL;
- res = dbus_g_proxy_call (proxy,
- "GetCurrentSession",
- &error,
- G_TYPE_INVALID,
- DBUS_TYPE_G_OBJECT_PATH,
- &session_id,
- G_TYPE_INVALID);
- if (! res) {
- if (error != NULL) {
- g_debug ("Failed to identify the current session: %s", error->message);
- g_error_free (error);
- } else {
- g_debug ("Failed to identify the current session");
- }
- goto out;
+ call = dbus_g_proxy_begin_call (proxy,
+ "GetCurrentSession",
+ (DBusGProxyCallNotify)
+ on_get_current_session_finished,
+ manager,
+ NULL,
+ G_TYPE_INVALID);
+ if (call == NULL) {
+ g_warning ("GdmUserManager: failed to make GetCurrentSession call");
+ goto failed;
}
- seat_id = get_seat_id_for_session (connection, session_id);
+ manager->priv->seat.get_current_session_call = call;
- out:
+ return;
+
+failed:
if (proxy != NULL) {
g_object_unref (proxy);
}
- g_free (session_id);
- return seat_id;
+ unload_seat (manager);
}
static gboolean
@@ -903,13 +994,6 @@ get_seat_proxy (GdmUserManager *manager)
g_assert (manager->priv->seat.proxy == NULL);
- manager->priv->seat.id = get_current_seat_id (manager->priv->connection);
- if (manager->priv->seat.id == NULL) {
- return;
- }
-
- g_debug ("GdmUserManager: Found current seat: %s", manager->priv->seat.id);
-
error = NULL;
proxy = dbus_g_proxy_new_for_name_owner (manager->priv->connection,
CK_NAME,
@@ -925,6 +1009,7 @@ get_seat_proxy (GdmUserManager *manager)
} else {
g_warning ("Failed to connect to the ConsoleKit seat object");
}
+ unload_seat (manager);
return;
}
@@ -949,7 +1034,24 @@ get_seat_proxy (GdmUserManager *manager)
manager,
NULL);
manager->priv->seat.proxy = proxy;
+ manager->priv->seat.state = GDM_USER_MANAGER_SEAT_STATE_LOADED;
+}
+static void
+unload_seat (GdmUserManager *manager)
+{
+ manager->priv->seat.state = GDM_USER_MANAGER_SEAT_STATE_UNLOADED;
+
+ if (manager->priv->seat.proxy != NULL) {
+ g_object_unref (manager->priv->seat.proxy);
+ manager->priv->seat.proxy = NULL;
+ }
+
+ g_free (manager->priv->seat.id);
+ manager->priv->seat.id = NULL;
+
+ g_free (manager->priv->seat.session_id);
+ manager->priv->seat.session_id = NULL;
}
/**
@@ -1180,6 +1282,14 @@ maybe_set_is_loaded (GdmUserManager *manager)
return;
}
+ /* Don't set is_loaded yet unless the seat is already loaded
+ * or failed to load.
+ */
+ if (manager->priv->seat.state != GDM_USER_MANAGER_SEAT_STATE_LOADED
+ && manager->priv->seat.state != GDM_USER_MANAGER_SEAT_STATE_UNLOADED) {
+ return;
+ }
+
set_is_loaded (manager, TRUE);
}
@@ -1661,15 +1771,12 @@ load_sessions_from_array (GdmUserManager *manager,
static void
on_get_sessions_finished (DBusGProxy *proxy,
DBusGProxyCall *call,
- gpointer data)
+ GdmUserManager *manager)
{
- GdmUserManager *manager;
GError *error;
gboolean res;
GPtrArray *sessions;
- manager = GDM_USER_MANAGER (data);
-
g_assert (manager->priv->get_sessions_call == call);
error = NULL;
@@ -1716,6 +1823,7 @@ load_sessions (GdmUserManager *manager)
call = dbus_g_proxy_begin_call (manager->priv->seat.proxy,
"GetSessions",
+ (DBusGProxyCallNotify)
on_get_sessions_finished,
manager,
NULL,
@@ -1729,9 +1837,42 @@ load_sessions (GdmUserManager *manager)
manager->priv->get_sessions_call = call;
}
+static void
+load_seat_incrementally (GdmUserManager *manager)
+{
+ g_assert (manager->priv->seat.proxy == NULL);
+
+ switch (manager->priv->seat.state) {
+ case GDM_USER_MANAGER_SEAT_STATE_GET_SESSION_ID:
+ get_current_session_id (manager);
+ break;
+ case GDM_USER_MANAGER_SEAT_STATE_GET_ID:
+ get_seat_id_for_current_session (manager);
+ break;
+ case GDM_USER_MANAGER_SEAT_STATE_GET_PROXY:
+ get_seat_proxy (manager);
+ break;
+ case GDM_USER_MANAGER_SEAT_STATE_LOADED:
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (manager->priv->seat.state == GDM_USER_MANAGER_SEAT_STATE_LOADED) {
+ gboolean res;
+
+ load_sessions (manager);
+ res = load_ck_history (manager);
+ }
+
+ maybe_set_is_loaded (manager);
+}
+
static gboolean
-load_users_idle (GdmUserManager *manager)
+load_idle (GdmUserManager *manager)
{
+ manager->priv->seat.state = GDM_USER_MANAGER_SEAT_STATE_UNLOADED + 1;
+ load_seat_incrementally (manager);
load_users (manager);
manager->priv->load_id = 0;
@@ -1739,13 +1880,13 @@ load_users_idle (GdmUserManager *manager)
}
static void
-queue_load_users (GdmUserManager *manager)
+queue_load_seat_and_users (GdmUserManager *manager)
{
if (manager->priv->load_id > 0) {
return;
}
- manager->priv->load_id = g_idle_add ((GSourceFunc)load_users_idle, manager);
+ manager->priv->load_id = g_idle_add ((GSourceFunc)load_idle, manager);
}
static gboolean
@@ -1958,17 +2099,11 @@ monitor_local_users (GdmUserManager *manager)
static void
load_users (GdmUserManager *manager)
{
- gboolean res;
-
manager->priv->shells = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
NULL);
reload_shells (manager);
-
- load_sessions (manager);
-
- res = load_ck_history (manager);
schedule_reload_passwd (manager);
}
@@ -2058,7 +2193,7 @@ gdm_user_manager_queue_load (GdmUserManager *manager)
g_return_if_fail (GDM_IS_USER_MANAGER (manager));
if (! manager->priv->is_loaded) {
- queue_load_users (manager);
+ queue_load_seat_and_users (manager);
}
}
@@ -2101,7 +2236,7 @@ gdm_user_manager_init (GdmUserManager *manager)
manager->priv->cancellable = g_cancellable_new ();
- get_seat_proxy (manager);
+ manager->priv->seat.state = GDM_USER_MANAGER_SEAT_STATE_UNLOADED;
}
static void
@@ -2121,6 +2256,8 @@ gdm_user_manager_finalize (GObject *object)
signal_pid (manager->priv->ck_history_pid, SIGTERM);
}
+ unload_seat (manager);
+
if (manager->priv->cancellable != NULL) {
g_object_unref (manager->priv->cancellable);
manager->priv->cancellable = NULL;
@@ -2136,10 +2273,6 @@ gdm_user_manager_finalize (GObject *object)
g_slist_free (manager->priv->include_usernames);
}
- if (manager->priv->seat.proxy != NULL) {
- g_object_unref (manager->priv->seat.proxy);
- }
-
if (manager->priv->ck_history_id != 0) {
g_source_remove (manager->priv->ck_history_id);
manager->priv->ck_history_id = 0;
@@ -2168,8 +2301,6 @@ gdm_user_manager_finalize (GObject *object)
g_file_monitor_cancel (manager->priv->shells_monitor);
g_hash_table_destroy (manager->priv->shells);
- g_free (manager->priv->seat.id);
-
G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object);
}