[gdm/wip/slave-connection: 10/37] daemon: drop display-id arg to GdmSessionDirect



commit 8bcdc3da8c5fb789c58eeb33d078e8f3f3f42a6c
Author: Ray Strode <rstrode redhat com>
Date:   Mon Jul 9 21:17:25 2012 -0400

    daemon: drop display-id arg to GdmSessionDirect
    
    It's not used anywhere, and so there's no reason to pass it along.

 daemon/Makefile.am           |   11 +-
 daemon/gdm-session-direct.c  | 3105 ------------------------------------
 daemon/gdm-session-direct.h  |   66 -
 daemon/gdm-session.c         | 3581 +++++++++++++++++++++++++++++++++++++-----
 daemon/gdm-session.h         |  197 ++--
 daemon/gdm-simple-slave.c    |   38 +-
 daemon/gdm-welcome-session.c |   14 +-
 daemon/test-session.c        |   31 +-
 po/POTFILES.in               |    2 -
 9 files changed, 3327 insertions(+), 3718 deletions(-)
---
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 7bb68f2..6116ebe 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -67,9 +67,6 @@ test_session_SOURCES = 		\
 	test-session.c	 	\
 	gdm-session.c		\
 	gdm-session.h		\
-	gdm-session-private.h	\
-	gdm-session-direct.c	\
-	gdm-session-direct.h	\
 	gdm-session-record.c	\
 	gdm-session-record.h	\
 	gdm-session-worker-job.c\
@@ -107,9 +104,6 @@ gdm_simple_slave_SOURCES = 		\
 	gdm-server.h			\
 	gdm-session.c			\
 	gdm-session.h			\
-	gdm-session-private.h		\
-	gdm-session-direct.c		\
-	gdm-session-direct.h		\
 	gdm-session-record.c		\
 	gdm-session-record.h		\
 	gdm-session-worker-job.c	\
@@ -141,9 +135,6 @@ gdm_xdmcp_chooser_slave_SOURCES = 		\
 	gdm-chooser-server.h			\
 	gdm-session.c				\
 	gdm-session.h				\
-	gdm-session-direct.c			\
-	gdm-session-direct.h			\
-	gdm-session-private.h			\
 	gdm-session-record.c			\
 	gdm-session-record.h			\
 	gdm-session-worker-job.c		\
@@ -286,7 +277,7 @@ EXTRA_DIST = 				\
 	gdm-slave.xml			\
 	gdm-simple-slave.xml		\
 	gdm-xdmcp-chooser-slave.xml	\
-	gdm-session-direct.xml		\
+	gdm-session.xml			\
 	gdm-manager.xml			\
 	gdm-display.xml			\
 	gdm-xdmcp-greeter-display.xml	\
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index b91ec63..044a8a7 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -1,11 +1,12 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
+ * Copyright (C) 2006 Ray Strode <rstrode redhat com>
  * Copyright (C) 2007 William Jon McCann <mccann jhu edu>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,19 +15,114 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
  */
 
 #include "config.h"
 
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <locale.h>
+
 #include <glib.h>
 #include <glib/gi18n.h>
+#include <glib/gstdio.h>
 #include <glib-object.h>
 
+#ifdef HAVE_LIBXKLAVIER
+#include <libxklavier/xklavier.h>
+#include <X11/Xlib.h> /* for Display */
+#endif
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
 #include "gdm-session.h"
 #include "gdm-session-private.h"
 
