[gdm/gnome-2-30] Set up seat proxy asynchronously with users



commit 18735c4bbf4c1e5df571f1d97283a55147a8fa47
Author: Ray Strode <rstrode redhat com>
Date:   Wed Jun 23 23:05:21 2010 -0400

    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

 gui/simple-greeter/gdm-user-manager.c |  313 +++++++++++++++++++++++----------
 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 ede66b7..d6c6ce5 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);
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]