[gdm/wip/wayland-rebase: 16/20] daemon: move user session code from slave to main daemon



commit e804a288b77d7097839008d4e1593058ac47955b
Author: Ray Strode <rstrode redhat com>
Date:   Tue Sep 17 15:52:25 2013 -0400

    daemon: move user session code from slave to main daemon
    
    This will allow us to run a session without a slave babysitting it.

 daemon/Makefile.am               |   14 +
 daemon/gdm-display.c             |  272 +++++++---
 daemon/gdm-display.h             |   39 +-
 daemon/gdm-manager.c             | 1196 ++++++++++++++++++++++++++++++++++++--
 daemon/gdm-simple-slave.c        |  848 ++-------------------------
 daemon/gdm-slave.c               |  721 ++---------------------
 daemon/gdm-slave.h               |   31 +-
 daemon/gdm-slave.xml             |   20 +-
 daemon/gdm-xdmcp-chooser-slave.c |   26 -
 9 files changed, 1507 insertions(+), 1660 deletions(-)
---
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 7eacbdc..218e799 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -313,6 +313,14 @@ gdm_SOURCES =                      \
        gdm-transient-display.h         \
        gdm-manager.c                   \
        gdm-manager.h                   \
+       gdm-session.c                   \
+       gdm-session.h                   \
+       gdm-session-record.c            \
+       gdm-session-record.h            \
+       gdm-session-worker-common.c     \
+       gdm-session-worker-common.h     \
+       gdm-session-worker-job.c        \
+       gdm-session-worker-job.h        \
        gdm-slave-job.c                 \
        gdm-slave-job.h                 \
        gdm-dbus-util.c                 \
@@ -332,6 +340,12 @@ nodist_gdm_SOURCES =                       \
        gdm-static-display-glue.c               \
        gdm-slave-glue.h                        \
        gdm-slave-glue.c                        \
+       gdm-session-glue.h                      \
+       gdm-session-glue.c                      \
+       gdm-session-worker-glue.c               \
+       gdm-session-worker-glue.h               \
+       gdm-session-enum-types.c                \
+       gdm-session-enum-types.h                \
        $(NULL)
 
 XDMCP_SOURCES =                                \
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 1791127..07240e9 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -104,6 +104,8 @@ static void     gdm_display_class_init  (GdmDisplayClass *klass);
 static void     gdm_display_init        (GdmDisplay      *display);
 static void     gdm_display_finalize    (GObject         *object);
 static void     queue_finish            (GdmDisplay      *display);
+static void     _gdm_display_set_status (GdmDisplay *display,
+                                         int         status);
 
 G_DEFINE_ABSTRACT_TYPE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
 
@@ -297,6 +299,13 @@ on_name_vanished (GDBusConnection *connection,
 }
 
 static void
+on_slave_started (GdmDBusSlave *slave_proxy,
+                  GdmDisplay   *display)
+{
+        _gdm_display_set_status (display, GDM_DISPLAY_MANAGED);
+}
+
+static void
 gdm_display_real_set_slave_bus_name_finish (GObject      *source_object,
                                             GAsyncResult *res,
                                             gpointer      user_data)
@@ -309,6 +318,10 @@ gdm_display_real_set_slave_bus_name_finish (GObject      *source_object,
                                 G_OBJECT (display),
                                 "session-id",
                                 G_BINDING_DEFAULT);
+        g_signal_connect (G_OBJECT (display->priv->slave_proxy),
+                          "started",
+                          G_CALLBACK (on_slave_started),
+                          display);
 }
 
 static gboolean
@@ -340,6 +353,12 @@ gdm_display_real_set_slave_bus_name (GdmDisplay *display,
                                   gdm_display_real_set_slave_bus_name_finish,
                                   display);
 
+        display->priv->slave_proxy = GDM_DBUS_SLAVE (gdm_dbus_slave_proxy_new_sync 
(display->priv->connection,
+                                                                                    G_DBUS_PROXY_FLAGS_NONE,
+                                                                                    name,
+                                                                                    GDM_SLAVE_PATH,
+                                                                                    NULL, NULL));
+
         return TRUE;
 }
 
@@ -438,20 +457,38 @@ gdm_display_real_get_timed_login_details (GdmDisplay *display,
 
 gboolean
 gdm_display_get_timed_login_details (GdmDisplay *display,
-                                     gboolean   *enabled,
-                                     char      **username,
-                                     int        *delay,
+                                     gboolean   *out_enabled,
+                                     char      **out_username,
+                                     int        *out_delay,
                                      GError    **error)
 {
+        gboolean enabled;
+        char *username;
+        int delay;
+
         g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE);
 
-        GDM_DISPLAY_GET_CLASS (display)->get_timed_login_details (display, enabled, username, delay);
+        GDM_DISPLAY_GET_CLASS (display)->get_timed_login_details (display, &enabled, &username, &delay);
 
-        g_debug ("GdmSlave: Got timed login details for display %s: %d '%s' %d",
+        g_debug ("GdmDisplay: Got timed login details for display %s: %d '%s' %d",
                  display->priv->x11_display_name,
-                 *enabled,
-                 *username ? *username : "(null)",
-                 *delay);
+                 enabled,
+                 username,
+                 delay);
+
+        if (out_enabled) {
+                *out_enabled = enabled;
+        }
+
+        if (out_username) {
+                *out_username = username;
+        } else {
+                g_free (username);
+        }
+
+        if (out_delay) {
+                *out_delay = delay;
+        }
 
         return TRUE;
 }
@@ -1329,74 +1366,6 @@ register_display (GdmDisplay *display)
         return TRUE;
 }
 
-char *
-gdm_display_open_session_sync (GdmDisplay    *display,
-                               GPid           pid_of_caller,
-                               uid_t          uid_of_caller,
-                               GCancellable  *cancellable,
-                               GError       **error)
-{
-        char *address;
-        int ret;
-
-        if (display->priv->slave_proxy == NULL) {
-                g_set_error (error,
-                             G_DBUS_ERROR,
-                             G_DBUS_ERROR_ACCESS_DENIED,
-                             _("No session available yet"));
-                return NULL;
-        }
-
-        address = NULL;
-        ret = gdm_dbus_slave_call_open_session_sync (display->priv->slave_proxy,
-                                                     (int) pid_of_caller,
-                                                     (int) uid_of_caller,
-                                                     &address,
-                                                     cancellable,
-                                                     error);
-
-        if (!ret) {
-                return NULL;
-        }
-
-        return address;
-}
-
-char *
-gdm_display_open_reauthentication_channel_sync (GdmDisplay    *display,
-                                                const char    *username,
-                                                GPid           pid_of_caller,
-                                                uid_t          uid_of_caller,
-                                                GCancellable  *cancellable,
-                                                GError       **error)
-{
-        char *address;
-        int ret;
-
-        if (display->priv->slave_proxy == NULL) {
-                g_set_error (error,
-                             G_DBUS_ERROR,
-                             G_DBUS_ERROR_ACCESS_DENIED,
-                             _("No session available yet"));
-                return NULL;
-        }
-
-        address = NULL;
-        ret = gdm_dbus_slave_call_open_reauthentication_channel_sync (display->priv->slave_proxy,
-                                                                      username,
-                                                                      pid_of_caller,
-                                                                      uid_of_caller,
-                                                                      &address,
-                                                                      cancellable,
-                                                                      error);
-
-        if (!ret) {
-                return NULL;
-        }
-
-        return address;
-}
-
 /*
   dbus-send --system --print-reply --dest=org.gnome.DisplayManager /org/gnome/DisplayManager/Displays/1 
org.freedesktop.DBus.Introspectable.Introspect
 */
@@ -1642,3 +1611,154 @@ gdm_display_get_object_skeleton (GdmDisplay *display)
 {
         return display->priv->object_skeleton;
 }
+
+static void
+on_slave_set_up (GdmDBusSlave *slave,
+                 GAsyncResult *result,
+                 GTask        *task)
+{
+        GError *error = NULL;
+        char *username = NULL;
+
+        if (!gdm_dbus_slave_call_set_up_initial_session_finish (slave, &username, result, &error)) {
+                g_task_return_error (task, error);
+                return;
+        }
+
+        g_debug ("GdmDisplay: slave set up for %s user to connect",
+                 username);
+
+        g_task_return_pointer (task, username, NULL);
+}
+
+void
+gdm_display_set_up_initial_session (GdmDisplay           *display,
+                                    GCancellable         *cancellable,
+                                    GAsyncReadyCallback   callback,
+                                    gpointer              user_data)
+{
+        GTask *task;
+
+        task = g_task_new (display, cancellable, callback, user_data);
+
+        gdm_dbus_slave_call_set_up_initial_session (display->priv->slave_proxy,
+                                                    cancellable,
+                                                    (GAsyncReadyCallback)
+                                                    on_slave_set_up,
+                                                    task);
+}
+
+char *
+gdm_display_set_up_initial_session_finish (GdmDisplay    *display,
+                                           GAsyncResult  *result,
+                                           GError       **error)
+{
+        char *username;
+
+        username = g_task_propagate_pointer (G_TASK (result), error);
+        g_object_unref (G_OBJECT (result));
+
+        return username;
+}
+
+static void
+on_slave_started_initial_session (GdmDBusSlave *slave,
+                                  GAsyncResult *result,
+                                  GTask        *task)
+{
+        GError *error = NULL;
+
+        if (!gdm_dbus_slave_call_start_initial_session_finish (slave, result, &error)) {
+                g_task_return_error (task, error);
+                return;
+        }
+
+        g_debug ("GdmDisplay: slave started initial session");
+
+        g_task_return_boolean (task, TRUE);
+}
+
+void
+gdm_display_start_initial_session (GdmDisplay          *display,
+                                   GCancellable        *cancellable,
+                                   GAsyncReadyCallback  callback,
+                                   gpointer             user_data)
+{
+        GTask *task;
+
+        task = g_task_new (display, cancellable, callback, user_data);
+
+        gdm_dbus_slave_call_start_initial_session (display->priv->slave_proxy,
+                                                   cancellable,
+                                                   (GAsyncReadyCallback)
+                                                   on_slave_started_initial_session,
+                                                   task);
+}
+
+gboolean
+gdm_display_start_initial_session_finish (GdmDisplay    *display,
+                                          GAsyncResult  *result,
+                                          GError       **error)
+{
+        gboolean outcome;
+
+        outcome = g_task_propagate_boolean (G_TASK (result), error);
+        g_object_unref (G_OBJECT (result));
+
+        return outcome;
+}
+
+static void
+on_slave_initial_session_stopped (GdmDBusSlave *slave,
+                                  GAsyncResult *result,
+                                  GTask        *task)
+{
+        GError *error = NULL;
+
+        if (!gdm_dbus_slave_call_stop_initial_session_finish (slave, result, &error)) {
+                g_task_return_error (task, error);
+                return;
+        }
+
+        g_debug ("GdmDisplay: slave set up for user session to start");
+
+        g_task_return_boolean (task, TRUE);
+}
+
+void
+gdm_display_stop_initial_session (GdmDisplay          *display,
+                                  const char          *username,
+                                  GCancellable        *cancellable,
+                                  GAsyncReadyCallback  callback,
+                                  gpointer             user_data)
+{
+        GTask *task;
+
+        task = g_task_new (display, cancellable, callback, user_data);
+
+        gdm_dbus_slave_call_stop_initial_session (display->priv->slave_proxy,
+                                                  username,
+                                                  cancellable,
+                                                  (GAsyncReadyCallback)
+                                                  on_slave_initial_session_stopped,
+                                                  task);
+}
+
+gboolean
+gdm_display_stop_initial_session_finish (GdmDisplay    *display,
+                                         GAsyncResult  *result,
+                                         GError       **error)
+{
+        gboolean outcome;
+
+        outcome = g_task_propagate_boolean (G_TASK (result), error);
+        g_object_unref (G_OBJECT (result));
+
+        return outcome;
+}
+
+gboolean
+gdm_display_run_pre_session_script (GdmDisplay *display)
+{
+        return FALSE;
+}
diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h
index bfba143..391c2dd 100644
--- a/daemon/gdm-display.h
+++ b/daemon/gdm-display.h
@@ -90,18 +90,6 @@ GType               gdm_display_get_type                       (void);
 
 int                 gdm_display_get_status                     (GdmDisplay *display);
 time_t              gdm_display_get_creation_time              (GdmDisplay *display);
-char *              gdm_display_open_session_sync              (GdmDisplay    *display,
-                                                                GPid           pid_of_caller,
-                                                                uid_t          uid_of_caller,
-                                                                GCancellable  *cancellable,
-                                                                GError       **error);
-
-char *              gdm_display_open_reauthentication_channel_sync        (GdmDisplay    *display,
-                                                                           const char    *username,
-                                                                           GPid           pid_of_caller,
-                                                                           uid_t          uid_of_caller,
-                                                                           GCancellable  *cancellable,
-                                                                           GError       **error);
 char *              gdm_display_get_session_id                 (GdmDisplay *display);
 gboolean            gdm_display_create_authority               (GdmDisplay *display);
 gboolean            gdm_display_prepare                        (GdmDisplay *display);
@@ -157,6 +145,33 @@ gboolean            gdm_display_set_slave_bus_name             (GdmDisplay *disp
                                                                 const char *name,
                                                                 GError    **error);
 
+void                gdm_display_set_up_initial_session           (GdmDisplay *display,
+                                                                  GCancellable *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer user_data);
+
+char *              gdm_display_set_up_initial_session_finish    (GdmDisplay *display,
+                                                                  GAsyncResult *result,
+                                                                  GError **error);
+void                gdm_display_start_initial_session           (GdmDisplay *display,
+                                                                 GCancellable *cancellable,
+                                                                 GAsyncReadyCallback callback,
+                                                                 gpointer user_data);
+
+gboolean            gdm_display_start_initial_session_finish    (GdmDisplay *display,
+                                                                 GAsyncResult *result,
+                                                                 GError **error);
+void                gdm_display_stop_initial_session           (GdmDisplay   *display,
+                                                                const char   *username,
+                                                                GCancellable *cancellable,
+                                                                GAsyncReadyCallback callback,
+                                                                gpointer user_data);
+
+gboolean           gdm_display_stop_initial_session_finish     (GdmDisplay *display,
+                                                                GAsyncResult *result,
+                                                                GError **error);
+gboolean           gdm_display_run_pre_session_script          (GdmDisplay *display);
+
 G_END_DECLS
 
 #endif /* __GDM_DISPLAY_H */
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 5108c37..6624e85 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -46,6 +46,7 @@
 #include "gdm-display-store.h"
 #include "gdm-display-factory.h"
 #include "gdm-local-display-factory.h"
