[gdm/wip/slave-connection: 26/32] daemon: Add an interface for communicating with GDM via D-Bus



commit bbad6d44d7118e28419088d1ae8f1489f1f24caf
Author: Ray Strode <rstrode redhat com>
Date:   Fri May 18 21:04:21 2012 +0200

    daemon: Add an interface for communicating with GDM via D-Bus
    
    One goal for GNOME 3.6, is to replace the screen locking functionality
    provided by gnome-screensaver with redesigned functionality provided
    by gnome-shell.
    
    At the same time, it makes sense to consolidate the yucky PAM
    authentication code to one place (GDM).
    
    Right now only greeters can talk to GDM.  At the time the greeter is
    started, the slave sets up a private communication channel which the
    greeter then connects to for initiating communication.
    
    This commit adds a new method to the org.gnome.DisplayManager.Manager
    interface that allows opening a private connection to the slave that
    is associated with the currently running session.  That slave exports
    the session object over the bus that greeters (and potentially
    screensavers) can interact with the session as appropriate.
    
    This commit also drops gdm-greeter-server and gdm-chooser-server which
    don't fit the new model, and are really just thin middle men that don't do
    anything important.
    
    Furthermore, this commit splits GdmSession interfaces 3 orthogonal parts
    up into 3 separate interfaces on the session object.
    
    Based on work by Giovanni Campagna <gcampagna src gnome org>
    
    https://bugzilla.gnome.org/show_bug.cgi?id=676381

 .gitignore                       |    1 +
 daemon/Makefile.am               |   25 +-
 daemon/gdm-chooser-server.c      |  419 -------------
 daemon/gdm-chooser-server.h      |   63 --
 daemon/gdm-chooser-session.c     |    3 -
 daemon/gdm-dbus-util.c           |   40 ++
 daemon/gdm-dbus-util.h           |    6 +
 daemon/gdm-display.c             |  102 +++-
 daemon/gdm-display.h             |    9 +-
 daemon/gdm-display.xml           |    5 +-
 daemon/gdm-greeter-server.c      |  932 ----------------------------
 daemon/gdm-greeter-server.h      |  118 ----
 daemon/gdm-greeter-server.xml    |   92 ---
 daemon/gdm-greeter-session.c     |    3 -
 daemon/gdm-manager.c             |  203 ++++++-
 daemon/gdm-manager.xml           |    8 +
 daemon/gdm-session-worker.c      |  412 ++++++++-----
 daemon/gdm-session.c             | 1243 ++++++++++++++++++++++++--------------
 daemon/gdm-session.h             |   68 +--
 daemon/gdm-session.xml           |  122 ++++-
 daemon/gdm-simple-slave.c        |  783 ++++++------------------
 daemon/gdm-slave.c               |  138 +++++
 daemon/gdm-slave.h               |   23 +
 daemon/gdm-slave.xml             |   12 +-
 daemon/gdm-welcome-session.c     |  106 +---
 daemon/gdm-welcome-session.h     |    5 +-
 daemon/gdm-xdmcp-chooser-slave.c |   72 ++-
 daemon/test-session.c            |    5 +-
 data/gdm.conf.in                 |   15 +-
 29 files changed, 1971 insertions(+), 3062 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 9b0e977..b2e253a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -111,6 +111,7 @@ daemon/gdm-factory-slave
 daemon/gdm-session-worker
 daemon/gdm-simple-slave
 daemon/gdm-xdmcp-chooser-slave
+daemon/test-external-greeter
 daemon/test-session
 data/gdm.schemas.in
 depcomp
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 0fe2f1f..3a23a35 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -33,6 +33,7 @@ BUILT_SOURCES =					\
 	gdm-xdmcp-chooser-slave-glue.h		\
 	gdm-display-glue.h			\
 	gdm-xdmcp-display-glue.h		\
+	gdm-manager-glue.h			\
 	gdm-static-display-glue.h		\
 	gdm-transient-display-glue.h		\
 	gdm-local-display-factory-glue.h	\
@@ -75,19 +76,19 @@ gdm-local-display-factory-glue.c gdm-local-display-factory-glue.h : gdm-local-di
 		--generate-c-code=gdm-local-display-factory-glue	\
 		$(srcdir)/gdm-local-display-factory.xml
 
-gdm-session-glue.c gdm-session-glue.h : gdm-session.xml Makefile.am
+gdm-manager-glue.c gdm-manager-glue.h : gdm-manager.xml Makefile.am
 	$(AM_V_GEN)gdbus-codegen 					\
 		--c-namespace=GdmDBus					\
 		--interface-prefix=org.gnome.DisplayManager		\
-		--generate-c-code=gdm-session-glue			\
-		$(srcdir)/gdm-session.xml
+		--generate-c-code=gdm-manager-glue			\
+		$(srcdir)/gdm-manager.xml
 
-gdm-greeter-glue.c gdm-greeter-glue.h : gdm-greeter-server.xml Makefile.am
+gdm-session-glue.c gdm-session-glue.h : gdm-session.xml Makefile.am
 	$(AM_V_GEN)gdbus-codegen 					\
 		--c-namespace=GdmDBus					\
 		--interface-prefix=org.gnome.DisplayManager		\
-		--generate-c-code=gdm-greeter-glue			\
-		$(srcdir)/gdm-greeter-server.xml
+		--generate-c-code=gdm-session-glue			\
+		$(srcdir)/gdm-session.xml
 
 gdm-slave-glue.c gdm-slave-glue.h: gdm-slave.xml Makefile.am
 	$(AM_V_GEN)gdbus-codegen 					\
@@ -145,8 +146,6 @@ endif
 
 gdm_simple_slave_SOURCES = 		\
 	simple-slave-main.c 		\
-	gdm-greeter-server.c		\
-	gdm-greeter-server.h		\
 	gdm-welcome-session.c		\
 	gdm-welcome-session.h		\
 	gdm-greeter-session.c		\
@@ -195,8 +194,6 @@ gdm_simple_slave_LDADD = 			\
 
 gdm_xdmcp_chooser_slave_SOURCES = 		\
 	xdmcp-chooser-slave-main.c 		\
-	gdm-chooser-server.c			\
-	gdm-chooser-server.h			\
 	gdm-session.c				\
 	gdm-session.h				\
 	gdm-session-record.c			\
@@ -297,6 +294,8 @@ gdm_binary_SOURCES = 			\
 	gdm-manager.h			\
 	gdm-slave-proxy.c		\
 	gdm-slave-proxy.h		\
+	gdm-dbus-util.c			\
+	gdm-dbus-util.h			\
 	$(NULL)
 
 nodist_gdm_binary_SOURCES = 			\
@@ -304,10 +303,14 @@ nodist_gdm_binary_SOURCES = 			\
 	gdm-display-glue.c			\
 	gdm-local-display-factory-glue.h	\
 	gdm-local-display-factory-glue.c	\
+	gdm-manager-glue.h			\
+	gdm-manager-glue.c			\
 	gdm-transient-display-glue.h		\
 	gdm-transient-display-glue.c		\
 	gdm-static-display-glue.h		\
 	gdm-static-display-glue.c		\
+	gdm-slave-glue.h			\
+	gdm-slave-glue.c			\
 	$(NULL)
 
 XDMCP_SOURCES =				\
@@ -373,6 +376,7 @@ CLEANFILES =					\
 	gdm-display-glue.c			\
 	gdm-greeter-glue.c			\
 	gdm-local-display-factory-glue.c	\
+	gdm-manager-glue.c			\
 	gdm-session-glue.c			\
 	gdm-slave-glue.c			\
 	gdm-static-display-glue.c		\
@@ -384,7 +388,6 @@ CLEANFILES =					\
 
 EXTRA_DIST = 				\
 	gdm.in				\
-	gdm-greeter-server.xml		\
 	gdm-slave.xml			\
 	gdm-simple-slave.xml		\
 	gdm-xdmcp-chooser-slave.xml	\