+#include "gdm-session-record.h"
+#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"
+
+#ifndef GDM_SESSION_DEFAULT_PATH
+#define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin"
+#endif
+
+typedef struct
+{
+        GdmSession            *session;
+        GdmSessionWorkerJob   *job;
+        GPid                   worker_pid;
+        char                  *service_name;
+        DBusConnection        *worker_connection;
+        DBusMessage           *message_pending_reply;
+        guint32                is_stopping : 1;
+} GdmSessionConversation;
+
+struct _GdmSessionPrivate
+{
+        /* per open scope */
+        char                *selected_program;
+        char                *selected_session;
+        char                *saved_session;
+        char                *selected_language;
+        char                *saved_language;
+        char                *selected_user;
+        char                *user_x11_authority_file;
+
+        GHashTable          *conversations;
+
+        GdmSessionConversation *session_conversation;
+
+        GList               *pending_connections;
+
+        GPid                 session_pid;
+
+        /* object lifetime scope */
+        char                *display_id;
+        char                *display_name;
+        char                *display_hostname;
+        char                *display_device;
+        char                *display_seat_id;
+        char                *display_x11_authority_file;
+        gboolean             display_is_local;
+
+        char                *fallback_session_name;
+
+        DBusServer          *server;
+        char                *server_address;
+        GHashTable          *environment;
+        DBusGConnection     *connection;
+};
+
+enum {
+        PROP_0,
+        PROP_DISPLAY_NAME,
+        PROP_DISPLAY_HOSTNAME,
+        PROP_DISPLAY_IS_LOCAL,
+        PROP_DISPLAY_DEVICE,
+        PROP_DISPLAY_SEAT_ID,
+        PROP_DISPLAY_X11_AUTHORITY_FILE,
+        PROP_USER_X11_AUTHORITY_FILE,
+};
+
 enum {
         CONVERSATION_STARTED = 0,
         CONVERSATION_STOPPED,
@@ -57,211 +153,3082 @@ enum {
         LAST_SIGNAL
 };
 
-static guint signals [LAST_SIGNAL] = { 0, };
+static guint signals [LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (GdmSession,
+               gdm_session,
+               G_TYPE_OBJECT);
+
+static gboolean
+send_dbus_message (GdmSessionConversation *conversation,
+                   DBusMessage            *message)
+{
+        gboolean is_connected;
+        gboolean sent;
+
+        g_return_val_if_fail (message != NULL, FALSE);
+
+        if (conversation->worker_connection == NULL) {
+                g_warning ("There is no valid connection");
+                return FALSE;
+        }
+
+        is_connected = dbus_connection_get_is_connected (conversation->worker_connection);
+        if (! is_connected) {
+                g_warning ("Not connected!");
+                return FALSE;
+        }
+
+        sent = dbus_connection_send (conversation->worker_connection, message, NULL);
+
+        return sent;
+}
+
+static void
+send_dbus_string_signal (GdmSessionConversation *conversation,
+                         const char             *name,
+                         const char             *text)
+{
+        DBusMessage    *message;
+        DBusMessageIter iter;
+
+        g_return_if_fail (conversation != NULL);
+
+        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+                                           GDM_SESSION_DBUS_INTERFACE,
+                                           name);
+
+        dbus_message_iter_init_append (message, &iter);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text);
+
+        if (! send_dbus_message (conversation, message)) {
+                g_debug ("GdmSession: Could not send %s signal",
+                         name ? name : "(null)");
+        }
+
+        dbus_message_unref (message);
+}
+
+static void
+send_dbus_void_signal (GdmSessionConversation *conversation,
+                       const char             *name)
+{
+        DBusMessage *message;
+
+        g_return_if_fail (conversation != NULL);
+
+        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+                                           GDM_SESSION_DBUS_INTERFACE,
+                                           name);
+
+        if (! send_dbus_message (conversation, message)) {
+                g_debug ("GdmSession: Could not send %s signal", name);
+        }
+
+        dbus_message_unref (message);
+}
+
+static void
+emit_service_unavailable (GdmSession   *self,
+                          const char   *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SERVICE_UNAVAILABLE], 0, service_name);
+}
+
+static void
+emit_setup_complete (GdmSession   *self,
+                     const char   *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SETUP_COMPLETE], 0, service_name);
+}
+
+static void
+emit_setup_failed (GdmSession   *self,
+                   const char   *service_name,
+                   const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SETUP_FAILED], 0, service_name, text);
+}
+
+static void
+emit_reset_complete (GdmSession   *self)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [RESET_COMPLETE], 0);
+}
+
+static void
+emit_reset_failed (GdmSession   *self,
+                   const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [RESET_FAILED], 0, text);
+}
+
+static void
+emit_authenticated (GdmSession   *self,
+                    const char   *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [AUTHENTICATED], 0, service_name);
+}
+
+static void
+emit_authentication_failed (GdmSession   *self,
+                            const char   *service_name,
+                            const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [AUTHENTICATION_FAILED], 0, service_name, text);
+}
+
+static void
+emit_authorized (GdmSession   *self,
+                 const char   *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [AUTHORIZED], 0, service_name);
+}
+
+static void
+emit_authorization_failed (GdmSession   *self,
+                           const char   *service_name,
+                           const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [AUTHORIZATION_FAILED], 0, service_name, text);
+}
+
+static void
+emit_accredited (GdmSession   *self,
+                 const char   *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [ACCREDITED], 0, service_name);
+}
+
+static void
+emit_accreditation_failed (GdmSession   *self,
+                           const char   *service_name,
+                           const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [ACCREDITATION_FAILED], 0, service_name, text);
+}
+
+static void
+emit_info_query (GdmSession   *self,
+                 const char   *service_name,
+                 const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [INFO_QUERY], 0, service_name, text);
+}
+
+static void
+emit_secret_info_query (GdmSession   *self,
+                        const char   *service_name,
+                        const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SECRET_INFO_QUERY], 0, service_name, text);
+}
+
+static void
+emit_info (GdmSession   *self,
+           const char   *service_name,
+           const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [INFO], 0, service_name, text);
+}
+
+static void
+emit_problem (GdmSession   *self,
+              const char   *service_name,
+              const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [PROBLEM], 0, service_name, text);
+}
+
+static void
+emit_session_opened (GdmSession   *self,
+                     const char   *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SESSION_OPENED], 0, service_name);
+}
+
+static void
+emit_session_open_failed (GdmSession   *self,
+                          const char   *service_name,
+                          const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SESSION_OPEN_FAILED], 0, service_name, text);
+}
+
+static void
+emit_session_started (GdmSession   *self,
+                      const char   *service_name,
+                      int           pid)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SESSION_STARTED], 0, service_name, pid);
+}
+
+static void
+emit_session_start_failed (GdmSession   *self,
+                           const char   *service_name,
+                           const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SESSION_START_FAILED], 0, service_name, text);
+}
+
+static void
+emit_session_exited (GdmSession   *self,
+                     int           exit_code)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SESSION_EXITED], 0, exit_code);
+}
+
+static void
+emit_session_died (GdmSession   *self,
+                   int           signal_number)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SESSION_DIED], 0, signal_number);
+}
+
+static void
+emit_conversation_started (GdmSession   *self,
+                           const char   *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [CONVERSATION_STARTED], 0, service_name);
+}
+
+static void
+emit_conversation_stopped (GdmSession   *self,
+                           const char   *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [CONVERSATION_STOPPED], 0, service_name);
+}
+
+static void
+emit_default_language_name_changed (GdmSession   *self,
+                                    const char   *language_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [DEFAULT_LANGUAGE_NAME_CHANGED], 0, language_name);
+}
+
+static void
+emit_default_session_name_changed (GdmSession   *self,
+                                   const char   *session_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [DEFAULT_SESSION_NAME_CHANGED], 0, session_name);
+}
+
+static void
+emit_selected_user_changed (GdmSession   *self,
+                            const char   *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_signal_emit (self, signals [SELECTED_USER_CHANGED], 0, text);
+}
+
+static GdmSessionConversation *
+find_conversation_by_name (GdmSession *self,
+                           const char *service_name)
+{
+        GdmSessionConversation *conversation;
+
+        conversation = g_hash_table_lookup (self->priv->conversations, service_name);
+
+        if (conversation == NULL) {
+                g_warning ("Tried to look up non-existent conversation %s", service_name);
+        }
+
+        return conversation;
+}
+
+static void
+on_authentication_failed (GdmSession *self,
+                          const char *service_name,
+                          const char *message)
+{
+        GdmSessionConversation *conversation;
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation != NULL) {
+                gdm_session_record_failed (conversation->worker_pid,
+                                           self->priv->selected_user,
+                                           self->priv->display_hostname,
+                                           self->priv->display_name,
+                                           self->priv->display_device);
+        }
+}
+
+static void
+on_session_started (GdmSession *self,
+                    const char *service_name)
+{
+        GdmSessionConversation *conversation;
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation != NULL) {
+                gdm_session_record_login (conversation->worker_pid,
+                                          self->priv->selected_user,
+                                          self->priv->display_hostname,
+                                          self->priv->display_name,
+                                          self->priv->display_device);
+        }
+}
+
+static void
+on_session_start_failed (GdmSession *self,
+                         const char *service_name,
+                         const char *message)
+{
+        GdmSessionConversation *conversation;
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation != NULL) {
+                gdm_session_record_login (conversation->worker_pid,
+                                          self->priv->selected_user,
+                                          self->priv->display_hostname,
+                                          self->priv->display_name,
+                                          self->priv->display_device);
+        }
+}
+
+static void
+on_session_exited (GdmSession *self,
+                   int        exit_code)
+{
+
+        gdm_session_record_logout (self->priv->session_pid,
+                                   self->priv->selected_user,
+                                   self->priv->display_hostname,
+                                   self->priv->display_name,
+                                   self->priv->display_device);
+}
+
+
+static DBusHandlerResult
+gdm_session_handle_service_unavailable (GdmSession             *self,
+                                        GdmSessionConversation *conversation,
+                                        DBusMessage            *message)
+{
+        DBusMessage *reply;
+
+        g_debug ("GdmSession: Emitting 'service-unavailable' signal");
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        emit_service_unavailable (self, conversation->service_name);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_setup_complete (GdmSession             *self,
+                                   GdmSessionConversation *conversation,
+                                   DBusMessage            *message)
+{
+        DBusMessage *reply;
+
+        g_debug ("GdmSession: Emitting 'setup-complete' signal");
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        emit_setup_complete (self, conversation->service_name);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_setup_failed (GdmSession             *self,
+                                 GdmSessionConversation *conversation,
+                                 DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'setup-failed' signal");
+
+        emit_setup_failed (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+
+static DBusHandlerResult
+gdm_session_handle_reset_complete (GdmSession             *self,
+                                   GdmSessionConversation *conversation,
+                                   DBusMessage            *message)
+{
+        DBusMessage *reply;
+
+        g_debug ("GdmSession: Emitting 'reset-complete' signal");
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        emit_reset_complete (self);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_reset_failed (GdmSession             *self,
+                                 GdmSessionConversation *conversation,
+                                 DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'reset-failed' signal");
+
+        emit_reset_failed (self, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_authenticated (GdmSession             *self,
+                                  GdmSessionConversation *conversation,
+                                  DBusMessage            *message)
+{
+        DBusMessage *reply;
+
+        g_debug ("GdmSession: Emitting 'authenticated' signal");
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        emit_authenticated (self, conversation->service_name);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_authentication_failed (GdmSession             *self,
+                                          GdmSessionConversation *conversation,
+                                          DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'authentication-failed' signal");
+
+        emit_authentication_failed (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_authorized (GdmSession             *self,
+                               GdmSessionConversation *conversation,
+                               DBusMessage            *message)
+{
+        DBusMessage *reply;
+
+        g_debug ("GdmSession: Emitting 'authorized' signal");
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        emit_authorized (self, conversation->service_name);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_authorization_failed (GdmSession             *self,
+                                         GdmSessionConversation *conversation,
+                                         DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'authorization-failed' signal");
+
+        emit_authorization_failed (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_accredited (GdmSession             *self,
+                               GdmSessionConversation *conversation,
+                               DBusMessage            *message)
+{
+        DBusMessage *reply;
+
+        g_debug ("GdmSession: Emitting 'accredited' signal");
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        emit_accredited (self, conversation->service_name);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_accreditation_failed (GdmSession             *self,
+                                         GdmSessionConversation *conversation,
+                                         DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'accreditation-failed' signal");
+
+        emit_accreditation_failed (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static const char **
+get_system_session_dirs (void)
+{
+        static const char *search_dirs[] = {
+                "/etc/X11/sessions/",
+                DMCONFDIR "/Sessions/",
+                DATADIR "/xsessions/",
+                DATADIR "/gdm/BuiltInSessions/",
+                NULL
+        };
+
+        return search_dirs;
+}
+
+static gboolean
+is_prog_in_path (const char *prog)
+{
+        char    *f;
+        gboolean ret;
+
+        f = g_find_program_in_path (prog);
+        ret = (f != NULL);
+        g_free (f);
+        return ret;
+}
+
+static gboolean
+get_session_command_for_file (const char *file,
+                              char      **command)
+{
+        GKeyFile   *key_file;
+        GError     *error;
+        char       *exec;
+        gboolean    ret;
+        gboolean    res;
+
+        exec = NULL;
+        ret = FALSE;
+        if (command != NULL) {
+                *command = NULL;
+        }
+
+        key_file = g_key_file_new ();
+
+        g_debug ("GdmSession: looking for session file '%s'", file);
+
+        error = NULL;
+        res = g_key_file_load_from_dirs (key_file,
+                                         file,
+                                         get_system_session_dirs (),
+                                         NULL,
+                                         G_KEY_FILE_NONE,
+                                         &error);
+        if (! res) {
+                g_debug ("GdmSession: File '%s' not found: %s", file, error->message);
+                g_error_free (error);
+                if (command != NULL) {
+                        *command = NULL;
+                }
+                goto out;
+        }
+
+        error = NULL;
+        res = g_key_file_get_boolean (key_file,
+                                      G_KEY_FILE_DESKTOP_GROUP,
+                                      G_KEY_FILE_DESKTOP_KEY_HIDDEN,
+                                      &error);
+        if (error == NULL && res) {
+                g_debug ("GdmSession: Session %s is marked as hidden", file);
+                goto out;
+        }
+
+        exec = g_key_file_get_string (key_file,
+                                      G_KEY_FILE_DESKTOP_GROUP,
+                                      G_KEY_FILE_DESKTOP_KEY_TRY_EXEC,
+                                      NULL);
+        if (exec != NULL) {
+                res = is_prog_in_path (exec);
+                g_free (exec);
+                exec = NULL;
+
+                if (! res) {
+                        g_debug ("GdmSession: Command not found: %s",
+                                 G_KEY_FILE_DESKTOP_KEY_TRY_EXEC);
+                        goto out;
+                }
+        }
+
+        error = NULL;
+        exec = g_key_file_get_string (key_file,
+                                      G_KEY_FILE_DESKTOP_GROUP,
+                                      G_KEY_FILE_DESKTOP_KEY_EXEC,
+                                      &error);
+        if (error != NULL) {
+                g_debug ("GdmSession: %s key not found: %s",
+                         G_KEY_FILE_DESKTOP_KEY_EXEC,
+                         error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        if (command != NULL) {
+                *command = g_strdup (exec);
+        }
+        ret = TRUE;
+
+out:
+        g_free (exec);
+
+        return ret;
+}
+
+static gboolean
+get_session_command_for_name (const char *name,
+                              char      **command)
+{
+        gboolean res;
+        char    *filename;
+
+        filename = g_strdup_printf ("%s.desktop", name);
+        res = get_session_command_for_file (filename, command);
+        g_free (filename);
+
+        /*
+         * The GDM Xsession script honors "custom" as a valid session.  If the
+         * session is one of these, no file is needed, then just run the
+         * command as "custom".
+         */
+        if (!res && strcmp (name, GDM_CUSTOM_SESSION) == 0) {
+                g_debug ("No custom desktop file, but accepting it anyway.");
+                if (command != NULL) {
+                        *command = g_strdup (GDM_CUSTOM_SESSION);
+                }
+                res = TRUE;
+        }
+
+        return res;
+}
+
+static const char *
+get_default_language_name (GdmSession *self)
+{
+    if (self->priv->saved_language != NULL) {
+                return self->priv->saved_language;
+    }
+
+    return setlocale (LC_MESSAGES, NULL);
+}
+
+static const char *
+get_fallback_session_name (GdmSession *self)
+{
+        const char    **search_dirs;
+        int             i;
+        char           *name;
+        GSequence      *sessions;
+        GSequenceIter  *session;
+
+        if (self->priv->fallback_session_name != NULL) {
+                /* verify that the cached version still exists */
+                if (get_session_command_for_name (self->priv->fallback_session_name, NULL)) {
+                        goto out;
+                }
+        }
+
+        name = g_strdup ("gnome");
+        if (get_session_command_for_name (name, NULL)) {
+                g_free (self->priv->fallback_session_name);
+                self->priv->fallback_session_name = name;
+                goto out;
+        }
+        g_free (name);
+
+        sessions = g_sequence_new (g_free);
+
+        search_dirs = get_system_session_dirs ();
+        for (i = 0; search_dirs[i] != NULL; i++) {
+                GDir       *dir;
+                const char *base_name;
+
+                dir = g_dir_open (search_dirs[i], 0, NULL);
+
+                if (dir == NULL) {
+                        continue;
+                }
+
+                do {
+                        base_name = g_dir_read_name (dir);
+
+                        if (base_name == NULL) {
+                                break;
+                        }
+
+                        if (!g_str_has_suffix (base_name, ".desktop")) {
+                                continue;
+                        }
+
+                        if (get_session_command_for_file (base_name, NULL)) {
+
+                                g_sequence_insert_sorted (sessions, g_strdup (base_name), (GCompareDataFunc) g_strcmp0, NULL);
+                        }
+                } while (base_name != NULL);
+
+                g_dir_close (dir);
+        }
+
+        name = NULL;
+        session = g_sequence_get_begin_iter (sessions);
+        do {
+               if (g_sequence_get (session)) {
+                       char *base_name;
+
+                       g_free (name);
+                       base_name = g_sequence_get (session);
+                       name = g_strndup (base_name,
+                                         strlen (base_name) -
+                                         strlen (".desktop"));
+
+                       break;
+               }
+               session = g_sequence_iter_next (session);
+        } while (!g_sequence_iter_is_end (session));
+
+        g_free (self->priv->fallback_session_name);
+        self->priv->fallback_session_name = name;
+
+        g_sequence_free (sessions);
+
+ out:
+        return self->priv->fallback_session_name;
+}
+
+static const char *
+get_default_session_name (GdmSession *self)
+{
+        if (self->priv->saved_session != NULL) {
+                return self->priv->saved_session;
+        }
+
+        return get_fallback_session_name (self);
+}
+
+static void
+gdm_session_defaults_changed (GdmSession *self)
+{
+        emit_default_language_name_changed (self,
+                                            get_default_language_name (self));
+        emit_default_session_name_changed (self,
+                                           get_default_session_name (self));
+}
+
+void
+gdm_session_select_user (GdmSession *self,
+                         const char *text)
+{
+
+        g_debug ("GdmSession: Setting user: '%s'", text);
+
+        g_free (self->priv->selected_user);
+        self->priv->selected_user = g_strdup (text);
+
+        g_free (self->priv->saved_session);
+        self->priv->saved_session = NULL;
+
+        g_free (self->priv->saved_language);
+        self->priv->saved_language = NULL;
+}
+
+static DBusHandlerResult
+gdm_session_handle_username_changed (GdmSession             *self,
+                                     GdmSessionConversation *conversation,
+                                     DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        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);
+
+        emit_selected_user_changed (self, self->priv->selected_user);
+
+        gdm_session_defaults_changed (self);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+cancel_pending_query (GdmSessionConversation *conversation)
+{
+        DBusMessage *reply;
+
+        if (conversation->message_pending_reply == NULL) {
+                return;
+        }
+
+        g_debug ("GdmSession: Cancelling pending query");
+
+        reply = dbus_message_new_error (conversation->message_pending_reply,
+                                        GDM_SESSION_DBUS_ERROR_CANCEL,
+                                        "Operation cancelled");
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_connection_flush (conversation->worker_connection);
+
+        dbus_message_unref (reply);
+        dbus_message_unref (conversation->message_pending_reply);
+        conversation->message_pending_reply = NULL;
+}
+
+static void
+answer_pending_query (GdmSessionConversation *conversation,
+                      const char             *answer)
+{
+        DBusMessage    *reply;
+        DBusMessageIter iter;
+
+        reply = dbus_message_new_method_return (conversation->message_pending_reply);
+        dbus_message_iter_init_append (reply, &iter);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &answer);
+
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        dbus_message_unref (conversation->message_pending_reply);
+        conversation->message_pending_reply = NULL;
+}
+
+static void
+set_pending_query (GdmSessionConversation *conversation,
+                   DBusMessage            *message)
+{
+        g_assert (conversation->message_pending_reply == NULL);
+
+        conversation->message_pending_reply = dbus_message_ref (message);
+}
+
+static DBusHandlerResult
+gdm_session_handle_info_query (GdmSession             *self,
+                               GdmSessionConversation *conversation,
+                               DBusMessage            *message)
+{
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        set_pending_query (conversation, message);
+
+        g_debug ("GdmSession: Emitting 'info-query' signal");
+        emit_info_query (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_secret_info_query (GdmSession             *self,
+                                      GdmSessionConversation *conversation,
+                                      DBusMessage            *message)
+{
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        set_pending_query (conversation, message);
+
+        g_debug ("GdmSession: Emitting 'secret-info-query' signal");
+        emit_secret_info_query (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_info (GdmSession             *self,
+                         GdmSessionConversation *conversation,
+                         DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'info' signal");
+        emit_info (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_cancel_pending_query (GdmSession             *self,
+                                         GdmSessionConversation *conversation,
+                                         DBusMessage            *message)
+{
+        DBusMessage *reply;
+
+        g_debug ("GdmSession: worker cancelling pending query");
+
+        cancel_pending_query (conversation);
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_problem (GdmSession             *self,
+                            GdmSessionConversation *conversation,
+                            DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'problem' signal");
+        emit_problem (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_session_opened (GdmSession             *self,
+                                   GdmSessionConversation *conversation,
+                                   DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+
+        g_debug ("GdmSession: Handling SessionOpened");
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error, DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        g_debug ("GdmSession: Emitting 'session-opened' signal");
+
+        emit_session_opened (self, conversation->service_name);
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_open_failed (GdmSession             *self,
+                                GdmSessionConversation *conversation,
+                                DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'session-open-failed' signal");
+        emit_session_open_failed (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_session_started (GdmSession             *self,
+                                    GdmSessionConversation *conversation,
+                                    DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        int          pid;
+
+        pid = 0;
+
+        g_debug ("GdmSession: Handling SessionStarted");
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_INT32, &pid,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'session-started' signal with pid '%d'",
+                 pid);
+
+        self->priv->session_pid = pid;
+        self->priv->session_conversation = conversation;
+
+        emit_session_started (self, conversation->service_name, pid);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_start_failed (GdmSession             *self,
+                                 GdmSessionConversation *conversation,
+                                 DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *text;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &text,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'session-start-failed' signal");
+        emit_session_start_failed (self, conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_session_exited (GdmSession             *self,
+                                   GdmSessionConversation *conversation,
+                                   DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        int          code;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_INT32, &code,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'session-exited' signal with exit code '%d'",
+                 code);
+
+        self->priv->session_conversation = NULL;
+        emit_session_exited (self, code);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_session_died (GdmSession             *self,
+                                 GdmSessionConversation *conversation,
+                                 DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        int          code;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_INT32, &code,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        g_debug ("GdmSession: Emitting 'session-died' signal with signal number '%d'",
+                 code);
+
+        self->priv->session_conversation = NULL;
+        emit_session_died (self, code);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_saved_language_name_read (GdmSession             *self,
+                                             GdmSessionConversation *conversation,
+                                             DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *language_name;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &language_name,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        if (strcmp (language_name,
+                    get_default_language_name (self)) != 0) {
+                g_free (self->priv->saved_language);
+                self->priv->saved_language = g_strdup (language_name);
+
+                emit_default_language_name_changed (self, language_name);
+        }
+
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+gdm_session_handle_saved_session_name_read (GdmSession             *self,
+                                            GdmSessionConversation *conversation,
+                                            DBusMessage            *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        const char  *session_name;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &session_name,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (conversation->worker_connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        if (! get_session_command_for_name (session_name, NULL)) {
+                /* ignore sessions that don't exist */
+                g_debug ("GdmSession: not using invalid .dmrc session: %s", session_name);
+                g_free (self->priv->saved_session);
+                self->priv->saved_session = NULL;
+                goto out;
+        }
+
+        if (strcmp (session_name,
+                    get_default_session_name (self)) != 0) {
+                g_free (self->priv->saved_session);
+                self->priv->saved_session = g_strdup (session_name);
+
+                emit_default_session_name_changed (self, session_name);
+        }
+ out:
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+session_worker_message (DBusConnection *connection,
+                        DBusMessage    *message,
+                        void           *user_data)
+{
+        GdmSessionConversation *conversation = user_data;
+        GdmSession *session;
+
+        session = conversation->session;
+
+        if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "InfoQuery")) {
+                return gdm_session_handle_info_query (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SecretInfoQuery")) {
+                return gdm_session_handle_secret_info_query (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Info")) {
+                return gdm_session_handle_info (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Problem")) {
+                return gdm_session_handle_problem (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "CancelPendingQuery")) {
+                return gdm_session_handle_cancel_pending_query (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ServiceUnavailable")) {
+                return gdm_session_handle_service_unavailable (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupComplete")) {
+                return gdm_session_handle_setup_complete (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupFailed")) {
+                return gdm_session_handle_setup_failed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetComplete")) {
+                return gdm_session_handle_reset_complete (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetFailed")) {
+                return gdm_session_handle_reset_failed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authenticated")) {
+                return gdm_session_handle_authenticated (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthenticationFailed")) {
+                return gdm_session_handle_authentication_failed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authorized")) {
+                return gdm_session_handle_authorized (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthorizationFailed")) {
+                return gdm_session_handle_authorization_failed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Accredited")) {
+                return gdm_session_handle_accredited (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AccreditationFailed")) {
+                return gdm_session_handle_accreditation_failed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) {
+                return gdm_session_handle_username_changed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionOpened")) {
+                return gdm_session_handle_session_opened (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "OpenFailed")) {
+                return gdm_session_handle_open_failed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) {
+                return gdm_session_handle_session_started (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartFailed")) {
+                return gdm_session_handle_start_failed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionExited")) {
+                return gdm_session_handle_session_exited (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionDied")) {
+                return gdm_session_handle_session_died (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLanguageNameRead")) {
+                return gdm_session_handle_saved_language_name_read (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedSessionNameRead")) {
+                return gdm_session_handle_saved_session_name_read (session, conversation, message);
+        }
+
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult
+do_introspect (DBusConnection *connection,
+               DBusMessage    *message)
+{
+        DBusMessage *reply;
+        GString     *xml;
+        char        *xml_string;
+
+        g_debug ("GdmSession: Do introspect");
+
+        /* standard header */
+        xml = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
+                            "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\";>\n"
+                            "<node>\n"
+                            "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+                            "    <method name=\"Introspect\">\n"
+                            "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
+                            "    </method>\n"
+                            "  </interface>\n");
+
+        /* interface */
+        xml = g_string_append (xml,
+                               "  <interface name=\"org.gnome.DisplayManager.Session\">\n"
+                               "    <method name=\"SetupComplete\">\n"
+                               "    </method>\n"
+                               "    <method name=\"SetupFailed\">\n"
+                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"ResetComplete\">\n"
+                               "    </method>\n"
+                               "    <method name=\"ResetFailed\">\n"
+                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"Authenticated\">\n"
+                               "    </method>\n"
+                               "    <method name=\"AuthenticationFailed\">\n"
+                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"Authorized\">\n"
+                               "    </method>\n"
+                               "    <method name=\"AuthorizationFailed\">\n"
+                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"Accredited\">\n"
+                               "    </method>\n"
+                               "    <method name=\"AccreditationFailed\">\n"
+                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"CancelPendingQuery\">\n"
+                               "    </method>\n"
+                               "    <method name=\"InfoQuery\">\n"
+                               "      <arg name=\"query\" direction=\"in\" type=\"s\"/>\n"
+                               "      <arg name=\"answer\" direction=\"out\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"SecretInfoQuery\">\n"
+                               "      <arg name=\"query\" direction=\"in\" type=\"s\"/>\n"
+                               "      <arg name=\"answer\" direction=\"out\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"Info\">\n"
+                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"Problem\">\n"
+                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"UsernameChanged\">\n"
+                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"StartFailed\">\n"
+                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"SessionStarted\">\n"
+                               "      <arg name=\"pid\" direction=\"in\" type=\"i\"/>\n"
+                               "      <arg name=\"environment\" direction=\"in\" type=\"as\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"SessionExited\">\n"
+                               "      <arg name=\"code\" direction=\"in\" type=\"i\"/>\n"
+                               "    </method>\n"
+                               "    <method name=\"SessionDied\">\n"
+                               "      <arg name=\"signal\" direction=\"in\" type=\"i\"/>\n"
+                               "    </method>\n"
+                               "    <signal name=\"Reset\">\n"
+                               "    </signal>\n"
+                               "    <signal name=\"Setup\">\n"
+                               "      <arg name=\"service_name\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
+                               "      <arg name=\"display_device\" type=\"s\"/>\n"
+                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
+                               "      <arg name=\"hostname\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
+                               "    </signal>\n"
+                               "    <signal name=\"SetupForUser\">\n"
+                               "      <arg name=\"service_name\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
+                               "      <arg name=\"display_device\" type=\"s\"/>\n"
+                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
+                               "      <arg name=\"hostname\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
+                               "      <arg name=\"username\" type=\"s\"/>\n"
+                               "    </signal>\n"
+                               "    <signal name=\"SetupForProgram\">\n"
+                               "      <arg name=\"service_name\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
+                               "      <arg name=\"display_device\" type=\"s\"/>\n"
+                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
+                               "      <arg name=\"hostname\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
+                               "      <arg name=\"log_file\" type=\"s\"/>\n"
+                               "    </signal>\n"
+                               "    <signal name=\"Authenticate\">\n"
+                               "    </signal>\n"
+                               "    <signal name=\"Authorize\">\n"
+                               "    </signal>\n"
+                               "    <signal name=\"EstablishCredentials\">\n"
+                               "    </signal>\n"
+                               "    <signal name=\"RefreshCredentials\">\n"
+                               "    </signal>\n"
+                               "    <signal name=\"SetEnvironmentVariable\">\n"
+                               "      <arg name=\"name\" type=\"s\"/>\n"
+                               "      <arg name=\"value\" type=\"s\"/>\n"
+                               "    </signal>\n"
+                               "    <signal name=\"SetLanguageName\">\n"
+                               "      <arg name=\"language_name\" type=\"s\"/>\n"
+                               "    </signal>\n"
+                               "    <signal name=\"SetSessionName\">\n"
+                               "      <arg name=\"session_name\" type=\"s\"/>\n"
+                               "    </signal>\n"
+                               "    <signal name=\"SetSessionType\">\n"
+                               "      <arg name=\"session_type\" type=\"s\"/>\n"
+                               "    </signal>\n"
+                               "    <signal name=\"StartProgram\">\n"
+                               "      <arg name=\"command\" type=\"s\"/>\n"
+                               "    </signal>\n"
+                               "  </interface>\n");
+
+        reply = dbus_message_new_method_return (message);
+
+        xml = g_string_append (xml, "</node>\n");
+        xml_string = g_string_free (xml, FALSE);
+
+        dbus_message_append_args (reply,
+                                  DBUS_TYPE_STRING, &xml_string,
+                                  DBUS_TYPE_INVALID);
+
+        g_free (xml_string);
+
+        if (reply == NULL) {
+                g_error ("No memory");
+        }
+
+        if (! dbus_connection_send (connection, reply, NULL)) {
+                g_error ("No memory");
+        }
+
+        dbus_message_unref (reply);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+session_message_handler (DBusConnection  *connection,
+                         DBusMessage     *message,
+                         void            *user_data)
+{
+        const char *dbus_destination = dbus_message_get_destination (message);
+        const char *dbus_path        = dbus_message_get_path (message);
+        const char *dbus_interface   = dbus_message_get_interface (message);
+        const char *dbus_member      = dbus_message_get_member (message);
+
+        g_debug ("session_message_handler: destination=%s obj_path=%s interface=%s method=%s",
+                 dbus_destination ? dbus_destination : "(null)",
+                 dbus_path        ? dbus_path        : "(null)",
+                 dbus_interface   ? dbus_interface   : "(null)",
+                 dbus_member      ? dbus_member      : "(null)");
+
+        if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
+                DBusMessage *reply;
+
+                reply = dbus_message_new_method_return (message);
+
+                if (reply == NULL) {
+                        g_error ("No memory");
+                }
+
+                if (! dbus_connection_send (connection, reply, NULL)) {
+                        g_error ("No memory");
+                }
+
+                dbus_message_unref (reply);
+
+                return DBUS_HANDLER_RESULT_HANDLED;
+        } else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
+                   strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
+
+                g_debug ("GdmSession: Disconnected");
+
+                /*dbus_connection_unref (connection);*/
+
+                return DBUS_HANDLER_RESULT_HANDLED;
+        } else if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+                return do_introspect (connection, message);
+        } else {
+                return session_worker_message (connection, message, user_data);
+        }
+
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/* Note: Use abstract sockets like dbus does by default on Linux. Abstract
+ * sockets are only available on Linux.
+ */
+static char *
+generate_address (void)
+{
+        char *path;
+#if defined (__linux__)
+        int   i;
+        char  tmp[9];
+
+        for (i = 0; i < 8; i++) {
+                if (g_random_int_range (0, 2) == 0) {
+                        tmp[i] = g_random_int_range ('a', 'z' + 1);
+                } else {
+                        tmp[i] = g_random_int_range ('A', 'Z' + 1);
+                }
+        }
+        tmp[8] = '\0';
+
+        path = g_strdup_printf ("unix:abstract=/tmp/gdm-session-%s", tmp);
+#else
+        path = g_strdup ("unix:tmpdir=/tmp");
+#endif
+
+        return path;
+}
+
+static void
+session_unregister_handler (DBusConnection  *connection,
+                            void            *user_data)
+{
+        g_debug ("session_unregister_handler");
+}
+
+static GdmSessionConversation *
+find_conversation_by_pid (GdmSession *self,
+                          GPid        pid)
+{
+        GHashTableIter iter;
+        gpointer key, value;
+
+        g_hash_table_iter_init (&iter, self->priv->conversations);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GdmSessionConversation *conversation;
+
+                conversation = (GdmSessionConversation *) value;
+
+                if (conversation->worker_pid == pid) {
+                        return conversation;
+                }
+        }
+
+        return NULL;
+}
+
+static dbus_bool_t
+allow_user_function (DBusConnection *connection,
+                     unsigned long   uid,
+                     void           *data)
+{
+        if (0 == uid) {
+                return TRUE;
+        }
+
+        g_debug ("GdmSession: User not allowed");
+
+        return FALSE;
+}
+
+static gboolean
+register_worker (GdmSession *self,
+                 DBusConnection   *connection)
+{
+        GdmSessionConversation *conversation;
+        DBusObjectPathVTable vtable = { &session_unregister_handler,
+                                        &session_message_handler,
+                                        NULL, NULL, NULL, NULL };
+        GList *connection_node;
+        gulong pid;
+
+        g_debug ("GdmSession: Authenticating new connection");
+
+        connection_node = g_list_find (self->priv->pending_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_node);
+
+        if (!dbus_connection_get_unix_process_id (connection, &pid)) {
+                g_warning ("GdmSession: Unable to read pid on new worker connection");
+                dbus_connection_unref (connection);
+                return FALSE;
+        }
+
+        conversation = find_conversation_by_pid (self, (GPid) pid);
+
+        if (conversation == NULL) {
+                g_warning ("GdmSession: New worker connection is from unknown source");
+                dbus_connection_unref (connection);
+                return FALSE;
+        }
+
+        conversation->worker_connection = connection;
+
+        g_debug ("GdmSession: worker connection is %p", connection);
+
+        dbus_connection_register_object_path (connection,
+                                              GDM_SESSION_DBUS_PATH,
+                                              &vtable,
+                                              conversation);
+
+        g_debug ("GdmSession: Emitting conversation-started signal");
+        emit_conversation_started (self, conversation->service_name);
+
+        g_debug ("GdmSession: Conversation started");
+
+        return TRUE;
+}
+
+static DBusHandlerResult
+on_message (DBusConnection *connection,
+            DBusMessage    *message,
+            void           *user_data)
+{
+        GdmSession *self = GDM_SESSION (user_data);
+
+        g_debug ("GdmSession: got message");
+
+        if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Hello")) {
+                DBusMessage *reply;
+
+                if (register_worker (self, connection)) {
+                        reply = dbus_message_new_method_return (message);
+                } else {
+                        reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "");
+                }
+
+                dbus_connection_send (connection, reply, NULL);
+                return DBUS_HANDLER_RESULT_HANDLED;
+        }
+
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+handle_connection (DBusServer      *server,
+                   DBusConnection  *new_connection,
+                   void            *user_data)
+{
+        GdmSession *self = GDM_SESSION (user_data);
+        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,
+                                dbus_connection_ref (new_connection));
+        dbus_connection_setup_with_g_main (new_connection, NULL);
+        dbus_connection_set_exit_on_disconnect (new_connection, FALSE);
+
+        dbus_connection_set_unix_user_function (new_connection,
+                                                allow_user_function,
+                                                self,
+                                                NULL);
+        dbus_connection_add_filter (new_connection, on_message, self, NULL);
+}
+
+static gboolean
+setup_server (GdmSession *self)
+{
+        DBusError   error;
+        gboolean    ret;
+        char       *address;
+        const char *auth_mechanisms[] = {"EXTERNAL", NULL};
+
+        ret = FALSE;
+
+        g_debug ("GdmSession: Creating D-Bus server for session");
+
+        address = generate_address ();
+
+        dbus_error_init (&error);
+        self->priv->server = dbus_server_listen (address, &error);
+        g_free (address);
+
+        if (self->priv->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 */
+                goto out;
+        }
+
+        dbus_server_setup_with_g_main (self->priv->server, NULL);
+        dbus_server_set_auth_mechanisms (self->priv->server, auth_mechanisms);
+        dbus_server_set_new_connection_function (self->priv->server,
+                                                 handle_connection,
+                                                 self,
+                                                 NULL);
+        ret = TRUE;
+
+        g_free (self->priv->server_address);
+        self->priv->server_address = dbus_server_get_address (self->priv->server);
+
+        g_debug ("GdmSession: D-Bus server listening on %s", self->priv->server_address);
+
+ out:
+
+        return ret;
+}
+
+static void
+free_conversation (GdmSessionConversation *conversation)
+{
+        if (conversation->job != NULL) {
+                g_warning ("Freeing conversation '%s' with active job", conversation->service_name);
+        }
+
+        g_free (conversation->service_name);
+        g_free (conversation);
+}
+
+static void
+gdm_session_init (GdmSession *self)
+{
+        self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                                  GDM_TYPE_SESSION,
+                                                  GdmSessionPrivate);
+
+        g_signal_connect (self,
+                          "authentication-failed",
+                          G_CALLBACK (on_authentication_failed),
+                          NULL);
+        g_signal_connect (self,
+                          "session-started",
+                          G_CALLBACK (on_session_started),
+                          NULL);
+        g_signal_connect (self,
+                          "session-start-failed",
+                          G_CALLBACK (on_session_start_failed),
+                          NULL);
+        g_signal_connect (self,
+                          "session-exited",
+                          G_CALLBACK (on_session_exited),
+                          NULL);
+
+        self->priv->conversations = g_hash_table_new_full (g_str_hash,
+                                                           g_str_equal,
+                                                           (GDestroyNotify) g_free,
+                                                           (GDestroyNotify)
+                                                           free_conversation);
+        self->priv->environment = g_hash_table_new_full (g_str_hash,
+                                                         g_str_equal,
+                                                         (GDestroyNotify) g_free,
+                                                         (GDestroyNotify) g_free);
+
+        setup_server (self);
+
+}
+
+static void
+worker_started (GdmSessionWorkerJob    *job,
+                GdmSessionConversation *conversation)
+{
+        g_debug ("GdmSession: Worker job started");
+}
+
+static void
+worker_exited (GdmSessionWorkerJob    *job,
+               int                     code,
+               GdmSessionConversation *conversation)
+{
+
+        g_debug ("GdmSession: Worker job exited: %d", code);
+
+        g_object_ref (conversation->job);
+        if (conversation->session->priv->session_conversation == conversation) {
+                emit_session_exited (GDM_SESSION (conversation->session), code);
+        }
+
+        g_hash_table_steal (conversation->session->priv->conversations, conversation->service_name);
+
+        g_debug ("GdmSession: Emitting conversation-stopped signal");
+        emit_conversation_stopped (GDM_SESSION (conversation->session),
+                                   conversation->service_name);
+        g_object_unref (conversation->job);
+
+        if (conversation->is_stopping) {
+                g_object_unref (conversation->job);
+                conversation->job = NULL;
+        }
+
+        free_conversation (conversation);
+}
+
+static void
+worker_died (GdmSessionWorkerJob    *job,
+             int                     signum,
+             GdmSessionConversation *conversation)
+{
+
+        g_debug ("GdmSession: Worker job died: %d", signum);
+
+        g_object_ref (conversation->job);
+        if (conversation->session->priv->session_conversation == conversation) {
+                emit_session_died (GDM_SESSION (conversation->session), signum);
+        }
+
+        g_hash_table_steal (conversation->session->priv->conversations, conversation->service_name);
+
+        g_debug ("GdmSession: Emitting conversation-stopped signal");
+        emit_conversation_stopped (GDM_SESSION (conversation->session),
+                                   conversation->service_name);
+        g_object_unref (conversation->job);
+
+        if (conversation->is_stopping) {
+                g_object_unref (conversation->job);
+                conversation->job = NULL;
+        }
+
+        free_conversation (conversation);
+}
+
+static GdmSessionConversation *
+start_conversation (GdmSession *self,
+                    const char *service_name)
+{
+        GdmSessionConversation *conversation;
+        char                   *job_name;
+
+        conversation = g_new0 (GdmSessionConversation, 1);
+        conversation->session = self;
+        conversation->service_name = g_strdup (service_name);
+        conversation->worker_pid = -1;
+        conversation->job = gdm_session_worker_job_new ();
+        gdm_session_worker_job_set_server_address (conversation->job, self->priv->server_address);
+        g_signal_connect (conversation->job,
+                          "started",
+                          G_CALLBACK (worker_started),
+                          conversation);
+        g_signal_connect (conversation->job,
+                          "exited",
+                          G_CALLBACK (worker_exited),
+                          conversation);
+        g_signal_connect (conversation->job,
+                          "died",
+                          G_CALLBACK (worker_died),
+                          conversation);
+
+        job_name = g_strdup_printf ("gdm-session-worker [pam/%s]", service_name);
+        if (!gdm_session_worker_job_start (conversation->job, job_name)) {
+                g_object_unref (conversation->job);
+                g_free (conversation->service_name);
+                g_free (conversation);
+                g_free (job_name);
+                return NULL;
+        }
+
+        g_free (job_name);
+
+        conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job);
+
+        return conversation;
+}
+
+static void
+stop_conversation (GdmSessionConversation *conversation)
+{
+        GdmSession *session;
+
+        session = conversation->session;
+
+        if (conversation->worker_connection != NULL) {
+                dbus_connection_remove_filter (conversation->worker_connection, on_message, session);
+
+                dbus_connection_close (conversation->worker_connection);
+                conversation->worker_connection = NULL;
+        }
+
+        conversation->is_stopping = TRUE;
+        gdm_session_worker_job_stop (conversation->job);
+}
+
+static void
+stop_conversation_now (GdmSessionConversation *conversation)
+{
+        GdmSession *session;
+
+        session = conversation->session;
+
+        if (conversation->worker_connection != NULL) {
+                dbus_connection_remove_filter (conversation->worker_connection, on_message, session);
+
+                dbus_connection_close (conversation->worker_connection);
+                conversation->worker_connection = NULL;
+        }
+
+        gdm_session_worker_job_stop_now (conversation->job);
+        g_object_unref (conversation->job);
+        conversation->job = NULL;
+}
+
+void
+gdm_session_start_conversation (GdmSession *self,
+                                const char *service_name)
+{
+        GdmSessionConversation *conversation;
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        conversation = g_hash_table_lookup (self->priv->conversations,
+                                            service_name);
+
+        if (conversation != NULL) {
+                if (!conversation->is_stopping) {
+                        g_warning ("GdmSession: conversation %s started more than once", service_name);
+                        return;
+                }
+                g_debug ("GdmSession: stopping old conversation %s", service_name);
+                gdm_session_worker_job_stop_now (conversation->job);
+                g_object_unref (conversation->job);
+                conversation->job = NULL;
+        }
+
+        g_debug ("GdmSession: starting conversation %s", service_name);
+
+        conversation = start_conversation (self, service_name);
+
+        g_hash_table_insert (self->priv->conversations,
+                             g_strdup (service_name), conversation);
+}
+
+void
+gdm_session_stop_conversation (GdmSession *self,
+                               const char *service_name)
+{
+        GdmSessionConversation *conversation;
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_debug ("GdmSession: stopping conversation %s", service_name);
+
+        conversation = find_conversation_by_name (self, service_name);
+
+        if (conversation != NULL) {
+                stop_conversation (conversation);
+        }
+}
+
+static void
+send_setup (GdmSession *self,
+            const char *service_name)
+{
+        DBusMessage    *message;
+        DBusMessageIter iter;
+        const char     *display_name;
+        const char     *display_device;
+        const char     *display_seat_id;
+        const char     *display_hostname;
+        const char     *display_x11_authority_file;
+        GdmSessionConversation *conversation;
+
+        g_assert (service_name != NULL);
+
+        if (self->priv->display_name != NULL) {
+                display_name = self->priv->display_name;
+        } else {
+                display_name = "";
+        }
+        if (self->priv->display_hostname != NULL) {
+                display_hostname = self->priv->display_hostname;
+        } else {
+                display_hostname = "";
+        }
+        if (self->priv->display_device != NULL) {
+                display_device = self->priv->display_device;
+        } else {
+                display_device = "";
+        }
+        if (self->priv->display_seat_id != NULL) {
+                display_seat_id = self->priv->display_seat_id;
+        } else {
+                display_seat_id = "";
+        }
+        if (self->priv->display_x11_authority_file != NULL) {
+                display_x11_authority_file = self->priv->display_x11_authority_file;
+        } else {
+                display_x11_authority_file = "";
+        }
+
+        g_debug ("GdmSession: Beginning setup");
+
+        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+                                           GDM_SESSION_DBUS_INTERFACE,
+                                           "Setup");
+
+        dbus_message_iter_init_append (message, &iter);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation != NULL && ! send_dbus_message (conversation, message)) {
+                g_debug ("GdmSession: Could not send %s signal", "Setup");
+        }
+
+        dbus_message_unref (message);
+}
+
+static void
+send_setup_for_user (GdmSession *self,
+                     const char *service_name)
+{
+        DBusMessage    *message;
+        DBusMessageIter iter;
+        const char     *display_name;
+        const char     *display_device;
+        const char     *display_seat_id;
+        const char     *display_hostname;
+        const char     *display_x11_authority_file;
+        const char     *selected_user;
+        GdmSessionConversation *conversation;
+
+        g_assert (service_name != NULL);
+
+        if (self->priv->display_name != NULL) {
+                display_name = self->priv->display_name;
+        } else {
+                display_name = "";
+        }
+        if (self->priv->display_hostname != NULL) {
+                display_hostname = self->priv->display_hostname;
+        } else {
+                display_hostname = "";
+        }
+        if (self->priv->display_device != NULL) {
+                display_device = self->priv->display_device;
+        } else {
+                display_device = "";
+        }
+        if (self->priv->display_seat_id != NULL) {
+                display_seat_id = self->priv->display_seat_id;
+        } else {
+                display_seat_id = "";
+        }
+        if (self->priv->display_x11_authority_file != NULL) {
+                display_x11_authority_file = self->priv->display_x11_authority_file;
+        } else {
+                display_x11_authority_file = "";
+        }
+        if (self->priv->selected_user != NULL) {
+                selected_user = self->priv->selected_user;
+        } else {
+                selected_user = "";
+        }
+
+        g_debug ("GdmSession: Beginning setup for user %s", self->priv->selected_user);
+
+        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+                                           GDM_SESSION_DBUS_INTERFACE,
+                                           "SetupForUser");
+
+        dbus_message_iter_init_append (message, &iter);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &selected_user);
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation != NULL && ! send_dbus_message (conversation, message)) {
+                g_debug ("GdmSession: Could not send %s signal", "SetupForUser");
+        }
+
+        dbus_message_unref (message);
+}
+
+static void
+send_setup_for_program (GdmSession *self,
+                        const char *service_name,
+                        const char *log_file)
+{
+        DBusMessage    *message;
+        DBusMessageIter iter;
+        const char     *display_name;
+        const char     *display_device;
+        const char     *display_seat_id;
+        const char     *display_hostname;
+        const char     *display_x11_authority_file;
+        GdmSessionConversation *conversation;
+
+        g_assert (service_name != NULL);
+
+        if (self->priv->display_name != NULL) {
+                display_name = self->priv->display_name;
+        } else {
+                display_name = "";
+        }
+        if (self->priv->display_hostname != NULL) {
+                display_hostname = self->priv->display_hostname;
+        } else {
+                display_hostname = "";
+        }
+        if (self->priv->display_device != NULL) {
+                display_device = self->priv->display_device;
+        } else {
+                display_device = "";
+        }
+        if (self->priv->display_seat_id != NULL) {
+                display_seat_id = self->priv->display_seat_id;
+        } else {
+                display_seat_id = "";
+        }
+        if (self->priv->display_x11_authority_file != NULL) {
+                display_x11_authority_file = self->priv->display_x11_authority_file;
+        } else {
+                display_x11_authority_file = "";
+        }
+
+        g_debug ("GdmSession: Beginning setup for session for program with log '%s'", log_file);
+
+        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+                                           GDM_SESSION_DBUS_INTERFACE,
+                                           "SetupForProgram");
+
+        dbus_message_iter_init_append (message, &iter);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &log_file);
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation != NULL && ! send_dbus_message (conversation, message)) {
+                g_debug ("GdmSession: Could not send %s signal", "SetupForProgram");
+        }
+
+        dbus_message_unref (message);
+}
+
+void
+gdm_session_setup (GdmSession *self,
+                   const char *service_name)
+{
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        send_setup (self, service_name);
+        gdm_session_defaults_changed (self);
+}
+
+void
+gdm_session_setup_for_user (GdmSession *self,
+                            const char *service_name,
+                            const char *username)
+{
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+        g_return_if_fail (username != NULL);
+
+        gdm_session_select_user (self, username);
+
+        send_setup_for_user (self, service_name);
+        gdm_session_defaults_changed (self);
+}
+
+void
+gdm_session_setup_for_program (GdmSession *self,
+                               const char *service_name,
+                               const char *log_file)
+{
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        send_setup_for_program (self, service_name, log_file);
+}
+
+void
+gdm_session_authenticate (GdmSession *self,
+                          const char *service_name)
+{
+        GdmSessionConversation *conversation;
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation != NULL) {
+                send_dbus_void_signal (conversation, "Authenticate");
+        }
+}
+
+void
+gdm_session_authorize (GdmSession *self,
+                       const char *service_name)
+{
+        GdmSessionConversation *conversation;
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation != NULL) {
+                send_dbus_void_signal (conversation, "Authorize");
+        }
+}
+
+void
+gdm_session_accredit (GdmSession *self,
+                      const char *service_name,
+                      int         cred_flag)
+{
+        GdmSessionConversation *conversation;
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        conversation = find_conversation_by_name (self, service_name);
+        if (conversation == NULL) {
+                return;
+        }
+
+        switch (cred_flag) {
+        case GDM_SESSION_CRED_ESTABLISH:
+                send_dbus_void_signal (conversation, "EstablishCredentials");
+                break;
+        case GDM_SESSION_CRED_REFRESH:
+                send_dbus_void_signal (conversation, "RefreshCredentials");
+                break;
+        default:
+                g_assert_not_reached ();
+        }
+}
+
+static void
+send_environment_variable (const char             *key,
+                           const char             *value,
+                           GdmSessionConversation *conversation)
+{
+        DBusMessage    *message;
+        DBusMessageIter iter;
+
+        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+                                           GDM_SESSION_DBUS_INTERFACE,
+                                           "SetEnvironmentVariable");
+
+        dbus_message_iter_init_append (message, &iter);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
+
+        if (! send_dbus_message (conversation, message)) {
+                g_debug ("GdmSession: Could not send %s signal", "SetEnvironmentVariable");
+        }
+
+        dbus_message_unref (message);
+}
+
+static void
+send_environment (GdmSession       *self,
+                  GdmSessionConversation *conversation)
+{
+
+        g_hash_table_foreach (self->priv->environment,
+                              (GHFunc) send_environment_variable,
+                              conversation);
+}
+
+static const char *
+get_language_name (GdmSession *self)
+{
+        if (self->priv->selected_language != NULL) {
+                return self->priv->selected_language;
+        }
+
+        return get_default_language_name (self);
+}
+
+static const char *
+get_session_name (GdmSession *self)
+{
+        /* FIXME: test the session names before we use them? */
+
+        if (self->priv->selected_session != NULL) {
+                return self->priv->selected_session;
+        }
+
+        return get_default_session_name (self);
+}
+
+static char *
+get_session_command (GdmSession *self)
+{
+        gboolean    res;
+        char       *command;
+        const char *session_name;
+
+        session_name = get_session_name (self);
+
+        command = NULL;
+        res = get_session_command_for_name (session_name, &command);
+        if (! res) {
+                g_critical ("Cannot find a command for specified session: %s", session_name);
+                exit (1);
+        }
+
+        return command;
+}
+
+void
+gdm_session_set_environment_variable (GdmSession *self,
+                                      const char *key,
+                                      const char *value)
+{
+
+        g_return_if_fail (key != NULL);
+        g_return_if_fail (value != NULL);
+
+        g_hash_table_replace (self->priv->environment,
+                              g_strdup (key),
+                              g_strdup (value));
+}
+
+static void
+setup_session_environment (GdmSession *self)
+{
+        const char *locale;
+
+        gdm_session_set_environment_variable (self,
+                                              "GDMSESSION",
+                                              get_session_name (self));
+        gdm_session_set_environment_variable (self,
+                                              "DESKTOP_SESSION",
+                                              get_session_name (self));
+
+        locale = get_language_name (self);
+
+        if (locale != NULL && locale[0] != '\0') {
+                gdm_session_set_environment_variable (self,
+                                                      "LANG",
+                                                      locale);
+                gdm_session_set_environment_variable (self,
+                                                      "GDM_LANG",
+                                                      locale);
+        }
+
+        gdm_session_set_environment_variable (self,
+                                              "DISPLAY",
+                                              self->priv->display_name);
+
+        if (self->priv->user_x11_authority_file != NULL) {
+                gdm_session_set_environment_variable (self,
+                                                      "XAUTHORITY",
+                                                      self->priv->user_x11_authority_file);
+        }
+
+        if (g_getenv ("WINDOWPATH") != NULL) {
+                gdm_session_set_environment_variable (self,
+                                                      "WINDOWPATH",
+                                                      g_getenv ("WINDOWPATH"));
+        }
+
+
+        /* FIXME: We do this here and in the session worker.  We should consolidate
+         * somehow.
+         */
+        gdm_session_set_environment_variable (self,
+                                              "PATH",
+                                              strcmp (BINDIR, "/usr/bin") == 0?
+                                              GDM_SESSION_DEFAULT_PATH :
+                                              BINDIR ":" GDM_SESSION_DEFAULT_PATH);
+
+}
+
+void
+gdm_session_open_session (GdmSession *self,
+                          const char *service_name)
+{
+        GdmSessionConversation *conversation;
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        conversation = find_conversation_by_name (self, service_name);
 
-static void gdm_session_class_init (gpointer g_iface);
+        send_dbus_string_signal (conversation, "OpenSession", service_name);
+}
 
-GType
-gdm_session_get_type (void)
+static void
+stop_all_other_conversations (GdmSession              *self,
+                              GdmSessionConversation  *conversation_to_keep,
+                              gboolean                 now)
 {
-        static GType session_type = 0;
+        GHashTableIter iter;
+        gpointer key, value;
+
+        if (self->priv->conversations == NULL) {
+                return;
+        }
+
+        if (conversation_to_keep == NULL) {
+                g_debug ("GdmSession: Stopping all conversations");
+        } else {
+                g_debug ("GdmSession: Stopping all conversations "
+                         "except for %s", conversation_to_keep->service_name);
+        }
+
+        g_hash_table_iter_init (&iter, self->priv->conversations);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GdmSessionConversation *conversation;
+
+                conversation = (GdmSessionConversation *) value;
+
+                if (conversation == conversation_to_keep) {
+                        if (now) {
+                                g_hash_table_iter_steal (&iter);
+                                g_free (key);
+                        }
+                } else {
+                        if (now) {
+                                stop_conversation_now (conversation);
+                        } else {
+                                stop_conversation (conversation);
+                        }
+                }
+        }
+
+        if (now) {
+                g_hash_table_remove_all (self->priv->conversations);
 
-        if (!session_type) {
-                session_type = g_type_register_static_simple (G_TYPE_INTERFACE,
-                                                              "GdmSession",
-                                                              sizeof (GdmSessionIface),
-                                                              (GClassInitFunc) gdm_session_class_init,
-                                                              0, NULL, 0);
+                if (conversation_to_keep != NULL) {
+                        g_hash_table_insert (self->priv->conversations,
+                                             g_strdup (conversation_to_keep->service_name),
+                                             conversation_to_keep);
+                }
 
-                g_type_interface_add_prerequisite (session_type, G_TYPE_OBJECT);
+                if (self->priv->session_conversation != conversation_to_keep) {
+                        self->priv->session_conversation = NULL;
+                }
         }
 
-        return session_type;
 }
 
 void
-gdm_session_start_conversation (GdmSession *session,
-                                const char *service_name)
+gdm_session_start_session (GdmSession *self,
+                           const char *service_name)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        GdmSessionConversation *conversation;
+        char             *command;
+        char             *program;
+
+        g_return_if_fail (GDM_IS_SESSION (self));
+        g_return_if_fail (self->priv->session_conversation == NULL);
+
+        conversation = find_conversation_by_name (self, service_name);
+
+        if (conversation == NULL) {
+                g_warning ("GdmSession: Tried to start session of "
+                           "nonexistent conversation %s", service_name);
+                return;
+        }
 
-        GDM_SESSION_GET_IFACE (session)->start_conversation (session, service_name);
+        stop_all_other_conversations (self, conversation, FALSE);
+
+        if (self->priv->selected_program == NULL) {
+                command = get_session_command (self);
+
+                if (gdm_session_bypasses_xsession (self)) {
+                        program = g_strdup (command);
+                } else {
+                        program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
+                }
+
+                g_free (command);
+        } else {
+                program = g_strdup (self->priv->selected_program);
+        }
+
+        setup_session_environment (self);
+        send_environment (self, conversation);
+
+        send_dbus_string_signal (conversation, "StartProgram", program);
+        g_free (program);
 }
 
-void
-gdm_session_stop_conversation (GdmSession *session,
-                              const char *service_name)
+static void
+stop_all_conversations (GdmSession *self)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        GDM_SESSION_GET_IFACE (session)->stop_conversation (session, service_name);
+        stop_all_other_conversations (self, NULL, TRUE);
 }
 
 void
-gdm_session_close (GdmSession *session)
+gdm_session_close (GdmSession *self)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
 
-        GDM_SESSION_GET_IFACE (session)->close (session);
+        g_return_if_fail (GDM_IS_SESSION (self));
+
+        g_debug ("GdmSession: Closing session");
+
+        if (self->priv->session_conversation != NULL) {
+                gdm_session_record_logout (self->priv->session_pid,
+                                           self->priv->selected_user,
+                                           self->priv->display_hostname,
+                                           self->priv->display_name,
+                                           self->priv->display_device);
+        }
+
+        stop_all_conversations (self);
+
+        g_list_foreach (self->priv->pending_connections,
+                        (GFunc) dbus_connection_unref, NULL);
+        g_list_free (self->priv->pending_connections);
+        self->priv->pending_connections = NULL;
+
+        g_free (self->priv->selected_user);
+        self->priv->selected_user = NULL;
+
+        g_free (self->priv->selected_session);
+        self->priv->selected_session = NULL;
+
+        g_free (self->priv->saved_session);
+        self->priv->saved_session = NULL;
+
+        g_free (self->priv->selected_language);
+        self->priv->selected_language = NULL;
+
+        g_free (self->priv->saved_language);
+        self->priv->saved_language = NULL;
+
+        g_free (self->priv->user_x11_authority_file);
+        self->priv->user_x11_authority_file = NULL;
+
+        g_hash_table_remove_all (self->priv->environment);
+
+        self->priv->session_pid = -1;
+        self->priv->session_conversation = NULL;
 }
 
 void
-gdm_session_setup (GdmSession *session,
-                   const char *service_name)
+gdm_session_answer_query (GdmSession *self,
+                          const char *service_name,
+                          const char *text)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        GdmSessionConversation *conversation;
+
+        g_return_if_fail (GDM_IS_SESSION (self));
 
-        GDM_SESSION_GET_IFACE (session)->setup (session, service_name);
+        conversation = find_conversation_by_name (self, service_name);
+
+        answer_pending_query (conversation, text);
 }
 
 void
-gdm_session_setup_for_user (GdmSession *session,
-                            const char *service_name,
-                            const char *username)
+gdm_session_cancel  (GdmSession *self)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        g_return_if_fail (GDM_IS_SESSION (self));
 
-        GDM_SESSION_GET_IFACE (session)->setup_for_user (session, service_name, username);
+        stop_all_conversations (self);
 }
 
-void
-gdm_session_setup_for_program (GdmSession *session,
-                               const char *service_name,
-                               const char *log_file)
+char *
+gdm_session_get_username (GdmSession *self)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        g_return_val_if_fail (GDM_IS_SESSION (self), NULL);
 
-        GDM_SESSION_GET_IFACE (session)->setup_for_program (session, service_name, log_file);
+        return g_strdup (self->priv->selected_user);
 }
 
-void
-gdm_session_set_environment_variable (GdmSession *session,
-                                      const char *key,
-                                      const char *value)
+char *
+gdm_session_get_display_device (GdmSession *self)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        g_return_val_if_fail (GDM_IS_SESSION (self), NULL);
 
-        GDM_SESSION_GET_IFACE (session)->set_environment_variable (session, key, value);
+        return g_strdup (self->priv->display_device);
 }
 
-void
-gdm_session_authenticate (GdmSession *session,
-                          const char *service_name)
+char *
+gdm_session_get_display_seat_id (GdmSession *self)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        g_return_val_if_fail (GDM_IS_SESSION (self), NULL);
 
-        GDM_SESSION_GET_IFACE (session)->authenticate (session, service_name);
+        return g_strdup (self->priv->display_seat_id);
 }
 
-void
-gdm_session_authorize (GdmSession *session,
-                       const char *service_name)
+gboolean
+gdm_session_bypasses_xsession (GdmSession *self)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        GError     *error;
+        GKeyFile   *key_file;
+        gboolean    res;
+        gboolean    bypasses_xsession = FALSE;
+        char       *filename;
+
+        g_return_val_if_fail (self != NULL, FALSE);
+        g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
+
+        filename = g_strdup_printf ("%s.desktop", get_session_name (self));
+
+        key_file = g_key_file_new ();
+        error = NULL;
+        res = g_key_file_load_from_dirs (key_file,
+                                         filename,
+                                         get_system_session_dirs (),
+                                         NULL,
+                                         G_KEY_FILE_NONE,
+                                         &error);
+        if (! res) {
+                g_debug ("GdmSession: File '%s' not found: %s", filename, error->message);
+                goto out;
+        }
 
-        GDM_SESSION_GET_IFACE (session)->authorize (session, service_name);
+        error = NULL;
+        res = g_key_file_has_key (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", NULL);
+        if (!res) {
+                goto out;
+        } else {
+                bypasses_xsession = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", &error);
+                if (error) {
+                        bypasses_xsession = FALSE;
+                        g_error_free (error);
+                        goto out;
+                }
+                if (bypasses_xsession) {
+                        g_debug ("GdmSession: Session %s bypasses Xsession wrapper script", filename);
+                }
+        }
+
+out:
+        g_free (filename);
+        return bypasses_xsession;
 }
 
 void
-gdm_session_accredit (GdmSession *session,
-                      const char *service_name,
-                      int         flag)
+gdm_session_select_program (GdmSession *self,
+                            const char *text)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
 
-        GDM_SESSION_GET_IFACE (session)->accredit (session, service_name, flag);
+        g_free (self->priv->selected_program);
+
+        self->priv->selected_program = g_strdup (text);
 }
 
 void
-gdm_session_answer_query (GdmSession *session,
-                          const char *service_name,
-                          const char *text)
+gdm_session_select_session_type (GdmSession *self,
+                                 const char *text)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        GHashTableIter iter;
+        gpointer key, value;
 
-        GDM_SESSION_GET_IFACE (session)->answer_query (session, service_name, text);
+        g_hash_table_iter_init (&iter, self->priv->conversations);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GdmSessionConversation *conversation;
+
+                conversation = (GdmSessionConversation *) value;
+
+                send_dbus_string_signal (conversation, "SetSessionType",
+                                         text);
+        }
 }
 
 void
-gdm_session_select_program (GdmSession *session,
+gdm_session_select_session (GdmSession *self,
                             const char *text)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        GHashTableIter iter;
+        gpointer key, value;
+
+        g_free (self->priv->selected_session);
+
+        if (strcmp (text, "__previous") == 0) {
+                self->priv->selected_session = NULL;
+        } else {
+                self->priv->selected_session = g_strdup (text);
+        }
+
+        g_hash_table_iter_init (&iter, self->priv->conversations);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GdmSessionConversation *conversation;
+
+                conversation = (GdmSessionConversation *) value;
 
-        GDM_SESSION_GET_IFACE (session)->select_program (session, text);
+                send_dbus_string_signal (conversation, "SetSessionName",
+                                         get_session_name (self));
+        }
 }
 
 void
-gdm_session_select_session_type (GdmSession *session,
-                                 const char *text)
+gdm_session_select_language (GdmSession *self,
+                             const char *text)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        GHashTableIter iter;
+        gpointer key, value;
+
+        g_free (self->priv->selected_language);
+
+        if (strcmp (text, "__previous") == 0) {
+                self->priv->selected_language = NULL;
+        } else {
+                self->priv->selected_language = g_strdup (text);
+        }
+
+        g_hash_table_iter_init (&iter, self->priv->conversations);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GdmSessionConversation *conversation;
+
+                conversation = (GdmSessionConversation *) value;
 
-        GDM_SESSION_GET_IFACE (session)->select_session_type (session, text);
+                send_dbus_string_signal (conversation, "SetLanguageName",
+                                         get_language_name (self));
+        }
 }
-void
-gdm_session_select_session (GdmSession *session,
-                            const char *text)
+
+/* At some point we may want to read these right from
+ * the slave but for now I don't want the dependency */
+static void
+set_display_name (GdmSession *self,
+                  const char *name)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        g_free (self->priv->display_name);
+        self->priv->display_name = g_strdup (name);
+}
 
-        GDM_SESSION_GET_IFACE (session)->select_session (session, text);
+static void
+set_display_hostname (GdmSession *self,
+                      const char *name)
+{
+        g_free (self->priv->display_hostname);
+        self->priv->display_hostname = g_strdup (name);
 }
 
-void
-gdm_session_select_language (GdmSession *session,
-                             const char *text)
+static void
+set_display_device (GdmSession *self,
+                    const char *name)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        g_debug ("GdmSession: Setting display device: %s", name);
+        g_free (self->priv->display_device);
+        self->priv->display_device = g_strdup (name);
+}
 
-        GDM_SESSION_GET_IFACE (session)->select_language (session, text);
+static void
+set_display_seat_id (GdmSession *self,
+                     const char *name)
+{
+        g_free (self->priv->display_seat_id);
+        self->priv->display_seat_id = g_strdup (name);
 }
 
-void
-gdm_session_select_user (GdmSession *session,
-                         const char *text)
+static void
+set_user_x11_authority_file (GdmSession *self,
+                             const char *name)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        g_free (self->priv->user_x11_authority_file);
+        self->priv->user_x11_authority_file = g_strdup (name);
+}
 
-        GDM_SESSION_GET_IFACE (session)->select_user (session, text);
+static void
+set_display_x11_authority_file (GdmSession *self,
+                                const char *name)
+{
+        g_free (self->priv->display_x11_authority_file);
+        self->priv->display_x11_authority_file = g_strdup (name);
 }
 
-void
-gdm_session_cancel (GdmSession *session)
+static void
+set_display_is_local (GdmSession *self,
+                      gboolean    is_local)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        self->priv->display_is_local = is_local;
+}
 
-        GDM_SESSION_GET_IFACE (session)->cancel (session);
+static void
+gdm_session_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+        GdmSession *self;
+
+        self = GDM_SESSION (object);
+
+        switch (prop_id) {
+        case PROP_DISPLAY_NAME:
+                set_display_name (self, g_value_get_string (value));
+                break;
+        case PROP_DISPLAY_HOSTNAME:
+                set_display_hostname (self, g_value_get_string (value));
+                break;
+        case PROP_DISPLAY_DEVICE:
+                set_display_device (self, g_value_get_string (value));
+                break;
+        case PROP_DISPLAY_SEAT_ID:
+                set_display_seat_id (self, g_value_get_string (value));
+                break;
+        case PROP_USER_X11_AUTHORITY_FILE:
+                set_user_x11_authority_file (self, g_value_get_string (value));
+                break;
+        case PROP_DISPLAY_X11_AUTHORITY_FILE:
+                set_display_x11_authority_file (self, g_value_get_string (value));
+                break;
+        case PROP_DISPLAY_IS_LOCAL:
+                set_display_is_local (self, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
 }
 
-void
-gdm_session_open_session (GdmSession *session,
-                          const char *service_name)
+static void
+gdm_session_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+        GdmSession *self;
+
+        self = GDM_SESSION (object);
+
+        switch (prop_id) {
+        case PROP_DISPLAY_NAME:
+                g_value_set_string (value, self->priv->display_name);
+                break;
+        case PROP_DISPLAY_HOSTNAME:
+                g_value_set_string (value, self->priv->display_hostname);
+                break;
+        case PROP_DISPLAY_DEVICE:
+                g_value_set_string (value, self->priv->display_device);
+                break;
+        case PROP_DISPLAY_SEAT_ID:
+                g_value_set_string (value, self->priv->display_seat_id);
+                break;
+        case PROP_USER_X11_AUTHORITY_FILE:
+                g_value_set_string (value, self->priv->user_x11_authority_file);
+                break;
+        case PROP_DISPLAY_X11_AUTHORITY_FILE:
+                g_value_set_string (value, self->priv->display_x11_authority_file);
+                break;
+        case PROP_DISPLAY_IS_LOCAL:
+                g_value_set_boolean (value, self->priv->display_is_local);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gdm_session_dispose (GObject *object)
+{
+        GdmSession *self;
+
+        self = GDM_SESSION (object);
+
+        g_debug ("GdmSession: Disposing session");
+
+        gdm_session_close (self);
+
+        g_free (self->priv->display_id);
+        self->priv->display_id = NULL;
+
+        g_free (self->priv->display_name);
+        self->priv->display_name = NULL;
+
+        g_free (self->priv->display_hostname);
+        self->priv->display_hostname = NULL;
+
+        g_free (self->priv->display_device);
+        self->priv->display_device = NULL;
+
+        g_free (self->priv->display_seat_id);
+        self->priv->display_seat_id = NULL;
+
+        g_free (self->priv->display_x11_authority_file);
+        self->priv->display_x11_authority_file = NULL;
+
+        g_free (self->priv->server_address);
+        self->priv->server_address = NULL;
+
+        if (self->priv->server != NULL) {
+                dbus_server_disconnect (self->priv->server);
+                dbus_server_unref (self->priv->server);
+                self->priv->server = NULL;
+        }
+
+        if (self->priv->environment != NULL) {
+                g_hash_table_destroy (self->priv->environment);
+                self->priv->environment = NULL;
+        }
+
+        G_OBJECT_CLASS (gdm_session_parent_class)->dispose (object);
+}
+
+static void
+gdm_session_finalize (GObject *object)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        GdmSession   *self;
+        GObjectClass *parent_class;
+
+        self = GDM_SESSION (object);
+
+        g_free (self->priv->selected_user);
+        g_free (self->priv->selected_session);
+        g_free (self->priv->saved_session);
+        g_free (self->priv->selected_language);
+        g_free (self->priv->saved_language);
+
+        g_free (self->priv->fallback_session_name);
 
-        GDM_SESSION_GET_IFACE (session)->open_session (session, service_name);
+        parent_class = G_OBJECT_CLASS (gdm_session_parent_class);
+
+        if (parent_class->finalize != NULL)
+                parent_class->finalize (object);
 }
 
-void
-gdm_session_start_session (GdmSession *session,
-                           const char *service_name)
+static GObject *
+gdm_session_constructor (GType                  type,
+                         guint                  n_construct_properties,
+                         GObjectConstructParam *construct_properties)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
+        GdmSession *self;
 
-        GDM_SESSION_GET_IFACE (session)->start_session (session, service_name);
+        self = GDM_SESSION (G_OBJECT_CLASS (gdm_session_parent_class)->constructor (type,
+                                                                                    n_construct_properties,
+                                                                                    construct_properties));
+        return G_OBJECT (self);
 }
 
 static void
-gdm_session_class_init (gpointer g_iface)
+gdm_session_class_init (GdmSessionClass *session_class)
 {
-        GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+        GObjectClass *object_class;
+
+        object_class = G_OBJECT_CLASS (session_class);
+
+        object_class->get_property = gdm_session_get_property;
+        object_class->set_property = gdm_session_set_property;
+        object_class->constructor = gdm_session_constructor;
+        object_class->dispose = gdm_session_dispose;
+        object_class->finalize = gdm_session_finalize;
+
+        g_type_class_add_private (session_class, sizeof (GdmSessionPrivate));
 
         signals [CONVERSATION_STARTED] =
                 g_signal_new ("conversation-started",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, conversation_started),
+                              G_STRUCT_OFFSET (GdmSessionClass, conversation_started),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -269,9 +3236,9 @@ gdm_session_class_init (gpointer g_iface)
                               1, G_TYPE_STRING);
         signals [CONVERSATION_STOPPED] =
                 g_signal_new ("conversation-stopped",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, conversation_stopped),
+                              G_STRUCT_OFFSET (GdmSessionClass, conversation_stopped),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -279,9 +3246,9 @@ gdm_session_class_init (gpointer g_iface)
                               1, G_TYPE_STRING);
         signals [SERVICE_UNAVAILABLE] =
                 g_signal_new ("service-unavailable",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, service_unavailable),
+                              G_STRUCT_OFFSET (GdmSessionClass, service_unavailable),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -290,9 +3257,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING);
         signals [SETUP_COMPLETE] =
                 g_signal_new ("setup-complete",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, setup_complete),
+                              G_STRUCT_OFFSET (GdmSessionClass, setup_complete),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -301,9 +3268,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING);
         signals [SETUP_FAILED] =
                 g_signal_new ("setup-failed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, setup_failed),
+                              G_STRUCT_OFFSET (GdmSessionClass, setup_failed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -312,9 +3279,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [RESET_COMPLETE] =
                 g_signal_new ("reset-complete",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, reset_complete),
+                              G_STRUCT_OFFSET (GdmSessionClass, reset_complete),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__VOID,
@@ -322,9 +3289,9 @@ gdm_session_class_init (gpointer g_iface)
                               0);
         signals [RESET_FAILED] =
                 g_signal_new ("reset-failed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, reset_failed),
+                              G_STRUCT_OFFSET (GdmSessionClass, reset_failed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -333,9 +3300,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING);
         signals [AUTHENTICATED] =
                 g_signal_new ("authenticated",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, authenticated),
+                              G_STRUCT_OFFSET (GdmSessionClass, authenticated),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -343,9 +3310,9 @@ gdm_session_class_init (gpointer g_iface)
                               1, G_TYPE_STRING);
         signals [AUTHENTICATION_FAILED] =
                 g_signal_new ("authentication-failed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, authentication_failed),
+                              G_STRUCT_OFFSET (GdmSessionClass, authentication_failed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -354,9 +3321,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [AUTHORIZED] =
                 g_signal_new ("authorized",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, authorized),
+                              G_STRUCT_OFFSET (GdmSessionClass, authorized),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -364,9 +3331,9 @@ gdm_session_class_init (gpointer g_iface)
                               1, G_TYPE_STRING);
         signals [AUTHORIZATION_FAILED] =
                 g_signal_new ("authorization-failed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, authorization_failed),
+                              G_STRUCT_OFFSET (GdmSessionClass, authorization_failed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -375,9 +3342,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [ACCREDITED] =
                 g_signal_new ("accredited",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, accredited),
+                              G_STRUCT_OFFSET (GdmSessionClass, accredited),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -385,9 +3352,9 @@ gdm_session_class_init (gpointer g_iface)
                               1, G_TYPE_STRING);
         signals [ACCREDITATION_FAILED] =
                 g_signal_new ("accreditation-failed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, accreditation_failed),
+                              G_STRUCT_OFFSET (GdmSessionClass, accreditation_failed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -397,9 +3364,9 @@ gdm_session_class_init (gpointer g_iface)
 
          signals [INFO_QUERY] =
                 g_signal_new ("info-query",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, info_query),
+                              G_STRUCT_OFFSET (GdmSessionClass, info_query),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -408,9 +3375,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [SECRET_INFO_QUERY] =
                 g_signal_new ("secret-info-query",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, secret_info_query),
+                              G_STRUCT_OFFSET (GdmSessionClass, secret_info_query),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -419,9 +3386,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [INFO] =
                 g_signal_new ("info",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, info),
+                              G_STRUCT_OFFSET (GdmSessionClass, info),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -430,9 +3397,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [PROBLEM] =
                 g_signal_new ("problem",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, problem),
+                              G_STRUCT_OFFSET (GdmSessionClass, problem),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -441,9 +3408,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [SESSION_OPENED] =
                 g_signal_new ("session-opened",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, session_opened),
+                              G_STRUCT_OFFSET (GdmSessionClass, session_opened),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -452,9 +3419,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING);
         signals [SESSION_OPEN_FAILED] =
                 g_signal_new ("session-open-failed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, session_open_failed),
+                              G_STRUCT_OFFSET (GdmSessionClass, session_open_failed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -463,9 +3430,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [SESSION_STARTED] =
                 g_signal_new ("session-started",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, session_started),
+                              G_STRUCT_OFFSET (GdmSessionClass, session_started),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -474,9 +3441,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_INT);
         signals [SESSION_START_FAILED] =
                 g_signal_new ("session-start-failed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, session_start_failed),
+                              G_STRUCT_OFFSET (GdmSessionClass, session_start_failed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_generic,
@@ -485,9 +3452,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING, G_TYPE_STRING);
         signals [SESSION_EXITED] =
                 g_signal_new ("session-exited",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, session_exited),
+                              G_STRUCT_OFFSET (GdmSessionClass, session_exited),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__INT,
@@ -496,9 +3463,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_INT);
         signals [SESSION_DIED] =
                 g_signal_new ("session-died",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, session_died),
+                              G_STRUCT_OFFSET (GdmSessionClass, session_died),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__INT,
@@ -507,9 +3474,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_INT);
         signals [SELECTED_USER_CHANGED] =
                 g_signal_new ("selected-user-changed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, selected_user_changed),
+                              G_STRUCT_OFFSET (GdmSessionClass, selected_user_changed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -518,9 +3485,9 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING);
         signals [DEFAULT_LANGUAGE_NAME_CHANGED] =
                 g_signal_new ("default-language-name-changed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, default_language_name_changed),
+                              G_STRUCT_OFFSET (GdmSessionClass, default_language_name_changed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
@@ -529,239 +3496,87 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_STRING);
         signals [DEFAULT_SESSION_NAME_CHANGED] =
                 g_signal_new ("default-session-name-changed",
-                              iface_type,
+                              GDM_TYPE_SESSION,
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdmSessionIface, default_session_name_changed),
+                              G_STRUCT_OFFSET (GdmSessionClass, default_session_name_changed),
                               NULL,
                               NULL,
                               g_cclosure_marshal_VOID__STRING,
                               G_TYPE_NONE,
                               1,
                               G_TYPE_STRING);
-}
-
-void
-_gdm_session_service_unavailable (GdmSession   *session,
-                                  const char   *service_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        g_signal_emit (session, signals [SERVICE_UNAVAILABLE], 0, service_name);
-}
-
-void
-_gdm_session_setup_complete (GdmSession   *session,
-                             const char   *service_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        g_signal_emit (session, signals [SETUP_COMPLETE], 0, service_name);
-}
-
-void
-_gdm_session_setup_failed (GdmSession   *session,
-                           const char   *service_name,
-                           const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SETUP_FAILED], 0, service_name, text);
-}
-
-void
-_gdm_session_reset_complete (GdmSession   *session)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        g_signal_emit (session, signals [RESET_COMPLETE], 0);
-}
-
-void
-_gdm_session_reset_failed (GdmSession   *session,
-                           const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [RESET_FAILED], 0, text);
-}
-
-void
-_gdm_session_authenticated (GdmSession   *session,
-                            const char   *service_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        g_signal_emit (session, signals [AUTHENTICATED], 0, service_name);
-}
-
-void
-_gdm_session_authentication_failed (GdmSession   *session,
-                                    const char   *service_name,
-                                    const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [AUTHENTICATION_FAILED], 0, service_name, text);
-}
-
-void
-_gdm_session_authorized (GdmSession   *session,
-                         const char   *service_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        g_signal_emit (session, signals [AUTHORIZED], 0, service_name);
-}
-
-void
-_gdm_session_authorization_failed (GdmSession   *session,
-                                   const char   *service_name,
-                                   const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [AUTHORIZATION_FAILED], 0, service_name, text);
-}
-
-void
-_gdm_session_accredited (GdmSession   *session,
-                         const char   *service_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        g_signal_emit (session, signals [ACCREDITED], 0, service_name);
-}
 
-void
-_gdm_session_accreditation_failed (GdmSession   *session,
-                                   const char   *service_name,
-                                   const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [ACCREDITATION_FAILED], 0, service_name, text);
-}
-
-void
-_gdm_session_info_query (GdmSession   *session,
-                         const char   *service_name,
-                         const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [INFO_QUERY], 0, service_name, text);
-}
-
-void
-_gdm_session_secret_info_query (GdmSession   *session,
-                                const char   *service_name,
-                                const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SECRET_INFO_QUERY], 0, service_name, text);
-}
-
-void
-_gdm_session_info (GdmSession   *session,
-                   const char   *service_name,
-                   const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [INFO], 0, service_name, text);
-}
-
-void
-_gdm_session_problem (GdmSession   *session,
-                      const char   *service_name,
-                      const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [PROBLEM], 0, service_name, text);
-}
-
-void
-_gdm_session_session_opened (GdmSession   *session,
-                             const char   *service_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SESSION_OPENED], 0, service_name);
-}
-
-void
-_gdm_session_session_open_failed (GdmSession   *session,
-                                  const char   *service_name,
-                                  const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SESSION_OPEN_FAILED], 0, service_name, text);
-}
-
-void
-_gdm_session_session_started (GdmSession   *session,
-                              const char   *service_name,
-                              int           pid)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SESSION_STARTED], 0, service_name, pid);
-}
-
-void
-_gdm_session_session_start_failed (GdmSession   *session,
-                                   const char   *service_name,
-                                   const char   *text)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SESSION_START_FAILED], 0, service_name, text);
-}
-
-void
-_gdm_session_session_exited (GdmSession   *session,
-                             int           exit_code)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SESSION_EXITED], 0, exit_code);
-}
-
-void
-_gdm_session_session_died (GdmSession   *session,
-                           int           signal_number)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SESSION_DIED], 0, signal_number);
-}
-
-void
-_gdm_session_conversation_started (GdmSession   *session,
-                                   const char   *service_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [CONVERSATION_STARTED], 0, service_name);
-}
-
-void
-_gdm_session_conversation_stopped (GdmSession   *session,
-                                   const char   *service_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [CONVERSATION_STOPPED], 0, service_name);
-}
-
-void
-_gdm_session_default_language_name_changed (GdmSession   *session,
-                                            const char   *language_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        g_signal_emit (session, signals [DEFAULT_LANGUAGE_NAME_CHANGED], 0, language_name);
-}
-
-void
-_gdm_session_default_session_name_changed (GdmSession   *session,
-                                           const char   *session_name)
-{
-        g_return_if_fail (GDM_IS_SESSION (session));
-
-        g_signal_emit (session, signals [DEFAULT_SESSION_NAME_CHANGED], 0, session_name);
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_NAME,
+                                         g_param_spec_string ("display-name",
+                                                              "display name",
+                                                              "display name",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_HOSTNAME,
+                                         g_param_spec_string ("display-hostname",
+                                                              "display hostname",
+                                                              "display hostname",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_IS_LOCAL,
+                                         g_param_spec_boolean ("display-is-local",
+                                                               "display is local",
+                                                               "display is local",
+                                                               TRUE,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_X11_AUTHORITY_FILE,
+                                         g_param_spec_string ("display-x11-authority-file",
+                                                              "display x11 authority file",
+                                                              "display x11 authority file",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        /* not construct only */
+        g_object_class_install_property (object_class,
+                                         PROP_USER_X11_AUTHORITY_FILE,
+                                         g_param_spec_string ("user-x11-authority-file",
+                                                              "",
+                                                              "",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_DEVICE,
+                                         g_param_spec_string ("display-device",
+                                                              "display device",
+                                                              "display device",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_SEAT_ID,
+                                         g_param_spec_string ("display-seat-id",
+                                                              "display seat id",
+                                                              "display seat id",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
 
-void
-_gdm_session_selected_user_changed (GdmSession   *session,
-                                    const char   *text)
+GdmSession *
+gdm_session_new (const char *display_name,
+                 const char *display_hostname,
+                 const char *display_device,
+                 const char *display_seat_id,
+                 const char *display_x11_authority_file,
+                 gboolean    display_is_local)
 {
-        g_return_if_fail (GDM_IS_SESSION (session));
-        g_signal_emit (session, signals [SELECTED_USER_CHANGED], 0, text);
+        GdmSession *self;
+
+        self = g_object_new (GDM_TYPE_SESSION,
+                             "display-name", display_name,
+                             "display-hostname", display_hostname,
+                             "display-device", display_device,
+                             "display-seat-id", display_seat_id,
+                             "display-x11-authority-file", display_x11_authority_file,
+                             "display-is-local", display_is_local,
+                              NULL);
+
+        return self;
 }
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index 479d8e3..1961be0 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -1,11 +1,11 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2007 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2006 Ray Strode <rstrode redhat com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,11 +14,10 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
  */
 
-
 #ifndef __GDM_SESSION_H
 #define __GDM_SESSION_H
 
@@ -26,69 +25,29 @@
 
 G_BEGIN_DECLS
 
-#define GDM_TYPE_SESSION         (gdm_session_get_type ())
-#define GDM_SESSION(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_SESSION, GdmSession))
-#define GDM_SESSION_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_SESSION, GdmSessionClass))
-#define GDM_IS_SESSION(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_SESSION))
-#define GDM_SESSION_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDM_TYPE_SESSION, GdmSessionIface))
+#define GDM_TYPE_SESSION (gdm_session_get_type ())
+#define GDM_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SESSION, GdmSession))
+#define GDM_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SESSION, GdmSessionClass))
+#define GDM_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SESSION))
+#define GDM_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SESSION))
+#define GDM_SESSION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SESSION, GdmSessionClass))
 
-typedef struct _GdmSession      GdmSession; /* Dummy typedef */
-typedef struct _GdmSessionIface GdmSessionIface;
+typedef struct _GdmSessionPrivate GdmSessionPrivate;
 
 enum {
         GDM_SESSION_CRED_ESTABLISH = 0,
         GDM_SESSION_CRED_REFRESH,
 };
 
-struct _GdmSessionIface
+typedef struct
 {
-        GTypeInterface base_iface;
+        GObject            parent;
+        GdmSessionPrivate *priv;
+} GdmSession;
 
-        /* Methods */
-        void (* start_conversation)          (GdmSession   *session,
-                                              const char   *service_name);
-        void (* stop_conversation)           (GdmSession   *session,
-                                              const char   *service_name);
-        void (* service_unavailable)         (GdmSession   *session,
-                                              const char   *service_name);
-        void (* setup)                       (GdmSession   *session,
-                                              const char   *service_name);
-        void (* setup_for_user)              (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *username);
-        void (* setup_for_program)           (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *log_file);
-        void (* set_environment_variable)    (GdmSession   *session,
-                                              const char   *key,
-                                              const char   *value);
-        void (* reset)                       (GdmSession   *session);
-        void (* authenticate)                (GdmSession   *session,
-                                              const char   *service_name);
-        void (* authorize)                   (GdmSession   *session,
-                                              const char   *service_name);
-        void (* accredit)                    (GdmSession   *session,
-                                              const char   *service_name,
-                                              int           cred_flag);
-        void (* open_session)                (GdmSession   *session,
-                                              const char   *service_name);
-        void (* answer_query)                (GdmSession   *session,
-                                              const char   *service_name,
-                                              const char   *text);
-        void (* select_language)             (GdmSession   *session,
-                                              const char   *text);
-        void (* select_program)              (GdmSession   *session,
-                                              const char   *text);
-        void (* select_session_type)         (GdmSession   *session,
-                                              const char   *session_type);
-        void (* select_session)              (GdmSession   *session,
-                                              const char   *text);
-        void (* select_user)                 (GdmSession   *session,
-                                              const char   *text);
-        void (* start_session)               (GdmSession   *session,
-                                              const char   *service_name);
-        void (* close)                       (GdmSession   *session);
-        void (* cancel)                      (GdmSession   *session);
+typedef struct
+{
+        GObjectClass parent_class;
 
         /* Signals */
         void (* setup_complete)              (GdmSession   *session,
@@ -146,6 +105,8 @@ struct _GdmSessionIface
                                               const char   *service_name);
         void (* conversation_stopped)        (GdmSession   *session,
                                               const char   *service_name);
+        void (* service_unavailable)         (GdmSession   *session,
+                                              const char   *service_name);
         void (* selected_user_changed)       (GdmSession   *session,
                                               const char   *text);
 
@@ -153,54 +114,74 @@ struct _GdmSessionIface
                                                    const char   *text);
         void (* default_session_name_changed)     (GdmSession   *session,
                                                    const char   *text);
-};
-
-GType    gdm_session_get_type                    (void) G_GNUC_CONST;
-
-void     gdm_session_start_conversation          (GdmSession *session,
-                                                  const char *service_name);
-void     gdm_session_stop_conversation           (GdmSession *session,
-                                                  const char *service_name);
-void     gdm_session_setup                       (GdmSession *session,
-                                                  const char *service_name);
-void     gdm_session_setup_for_user              (GdmSession *session,
-                                                  const char *service_name,
-                                                  const char *username);
-void     gdm_session_setup_for_program           (GdmSession *session,
-                                                  const char *service_name,
-                                                  const char *log_file);
-void     gdm_session_set_environment_variable    (GdmSession *session,
-                                                  const char *key,
-                                                  const char *value);
-void     gdm_session_reset                       (GdmSession *session);
-void     gdm_session_authenticate                (GdmSession *session,
-                                                  const char *service_name);
-void     gdm_session_authorize                   (GdmSession *session,
-                                                  const char *service_name);
-void     gdm_session_accredit                    (GdmSession *session,
-                                                  const char *service_name,
-                                                  int         cred_flag);
-void     gdm_session_open_session                (GdmSession *session,
-                                                  const char *service_name);
-void     gdm_session_start_session               (GdmSession *session,
-                                                  const char *service_name);
-void     gdm_session_close                       (GdmSession *session);
-
-void     gdm_session_answer_query                (GdmSession *session,
-                                                  const char *service_name,
-                                                  const char *text);
-void     gdm_session_select_program              (GdmSession *session,
-                                                  const char *command_line);
-void     gdm_session_select_session_type         (GdmSession *session,
-                                                  const char *session_type);
-void     gdm_session_select_session              (GdmSession *session,
-                                                  const char *session_name);
-void     gdm_session_select_language             (GdmSession *session,
-                                                  const char *language);
-void     gdm_session_select_user                 (GdmSession *session,
-                                                  const char *username);
-void     gdm_session_cancel                      (GdmSession *session);
+} GdmSessionClass;
+
+GType            gdm_session_get_type                 (void);
+
+GdmSession      *gdm_session_new                      (const char *display_name,
+                                                       const char *display_hostname,
+                                                       const char *display_device,
+                                                       const char *display_seat_id,
+                                                       const char *display_x11_authority_file,
+                                                       gboolean    display_is_local);
+
+char             *gdm_session_get_username                (GdmSession     *session);
+char             *gdm_session_get_display_device          (GdmSession     *session);
+char             *gdm_session_get_display_seat_id         (GdmSession     *session);
+gboolean          gdm_session_bypasses_xsession           (GdmSession     *session);
+
+void              gdm_session_start_conversation          (GdmSession *session,
+                                                           const char *service_name);
+void              gdm_session_stop_conversation           (GdmSession *session,
+                                                           const char *service_name);
+void              gdm_session_setup                       (GdmSession *session,
+                                                           const char *service_name);
+void              gdm_session_setup_for_user              (GdmSession *session,
+                                                           const char *service_name,
+                                                           const char *username);
+void              gdm_session_setup_for_program           (GdmSession *session,
+                                                           const char *service_name,
+                                                           const char *log_file);
+void              gdm_session_set_environment_variable    (GdmSession *session,
+                                                           const char *key,
+                                                           const char *value);
+void              gdm_session_reset                       (GdmSession *session);
+void              gdm_session_authenticate                (GdmSession *session,
+                                                           const char *service_name);
+void              gdm_session_authorize                   (GdmSession *session,
+                                                           const char *service_name);
+void              gdm_session_accredit                    (GdmSession *session,
+                                                           const char *service_name,
+                                                           int         cred_flag);
+void              gdm_session_open_session                (GdmSession *session,
+                                                           const char *service_name);
+void              gdm_session_start_session               (GdmSession *session,
+                                                           const char *service_name);
+void              gdm_session_close                       (GdmSession *session);
+
+void              gdm_session_answer_query                (GdmSession *session,
+                                                           const char *service_name,
+                                                           const char *text);
+void              gdm_session_select_program              (GdmSession *session,
+                                                           const char *command_line);
+void              gdm_session_select_session_type         (GdmSession *session,
+                                                           const char *session_type);
+void              gdm_session_select_session              (GdmSession *session,
+                                                           const char *session_name);
+void              gdm_session_select_language             (GdmSession *session,
+                                                           const char *language);
+void              gdm_session_select_user                 (GdmSession *session,
+                                                           const char *username);
+void              gdm_session_cancel                      (GdmSession *session);
+
+/* Exported methods */
+gboolean          gdm_session_restart                  (GdmSession   *session,
+                                                        GError      **error);
+gboolean          gdm_session_stop                     (GdmSession   *session,
+                                                        GError      **error);
+gboolean          gdm_session_detach                   (GdmSession   *session,
+                                                        GError      **error);
 
 G_END_DECLS
 
-#endif /* __GDM_SESSION_H */
+#endif /* GDM_SESSION_H */
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 4dea4d2..42fa6af 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -50,7 +50,6 @@
 
 #include "gdm-server.h"
 #include "gdm-session.h"
-#include "gdm-session-direct.h"
 #include "gdm-greeter-server.h"
 #include "gdm-greeter-session.h"
 #include "gdm-settings-direct.h"
@@ -79,7 +78,7 @@ struct GdmSimpleSlavePrivate
         guint              connection_attempts;
 
         GdmServer         *server;
-        GdmSessionDirect  *session;
+        GdmSession        *session;
 
         GdmGreeterServer  *greeter_server;
         GdmGreeterSession *greeter;
@@ -122,7 +121,7 @@ on_session_started (GdmSession       *session,
         g_debug ("GdmSimpleSlave: session started %d", pid);
 
         /* Run the PreSession script. gdmslave suspends until script has terminated */
-        username = gdm_session_direct_get_username (slave->priv->session);
+        username = gdm_session_get_username (slave->priv->session);
         if (username != NULL) {
                 gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/PreSession", username);
         }
@@ -132,7 +131,7 @@ on_session_started (GdmSession       *session,
          * Note that error return status from PreSession script should
          * be ignored in the case of a X-GDM-BypassXsession session, which can
          * be checked by calling:
-         * gdm_session_direct_bypasses_xsession (session)
+         * gdm_session_bypasses_xsession (session)
          */
 }
 
@@ -144,8 +143,8 @@ gdm_simple_slave_grant_console_permissions (GdmSimpleSlave *slave)
         char *display_device;
         struct passwd *passwd_entry;
 
-        username = gdm_session_direct_get_username (slave->priv->session);
-        display_device = gdm_session_direct_get_display_device (slave->priv->session);
+        username = gdm_session_get_username (slave->priv->session);
+        display_device = gdm_session_get_display_device (slave->priv->session);
 
         if (username != NULL) {
                 gdm_get_pwent_for_name (username, &passwd_entry);
@@ -179,8 +178,8 @@ gdm_simple_slave_revoke_console_permissions (GdmSimpleSlave *slave)
         char *username;
         char *display_device;
 
-        username = gdm_session_direct_get_username (slave->priv->session);
-        display_device = gdm_session_direct_get_display_device (slave->priv->session);
+        username = gdm_session_get_username (slave->priv->session);
+        display_device = gdm_session_get_display_device (slave->priv->session);
 
         /*
          * Only do logindevperm processing if /dev/console or a device
@@ -238,7 +237,7 @@ add_user_authorization (GdmSimpleSlave *slave,
         char    *username;
         gboolean ret;
 
-        username = gdm_session_direct_get_username (slave->priv->session);
+        username = gdm_session_get_username (slave->priv->session);
         ret = gdm_slave_add_user_authorization (GDM_SLAVE (slave),
                                                 username,
                                                 filename);
@@ -376,7 +375,7 @@ on_session_authorized (GdmSession     *session,
         char *username;
         int   cred_flag;
 
-        username = gdm_session_direct_get_username (slave->priv->session);
+        username = gdm_session_get_username (slave->priv->session);
 
         ssid = gdm_slave_get_primary_session_id_for_user (GDM_SLAVE (slave), username);
         if (ssid != NULL && ssid [0] != '\0') {
@@ -414,7 +413,7 @@ try_migrate_session (GdmSimpleSlave *slave)
 
         g_debug ("GdmSimpleSlave: trying to migrate session");
 
-        username = gdm_session_direct_get_username (slave->priv->session);
+        username = gdm_session_get_username (slave->priv->session);
 
         /* try to switch to an existing session */
         res = gdm_slave_switch_to_user_session (GDM_SLAVE (slave), username);
@@ -438,7 +437,7 @@ stop_greeter (GdmSimpleSlave *slave)
         /* Run the PostLogin script. gdmslave suspends until script has terminated */
         username = NULL;
         if (slave->priv->session != NULL) {
-                username = gdm_session_direct_get_username (slave->priv->session);
+                username = gdm_session_get_username (slave->priv->session);
         }
 
         if (username != NULL) {
@@ -768,13 +767,12 @@ create_new_session (GdmSimpleSlave *slave)
                 display_device = gdm_server_get_display_device (slave->priv->server);
         }
 
-        slave->priv->session = gdm_session_direct_new (display_id,
-                                                       display_name,
-                                                       display_hostname,
-                                                       display_device,
-                                                       display_seat_id,
-                                                       display_x11_authority_file,
-                                                       display_is_local);
+        slave->priv->session = gdm_session_new (display_name,
+                                                display_hostname,
+                                                display_device,
+                                                display_seat_id,
+                                                display_x11_authority_file,
+                                                display_is_local);
         g_free (display_id);
         g_free (display_name);
         g_free (display_device);
@@ -1626,7 +1624,7 @@ gdm_simple_slave_stop (GdmSlave *slave)
                 /* Run the PostSession script. gdmslave suspends until script
                  * has terminated
                  */
-                username = gdm_session_direct_get_username (GDM_SIMPLE_SLAVE (slave)->priv->session);
+                username = gdm_session_get_username (GDM_SIMPLE_SLAVE (slave)->priv->session);
                 if (username != NULL) {
                         gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/PostSession", username);
                 }
diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
index 3431edb..503f4f8 100644
--- a/daemon/gdm-welcome-session.c
+++ b/daemon/gdm-welcome-session.c
@@ -47,7 +47,6 @@
 #include "gdm-common.h"
 
 #include "gdm-session.h"
-#include "gdm-session-direct.h"
 #include "gdm-welcome-session.h"
 
 #define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch"
@@ -830,13 +829,12 @@ gdm_welcome_session_start (GdmWelcomeSession *welcome_session)
                 return FALSE;
         }
 
-        welcome_session->priv->session = GDM_SESSION (gdm_session_direct_new (NULL,
-                                                                              welcome_session->priv->x11_display_name,
-                                                                              welcome_session->priv->x11_display_hostname,
-                                                                              welcome_session->priv->x11_display_device,
-                                                                              welcome_session->priv->x11_display_seat_id,
-                                                                              welcome_session->priv->x11_authority_file,
-                                                                              welcome_session->priv->x11_display_is_local));
+        welcome_session->priv->session = gdm_session_new (welcome_session->priv->x11_display_name,
+                                                          welcome_session->priv->x11_display_hostname,
+                                                          welcome_session->priv->x11_display_device,
+                                                          welcome_session->priv->x11_display_seat_id,
+                                                          welcome_session->priv->x11_authority_file,
+                                                          welcome_session->priv->x11_display_is_local);
 
         g_signal_connect (GDM_SESSION (welcome_session->priv->session),
                           "conversation-started",
diff --git a/daemon/test-session.c b/daemon/test-session.c
index f75d5ed..23eca7a 100644
--- a/daemon/test-session.c
+++ b/daemon/test-session.c
@@ -28,7 +28,7 @@
 
 #include <glib.h>
 
-#include "gdm-session-direct.h"
+#include "gdm-session.h"
 
 static GMainLoop *loop;
 
@@ -124,7 +124,7 @@ on_session_accredited (GdmSession *session,
 {
         char *username;
 
-        username = gdm_session_direct_get_username (GDM_SESSION_DIRECT (session));
+        username = gdm_session_get_username (GDM_SESSION (session));
 
         g_print ("%s%ssuccessfully accredited\n",
                  username ? username : "", username ? " " : "");
@@ -247,7 +247,7 @@ on_secret_info_query (GdmSession *session,
 }
 
 static void
-import_environment (GdmSessionDirect *session)
+import_environment (GdmSession *session)
 {
 }
 
@@ -255,23 +255,22 @@ int
 main (int   argc,
       char *argv[])
 {
-        GdmSessionDirect *session;
-        char             *username;
+        GdmSession *session;
+        char       *username;
 
         g_log_set_always_fatal (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
 
         g_type_init ();
 
         do {
-                g_debug ("creating instance of GdmSessionDirect object...");
-                session = gdm_session_direct_new ("/org/gnome/DisplayManager/Display1",
-                                                  ":0",
-                                                  g_get_host_name (),
-                                                  ttyname (STDIN_FILENO),
-                                                  "",
-                                                  getenv("XAUTHORITY"),
-                                                  TRUE);
-                g_debug ("GdmSessionDirect object created successfully");
+                g_debug ("creating instance of GdmSession object...");
+                session = gdm_session_new (":0",
+                                           g_get_host_name (),
+                                           ttyname (STDIN_FILENO),
+                                           "",
+                                           getenv("XAUTHORITY"),
+                                           TRUE);
+                g_debug ("GdmSession object created successfully");
 
                 if (argc <= 1) {
                         username = NULL;
@@ -362,8 +361,8 @@ main (int   argc,
                 g_main_loop_run (loop);
                 g_main_loop_unref (loop);
 
-                g_message ("destroying previously created GdmSessionDirect object...");
+                g_message ("destroying previously created GdmSession object...");
                 g_object_unref (session);
-                g_message ("GdmSessionDirect object destroyed successfully");
+                g_message ("GdmSession object destroyed successfully");
         } while (1);
 }
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3e779fc..cbbbaca 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -25,8 +25,6 @@ daemon/gdm-manager.c
 daemon/gdm-server.c
 daemon/gdm-session-auditor.c
 daemon/gdm-session.c
-daemon/gdm-session-direct.c
-daemon/gdm-session-settings.c
 daemon/gdm-session-settings.c
 daemon/gdm-session-worker.c
 daemon/gdm-session-worker-job.c



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