+#include "gdm-session.h"
 #include "gdm-xdmcp-display-factory.h"
 
 #define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
@@ -54,6 +55,15 @@
 #define GDM_MANAGER_PATH          GDM_DBUS_PATH "/Manager"
 #define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
 
+#define CK_NAME      "org.freedesktop.ConsoleKit"
+#define CK_PATH      "/org/freedesktop/ConsoleKit"
+#define CK_INTERFACE "org.freedesktop.ConsoleKit"
+
+#define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
+#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
+#define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
+#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+
 struct GdmManagerPrivate
 {
         GdmDisplayStore        *display_store;
@@ -61,7 +71,10 @@ struct GdmManagerPrivate
 #ifdef HAVE_LIBXDMCP
         GdmXdmcpDisplayFactory *xdmcp_factory;
 #endif
+        GList                  *user_sessions;
+        GHashTable             *open_reauthentication_requests;
         gboolean                xdmcp_enabled;
+        GCancellable           *cancellable;
 
         gboolean                started;
         gboolean                wait_for_go;
@@ -89,6 +102,12 @@ static guint signals [LAST_SIGNAL] = { 0, };
 static void     gdm_manager_class_init  (GdmManagerClass *klass);
 static void     gdm_manager_init        (GdmManager      *manager);
 static void     gdm_manager_finalize    (GObject         *object);
+static void     on_initial_session_set_up (GdmDisplay   *display,
+                                           GAsyncResult *result,
+                                           GdmManager   *manager);
+static void create_session_for_display (GdmManager *manager,
+                                        GdmDisplay *display,
+                                        uid_t       allowed_user);
 
 static gpointer manager_object = NULL;
 
@@ -254,32 +273,241 @@ get_uid_for_session_id (GDBusConnection  *connection,
         return FALSE;
 }
 
+#ifdef WITH_SYSTEMD
 static gboolean
-lookup_by_session_id (const char *id,
-                      GdmDisplay *display,
-                      gpointer    user_data)
+activate_session_id_for_systemd (GdmManager   *manager,
+                                 const char *seat_id,
+                                 const char *session_id)
 {
-        const char *looking_for = user_data;
-        char *current;
-        gboolean res;
+        GError *error = NULL;
+        GVariant *reply;
+
+        reply = g_dbus_connection_call_sync (manager->priv->connection,
+                                             "org.freedesktop.login1",
+                                             "/org/freedesktop/login1",
+                                             "org.freedesktop.login1.Manager",
+                                             "ActivateSessionOnSeat",
+                                             g_variant_new ("(ss)", session_id, seat_id),
+                                             NULL, /* expected reply */
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL,
+                                             &error);
+        if (reply == NULL) {
+                g_debug ("GdmManager: logind 'ActivateSessionOnSeat' %s raised:\n %s\n\n",
+                         g_dbus_error_get_remote_error (error), error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        g_variant_unref (reply);
+
+        return TRUE;
+}
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+static gboolean
+activate_session_id_for_ck (GdmManager *manager,
+                            const char *seat_id,
+                            const char *session_id)
+{
+        GError *error = NULL;
+        GVariant *reply;
+
+        reply = g_dbus_connection_call_sync (manager->priv->connection,
+                                             CK_NAME,
+                                             seat_id,
+                                             "org.freedesktop.ConsoleKit.Seat",
+                                             "ActivateSession",
+                                             g_variant_new ("(o)", session_id),
+                                             NULL, /* expected reply */
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL,
+                                             &error);
+        if (reply == NULL) {
+                g_debug ("GdmManager: ConsoleKit %s raised:\n %s\n\n",
+                         g_dbus_error_get_remote_error (error), error->message);
+                g_error_free (error);
+                return FALSE;
+        }
 
-        current = gdm_display_get_session_id (display);
+        g_variant_unref (reply);
 
-        res = g_strcmp0 (current, looking_for) == 0;
+        return TRUE;
+}
+#endif
 
-        g_free (current);
+static gboolean
+activate_session_id (GdmManager *manager,
+                     const char *seat_id,
+                     const char *session_id)
+{
 
-        return res;
+#ifdef WITH_SYSTEMD
+        if (LOGIND_RUNNING()) {
+                return activate_session_id_for_systemd (manager, seat_id, session_id);
+        }
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+        return activate_session_id_for_ck (manager, seat_id, session_id);
+#else
+        return FALSE;
+#endif
 }
 
-static GdmDisplay *
-get_display_and_details_for_bus_sender (GdmManager       *self,
+#ifdef WITH_SYSTEMD
+static gboolean
+session_unlock_for_systemd (GdmManager *manager,
+                            const char *ssid)
+{
+        GError *error = NULL;
+        GVariant *reply;
+
+        reply = g_dbus_connection_call_sync (manager->priv->connection,
+                                             "org.freedesktop.login1",
+                                             "/org/freedesktop/login1",
+                                             "org.freedesktop.login1.Manager",
+                                             "UnlockSession",
+                                             g_variant_new ("(s)", ssid),
+                                             NULL, /* expected reply */
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL,
+                                             &error);
+        if (reply == NULL) {
+                g_debug ("GdmManager: logind 'UnlockSession' %s raised:\n %s\n\n",
+                         g_dbus_error_get_remote_error (error), error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        g_variant_unref (reply);
+
+        return TRUE;
+}
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+static gboolean
+session_unlock_for_ck (GdmManager *manager,
+                       const char *ssid)
+{
+        GError *error = NULL;
+        GVariant *reply;
+
+        reply = g_dbus_connection_call_sync (manager->priv->connection,
+                                             CK_NAME,
+                                             ssid,
+                                             CK_SESSION_INTERFACE,
+                                             "Unlock",
+                                             NULL, /* parameters */
+                                             NULL, /* expected reply */
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL,
+                                             &error);
+        if (reply == NULL) {
+                g_debug ("GdmManager: ConsoleKit %s raised:\n %s\n\n",
+                         g_dbus_error_get_remote_error (error), error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        g_variant_unref (reply);
+
+        return TRUE;
+}
+#endif
+
+static gboolean
+session_unlock (GdmManager *manager,
+                const char *ssid)
+{
+
+        g_debug ("Unlocking session %s", ssid);
+
+#ifdef WITH_SYSTEMD
+        if (LOGIND_RUNNING()) {
+                return session_unlock_for_systemd (manager, ssid);
+        }
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+        return session_unlock_for_ck (manager, ssid);
+#else
+        return TRUE;
+#endif
+}
+
+static GdmSession *
+find_session_for_user_on_seat (GdmManager *manager,
+                               const char *username,
+                               const char *seat_id,
+                               GdmSession *dont_count_session)
+{
+        GList *node;
+
+        for (node = manager->priv->user_sessions; node != NULL; node = node->next) {
+                GdmSession *candidate_session = node->data;
+                char *candidate_username, *candidate_seat_id;
+
+                if (candidate_session == dont_count_session)
+                        continue;
+
+                if (!gdm_session_is_running (candidate_session))
+                        continue;
+
+                candidate_username = gdm_session_get_username (candidate_session);
+                candidate_seat_id = gdm_session_get_display_seat_id (candidate_session);
+
+                if (g_strcmp0 (candidate_username, username) == 0 &&
+                    g_strcmp0 (candidate_seat_id, seat_id) == 0) {
+                        g_free (candidate_username);
+                        g_free (candidate_seat_id);
+
+                        return candidate_session;
+                }
+
+                g_free (candidate_username);
+                g_free (candidate_seat_id);
+        }
+
+        return NULL;
+}
+
+static GdmSession *
+find_session_with_id (GdmManager *manager,
+                      const char *id)
+{
+        GList *node;
+        for (node = manager->priv->user_sessions; node != NULL; node = node->next) {
+                GdmSession *candidate_session = node->data;
+                char *candidate_id;
+
+                candidate_id = gdm_session_get_session_id (candidate_session);
+                if (g_strcmp0 (id, candidate_id) == 0) {
+                        g_free (candidate_id);
+
+                        return candidate_session;
+                }
+
+                g_free (candidate_id);
+        }
+
+        return NULL;
+}
+
+static GdmSession *
+get_session_and_details_for_bus_sender (GdmManager       *self,
                             GDBusConnection  *connection,
                             const char       *sender,
                             GPid             *out_pid,
                             uid_t            *out_uid)
 {
-        GdmDisplay *display = NULL;
+        GdmSession *session = NULL;
         char       *session_id = NULL;
         GError     *error = NULL;
         int         ret;
@@ -325,20 +553,66 @@ get_display_and_details_for_bus_sender (GdmManager       *self,
                 goto out;
         }
 
-        display = gdm_display_store_find (self->priv->display_store,
-                                          lookup_by_session_id,
-                                          (gpointer) session_id);
+        session = find_session_with_id (self, session_id);
 out:
         g_free (session_id);
 
-        if (display != NULL) {
+        if (session != NULL) {
             if (out_pid != NULL)
                 *out_pid = pid;
 
             if (out_uid != NULL)
                 *out_uid = session_uid;
         }
-        return display;
+        return session;
+}
+
+static gboolean
+switch_to_compatible_user_session (GdmManager *manager,
+                                   GdmSession *session,
+                                   gboolean    fail_if_already_switched)
+{
+        gboolean    res;
+        gboolean    ret;
+        char       *username;
+        char       *seat_id;
+        char       *ssid_to_activate = NULL;
+        GdmSession *existing_session;
+
+        ret = FALSE;
+
+        username = gdm_session_get_username (session);
+        seat_id = gdm_session_get_display_seat_id (session);
+
+        if (!fail_if_already_switched) {
+                session = NULL;
+        }
+
+        existing_session = find_session_for_user_on_seat (manager, username, seat_id, session);
+
+        if (existing_session != NULL) {
+                ssid_to_activate = gdm_session_get_session_id (existing_session);
+                res = activate_session_id (manager, seat_id, ssid_to_activate);
+                if (! res) {
+                        g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate);
+                        goto out;
+                }
+
+                res = session_unlock (manager, ssid_to_activate);
+                if (!res) {
+                        /* this isn't fatal */
+                        g_debug ("GdmManager: unable to unlock session: %s", ssid_to_activate);
+                }
+        } else {
+                goto out;
+        }
+
+        ret = TRUE;
+
+ out:
+        g_free (ssid_to_activate);
+
+        return ret;
 }
 
 static gboolean
@@ -346,21 +620,21 @@ gdm_manager_handle_open_session (GdmDBusManager        *manager,
                                  GDBusMethodInvocation *invocation)
 {
         GdmManager       *self = GDM_MANAGER (manager);
-        const char       *sender = NULL;
+        const char       *sender;
         GError           *error = NULL;
         GDBusConnection  *connection;
-        GdmDisplay       *display;
+        GdmSession       *session;
         char             *address;
         GPid              pid;
-        uid_t             uid;
+        uid_t             uid, allowed_user;
 
         g_debug ("GdmManager: trying to open new session");
 
         sender = g_dbus_method_invocation_get_sender (invocation);
         connection = g_dbus_method_invocation_get_connection (invocation);
-        display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid);
+        session = get_session_and_details_for_bus_sender (self, connection, sender, &pid, &uid);
 
-        if (display == NULL) {
+        if (session == NULL) {
                 g_dbus_method_invocation_return_error_literal (invocation,
                                                                G_DBUS_ERROR,
                                                                G_DBUS_ERROR_ACCESS_DENIED,
@@ -369,7 +643,23 @@ gdm_manager_handle_open_session (GdmDBusManager        *manager,
                 return TRUE;
         }
 
-        address = gdm_display_open_session_sync (display, pid, uid, NULL, &error);
+        if (gdm_session_is_running (session)) {
+                error = g_error_new (G_DBUS_ERROR,
+                                     G_DBUS_ERROR_ACCESS_DENIED,
+                                     _("Can only be called before user is logged in"));
+                return FALSE;
+        }
+
+        allowed_user = gdm_session_get_allowed_user (session);
+
+        if (uid != allowed_user) {
+                error = g_error_new (G_DBUS_ERROR,
+                                     G_DBUS_ERROR_ACCESS_DENIED,
+                                     _("Caller not GDM"));
+                return FALSE;
+        }
+
+        address = gdm_session_get_server_address (session);
 
         if (address == NULL) {
                 g_dbus_method_invocation_return_gerror (invocation, error);
@@ -391,11 +681,9 @@ gdm_manager_handle_open_reauthentication_channel (GdmDBusManager        *manager
                                                   const char            *username)
 {
         GdmManager       *self = GDM_MANAGER (manager);
-        const char       *sender = NULL;
-        GError           *error = NULL;
+        const char       *sender;
+        GdmSession       *session;
         GDBusConnection  *connection;
-        GdmDisplay       *display;
-        char             *address;
         GPid              pid;
         uid_t             uid;
 
@@ -403,9 +691,9 @@ gdm_manager_handle_open_reauthentication_channel (GdmDBusManager        *manager
 
         sender = g_dbus_method_invocation_get_sender (invocation);
         connection = g_dbus_method_invocation_get_connection (invocation);
-        display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid);
+        session = get_session_and_details_for_bus_sender (self, connection, sender, &pid, &uid);
 
-        if (display == NULL) {
+        if (session == NULL) {
                 g_dbus_method_invocation_return_error_literal (invocation,
                                                                G_DBUS_ERROR,
                                                                G_DBUS_ERROR_ACCESS_DENIED,
@@ -414,23 +702,11 @@ gdm_manager_handle_open_reauthentication_channel (GdmDBusManager        *manager
                 return TRUE;
         }
 
-        address = gdm_display_open_reauthentication_channel_sync (display,
-                                                                  username,
-                                                                  pid,
-                                                                  uid,
-                                                                  NULL,
-                                                                  &error);
-
-        if (address == NULL) {
-                g_dbus_method_invocation_return_gerror (invocation, error);
-                g_error_free (error);
-                return TRUE;
-        }
+        gdm_session_start_reauthentication (session, pid, uid);
 
-        gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
-                                                                 invocation,
-                                                                 address);
-        g_free (address);
+        g_hash_table_insert (self->priv->open_reauthentication_requests,
+                             GINT_TO_POINTER (pid),
+                             invocation);
 
         return TRUE;
 }
@@ -443,6 +719,33 @@ manager_interface_init (GdmDBusManagerIface *interface)
 }
 
 static void
+on_display_status_changed (GdmDisplay *display,
+                           GParamSpec *arg1,
+                           GdmManager *manager)
+{
+        int         status;
+
+        status = gdm_display_get_status (display);
+
+        switch (status) {
+                case GDM_DISPLAY_MANAGED:
+                        gdm_display_set_up_initial_session (display,
+                                                            NULL,
+                                                            (GAsyncReadyCallback)
+                                                            on_initial_session_set_up,
+                                                            manager);
+                        break;
+                case GDM_DISPLAY_FAILED:
+                case GDM_DISPLAY_UNMANAGED:
+                case GDM_DISPLAY_FINISHED:
+                        break;
+                default:
+                        break;
+        }
+
+}
+
+static void
 on_display_removed (GdmDisplayStore *display_store,
                     const char      *id,
                     GdmManager      *manager)
@@ -450,14 +753,798 @@ on_display_removed (GdmDisplayStore *display_store,
         GdmDisplay *display;
 
         display = gdm_display_store_lookup (display_store, id);
-
         if (display != NULL) {
                 g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
 
+                g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), 
manager);
+
                 g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, id);
         }
 }
 
+static GdmDisplay *
+get_display_for_session (GdmManager *manager,
+                         GdmSession *session)
+{
+        return g_object_get_data (G_OBJECT (session), "gdm-display");
+}
+
+typedef struct
+{
+        GdmManager *manager;
+        GdmSession *session;
+        char *service_name;
+        guint idle_id;
+} StartUserSessionOperation;
+
+static void
+destroy_start_user_session_operation (StartUserSessionOperation *operation)
+{
+        g_object_set_data (G_OBJECT (operation->session),
+                           "start-user-session-operation",
+                           NULL);
+        g_object_unref (operation->session);
+        g_free (operation->service_name);
+        g_slice_free (StartUserSessionOperation, operation);
+}
+
+static void
+start_user_session (GdmManager *manager,
+                    GdmDisplay *display,
+                    StartUserSessionOperation *operation)
+{
+        if (display != NULL) {
+                char *auth_file;
+                char *username;
+
+                auth_file = NULL;
+                username = gdm_session_get_username (operation->session);
+                gdm_display_add_user_authorization (display,
+                                                    username,
+                                                    &auth_file,
+                                                    NULL);
+                g_free (username);
+
+                g_assert (auth_file != NULL);
+
+                g_object_set (operation->session,
+                              "user-x11-authority-file", auth_file,
+                              NULL);
+
+                g_free (auth_file);
+        }
+
+        gdm_session_start_session (operation->session,
+                                   operation->service_name);
+        destroy_start_user_session_operation (operation);
+}
+
+static void
+on_initial_session_stopped (GdmDisplay   *display,
+                            GAsyncResult *result,
+                            StartUserSessionOperation *operation)
+{
+        GError *error = NULL;
+        gboolean stopped;
+
+        stopped = gdm_display_stop_initial_session_finish (display, result, &error);
+
+        if (!stopped) {
+                g_warning ("Couldn't stop initial session on display: %s",
+                           error->message);
+                g_error_free (error);
+                gdm_display_unmanage (display);
+                gdm_display_finish (display);
+                return;
+        }
+
+        start_user_session (operation->manager, display, operation);
+}
+
+static gboolean
+on_start_user_session (StartUserSessionOperation *operation)
+{
+        gboolean migrated;
+        gboolean fail_if_already_switched = TRUE;
+
+        g_debug ("GdmManager: start or jump to session");
+
+        /* If there's already a session running, jump to it.
+         * If the only session running is the one we just opened,
+         * start a session on it.
+         */
+        migrated = switch_to_compatible_user_session (operation->manager, operation->session, 
fail_if_already_switched);
+
+        g_debug ("GdmManager: migrated: %d", migrated);
+        if (migrated) {
+                /* We don't stop the manager here because
+                   when Xorg exits it switches to the VT it was
+                   started from.  That interferes with fast
+                   user switching. */
+                gdm_session_reset (operation->session);
+                destroy_start_user_session_operation (operation);
+        } else {
+                GdmDisplay *display;
+                char *username;
+
+                display = get_display_for_session (operation->manager, operation->session);
+                username = gdm_session_get_username (operation->session);
+
+                gdm_display_stop_initial_session (display,
+                                                  username,
+                                                  NULL,
+                                                  (GAsyncReadyCallback)
+                                                  on_initial_session_stopped,
+                                                  operation);
+                g_free (username);
+        }
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+queue_start_user_session (GdmManager *manager,
+                          GdmSession *session,
+                          const char *service_name)
+{
+        StartUserSessionOperation *operation;
+
+        operation = g_slice_new0 (StartUserSessionOperation);
+        operation->manager = manager;
+        operation->session = g_object_ref (session);
+        operation->service_name = g_strdup (service_name);
+
+        operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
+        g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
+}
+
+static void
+start_user_session_if_ready (GdmManager *manager,
+                             GdmSession *session,
+                             const char *service_name)
+{
+        gboolean start_when_ready;
+
+        start_when_ready = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), "start-when-ready"));
+        if (start_when_ready) {
+                g_object_set_data (G_OBJECT (session), "waiting-to-start", GINT_TO_POINTER (FALSE));
+                queue_start_user_session (manager, session, service_name);
+        } else {
+                g_object_set_data (G_OBJECT (session), "waiting-to-start", GINT_TO_POINTER (TRUE));
+        }
+}
+
+static void
+on_session_opened (GdmSession       *session,
+                   const char       *service_name,
+                   const char       *session_id,
+                   GdmManager       *manager)
+{
+        manager->priv->user_sessions = g_list_append (manager->priv->user_sessions,
+                                                      g_object_ref (session));
+        if (g_strcmp0 (service_name, "gdm-autologin") == 0 &&
+            !gdm_session_client_is_connected (session)) {
+                /* If we're auto logging in then don't wait for the go-ahead from a greeter,
+                 * (since there is no greeter) */
+                g_object_set_data (G_OBJECT (session), "start-when-ready", GINT_TO_POINTER (TRUE));
+        }
+
+        start_user_session_if_ready (manager, session, service_name);
+}
+
+static void
+on_user_session_started (GdmSession *session,
+                         const char *service_name,
+                         int         pid,
+                         GdmManager *manager)
+{
+        GdmDisplay *display;
+
+        g_debug ("GdmManager: session started %d", pid);
+
+        display = get_display_for_session (manager, session);
+
+        if (display == NULL) {
+                return;
+        }
+}
+
+static void
+remove_user_session (GdmManager *manager,
+                     GdmSession *session)
+{
+        GList *node;
+        GdmDisplay *display;
+
+        display = get_display_for_session (manager, session);
+
+        if (display != NULL) {
+                gdm_display_unmanage (display);
+                gdm_display_finish (display);
+        }
+
+        node = g_list_find (manager->priv->user_sessions, session);
+
+        if (node != NULL) {
+                manager->priv->user_sessions = g_list_delete_link (manager->priv->user_sessions, node);
+                gdm_session_close (session);
+                g_object_unref (session);
+        }
+}
+
+static void
+on_user_session_exited (GdmSession *session,
+                        int         code,
+                        GdmManager *manager)
+{
+        g_debug ("GdmManager: session exited with status %d", code);
+        remove_user_session (manager, session);
+}
+
+static void
+on_user_session_died (GdmSession *session,
+                      int         signal_number,
+                      GdmManager *manager)
+{
+        g_debug ("GdmManager: session died with signal %s", strsignal (signal_number));
+        remove_user_session (manager, session);
+}
+
+static char *
+query_ck_for_display_device (GdmManager *manager,
+                             GdmDisplay *display)
+{
+        char    *out;
+        char    *command;
+        char    *display_name = NULL;
+        int      status;
+        gboolean res;
+        GError  *error;
+
+        g_object_get (G_OBJECT (display),
+                      "x11-display-name", &display_name,
+                      NULL);
+
+        error = NULL;
+        command = g_strdup_printf (CONSOLEKIT_DIR "/ck-get-x11-display-device --display %s",
+                                   display_name);
+        g_free (display_name);
+
+        g_debug ("GdmManager: Running helper %s", command);
+        out = NULL;
+        res = g_spawn_command_line_sync (command,
+                                         &out,
+                                         NULL,
+                                         &status,
+                                         &error);
+        if (! res) {
+                g_warning ("GdmManager: Could not run helper %s: %s", command, error->message);
+                g_error_free (error);
+        } else {
+                out = g_strstrip (out);
+                g_debug ("GdmManager: Got tty: '%s'", out);
+        }
+
+        g_free (command);
+
+        return out;
+}
+
+static char *
+get_display_device (GdmManager *manager,
+                    GdmDisplay *display)
+{
+#ifdef WITH_SYSTEMD
+        if (LOGIND_RUNNING()) {
+                /* systemd finds the display device out on its own based on the display */
+                return NULL;
+        }
+#endif
+
+        return query_ck_for_display_device (manager, display);
+}
+
+static void
+on_ready_to_request_timed_login (GdmSession         *session,
+                                 GSimpleAsyncResult *result,
+                                 gpointer           *user_data)
+{
+        int delay = GPOINTER_TO_INT (user_data);
+        GCancellable *cancellable;
+        char         *username;
+
+        cancellable = g_object_get_data (G_OBJECT (result),
+                                         "cancellable");
+        if (g_cancellable_is_cancelled (cancellable)) {
+                return;
+        }
+
+        username = g_simple_async_result_get_source_tag (result);
+
+        gdm_session_request_timed_login (session, username, delay);
+
+        g_object_weak_unref (G_OBJECT (session),
+                             (GWeakNotify)
+                             g_cancellable_cancel,
+                             cancellable);
+        g_object_weak_unref (G_OBJECT (session),
+                             (GWeakNotify)
+                             g_object_unref,
+                             cancellable);
+        g_object_weak_unref (G_OBJECT (session),
+                             (GWeakNotify)
+                             g_free,
+                             username);
+
+        g_free (username);
+}
+
+static gboolean
+on_wait_for_greeter_timeout (GSimpleAsyncResult *result)
+{
+        g_simple_async_result_complete (result);
+
+        return FALSE;
+}
+
+static void
+on_session_reauthenticated (GdmSession *session,
+                            const char *service_name,
+                            GdmManager *manager)
+{
+        gboolean fail_if_already_switched = FALSE;
+        /* There should already be a session running, so jump to its
+         * VT. In the event we're already on the right VT, (i.e. user
+         * used an unlock screen instead of a user switched login screen),
+         * then silently succeed and unlock the session.
+         */
+        switch_to_compatible_user_session (manager, session, fail_if_already_switched);
+}
+
+static void
+on_session_client_ready_for_session_to_start (GdmSession      *session,
+                                              const char      *service_name,
+                                              gboolean         client_is_ready,
+                                              GdmManager      *manager)
+{
+        gboolean waiting_to_start_user_session;
+
+        if (client_is_ready) {
+                g_debug ("GdmManager: Will start session when ready");
+        } else {
+                g_debug ("GdmManager: Will start session when ready and told");
+        }
+
+        waiting_to_start_user_session = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session),
+                                                                       "waiting-to-start"));
+
+        g_object_set_data (G_OBJECT (session),
+                           "start-when-ready",
+                           GINT_TO_POINTER (client_is_ready));
+
+        if (client_is_ready && waiting_to_start_user_session) {
+                start_user_session_if_ready (manager, session, service_name);
+        }
+}
+
+static void
+on_session_client_connected (GdmSession      *session,
+                             GCredentials    *credentials,
+                             GPid             pid_of_client,
+                             GdmManager      *manager)
+{
+        GdmDisplay *display;
+        gboolean timed_login_enabled;
+        char    *username;
+        int      delay;
+        gboolean enabled, display_is_local;
+
+        g_debug ("GdmManager: client connected");
+
+        display = get_display_for_session (manager, session);
+
+        if (display == NULL) {
+                return;
+        }
+
+        g_object_get (display, "is-local", &display_is_local, NULL);
+
+        timed_login_enabled = FALSE;
+        gdm_display_get_timed_login_details (display, &enabled, &username, &delay, NULL);
+
+        if (! timed_login_enabled) {
+                return;
+        }
+
+        /* temporary hack to fix timed login
+         * http://bugzilla.gnome.org/680348
+         */
+        if (delay > 0) {
+                GSimpleAsyncResult *result;
+                GCancellable       *cancellable;
+                guint               timeout_id;
+                gpointer            source_tag;
+
+                delay = MAX (delay, 4);
+
+                cancellable = g_cancellable_new ();
+                source_tag = g_strdup (username);
+                result = g_simple_async_result_new (G_OBJECT (session),
+                                                    (GAsyncReadyCallback)
+                                                    on_ready_to_request_timed_login,
+                                                    GINT_TO_POINTER (delay),
+                                                    source_tag);
+                g_simple_async_result_set_check_cancellable (result, cancellable);
+                g_object_set_data (G_OBJECT (result),
+                                   "cancellable",
+                                   cancellable);
+
+                timeout_id = g_timeout_add_seconds_full (delay - 2,
+                                                         G_PRIORITY_DEFAULT,
+                                                         (GSourceFunc)
+                                                         on_wait_for_greeter_timeout,
+                                                         g_object_ref (result),
+                                                         (GDestroyNotify)
+                                                         g_object_unref);
+                g_cancellable_connect (cancellable,
+                                       G_CALLBACK (g_source_remove),
+                                       GINT_TO_POINTER (timeout_id),
+                                       NULL);
+
+                g_object_weak_ref (G_OBJECT (session),
+                                   (GWeakNotify)
+                                   g_cancellable_cancel,
+                                   cancellable);
+                g_object_weak_ref (G_OBJECT (session),
+                                   (GWeakNotify)
+                                   g_object_unref,
+                                   cancellable);
+                g_object_weak_ref (G_OBJECT (session),
+                                   (GWeakNotify)
+                                   g_free,
+                                   source_tag);
+        }
+
+        g_free (username);
+}
+
+static void
+on_session_client_disconnected (GdmSession   *session,
+                                GCredentials *credentials,
+                                GPid          pid_of_client,
+                                GdmManager   *manager)
+{
+        GdmDisplay *display;
+        gboolean display_is_local;
+
+        g_debug ("GdmManager: client disconnected");
+
+        display = get_display_for_session (manager, session);
+
+        if (display == NULL) {
+                return;
+        }
+
+        g_object_get (G_OBJECT (display),
+                      "is-local", &display_is_local,
+                      NULL);
+
+        if ( ! display_is_local && gdm_session_is_running (session)) {
+                gdm_display_unmanage (display);
+                gdm_display_finish (display);
+        }
+}
+
+typedef struct
+{
+        GdmManager *manager;
+        GdmSession *session;
+        guint idle_id;
+} ResetSessionOperation;
+
+static void
+destroy_reset_session_operation (ResetSessionOperation *operation)
+{
+        g_object_set_data (G_OBJECT (operation->session),
+                           "reset-session-operation",
+                           NULL);
+        g_object_unref (operation->session);
+        g_slice_free (ResetSessionOperation, operation);
+}
+
+static gboolean
+on_reset_session (ResetSessionOperation *operation)
+{
+        gdm_session_reset (operation->session);
+
+        destroy_reset_session_operation (operation);
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+queue_session_reset (GdmManager *manager,
+                     GdmSession *session)
+{
+        ResetSessionOperation *operation;
+
+        operation = g_object_get_data (G_OBJECT (session), "reset-session-operation");
+
+        if (operation != NULL) {
+                return;
+        }
+
+        operation = g_slice_new0 (ResetSessionOperation);
+        operation->manager = manager;
+        operation->session = g_object_ref (session);
+        operation->idle_id = g_idle_add ((GSourceFunc) on_reset_session, operation);
+
+        g_object_set_data (G_OBJECT (session), "reset-session-operation", operation);
+}
+
+static void
+on_session_cancelled (GdmSession  *session,
+                      GdmManager  *manager)
+{
+        g_debug ("GdmManager: Session was cancelled");
+        queue_session_reset (manager, session);
+}
+
+static void
+on_session_conversation_started (GdmSession *session,
+                                 const char *service_name,
+                                 GdmManager *manager)
+{
+        GdmDisplay *display;
+        gboolean    enabled;
+        char       *username;
+        int         delay;
+
+        g_debug ("GdmManager: session conversation started for service %s", service_name);
+
+        if (g_strcmp0 (service_name, "gdm-autologin") != 0) {
+                return;
+        }
+
+        display = get_display_for_session (manager, session);
+
+        if (display == NULL) {
+                g_debug ("GdmManager: conversation has no associated display");
+                return;
+        }
+
+        enabled = FALSE;
+        gdm_display_get_timed_login_details (display, &enabled, &username, &delay, NULL);
+        if (! enabled) {
+                return;
+        }
+
+        if (delay == 0) {
+                g_debug ("GdmManager: begin auto login for user '%s'", username);
+                /* service_name will be "gdm-autologin"
+                 */
+                gdm_session_setup_for_user (session, service_name, username);
+        }
+
+        g_free (username);
+}
+
+static void
+on_session_conversation_stopped (GdmSession *session,
+                                 const char *service_name,
+                                 GdmManager *manager)
+{
+        g_debug ("GdmManager: session conversation '%s' stopped", service_name);
+}
+
+static void
+on_session_reauthentication_started (GdmSession *session,
+                                     int         pid_of_caller,
+                                     const char *address,
+                                     GdmManager *manager)
+{
+        GDBusMethodInvocation *invocation;
+        gpointer               source_tag;
+
+        g_debug ("GdmManager: reauthentication started");
+
+        source_tag = GINT_TO_POINTER (pid_of_caller);
+
+        invocation = g_hash_table_lookup (manager->priv->open_reauthentication_requests,
+                                          source_tag);
+
+        if (invocation != NULL) {
+                gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
+                                                                         invocation,
+                                                                         address);
+        }
+
+        g_hash_table_remove (manager->priv->open_reauthentication_requests,
+                             source_tag);
+}
+
+static void
+start_autologin_conversation_if_necessary (GdmManager *manager,
+                                           GdmDisplay *display,
+                                           GdmSession *session)
+{
+        gboolean enabled;
+
+        if (g_file_test (GDM_RAN_ONCE_MARKER_FILE, G_FILE_TEST_EXISTS)) {
+                return;
+        }
+
+        gdm_display_get_timed_login_details (display, &enabled, NULL, NULL, NULL);
+
+        if (!enabled) {
+                return;
+        }
+
+        g_debug ("GdmManager: Starting automatic login conversation");
+        gdm_session_start_conversation (session, "gdm-autologin");
+}
+
+static void
+touch_marker_file (GdmManager *manager)
+{
+        int fd;
+
+        fd = g_creat (GDM_RAN_ONCE_MARKER_FILE, 0644);
+
+        if (fd < 0 && errno != EEXIST) {
+                g_warning ("could not create %s to mark run, this may cause auto login "
+                           "to repeat: %m", GDM_RAN_ONCE_MARKER_FILE);
+                return;
+        }
+
+        fsync (fd);
+        close (fd);
+}
+
+static void
+on_initial_session_started (GdmDisplay   *display,
+                            GAsyncResult *result,
+                            GdmManager   *manager)
+{
+        GError *error = NULL;
+        if (!gdm_display_start_initial_session_finish (display, result, &error)) {
+                g_warning ("GdmManager: couldn't start initial session: %s", error->message);
+                gdm_display_unmanage (display);
+                gdm_display_finish (display);
+                return;
+        }
+}
+
+static void
+create_session_for_display (GdmManager *manager,
+                            GdmDisplay *display,
+                            uid_t       allowed_user)
+{
+        GdmSession *session;
+        gboolean    display_is_local = FALSE;
+        char       *display_name = NULL;
+        char       *display_device = NULL;
+        char       *remote_hostname = NULL;
+        char       *display_auth_file = NULL;
+        char       *display_seat_id = NULL;
+        char       *display_id = NULL;
+
+        g_object_get (G_OBJECT (display),
+                      "id", &display_id,
+                      "x11-display-name", &display_name,
+                      "is-local", &display_is_local,
+                      "remote-hostname", &remote_hostname,
+                      "x11-authority-file", &display_auth_file,
+                      "seat-id", &display_seat_id,
+                      NULL);
+        display_device = get_display_device (manager, display);
+
+        session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_LOGIN,
+                                   allowed_user,
+                                   display_name,
+                                   remote_hostname,
+                                   display_device,
+                                   display_seat_id,
+                                   display_auth_file,
+                                   display_is_local,
+                                   NULL);
+        g_free (display_name);
+        g_free (remote_hostname);
+        g_free (display_auth_file);
+        g_free (display_seat_id);
+
+        g_signal_connect (session,
+                          "reauthentication-started",
+                          G_CALLBACK (on_session_reauthentication_started),
+                          manager);
+        g_signal_connect (session,
+                          "reauthenticated",
+                          G_CALLBACK (on_session_reauthenticated),
+                          manager);
+        g_signal_connect (session,
+                          "client-ready-for-session-to-start",
+                          G_CALLBACK (on_session_client_ready_for_session_to_start),
+                          manager);
+        g_signal_connect (session,
+                          "client-connected",
+                          G_CALLBACK (on_session_client_connected),
+                          manager);
+        g_signal_connect (session,
+                          "client-disconnected",
+                          G_CALLBACK (on_session_client_disconnected),
+                          manager);
+        g_signal_connect (session,
+                          "cancelled",
+                          G_CALLBACK (on_session_cancelled),
+                          manager);
+        g_signal_connect (session,
+                          "conversation-started",
+                          G_CALLBACK (on_session_conversation_started),
+                          manager);
+        g_signal_connect (session,
+                          "conversation-stopped",
+                          G_CALLBACK (on_session_conversation_stopped),
+                          manager);
+        g_signal_connect (session,
+                          "session-opened",
+                          G_CALLBACK (on_session_opened),
+                          manager);
+        g_signal_connect (session,
+                          "session-started",
+                          G_CALLBACK (on_user_session_started),
+                          manager);
+        g_signal_connect (session,
+                          "session-exited",
+                          G_CALLBACK (on_user_session_exited),
+                          manager);
+        g_signal_connect (session,
+                          "session-died",
+                          G_CALLBACK (on_user_session_died),
+                          manager);
+        g_object_set_data (G_OBJECT (session), "gdm-display", display);
+        g_object_set_data_full (G_OBJECT (display), "gdm-session", g_object_ref (session), (GDestroyNotify) 
g_object_unref);
+
+        start_autologin_conversation_if_necessary (manager, display, session);
+        touch_marker_file (manager);
+}
+
+static void
+on_initial_session_set_up (GdmDisplay   *display,
+                           GAsyncResult *result,
+                           GdmManager   *manager)
+{
+        GError *error = NULL;
+        char *allowed_user;
+        struct passwd *passwd_entry;
+
+        allowed_user = gdm_display_set_up_initial_session_finish (display, result, &error);
+
+        if (allowed_user == NULL) {
+                g_warning ("Couldn't start initial session on display: %s",
+                           error->message);
+                g_error_free (error);
+                gdm_display_unmanage (display);
+                gdm_display_finish (display);
+                return;
+        }
+
+        if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
+                g_warning ("GdmManager: couldn't look up username %s",
+                           allowed_user);
+                gdm_display_finish (display);
+                return;
+        }
+
+        create_session_for_display (manager, display, passwd_entry->pw_uid);
+        g_free (allowed_user);
+
+        gdm_display_start_initial_session (display,
+                                           NULL,
+                                           (GAsyncReadyCallback)
+                                           on_initial_session_started,
+                                           manager);
+}
+
 static void
 on_display_added (GdmDisplayStore *display_store,
                   const char      *id,
@@ -470,6 +1557,10 @@ on_display_added (GdmDisplayStore *display_store,
         if (display != NULL) {
                 g_dbus_object_manager_server_export (manager->priv->object_manager,
                                                      gdm_display_get_object_skeleton (display));
+
+                g_signal_connect (display, "notify::status",
+                                  G_CALLBACK (on_display_status_changed),
+                                  manager);
                 g_signal_emit (manager, signals[DISPLAY_ADDED], 0, id);
         }
 }
@@ -774,7 +1865,13 @@ gdm_manager_init (GdmManager *manager)
         manager->priv = GDM_MANAGER_GET_PRIVATE (manager);
 
         manager->priv->display_store = gdm_display_store_new ();
-
+        manager->priv->user_sessions = NULL;
+        manager->priv->open_reauthentication_requests = g_hash_table_new_full (NULL,
+                                                                               NULL,
+                                                                               (GDestroyNotify)
+                                                                               NULL,
+                                                                               (GDestroyNotify)
+                                                                               g_object_unref);
         g_signal_connect (G_OBJECT (manager->priv->display_store),
                           "display-added",
                           G_CALLBACK (on_display_added),
@@ -811,6 +1908,9 @@ gdm_manager_finalize (GObject *object)
         g_clear_object (&manager->priv->xdmcp_factory);
 #endif
         g_clear_object (&manager->priv->local_factory);
+        g_hash_table_unref (manager->priv->open_reauthentication_requests);
+        g_list_free_full (manager->priv->user_sessions, (GDestroyNotify) g_object_unref);
+        manager->priv->user_sessions = NULL;
 
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
                                               G_CALLBACK (on_display_added),
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index d83216b..749d682 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -70,10 +70,8 @@
 struct GdmSimpleSlavePrivate
 {
         GPid               pid;
+        char              *username;
         gint               greeter_reset_id;
-        guint              start_session_id;
-
-        char              *start_session_service_name;
 
         int                ping_interval;
 
@@ -82,22 +80,14 @@ struct GdmSimpleSlavePrivate
 
         GdmServer         *server;
 
-        /* we control the user session */
-        GdmSession        *session;
-
         /* this spawns and controls the greeter session */
         GdmLaunchEnvironment *greeter_environment;
 
-        GHashTable        *open_reauthentication_requests;
-
         GDBusProxy        *accountsservice_proxy;
         guint              have_existing_user_accounts : 1;
         guint              accountsservice_ready : 1;
         guint              waiting_to_connect_to_display : 1;
 
-        guint              start_session_when_ready : 1;
-        guint              waiting_to_start_session : 1;
-        guint              session_is_running : 1;
 #ifdef  HAVE_LOGINDEVPERM
         gboolean           use_logindevperm;
 #endif
@@ -114,22 +104,10 @@ enum {
 static void     gdm_simple_slave_class_init     (GdmSimpleSlaveClass *klass);
 static void     gdm_simple_slave_init           (GdmSimpleSlave      *simple_slave);
 static void     gdm_simple_slave_finalize       (GObject             *object);
-static void     gdm_simple_slave_open_reauthentication_channel (GdmSlave             *slave,
-                                                                const char           *username,
-                                                                GPid                  pid_of_caller,
-                                                                uid_t                 uid_of_caller,
-                                                                GAsyncReadyCallback   callback,
-                                                                gpointer              user_data,
-                                                                GCancellable         *cancellable);
 
 static gboolean wants_initial_setup (GdmSimpleSlave *slave);
 G_DEFINE_TYPE (GdmSimpleSlave, gdm_simple_slave, GDM_TYPE_SLAVE)
 
-static void create_new_session (GdmSimpleSlave  *slave);
-static void start_session      (GdmSimpleSlave  *slave);
-static void queue_start_session (GdmSimpleSlave *slave,
-                                 const char     *service_name);
-
 static gboolean
 chown_file (GFile   *file,
             uid_t    uid,
@@ -247,38 +225,6 @@ out:
         g_free (gis_dir_path);
 }
 
-static void
-on_session_started (GdmSession       *session,
-                    const char       *service_name,
-                    int               pid,
-                    GdmSimpleSlave   *slave)
-{
-        char *username;
-        char *session_id;
-
-        g_debug ("GdmSimpleSlave: session started %d", pid);
-
-        slave->priv->session_is_running = TRUE;
-
-        session_id = gdm_session_get_session_id (session);
-        g_object_set (GDM_SLAVE (slave), "session-id", session_id, NULL);
-        g_free (session_id);
-
-        /* Run the PreSession script. gdmslave suspends until script has terminated */
-        username = gdm_session_get_username (slave->priv->session);
-        if (username != NULL) {
-                gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/PreSession", username);
-        }
-        g_free (username);
-
-        /* FIXME: should we do something here?
-         * Note that error return status from PreSession script should
-         * be ignored in the case of a X-GDM-BypassXsession session, which can
-         * be checked by calling:
-         * gdm_session_bypasses_xsession (session)
-         */
-}
-
 #ifdef  HAVE_LOGINDEVPERM
 static void
 gdm_simple_slave_grant_console_permissions (GdmSimpleSlave *slave)
@@ -350,53 +296,10 @@ gdm_simple_slave_revoke_console_permissions (GdmSimpleSlave *slave)
 #endif  /* HAVE_LOGINDEVPERM */
 
 static void
-on_session_exited (GdmSession       *session,
-                   int               exit_code,
-                   GdmSimpleSlave   *slave)
+reset_session (GdmSimpleSlave *slave)
 {
-        g_object_set (GDM_SLAVE (slave), "session-id", NULL, NULL);
-
-        g_debug ("GdmSimpleSlave: session exited with code %d\n", exit_code);
-        gdm_slave_stop (GDM_SLAVE (slave));
-}
-
-static void
-on_session_died (GdmSession       *session,
-                 int               signal_number,
-                 GdmSimpleSlave   *slave)
-{
-        g_object_set (GDM_SLAVE (slave), "session-id", NULL, NULL);
-
-        g_debug ("GdmSimpleSlave: session died with signal %d, (%s)",
-                 signal_number,
-                 g_strsignal (signal_number));
-        gdm_slave_stop (GDM_SLAVE (slave));
-}
-
-static gboolean
-add_user_authorization (GdmSimpleSlave *slave,
-                        char          **filename)
-{
-        char    *username;
-        gboolean ret;
-
-        username = gdm_session_get_username (slave->priv->session);
-        ret = gdm_slave_add_user_authorization (GDM_SLAVE (slave),
-                                                username,
-                                                filename);
-        g_free (username);
-
-        return ret;
-}
-
-static void
-reset_session (GdmSimpleSlave  *slave)
-{
-        if (slave->priv->session == NULL) {
-                return;
-        }
-
-        gdm_session_reset (slave->priv->session);
+        /* emit session reset signal here for the main daemon
+           process to pick up */
 }
 
 static gboolean
@@ -421,42 +324,8 @@ queue_greeter_reset (GdmSimpleSlave  *slave)
 }
 
 static void
-gdm_simple_slave_start_session_when_ready (GdmSimpleSlave *slave,
-                                           const char     *service_name)
-{
-        if (slave->priv->start_session_when_ready) {
-                slave->priv->waiting_to_start_session = FALSE;
-                queue_start_session (slave, service_name);
-        } else {
-                slave->priv->waiting_to_start_session = TRUE;
-        }
-}
-
-static gboolean
-switch_to_and_unlock_session (GdmSimpleSlave  *slave,
-                              gboolean         fail_if_already_switched)
-{
-        char    *username;
-        char    *session_id;
-        gboolean res;
-
-        username = gdm_session_get_username (slave->priv->session);
-        session_id = gdm_session_get_session_id (slave->priv->session);
-
-        g_debug ("GdmSimpleSlave: trying to switch to session for user %s", username);
-
-        /* try to switch to an existing session */
-        res = gdm_slave_switch_to_user_session (GDM_SLAVE (slave), username, session_id, 
fail_if_already_switched);
-        g_free (username);
-        g_free (session_id);
-
-        return res;
-}
-
-static void
 stop_greeter (GdmSimpleSlave *slave)
 {
-        char *username;
         gboolean script_successful;
 
         g_debug ("GdmSimpleSlave: Stopping greeter");
@@ -467,22 +336,15 @@ stop_greeter (GdmSimpleSlave *slave)
         }
 
         /* Run the PostLogin script. gdmslave suspends until script has terminated */
-        username = NULL;
-        if (slave->priv->session != NULL) {
-                username = gdm_session_get_username (slave->priv->session);
-        }
-
-        if (username != NULL) {
-                script_successful = gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/PostLogin", 
username);
+        if (slave->priv->username != NULL) {
+                script_successful = gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/PostLogin", 
slave->priv->username);
         } else {
                 script_successful = TRUE;
         }
-        g_free (username);
 
         if (!script_successful) {
                 g_debug ("GdmSimpleSlave: PostLogin script unsuccessful");
 
-                slave->priv->start_session_id = 0;
                 queue_greeter_reset (slave);
                 return;
         }
@@ -491,492 +353,6 @@ stop_greeter (GdmSimpleSlave *slave)
 }
 
 static void
-start_session (GdmSimpleSlave  *slave)
-{
-        char           *auth_file;
-
-        auth_file = NULL;
-        add_user_authorization (slave, &auth_file);
-
-        g_assert (auth_file != NULL);
-
-        g_object_set (slave->priv->session,
-                      "user-x11-authority-file", auth_file,
-                      NULL);
-
-        g_free (auth_file);
-
-        if (slave->priv->doing_initial_setup) {
-                chown_initial_setup_home_dir ();
-        }
-
-        gdm_session_start_session (slave->priv->session,
-                                   slave->priv->start_session_service_name);
-
-        slave->priv->start_session_id = 0;
-        g_free (slave->priv->start_session_service_name);
-        slave->priv->start_session_service_name = NULL;
-}
-
-static gboolean
-start_session_timeout (GdmSimpleSlave  *slave)
-{
-        gboolean migrated;
-        gboolean fail_if_already_switched = TRUE;
-
-        g_debug ("GdmSimpleSlave: accredited");
-
-        /* If there's already a session running, jump to it.
-         * If the only session running is the one we just opened,
-         * start a session on it.
-         *
-         * We assume we're in the former case if we need to switch
-         * VTs, and we assume we're in the latter case if we don't.
-         */
-        migrated = switch_to_and_unlock_session (slave, fail_if_already_switched);
-        g_debug ("GdmSimpleSlave: migrated: %d", migrated);
-        if (migrated) {
-                /* We don't stop the slave here because
-                   when Xorg exits it switches to the VT it was
-                   started from.  That interferes with fast
-                   user switching. */
-                gdm_session_reset (slave->priv->session);
-
-                slave->priv->start_session_id = 0;
-                g_free (slave->priv->start_session_service_name);
-                slave->priv->start_session_service_name = NULL;
-        } else {
-                if (slave->priv->greeter_environment == NULL) {
-                        /* auto login */
-                        start_session (slave);
-                } else {
-                        /* Session actually gets started from on_greeter_environment_session_stop */
-                        stop_greeter (slave);
-                }
-        }
-
-        return FALSE;
-}
-
-static void
-queue_start_session (GdmSimpleSlave *slave,
-                     const char     *service_name)
-{
-        if (slave->priv->start_session_id > 0) {
-                return;
-        }
-
-        slave->priv->start_session_id = g_idle_add ((GSourceFunc)start_session_timeout, slave);
-        slave->priv->start_session_service_name = g_strdup (service_name);
-}
-
-static void
-on_session_reauthenticated (GdmSession       *session,
-                            const char       *service_name,
-                            GdmSimpleSlave   *slave)
-{
-        gboolean fail_if_already_switched = FALSE;
-
-        /* There should already be a session running, so jump to it's
-         * VT. In the event we're already on the right VT, (i.e. user
-         * used an unlock screen instead of a user switched login screen),
-         * then silently succeed and unlock the session.
-         */
-        switch_to_and_unlock_session (slave, fail_if_already_switched);
-}
-
-static void
-on_session_opened (GdmSession       *session,
-                   const char       *service_name,
-                   const char       *session_id,
-                   GdmSimpleSlave   *slave)
-{
-
-#ifdef  HAVE_LOGINDEVPERM
-        gdm_simple_slave_grant_console_permissions (slave);
-#endif  /* HAVE_LOGINDEVPERM */
-
-        if (g_strcmp0 (service_name, "gdm-autologin") == 0 &&
-            !gdm_session_client_is_connected (slave->priv->session)) {
-                /* If we're auto logging in then don't wait for the go-ahead from a greeter,
-                 * (since there is no greeter) */
-                slave->priv->start_session_when_ready = TRUE;
-        }
-
-        gdm_simple_slave_start_session_when_ready (slave, service_name);
-}
-
-static void
-on_session_conversation_started (GdmSession       *session,
-                                 const char       *service_name,
-                                 GdmSimpleSlave   *slave)
-{
-        gboolean enabled;
-        char    *username;
-        int      delay;
-
-        g_debug ("GdmSimpleSlave: session conversation started for service %s", service_name);
-
-        if (g_strcmp0 (service_name, "gdm-autologin") != 0) {
-                return;
-        }
-
-        enabled = FALSE;
-        gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, &username, &delay);
-        if (! enabled) {
-                return;
-        }
-
-        if (delay == 0) {
-                g_debug ("GdmSimpleSlave: begin auto login for user '%s'", username);
-                /* service_name will be "gdm-autologin"
-                 */
-                gdm_session_setup_for_user (slave->priv->session, service_name, username);
-        }
-
-        g_free (username);
-}
-
-static void
-on_session_conversation_stopped (GdmSession       *session,
-                                 const char       *service_name,
-                                 GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: conversation stopped");
-
-}
-
-static void
-start_autologin_conversation_if_necessary (GdmSimpleSlave  *slave)
-{
-        gboolean enabled;
-
-        if (g_file_test (GDM_RAN_ONCE_MARKER_FILE, G_FILE_TEST_EXISTS)) {
-                return;
-        }
-
-        gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, NULL, NULL);
-
-        if (!enabled) {
-                return;
-        }
-
-        g_debug ("GdmSimpleSlave: Starting automatic login conversation");
-        gdm_session_start_conversation (slave->priv->session, "gdm-autologin");
-}
-
-static void
-on_session_reauthentication_started (GdmSession      *session,
-                                     int              pid_of_caller,
-                                     const char      *address,
-                                     GdmSimpleSlave  *slave)
-{
-        GSimpleAsyncResult *result;
-        gpointer            source_tag;
-
-        g_debug ("GdmSimpleSlave: reauthentication started");
-
-        source_tag = GINT_TO_POINTER (pid_of_caller);
-
-        result = g_hash_table_lookup (slave->priv->open_reauthentication_requests,
-                                      source_tag);
-
-        if (result != NULL) {
-                g_simple_async_result_set_op_res_gpointer (result,
-                                                           g_strdup (address),
-                                                           (GDestroyNotify)
-                                                           g_free);
-                g_simple_async_result_complete_in_idle (result);
-        }
-
-        g_hash_table_remove (slave->priv->open_reauthentication_requests,
-                             source_tag);
-}
-
-static void
-on_session_client_ready_for_session_to_start (GdmSession      *session,
-                                              const char      *service_name,
-                                              gboolean         client_is_ready,
-                                              GdmSimpleSlave  *slave)
-{
-        if (client_is_ready) {
-                g_debug ("GdmSimpleSlave: Will start session when ready");
-        } else {
-                g_debug ("GdmSimpleSlave: Will start session when ready and told");
-        }
-
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-
-        slave->priv->start_session_when_ready = client_is_ready;
-
-        if (client_is_ready && slave->priv->waiting_to_start_session) {
-                gdm_simple_slave_start_session_when_ready (slave, service_name);
-        }
-}
-
-static void
-on_ready_to_request_timed_login (GdmSession         *session,
-                                 GSimpleAsyncResult *result,
-                                 gpointer           *user_data)
-{
-        int delay = GPOINTER_TO_INT (user_data);
-        GCancellable *cancellable;
-        char         *username;
-
-        cancellable = g_object_get_data (G_OBJECT (result),
-                                         "cancellable");
-        if (g_cancellable_is_cancelled (cancellable)) {
-                return;
-        }
-
-        username = g_simple_async_result_get_source_tag (result);
-
-        gdm_session_request_timed_login (session, username, delay);
-
-        g_object_weak_unref (G_OBJECT (session),
-                             (GWeakNotify)
-                             g_cancellable_cancel,
-                             cancellable);
-        g_object_weak_unref (G_OBJECT (session),
-                             (GWeakNotify)
-                             g_object_unref,
-                             cancellable);
-        g_object_weak_unref (G_OBJECT (session),
-                             (GWeakNotify)
-                             g_free,
-                             username);
-
-        g_free (username);
-}
-
-static gboolean
-on_wait_for_greeter_timeout (GSimpleAsyncResult *result)
-{
-        g_simple_async_result_complete (result);
-
-        return FALSE;
-}
-
-static void
-on_session_client_connected (GdmSession          *session,
-                             GCredentials        *credentials,
-                             GPid                 pid_of_client,
-                             GdmSimpleSlave      *slave)
-{
-        gboolean timed_login_enabled;
-        char    *username;
-        int      delay;
-        gboolean display_is_local;
-
-        g_debug ("GdmSimpleSlave: client connected");
-
-        g_object_get (slave,
-                      "display-is-local", &display_is_local,
-                      NULL);
-
-        /* If XDMCP stop pinging */
-        if ( ! display_is_local) {
-                alarm (0);
-        }
-
-        timed_login_enabled = FALSE;
-        gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &timed_login_enabled, &username, &delay);
-
-        if (! timed_login_enabled) {
-                return;
-        }
-
-        /* temporary hack to fix timed login
-         * http://bugzilla.gnome.org/680348
-         */
-        if (delay > 0) {
-                GSimpleAsyncResult *result;
-                GCancellable       *cancellable;
-                guint               timeout_id;
-                gpointer            source_tag;
-
-                delay = MAX (delay, 4);
-
-                cancellable = g_cancellable_new ();
-                source_tag = g_strdup (username);
-                result = g_simple_async_result_new (G_OBJECT (session),
-                                                    (GAsyncReadyCallback)
-                                                    on_ready_to_request_timed_login,
-                                                    GINT_TO_POINTER (delay),
-                                                    source_tag);
-                g_simple_async_result_set_check_cancellable (result, cancellable);
-                g_object_set_data (G_OBJECT (result),
-                                   "cancellable",
-                                   cancellable);
-
-                timeout_id = g_timeout_add_seconds_full (delay - 2,
-                                                         G_PRIORITY_DEFAULT,
-                                                         (GSourceFunc)
-                                                         on_wait_for_greeter_timeout,
-                                                         g_object_ref (result),
-                                                         (GDestroyNotify)
-                                                         g_object_unref);
-                g_cancellable_connect (cancellable,
-                                       G_CALLBACK (g_source_remove),
-                                       GINT_TO_POINTER (timeout_id),
-                                       NULL);
-
-                g_object_weak_ref (G_OBJECT (session),
-                                   (GWeakNotify)
-                                   g_cancellable_cancel,
-                                   cancellable);
-                g_object_weak_ref (G_OBJECT (session),
-                                   (GWeakNotify)
-                                   g_object_unref,
-                                   cancellable);
-                g_object_weak_ref (G_OBJECT (session),
-                                   (GWeakNotify)
-                                   g_free,
-                                   source_tag);
-        }
-
-        g_free (username);
-}
-
-static void
-on_session_client_disconnected (GdmSession          *session,
-                                GCredentials        *credentials,
-                                GPid                 pid_of_client,
-                                GdmSimpleSlave      *slave)
-{
-        g_debug ("GdmSimpleSlave: client disconnected");
-}
-
-static void
-on_session_cancelled (GdmSession      *session,
-                      GdmSimpleSlave  *slave)
-{
-        g_debug ("GdmSimpleSlave: Session was cancelled");
-        queue_greeter_reset (slave);
-}
-
-static void
-touch_marker_file (GdmSimpleSlave *slave)
-{
-        int fd;
-
-        fd = g_creat (GDM_RAN_ONCE_MARKER_FILE, 0644);
-
-        if (fd < 0 && errno != EEXIST) {
-                g_warning ("could not create %s to mark run, this may cause auto login "
-                           "to repeat: %m", GDM_RAN_ONCE_MARKER_FILE);
-                return;
-        }
-
-        fsync (fd);
-        close (fd);
-}
-
-static void
-create_new_session (GdmSimpleSlave  *slave)
-{
-        gboolean       display_is_local;
-        char          *display_name;
-        char          *display_hostname;
-        char          *display_device;
-        char          *display_seat_id;
-        char          *display_x11_authority_file;
-        GdmSession    *greeter_session;
-        uid_t          greeter_uid;
-
-        g_debug ("GdmSimpleSlave: Creating new session");
-
-        if (slave->priv->greeter_environment != NULL) {
-                greeter_session = gdm_launch_environment_get_session (GDM_LAUNCH_ENVIRONMENT 
(slave->priv->greeter_environment));
-                greeter_uid = gdm_session_get_allowed_user (greeter_session);
-        } else {
-                greeter_uid = 0;
-        }
-
-        g_object_get (slave,
-                      "display-name", &display_name,
-                      "display-hostname", &display_hostname,
-                      "display-is-local", &display_is_local,
-                      "display-x11-authority-file", &display_x11_authority_file,
-                      "display-seat-id", &display_seat_id,
-                      NULL);
-
-        display_device = NULL;
-        if (slave->priv->server != NULL) {
-                display_device = gdm_server_get_display_device (slave->priv->server);
-        }
-
-        slave->priv->session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_LOGIN,
-                                                greeter_uid,
-                                                display_name,
-                                                display_hostname,
-                                                display_device,
-                                                display_seat_id,
-                                                display_x11_authority_file,
-                                                display_is_local,
-                                                NULL);
-
-        g_free (display_name);
-        g_free (display_device);
-        g_free (display_hostname);
-
-        g_signal_connect (slave->priv->session,
-                          "reauthentication-started",
-                          G_CALLBACK (on_session_reauthentication_started),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "reauthenticated",
-                          G_CALLBACK (on_session_reauthenticated),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "client-ready-for-session-to-start",
-                          G_CALLBACK (on_session_client_ready_for_session_to_start),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "client-connected",
-                          G_CALLBACK (on_session_client_connected),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "client-disconnected",
-                          G_CALLBACK (on_session_client_disconnected),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "cancelled",
-                          G_CALLBACK (on_session_cancelled),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "conversation-started",
-                          G_CALLBACK (on_session_conversation_started),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "conversation-stopped",
-                          G_CALLBACK (on_session_conversation_stopped),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "session-opened",
-                          G_CALLBACK (on_session_opened),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "session-started",
-                          G_CALLBACK (on_session_started),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "session-exited",
-                          G_CALLBACK (on_session_exited),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "session-died",
-                          G_CALLBACK (on_session_died),
-                          slave);
-
-        start_autologin_conversation_if_necessary (slave);
-
-        touch_marker_file (slave);
-}
-
-static void
 on_greeter_environment_session_opened (GdmLaunchEnvironment *greeter_environment,
                                        GdmSimpleSlave       *slave)
 {
@@ -1001,11 +377,7 @@ on_greeter_environment_session_stopped (GdmLaunchEnvironment *greeter_environmen
                                         GdmSimpleSlave       *slave)
 {
         g_debug ("GdmSimpleSlave: Greeter stopped");
-        if (slave->priv->start_session_service_name == NULL) {
-                gdm_slave_stop (GDM_SLAVE (slave));
-        } else {
-                start_session (slave);
-        }
+        gdm_slave_stop (GDM_SLAVE (slave));
 
         g_object_unref (slave->priv->greeter_environment);
         slave->priv->greeter_environment = NULL;
@@ -1017,9 +389,7 @@ on_greeter_environment_session_exited (GdmLaunchEnvironment    *greeter_environm
                                        GdmSimpleSlave          *slave)
 {
         g_debug ("GdmSimpleSlave: Greeter exited: %d", code);
-        if (slave->priv->start_session_service_name == NULL) {
-                gdm_slave_stop (GDM_SLAVE (slave));
-        }
+        gdm_slave_stop (GDM_SLAVE (slave));
 }
 
 static void
@@ -1028,9 +398,7 @@ on_greeter_environment_session_died (GdmLaunchEnvironment    *greeter_environmen
                                      GdmSimpleSlave          *slave)
 {
         g_debug ("GdmSimpleSlave: Greeter died: %d", signal);
-        if (slave->priv->start_session_service_name == NULL) {
-                gdm_slave_stop (GDM_SLAVE (slave));
-        }
+        gdm_slave_stop (GDM_SLAVE (slave));
 }
 
 #ifdef  WITH_PLYMOUTH
@@ -1335,17 +703,58 @@ wants_initial_setup (GdmSimpleSlave *slave)
 }
 
 static void
-setup_session (GdmSimpleSlave *slave)
+gdm_simple_slave_set_up_initial_session (GdmSlave  *slave,
+                                         char     **username)
 {
-        if (wants_initial_setup (slave)) {
-                start_initial_setup (slave);
-        } else if (wants_autologin (slave)) {
-                /* Run the init script. gdmslave suspends until script has terminated */
-                gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", GDM_USERNAME);
+        GdmSimpleSlave *self = GDM_SIMPLE_SLAVE (slave);
+
+        if (wants_initial_setup (self)) {
+                *username = g_strdup (INITIAL_SETUP_USERNAME);
+        } else if (wants_autologin (self)) {
+                *username = g_strdup ("root");
         } else {
-                start_greeter (slave);
+                *username = g_strdup (GDM_USERNAME);
+        }
+}
+
+static void
+gdm_simple_slave_stop_initial_session (GdmSlave   *slave,
+                                       const char *username)
+{
+        GdmSimpleSlave *self = GDM_SIMPLE_SLAVE (slave);
+
+        gdm_slave_run_script (slave, GDMCONFDIR "/PreSession", username);
+        if (self->priv->greeter_environment != NULL) {
+
+                g_signal_handlers_disconnect_by_func (self->priv->greeter_environment,
+                                                      G_CALLBACK (on_greeter_environment_session_stopped),
+                                                      self);
+                g_signal_handlers_disconnect_by_func (self->priv->greeter_environment,
+                                                      G_CALLBACK (on_greeter_environment_session_exited),
+                                                      self);
+                g_signal_handlers_disconnect_by_func (self->priv->greeter_environment,
+                                                      G_CALLBACK (on_greeter_environment_session_died),
+                                                      self);
+                stop_greeter (self);
+                self->priv->greeter_environment = NULL;
+        }
+
+        if (GDM_SIMPLE_SLAVE (slave)->priv->doing_initial_setup) {
+                chown_initial_setup_home_dir ();
+        }
+}
+
+static void
+gdm_simple_slave_start_initial_session (GdmSlave *slave)
+{
+        if (wants_initial_setup (GDM_SIMPLE_SLAVE (slave))) {
+                start_initial_setup (GDM_SIMPLE_SLAVE (slave));
+        } else if (wants_autologin (GDM_SIMPLE_SLAVE (slave))) {
+                /* no session to start so just run /Init and we're done */
+                gdm_slave_run_script (slave, GDMCONFDIR "/Init", GDM_USERNAME);
+        } else {
+                start_greeter (GDM_SIMPLE_SLAVE (slave));
         }
-        create_new_session (slave);
 }
 
 static gboolean
@@ -1358,7 +767,6 @@ idle_connect_to_display (GdmSimpleSlave *slave)
         res = gdm_slave_connect_to_x11_display (GDM_SLAVE (slave));
         if (res) {
                 setup_server (slave);
-                setup_session (slave);
         } else {
                 if (slave->priv->connection_attempts >= MAX_CONNECT_ATTEMPTS) {
                         g_warning ("Unable to connect to display after %d tries - bailing out", 
slave->priv->connection_attempts);
@@ -1556,99 +964,6 @@ gdm_simple_slave_run (GdmSimpleSlave *slave)
 }
 
 static gboolean
-gdm_simple_slave_open_session (GdmSlave  *slave,
-                               GPid       pid_of_caller,
-                               uid_t      uid_of_caller,
-                               char     **address,
-                               GError   **error)
-{
-        GdmSimpleSlave     *self = GDM_SIMPLE_SLAVE (slave);
-        uid_t               allowed_user;
-
-        if (self->priv->session_is_running) {
-                g_set_error (error,
-                             G_DBUS_ERROR,
-                             G_DBUS_ERROR_ACCESS_DENIED,
-                             _("Can only be called before user is logged in"));
-                return FALSE;
-        }
-
-        allowed_user = gdm_session_get_allowed_user (self->priv->session);
-
-        if (uid_of_caller != allowed_user) {
-                g_set_error (error,
-                             G_DBUS_ERROR,
-                             G_DBUS_ERROR_ACCESS_DENIED,
-                             _("Caller not GDM"));
-                return FALSE;
-        }
-
-        *address = gdm_session_get_server_address (self->priv->session);
-
-        return TRUE;
-}
-
-static char *
-gdm_simple_slave_open_reauthentication_channel_finish (GdmSlave      *slave,
-                                                       GAsyncResult  *result,
-                                                       GError       **error)
-{
-        GdmSimpleSlave  *self = GDM_SIMPLE_SLAVE (slave);
-        const char      *address;
-
-        g_return_val_if_fail (g_simple_async_result_is_valid (result,
-                                                              G_OBJECT (self),
-                                                              
gdm_simple_slave_open_reauthentication_channel), NULL);
-
-        address = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
-
-        if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) {
-                return NULL;
-        }
-
-        return g_strdup (address);
-}
-
-static void
-gdm_simple_slave_open_reauthentication_channel (GdmSlave             *slave,
-                                                const char           *username,
-                                                GPid                  pid_of_caller,
-                                                uid_t                 uid_of_caller,
-                                                GAsyncReadyCallback   callback,
-                                                gpointer              user_data,
-                                                GCancellable         *cancellable)
-{
-        GdmSimpleSlave     *self = GDM_SIMPLE_SLAVE (slave);
-        GSimpleAsyncResult *result;
-
-        result = g_simple_async_result_new (G_OBJECT (slave),
-                                            callback,
-                                            user_data,
-                                            gdm_simple_slave_open_reauthentication_channel);
-
-        g_simple_async_result_set_check_cancellable (result, cancellable);
-
-        if (!self->priv->session_is_running) {
-                g_simple_async_result_set_error (result,
-                                                 G_DBUS_ERROR,
-                                                 G_DBUS_ERROR_ACCESS_DENIED,
-                                                 _("User not logged in"));
-                g_simple_async_result_complete_in_idle (result);
-
-        } else {
-                g_hash_table_insert (self->priv->open_reauthentication_requests,
-                                     GINT_TO_POINTER (pid_of_caller),
-                                     g_object_ref (result));
-
-                gdm_session_start_reauthentication (self->priv->session,
-                                                    pid_of_caller,
-                                                    uid_of_caller);
-        }
-
-        g_object_unref (result);
-}
-
-static gboolean
 gdm_simple_slave_start (GdmSlave *slave)
 {
         GDM_SLAVE_CLASS (gdm_simple_slave_parent_class)->start (slave);
@@ -1687,38 +1002,6 @@ gdm_simple_slave_stop (GdmSlave *slave)
                 g_clear_object (&self->priv->greeter_environment);
         }
 
-        if (self->priv->start_session_id > 0) {
-                g_source_remove (self->priv->start_session_id);
-                self->priv->start_session_id = 0;
-        }
-
-        g_clear_pointer (&self->priv->start_session_service_name,
-                         (GDestroyNotify) g_free);
-
-        if (self->priv->session_is_running) {
-                char *username;
-
-                /* Run the PostSession script. gdmslave suspends until script
-                 * has terminated
-                 */
-                username = gdm_session_get_username (self->priv->session);
-                if (username != NULL) {
-                        gdm_slave_run_script (slave, GDMCONFDIR "/PostSession", username);
-                }
-                g_free (username);
-
-#ifdef  HAVE_LOGINDEVPERM
-                gdm_simple_slave_revoke_console_permissions (self);
-#endif
-
-                self->priv->session_is_running = FALSE;
-        }
-
-        if (self->priv->session != NULL) {
-                gdm_session_close (self->priv->session);
-                g_clear_object (&self->priv->session);
-        }
-
         if (self->priv->server != NULL) {
                 gdm_server_stop (self->priv->server);
                 g_clear_object (&self->priv->server);
@@ -1739,9 +1022,9 @@ gdm_simple_slave_class_init (GdmSimpleSlaveClass *klass)
 
         slave_class->start = gdm_simple_slave_start;
         slave_class->stop = gdm_simple_slave_stop;
-        slave_class->open_session = gdm_simple_slave_open_session;
-        slave_class->open_reauthentication_channel = gdm_simple_slave_open_reauthentication_channel;
-        slave_class->open_reauthentication_channel_finish = 
gdm_simple_slave_open_reauthentication_channel_finish;
+        slave_class->set_up_initial_session = gdm_simple_slave_set_up_initial_session;
+        slave_class->start_initial_session = gdm_simple_slave_start_initial_session;
+        slave_class->stop_initial_session = gdm_simple_slave_stop_initial_session;
 
         g_type_class_add_private (klass, sizeof (GdmSimpleSlavePrivate));
 }
@@ -1753,13 +1036,6 @@ gdm_simple_slave_init (GdmSimpleSlave *slave)
 #ifdef  HAVE_LOGINDEVPERM
         slave->priv->use_logindevperm = FALSE;
 #endif
-
-        slave->priv->open_reauthentication_requests = g_hash_table_new_full (NULL,
-                                                                             NULL,
-                                                                             (GDestroyNotify)
-                                                                             NULL,
-                                                                             (GDestroyNotify)
-                                                                             g_object_unref);
 }
 
 static void
@@ -1776,8 +1052,6 @@ gdm_simple_slave_finalize (GObject *object)
 
         gdm_slave_stop (GDM_SLAVE (slave));
 
-        g_hash_table_unref (slave->priv->open_reauthentication_requests);
-
         if (slave->priv->greeter_reset_id > 0) {
                 g_source_remove (slave->priv->greeter_reset_id);
                 slave->priv->greeter_reset_id = 0;
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index a635488..7ee3d21 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -200,7 +200,6 @@ get_script_environment (GdmSlave   *slave,
         GPtrArray     *env;
         GHashTable    *hash;
         struct passwd *pwent;
-        char          *temp;
 
         env = g_ptr_array_new ();
 
@@ -637,6 +636,10 @@ gdm_slave_connect_to_x11_display (GdmSlave *slave)
                 ret = TRUE;
         }
 
+        if (ret) {
+                gdm_dbus_slave_emit_started (slave->priv->skeleton);
+        }
+
         return ret;
 }
 
@@ -1001,8 +1004,7 @@ gdm_slave_parse_enriched_login (GdmSlave   *slave,
                 }
         }
 