diff --git a/daemon/gdm-chooser-session.c b/daemon/gdm-chooser-session.c
index 6aa60a6..9af116f 100644
--- a/daemon/gdm-chooser-session.c
+++ b/daemon/gdm-chooser-session.c
@@ -78,9 +78,6 @@ gdm_chooser_session_new (const char *display_name,
 
         object = g_object_new (GDM_TYPE_CHOOSER_SESSION,
                                "command", LIBEXECDIR "/gdm-simple-chooser",
-                               "server-dbus-path", GDM_CHOOSER_SERVER_DBUS_PATH,
-                               "server-dbus-interface", GDM_CHOOSER_SERVER_DBUS_INTERFACE,
-                               "server-env-var-name", "GDM_CHOOSER_DBUS_ADDRESS",
                                "x11-display-name", display_name,
                                "x11-display-device", display_device,
                                "x11-display-hostname", display_hostname,
diff --git a/daemon/gdm-dbus-util.c b/daemon/gdm-dbus-util.c
index 06ae667..ebaa43f 100644
--- a/daemon/gdm-dbus-util.c
+++ b/daemon/gdm-dbus-util.c
@@ -121,3 +121,43 @@ gdm_dbus_setup_private_server (GDBusAuthObserver  *observer,
 
         return server;
 }
+
+gboolean
+gdm_dbus_get_pid_for_name (const char  *system_bus_name,
+                           pid_t       *out_pid,
+                           GError     **error)
+{
+        GDBusConnection *bus;
+        GVariant *reply;
+        gboolean retval = FALSE;
+        unsigned int v;
+
+        bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
+        if (bus == NULL) {
+                return FALSE;
+        }
+
+        reply = g_dbus_connection_call_sync (bus,
+                                             "org.freedesktop.DBus",
+                                             "/org/freedesktop/DBus",
+                                             "org.freedesktop.DBus",
+                                             "GetConnectionUnixProcessID",
+                                             g_variant_new ("(s)", system_bus_name),
+                                             G_VARIANT_TYPE ("(u)"),
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL, error);
+        if (reply == NULL) {
+                goto out;
+        }
+
+        g_variant_get (reply, "(u)", &v);
+        *out_pid = v;
+        g_variant_unref (reply);
+
+        retval = TRUE;
+ out:
+        g_object_unref (bus);
+
+        return retval;
+}
diff --git a/daemon/gdm-dbus-util.h b/daemon/gdm-dbus-util.h
index acdb197..d83dea7 100644
--- a/daemon/gdm-dbus-util.h
+++ b/daemon/gdm-dbus-util.h
@@ -22,8 +22,14 @@
 #define __GDM_DBUS_UTIL_H
 
 #include <gio/gio.h>
+#include <unistd.h>
+#include <sys/types.h>
 
 GDBusServer *gdm_dbus_setup_private_server (GDBusAuthObserver  *observer,
 					    GError            **error);
 
+gboolean gdm_dbus_get_pid_for_name (const char  *system_bus_name,
+                                    pid_t       *out_pid,
+                                    GError     **error);
+
 #endif
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 799a51c..6141aca 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -41,17 +41,19 @@
 #include "gdm-settings-keys.h"
 
 #include "gdm-slave-proxy.h"
-
-static guint32 display_serial = 1;
+#include "gdm-slave-glue.h"
+#include "gdm-dbus-util.h"
 
 #define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate))
 
+#define GDM_SLAVE_PATH "/org/gnome/DisplayManager/Slave"
 #define DEFAULT_SLAVE_COMMAND LIBEXECDIR "/gdm-simple-slave"
 
 struct GdmDisplayPrivate
 {
         char                 *id;
         char                 *seat_id;
+        char                 *session_id;
 
         char                 *remote_hostname;
         int                   x11_display_number;
@@ -70,6 +72,7 @@ struct GdmDisplayPrivate
 
         GdmSlaveProxy        *slave_proxy;
         char                 *slave_bus_name;
+        GdmDBusSlave         *slave_bus_proxy;
         int                   slave_name_id;
         GDBusConnection      *connection;
         GdmDisplayAccessFile *user_access_file;
@@ -83,6 +86,7 @@ enum {
         PROP_ID,
         PROP_STATUS,
         PROP_SEAT_ID,
+        PROP_SESSION_ID,
         PROP_REMOTE_HOSTNAME,
         PROP_X11_DISPLAY_NUMBER,
         PROP_X11_DISPLAY_NAME,
@@ -110,20 +114,6 @@ gdm_display_error_quark (void)
         return ret;
 }
 
-static guint32
-get_next_display_serial (void)
-{
-        guint32 serial;
-
-        serial = display_serial++;
-
-        if ((gint32)display_serial < 0) {
-                display_serial = 1;
-        }
-
-        return serial;
-}
-
 time_t
 gdm_display_get_creation_time (GdmDisplay *display)
 {
@@ -140,6 +130,12 @@ gdm_display_get_status (GdmDisplay *display)
         return display->priv->status;
 }
 
+char *
+gdm_display_get_session_id (GdmDisplay *display)
+{
+        return g_strdup (display->priv->session_id);
+}
+
 static GdmDisplayAccessFile *
 _create_access_file_for_user (GdmDisplay  *display,
                               const char  *username,
@@ -308,6 +304,19 @@ gdm_display_real_set_slave_bus_name (GdmDisplay *display,
                                         on_name_vanished,
                                         g_object_ref (display),
                                         NULL);
+
+        g_clear_object (&display->priv->slave_bus_proxy);
+        display->priv->slave_bus_proxy = GDM_DBUS_SLAVE (gdm_dbus_slave_proxy_new_sync (display->priv->connection,
+                                                                                        G_DBUS_PROXY_FLAGS_NONE,
+                                                                                        name,
+                                                                                        GDM_SLAVE_PATH,
+                                                                                        NULL, NULL));
+        g_object_bind_property (G_OBJECT (display->priv->slave_bus_proxy),
+                                "session-id",
+                                G_OBJECT (display),
+                                "session-id",
+                                G_BINDING_DEFAULT);
+
         return TRUE;
 }
 
@@ -823,6 +832,14 @@ _gdm_display_set_seat_id (GdmDisplay     *display,
 }
 
 static void
+_gdm_display_set_session_id (GdmDisplay     *display,
+                             const char     *session_id)
+{
+        g_free (display->priv->session_id);
+        display->priv->session_id = g_strdup (session_id);
+}
+
+static void
 _gdm_display_set_remote_hostname (GdmDisplay     *display,
                                   const char     *hostname)
 {
@@ -888,6 +905,9 @@ gdm_display_set_property (GObject        *object,
         case PROP_SEAT_ID:
                 _gdm_display_set_seat_id (self, g_value_get_string (value));
                 break;
+        case PROP_SESSION_ID:
+                _gdm_display_set_session_id (self, g_value_get_string (value));
+                break;
         case PROP_REMOTE_HOSTNAME:
                 _gdm_display_set_remote_hostname (self, g_value_get_string (value));
                 break;
@@ -932,6 +952,9 @@ gdm_display_get_property (GObject        *object,
         case PROP_SEAT_ID:
                 g_value_set_string (value, self->priv->seat_id);
                 break;
+        case PROP_SESSION_ID:
+                g_value_set_string (value, self->priv->session_id);
+                break;
         case PROP_REMOTE_HOSTNAME:
                 g_value_set_string (value, self->priv->remote_hostname);
                 break;
@@ -1176,8 +1199,6 @@ handle_remove_user_authorization (GdmDBusDisplay        *skeleton,
         return TRUE;
 }
 
-
-
 static gboolean
 register_display (GdmDisplay *display)
 {
@@ -1227,6 +1248,35 @@ register_display (GdmDisplay *display)
         return TRUE;
 }
 
+char *
+gdm_display_open_session_sync (GdmDisplay    *display,
+                               GCancellable  *cancellable,
+                               GError       **error)
+{
+        char *address;
+        int ret;
+
+        if (display->priv->slave_bus_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_bus_proxy,
+                                                     &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
 */
@@ -1237,14 +1287,21 @@ gdm_display_constructor (GType                  type,
                          GObjectConstructParam *construct_properties)
 {
         GdmDisplay      *display;
+        char            *canonical_display_name;
         gboolean         res;
 
         display = GDM_DISPLAY (G_OBJECT_CLASS (gdm_display_parent_class)->constructor (type,
                                                                                        n_construct_properties,
                                                                                        construct_properties));
 
+        canonical_display_name = g_strdelimit (g_strdup (display->priv->x11_display_name),
+                                               ":" G_STR_DELIMITERS, '_');
+
         g_free (display->priv->id);
-        display->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Displays/%u", get_next_display_serial ());
+        display->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Displays/%s",
+                                             canonical_display_name);
+
+        g_free (canonical_display_name);
 
         res = register_display (display);
         if (! res) {
@@ -1352,6 +1409,13 @@ gdm_display_class_init (GdmDisplayClass *klass)
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
         g_object_class_install_property (object_class,
+                                         PROP_SESSION_ID,
+                                         g_param_spec_string ("session id",
+                                                              "session id",
+                                                              "session id",
+                                                              NULL,
+                                                              G_PARAM_READWRITE));
+        g_object_class_install_property (object_class,
                                          PROP_X11_COOKIE,
                                          g_param_spec_string ("x11-cookie",
                                                               "cookie",
diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h
index 6cbcca2..1f4d3db 100644
--- a/daemon/gdm-display.h
+++ b/daemon/gdm-display.h
@@ -79,7 +79,8 @@ typedef struct
 typedef enum
 {
          GDM_DISPLAY_ERROR_GENERAL,
-         GDM_DISPLAY_ERROR_GETTING_USER_INFO
+         GDM_DISPLAY_ERROR_GETTING_USER_INFO,
+         GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
 } GdmDisplayError;
 
 #define GDM_DISPLAY_ERROR gdm_display_error_quark ()
@@ -89,8 +90,10 @@ 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_get_user_auth                  (GdmDisplay *display);
-
+char *              gdm_display_open_session_sync              (GdmDisplay    *display,
+                                                                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);
 gboolean            gdm_display_manage                         (GdmDisplay *display);
diff --git a/daemon/gdm-display.xml b/daemon/gdm-display.xml
index 13c734d..fbeb323 100644
--- a/daemon/gdm-display.xml
+++ b/daemon/gdm-display.xml
@@ -17,7 +17,7 @@
       <arg name="filename" direction="out" type="s"/>
     </method>
     <method name="GetSeatId">
-      <arg name="filename" direction="out" type="s"/>
+      <arg name="seat_id" direction="out" type="s"/>
     </method>
     <method name="GetRemoteHostname">
       <arg name="hostname" direction="out" type="s"/>
@@ -43,5 +43,8 @@
       <arg name="username" direction="out" type="s"/>
       <arg name="delay" direction="out" type="i"/>
     </method>
+    <method name="ConnectToSlave">
+      <arg name="address" direction="out" type="s"/>
+    </method>
   </interface>
 </node>
diff --git a/daemon/gdm-greeter-session.c b/daemon/gdm-greeter-session.c
index 464b16b..f9f16e3 100644
--- a/daemon/gdm-greeter-session.c
+++ b/daemon/gdm-greeter-session.c
@@ -89,9 +89,6 @@ gdm_greeter_session_new (const char *display_name,
 
         object = g_object_new (GDM_TYPE_GREETER_SESSION,
                                "command", command,
-                               "server-dbus-path", GDM_GREETER_SERVER_DBUS_PATH,
-                               "server-dbus-interface", GDM_GREETER_SERVER_DBUS_INTERFACE,
-                               "server-env-var-name", "GDM_GREETER_DBUS_ADDRESS",
                                "x11-display-name", display_name,
                                "x11-display-seat-id", seat_id,
                                "x11-display-device", display_device,
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index c0bdc5c..931b3b8 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -34,9 +34,16 @@
 #include <glib/gstdio.h>
 #include <glib-object.h>
 
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-daemon.h>
+#include <systemd/sd-login.h>
+#endif
+
 #include "gdm-common.h"
 
+#include "gdm-dbus-util.h"
 #include "gdm-manager.h"
+#include "gdm-manager-glue.h"
 #include "gdm-display-store.h"
 #include "gdm-display-factory.h"
 #include "gdm-local-display-factory.h"
@@ -44,9 +51,9 @@
 
 #define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
 
-#define GDM_DBUS_PATH         "/org/gnome/DisplayManager"
-#define GDM_MANAGER_DBUS_PATH GDM_DBUS_PATH "/Displays"
-#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.Manager"
+#define GDM_DBUS_PATH             "/org/gnome/DisplayManager"
+#define GDM_MANAGER_PATH          GDM_DBUS_PATH "Manager"
+#define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
 
 struct GdmManagerPrivate
 {
@@ -85,7 +92,178 @@ static void     gdm_manager_finalize    (GObject         *object);
 
 static gpointer manager_object = NULL;
 
-G_DEFINE_TYPE (GdmManager, gdm_manager, G_TYPE_OBJECT)
+static void manager_interface_init (GdmDBusManagerIface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (GdmManager,
+                         gdm_manager,
+                         G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GDM_DBUS_TYPE_MANAGER,
+                                                manager_interface_init));
+
+#ifdef WITH_SYSTEMD
+static char *
+get_session_id_for_pid_systemd (pid_t    pid,
+                                GError **error)
+{
+        char *session, *gsession;
+        int ret;
+
+        ret = sd_pid_get_session (pid, &session);
+        if (ret < 0) {
+                g_set_error (error,
+                             GDM_DISPLAY_ERROR,
+                             GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
+                             "Error getting session id from systemd: %s",
+                             g_strerror (-ret));
+        }
+
+        if (session != NULL) {
+                gsession = g_strdup (session);
+                free (session);
+
+                return gsession;
+        } else {
+                return NULL;
+        }
+}
+#endif
+
+#ifdef WITH_CONSOLEKIT
+static char *
+get_session_id_for_pid_consolekit (GDBusConnection  *connection,
+                                   pid_t             pid,
+                                   GError          **error)
+{
+        GVariant *reply;
+        char *retval;
+
+        reply = g_dbus_connection_call_sync (connection,
+                                             "org.freedesktop.ConsoleKit",
+                                             "/org/freedesktop/ConsoleKit/Manager",
+                                             "org.freedesktop.ConsoleKit.Manager",
+                                             "GetSessionForUnixProcess",
+                                             g_variant_new ("(u)", pid),
+                                             G_VARIANT_TYPE ("(o)"),
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL, error);
+        if (reply == NULL) {
+                return NULL;
+        }
+
+        g_variant_get (reply, "(o)", &retval);
+        g_variant_unref (reply);
+
+        return retval;
+}
+#endif
+
+static char *
+get_session_id_for_pid (GDBusConnection  *connection,
+                        pid_t             pid,
+                        GError          **error)
+{
+#ifdef WITH_SYSTEMD
+        if (sd_booted () > 0) {
+                return get_session_id_for_pid_systemd (pid, error);
+        }
+#endif
+
+#ifdef WITH_CONSOLEKIT
+        return get_session_id_for_pid_consolekit (connection, pid, error);
+#endif
+
+        return NULL;
+}
+
+static gboolean
+lookup_by_session_id (const char *id,
+                      GdmDisplay *display,
+                      gpointer    user_data)
+{
+        const char *looking_for = user_data;
+        char *current;
+        gboolean res;
+
+        current = gdm_display_get_session_id (display);
+
+        res = g_strcmp0 (current, looking_for) == 0;
+
+        g_free (current);
+
+        return res;
+}
+
+static gboolean
+gdm_manager_handle_open_session (GdmDBusManager        *manager,
+                                 GDBusMethodInvocation *invocation)
+{
+        GdmManager       *self = GDM_MANAGER (manager);
+        GDBusConnection  *connection;
+        GdmDisplay       *display;
+        const char       *sender;
+        char             *session_id;
+        GError           *error;
+        char             *address;
+        int               ret;
+        GPid              pid;
+
+        sender = g_dbus_method_invocation_get_sender (invocation);
+        error = NULL;
+        ret = gdm_dbus_get_pid_for_name (sender, &pid, &error);
+
+        if (!ret) {
+                g_prefix_error (&error, "Error while retrieving caller session id: ");
+                g_dbus_method_invocation_return_gerror (invocation, error);
+                g_error_free (error);
+                return TRUE;
+
+        }
+
+        connection = g_dbus_method_invocation_get_connection (invocation);
+        session_id = get_session_id_for_pid (connection, pid, &error);
+
+        if (session_id == NULL) {
+                g_dbus_method_invocation_return_gerror (invocation, error);
+                g_error_free (error);
+                return TRUE;
+        }
+
+        display = gdm_display_store_find (self->priv->display_store,
+                                          lookup_by_session_id,
+                                          (gpointer) session_id);
+        g_free (session_id);
+
+        if (display == NULL) {
+                g_dbus_method_invocation_return_error_literal (invocation,
+                                                               G_DBUS_ERROR,
+                                                               G_DBUS_ERROR_ACCESS_DENIED,
+                                                               _("No session available"));
+
+                return TRUE;
+        }
+
+        address = gdm_display_open_session_sync (display, NULL, &error);
+
+        if (address == NULL) {
+                g_dbus_method_invocation_return_gerror (invocation, error);
+                g_error_free (error);
+                return TRUE;
+        }
+
+        gdm_dbus_manager_complete_open_session (GDM_DBUS_MANAGER (manager),
+                                                invocation,
+                                                address);
+        g_free (address);
+
+        return TRUE;
+}
+
+static void
+manager_interface_init (GdmDBusManagerIface *interface)
+{
+        interface->handle_open_session = gdm_manager_handle_open_session;
+}
 
 static void
 on_display_removed (GdmDisplayStore *display_store,
@@ -235,17 +413,30 @@ register_manager (GdmManager *manager)
         GDBusObjectManagerServer *object_server;
 
         error = NULL;
-        manager->priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+        manager->priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
+                                                    NULL,
+                                                    &error);
         if (manager->priv->connection == NULL) {
                 g_critical ("error getting system bus: %s", error->message);
                 g_error_free (error);
                 exit (1);
         }
 
-        object_server = g_dbus_object_manager_server_new (GDM_MANAGER_DBUS_PATH);
+        object_server = g_dbus_object_manager_server_new (GDM_MANAGER_DISPLAYS_PATH);
         g_dbus_object_manager_server_set_connection (object_server, manager->priv->connection);
         manager->priv->object_manager = object_server;
 
+        if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (manager),
+                                               manager->priv->connection,
+                                               GDM_MANAGER_PATH,
+                                               &error)) {
+                g_critical ("error exporting interface to %s: %s",
+                            GDM_MANAGER_PATH,
+                            error->message);
+                g_error_free (error);
+                exit (1);
+        }
+
         return TRUE;
 }
 
diff --git a/daemon/gdm-manager.xml b/daemon/gdm-manager.xml
new file mode 100644
index 0000000..8c1a94e
--- /dev/null
+++ b/daemon/gdm-manager.xml
@@ -0,0 +1,8 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+<node name="/org/gnome/DisplayManager/Manager">
+  <interface name="org.gnome.DisplayManager.Manager">
+    <method name="OpenSession">
+      <arg name="address" direction="out" type="s"/>
+    </method>
+  </interface>
+</node>
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 1922920..3de8d09 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -122,6 +122,7 @@ struct GdmSessionWorkerPrivate
         char             *username;
         char             *log_file;
         char             *session_type;
+        char             *session_id;
         uid_t             uid;
         gid_t             gid;
         gboolean          password_is_required;
@@ -134,9 +135,9 @@ struct GdmSessionWorkerPrivate
         guint32           is_program_session : 1;
         guint             state_change_idle_id;
 
-        char             *server_address;
-        GDBusConnection  *connection;
-        GdmDBusSession   *session_proxy;
+        char                 *server_address;
+        GDBusConnection      *connection;
+        GdmDBusWorkerManager *manager;
 
         GdmSessionAuditor  *auditor;
         GdmSessionSettings *user_settings;
@@ -337,6 +338,51 @@ out:
         g_clear_pointer (&worker->priv->session_cookie,
                          (GDestroyNotify) g_free);
 }
+
+static char *
+get_ck_session_id (GdmSessionWorker *worker)
+{
+        GDBusConnection  *system_bus;
+        GVariant         *reply;
+        GError           *error = NULL;
+        char             *session_id = NULL;
+
+        error = NULL;
+        system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+
+        if (system_bus == NULL) {
+                g_warning ("Couldn't create connection to system bus: %s",
+                           error->message);
+
+                g_error_free (error);
+                goto out;
+        }
+
+        reply = g_dbus_connection_call_sync (system_bus,
+                                             "org.freedesktop.ConsoleKit",
+                                             "/org/freedesktop/ConsoleKit/Manager",
+                                             "org.freedesktop.ConsoleKit.Manager",
+                                             "GetCurrentSession",
+                                             NULL,
+                                             G_VARIANT_TYPE ("(o)"),
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL,
+                                             &error);
+
+        if (reply == NULL) {
+                g_warning ("%s", error->message);
+                g_clear_error (&error);
+                goto out;
+        }
+
+        g_variant_get (reply, "(o)", &session_id);
+
+        g_variant_unref (reply);
+
+out:
+        return session_id;
+}
 #endif
 
 /* adapted from glib script_execute */
@@ -584,10 +630,11 @@ gdm_session_worker_update_username (GdmSessionWorker *worker)
                 worker->priv->username = username;
                 username = NULL;
 
-                gdm_dbus_session_call_username_changed_sync (worker->priv->session_proxy,
-                                                             worker->priv->service,
-                                                             worker->priv->username,
-                                                             NULL, NULL);
+                gdm_dbus_worker_manager_call_username_changed_sync (worker->priv->manager,
+                                                                    worker->priv->service,
+                                                                    worker->priv->username,
+                                                                    NULL,
+                                                                    NULL);
 
                 /* We have a new username to try. If we haven't been able to
                  * read user settings up until now, then give it a go now
@@ -609,11 +656,12 @@ gdm_session_worker_ask_question (GdmSessionWorker *worker,
                                  const char       *question,
                                  char            **answerp)
 {
-        return gdm_dbus_session_call_info_query_sync (worker->priv->session_proxy,
-                                                      worker->priv->service,
-                                                      question,
-                                                      answerp,
-                                                      NULL, NULL);
+        return gdm_dbus_worker_manager_call_info_query_sync (worker->priv->manager,
+                                                             worker->priv->service,
+                                                             question,
+                                                             answerp,
+                                                             NULL,
+                                                             NULL);
 }
 
 static gboolean
@@ -621,31 +669,34 @@ gdm_session_worker_ask_for_secret (GdmSessionWorker *worker,
                                    const char       *question,
                                    char            **answerp)
 {
-        return gdm_dbus_session_call_secret_info_query_sync (worker->priv->session_proxy,
-                                                             worker->priv->service,
-                                                             question,
-                                                             answerp,
-                                                             NULL, NULL);
+        return gdm_dbus_worker_manager_call_secret_info_query_sync (worker->priv->manager,
+                                                                    worker->priv->service,
+                                                                    question,
+                                                                    answerp,
+                                                                    NULL,
+                                                                    NULL);
 }
 
 static gboolean
 gdm_session_worker_report_info (GdmSessionWorker *worker,
                                 const char       *info)
 {
-        return gdm_dbus_session_call_info_sync (worker->priv->session_proxy,
-                                                worker->priv->service,
-                                                info,
-                                                NULL, NULL);
+        return gdm_dbus_worker_manager_call_info_sync (worker->priv->manager,
+                                                       worker->priv->service,
+                                                       info,
+                                                       NULL,
+                                                       NULL);
 }
 
 static gboolean
 gdm_session_worker_report_problem (GdmSessionWorker *worker,
                                    const char       *problem)
 {
-        return gdm_dbus_session_call_problem_sync (worker->priv->session_proxy,
-                                                   worker->priv->service,
-                                                   problem,
-                                                   NULL, NULL);
+        return gdm_dbus_worker_manager_call_problem_sync (worker->priv->manager,
+                                                          worker->priv->service,
+                                                          problem,
+                                                          NULL,
+                                                          NULL);
 }
 
 static char *
@@ -720,9 +771,10 @@ gdm_session_worker_process_pam_message (GdmSessionWorker          *worker,
         }
 
         if (worker->priv->timed_out) {
-                gdm_dbus_session_call_cancel_pending_query_sync (worker->priv->session_proxy,
-                                                                 worker->priv->service,
-                                                                 NULL, NULL);
+                gdm_dbus_worker_manager_call_cancel_pending_query_sync (worker->priv->manager,
+                                                                        worker->priv->service,
+                                                                        NULL,
+                                                                        NULL);
                 worker->priv->timed_out = FALSE;
         }
 
@@ -1504,10 +1556,11 @@ session_worker_child_watch (GPid              pid,
 
         gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
 
-        gdm_dbus_session_call_session_exited_sync (worker->priv->session_proxy,
-                                                   worker->priv->service,
-                                                   status,
-                                                   NULL, NULL);
+        gdm_dbus_worker_manager_call_session_exited_sync (worker->priv->manager,
+                                                          worker->priv->service,
+                                                          status,
+                                                          NULL,
+                                                          NULL);
 
         worker->priv->child_pid = -1;
 }
@@ -1812,6 +1865,7 @@ gdm_session_worker_open_session (GdmSessionWorker  *worker,
 {
         int error_code;
         int flags;
+        char *session_id;
 
         g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
         g_assert (geteuid () == 0);
@@ -1835,6 +1889,19 @@ gdm_session_worker_open_session (GdmSessionWorker  *worker,
         g_debug ("GdmSessionWorker: state SESSION_OPENED");
         worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_OPENED;
 
+        session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID");
+
+        if (session_id != NULL) {
+                g_free (worker->priv->session_id);
+                worker->priv->session_id = session_id;
+        }
+
+#ifdef WITH_CONSOLE_KIT
+        if (session_id == NULL) {
+                session_id = get_ck_session_id (worker);
+        }
+#endif
+
  out:
         if (error_code != PAM_SUCCESS) {
                 gdm_session_worker_uninitialize_pam (worker, error_code);
@@ -1896,19 +1963,19 @@ gdm_session_worker_get_property (GObject    *object,
 }
 
 static void
-on_set_environment_variable (GdmDBusSession   *proxy,
-                             const char       *key,
-                             const char       *value,
-                             GdmSessionWorker *worker)
+on_set_environment_variable (GdmDBusWorkerManager *proxy,
+                             const char           *key,
+                             const char           *value,
+                             GdmSessionWorker     *worker)
 {
         g_debug ("GdmSessionWorker: set env: %s = %s", key, value);
         gdm_session_worker_set_environment_variable (worker, key, value);
 }
 
 static void
-on_set_session_name (GdmDBusSession   *proxy,
-                     const char       *session_name,
-                     GdmSessionWorker *worker)
+on_set_session_name (GdmDBusWorkerManager *proxy,
+                     const char           *session_name,
+                     GdmSessionWorker     *worker)
 {
         g_debug ("GdmSessionWorker: session name set to %s", session_name);
         gdm_session_settings_set_session_name (worker->priv->user_settings,
@@ -1916,9 +1983,9 @@ on_set_session_name (GdmDBusSession   *proxy,
 }
 
 static void
-on_set_session_type (GdmDBusSession   *proxy,
-                     const char       *session_type,
-                     GdmSessionWorker *worker)
+on_set_session_type (GdmDBusWorkerManager *proxy,
+                     const char           *session_type,
+                     GdmSessionWorker     *worker)
 {
         g_debug ("GdmSessionWorker: session type set to %s", session_type);
         g_free (worker->priv->session_type);
@@ -1926,9 +1993,9 @@ on_set_session_type (GdmDBusSession   *proxy,
 }
 
 static void
-on_set_language_name (GdmDBusSession   *proxy,
-                      const char       *language_name,
-                      GdmSessionWorker *worker)
+on_set_language_name (GdmDBusWorkerManager *proxy,
+                      const char           *language_name,
+                      GdmSessionWorker     *worker)
 {
         g_debug ("GdmSessionWorker: language name set to %s", language_name);
         gdm_session_settings_set_language_name (worker->priv->user_settings,
@@ -1943,9 +2010,10 @@ on_saved_language_name_read (GdmSessionWorker *worker)
         language_name = gdm_session_settings_get_language_name (worker->priv->user_settings);
 
         g_debug ("GdmSessionWorker: Saved language is %s", language_name);
-        gdm_dbus_session_call_saved_language_name_read_sync (worker->priv->session_proxy,
-                                                             language_name,
-                                                             NULL, NULL);
+        gdm_dbus_worker_manager_call_saved_language_name_read_sync (worker->priv->manager,
+                                                                    language_name,
+                                                                    NULL,
+                                                                    NULL);
         g_free (language_name);
 }
 
@@ -1957,9 +2025,10 @@ on_saved_session_name_read (GdmSessionWorker *worker)
         session_name = gdm_session_settings_get_session_name (worker->priv->user_settings);
 
         g_debug ("GdmSessionWorker: Saved session is %s", session_name);
-        gdm_dbus_session_call_saved_session_name_read_sync (worker->priv->session_proxy,
-                                                            session_name,
-                                                            NULL, NULL);
+        gdm_dbus_worker_manager_call_saved_session_name_read_sync (worker->priv->manager,
+                                                                   session_name,
+                                                                   NULL,
+                                                                   NULL);
         g_free (session_name);
 }
 
@@ -1983,15 +2052,17 @@ do_setup (GdmSessionWorker *worker)
                 if (g_error_matches (error,
                                      GDM_SESSION_WORKER_ERROR,
                                      GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE)) {
-                        gdm_dbus_session_call_service_unavailable_sync (worker->priv->session_proxy,
+                        gdm_dbus_worker_manager_call_service_unavailable_sync (worker->priv->manager,
+                                                                               worker->priv->service,
+                                                                               error->message,
+                                                                               NULL,
+                                                                               NULL);
+                } else {
+                        gdm_dbus_worker_manager_call_setup_failed_sync (worker->priv->manager,
                                                                         worker->priv->service,
                                                                         error->message,
-                                                                        NULL, NULL);
-                } else {
-                        gdm_dbus_session_call_setup_failed_sync (worker->priv->session_proxy,
-                                                                 worker->priv->service,
-                                                                 error->message,
-                                                                 NULL, NULL);
+                                                                        NULL,
+                                                                        NULL);
                 }
                 g_error_free (error);
                 return;
@@ -2009,9 +2080,10 @@ do_setup (GdmSessionWorker *worker)
                                               G_CALLBACK (on_saved_language_name_read),
                                               worker);
 
-        gdm_dbus_session_call_setup_complete_sync (worker->priv->session_proxy,
-                                                   worker->priv->service,
-                                                   NULL, NULL);
+        gdm_dbus_worker_manager_call_setup_complete_sync (worker->priv->manager,
+                                                          worker->priv->service,
+                                                          NULL,
+                                                          NULL);
 }
 
 static void
@@ -2031,16 +2103,18 @@ do_authenticate (GdmSessionWorker *worker)
                                      GDM_SESSION_WORKER_ERROR,
                                      GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE)) {
                         g_debug ("GdmSessionWorker: Unable to use authentication service");
-                        gdm_dbus_session_call_service_unavailable_sync (worker->priv->session_proxy,
-                                                                        worker->priv->service,
-                                                                        error->message,
-                                                                        NULL, NULL);
+                        gdm_dbus_worker_manager_call_service_unavailable_sync (worker->priv->manager,
+                                                                               worker->priv->service,
+                                                                               error->message,
+                                                                               NULL,
+                                                                               NULL);
                 } else {
                         g_debug ("GdmSessionWorker: Unable to verify user");
-                        gdm_dbus_session_call_authentication_failed_sync (worker->priv->session_proxy,
-                                                                          worker->priv->service,
-                                                                          error->message,
-                                                                          NULL, NULL);
+                        gdm_dbus_worker_manager_call_authentication_failed_sync (worker->priv->manager,
+                                                                                 worker->priv->service,
+                                                                                 error->message,
+                                                                                 NULL,
+                                                                                 NULL);
                 }
                 g_error_free (error);
                 return;
@@ -2054,9 +2128,10 @@ do_authenticate (GdmSessionWorker *worker)
                 gdm_session_worker_update_username (worker);
         }
 
-        gdm_dbus_session_call_authenticated_sync (worker->priv->session_proxy,
-                                                  worker->priv->service,
-                                                  NULL, NULL);
+        gdm_dbus_worker_manager_call_authenticated_sync (worker->priv->manager,
+                                                         worker->priv->service,
+                                                         NULL,
+                                                         NULL);
 }
 
 static void
@@ -2072,17 +2147,19 @@ do_authorize (GdmSessionWorker *worker)
                                                  worker->priv->password_is_required,
                                                  &error);
         if (! res) {
-                gdm_dbus_session_call_authorization_failed_sync (worker->priv->session_proxy,
-                                                                 worker->priv->service,
-                                                                 error->message,
-                                                                 NULL, NULL);
+                gdm_dbus_worker_manager_call_authorization_failed_sync (worker->priv->manager,
+                                                                        worker->priv->service,
+                                                                        error->message,
+                                                                        NULL,
+                                                                        NULL);
                 g_error_free (error);
                 return;
         }
 
-        gdm_dbus_session_call_authorized_sync (worker->priv->session_proxy,
-                                               worker->priv->service,
-                                               NULL, NULL);
+        gdm_dbus_worker_manager_call_authorized_sync (worker->priv->manager,
+                                                      worker->priv->service,
+                                                      NULL,
+                                                      NULL);
 }
 
 static void
@@ -2097,17 +2174,19 @@ do_accredit (GdmSessionWorker *worker)
         res = gdm_session_worker_accredit_user (worker, &error);
 
         if (! res) {
-                gdm_dbus_session_call_accreditation_failed_sync (worker->priv->session_proxy,
-                                                                 worker->priv->service,
-                                                                 error->message,
-                                                                 NULL, NULL);
+                gdm_dbus_worker_manager_call_accreditation_failed_sync (worker->priv->manager,
+                                                                        worker->priv->service,
+                                                                        error->message,
+                                                                        NULL,
+                                                                        NULL);
                 g_error_free (error);
                 return;
         }
 
-        gdm_dbus_session_call_accredited_sync (worker->priv->session_proxy,
-                                               worker->priv->service,
-                                               NULL, NULL);
+        gdm_dbus_worker_manager_call_accredited_sync (worker->priv->manager,
+                                                      worker->priv->service,
+                                                      NULL,
+                                                      NULL);
 }
 
 static void
@@ -2177,17 +2256,21 @@ do_open_session (GdmSessionWorker *worker)
         error = NULL;
         res = gdm_session_worker_open_session (worker, &error);
         if (! res) {
-                gdm_dbus_session_call_open_failed_sync (worker->priv->session_proxy,
-                                                        worker->priv->service,
-                                                        error->message,
-                                                        NULL, NULL);
+                gdm_dbus_worker_manager_call_open_failed_sync (worker->priv->manager,
+                                                               worker->priv->service,
+                                                               error->message,
+                                                               NULL,
+                                                               NULL);
                 g_error_free (error);
                 return;
         }
 
-        gdm_dbus_session_call_opened_sync (worker->priv->session_proxy,
-                                           worker->priv->service,
-                                           NULL, NULL);
+        gdm_dbus_worker_manager_call_opened_sync (worker->priv->manager,
+                                                  worker->priv->service,
+                                                  worker->priv->session_id ?
+                                                  worker->priv->session_id : "",
+                                                  NULL,
+                                                  NULL);
 }
 
 static void
@@ -2199,18 +2282,20 @@ do_start_session (GdmSessionWorker *worker)
         error = NULL;
         res = gdm_session_worker_start_session (worker, &error);
         if (! res) {
-                gdm_dbus_session_call_session_start_failed_sync (worker->priv->session_proxy,
-                                                                 worker->priv->service,
-                                                                 error->message,
-                                                                 NULL, NULL);
+                gdm_dbus_worker_manager_call_session_start_failed_sync (worker->priv->manager,
+                                                                        worker->priv->service,
+                                                                        error->message,
+                                                                        NULL,
+                                                                        NULL);
                 g_error_free (error);
                 return;
         }
 
-        gdm_dbus_session_call_session_started_sync (worker->priv->session_proxy,
-                                                    worker->priv->service,
-                                                    worker->priv->child_pid,
-                                                    NULL, NULL);
+        gdm_dbus_worker_manager_call_session_started_sync (worker->priv->manager,
+                                                           worker->priv->service,
+                                                           worker->priv->child_pid,
+                                                           NULL,
+                                                           NULL);
 }
 
 static const char *
@@ -2304,9 +2389,9 @@ queue_state_change (GdmSessionWorker *worker)
 }
 
 static void
-on_start_program (GdmDBusSession   *proxy,
-                  const char       *text,
-                  GdmSessionWorker *worker)
+on_start_program (GdmDBusWorkerManager *proxy,
+                  const char           *text,
+                  GdmSessionWorker     *worker)
 {
         GError *parse_error = NULL;
 
@@ -2328,14 +2413,14 @@ on_start_program (GdmDBusSession   *proxy,
 }
 
 static void
-on_setup (GdmDBusSession   *proxy,
-          const char       *service,
-          const char       *x11_display_name,
-          const char       *x11_authority_file,
-          const char       *console,
-          const char       *seat_id,
-          const char       *hostname,
-          GdmSessionWorker *worker)
+on_setup (GdmDBusWorkerManager *proxy,
+          const char           *service,
+          const char           *x11_display_name,
+          const char           *x11_authority_file,
+          const char           *console,
+          const char           *seat_id,
+          const char           *hostname,
+          GdmSessionWorker     *worker)
 {
         if (worker->priv->state != GDM_SESSION_WORKER_STATE_NONE) {
                 g_debug ("GdmSessionWorker: ignoring spurious setup while in state %s", get_state_name (worker->priv->state));
@@ -2355,15 +2440,15 @@ on_setup (GdmDBusSession   *proxy,
 }
 
 static void
-on_setup_for_user (GdmDBusSession   *proxy,
-                   const char       *service,
-                   const char       *username,
-                   const char       *x11_display_name,
-                   const char       *x11_authority_file,
-                   const char       *console,
-                   const char       *seat_id,
-                   const char       *hostname,
-                   GdmSessionWorker *worker)
+on_setup_for_user (GdmDBusWorkerManager *proxy,
+                   const char           *service,
+                   const char           *username,
+                   const char           *x11_display_name,
+                   const char           *x11_authority_file,
+                   const char           *console,
+                   const char           *seat_id,
+                   const char           *hostname,
+                   GdmSessionWorker     *worker)
 {
         if (worker->priv->state != GDM_SESSION_WORKER_STATE_NONE) {
                 g_debug ("GdmSessionWorker: ignoring spurious setup while in state %s", get_state_name (worker->priv->state));
@@ -2402,15 +2487,15 @@ on_setup_for_user (GdmDBusSession   *proxy,
 }
 
 static void
-on_setup_for_program (GdmDBusSession   *proxy,
-                      const char       *service,
-                      const char       *x11_display_name,
-                      const char       *x11_authority_file,
-                      const char       *console,
-                      const char       *seat_id,
-                      const char       *hostname,
-                      const char       *log_file,
-                      GdmSessionWorker *worker)
+on_setup_for_program (GdmDBusWorkerManager *proxy,
+                      const char           *service,
+                      const char           *x11_display_name,
+                      const char           *x11_authority_file,
+                      const char           *console,
+                      const char           *seat_id,
+                      const char           *hostname,
+                      const char           *log_file,
+                      GdmSessionWorker     *worker)
 {
         if (worker->priv->state != GDM_SESSION_WORKER_STATE_NONE) {
                 g_debug ("GdmSessionWorker: ignoring spurious setup while in state %s", get_state_name (worker->priv->state));
@@ -2431,9 +2516,9 @@ on_setup_for_program (GdmDBusSession   *proxy,
 }
 
 static void
-on_authenticate (GdmDBusSession   *session,
-                 const char       *service_name,
-                 GdmSessionWorker *worker)
+on_authenticate (GdmDBusWorkerManager *manager,
+                 const char           *service_name,
+                 GdmSessionWorker     *worker)
 {
         if (worker->priv->state != GDM_SESSION_WORKER_STATE_SETUP_COMPLETE) {
                 g_debug ("GdmSessionWorker: ignoring spurious authenticate for user while in state %s", get_state_name (worker->priv->state));
@@ -2444,9 +2529,9 @@ on_authenticate (GdmDBusSession   *session,
 }
 
 static void
-on_authorize (GdmDBusSession   *session,
-              const char       *service_name,
-              GdmSessionWorker *worker)
+on_authorize (GdmDBusWorkerManager *manager,
+              const char           *service_name,
+              GdmSessionWorker     *worker)
 {
         if (worker->priv->state != GDM_SESSION_WORKER_STATE_AUTHENTICATED) {
                 g_debug ("GdmSessionWorker: ignoring spurious authorize for user while in state %s", get_state_name (worker->priv->state));
@@ -2457,9 +2542,9 @@ on_authorize (GdmDBusSession   *session,
 }
 
 static void
-on_establish_credentials (GdmDBusSession   *session,
-                          const char       *service_name,
-                          GdmSessionWorker *worker)
+on_establish_credentials (GdmDBusWorkerManager *manager,
+                          const char           *service_name,
+                          GdmSessionWorker     *worker)
 {
         if (worker->priv->state != GDM_SESSION_WORKER_STATE_AUTHORIZED) {
                 g_debug ("GdmSessionWorker: ignoring spurious establish credentials for user while in state %s", get_state_name (worker->priv->state));
@@ -2472,9 +2557,9 @@ on_establish_credentials (GdmDBusSession   *session,
 }
 
 static void
-on_open_session (GdmDBusSession   *session,
-                 const char       *service_name,
-                 GdmSessionWorker *worker)
+on_open_session (GdmDBusWorkerManager *manager,
+                 const char           *service_name,
+                 GdmSessionWorker     *worker)
 {
         if (worker->priv->state != GDM_SESSION_WORKER_STATE_ACCREDITED) {
                 g_debug ("GdmSessionWorker: ignoring spurious open session for user while in state %s", get_state_name (worker->priv->state));
@@ -2511,64 +2596,64 @@ gdm_session_worker_constructor (GType                  type,
                 exit (1);
         }
 
-        worker->priv->session_proxy = GDM_DBUS_SESSION (gdm_dbus_session_proxy_new_sync (worker->priv->connection,
-                                                                                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
-                                                                                         NULL, /* dbus name */
-                                                                                         GDM_SESSION_DBUS_PATH,
-                                                                                         NULL,
-                                                                                         &error));
-        if (worker->priv->session_proxy == NULL) {
+        worker->priv->manager = GDM_DBUS_WORKER_MANAGER (gdm_dbus_worker_manager_proxy_new_sync (worker->priv->connection,
+                                                                                                 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+                                                                                                 NULL, /* dbus name */
+                                                                                                 GDM_SESSION_DBUS_PATH,
+                                                                                                 NULL,
+                                                                                                 &error));
+        if (worker->priv->manager == NULL) {
                 g_warning ("error creating session proxy: %s", error->message);
                 g_clear_error (&error);
 
                 exit (1);
         }
 
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "authenticate",
                           G_CALLBACK (on_authenticate),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "authorize",
                           G_CALLBACK (on_authorize),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "establish-credentials",
                           G_CALLBACK (on_establish_credentials),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "open-session",
                           G_CALLBACK (on_open_session),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "set-environment-variable",
                           G_CALLBACK (on_set_environment_variable),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "set-session-name",
                           G_CALLBACK (on_set_session_name),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "set-language-name",
                           G_CALLBACK (on_set_language_name),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "set-session-type",
                           G_CALLBACK (on_set_session_type),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "setup",
                           G_CALLBACK (on_setup),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "setup-for-user",
                           G_CALLBACK (on_setup_for_user),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "setup-for-program",
                           G_CALLBACK (on_setup_for_program),
                           worker);
-        g_signal_connect (worker->priv->session_proxy,
+        g_signal_connect (worker->priv->manager,
                           "start-program",
                           G_CALLBACK (on_start_program),
                           worker);
@@ -2576,8 +2661,9 @@ gdm_session_worker_constructor (GType                  type,
         /* Send an initial Hello message so that the session can associate
          * the conversation we manage with our pid.
          */
-        gdm_dbus_session_call_hello_sync (worker->priv->session_proxy,
-                                          NULL, NULL);
+        gdm_dbus_worker_manager_call_hello_sync (worker->priv->manager,
+                                                 NULL,
+                                                 NULL);
 
         return G_OBJECT (worker);
 }
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index bc9aad9..4f3e9bb 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -56,9 +56,8 @@
 #include "gdm-session-worker-job.h"
 #include "gdm-common.h"
 
-#define GDM_SESSION_DBUS_PATH         "/org/gnome/DisplayManager/Session"
-#define GDM_SESSION_DBUS_INTERFACE    "org.gnome.DisplayManager.Session"
 #define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel"
+#define GDM_SESSION_DBUS_OBJECT_PATH "/org/gnome/DisplayManager/Session"
 
 #ifndef GDM_SESSION_DEFAULT_PATH
 #define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin"
@@ -72,7 +71,7 @@ typedef struct
         char                  *service_name;
         GDBusConnection       *worker_connection;
         GDBusMethodInvocation *pending_invocation;
-        GdmDBusSession        *worker_skeleton;
+        GdmDBusWorkerManager  *worker_manager_interface;
         char                  *session_id;
         guint32                is_stopping : 1;
 } GdmSessionConversation;
@@ -92,7 +91,11 @@ struct _GdmSessionPrivate
 
         GdmSessionConversation *session_conversation;
 
-        GList               *pending_connections;
+        GdmDBusUserVerifier   *user_verifier_interface;
+        GdmDBusGreeterSession *greeter_session_interface;
+
+        GList               *pending_worker_connections;
+        GList               *outside_connections;
 
         GPid                 session_pid;
 
@@ -107,7 +110,8 @@ struct _GdmSessionPrivate
 
         char                *fallback_session_name;
 
-        GDBusServer         *server;
+        GDBusServer         *worker_server;
+        GDBusServer         *outside_server;
         GHashTable          *environment;
 };
 
@@ -126,28 +130,20 @@ enum {
 enum {
         CONVERSATION_STARTED = 0,
         CONVERSATION_STOPPED,
-        SERVICE_UNAVAILABLE,
         SETUP_COMPLETE,
-        SETUP_FAILED,
-        AUTHENTICATED,
-        AUTHENTICATION_FAILED,
+        CANCELLED,
+        HOSTNAME_SELECTED,
+        CLIENT_CONNECTED,
+        CLIENT_DISCONNECTED,
+        CLIENT_READY_FOR_SESSION_TO_START,
+        DISCONNECTED,
         AUTHORIZED,
         AUTHORIZATION_FAILED,
-        ACCREDITED,
-        ACCREDITATION_FAILED,
-        INFO,
-        PROBLEM,
-        INFO_QUERY,
-        SECRET_INFO_QUERY,
         SESSION_OPENED,
-        SESSION_OPEN_FAILED,
         SESSION_STARTED,
         SESSION_START_FAILED,
         SESSION_EXITED,
         SESSION_DIED,
-        SELECTED_USER_CHANGED,
-        DEFAULT_LANGUAGE_NAME_CHANGED,
-        DEFAULT_SESSION_NAME_CHANGED,
         LAST_SIGNAL
 };
 
@@ -234,133 +230,152 @@ on_session_exited (GdmSession *self,
                                    self->priv->display_device);
 }
 
+static void
+report_problem_and_stop_conversation (GdmSession *self,
+                                      const char *service_name,
+                                      const char *message)
+{
+        gdm_dbus_user_verifier_emit_problem (self->priv->user_verifier_interface,
+                                             service_name,
+                                             message);
+
+        gdm_session_stop_conversation (self, service_name);
+}
+
 static gboolean
-gdm_session_handle_service_unavailable (GdmDBusSession        *skeleton,
+gdm_session_handle_service_unavailable (GdmDBusWorkerManager  *worker_manager_interface,
                                         GDBusMethodInvocation *invocation,
                                         const char            *service_name,
                                         const char            *message,
                                         GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_service_unavailable (worker_manager_interface,
+                                                              invocation);
 
-        g_debug ("GdmSession: Emitting 'service-unavailable' signal");
-        g_signal_emit (self, signals[SERVICE_UNAVAILABLE], 0, service_name);
+        gdm_dbus_user_verifier_emit_service_unavailable (self->priv->user_verifier_interface,
+                                                         service_name,
+                                                         message);
+
+        gdm_session_stop_conversation (self, service_name);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_setup_complete (GdmDBusSession        *skeleton,
+gdm_session_handle_setup_complete (GdmDBusWorkerManager  *worker_manager_interface,
                                    GDBusMethodInvocation *invocation,
                                    const char            *service_name,
                                    GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_setup_complete (worker_manager_interface,
+                                                         invocation);
+
+        g_signal_emit (G_OBJECT (self),
+                       signals [SETUP_COMPLETE],
+                       0,
+                       service_name);
 
-        g_debug ("GdmSession: Emitting 'setup-complete' signal");
-        g_signal_emit (self, signals[SETUP_COMPLETE], 0, service_name);
+        gdm_session_authenticate (self, service_name);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_setup_failed (GdmDBusSession        *skeleton,
+gdm_session_handle_setup_failed (GdmDBusWorkerManager  *worker_manager_interface,
                                  GDBusMethodInvocation *invocation,
                                  const char            *service_name,
                                  const char            *message,
                                  GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_setup_failed (worker_manager_interface,
+                                                       invocation);
 
-        g_debug ("GdmSession: Emitting 'setup-failed' signal");
-        g_signal_emit (self, signals[SETUP_FAILED], 0, service_name, message);
+        report_problem_and_stop_conversation (self, service_name, message);
 
         return TRUE;
 }
 
-
 static gboolean
-gdm_session_handle_authenticated (GdmDBusSession        *skeleton,
+gdm_session_handle_authenticated (GdmDBusWorkerManager  *worker_manager_interface,
                                   GDBusMethodInvocation *invocation,
                                   const char            *service_name,
                                   GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
-
-        g_debug ("GdmSession: Emitting 'authenticated' signal");
-        g_signal_emit (self, signals[AUTHENTICATED], 0, service_name);
+        gdm_dbus_worker_manager_complete_authenticated (worker_manager_interface,
+                                                        invocation);
+        gdm_session_authorize (self, service_name);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_authentication_failed (GdmDBusSession        *skeleton,
+gdm_session_handle_authentication_failed (GdmDBusWorkerManager  *worker_manager_interface,
                                           GDBusMethodInvocation *invocation,
                                           const char            *service_name,
                                           const char            *message,
                                           GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
-
-        g_debug ("GdmSession: Emitting 'authentication-failed' signal");
-        g_signal_emit (self, signals[AUTHENTICATION_FAILED], 0, service_name, message);
+        gdm_dbus_worker_manager_complete_authentication_failed (worker_manager_interface,
+                                                                invocation);
+        report_problem_and_stop_conversation (self, service_name, message);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_authorized (GdmDBusSession        *skeleton,
+gdm_session_handle_authorized (GdmDBusWorkerManager  *worker_manager_interface,
                                GDBusMethodInvocation *invocation,
                                const char            *service_name,
                                GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
-
-        g_debug ("GdmSession: Emitting 'authorized' signal");
-        g_signal_emit (self, signals[AUTHORIZED], 0, service_name);
+        gdm_dbus_worker_manager_complete_authorized (worker_manager_interface,
+                                                     invocation);
+        gdm_session_accredit (self, service_name);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_authorization_failed (GdmDBusSession        *skeleton,
+gdm_session_handle_authorization_failed (GdmDBusWorkerManager  *worker_manager_interface,
                                          GDBusMethodInvocation *invocation,
                                          const char            *service_name,
                                          const char            *message,
                                          GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_authorization_failed (worker_manager_interface,
+                                                               invocation);
 
-        g_debug ("GdmSession: Emitting 'authorization-failed' signal");
-        g_signal_emit (self, signals[AUTHORIZATION_FAILED], 0, service_name, message);
+        report_problem_and_stop_conversation (self, service_name, message);
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_accredited (GdmDBusSession        *skeleton,
+gdm_session_handle_accredited (GdmDBusWorkerManager  *worker_manager_interface,
                                GDBusMethodInvocation *invocation,
                                const char            *service_name,
                                GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_accredited (worker_manager_interface,
+                                                     invocation);
 
-        g_debug ("GdmSession: Emitting 'accredited' signal");
-        g_signal_emit (self, signals[ACCREDITED], 0, service_name);
+        gdm_session_open_session (self, service_name);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_accreditation_failed (GdmDBusSession        *skeleton,
+gdm_session_handle_accreditation_failed (GdmDBusWorkerManager  *worker_manager_interface,
                                          GDBusMethodInvocation *invocation,
                                          const char            *service_name,
                                          const char            *message,
                                          GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_accreditation_failed (worker_manager_interface,
+                                                               invocation);
 
-        g_debug ("GdmSession: Emitting 'accreditation-failed' signal");
-        g_signal_emit (self, signals[ACCREDITATION_FAILED], 0, service_name, message);
+#warning emit TRY_TO_MIGRATE or something like that.  The idea is, we don't care if accreditation fails if the user is already logged in.  though maybe we should rethink how user switching is done so that its done in the same way unlock will be done, then we won't even try to accredit in the first place.
+
+        report_problem_and_stop_conversation (self, service_name, message);
         return TRUE;
 }
 
@@ -609,15 +624,11 @@ get_default_session_name (GdmSession *self)
 static void
 gdm_session_defaults_changed (GdmSession *self)
 {
-        g_signal_emit (self,
-                       signals[DEFAULT_LANGUAGE_NAME_CHANGED],
-                       0,
-                       get_default_language_name (self));
 
-        g_signal_emit (self,
-                       signals[DEFAULT_SESSION_NAME_CHANGED],
-                       0,
-                       get_default_session_name (self));
+        gdm_dbus_greeter_session_emit_default_language_name_changed (self->priv->greeter_session_interface,
+                                                                     get_default_language_name (self));
+        gdm_dbus_greeter_session_emit_default_session_name_changed (self->priv->greeter_session_interface,
+                                                                    get_default_session_name (self));
 }
 
 void
@@ -638,21 +649,20 @@ gdm_session_select_user (GdmSession *self,
 }
 
 static gboolean
-gdm_session_handle_username_changed (GdmDBusSession        *skeleton,
+gdm_session_handle_username_changed (GdmDBusWorkerManager  *worker_manager_interface,
                                      GDBusMethodInvocation *invocation,
                                      const char            *service_name,
-                                     const char            *text,
+                                     const char            *username,
                                      GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_username_changed (worker_manager_interface,
+                                                           invocation);
 
         g_debug ("GdmSession: changing username from '%s' to '%s'",
                  self->priv->selected_user != NULL ? self->priv->selected_user : "<unset>",
-                 (strlen (text)) ? text : "<unset>");
-
-        gdm_session_select_user (self, (strlen (text) > 0) ? g_strdup (text) : NULL);
-        g_signal_emit (self, signals[SELECTED_USER_CHANGED], 0, self->priv->selected_user);
+                 (strlen (username)) ? username : "<unset>");
 
+        gdm_session_select_user (self, (strlen (username) > 0) ? g_strdup (username) : NULL);
         gdm_session_defaults_changed (self);
 
         return TRUE;
@@ -692,10 +702,10 @@ set_pending_query (GdmSessionConversation *conversation,
 }
 
 static gboolean
-gdm_session_handle_info_query (GdmDBusSession        *skeleton,
+gdm_session_handle_info_query (GdmDBusWorkerManager  *worker_manager_interface,
                                GDBusMethodInvocation *invocation,
                                const char            *service_name,
-                               const char            *text,
+                               const char            *query,
                                GdmSession            *self)
 {
         GdmSessionConversation *conversation;
@@ -703,17 +713,18 @@ gdm_session_handle_info_query (GdmDBusSession        *skeleton,
         conversation = find_conversation_by_name (self, service_name);
         set_pending_query (conversation, invocation);
 
-        g_debug ("GdmSession: Emitting 'info-query' signal");
-        g_signal_emit (self, signals[INFO_QUERY], 0, service_name, text);
+        gdm_dbus_user_verifier_emit_info_query (self->priv->user_verifier_interface,
+                                                service_name,
+                                                query);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_secret_info_query (GdmDBusSession        *skeleton,
+gdm_session_handle_secret_info_query (GdmDBusWorkerManager  *worker_manager_interface,
                                       GDBusMethodInvocation *invocation,
                                       const char            *service_name,
-                                      const char            *text,
+                                      const char            *query,
                                       GdmSession            *self)
 {
         GdmSessionConversation *conversation;
@@ -721,29 +732,32 @@ gdm_session_handle_secret_info_query (GdmDBusSession        *skeleton,
         conversation = find_conversation_by_name (self, service_name);
         set_pending_query (conversation, invocation);
 
-        g_debug ("GdmSession: Emitting 'secret-info-query' signal");
-        g_signal_emit (self, signals[SECRET_INFO_QUERY], 0, service_name, text);
+        gdm_dbus_user_verifier_emit_secret_info_query (self->priv->user_verifier_interface,
+                                                       service_name,
+                                                       query);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_info (GdmDBusSession        *skeleton,
+gdm_session_handle_info (GdmDBusWorkerManager  *worker_manager_interface,
                          GDBusMethodInvocation *invocation,
                          const char            *service_name,
-                         const char            *text,
+                         const char            *info,
                          GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_info (worker_manager_interface,
+                                               invocation);
 
-        g_debug ("GdmSession: Emitting 'info' signal");
-        g_signal_emit (self, signals[INFO], 0, service_name, text);
+        gdm_dbus_user_verifier_emit_info (self->priv->user_verifier_interface,
+                                          service_name,
+                                          info);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_cancel_pending_query (GdmDBusSession        *skeleton,
+gdm_session_handle_cancel_pending_query (GdmDBusWorkerManager  *worker_manager_interface,
                                          GDBusMethodInvocation *invocation,
                                          const char            *service_name,
                                          GdmSession            *self)
@@ -753,79 +767,88 @@ gdm_session_handle_cancel_pending_query (GdmDBusSession        *skeleton,
         conversation = find_conversation_by_name (self, service_name);
         cancel_pending_query (conversation);
 
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_cancel_pending_query (worker_manager_interface,
+                                                               invocation);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_problem (GdmDBusSession        *skeleton,
+gdm_session_handle_problem (GdmDBusWorkerManager  *worker_manager_interface,
                             GDBusMethodInvocation *invocation,
                             const char            *service_name,
-                            const char            *text,
+                            const char            *problem,
                             GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
-
-        g_debug ("GdmSession: Emitting 'problem' signal");
-        g_signal_emit (self, signals[PROBLEM], 0, service_name, text);
+        gdm_dbus_worker_manager_complete_problem (worker_manager_interface,
+                                                  invocation);
 
+        gdm_dbus_user_verifier_emit_problem (self->priv->user_verifier_interface,
+                                             service_name,
+                                             problem);
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_opened (GdmDBusSession        *skeleton,
+gdm_session_handle_opened (GdmDBusWorkerManager  *worker_manager_interface,
                            GDBusMethodInvocation *invocation,
                            const char            *service_name,
+                           const char            *session_id,
                            GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        GdmSessionConversation *conversation;
+
+        conversation = find_conversation_by_name (self, service_name);
+
+        g_clear_pointer (&conversation->session_id,
+                         (GDestroyNotify) g_free);
+
+        conversation->session_id = g_strdup (session_id);
+
+        gdm_dbus_worker_manager_complete_opened (worker_manager_interface,
+                                                 invocation);
+
+        gdm_dbus_greeter_session_emit_session_opened (self->priv->greeter_session_interface,
+                                                      service_name);
 
         g_debug ("GdmSession: Emitting 'session-opened' signal");
-        g_signal_emit (self, signals[SESSION_OPENED], 0, service_name);
+        g_signal_emit (self, signals[SESSION_OPENED], 0, service_name, session_id);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_open_failed (GdmDBusSession        *skeleton,
+gdm_session_handle_open_failed (GdmDBusWorkerManager  *worker_manager_interface,
                                 GDBusMethodInvocation *invocation,
                                 const char            *service_name,
                                 const char            *message,
                                 GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_open_failed (worker_manager_interface,
+                                                      invocation);
 
-        g_debug ("GdmSession: Emitting 'session-open-failed' signal");
-        g_signal_emit (self, signals[SESSION_OPEN_FAILED], 0, service_name, message);
+        report_problem_and_stop_conversation (self, service_name, message);
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_session_started (GdmDBusSession        *skeleton,
+gdm_session_handle_session_started (GdmDBusWorkerManager  *worker_manager_interface,
                                     GDBusMethodInvocation *invocation,
                                     const char            *service_name,
-                                    const char            *session_id,
                                     int                    pid,
                                     GdmSession            *self)
 {
         GdmSessionConversation *conversation;
 
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_session_started (worker_manager_interface,
+                                                          invocation);
 
         conversation = find_conversation_by_name (self, service_name);
 
         self->priv->session_pid = pid;
         self->priv->session_conversation = conversation;
 
-        g_clear_pointer (&conversation->session_id,
-                         (GDestroyNotify) g_free);
-
-        if (session_id != NULL && session_id[0] != '\0') {
-                conversation->session_id = g_strdup (session_id);
-        }
-
         g_debug ("GdmSession: Emitting 'session-started' signal with pid '%d'", pid);
         g_signal_emit (self, signals[SESSION_STARTED], 0, service_name, pid);
 
@@ -833,13 +856,15 @@ gdm_session_handle_session_started (GdmDBusSession        *skeleton,
 }
 
 static gboolean
-gdm_session_handle_session_start_failed (GdmDBusSession        *skeleton,
+gdm_session_handle_session_start_failed (GdmDBusWorkerManager  *worker_manager_interface,
                                          GDBusMethodInvocation *invocation,
                                          const char            *service_name,
                                          const char            *message,
                                          GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_session_start_failed (worker_manager_interface,
+                                                               invocation);
+        gdm_session_stop_conversation (self, service_name);
 
         g_debug ("GdmSession: Emitting 'session-start-failed' signal");
         g_signal_emit (self, signals[SESSION_START_FAILED], 0, service_name, message);
@@ -848,13 +873,14 @@ gdm_session_handle_session_start_failed (GdmDBusSession        *skeleton,
 }
 
 static gboolean
-gdm_session_handle_session_exited_or_died (GdmDBusSession        *skeleton,
+gdm_session_handle_session_exited_or_died (GdmDBusWorkerManager  *worker_manager_interface,
                                            GDBusMethodInvocation *invocation,
                                            const char            *service_name,
                                            int                    status,
                                            GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_session_exited (worker_manager_interface,
+                                                         invocation);
 
         self->priv->session_conversation = NULL;
 
@@ -872,31 +898,34 @@ gdm_session_handle_session_exited_or_died (GdmDBusSession        *skeleton,
 }
 
 static gboolean
-gdm_session_handle_saved_language_name_read (GdmDBusSession        *skeleton,
+gdm_session_handle_saved_language_name_read (GdmDBusWorkerManager  *worker_manager_interface,
                                              GDBusMethodInvocation *invocation,
                                              const char            *language_name,
                                              GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_saved_language_name_read (worker_manager_interface,
+                                                                   invocation);
 
         if (strcmp (language_name,
                     get_default_language_name (self)) != 0) {
                 g_free (self->priv->saved_language);
                 self->priv->saved_language = g_strdup (language_name);
 
-                g_signal_emit (self, signals[DEFAULT_LANGUAGE_NAME_CHANGED], 0, language_name);
+                gdm_dbus_greeter_session_emit_default_language_name_changed (self->priv->greeter_session_interface,
+                                                                             language_name);
         }
 
         return TRUE;
 }
 
 static gboolean
-gdm_session_handle_saved_session_name_read (GdmDBusSession        *skeleton,
+gdm_session_handle_saved_session_name_read (GdmDBusWorkerManager  *worker_manager_interface,
                                             GDBusMethodInvocation *invocation,
                                             const char            *session_name,
                                             GdmSession            *self)
 {
-        g_dbus_method_invocation_return_value (invocation, NULL);
+        gdm_dbus_worker_manager_complete_saved_session_name_read (worker_manager_interface,
+                                                                   invocation);
 
         if (! get_session_command_for_name (session_name, NULL)) {
                 /* ignore sessions that don't exist */
@@ -911,7 +940,8 @@ gdm_session_handle_saved_session_name_read (GdmDBusSession        *skeleton,
                 g_free (self->priv->saved_session);
                 self->priv->saved_session = g_strdup (session_name);
 
-                g_signal_emit (self, signals[DEFAULT_SESSION_NAME_CHANGED], 0, session_name);
+                gdm_dbus_greeter_session_emit_default_session_name_changed (self->priv->greeter_session_interface,
+                                                                            session_name);
         }
  out:
         return TRUE;
@@ -939,12 +969,13 @@ find_conversation_by_pid (GdmSession *self,
 }
 
 static gboolean
-allow_user_function (GDBusAuthObserver *observer,
-                     GIOStream         *stream,
-                     GCredentials      *credentials)
+allow_worker_function (GDBusAuthObserver *observer,
+                       GIOStream         *stream,
+                       GCredentials      *credentials)
 {
-        if (g_credentials_get_unix_user (credentials, NULL) == 0)
+        if (g_credentials_get_unix_user (credentials, NULL) == 0) {
                 return TRUE;
+        }
 
         g_debug ("GdmSession: User not allowed");
 
@@ -974,7 +1005,7 @@ credentials_get_unix_pid (GCredentials *credentials)
 }
 
 static gboolean
-register_worker (GdmDBusSession        *skeleton,
+register_worker (GdmDBusWorkerManager  *worker_manager_interface,
                  GDBusMethodInvocation *invocation,
                  GdmSession            *self)
 {
@@ -987,15 +1018,18 @@ register_worker (GdmDBusSession        *skeleton,
         g_debug ("GdmSession: Authenticating new connection");
 
         connection = g_dbus_method_invocation_get_connection (invocation);
-        connection_node = g_list_find (self->priv->pending_connections, connection);
+        connection_node = g_list_find (self->priv->pending_worker_connections, connection);
 
         if (connection_node == NULL) {
                 g_debug ("GdmSession: Ignoring connection that we aren't tracking");
                 return FALSE;
         }
 
-        self->priv->pending_connections =
-                g_list_delete_link (self->priv->pending_connections,
+        /* connection was ref'd when it was added to list, we're taking that
+         * reference over and removing it from the list
+         */
+        self->priv->pending_worker_connections =
+                g_list_delete_link (self->priv->pending_worker_connections,
                                     connection_node);
 
         credentials = g_dbus_connection_get_peer_credentials (connection);
@@ -1015,8 +1049,8 @@ register_worker (GdmDBusSession        *skeleton,
 
         g_dbus_method_invocation_return_value (invocation, NULL);
 
-        conversation->worker_connection = g_object_ref (connection);
-        conversation->worker_skeleton = g_object_ref (skeleton);
+        conversation->worker_connection = connection;
+        conversation->worker_manager_interface = g_object_ref (worker_manager_interface);
         g_debug ("GdmSession: worker connection is %p", connection);
 
         g_debug ("GdmSession: Emitting conversation-started signal");
@@ -1027,133 +1061,556 @@ register_worker (GdmDBusSession        *skeleton,
         return TRUE;
 }
 
-static gboolean
-handle_connection (GDBusServer      *server,
-                   GDBusConnection  *connection,
-                   GdmSession       *self)
+static void
+export_worker_manager_interface (GdmSession      *self,
+                                 GDBusConnection *connection)
 {
-        GdmDBusSession *skeleton;
-
-        g_debug ("GdmSession: Handing new connection");
-
-        /* add to the list of pending connections.  We won't be able to
-         * associate it with a specific worker conversation until we have
-         * authenticated the connection (from the Hello handler).
-         */
-        self->priv->pending_connections =
-                g_list_prepend (self->priv->pending_connections,
-                                g_object_ref (connection));
+        GdmDBusWorkerManager *worker_manager_interface;
 
-        skeleton = GDM_DBUS_SESSION (gdm_dbus_session_skeleton_new ());
-        g_signal_connect (skeleton,
+        worker_manager_interface = GDM_DBUS_WORKER_MANAGER (gdm_dbus_worker_manager_skeleton_new ());
+        g_signal_connect (worker_manager_interface,
                           "handle-hello",
                           G_CALLBACK (register_worker),
                           self);
-        g_signal_connect (skeleton,
-                          "handle-info-query",
-                          G_CALLBACK (gdm_session_handle_info_query),
-                          self);
-        g_signal_connect (skeleton,
-                          "handle-secret-info-query",
-                          G_CALLBACK (gdm_session_handle_secret_info_query),
+        g_signal_connect (worker_manager_interface,
+                          "handle-cancel-pending-query",
+                          G_CALLBACK (gdm_session_handle_cancel_pending_query),
                           self);
-        g_signal_connect (skeleton,
-                          "handle-info",
-                          G_CALLBACK (gdm_session_handle_info),
+        g_signal_connect (worker_manager_interface,
+                          "handle-username-changed",
+                          G_CALLBACK (gdm_session_handle_username_changed),
                           self);
-        g_signal_connect (skeleton,
-                          "handle-problem",
-                          G_CALLBACK (gdm_session_handle_problem),
+        g_signal_connect (worker_manager_interface,
+                          "handle-saved-language-name-read",
+                          G_CALLBACK (gdm_session_handle_saved_language_name_read),
                           self);
-        g_signal_connect (skeleton,
-                          "handle-cancel-pending-query",
-                          G_CALLBACK (gdm_session_handle_cancel_pending_query),
+        g_signal_connect (worker_manager_interface,
+                          "handle-saved-session-name-read",
+                          G_CALLBACK (gdm_session_handle_saved_session_name_read),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-service-unavailable",
                           G_CALLBACK (gdm_session_handle_service_unavailable),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-setup-complete",
                           G_CALLBACK (gdm_session_handle_setup_complete),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-setup-failed",
                           G_CALLBACK (gdm_session_handle_setup_failed),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-authenticated",
                           G_CALLBACK (gdm_session_handle_authenticated),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-authentication-failed",
                           G_CALLBACK (gdm_session_handle_authentication_failed),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-authorized",
                           G_CALLBACK (gdm_session_handle_authorized),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-authorization-failed",
                           G_CALLBACK (gdm_session_handle_authorization_failed),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-accredited",
                           G_CALLBACK (gdm_session_handle_accredited),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-accreditation-failed",
                           G_CALLBACK (gdm_session_handle_accreditation_failed),
                           self);
-        g_signal_connect (skeleton,
-                          "handle-username-changed",
-                          G_CALLBACK (gdm_session_handle_username_changed),
+        g_signal_connect (worker_manager_interface,
+                          "handle-info-query",
+                          G_CALLBACK (gdm_session_handle_info_query),
+                          self);
+        g_signal_connect (worker_manager_interface,
+                          "handle-secret-info-query",
+                          G_CALLBACK (gdm_session_handle_secret_info_query),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
+                          "handle-info",
+                          G_CALLBACK (gdm_session_handle_info),
+                          self);
+        g_signal_connect (worker_manager_interface,
+                          "handle-problem",
+                          G_CALLBACK (gdm_session_handle_problem),
+                          self);
+        g_signal_connect (worker_manager_interface,
                           "handle-opened",
                           G_CALLBACK (gdm_session_handle_opened),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-open-failed",
                           G_CALLBACK (gdm_session_handle_open_failed),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-session-started",
                           G_CALLBACK (gdm_session_handle_session_started),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-session-start-failed",
                           G_CALLBACK (gdm_session_handle_session_start_failed),
                           self);
-        g_signal_connect (skeleton,
+        g_signal_connect (worker_manager_interface,
                           "handle-session-exited",
                           G_CALLBACK (gdm_session_handle_session_exited_or_died),
                           self);
-        g_signal_connect (skeleton,
-                          "handle-saved-language-name-read",
-                          G_CALLBACK (gdm_session_handle_saved_language_name_read),
+
+        g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (worker_manager_interface),
+                                          connection,
+                                          GDM_SESSION_DBUS_OBJECT_PATH,
+                                          NULL);
+}
+
+static void
+on_worker_connection_closed (GDBusConnection *connection,
+                             gboolean         remote_peer_vanished,
+                             GError          *error,
+                             GdmSession      *self)
+{
+        self->priv->pending_worker_connections =
+            g_list_remove (self->priv->pending_worker_connections,
+                           connection);
+        g_object_unref (connection);
+}
+
+static gboolean
+handle_connection_from_worker (GDBusServer      *server,
+                               GDBusConnection  *connection,
+                               GdmSession       *self)
+{
+
+        g_debug ("GdmSession: Handling new connection from worker");
+
+        /* add to the list of pending connections.  We won't be able to
+         * associate it with a specific worker conversation until we have
+         * authenticated the connection (from the Hello handler).
+         */
+        self->priv->pending_worker_connections =
+                g_list_prepend (self->priv->pending_worker_connections,
+                                g_object_ref (connection));
+
+        g_signal_connect (connection,
+                          "closed",
+                          G_CALLBACK (on_worker_connection_closed),
                           self);
-        g_signal_connect (skeleton,
-                          "handle-saved-session-name-read",
-                          G_CALLBACK (gdm_session_handle_saved_session_name_read),
+
+        export_worker_manager_interface (self, connection);
+
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_start_conversation (GdmDBusUserVerifier    *user_verifier_interface,
+                                              GDBusMethodInvocation  *invocation,
+                                              const char             *service_name,
+                                              GdmSession             *self)
+{
+        gdm_dbus_user_verifier_complete_start_conversation (user_verifier_interface,
+                                                            invocation);
+        gdm_session_start_conversation (self, service_name);
+
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_stop_conversation (GdmDBusUserVerifier    *user_verifier_interface,
+                                             GDBusMethodInvocation  *invocation,
+                                             const char             *service_name,
+                                             GdmSession             *self)
+{
+        gdm_dbus_user_verifier_complete_stop_conversation (user_verifier_interface,
+                                                           invocation);
+        gdm_session_stop_conversation (self, service_name);
+
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_begin_verification (GdmDBusUserVerifier    *user_verifier_interface,
+                                              GDBusMethodInvocation  *invocation,
+                                              const char             *service_name,
+                                              GdmSession             *self)
+{
+        gdm_dbus_user_verifier_complete_begin_verification (user_verifier_interface,
+                                                            invocation);
+        gdm_session_setup (self, service_name);
+
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_begin_verification_for_user (GdmDBusUserVerifier    *user_verifier_interface,
+                                                       GDBusMethodInvocation  *invocation,
+                                                       const char             *service_name,
+                                                       const char             *username,
+                                                       GdmSession             *self)
+{
+        gdm_dbus_user_verifier_complete_begin_verification_for_user (user_verifier_interface,
+                                                                     invocation);
+        gdm_session_setup_for_user (self, service_name, username);
+
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_answer_query (GdmDBusUserVerifier    *user_verifier_interface,
+                                        GDBusMethodInvocation  *invocation,
+                                        const char             *service_name,
+                                        const char             *answer,
+                                        GdmSession             *self)
+{
+        gdm_dbus_user_verifier_complete_answer_query (user_verifier_interface,
+                                                      invocation);
+        gdm_session_answer_query (self, service_name, answer);
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_cancel (GdmDBusUserVerifier    *user_verifier_interface,
+                                  GDBusMethodInvocation  *invocation,
+                                  GdmSession             *self)
+{
+        gdm_dbus_user_verifier_complete_cancel (user_verifier_interface,
+                                                invocation);
+        gdm_session_cancel (self);
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_select_session (GdmDBusGreeterSession  *greeter_session_interface,
+                                          GDBusMethodInvocation  *invocation,
+                                          const char             *session,
+                                          GdmSession             *self)
+{
+        gdm_dbus_greeter_session_complete_select_session (greeter_session_interface,
+                                                          invocation);
+        gdm_session_select_session (self, session);
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_select_language (GdmDBusGreeterSession  *greeter_session_interface,
+                                           GDBusMethodInvocation  *invocation,
+                                           const char             *language,
+                                           GdmSession             *self)
+{
+        gdm_dbus_greeter_session_complete_select_language (greeter_session_interface,
+                                                           invocation);
+        gdm_session_select_language (self, language);
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_select_user (GdmDBusGreeterSession *greeter_session_interface,
+                                       GDBusMethodInvocation *invocation,
+                                       const char            *username,
+                                       GdmSession            *self)
+{
+        gdm_dbus_greeter_session_complete_select_user (greeter_session_interface,
+                                                       invocation);
+        gdm_session_select_user (self, username);
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_start_session_when_ready (GdmDBusGreeterSession *greeter_session_interface,
+                                                    GDBusMethodInvocation *invocation,
+                                                    const char            *service_name,
+                                                    gboolean               client_is_ready,
+                                                    GdmSession            *self)
+{
+
+        gdm_dbus_greeter_session_complete_start_session_when_ready (greeter_session_interface,
+                                                                    invocation);
+        g_signal_emit (G_OBJECT (self),
+                       signals [CLIENT_READY_FOR_SESSION_TO_START],
+                       0,
+                       service_name,
+                       client_is_ready);
+        return TRUE;
+}
+
+static gboolean
+gdm_session_handle_client_begin_auto_login (GdmDBusGreeterSession *greeter_session_interface,
+                                            GDBusMethodInvocation *invocation,
+                                            const char            *username,
+                                            GdmSession            *self)
+{
+        gdm_dbus_greeter_session_complete_begin_auto_login (greeter_session_interface,
+                                                            invocation);
+
+        g_debug ("GdmSession: begin auto login for user '%s'", username);
+
+        gdm_session_setup_for_user (self, "gdm-autologin", username);
+
+        return TRUE;
+}
+
+static void
+export_user_verifier_interface (GdmSession      *self,
+                                GDBusConnection *connection)
+{
+        GdmDBusUserVerifier   *user_verifier_interface;
+        user_verifier_interface = GDM_DBUS_USER_VERIFIER (gdm_dbus_user_verifier_skeleton_new ());
+        g_signal_connect (user_verifier_interface,
+                          "handle-start-converstion",
+                          G_CALLBACK (gdm_session_handle_client_start_conversation),
+                          self);
+        g_signal_connect (user_verifier_interface,
+                          "handle-stop-conversation",
+                          G_CALLBACK (gdm_session_handle_client_stop_conversation),
+                          self);
+        g_signal_connect (user_verifier_interface,
+                          "handle-begin-verification",
+                          G_CALLBACK (gdm_session_handle_client_begin_verification),
+                          self);
+        g_signal_connect (user_verifier_interface,
+                          "handle-begin-verification-for-user",
+                          G_CALLBACK (gdm_session_handle_client_begin_verification_for_user),
+                          self);
+        g_signal_connect (user_verifier_interface,
+                          "handle-answer-query",
+                          G_CALLBACK (gdm_session_handle_client_answer_query),
+                          self);
+        g_signal_connect (user_verifier_interface,
+                          "handle-cancel",
+                          G_CALLBACK (gdm_session_handle_client_cancel),
+                          self);
+
+        g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (user_verifier_interface),
+                                          connection,
+                                          GDM_SESSION_DBUS_OBJECT_PATH,
+                                          NULL);
+
+}
+
+static void
+export_greeter_session_interface (GdmSession      *self,
+                                  GDBusConnection *connection)
+{
+        GdmDBusGreeterSession *greeter_session_interface;
+
+        greeter_session_interface = GDM_DBUS_GREETER_SESSION (gdm_dbus_greeter_session_skeleton_new ());
+
+        g_signal_connect (greeter_session_interface,
+                          "handle-begin-auto-login",
+                          G_CALLBACK (gdm_session_handle_client_begin_auto_login),
+                          self);
+        g_signal_connect (greeter_session_interface,
+                          "handle-select-session",
+                          G_CALLBACK (gdm_session_handle_client_select_session),
+                          self);
+        g_signal_connect (greeter_session_interface,
+                          "handle-select-language",
+                          G_CALLBACK (gdm_session_handle_client_select_language),
+                          self);
+        g_signal_connect (greeter_session_interface,
+                          "handle-select-user",
+                          G_CALLBACK (gdm_session_handle_client_select_user),
+                          self);
+        g_signal_connect (greeter_session_interface,
+                          "handle-start-session-when-ready",
+                          G_CALLBACK (gdm_session_handle_client_start_session_when_ready),
                           self);
 
-        g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
+        g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (greeter_session_interface),
                                           connection,
-                                          "/org/gnome/DisplayManager/Session",
+                                          GDM_SESSION_DBUS_OBJECT_PATH,
                                           NULL);
 
+}
+
+static gboolean
+gdm_session_handle_client_select_hostname (GdmDBusChooserSession *chooser_session_interface,
+                                           GDBusMethodInvocation *invocation,
+                                           const char            *hostname,
+                                           GdmSession            *self)
+{
+
+        gdm_dbus_chooser_session_complete_select_hostname (chooser_session_interface,
+                                                           invocation);
+        g_signal_emit (self, signals[HOSTNAME_SELECTED], 0, hostname);
         return TRUE;
 }
 
+static gboolean
+gdm_session_handle_client_disconnect (GdmDBusChooserSession *chooser_session_interface,
+                                      GDBusMethodInvocation *invocation,
+                                      GdmSession            *self)
+{
+        gdm_dbus_chooser_session_complete_disconnect (chooser_session_interface,
+                                                      invocation);
+        g_signal_emit (self, signals[DISCONNECTED], 0);
+        return TRUE;
+}
+
+static void
+export_chooser_session_interface (GdmSession      *self,
+                                  GDBusConnection *connection)
+{
+        GdmDBusChooserSession *chooser_session_interface;
+
+        chooser_session_interface = GDM_DBUS_CHOOSER_SESSION (gdm_dbus_chooser_session_skeleton_new ());
+
+        g_signal_connect (chooser_session_interface,
+                          "handle-select-hostname",
+                          G_CALLBACK (gdm_session_handle_client_select_hostname),
+                          self);
+        g_signal_connect (chooser_session_interface,
+                          "handle-disconnect",
+                          G_CALLBACK (gdm_session_handle_client_disconnect),
+                          self);
+
+        g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (chooser_session_interface),
+                                          connection,
+                                          GDM_SESSION_DBUS_OBJECT_PATH,
+                                          NULL);
+}
+
 static void
-setup_server (GdmSession *self)
+on_outside_connection_closed (GDBusConnection *connection,
+                              gboolean         remote_peer_vanished,
+                              GError          *error,
+                              GdmSession      *self)
+{
+        self->priv->outside_connections =
+            g_list_remove (self->priv->outside_connections,
+                            connection);
+        g_object_unref (connection);
+
+        g_signal_emit (G_OBJECT (self),
+                       signals [CLIENT_DISCONNECTED],
+                       0);
+}
+
+static gboolean
+handle_connection_from_outside (GDBusServer      *server,
+                                GDBusConnection  *connection,
+                                GdmSession       *self)
+{
+        g_debug ("GdmSession: Handling new connection from outside");
+
+        self->priv->outside_connections =
+            g_list_prepend (self->priv->outside_connections,
+                            g_object_ref (connection));
+
+        g_signal_connect (connection,
+                          "closed",
+                          G_CALLBACK (on_outside_connection_closed),
+                          self);
+
+        export_user_verifier_interface (self, connection);
+        export_greeter_session_interface (self, connection);
+        export_chooser_session_interface (self, connection);
+
+        g_signal_emit (G_OBJECT (self),
+                       signals [CLIENT_CONNECTED],
+                       0);
+
+        return TRUE;
+}
+
+static void
+setup_worker_server (GdmSession *self)
 {
         GDBusAuthObserver *observer;
         GDBusServer *server;
         GError *error = NULL;
 
-        g_debug ("GdmSession: Creating D-Bus server for session");
+        g_debug ("GdmSession: Creating D-Bus server for worker for session");
+
+        observer = g_dbus_auth_observer_new ();
+        g_signal_connect (observer,
+                          "authorize-authenticated-peer",
+                          G_CALLBACK (allow_worker_function),
+                          NULL);
+
+        server = gdm_dbus_setup_private_server (observer, &error);
+        g_object_unref (observer);
+
+        if (server == NULL) {
+                g_warning ("Cannot create worker D-Bus server for the session: %s",
+                           error->message);
+                return;
+        }
+
+        g_signal_connect (server,
+                          "new-connection",
+                          G_CALLBACK (handle_connection_from_worker),
+                          self);
+        self->priv->worker_server = server;
+
+        g_dbus_server_start (server);
+
+        g_debug ("GdmSession: D-Bus server for workers listening on %s",
+        g_dbus_server_get_client_address (self->priv->worker_server));
+}
+
+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;
+}
+
+static gboolean
+allow_user_function (GDBusAuthObserver *observer,
+                     GIOStream         *stream,
+                     GCredentials      *credentials)
+{
+        uid_t uid;
+        gid_t gid;
+        uid_t client_uid;
+
+        if (!_get_uid_and_gid_for_user (GDM_USERNAME, &uid, &gid)) {
+                g_debug ("GdmSession: Unable to determine uid for gdm user");
+                return FALSE;
+        }
+
+        client_uid = g_credentials_get_unix_user (credentials, NULL);
+        if (uid == client_uid) {
+                return TRUE;
+        }
+
+        g_debug ("GdmSession: User not allowed");
+
+        return FALSE;
+}
+
+static void
+setup_outside_server (GdmSession *self)
+{
+        GDBusAuthObserver *observer;
+        GDBusServer *server;
+        GError *error = NULL;
+
+        g_debug ("GdmSession: Creating D-Bus server for greeters and such");
 
         observer = g_dbus_auth_observer_new ();
         g_signal_connect (observer,
@@ -1165,21 +1622,21 @@ setup_server (GdmSession *self)
         g_object_unref (observer);
 
         if (server == NULL) {
-                g_warning ("Cannot create D-BUS server for the session: %s", error->message);
-                /* FIXME: should probably fail if we can't create the socket */
+                g_warning ("Cannot create greeter D-Bus server for the session: %s",
+                           error->message);
                 return;
         }
 
         g_signal_connect (server,
                           "new-connection",
-                          G_CALLBACK (handle_connection),
+                          G_CALLBACK (handle_connection_from_outside),
                           self);
-        self->priv->server = server;
+        self->priv->outside_server = server;
 
         g_dbus_server_start (server);
 
-        g_debug ("GdmSession: D-Bus server listening on %s",
-        g_dbus_server_get_client_address (self->priv->server));
+        g_debug ("GdmSession: D-Bus server for greeters listening on %s",
+        g_dbus_server_get_client_address (self->priv->outside_server));
 }
 
 static void
@@ -1227,7 +1684,8 @@ gdm_session_init (GdmSession *self)
                                                          (GDestroyNotify) g_free,
                                                          (GDestroyNotify) g_free);
 
-        setup_server (self);
+        setup_worker_server (self);
+        setup_outside_server (self);
 }
 
 static void
@@ -1306,7 +1764,7 @@ start_conversation (GdmSession *self,
         conversation->worker_pid = -1;
         conversation->job = gdm_session_worker_job_new ();
         gdm_session_worker_job_set_server_address (conversation->job,
-                                                   g_dbus_server_get_client_address (self->priv->server));
+                                                   g_dbus_server_get_client_address (self->priv->worker_server));
         g_signal_connect (conversation->job,
                           "started",
                           G_CALLBACK (worker_started),
@@ -1351,7 +1809,7 @@ stop_conversation (GdmSessionConversation *conversation)
 static void
 stop_conversation_now (GdmSessionConversation *conversation)
 {
-        g_clear_object (&conversation->worker_skeleton);
+        g_clear_object (&conversation->worker_manager_interface);
 
         if (conversation->worker_connection != NULL) {
                 g_dbus_connection_close_sync (conversation->worker_connection, NULL, NULL);
@@ -1452,13 +1910,13 @@ send_setup (GdmSession *self,
 
         conversation = find_conversation_by_name (self, service_name);
         if (conversation != NULL) {
-                gdm_dbus_session_emit_setup (conversation->worker_skeleton,
-                                             service_name,
-                                             display_name,
-                                             display_x11_authority_file,
-                                             display_device,
-                                             display_seat_id,
-                                             display_hostname);
+                gdm_dbus_worker_manager_emit_setup (conversation->worker_manager_interface,
+                                                    service_name,
+                                                    display_name,
+                                                    display_x11_authority_file,
+                                                    display_device,
+                                                    display_seat_id,
+                                                    display_hostname);
         }
 }
 
@@ -1512,14 +1970,14 @@ send_setup_for_user (GdmSession *self,
         g_debug ("GdmSession: Beginning setup for user %s", self->priv->selected_user);
 
         if (conversation != NULL) {
-                gdm_dbus_session_emit_setup_for_user (conversation->worker_skeleton,
-                                                      service_name,
-                                                      selected_user,
-                                                      display_name,
-                                                      display_x11_authority_file,
-                                                      display_device,
-                                                      display_seat_id,
-                                                      display_hostname);
+                gdm_dbus_worker_manager_emit_setup_for_user (conversation->worker_manager_interface,
+                                                             service_name,
+                                                             selected_user,
+                                                             display_name,
+                                                             display_x11_authority_file,
+                                                             display_device,
+                                                             display_seat_id,
+                                                             display_hostname);
         }
 }
 
@@ -1567,14 +2025,14 @@ send_setup_for_program (GdmSession *self,
 
         conversation = find_conversation_by_name (self, service_name);
         if (conversation != NULL) {
-                gdm_dbus_session_emit_setup_for_program (conversation->worker_skeleton,
-                                                         service_name,
-                                                         display_name,
-                                                         display_x11_authority_file,
-                                                         display_device,
-                                                         display_seat_id,
-                                                         display_hostname,
-                                                         log_file);
+                gdm_dbus_worker_manager_emit_setup_for_program (conversation->worker_manager_interface,
+                                                                service_name,
+                                                                display_name,
+                                                                display_x11_authority_file,
+                                                                display_device,
+                                                                display_seat_id,
+                                                                display_hostname,
+                                                                log_file);
         }
 }
 
@@ -1589,25 +2047,6 @@ gdm_session_setup (GdmSession *self,
         gdm_session_defaults_changed (self);
 }
 
-typedef struct {
-        GdmSession *instance;
-        char       *service_name;
-} SetupForUserClosure;
-
-static gboolean
-emit_setup_complete (gpointer data)
-{
-        SetupForUserClosure *closure = data;
-
-        g_signal_emit (closure->instance, signals[SETUP_COMPLETE], 0, closure->service_name);
-
-        g_free (closure->service_name);
-        g_object_unref (closure->instance);
-
-        g_slice_free (SetupForUserClosure, data);
-
-        return G_SOURCE_REMOVE;
-}
 
 void
 gdm_session_setup_for_user (GdmSession *self,
@@ -1618,23 +2057,10 @@ gdm_session_setup_for_user (GdmSession *self,
         g_return_if_fail (GDM_IS_SESSION (self));
         g_return_if_fail (username != NULL);
 
-        if (self->priv->session_conversation != NULL &&
-            g_strcmp0 (self->priv->session_conversation->service_name, service_name) == 0) {
-                SetupForUserClosure *closure;
-
-                g_warn_if_fail (g_strcmp0 (self->priv->selected_user, username) == 0);
-
-                closure = g_slice_new (SetupForUserClosure);
-                closure->instance = g_object_ref (self);
-                closure->service_name = g_strdup (service_name);
-
-                g_idle_add (emit_setup_complete, closure);
-        } else {
-                gdm_session_select_user (self, username);
+        gdm_session_select_user (self, username);
 
-                send_setup_for_user (self, service_name);
-                gdm_session_defaults_changed (self);
-        }
+        send_setup_for_user (self, service_name);
+        gdm_session_defaults_changed (self);
 }
 
 void
@@ -1658,8 +2084,8 @@ gdm_session_authenticate (GdmSession *self,
 
         conversation = find_conversation_by_name (self, service_name);
         if (conversation != NULL) {
-                gdm_dbus_session_emit_authenticate (conversation->worker_skeleton,
-                                                    service_name);
+                gdm_dbus_worker_manager_emit_authenticate (conversation->worker_manager_interface,
+                                                           service_name);
         }
 }
 
@@ -1673,15 +2099,14 @@ gdm_session_authorize (GdmSession *self,
 
         conversation = find_conversation_by_name (self, service_name);
         if (conversation != NULL) {
-                gdm_dbus_session_emit_authorize (conversation->worker_skeleton,
-                                                 service_name);
+                gdm_dbus_worker_manager_emit_authorize (conversation->worker_manager_interface,
+                                                        service_name);
         }
 }
 
 void
 gdm_session_accredit (GdmSession *self,
-                      const char *service_name,
-                      gboolean    refresh)
+                      const char *service_name)
 {
         GdmSessionConversation *conversation;
 
@@ -1692,15 +2117,8 @@ gdm_session_accredit (GdmSession *self,
                 return;
         }
 
-        if (refresh) {
-                /* FIXME: need to support refresh
-                 */
-                gdm_dbus_session_emit_establish_credentials (conversation->worker_skeleton,
-                                                             service_name);
-        } else {
-                gdm_dbus_session_emit_establish_credentials (conversation->worker_skeleton,
-                                                             service_name);
-        }
+        gdm_dbus_worker_manager_emit_establish_credentials (conversation->worker_manager_interface,
+                                                            service_name);
 }
 
 static void
@@ -1708,9 +2126,9 @@ send_environment_variable (const char             *key,
                            const char             *value,
                            GdmSessionConversation *conversation)
 {
-        gdm_dbus_session_emit_set_environment_variable (conversation->worker_skeleton,
-                                                        key,
-                                                        value);
+        gdm_dbus_worker_manager_emit_set_environment_variable (conversation->worker_manager_interface,
+                                                               key,
+                                                               value);
 }
 
 static void
@@ -1838,8 +2256,8 @@ gdm_session_open_session (GdmSession *self,
 
         conversation = find_conversation_by_name (self, service_name);
 
-        gdm_dbus_session_emit_open_session (conversation->worker_skeleton,
-                                            service_name);
+        gdm_dbus_worker_manager_emit_open_session (conversation->worker_manager_interface,
+                                                   service_name);
 }
 
 static void
@@ -1935,8 +2353,8 @@ gdm_session_start_session (GdmSession *self,
         setup_session_environment (self);
         send_environment (self, conversation);
 
-        gdm_dbus_session_emit_start_program (conversation->worker_skeleton,
-                                             program);
+        gdm_dbus_worker_manager_emit_start_program (conversation->worker_manager_interface,
+                                                    program);
         g_free (program);
 }
 
@@ -1964,8 +2382,8 @@ gdm_session_close (GdmSession *self)
 
         stop_all_conversations (self);
 
-        g_list_free_full (self->priv->pending_connections, g_object_unref);
-        self->priv->pending_connections = NULL;
+        g_list_free_full (self->priv->pending_worker_connections, g_object_unref);
+        self->priv->pending_worker_connections = NULL;
 
         g_free (self->priv->selected_user);
         self->priv->selected_user = NULL;
@@ -2010,7 +2428,41 @@ gdm_session_cancel  (GdmSession *self)
 {
         g_return_if_fail (GDM_IS_SESSION (self));
 
-        stop_all_conversations (self);
+        g_signal_emit (G_OBJECT (self), signals [CANCELLED], 0);
+}
+
+void
+gdm_session_reset (GdmSession *self)
+{
+        gdm_dbus_user_verifier_emit_reset (self->priv->user_verifier_interface);
+
+        gdm_session_close (self);
+}
+
+void
+gdm_session_request_timed_login (GdmSession *self,
+                                 const char *username,
+                                 int         delay)
+{
+        gdm_dbus_greeter_session_emit_timed_login_requested (self->priv->greeter_session_interface,
+                                                             username,
+                                                             delay);
+}
+
+gboolean
+gdm_session_client_is_connected (GdmSession *self)
+{
+        g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
+
+        return self->priv->outside_connections != NULL;
+}
+
+char *
+gdm_session_get_server_address (GdmSession *self)
+{
+        g_return_val_if_fail (GDM_IS_SESSION (self), NULL);
+
+        return g_strdup (g_dbus_server_get_client_address (self->priv->outside_server));
 }
 
 char *
@@ -2124,8 +2576,8 @@ gdm_session_select_session_type (GdmSession *self,
 
                 conversation = (GdmSessionConversation *) value;
 
-                gdm_dbus_session_emit_set_session_type (conversation->worker_skeleton,
-                                                        text);
+                gdm_dbus_worker_manager_emit_set_session_type (conversation->worker_manager_interface,
+                                                               text);
         }
 }
 
@@ -2150,8 +2602,8 @@ gdm_session_select_session (GdmSession *self,
 
                 conversation = (GdmSessionConversation *) value;
 
-                gdm_dbus_session_emit_set_session_name (conversation->worker_skeleton,
-                                                        get_session_name (self));
+                gdm_dbus_worker_manager_emit_set_session_name (conversation->worker_manager_interface,
+                                                               get_session_name (self));
         }
 }
 
@@ -2176,8 +2628,8 @@ gdm_session_select_language (GdmSession *self,
 
                 conversation = (GdmSessionConversation *) value;
 
-                gdm_dbus_session_emit_set_language_name (conversation->worker_skeleton,
-                                                         get_language_name (self));
+                gdm_dbus_worker_manager_emit_set_language_name (conversation->worker_manager_interface,
+                                                                get_language_name (self));
         }
 }
 
@@ -2358,9 +2810,9 @@ gdm_session_dispose (GObject *object)
         g_free (self->priv->display_x11_authority_file);
         self->priv->display_x11_authority_file = NULL;
 
-        if (self->priv->server != NULL) {
-                g_dbus_server_stop (self->priv->server);
-                g_clear_object (&self->priv->server);
+        if (self->priv->worker_server != NULL) {
+                g_dbus_server_stop (self->priv->worker_server);
+                g_clear_object (&self->priv->worker_server);
         }
 
         if (self->priv->environment != NULL) {
@@ -2441,17 +2893,6 @@ gdm_session_class_init (GdmSessionClass *session_class)
                               g_cclosure_marshal_VOID__STRING,
                               G_TYPE_NONE,
                               1, G_TYPE_STRING);
-        signals [SERVICE_UNAVAILABLE] =
-                g_signal_new ("service-unavailable",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, service_unavailable),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_VOID__STRING,
-                              G_TYPE_NONE,
-                              1,
-                              G_TYPE_STRING);
         signals [SETUP_COMPLETE] =
                 g_signal_new ("setup-complete",
                               GDM_TYPE_SESSION,
@@ -2463,125 +2904,6 @@ gdm_session_class_init (GdmSessionClass *session_class)
                               G_TYPE_NONE,
                               1,
                               G_TYPE_STRING);
-        signals [SETUP_FAILED] =
-                g_signal_new ("setup-failed",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, setup_failed),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
-                              2,
-                              G_TYPE_STRING, G_TYPE_STRING);
-        signals [AUTHENTICATED] =
-                g_signal_new ("authenticated",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, authenticated),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_VOID__STRING,
-                              G_TYPE_NONE,
-                              1, G_TYPE_STRING);
-        signals [AUTHENTICATION_FAILED] =
-                g_signal_new ("authentication-failed",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, authentication_failed),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
-                              2,
-                              G_TYPE_STRING, G_TYPE_STRING);
-        signals [AUTHORIZED] =
-                g_signal_new ("authorized",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, authorized),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_VOID__STRING,
-                              G_TYPE_NONE,
-                              1, G_TYPE_STRING);
-        signals [AUTHORIZATION_FAILED] =
-                g_signal_new ("authorization-failed",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, authorization_failed),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
-                              2,
-                              G_TYPE_STRING, G_TYPE_STRING);
-        signals [ACCREDITED] =
-                g_signal_new ("accredited",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, accredited),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_VOID__STRING,
-                              G_TYPE_NONE,
-                              1, G_TYPE_STRING);
-        signals [ACCREDITATION_FAILED] =
-                g_signal_new ("accreditation-failed",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, accreditation_failed),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
-                              2,
-                              G_TYPE_STRING, G_TYPE_STRING);
-
-         signals [INFO_QUERY] =
-                g_signal_new ("info-query",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, info_query),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
-                              2,
-                              G_TYPE_STRING, G_TYPE_STRING);
-        signals [SECRET_INFO_QUERY] =
-                g_signal_new ("secret-info-query",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, secret_info_query),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
-                              2,
-                              G_TYPE_STRING, G_TYPE_STRING);
-        signals [INFO] =
-                g_signal_new ("info",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, info),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
-                              2,
-                              G_TYPE_STRING, G_TYPE_STRING);
-        signals [PROBLEM] =
-                g_signal_new ("problem",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, problem),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
-                              2,
-                              G_TYPE_STRING, G_TYPE_STRING);
         signals [SESSION_OPENED] =
                 g_signal_new ("session-opened",
                               GDM_TYPE_SESSION,
@@ -2591,19 +2913,9 @@ gdm_session_class_init (GdmSessionClass *session_class)
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
                               G_TYPE_NONE,
-                              1,
-                              G_TYPE_STRING);
-        signals [SESSION_OPEN_FAILED] =
-                g_signal_new ("session-open-failed",
-                              GDM_TYPE_SESSION,
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, session_open_failed),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_generic,
-                              G_TYPE_NONE,
                               2,
-                              G_TYPE_STRING, G_TYPE_STRING);
+                              G_TYPE_STRING,
+                              G_TYPE_STRING);
         signals [SESSION_STARTED] =
                 g_signal_new ("session-started",
                               GDM_TYPE_SESSION,
@@ -2614,7 +2926,8 @@ gdm_session_class_init (GdmSessionClass *session_class)
                               g_cclosure_marshal_generic,
                               G_TYPE_NONE,
                               2,
-                              G_TYPE_STRING, G_TYPE_INT);
+                              G_TYPE_STRING,
+                              G_TYPE_INT);
         signals [SESSION_START_FAILED] =
                 g_signal_new ("session-start-failed",
                               GDM_TYPE_SESSION,
@@ -2648,39 +2961,61 @@ gdm_session_class_init (GdmSessionClass *session_class)
                               G_TYPE_NONE,
                               1,
                               G_TYPE_INT);
-        signals [SELECTED_USER_CHANGED] =
-                g_signal_new ("selected-user-changed",
+        signals [CANCELLED] =
+                g_signal_new ("cancelled",
                               GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, selected_user_changed),
+                              G_STRUCT_OFFSET (GdmSessionClass, cancelled),
                               NULL,
                               NULL,
-                              g_cclosure_marshal_VOID__STRING,
+                              g_cclosure_marshal_VOID__VOID,
                               G_TYPE_NONE,
-                              1,
-                              G_TYPE_STRING);
-        signals [DEFAULT_LANGUAGE_NAME_CHANGED] =
-                g_signal_new ("default-language-name-changed",
+                              0);
+
+        signals [CLIENT_CONNECTED] =
+                g_signal_new ("client-connected",
                               GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, default_language_name_changed),
+                              G_STRUCT_OFFSET (GdmSessionClass, client_connected),
                               NULL,
                               NULL,
-                              g_cclosure_marshal_VOID__STRING,
+                              g_cclosure_marshal_VOID__VOID,
                               G_TYPE_NONE,
-                              1,
-                              G_TYPE_STRING);
-        signals [DEFAULT_SESSION_NAME_CHANGED] =
-                g_signal_new ("default-session-name-changed",
+                              0);
+
+        signals [CLIENT_DISCONNECTED] =
+                g_signal_new ("client-disconnected",
                               GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionClass, default_session_name_changed),
+                              G_STRUCT_OFFSET (GdmSessionClass, client_disconnected),
                               NULL,
                               NULL,
-                              g_cclosure_marshal_VOID__STRING,
+                              g_cclosure_marshal_VOID__VOID,
                               G_TYPE_NONE,
-                              1,
-                              G_TYPE_STRING);
+                              0);
+        signals [CLIENT_READY_FOR_SESSION_TO_START] =
+                g_signal_new ("client-ready-for-session-to-start",
+                              GDM_TYPE_SESSION,
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GdmSessionClass, client_ready_for_session_to_start),
+                              NULL,
+                              NULL,
+                              NULL,
+                              G_TYPE_NONE,
+                              2,
+                              G_TYPE_STRING,
+                              G_TYPE_BOOLEAN);
+
+        signals [DISCONNECTED] =
+                g_signal_new ("disconnected",
+                              GDM_TYPE_SESSION,
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GdmSessionClass, disconnected),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
 
         g_object_class_install_property (object_class,
                                          PROP_DISPLAY_ID,
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index b716cbe..5b23019 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -45,49 +45,20 @@ typedef struct
         GObjectClass parent_class;
 
         /* Signals */
-        void (* setup_complete)              (GdmSession   *session,
-                                              const char   *service_name);
-        void (* setup_failed)                (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *message);
-        void (* reset_complete)              (GdmSession   *session);
-        void (* reset_failed)                (GdmSession   *session,
-                                              const char   *message);
-        void (* authenticated)               (GdmSession   *session,
-                                              const char   *service_name);
-        void (* authentication_failed)       (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *message);
-        void (* authorized)                  (GdmSession   *session,
-                                              const char   *service_name);
-        void (* authorization_failed)        (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *message);
-        void (* accredited)                  (GdmSession   *session,
-                                              const char   *service_name);
-        void (* accreditation_failed)        (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *message);
-
-        void (* info_query)                  (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *query_text);
-        void (* secret_info_query)           (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *query_text);
-        void (* info)                        (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *info);
-        void (* problem)                     (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *problem);
+        void (* client_ready_for_session_to_start) (GdmSession   *session,
+                                                    const char   *service_name,
+                                                    gboolean      client_is_ready);
+
+        void (* cancelled)                   (GdmSession   *session);
+        void (* client_connected)            (GdmSession   *session);
+        void (* client_disconnected)         (GdmSession   *session);
+        void (* disconnected)                (GdmSession   *session);
         void (* session_opened)              (GdmSession   *session,
-                                              const char   *service_name);
-        void (* session_open_failed)         (GdmSession   *session,
                                               const char   *service_name,
-                                              const char   *message);
+                                              const char   *session_id);
         void (* session_started)             (GdmSession   *session,
                                               const char   *service_name,
+                                              const char   *session_id,
                                               int           pid);
         void (* session_start_failed)        (GdmSession   *session,
                                               const char   *service_name,
@@ -100,15 +71,8 @@ typedef struct
                                               const char   *service_name);
         void (* conversation_stopped)        (GdmSession   *session,
                                               const char   *service_name);
-        void (* service_unavailable)         (GdmSession   *session,
+        void (* setup_complete)              (GdmSession   *session,
                                               const char   *service_name);
-        void (* selected_user_changed)       (GdmSession   *session,
-                                              const char   *text);
-
-        void (* default_language_name_changed)    (GdmSession   *session,
-                                                   const char   *text);
-        void (* default_session_name_changed)     (GdmSession   *session,
-                                                   const char   *text);
 } GdmSessionClass;
 
 GType            gdm_session_get_type                 (void);
@@ -121,9 +85,11 @@ GdmSession      *gdm_session_new                      (const char *display_id,
                                                        const char *display_x11_authority_file,
                                                        gboolean    display_is_local);
 
+char             *gdm_session_get_server_address          (GdmSession     *session);
 char             *gdm_session_get_username                (GdmSession     *session);
 char             *gdm_session_get_display_device          (GdmSession     *session);
 char             *gdm_session_get_display_seat_id         (GdmSession     *session);
+char             *gdm_session_get_session_id              (GdmSession     *session);
 gboolean          gdm_session_bypasses_xsession           (GdmSession     *session);
 
 void              gdm_session_start_conversation          (GdmSession *session,
@@ -147,8 +113,7 @@ void              gdm_session_authenticate                (GdmSession *session,
 void              gdm_session_authorize                   (GdmSession *session,
                                                            const char *service_name);
 void              gdm_session_accredit                    (GdmSession *session,
-                                                           const char *service_name,
-                                                           int         cred_flag);
+                                                           const char *service_name);
 void              gdm_session_open_session                (GdmSession *session,
                                                            const char *service_name);
 void              gdm_session_start_session               (GdmSession *session,
@@ -169,6 +134,11 @@ void              gdm_session_select_language             (GdmSession *session,
 void              gdm_session_select_user                 (GdmSession *session,
                                                            const char *username);
 void              gdm_session_cancel                      (GdmSession *session);
+void              gdm_session_reset                       (GdmSession *session);
+void              gdm_session_request_timed_login         (GdmSession *session,
+                                                           const char *username,
+                                                           int         delay);
+gboolean          gdm_session_client_is_connected         (GdmSession *session);
 
 G_END_DECLS
 
diff --git a/daemon/gdm-session.xml b/daemon/gdm-session.xml
index c320c09..21e0d57 100644
--- a/daemon/gdm-session.xml
+++ b/daemon/gdm-session.xml
@@ -2,15 +2,7 @@
 <node name="/org/gnome/DisplayManager/Session">
   <!-- methods are called by the session worker,
        signals are emitted by the simple slave -->
-  <interface name="org.gnome.DisplayManager.Session">
-    <method name="ConversationStarted">
-      <arg name="service_name" direction="in" type="s"/>
-    </method>
-    <signal name="StartConversation">
-      <arg name="service_name" type="s"/>
-    </signal>
-    <signal name="Close"/>
-    <signal name="Cancelled"/>
+  <interface name="org.gnome.DisplayManager.WorkerManager">
     <method name="Hello" />
     <method name="CancelPendingQuery">
       <arg name="service_name" type="s" direction="in"/>
@@ -25,9 +17,6 @@
     <method name="SavedSessionNameRead">
       <arg name="session_name" type="s" direction="in"/>
     </method>
-    <signal name="StartProgram">
-      <arg name="command" type="s"/>
-    </signal>
     <method name="ServiceUnavailable">
       <arg name="service_name" direction="in" type="s"/>
       <arg name="message" direction="in" type="s"/>
@@ -62,24 +51,25 @@
     </method>
     <method name="InfoQuery">
       <arg name="service_name" direction="in" type="s"/>
-      <arg name="text" direction="in" type="s"/>
+      <arg name="query" direction="in" type="s"/>
       <arg name="answer" direction="out" type="s"/>
     </method>
     <method name="SecretInfoQuery">
       <arg name="service_name" direction="in" type="s"/>
-      <arg name="text" direction="in" type="s"/>
+      <arg name="query" direction="in" type="s"/>
       <arg name="answer" direction="out" type="s"/>
     </method>
     <method name="Info">
       <arg name="service_name" direction="in" type="s"/>
-      <arg name="text" direction="in" type="s"/>
+      <arg name="info" direction="in" type="s"/>
     </method>
     <method name="Problem">
       <arg name="service_name" direction="in" type="s"/>
-      <arg name="text" direction="in" type="s"/>
+      <arg name="problem" direction="in" type="s"/>
     </method>
     <method name="Opened">
       <arg name="service_name" direction="in" type="s"/>
+      <arg name="session_id" direction="in" type="s"/>
     </method>
     <method name="OpenFailed">
       <arg name="service_name" direction="in" type="s"/>
@@ -100,6 +90,14 @@
       <arg name="status" direction="in" type="i"/>
     </method>
 
+    <signal name="StartConversation">
+      <arg name="service_name" type="s"/>
+    </signal>
+    <signal name="StartProgram">
+      <arg name="command" type="s"/>
+    </signal>
+    <signal name="Close"/>
+    <signal name="Cancelled"/>
     <signal name="Reset" />
     <signal name="Setup">
       <arg name="service_name" type="s"/>
@@ -156,4 +154,96 @@
       <arg name="session_type" type="s" />
     </signal>
   </interface>
+  <interface name="org.gnome.DisplayManager.UserVerifier">
+    <method name="StartConversation">
+      <arg name="service_name" direction="in" type="s"/>
+    </method>
+    <method name="StopConversation">
+      <arg name="service_name" direction="in" type="s"/>
+    </method>
+    <method name="BeginVerification">
+      <arg name="service_name" direction="in" type="s"/>
+    </method>
+    <method name="BeginVerificationForUser">
+      <arg name="service_name" direction="in" type="s"/>
+      <arg name="username" direction="in" type="s"/>
+    </method>
+    <method name="AnswerQuery">
+      <arg name="service_name" direction="in" type="s"/>
+      <arg name="answer" direction="in" type="s"/>
+    </method>
+    <method name="Cancel">
+    </method>
+    <signal name="Info">
+      <arg name="service_name" type="s"/>
+      <arg name="info" type="s"/>
+    </signal>
+    <signal name="Problem">
+      <arg name="service_name" type="s"/>
+      <arg name="problem" type="s"/>
+    </signal>
+    <signal name="InfoQuery">
+      <arg name="service_name" type="s"/>
+      <arg name="query" type="s"/>
+    </signal>
+    <signal name="SecretInfoQuery">
+      <arg name="service_name" type="s"/>
+      <arg name="query" type="s"/>
+    </signal>
+    <signal name="Ready">
+      <arg name="service_name" type="s"/>
+    </signal>
+    <signal name="ConversationStopped">
+      <arg name="service_name" type="s"/>
+    </signal>
+    <signal name="Reset">
+    </signal>
+    <signal name="ServiceUnavailable">
+      <arg name="service_name" type="s"/>
+      <arg name="message" type="s"/>
+    </signal>
+    <signal name="VerificationComplete">
+      <arg name="service_name" type="s"/>
+    </signal>
+  </interface>
+  <interface name="org.gnome.DisplayManager.GreeterSession">
+    <method name="SelectSession">
+      <arg name="session" direction="in" type="s"/>
+    </method>
+    <method name="SelectLanguage">
+      <arg name="language" direction="in" type="s"/>
+    </method>
+    <method name="SelectUser">
+      <arg name="username" direction="in" type="s"/>
+    </method>
+    <method name="BeginAutoLogin">
+      <arg name="username" direction="in" type="s"/>
+    </method>
+    <method name="StartSessionWhenReady">
+      <arg name="service_name" direction="in" type="s"/>
+      <arg name="should_start_session" direction="in" type="b"/>
+    </method>
+    <signal name="SelectedUserChanged">
+      <arg name="username" type="s"/>
+    </signal>
+    <signal name="DefaultLanguageNameChanged">
+      <arg name="language_name" type="s"/>
+    </signal>
+    <signal name="DefaultSessionNameChanged">
+      <arg name="session_name" type="s"/>
+    </signal>
+    <signal name="TimedLoginRequested">
+      <arg name="username" type="s"/>
+      <arg name="delay" type="i"/>
+    </signal>
+    <signal name="SessionOpened">
+      <arg name="service_name" type="s"/>
+    </signal>
+  </interface>
+  <interface name="org.gnome.DisplayManager.ChooserSession">
+    <method name="SelectHostname">
+      <arg name="hostname" direction="in" type="s"/>
+    </method>
+    <method name="Disconnect" />
+  </interface>
 </node>
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 6968017..5aef8bb 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -49,7 +49,7 @@
 
 #include "gdm-server.h"
 #include "gdm-session.h"
-#include "gdm-greeter-server.h"
+#include "gdm-session-glue.h"
 #include "gdm-greeter-session.h"
 #include "gdm-settings-direct.h"
 #include "gdm-settings-keys.h"
@@ -65,8 +65,7 @@
 struct GdmSimpleSlavePrivate
 {
         GPid               pid;
-
-        guint              greeter_reset_id;
+        gint               greeter_reset_id;
         guint              start_session_id;
 
         char              *start_session_service_name;
@@ -78,12 +77,11 @@ struct GdmSimpleSlavePrivate
 
         GdmServer         *server;
         GdmSession        *session;
-
-        GdmGreeterServer  *greeter_server;
         GdmGreeterSession *greeter;
 
         guint              start_session_when_ready : 1;
         guint              waiting_to_start_session : 1;
+        guint              session_is_running : 1;
 #ifdef  HAVE_LOGINDEVPERM
         gboolean           use_logindevperm;
 #endif
@@ -102,10 +100,10 @@ static void     gdm_simple_slave_finalize       (GObject             *object);
 
 G_DEFINE_TYPE (GdmSimpleSlave, gdm_simple_slave, GDM_TYPE_SLAVE)
 
-static void create_new_session (GdmSimpleSlave *slave);
-static void destroy_session    (GdmSimpleSlave *slave);
+static void create_new_session (GdmSimpleSlave  *slave);
+static void destroy_session    (GdmSimpleSlave  *slave);
 static void start_greeter      (GdmSimpleSlave *slave);
-static void start_session      (GdmSimpleSlave *slave);
+static void start_session      (GdmSimpleSlave  *slave);
 static void queue_start_session (GdmSimpleSlave *slave,
                                  const char     *service_name);
 
@@ -116,9 +114,16 @@ on_session_started (GdmSession       *session,
                     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) {
@@ -209,6 +214,9 @@ on_session_exited (GdmSession       *session,
                    int               exit_code,
                    GdmSimpleSlave   *slave)
 {
+        slave->priv->session_is_running = FALSE;
+        g_object_set (GDM_SLAVE (slave), "session-id", NULL, NULL);
+
         g_debug ("GdmSimpleSlave: session exited with code %d\n", exit_code);
         if (slave->priv->start_session_service_name == NULL) {
                 gdm_slave_stopped (GDM_SLAVE (slave));
@@ -220,6 +228,9 @@ on_session_died (GdmSession       *session,
                  int               signal_number,
                  GdmSimpleSlave   *slave)
 {
+        slave->priv->session_is_running = FALSE;
+        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));
@@ -246,19 +257,21 @@ add_user_authorization (GdmSimpleSlave *slave,
 }
 
 static void
-reset_session (GdmSimpleSlave *slave)
+reset_session (GdmSimpleSlave  *slave)
 {
-        destroy_session (slave);
-        create_new_session (slave);
+        if (slave->priv->session == NULL) {
+                return;
+        }
+
+        gdm_session_reset (slave->priv->session);
 }
 
 static gboolean
-greeter_reset_timeout (GdmSimpleSlave *slave)
+greeter_reset_timeout (GdmSimpleSlave  *slave)
 {
         g_debug ("GdmSimpleSlave: resetting greeter");
 
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_reset (slave->priv->greeter_server);
+        if (gdm_session_client_is_connected (slave->priv->session)) {
                 reset_session (slave);
         } else {
                 start_greeter (slave);
@@ -269,7 +282,7 @@ greeter_reset_timeout (GdmSimpleSlave *slave)
 }
 
 static void
-queue_greeter_reset (GdmSimpleSlave *slave)
+queue_greeter_reset (GdmSimpleSlave  *slave)
 {
         if (slave->priv->greeter_reset_id > 0) {
                 return;
@@ -279,66 +292,6 @@ queue_greeter_reset (GdmSimpleSlave *slave)
 }
 
 static void
-on_session_service_unavailable (GdmSession       *session,
-                                const char       *service_name,
-                                GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_service_unavailable (slave->priv->greeter_server,
-                                                        service_name);
-        }
-
-        gdm_session_stop_conversation (session, service_name);
-}
-
-static void
-on_session_setup_complete (GdmSession       *session,
-                           const char       *service_name,
-                           GdmSimpleSlave   *slave)
-{
-        gdm_session_authenticate (session, service_name);
-}
-
-static void
-on_session_setup_failed (GdmSession       *session,
-                         const char       *service_name,
-                         const char       *message,
-                         GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_problem (slave->priv->greeter_server,
-                                            service_name,
-                                            message != NULL ? message:  _("Unable to initialize login system"));
-        }
-
-        gdm_session_stop_conversation (session, service_name);
-}
-
-static void
-on_session_authenticated (GdmSession       *session,
-                          const char       *service_name,
-                          GdmSimpleSlave   *slave)
-{
-        gdm_session_authorize (session, service_name);
-}
-
-static void
-on_session_authentication_failed (GdmSession       *session,
-                                  const char       *service_name,
-                                  const char       *message,
-                                  GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_problem (slave->priv->greeter_server,
-                                            service_name,
-                                            message != NULL ? message : _("Unable to authenticate user"));
-        }
-
-        g_debug ("GdmSimpleSlave: Authentication failed - may retry");
-        gdm_session_stop_conversation (session, service_name);
-}
-
-static void
 gdm_simple_slave_start_session_when_ready (GdmSimpleSlave *slave,
                                            const char     *service_name)
 {
@@ -350,32 +303,8 @@ gdm_simple_slave_start_session_when_ready (GdmSimpleSlave *slave,
         }
 }
 
-static void
-on_session_authorized (GdmSession       *session,
-                       const char       *service_name,
-                       GdmSimpleSlave   *slave)
-{
-        /* FIXME: we don't yet support refresh */
-        gdm_session_accredit (slave->priv->session, service_name, FALSE);
-}
-
-static void
-on_session_authorization_failed (GdmSession       *session,
-                                 const char       *service_name,
-                                 const char       *message,
-                                 GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_problem (slave->priv->greeter_server,
-                                            service_name,
-                                            message != NULL ? message :  _("Unable to authorize user"));
-        }
-
-        gdm_session_stop_conversation (session, service_name);
-}
-
 static gboolean
-try_migrate_session (GdmSimpleSlave *slave)
+try_migrate_session (GdmSimpleSlave  *slave)
 {
         char    *username;
         gboolean res;
@@ -418,9 +347,10 @@ stop_greeter (GdmSimpleSlave *slave)
 }
 
 static void
-start_session (GdmSimpleSlave *slave)
+start_session (GdmSimpleSlave  *slave)
 {
-        char    *auth_file;
+        char           *auth_file;
+
         auth_file = NULL;
         add_user_authorization (slave, &auth_file);
 
@@ -433,7 +363,7 @@ start_session (GdmSimpleSlave *slave)
         g_free (auth_file);
 
         gdm_session_start_session (slave->priv->session,
-                                          slave->priv->start_session_service_name);
+                                   slave->priv->start_session_service_name);
 
         slave->priv->start_session_id = 0;
         g_free (slave->priv->start_session_service_name);
@@ -441,11 +371,11 @@ start_session (GdmSimpleSlave *slave)
 }
 
 static gboolean
-start_session_timeout (GdmSimpleSlave *slave)
+start_session_timeout (GdmSimpleSlave  *slave)
 {
-
         gboolean migrated;
 
+
         g_debug ("GdmSimpleSlave: accredited");
 
         migrated = try_migrate_session (slave);
@@ -487,13 +417,9 @@ queue_start_session (GdmSimpleSlave *slave,
         slave->priv->start_session_service_name = g_strdup (service_name);
 }
 
-static void
-on_session_accredited (GdmSession       *session,
-                       const char       *service_name,
-                       GdmSimpleSlave   *slave)
-{
-        gdm_session_open_session (session, service_name);
-}
+
+#pragma FIXME need to figure out migration
+#if 0
 
 static void
 on_session_accreditation_failed (GdmSession       *session,
@@ -503,132 +429,62 @@ on_session_accreditation_failed (GdmSession       *session,
 {
         gboolean migrated;
 
-        g_debug ("GdmSimpleSlave: accreditation failed");
 
-        migrated = try_migrate_session (slave);
+        /* Only try migration if slave is the primary session */
+        if (slave == slave->priv->session)
+                migrated = try_migrate_session (slave);
+        else
+                migrated = FALSE;
 
         /* If we switched to another session we don't care if
            accreditation fails */
         if (! migrated) {
-                if (slave->priv->greeter_server != NULL) {
-                        const char *problem;
-                        if (message) {
-                                problem = message;
-                        } else {
-                                problem = _("Unable to establish credentials");
-                        }
-                        gdm_greeter_server_problem (slave->priv->greeter_server,
-                                                    service_name,
-                                                    problem);
-                }
+                g_debug ("GdmSimpleSlave: accreditation failed: %s", message);
         }
 
         gdm_session_stop_conversation (session, service_name);
 }
+#endif
 
 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 (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_session_opened (slave->priv->greeter_server, service_name);
+        if (gdm_session_client_is_connected (slave->priv->session)) {
                 gdm_simple_slave_start_session_when_ready (slave, service_name);
         } else {
+                /* Auto login */
                 slave->priv->start_session_when_ready = TRUE;
                 gdm_simple_slave_start_session_when_ready (slave, service_name);
         }
 }
 
 static void
-on_session_open_failed (GdmSession       *session,
-                        const char       *service_name,
-                        const char       *message,
-                        GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_problem (slave->priv->greeter_server,
-                                            service_name,
-                                            _("Unable to open session"));
-        }
-
-        gdm_session_stop_conversation (session, service_name);
-}
-
-static void
-on_session_info (GdmSession       *session,
-                 const char       *service_name,
-                 const char       *text,
-                 GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: Info: %s", text);
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_info (slave->priv->greeter_server, service_name, text);
-        }
-}
-
-static void
-on_session_problem (GdmSession       *session,
-                    const char       *service_name,
-                    const char       *text,
-                    GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: Problem: %s", text);
-        gdm_greeter_server_problem (slave->priv->greeter_server, service_name, text);
-}
-
-static void
-on_session_info_query (GdmSession       *session,
-                       const char       *service_name,
-                       const char       *text,
-                       GdmSimpleSlave   *slave)
-{
-
-        g_debug ("GdmSimpleSlave: Info query: %s", text);
-        gdm_greeter_server_info_query (slave->priv->greeter_server, service_name, text);
-}
-
-static void
-on_session_secret_info_query (GdmSession       *session,
-                              const char       *service_name,
-                              const char       *text,
-                              GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: Secret info query: %s", text);
-        gdm_greeter_server_secret_info_query (slave->priv->greeter_server, service_name, text);
-}
-
-static void
 on_session_conversation_started (GdmSession       *session,
                                  const char       *service_name,
                                  GdmSimpleSlave   *slave)
 {
-        gboolean res;
         gboolean enabled;
         char    *username;
         int      delay;
 
-        g_debug ("GdmSimpleSlave: session conversation started");
-        if (slave->priv->greeter_server != NULL) {
-                res = gdm_greeter_server_ready (slave->priv->greeter_server,
-                                                service_name);
-                if (! res) {
-                        g_warning ("Unable to send ready");
-                }
-        }
 
+        g_debug ("GdmSimpleSlave: session conversation started");
         enabled = FALSE;
         gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, &username, &delay);
         if (! enabled) {
                 return;
         }
 
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_request_timed_login (slave->priv->greeter_server, username, delay);
+        if (delay > 0) {
+                gdm_session_request_timed_login (session, username, delay);
         } else {
                 g_debug ("GdmSimpleSlave: begin auto login for user '%s'", username);
                 /* service_name will be "gdm-autologin"
@@ -644,70 +500,93 @@ on_session_conversation_stopped (GdmSession       *session,
                                  const char       *service_name,
                                  GdmSimpleSlave   *slave)
 {
-        gboolean res;
         g_debug ("GdmSimpleSlave: conversation stopped");
 
-        if (slave->priv->greeter != NULL) {
-                res = gdm_greeter_server_conversation_stopped (slave->priv->greeter_server,
-                                                               service_name);
-                if (! res) {
-                        g_warning ("Unable to send conversation stopped");
-                }
-        }
 }
 
 static void
-on_session_selected_user_changed (GdmSession       *session,
-                                  const char       *text,
-                                  GdmSimpleSlave   *slave)
+start_autologin_conversation_if_necessary (GdmSimpleSlave  *slave)
 {
-        g_debug ("GdmSimpleSlave: Selected user changed: %s", text);
+        gboolean enabled;
 
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_selected_user_changed (slave->priv->greeter_server, text);
+        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_default_language_name_changed (GdmSession       *session,
-                                  const char       *text,
-                                  GdmSimpleSlave   *slave)
+on_session_client_ready_for_session_to_start (GdmSession      *session,
+                                              const char      *service_name,
+                                              gboolean         client_is_ready,
+                                              GdmSimpleSlave  *slave)
 {
-        g_debug ("GdmSimpleSlave: Default language name changed: %s", text);
+        
+        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 (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_default_language_name_changed (slave->priv->greeter_server, text);
+        if (client_is_ready && slave->priv->waiting_to_start_session) {
+                gdm_simple_slave_start_session_when_ready (slave, service_name);
         }
 }
-
 static void
-on_default_session_name_changed (GdmSession       *session,
-                                 const char       *text,
-                                 GdmSimpleSlave   *slave)
+on_session_client_connected (GdmSession          *session,
+                             GdmSimpleSlave      *slave)
 {
-        g_debug ("GdmSimpleSlave: Default session name changed: %s", text);
+        gboolean display_is_local;
+
+        g_debug ("GdmSimpleSlave: client connected");
+
+        g_object_get (slave,
+                      "display-is-local", &display_is_local,
+                      NULL);
 
-        if (slave->priv->greeter_server != NULL) {
-                gdm_greeter_server_default_session_name_changed (slave->priv->greeter_server, text);
+        /* If XDMCP stop pinging */
+        if ( ! display_is_local) {
+                alarm (0);
         }
 }
 
 static void
-start_autologin_conversation_if_necessary (GdmSimpleSlave *slave)
+on_session_client_disconnected (GdmSession          *session,
+                                GdmSimpleSlave      *slave)
 {
-        gboolean enabled;
-        gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, NULL, NULL);
+        gboolean display_is_local;
 
-        if (!enabled) {
-                return;
+        g_debug ("GdmSimpleSlave: client disconnected");
+
+        g_object_get (slave,
+                      "display-is-local", &display_is_local,
+                      NULL);
+
+        if ( ! display_is_local) {
+                gdm_slave_stopped (GDM_SLAVE (slave));
         }
+}
 
-        g_debug ("GdmSimpleSlave: Starting automatic login conversation");
-        gdm_session_start_conversation (slave->priv->session, "gdm-autologin");
+static void
+on_session_cancelled (GdmSession      *session,
+                      GdmSimpleSlave  *slave)
+{
+        g_debug ("GdmSimpleSlave: Session was cancelled");
+        queue_greeter_reset (slave);
 }
 
 static void
-create_new_session (GdmSimpleSlave *slave)
+create_new_session (GdmSimpleSlave  *slave)
 {
         gboolean       display_is_local;
         char          *display_id;
@@ -740,80 +619,41 @@ create_new_session (GdmSimpleSlave *slave)
                                                 display_seat_id,
                                                 display_x11_authority_file,
                                                 display_is_local);
+
         g_free (display_id);
         g_free (display_name);
         g_free (display_device);
         g_free (display_hostname);
 
         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,
-                          "service-unavailable",
-                          G_CALLBACK (on_session_service_unavailable),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "setup-complete",
-                          G_CALLBACK (on_session_setup_complete),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "setup-failed",
-                          G_CALLBACK (on_session_setup_failed),
+                          "client-ready-for-session-to-start",
+                          G_CALLBACK (on_session_client_ready_for_session_to_start),
                           slave);
         g_signal_connect (slave->priv->session,
-                          "authenticated",
-                          G_CALLBACK (on_session_authenticated),
+                          "client-connected",
+                          G_CALLBACK (on_session_client_connected),
                           slave);
         g_signal_connect (slave->priv->session,
-                          "authentication-failed",
-                          G_CALLBACK (on_session_authentication_failed),
+                          "client-disconnected",
+                          G_CALLBACK (on_session_client_disconnected),
                           slave);
         g_signal_connect (slave->priv->session,
-                          "authorized",
-                          G_CALLBACK (on_session_authorized),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "authorization-failed",
-                          G_CALLBACK (on_session_authorization_failed),
+                          "cancelled",
+                          G_CALLBACK (on_session_cancelled),
                           slave);
         g_signal_connect (slave->priv->session,
-                          "accredited",
-                          G_CALLBACK (on_session_accredited),
+                          "conversation-started",
+                          G_CALLBACK (on_session_conversation_started),
                           slave);
         g_signal_connect (slave->priv->session,
-                          "accreditation-failed",
-                          G_CALLBACK (on_session_accreditation_failed),
+                          "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-open-failed",
-                          G_CALLBACK (on_session_open_failed),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "info",
-                          G_CALLBACK (on_session_info),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "problem",
-                          G_CALLBACK (on_session_problem),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "info-query",
-                          G_CALLBACK (on_session_info_query),
-                          slave);
-        g_signal_connect (slave->priv->session,
-                          "secret-info-query",
-                          G_CALLBACK (on_session_secret_info_query),
-                          slave);
-        g_signal_connect (slave->priv->session,
                           "session-started",
                           G_CALLBACK (on_session_started),
                           slave);
@@ -825,83 +665,39 @@ create_new_session (GdmSimpleSlave *slave)
                           "session-died",
                           G_CALLBACK (on_session_died),
                           slave);
-        g_signal_connect (slave->priv->session,
-                          "selected-user-changed",
-                          G_CALLBACK (on_session_selected_user_changed),
-                          slave);
-
-        g_signal_connect (slave->priv->session,
-                          "default-language-name-changed",
-                          G_CALLBACK (on_default_language_name_changed),
-                          slave);
-
-        g_signal_connect (slave->priv->session,
-                          "default-session-name-changed",
-                          G_CALLBACK (on_default_session_name_changed),
-                          slave);
 
         start_autologin_conversation_if_necessary (slave);
 }
 
 static void
-destroy_session (GdmSimpleSlave *slave)
+destroy_session (GdmSimpleSlave  *slave)
 {
         if (slave->priv->session == NULL) {
                 return;
         }
 
         g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_conversation_started),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_conversation_stopped),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_service_unavailable),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_setup_complete),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_setup_failed),
+                                              G_CALLBACK (on_session_client_ready_for_session_to_start),
                                               slave);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_authenticated),
+                                              G_CALLBACK (on_session_client_connected),
                                               slave);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_authentication_failed),
+                                              G_CALLBACK (on_session_client_disconnected),
                                               slave);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_authorized),
+                                              G_CALLBACK (on_session_cancelled),
                                               slave);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_authorization_failed),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_accredited),
+                                              G_CALLBACK (on_session_conversation_started),
                                               slave);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_accreditation_failed),
+                                              G_CALLBACK (on_session_conversation_stopped),
                                               slave);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
                                               G_CALLBACK (on_session_opened),
                                               slave);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_open_failed),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_info),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_problem),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_info_query),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_secret_info_query),
-                                              slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
                                               G_CALLBACK (on_session_started),
                                               slave);
         g_signal_handlers_disconnect_by_func (slave->priv->session,
@@ -910,38 +706,42 @@ destroy_session (GdmSimpleSlave *slave)
         g_signal_handlers_disconnect_by_func (slave->priv->session,
                                               G_CALLBACK (on_session_died),
                                               slave);
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_session_selected_user_changed),
-                                              slave);
-
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_default_language_name_changed),
-                                              slave);
-
-        g_signal_handlers_disconnect_by_func (slave->priv->session,
-                                              G_CALLBACK (on_default_session_name_changed),
-                                              slave);
 
         gdm_session_close (slave->priv->session);
         g_clear_object (&slave->priv->session);
 }
 
 static void
-on_greeter_session_start (GdmGreeterSession *greeter,
-                          GdmSimpleSlave    *slave)
+on_greeter_session_opened (GdmGreeterSession *greeter,
+                           GdmSimpleSlave    *slave)
+{
+        GdmSession *session;
+        char       *session_id;
+
+        g_debug ("GdmSimpleSlave: Greeter session opened");
+
+        session = gdm_welcome_session_get_session (GDM_WELCOME_SESSION (greeter));
+        session_id = gdm_session_get_session_id (session);
+
+        g_object_set (GDM_SLAVE (slave), "session-id", session_id, NULL);
+        g_free (session_id);
+}
+
+static void
+on_greeter_session_started (GdmGreeterSession *greeter,
+                            GdmSimpleSlave    *slave)
 {
         g_debug ("GdmSimpleSlave: Greeter started");
 }
 
 static void
-on_greeter_session_stop (GdmGreeterSession *greeter,
-                         GdmSimpleSlave    *slave)
+on_greeter_session_stopped (GdmGreeterSession *greeter,
+                            GdmSimpleSlave    *slave)
 {
         g_debug ("GdmSimpleSlave: Greeter stopped");
         if (slave->priv->start_session_service_name == NULL) {
                 gdm_slave_stopped (GDM_SLAVE (slave));
         } else {
-                gdm_greeter_server_stop (slave->priv->greeter_server);
                 start_session (slave);
         }
 
@@ -972,172 +772,6 @@ on_greeter_session_died (GdmGreeterSession    *greeter,
         }
 }
 
-static void
-on_greeter_start_conversation (GdmGreeterServer *greeter_server,
-                               const char       *service_name,
-                               GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-
-        g_debug ("GdmSimpleSlave: starting conversation with '%s' pam service'", service_name);
-        gdm_session_start_conversation (slave->priv->session, service_name);
-}
-
-static void
-on_greeter_begin_verification (GdmGreeterServer *greeter_server,
-                               const char       *service_name,
-                               GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: begin verification");
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-        gdm_session_setup (slave->priv->session, service_name);
-}
-
-static void
-on_greeter_begin_auto_login (GdmGreeterServer *greeter_server,
-                             const char       *username,
-                             GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: begin auto login for user '%s'", username);
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-        gdm_session_setup_for_user (slave->priv->session, "gdm-autologin", username);
-}
-
-static void
-on_greeter_begin_verification_for_user (GdmGreeterServer *greeter_server,
-                                        const char       *service_name,
-                                        const char       *username,
-                                        GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: begin verification");
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-        gdm_session_setup_for_user (slave->priv->session, service_name, username);
-}
-
-static void
-on_greeter_answer (GdmGreeterServer *greeter_server,
-                   const char       *service_name,
-                   const char       *text,
-                   GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-        gdm_session_answer_query (slave->priv->session, service_name, text);
-}
-
-static void
-on_greeter_session_selected (GdmGreeterServer *greeter_server,
-                             const char       *text,
-                             GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-        gdm_session_select_session (slave->priv->session, text);
-}
-
-static void
-on_greeter_language_selected (GdmGreeterServer *greeter_server,
-                              const char       *text,
-                              GdmSimpleSlave   *slave)
-{
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-        gdm_session_select_language (slave->priv->session, text);
-}
-
-static void
-on_greeter_user_selected (GdmGreeterServer *greeter_server,
-                          const char       *text,
-                          GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: Greeter user selected");
-}
-
-static void
-on_greeter_cancel (GdmGreeterServer *greeter_server,
-                   GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: Greeter cancelled");
-        queue_greeter_reset (slave);
-}
-
-static void
-on_greeter_connected (GdmGreeterServer *greeter_server,
-                      GdmSimpleSlave   *slave)
-{
-        gboolean display_is_local;
-
-        g_debug ("GdmSimpleSlave: Greeter connected");
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-
-        g_object_get (slave,
-                      "display-is-local", &display_is_local,
-                      NULL);
-
-        /* If XDMCP stop pinging */
-        if ( ! display_is_local) {
-                alarm (0);
-        }
-}
-
-static void
-on_greeter_disconnected (GdmGreeterServer *greeter_server,
-                         GdmSimpleSlave   *slave)
-{
-        gboolean display_is_local;
-
-        g_debug ("GdmSimpleSlave: Greeter disconnected");
-
-        g_object_get (slave,
-                      "display-is-local", &display_is_local,
-                      NULL);
-
-        if ( ! display_is_local) {
-                gdm_slave_stopped (GDM_SLAVE (slave));
-        }
-}
-
-static void
-on_start_session_when_ready (GdmGreeterServer *session,
-                             const char       *service_name,
-                             GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: Will start session when ready");
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-        slave->priv->start_session_when_ready = TRUE;
-
-        if (slave->priv->waiting_to_start_session) {
-                gdm_simple_slave_start_session_when_ready (slave, service_name);
-        }
-}
-
-static void
-on_start_session_later (GdmGreeterServer *session,
-                        const char       *service_name,
-                        GdmSimpleSlave   *slave)
-{
-        g_debug ("GdmSimpleSlave: Will start session when ready and told");
-        if (slave->priv->greeter_reset_id > 0) {
-                return;
-        }
-        slave->priv->start_session_when_ready = FALSE;
-}
-
 #ifdef  WITH_PLYMOUTH
 static gboolean
 plymouth_is_running (void)
@@ -1243,7 +877,6 @@ start_greeter (GdmSimpleSlave *slave)
         char          *display_device;
         char          *display_hostname;
         char          *auth_file;
-        char          *address;
         gboolean       res;
 
         g_debug ("GdmSimpleSlave: Running greeter");
@@ -1285,63 +918,6 @@ start_greeter (GdmSimpleSlave *slave)
         /* Run the init script. gdmslave suspends until script has terminated */
         gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", GDM_USERNAME);
 
-        slave->priv->greeter_server = gdm_greeter_server_new (display_id);
-        g_signal_connect (slave->priv->greeter_server,
-                          "start-conversation",
-                          G_CALLBACK (on_greeter_start_conversation),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "begin-auto-login",
-                          G_CALLBACK (on_greeter_begin_auto_login),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "begin-verification",
-                          G_CALLBACK (on_greeter_begin_verification),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "begin-verification-for-user",
-                          G_CALLBACK (on_greeter_begin_verification_for_user),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "query-answer",
-                          G_CALLBACK (on_greeter_answer),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "session-selected",
-                          G_CALLBACK (on_greeter_session_selected),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "language-selected",
-                          G_CALLBACK (on_greeter_language_selected),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "user-selected",
-                          G_CALLBACK (on_greeter_user_selected),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "connected",
-                          G_CALLBACK (on_greeter_connected),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "disconnected",
-                          G_CALLBACK (on_greeter_disconnected),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "cancelled",
-                          G_CALLBACK (on_greeter_cancel),
-                          slave);
-        g_signal_connect (slave->priv->greeter_server,
-                          "start-session-when-ready",
-                          G_CALLBACK (on_start_session_when_ready),
-                          slave);
-
-        g_signal_connect (slave->priv->greeter_server,
-                          "start-session-later",
-                          G_CALLBACK (on_start_session_later),
-                          slave);
-
-        gdm_greeter_server_start (slave->priv->greeter_server);
-
         g_debug ("GdmSimpleSlave: Creating greeter on %s %s %s", display_name, display_device, display_hostname);
         slave->priv->greeter = gdm_greeter_session_new (display_name,
                                                         seat_id,
@@ -1349,12 +925,16 @@ start_greeter (GdmSimpleSlave *slave)
                                                         display_hostname,
                                                         display_is_local);
         g_signal_connect (slave->priv->greeter,
+                          "opened",
+                          G_CALLBACK (on_greeter_session_opened),
+                          slave);
+        g_signal_connect (slave->priv->greeter,
                           "started",
-                          G_CALLBACK (on_greeter_session_start),
+                          G_CALLBACK (on_greeter_session_started),
                           slave);
         g_signal_connect (slave->priv->greeter,
                           "stopped",
-                          G_CALLBACK (on_greeter_session_stop),
+                          G_CALLBACK (on_greeter_session_stopped),
                           slave);
         g_signal_connect (slave->priv->greeter,
                           "exited",
@@ -1368,9 +948,6 @@ start_greeter (GdmSimpleSlave *slave)
                       "x11-authority-file", auth_file,
                       NULL);
 
-        address = gdm_greeter_server_get_address (slave->priv->greeter_server);
-        gdm_welcome_session_set_server_address (GDM_WELCOME_SESSION (slave->priv->greeter), address);
-        g_free (address);
         gdm_welcome_session_start (GDM_WELCOME_SESSION (slave->priv->greeter));
 
         g_free (display_id);
@@ -1544,6 +1121,37 @@ gdm_simple_slave_run (GdmSimpleSlave *slave)
 }
 
 static gboolean
+gdm_simple_slave_open_session (GdmSlave   *slave,
+                               char      **address,
+                               GError    **error)
+{
+        GdmSimpleSlave  *self = GDM_SIMPLE_SLAVE (slave);
+        GdmSession      *session;
+
+        if (self->priv->session_is_running) {
+                g_set_error (error,
+                             G_DBUS_ERROR,
+                             G_DBUS_ERROR_ACCESS_DENIED,
+                             _("Greeter access only currently supported"));
+                return FALSE;
+        }
+
+        session = self->priv->session;
+
+        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 gboolean
 gdm_simple_slave_start (GdmSlave *slave)
 {
         GDM_SLAVE_CLASS (gdm_simple_slave_parent_class)->start (slave);
@@ -1566,7 +1174,7 @@ gdm_simple_slave_stop (GdmSlave *slave)
                 stop_greeter (self);
         }
 
-        if (self->priv->session != NULL) {
+        if (self->priv->session_is_running) {
                 char *username;
 
                 /* Run the PostSession script. gdmslave suspends until script
@@ -1647,6 +1255,7 @@ 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;
 
         g_type_class_add_private (klass, sizeof (GdmSimpleSlavePrivate));
 }
@@ -1663,20 +1272,20 @@ gdm_simple_slave_init (GdmSimpleSlave *slave)
 static void
 gdm_simple_slave_finalize (GObject *object)
 {
-        GdmSimpleSlave *simple_slave;
+        GdmSimpleSlave *slave;
 
         g_return_if_fail (object != NULL);
         g_return_if_fail (GDM_IS_SIMPLE_SLAVE (object));
 
-        simple_slave = GDM_SIMPLE_SLAVE (object);
+        slave = GDM_SIMPLE_SLAVE (object);
 
-        g_return_if_fail (simple_slave->priv != NULL);
+        g_return_if_fail (slave->priv != NULL);
 
-        gdm_simple_slave_stop (GDM_SLAVE (simple_slave));
+        gdm_simple_slave_stop (GDM_SLAVE (slave));
 
-        if (simple_slave->priv->greeter_reset_id > 0) {
-                g_source_remove (simple_slave->priv->greeter_reset_id);
-                simple_slave->priv->greeter_reset_id = 0;
+        if (slave->priv->greeter_reset_id > 0) {
+                g_source_remove (slave->priv->greeter_reset_id);
+                slave->priv->greeter_reset_id = 0;
         }
 
         G_OBJECT_CLASS (gdm_simple_slave_parent_class)->finalize (object);
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index 94c8d44..db77dbf 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -76,6 +76,8 @@
 #define GDM_DBUS_NAME              "org.gnome.DisplayManager"
 #define GDM_DBUS_DISPLAY_INTERFACE "org.gnome.DisplayManager.Display"
 
+#define GDM_SLAVE_PATH "/org/gnome/DisplayManager/Slave"
+
 #define MAX_CONNECT_ATTEMPTS 10
 
 struct GdmSlavePrivate
@@ -86,6 +88,8 @@ struct GdmSlavePrivate
 
         Display         *server_display;
 
+        char            *session_id;
+
         /* cached display values */
         char            *display_id;
         char            *display_name;
@@ -102,10 +106,12 @@ struct GdmSlavePrivate
 
         GdmDBusDisplay  *display_proxy;
         GDBusConnection *connection;
+        GdmDBusSlave    *skeleton;
 };
 
 enum {
         PROP_0,
+        PROP_SESSION_ID,
         PROP_DISPLAY_ID,
         PROP_DISPLAY_NAME,
         PROP_DISPLAY_NUMBER,
@@ -130,6 +136,17 @@ G_DEFINE_ABSTRACT_TYPE (GdmSlave, gdm_slave, G_TYPE_OBJECT)
 
 #define CURSOR_WATCH XC_watch
 
+GQuark
+gdm_slave_error_quark (void)
+{
+        static GQuark ret = 0;
+        if (ret == 0) {
+                ret = g_quark_from_static_string ("gdm-slave-error-quark");
+        }
+
+        return ret;
+}
+
 static void
 gdm_slave_whack_temp_auth_file (GdmSlave *slave)
 {
@@ -1690,6 +1707,14 @@ gdm_slave_switch_to_user_session (GdmSlave   *slave,
 }
 
 static void
+_gdm_slave_set_session_id (GdmSlave   *slave,
+                           const char *id)
+{
+        g_free (slave->priv->session_id);
+        slave->priv->session_id = g_strdup (id);
+}
+
+static void
 _gdm_slave_set_display_id (GdmSlave   *slave,
                            const char *id)
 {
@@ -1754,6 +1779,9 @@ gdm_slave_set_property (GObject      *object,
         self = GDM_SLAVE (object);
 
         switch (prop_id) {
+        case PROP_SESSION_ID:
+                _gdm_slave_set_session_id (self, g_value_get_string (value));
+                break;
         case PROP_DISPLAY_ID:
                 _gdm_slave_set_display_id (self, g_value_get_string (value));
                 break;
@@ -1792,6 +1820,9 @@ gdm_slave_get_property (GObject    *object,
         self = GDM_SLAVE (object);
 
         switch (prop_id) {
+        case PROP_SESSION_ID:
+                g_value_set_string (value, self->priv->session_id);
+                break;
         case PROP_DISPLAY_ID:
                 g_value_set_string (value, self->priv->display_id);
                 break;
@@ -1820,6 +1851,76 @@ gdm_slave_get_property (GObject    *object,
 }
 
 static gboolean
+handle_open_session (GdmDBusSlave          *skeleton,
+                     GDBusMethodInvocation *invocation,
+                     GdmSlave              *slave)
+{
+        GError        *error;
+        GdmSlaveClass *slave_class;
+        char          *address;
+
+        slave_class = GDM_SLAVE_GET_CLASS (slave);
+        if (slave_class->open_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,
+                                        &address,
+                                        &error)) {
+                g_dbus_method_invocation_return_gerror (invocation, error);
+                g_error_free (error);
+                return TRUE;
+        }
+
+        gdm_dbus_slave_complete_open_session (skeleton, invocation, address);
+
+        g_free (address);
+
+        return TRUE;
+}
+
+static gboolean
+handle_get_private_connection (GdmDBusSlave          *skeleton,
+                               GDBusMethodInvocation *invocation,
+                               const char            *session_id,
+                               GdmSlave              *slave)
+{
+        GError *local_error;
+        GdmSlaveClass *klass;
+        char *address;
+
+        klass = GDM_SLAVE_GET_CLASS (slave);
+        if (!klass->get_private_connection) {
+                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;
+        }
+
+        local_error = NULL;
+        address = NULL;
+        if (!klass->get_private_connection (slave,
+                                            session_id,
+                                            &address,
+                                            &local_error)) {
+                g_dbus_method_invocation_return_gerror (invocation,
+                                                        local_error);
+                g_error_free (local_error);
+                return TRUE;
+        }
+
+        gdm_dbus_slave_complete_get_private_connection (skeleton, invocation, address);
+
+        g_free (address);
+        return TRUE;
+}
+
+static gboolean
 register_slave (GdmSlave *slave)
 {
         GError *error;
@@ -1834,6 +1935,26 @@ register_slave (GdmSlave *slave)
                 exit (1);
         }
 
+        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),
+                          slave);
+        g_signal_connect (slave->priv->skeleton,
+                          "handle-get-private-connection",
+                          G_CALLBACK (handle_get_private_connection),
+                          slave);
+
+        g_object_bind_property (G_OBJECT (slave),
+                                "session-id",
+                                G_OBJECT (slave->priv->skeleton),
+                                "session-id",
+                                G_BINDING_DEFAULT);
+
+        gdm_slave_export_interface (slave,
+                                    G_DBUS_INTERFACE_SKELETON (slave->priv->skeleton));
+
         return TRUE;
 }
 
@@ -1874,6 +1995,13 @@ gdm_slave_class_init (GdmSlaveClass *klass)
         g_type_class_add_private (klass, sizeof (GdmSlavePrivate));
 
         g_object_class_install_property (object_class,
+                                         PROP_SESSION_ID,
+                                         g_param_spec_string ("session-id",
+                                                              "Session id",
+                                                              "ID of session",
+                                                              NULL,
+                                                              G_PARAM_READWRITE));
+        g_object_class_install_property (object_class,
                                          PROP_DISPLAY_ID,
                                          g_param_spec_string ("display-id",
                                                               "id",
@@ -1972,3 +2100,13 @@ gdm_slave_finalize (GObject *object)
 
         G_OBJECT_CLASS (gdm_slave_parent_class)->finalize (object);
 }
+
+void
+gdm_slave_export_interface (GdmSlave               *slave,
+                            GDBusInterfaceSkeleton *interface)
+{
+        g_dbus_interface_skeleton_export (interface,
+                                          slave->priv->connection,
+                                          GDM_SLAVE_PATH,
+                                          NULL);
+}
diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h
index 128ca3e..a937593 100644
--- a/daemon/gdm-slave.h
+++ b/daemon/gdm-slave.h
@@ -50,10 +50,29 @@ typedef struct
         gboolean (*start) (GdmSlave *slave);
         gboolean (*stop)  (GdmSlave *slave);
 
+        gboolean (*open_session) (GdmSlave    *slave,
+                                  char       **address,
+                                  GError     **error);
+        gboolean (*get_private_connection) (GdmSlave    *slave,
+                                            const char  *session_id,
+                                            char       **address,
+                                            GError     **error);
+
         /* signals */
         void (*stopped) (GdmSlave *slave);
 } GdmSlaveClass;
 
+typedef enum
+{
+        GDM_SLAVE_ERROR_GENERIC,
+        GDM_SLAVE_ERROR_UNSUPPORTED,
+        GDM_SLAVE_ERROR_NOT_OPENED,
+        GDM_SLAVE_ERROR_WRONG_SESSION,
+} GdmSlaveError;
+
+#define GDM_SLAVE_ERROR (gdm_slave_error_quark ())
+
+GQuark              gdm_slave_error_quark            (void);
 GType               gdm_slave_get_type               (void);
 gboolean            gdm_slave_start                  (GdmSlave   *slave);
 gboolean            gdm_slave_stop                   (GdmSlave   *slave);
@@ -85,6 +104,10 @@ gboolean            gdm_slave_run_script             (GdmSlave   *slave,
                                                       const char *username);
 void                gdm_slave_stopped                (GdmSlave   *slave);
 
+void                gdm_slave_export_interface       (GdmSlave               *slave,
+                                                      GDBusInterfaceSkeleton *interface);
+
+
 G_END_DECLS
 
 #endif /* __GDM_SLAVE_H */
diff --git a/daemon/gdm-slave.xml b/daemon/gdm-slave.xml
index 6566594..dbe5930 100644
--- a/daemon/gdm-slave.xml
+++ b/daemon/gdm-slave.xml
@@ -1,5 +1,15 @@
 <!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">
-  </interface>
+    <method name="GetPrivateConnection">
+      <arg name="session_id" type="s" direction="in" />
+      <arg name="address" type="s" direction="out" />
+    </method>
+
+    <method name="OpenSession">
+      <arg name="address" type="s" direction="out" />
+    </method>
+
+    <property name="session_id" type="s" access="read"/>â
+  </interface>â
 </node>
diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
index fbc85a6..ad25639 100644
--- a/daemon/gdm-welcome-session.c
+++ b/daemon/gdm-welcome-session.c
@@ -56,7 +56,7 @@ extern char **environ;
 
 struct GdmWelcomeSessionPrivate
 {
-        GdmSession       *session;
+        GdmSession     *session;
         char           *command;
         GPid            pid;
 
@@ -75,7 +75,6 @@ struct GdmWelcomeSessionPrivate
         char           *dbus_bus_address;
         char           *server_dbus_path;
         char           *server_dbus_interface;
-        char           *server_env_var_name;
 
         char           *server_address;
 };
@@ -91,14 +90,13 @@ enum {
         PROP_USER_NAME,
         PROP_GROUP_NAME,
         PROP_RUNTIME_DIR,
-        PROP_SERVER_ADDRESS,
         PROP_COMMAND,
         PROP_SERVER_DBUS_PATH,
         PROP_SERVER_DBUS_INTERFACE,
-        PROP_SERVER_ENV_VAR_NAME
 };
 
 enum {
+        OPENED,
         STARTED,
         STOPPED,
         EXITED,
@@ -274,11 +272,6 @@ build_welcome_environment (GdmWelcomeSession *welcome_session,
                                      g_strdup ("DBUS_SESSION_BUS_ADDRESS"),
                                      g_strdup (welcome_session->priv->dbus_bus_address));
         }
-        if (welcome_session->priv->server_address != NULL) {
-                g_assert (welcome_session->priv->server_env_var_name != NULL);
-                g_hash_table_insert (hash, g_strdup (welcome_session->priv->server_env_var_name),
-                                     g_strdup (welcome_session->priv->server_address));
-        }
 
         g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (welcome_session->priv->x11_authority_file));
         g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (welcome_session->priv->x11_display_name));
@@ -695,39 +688,15 @@ on_session_setup_complete (GdmSession        *session,
         g_hash_table_destroy (hash);
 
         gdm_session_select_session_type (welcome_session->priv->session, "LoginWindow");
-
-        gdm_session_authenticate (welcome_session->priv->session, service_name);
-}
-
-static void
-on_session_authenticated (GdmSession        *session,
-                          const char        *service_name,
-                          GdmWelcomeSession *welcome_session)
-{
-        gdm_session_authorize (welcome_session->priv->session, service_name);
-}
-
-static void
-on_session_authorized (GdmSession        *session,
-                       const char        *service_name,
-                       GdmWelcomeSession *welcome_session)
-{
-        gdm_session_accredit (welcome_session->priv->session, service_name, FALSE);
-}
-
-static void
-on_session_accredited (GdmSession        *session,
-                       const char        *service_name,
-                       GdmWelcomeSession *welcome_session)
-{
-        gdm_session_open_session (welcome_session->priv->session, service_name);
 }
 
 static void
 on_session_opened (GdmSession        *session,
                    const char        *service_name,
+                   const char        *session_id,
                    GdmWelcomeSession *welcome_session)
 {
+        g_signal_emit (G_OBJECT (welcome_session), signals [OPENED], 0);
         gdm_session_start_session (welcome_session->priv->session, service_name);
 }
 
@@ -839,18 +808,6 @@ gdm_welcome_session_start (GdmWelcomeSession *welcome_session)
                           G_CALLBACK (on_session_setup_complete),
                           welcome_session);
         g_signal_connect (welcome_session->priv->session,
-                          "authenticated",
-                          G_CALLBACK (on_session_authenticated),
-                          welcome_session);
-        g_signal_connect (welcome_session->priv->session,
-                          "authorized",
-                          G_CALLBACK (on_session_authorized),
-                          welcome_session);
-        g_signal_connect (welcome_session->priv->session,
-                          "accredited",
-                          G_CALLBACK (on_session_accredited),
-                          welcome_session);
-        g_signal_connect (welcome_session->priv->session,
                           "session-opened",
                           G_CALLBACK (on_session_opened),
                           welcome_session);
@@ -893,14 +850,10 @@ gdm_welcome_session_stop (GdmWelcomeSession *welcome_session)
         return TRUE;
 }
 
-void
-gdm_welcome_session_set_server_address (GdmWelcomeSession *welcome_session,
-                                        const char        *address)
+GdmSession *
+gdm_welcome_session_get_session (GdmWelcomeSession *welcome_session)
 {
-        g_return_if_fail (GDM_IS_WELCOME_SESSION (welcome_session));
-
-        g_free (welcome_session->priv->server_address);
-        welcome_session->priv->server_address = g_strdup (address);
+        return welcome_session->priv->session;
 }
 
 static void
@@ -999,14 +952,6 @@ _gdm_welcome_session_set_command (GdmWelcomeSession *welcome_session,
 }
 
 static void
-_gdm_welcome_session_set_server_env_var_name (GdmWelcomeSession *welcome_session,
-                                              const char        *name)
-{
-        g_free (welcome_session->priv->server_env_var_name);
-        welcome_session->priv->server_env_var_name = g_strdup (name);
-}
-
-static void
 gdm_welcome_session_set_property (GObject      *object,
                                   guint         prop_id,
                                   const GValue *value,
@@ -1044,18 +989,12 @@ gdm_welcome_session_set_property (GObject      *object,
         case PROP_RUNTIME_DIR:
                 _gdm_welcome_session_set_runtime_dir (self, g_value_get_string (value));
                 break;
-        case PROP_SERVER_ADDRESS:
-                gdm_welcome_session_set_server_address (self, g_value_get_string (value));
-                break;
         case PROP_SERVER_DBUS_PATH:
                 _gdm_welcome_session_set_server_dbus_path (self, g_value_get_string (value));
                 break;
         case PROP_SERVER_DBUS_INTERFACE:
                 _gdm_welcome_session_set_server_dbus_interface (self, g_value_get_string (value));
                 break;
-        case PROP_SERVER_ENV_VAR_NAME:
-                _gdm_welcome_session_set_server_env_var_name (self, g_value_get_string (value));
-                break;
         case PROP_COMMAND:
                 _gdm_welcome_session_set_command (self, g_value_get_string (value));
                 break;
@@ -1103,18 +1042,12 @@ gdm_welcome_session_get_property (GObject    *object,
         case PROP_RUNTIME_DIR:
                 g_value_set_string (value, self->priv->runtime_dir);
                 break;
-        case PROP_SERVER_ADDRESS:
-                g_value_set_string (value, self->priv->server_address);
-                break;
         case PROP_SERVER_DBUS_PATH:
                 g_value_set_string (value, self->priv->server_dbus_path);
                 break;
         case PROP_SERVER_DBUS_INTERFACE:
                 g_value_set_string (value, self->priv->server_dbus_interface);
                 break;
-        case PROP_SERVER_ENV_VAR_NAME:
-                g_value_set_string (value, self->priv->server_env_var_name);
-                break;
         case PROP_COMMAND:
                 g_value_set_string (value, self->priv->command);
                 break;
@@ -1199,13 +1132,6 @@ gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass)
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
         g_object_class_install_property (object_class,
-                                         PROP_SERVER_ADDRESS,
-                                         g_param_spec_string ("server-address",
-                                                              "server address",
-                                                              "server address",
-                                                              NULL,
-                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-        g_object_class_install_property (object_class,
                                          PROP_SERVER_DBUS_PATH,
                                          g_param_spec_string ("server-dbus-path",
                                                               "server dbus path",
@@ -1220,19 +1146,22 @@ gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass)
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
         g_object_class_install_property (object_class,
-                                         PROP_SERVER_ENV_VAR_NAME,
-                                         g_param_spec_string ("server-env-var-name",
-                                                              "server env var name",
-                                                              "server env var name",
-                                                              NULL,
-                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-        g_object_class_install_property (object_class,
                                          PROP_COMMAND,
                                          g_param_spec_string ("command",
                                                               "command",
                                                               "command",
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        signals [OPENED] =
+                g_signal_new ("opened",
+                              G_OBJECT_CLASS_TYPE (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GdmWelcomeSessionClass, opened),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
         signals [STARTED] =
                 g_signal_new ("started",
                               G_OBJECT_CLASS_TYPE (object_class),
@@ -1317,7 +1246,6 @@ gdm_welcome_session_finalize (GObject *object)
         g_free (welcome_session->priv->server_address);
         g_free (welcome_session->priv->server_dbus_path);
         g_free (welcome_session->priv->server_dbus_interface);
-        g_free (welcome_session->priv->server_env_var_name);
         g_free (welcome_session->priv->dbus_bus_address);
 
         G_OBJECT_CLASS (gdm_welcome_session_parent_class)->finalize (object);
diff --git a/daemon/gdm-welcome-session.h b/daemon/gdm-welcome-session.h
index b6d49d3..290aca5 100644
--- a/daemon/gdm-welcome-session.h
+++ b/daemon/gdm-welcome-session.h
@@ -23,6 +23,7 @@
 #define __GDM_WELCOME_SESSION_H
 
 #include <glib-object.h>
+#include "gdm-session.h"
 
 G_BEGIN_DECLS
 
@@ -51,6 +52,7 @@ typedef struct
 
 
         /* signals */
+        void (* opened)            (GdmWelcomeSession  *welcome_session);
         void (* started)           (GdmWelcomeSession  *welcome_session);
         void (* stopped)           (GdmWelcomeSession  *welcome_session);
         void (* exited)            (GdmWelcomeSession  *welcome_session,
@@ -61,10 +63,9 @@ typedef struct
 
 GType                 gdm_welcome_session_get_type           (void);
 
-void                  gdm_welcome_session_set_server_address (GdmWelcomeSession *welcome_session,
-                                                              const char        *server_address);
 gboolean              gdm_welcome_session_start              (GdmWelcomeSession *welcome_session);
 gboolean              gdm_welcome_session_stop               (GdmWelcomeSession *welcome_session);
+GdmSession *          gdm_welcome_session_get_session        (GdmWelcomeSession *welcome_session);
 
 G_END_DECLS
 
diff --git a/daemon/gdm-xdmcp-chooser-slave.c b/daemon/gdm-xdmcp-chooser-slave.c
index 45d04ad..0fc3815 100644
--- a/daemon/gdm-xdmcp-chooser-slave.c
+++ b/daemon/gdm-xdmcp-chooser-slave.c
@@ -42,10 +42,10 @@
 #include "gdm-xdmcp-chooser-slave-glue.h"
 
 #include "gdm-server.h"
-#include "gdm-chooser-server.h"
 #include "gdm-chooser-session.h"
 #include "gdm-settings-direct.h"
 #include "gdm-settings-keys.h"
+#include "gdm-session.h"
 
 #define GDM_XDMCP_CHOOSER_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_XDMCP_CHOOSER_SLAVE, GdmXdmcpChooserSlavePrivate))
 
@@ -64,7 +64,6 @@ struct GdmXdmcpChooserSlavePrivate
 
         guint              connection_attempts;
 
-        GdmChooserServer  *chooser_server;
         GdmChooserSession *chooser;
 
         GdmDBusXdmcpChooserSlave *skeleton;
@@ -121,7 +120,7 @@ on_chooser_session_died (GdmChooserSession    *chooser,
 }
 
 static void
-on_chooser_hostname_selected (GdmChooserServer     *chooser_server,
+on_chooser_hostname_selected (GdmSession           *session,
                               const char           *name,
                               GdmXdmcpChooserSlave *slave)
 {
@@ -133,7 +132,7 @@ on_chooser_hostname_selected (GdmChooserServer     *chooser_server,
 }
 
 static void
-on_chooser_disconnected (GdmChooserServer     *chooser_server,
+on_chooser_disconnected (GdmSession           *session,
                          GdmXdmcpChooserSlave *slave)
 {
         g_debug ("GdmXdmcpChooserSlave: Chooser disconnected");
@@ -145,7 +144,7 @@ on_chooser_disconnected (GdmChooserServer     *chooser_server,
 }
 
 static void
-on_chooser_connected (GdmChooserServer     *chooser_server,
+on_chooser_connected (GdmSession           *session,
                       GdmXdmcpChooserSlave *slave)
 {
         g_debug ("GdmXdmcpChooserSlave: Chooser connected");
@@ -166,8 +165,8 @@ run_chooser (GdmXdmcpChooserSlave *slave)
         char          *display_device;
         char          *display_hostname;
         char          *auth_file;
-        char          *address;
         gboolean       res;
+        GdmSession    *session;
 
         g_debug ("GdmXdmcpChooserSlave: Running chooser");
 
@@ -200,23 +199,6 @@ run_chooser (GdmXdmcpChooserSlave *slave)
         /* Run the init script. gdmslave suspends until script has terminated */
         gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", GDM_USERNAME);
 
-        slave->priv->chooser_server = gdm_chooser_server_new (display_id);
-        g_signal_connect (slave->priv->chooser_server,
-                          "hostname-selected",
-                          G_CALLBACK (on_chooser_hostname_selected),
-                          slave);
-        g_signal_connect (slave->priv->chooser_server,
-                          "disconnected",
-                          G_CALLBACK (on_chooser_disconnected),
-                          slave);
-        g_signal_connect (slave->priv->chooser_server,
-                          "connected",
-                          G_CALLBACK (on_chooser_connected),
-                          slave);
-        gdm_chooser_server_start (slave->priv->chooser_server);
-
-        address = gdm_chooser_server_get_address (slave->priv->chooser_server);
-
         g_debug ("GdmXdmcpChooserSlave: Creating chooser on %s %s %s", display_name, display_device, display_hostname);
         slave->priv->chooser = gdm_chooser_session_new (display_name,
                                                         display_device,
@@ -240,7 +222,25 @@ run_chooser (GdmXdmcpChooserSlave *slave)
         g_object_set (slave->priv->chooser,
                       "x11-authority-file", auth_file,
                       NULL);
-        gdm_welcome_session_set_server_address (GDM_WELCOME_SESSION (slave->priv->chooser), address);
+
+        session = gdm_welcome_session_get_session (GDM_WELCOME_SESSION (slave->priv->chooser));
+
+        g_signal_connect (session,
+                          "hostname-selected",
+                          G_CALLBACK (on_chooser_hostname_selected),
+                          slave);
+        g_signal_connect (session,
+                          "client-disconnected",
+                          G_CALLBACK (on_chooser_disconnected),
+                          slave);
+        g_signal_connect (session,
+                          "disconnected",
+                          G_CALLBACK (on_chooser_disconnected),
+                          slave);
+        g_signal_connect (session,
+                          "client-connected",
+                          G_CALLBACK (on_chooser_connected),
+                          slave);
         gdm_welcome_session_start (GDM_WELCOME_SESSION (slave->priv->chooser));
 
         g_free (display_id);
@@ -317,6 +317,29 @@ gdm_xdmcp_chooser_slave_stop (GdmSlave *slave)
         return TRUE;
 }
 
+static gboolean
+gdm_xdmcp_chooser_slave_open_session (GdmSlave   *slave,
+                                      char      **address,
+                                      GError    **error)
+{
+        GdmXdmcpChooserSlave *self = GDM_XDMCP_CHOOSER_SLAVE (slave);
+        GdmSession      *session;
+
+        session = gdm_welcome_session_get_session (GDM_WELCOME_SESSION (self->priv->chooser));
+
+        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,
@@ -347,6 +370,7 @@ 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;
 
         signals [HOSTNAME_SELECTED] =
                 g_signal_new ("hostname-selected",
diff --git a/daemon/test-session.c b/daemon/test-session.c
index 31be1ec..85e13d8 100644
--- a/daemon/test-session.c
+++ b/daemon/test-session.c
@@ -86,7 +86,7 @@ on_session_authorized (GdmSession *session,
                        gpointer    data)
 {
         g_debug ("Session authorized");
-        gdm_session_accredit (session, service_name, FALSE);
+        gdm_session_accredit (session, service_name);
 }
 
 static void
@@ -246,7 +246,8 @@ main (int   argc,
         g_type_init ();
 
         do {
-                session = gdm_session_new ("/org/gnome/DisplayManager/Displays/1",
+                g_debug ("creating instance of GdmSession object...");
+                session = gdm_session_new ("/org/gnome/DisplayManager/Displays/_0",
                                            ":0",
                                            g_get_host_name (),
                                            ttyname (STDIN_FILENO),
diff --git a/data/gdm.conf.in b/data/gdm.conf.in
index 23e5fcc..1bd6fc7 100644
--- a/data/gdm.conf.in
+++ b/data/gdm.conf.in
@@ -24,6 +24,11 @@
     <allow send_destination="org.gnome.DisplayManager"
            send_interface="org.freedesktop.DBus.Introspectable"/>
 
+    <!-- root can request private connections to everyone
+         (as long as they implement the interface, that is) -->
+    <allow send_interface="org.gnome.DisplayManager.Slave"
+	   send_member="GetPrivateConnection"/>
+
   </policy>
 
   <policy context="default">
@@ -43,6 +48,8 @@
           send_interface="org.freedesktop.DBus.Properties" />
     <allow send_destination="org.gnome.DisplayManager"
            send_interface="org.freedesktop.DBus.Introspectable"/>
+    <allow send_destination="org.gnome.DisplayManager"
+	   send_interface="org.freedesktop.DBus.ObjectManager"/>
 
     <allow send_destination="org.gnome.DisplayManager"
            send_interface="org.gnome.DisplayManager.Display"
@@ -62,15 +69,13 @@
     <allow send_destination="org.gnome.DisplayManager"
            send_interface="org.gnome.DisplayManager.Display"
            send_member="IsLocal"/>
+    <allow send_destination="org.gnome.DisplayManager"
+	   send_interface="org.gnome.DisplayManager.Display"
+	   send_member="ConnectToSlave"/>
 
     <allow send_destination="org.gnome.DisplayManager"
            send_interface="org.gnome.DisplayManager.LocalDisplayFactory"
            send_member="CreateTransientDisplay"/>
-
-    <allow send_destination="org.gnome.DisplayManager"
-           send_interface="org.gnome.DisplayManager.Manager"
-           send_member="GetDisplays"/>
-
   </policy>
 
   <policy user="@GDM_USERNAME@">



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