- out:
-
+out:
         return parsed_username;
 }
 
@@ -1081,620 +1083,6 @@ gdm_slave_get_timed_login_details (GdmSlave   *slave,
         return res;
 }
 
-static gboolean
-_get_uid_and_gid_for_user (const char *username,
-                           uid_t      *uid,
-                           gid_t      *gid)
-{
-        struct passwd *passwd_entry;
-
-        g_assert (username != NULL);
-
-        errno = 0;
-        gdm_get_pwent_for_name (username, &passwd_entry);
-
-        if (passwd_entry == NULL) {
-                return FALSE;
-        }
-
-        if (uid != NULL) {
-                *uid = passwd_entry->pw_uid;
-        }
-
-        if (gid != NULL) {
-                *gid = passwd_entry->pw_gid;
-        }
-
-        return TRUE;
-}
-
-#ifdef WITH_CONSOLE_KIT
-
-static gboolean
-x11_session_is_on_seat (GdmSlave        *slave,
-                        const char      *session_id,
-                        const char      *seat_id)
-{
-        GError          *error = NULL;
-        GVariant        *reply;
-        char            *sid;
-        gboolean         ret;
-        char            *x11_display_device;
-        char            *x11_display;
-
-        ret = FALSE;
-        sid = NULL;
-        x11_display = NULL;
-        x11_display_device = NULL;
-
-        if (seat_id == NULL || seat_id[0] == '\0' || session_id == NULL || session_id[0] == '\0') {
-                return FALSE;
-        }
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             CK_NAME,
-                                             session_id,
-                                             CK_SESSION_INTERFACE,
-                                             "GetSeatId",
-                                             NULL, /* parameters */
-                                             G_VARIANT_TYPE ("(o)"),
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_debug ("Failed to identify the current seat: %s", error->message);
-                g_error_free (error);
-                return FALSE;
-        }
-
-        g_variant_get (reply, "(o)", &sid);
-        g_variant_unref (reply);
-
-        if (sid == NULL || sid[0] == '\0' || strcmp (sid, seat_id) != 0) {
-                g_debug ("GdmSlave: session not on current seat: %s", seat_id);
-                goto out;
-        }
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             CK_NAME,
-                                             session_id,
-                                             CK_SESSION_INTERFACE,
-                                             "GetX11Display",
-                                             NULL, /* parameters */
-                                             G_VARIANT_TYPE ("(s)"),
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_error_free (error);
-                goto out;
-        }
-
-        g_variant_get (reply, "(s)", &x11_display);
-        g_variant_unref (reply);
-
-        /* ignore tty sessions */
-        if (x11_display == NULL || x11_display[0] == '\0') {
-                goto out;
-        }
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             CK_NAME,
-                                             session_id,
-                                             CK_SESSION_INTERFACE,
-                                             "GetX11DisplayDevice",
-                                             NULL, /* parameters */
-                                             G_VARIANT_TYPE ("(s)"),
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_error_free (error);
-                goto out;
-        }
-
-        g_variant_get (reply, "(s)", &x11_display_device);
-        g_variant_unref (reply);
-
-        if (x11_display_device == NULL || x11_display_device[0] == '\0') {
-                goto out;
-        }
-
-        ret = TRUE;
- out:
-        g_free (x11_display_device);
-        g_free (x11_display);
-        g_free (sid);
-
-        return ret;
-}
-
-#endif
-
-#ifdef WITH_SYSTEMD
-static char*
-gdm_slave_get_primary_session_id_for_user_from_systemd (GdmSlave   *slave,
-                                                        const char *username)
-{
-        int     res, i;
-        char  **sessions;
-        uid_t   uid;
-        char   *primary_ssid;
-        gboolean got_primary_ssid;
-
-        primary_ssid = NULL;
-        got_primary_ssid = FALSE;
-
-        res = sd_seat_can_multi_session (slave->priv->display_seat_id);
-        if (res < 0) {
-                g_warning ("GdmSlave: Failed to determine whether seat is multi-session capable: %s", 
strerror (-res));
-                return NULL;
-        } else if (res == 0) {
-                g_debug ("GdmSlave: seat is unable to activate sessions");
-                return NULL;
-        }
-
-        if (! _get_uid_and_gid_for_user (username, &uid, NULL)) {
-                g_debug ("GdmSlave: unable to determine uid for user: %s", username);
-                return NULL;
-        }
-
-        res = sd_seat_get_sessions (slave->priv->display_seat_id, &sessions, NULL, NULL);
-        if (res < 0) {
-                g_warning ("GdmSlave: Failed to get sessions on seat: %s", strerror (-res));
-                return NULL;
-        }
-
-        if (sessions == NULL) {
-                g_debug ("GdmSlave: seat has no active sessions");
-                return NULL;
-        }
-
-        for (i = 0; sessions[i] != NULL; i++) {
-                char *type;
-                char *state;
-                gboolean is_closing;
-                gboolean is_active;
-                gboolean is_x11;
-                uid_t other;
-
-                res = sd_session_get_type (sessions[i], &type);
-
-                if (res < 0) {
-                        g_warning ("GdmSlave: could not fetch type of session '%s': %s",
-                                   sessions[i], strerror (-res));
-                        continue;
-                }
-
-                is_x11 = g_strcmp0 (type, "x11") == 0;
-                free (type);
-
-                /* Only migrate to graphical sessions
-                 */
-                if (!is_x11) {
-                        continue;
-                }
-
-                /* Always give preference to non-active sessions,
-                 * so we migrate when we can and don't when we can't
-                 */
-                res = sd_session_get_state (sessions[i], &state);
-                if (res < 0) {
-                        g_warning ("GdmSlave: could not fetch state of session '%s': %s",
-                                   sessions[i], strerror (-res));
-                        continue;
-                }
-
-                is_closing = g_strcmp0 (state, "closing") == 0;
-                is_active = g_strcmp0 (state, "active") == 0;
-                free (state);
-
-                /* Ignore closing sessions
-                 */
-                if (is_closing) {
-                        continue;
-                }
-
-                res = sd_session_get_uid (sessions[i], &other);
-                if (res == 0 && other == uid && !got_primary_ssid) {
-                        g_free (primary_ssid);
-                        primary_ssid = g_strdup (sessions[i]);
-
-                        if (!is_active) {
-                                got_primary_ssid = TRUE;
-                        }
-                }
-                free (sessions[i]);
-        }
-
-        free (sessions);
-        return primary_ssid;
-}
-#endif
-
-#ifdef WITH_CONSOLE_KIT
-static char *
-gdm_slave_get_primary_session_id_for_user_from_ck (GdmSlave   *slave,
-                                                   const char *username)
-{
-        gboolean      can_activate_sessions;
-        GError       *error;
-        const char  **sessions;
-        int           i;
-        char         *primary_ssid;
-        uid_t         uid;
-        GVariant     *reply;
-
-        error = NULL;
-        primary_ssid = NULL;
-
-        g_debug ("GdmSlave: getting proxy for seat: %s", slave->priv->display_seat_id);
-        g_debug ("GdmSlave: checking if seat can activate sessions");
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             CK_NAME,
-                                             slave->priv->display_seat_id,
-                                             CK_SEAT_INTERFACE,
-                                             "CanActivateSessions",
-                                             NULL, /* parameters */
-                                             G_VARIANT_TYPE ("(b)"),
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_warning ("unable to determine if seat can activate sessions: %s", error->message);
-                g_error_free (error);
-                return NULL;
-        }
-
-        g_variant_get (reply, "(b)", &can_activate_sessions);
-        g_variant_unref (reply);
-
-        if (! can_activate_sessions) {
-                g_debug ("GdmSlave: seat is unable to activate sessions");
-                return NULL;
-        }
-
-        if (! _get_uid_and_gid_for_user (username, &uid, NULL)) {
-                g_debug ("GdmSlave: unable to determine uid for user: %s", username);
-                return NULL;
-        }
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             CK_NAME,
-                                             CK_MANAGER_PATH,
-                                             CK_MANAGER_INTERFACE,
-                                             "GetSessionsForUnixUser",
-                                             g_variant_new ("(u)", uid),
-                                             G_VARIANT_TYPE ("(ao)"),
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-
-        if (reply == NULL) {
-                g_warning ("unable to determine sessions for user: %s", error->message);
-                g_error_free (error);
-                return NULL;
-        }
-
-        g_variant_get_child (reply, 0, "^a&o", &sessions);
-        for (i = 0; sessions[i] != NULL; i++) {
-                if (x11_session_is_on_seat (slave, sessions[i], slave->priv->display_seat_id)) {
-                        primary_ssid = g_strdup (sessions[i]);
-                        break;
-                }
-        }
-
-        g_free (sessions);
-        g_variant_unref (reply);
-        return primary_ssid;
-}
-#endif
-
-char *
-gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
-                                           const char *username)
-{
-
-        if (slave->priv->display_seat_id == NULL || slave->priv->display_seat_id[0] == '\0') {
-                g_debug ("GdmSlave: display seat ID is not set; can't switch sessions");
-                return NULL;
-        }
-
-#ifdef WITH_SYSTEMD
-        if (LOGIND_RUNNING()) {
-                return gdm_slave_get_primary_session_id_for_user_from_systemd (slave, username);
-        }
-#endif
-
-#ifdef WITH_CONSOLE_KIT
-        return gdm_slave_get_primary_session_id_for_user_from_ck (slave, username);
-#else
-        return NULL;
-#endif
-}
-
-#ifdef WITH_SYSTEMD
-static gboolean
-activate_session_id_for_systemd (GdmSlave   *slave,
-                                 const char *seat_id,
-                                 const char *session_id)
-{
-        GError *error = NULL;
-        GVariant *reply;
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             "org.freedesktop.login1",
-                                             "/org/freedesktop/login1",
-                                             "org.freedesktop.login1.Manager",
-                                             "ActivateSessionOnSeat",
-                                             g_variant_new ("(ss)", session_id, seat_id),
-                                             NULL, /* expected reply */
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_debug ("GdmSlave: logind 'ActivateSessionOnSeat' %s raised:\n %s\n\n",
-                         g_dbus_error_get_remote_error (error), error->message);
-                g_error_free (error);
-                return FALSE;
-        }
-
-        g_variant_unref (reply);
-
-        return TRUE;
-}
-#endif
-
-#ifdef WITH_CONSOLE_KIT
-static gboolean
-activate_session_id_for_ck (GdmSlave   *slave,
-                            const char *seat_id,
-                            const char *session_id)
-{
-        GError *error = NULL;
-        GVariant *reply;
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             CK_NAME,
-                                             seat_id,
-                                             "org.freedesktop.ConsoleKit.Seat",
-                                             "ActivateSession",
-                                             g_variant_new ("(o)", session_id),
-                                             NULL, /* expected reply */
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_debug ("GdmSlave: ConsoleKit %s raised:\n %s\n\n",
-                         g_dbus_error_get_remote_error (error), error->message);
-                g_error_free (error);
-                return FALSE;
-        }
-
-        g_variant_unref (reply);
-
-        return TRUE;
-}
-#endif
-
-static gboolean
-activate_session_id (GdmSlave   *slave,
-                     const char *seat_id,
-                     const char *session_id)
-{
-
-#ifdef WITH_SYSTEMD
-        if (LOGIND_RUNNING()) {
-                return activate_session_id_for_systemd (slave, seat_id, session_id);
-        }
-#endif
-
-#ifdef WITH_CONSOLE_KIT
-        return activate_session_id_for_ck (slave, seat_id, session_id);
-#else
-        return FALSE;
-#endif
-}
-
-#ifdef WITH_CONSOLE_KIT
-static gboolean
-ck_session_is_active (GdmSlave   *slave,
-                      const char *seat_id,
-                      const char *session_id)
-{
-        GError *error = NULL;
-        GVariant *reply;
-        gboolean is_active;
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             CK_NAME,
-                                             session_id,
-                                             "org.freedesktop.ConsoleKit.Session",
-                                             "IsActive",
-                                             NULL,
-                                             G_VARIANT_TYPE ("(b)"),
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_debug ("GdmSlave: ConsoleKit IsActive %s raised:\n %s\n\n",
-                         g_dbus_error_get_remote_error (error), error->message);
-                g_error_free (error);
-                return FALSE;
-        }
-
-        g_variant_get (reply, "(b)", &is_active);
-        g_variant_unref (reply);
-
-        return is_active;
-}
-#endif
-
-static gboolean
-session_is_active (GdmSlave   *slave,
-                   const char *seat_id,
-                   const char *session_id)
-{
-#ifdef WITH_SYSTEMD
-        if (LOGIND_RUNNING()) {
-                return sd_session_is_active (session_id) > 0;
-        }
-#endif
-
-#ifdef WITH_CONSOLE_KIT
-        return ck_session_is_active (slave, seat_id, session_id);
-#else
-        return FALSE;
-#endif
-}
-
-#ifdef WITH_SYSTEMD
-static gboolean
-session_unlock_for_systemd (GdmSlave   *slave,
-                            const char *ssid)
-{
-        GError *error = NULL;
-        GVariant *reply;
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             "org.freedesktop.login1",
-                                             "/org/freedesktop/login1",
-                                             "org.freedesktop.login1.Manager",
-                                             "UnlockSession",
-                                             g_variant_new ("(s)", ssid),
-                                             NULL, /* expected reply */
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_debug ("GdmSlave: logind 'UnlockSession' %s raised:\n %s\n\n",
-                         g_dbus_error_get_remote_error (error), error->message);
-                g_error_free (error);
-                return FALSE;
-        }
-
-        g_variant_unref (reply);
-
-        return TRUE;
-}
-#endif
-
-#ifdef WITH_CONSOLE_KIT
-static gboolean
-session_unlock_for_ck (GdmSlave   *slave,
-                       const char *ssid)
-{
-        GError *error = NULL;
-        GVariant *reply;
-
-        reply = g_dbus_connection_call_sync (slave->priv->connection,
-                                             CK_NAME,
-                                             ssid,
-                                             CK_SESSION_INTERFACE,
-                                             "Unlock",
-                                             NULL, /* parameters */
-                                             NULL, /* expected reply */
-                                             G_DBUS_CALL_FLAGS_NONE,
-                                             -1,
-                                             NULL,
-                                             &error);
-        if (reply == NULL) {
-                g_debug ("GdmSlave: ConsoleKit %s raised:\n %s\n\n",
-                         g_dbus_error_get_remote_error (error), error->message);
-                g_error_free (error);
-                return FALSE;
-        }
-
-        g_variant_unref (reply);
-
-        return TRUE;
-}
-#endif
-
-static gboolean
-session_unlock (GdmSlave   *slave,
-                const char *ssid)
-{
-
-        g_debug ("Unlocking session %s", ssid);
-
-#ifdef WITH_SYSTEMD
-        if (LOGIND_RUNNING()) {
-                return session_unlock_for_systemd (slave, ssid);
-        }
-#endif
-
-#ifdef WITH_CONSOLE_KIT
-        return session_unlock_for_ck (slave, ssid);
-#else
-        return TRUE;
-#endif
-}
-
-gboolean
-gdm_slave_switch_to_user_session (GdmSlave   *slave,
-                                  const char *username,
-                                  const char *session_id,
-                                  gboolean    fail_if_already_switched)
-{
-        gboolean    res;
-        gboolean    ret;
-        gboolean    session_already_switched;
-        char       *ssid_to_activate;
-
-        ret = FALSE;
-
-        if (session_id != NULL) {
-                ssid_to_activate = g_strdup (session_id);
-        } else {
-                ssid_to_activate = gdm_slave_get_primary_session_id_for_user (slave, username);
-                if (ssid_to_activate == NULL) {
-                        g_debug ("GdmSlave: unable to determine session to activate");
-                        goto out;
-                }
-        }
-
-        session_already_switched = session_is_active (slave, slave->priv->display_seat_id, ssid_to_activate);
-
-        g_debug ("GdmSlave: Activating session: '%s'", ssid_to_activate);
-
-        if (session_already_switched && fail_if_already_switched) {
-                g_debug ("GdmSlave: unable to activate session since it's already active: %s", 
ssid_to_activate);
-                goto out;
-        }
-
-        if (!session_already_switched) {
-                res = activate_session_id (slave, slave->priv->display_seat_id, ssid_to_activate);
-                if (! res) {
-                        g_debug ("GdmSlave: unable to activate session: %s", ssid_to_activate);
-                        goto out;
-                }
-        }
-
-        res = session_unlock (slave, ssid_to_activate);
-        if (!res) {
-                /* this isn't fatal */
-                g_debug ("GdmSlave: unable to unlock session: %s", ssid_to_activate);
-        }
-
-        ret = TRUE;
-
- out:
-        g_free (ssid_to_activate);
-
-        return ret;
-}
-
 static void
 _gdm_slave_set_session_id (GdmSlave   *slave,
                            const char *id)
@@ -1853,95 +1241,71 @@ gdm_slave_get_property (GObject    *object,
 }
 
 static gboolean
-handle_open_session (GdmDBusSlave          *skeleton,
-                     GDBusMethodInvocation *invocation,
-                     int                    pid_of_caller,
-                     int                    uid_of_caller,
-                     GdmSlave              *slave)
+handle_set_up_initial_session (GdmDBusSlave          *skeleton,
+                               GDBusMethodInvocation *invocation,
+                               GdmSlave              *slave)
 {
-        GError        *error;
         GdmSlaveClass *slave_class;
-        char          *address;
+        char          *username;
 
         slave_class = GDM_SLAVE_GET_CLASS (slave);
-        if (slave_class->open_session == NULL) {
+        if (slave_class->set_up_initial_session == NULL) {
                 g_dbus_method_invocation_return_dbus_error (invocation,
                                                             "org.gnome.DisplayManager.Slave.Unsupported",
                                                             "Connections to the slave are not supported by 
this slave");
                 return TRUE;
         }
 
-        error = NULL;
-        address = NULL;
-        if (!slave_class->open_session (slave,
-                                        (GPid) pid_of_caller,
-                                        (uid_t) uid_of_caller,
-                                        &address,
-                                        &error)) {
-                g_dbus_method_invocation_return_gerror (invocation, error);
-                g_error_free (error);
-                return TRUE;
-        }
+        username = NULL;
+        slave_class->set_up_initial_session (slave, &username);
 
-        gdm_dbus_slave_complete_open_session (skeleton, invocation, address);
+        gdm_dbus_slave_complete_set_up_initial_session (skeleton, invocation, username);
 
-        g_free (address);
+        g_free (username);
         return TRUE;
 }
 
-static void
-on_reauthentication_channel_opened (GdmSlave              *slave,
-                                    GAsyncResult          *result,
-                                    GDBusMethodInvocation *invocation)
+static gboolean
+handle_start_initial_session (GdmDBusSlave          *skeleton,
+                              GDBusMethodInvocation *invocation,
+                              GdmSlave              *slave)
 {
-        GdmSlaveClass      *slave_class;
-        GError             *error;
-        char               *address;
+        GdmSlaveClass *slave_class;
 
         slave_class = GDM_SLAVE_GET_CLASS (slave);
+        if (slave_class->start_initial_session == NULL) {
+                g_dbus_method_invocation_return_dbus_error (invocation,
+                                                            "org.gnome.DisplayManager.Slave.Unsupported",
+                                                            "Connections to the slave are not supported by 
this slave");
+                return TRUE;
+        }
 
-        g_assert (slave_class->open_reauthentication_channel_finish != NULL);
+        slave_class->start_initial_session (slave);
 
-        error = NULL;
-        address = slave_class->open_reauthentication_channel_finish (slave, result, &error);
+        gdm_dbus_slave_complete_start_initial_session (skeleton, invocation);
 
-        if (address == NULL) {
-                g_dbus_method_invocation_return_gerror (invocation, error);
-        } else {
-                gdm_dbus_slave_complete_open_reauthentication_channel (slave->priv->skeleton,
-                                                                       invocation,
-                                                                       address);
-        }
-
-        g_object_unref (invocation);
+        return TRUE;
 }
 
 static gboolean
-handle_open_reauthentication_channel (GdmDBusSlave          *skeleton,
-                                      GDBusMethodInvocation *invocation,
-                                      const char            *username,
-                                      GPid                   pid_of_caller,
-                                      uid_t                  uid_of_caller,
-                                      GdmSlave              *slave)
+handle_stop_initial_session (GdmDBusSlave          *skeleton,
+                             GDBusMethodInvocation *invocation,
+                             const char            *username,
+                             GdmSlave              *slave)
 {
         GdmSlaveClass *slave_class;
 
         slave_class = GDM_SLAVE_GET_CLASS (slave);
-        if (slave_class->open_reauthentication_channel == NULL) {
+        if (slave_class->stop_initial_session == NULL) {
                 g_dbus_method_invocation_return_dbus_error (invocation,
                                                             "org.gnome.DisplayManager.Slave.Unsupported",
                                                             "Connections to the slave are not supported by 
this slave");
                 return TRUE;
         }
 
-        slave_class->open_reauthentication_channel (slave,
-                                                    username,
-                                                    pid_of_caller,
-                                                    uid_of_caller,
-                                                    (GAsyncReadyCallback)
-                                                    on_reauthentication_channel_opened,
-                                                    g_object_ref (invocation),
-                                                    NULL);
+        slave_class->stop_initial_session (slave, username);
+
+        gdm_dbus_slave_complete_stop_initial_session (skeleton, invocation);
 
         return TRUE;
 }
@@ -1964,14 +1328,17 @@ register_slave (GdmSlave *slave)
         slave->priv->skeleton = GDM_DBUS_SLAVE (gdm_dbus_slave_skeleton_new ());
 
         g_signal_connect (slave->priv->skeleton,
-                          "handle-open-session",
-                          G_CALLBACK (handle_open_session),
+                          "handle-set-up-initial-session",
+                          G_CALLBACK (handle_set_up_initial_session),
                           slave);
         g_signal_connect (slave->priv->skeleton,
-                          "handle-open-reauthentication-channel",
-                          G_CALLBACK (handle_open_reauthentication_channel),
+                          "handle-start-initial-session",
+                          G_CALLBACK (handle_start_initial_session),
+                          slave);
+        g_signal_connect (slave->priv->skeleton,
+                          "handle-stop-initial-session",
+                          G_CALLBACK (handle_stop_initial_session),
                           slave);
-
         g_object_bind_property (G_OBJECT (slave),
                                 "session-id",
                                 G_OBJECT (slave->priv->skeleton),
diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h
index 9808433..e3264f8 100644
--- a/daemon/gdm-slave.h
+++ b/daemon/gdm-slave.h
@@ -50,22 +50,11 @@ typedef struct
         gboolean (*start) (GdmSlave *slave);
         gboolean (*stop)  (GdmSlave *slave);
 
-        gboolean     (*open_session)       (GdmSlave   *slave,
-                                            GPid        pid_of_caller,
-                                            uid_t       uid_of_caller,
-                                            char      **address,
-                                            GError    **error);
-
-        void     (*open_reauthentication_channel) (GdmSlave            *slave,
-                                                   const char          *username,
-                                                   GPid                 pid_of_caller,
-                                                   uid_t                uid_of_caller,
-                                                   GAsyncReadyCallback  callback,
-                                                   gpointer             user_data,
-                                                   GCancellable        *cancellable);
-        char *   (*open_reauthentication_channel_finish) (GdmSlave      *slave,
-                                                          GAsyncResult  *result,
-                                                          GError       **error);
+        void     (* set_up_initial_session) (GdmSlave    *slave,
+                                             char       **username);
+        void     (* start_initial_session) (GdmSlave  *slave);
+        void     (* stop_initial_session) (GdmSlave   *slave,
+                                           const char *username);
 
         /* signals */
         void (*stopped) (GdmSlave *slave);
@@ -85,24 +74,14 @@ GQuark              gdm_slave_error_quark            (void);
 GType               gdm_slave_get_type               (void);
 gboolean            gdm_slave_start                  (GdmSlave   *slave);
 gboolean            gdm_slave_stop                   (GdmSlave   *slave);
-
-char *              gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
-                                                               const char *username);
-
 gboolean            gdm_slave_get_timed_login_details (GdmSlave  *slave,
                                                        gboolean  *enabled,
                                                        char     **username,
                                                        int       *delay);
-
 gboolean            gdm_slave_add_user_authorization (GdmSlave   *slave,
                                                       const char *username,
                                                       char      **filename);
 
-gboolean            gdm_slave_switch_to_user_session (GdmSlave   *slave,
-                                                      const char *username,
-                                                      const char *session_id,
-                                                      gboolean    fail_if_already_switched);
-
 gboolean            gdm_slave_connect_to_x11_display (GdmSlave   *slave);
 
 void                gdm_slave_set_initial_cursor_position (GdmSlave *slave);
diff --git a/daemon/gdm-slave.xml b/daemon/gdm-slave.xml
index d055252..3f563b4 100644
--- a/daemon/gdm-slave.xml
+++ b/daemon/gdm-slave.xml
@@ -1,19 +1,23 @@
 <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" 
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
 <node>
   <interface name="org.gnome.DisplayManager.Slave">
-    <method name="OpenSession">
-      <arg name="pid_of_caller" type="i" direction="in" />
-      <arg name="uid_of_caller" type="i" direction="in" />
-      <arg name="address" type="s" direction="out" />
+    <method name="StopGreeter">
     </method>
 
-    <method name="OpenReauthenticationChannel">
+    <method name="SetUpInitialSession">
+      <arg name="username" type="s" direction="out" />
+    </method>
+
+    <method name="StartInitialSession">
+    </method>
+
+    <method name="StopInitialSession">
       <arg name="username" type="s" direction="in" />
-      <arg name="pid_of_caller" type="i" direction="in" />
-      <arg name="uid_of_caller" type="i" direction="in" />
-      <arg name="address" type="s" direction="out" />
     </method>
 
+    <signal name="Started">
+    </signal>
+
     <property name="session_id" type="s" access="read"/>
   </interface>
 </node>
diff --git a/daemon/gdm-xdmcp-chooser-slave.c b/daemon/gdm-xdmcp-chooser-slave.c
index 0a90130..7745c74 100644
--- a/daemon/gdm-xdmcp-chooser-slave.c
+++ b/daemon/gdm-xdmcp-chooser-slave.c
@@ -345,31 +345,6 @@ gdm_xdmcp_chooser_slave_stop (GdmSlave *slave)
         return TRUE;
 }
 
-static gboolean
-gdm_xdmcp_chooser_slave_open_session (GdmSlave  *slave,
-                                      GPid       pid_of_caller,
-                                      uid_t      uid_of_caller,
-                                      char     **address,
-                                      GError   **error)
-{
-        GdmXdmcpChooserSlave *self = GDM_XDMCP_CHOOSER_SLAVE (slave);
-        GdmSession           *session;
-
-        session = gdm_launch_environment_get_session (GDM_LAUNCH_ENVIRONMENT 
(self->priv->chooser_environment));
-
-        if (gdm_session_client_is_connected (session)) {
-                g_set_error (error,
-                             G_DBUS_ERROR,
-                             G_DBUS_ERROR_ACCESS_DENIED,
-                             _("Currently, only one client can be connected at once"));
-
-                return FALSE;
-        }
-
-        *address = gdm_session_get_server_address (session);
-        return TRUE;
-}
-
 static GObject *
 gdm_xdmcp_chooser_slave_constructor (GType                  type,
                                      guint                  n_construct_properties,
@@ -399,7 +374,6 @@ gdm_xdmcp_chooser_slave_class_init (GdmXdmcpChooserSlaveClass *klass)
 
         slave_class->start = gdm_xdmcp_chooser_slave_start;
         slave_class->stop = gdm_xdmcp_chooser_slave_stop;
-        slave_class->open_session = gdm_xdmcp_chooser_slave_open_session;
 
         g_type_class_add_private (klass, sizeof (GdmXdmcpChooserSlavePrivate));
 }



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