[gdm/multi-stack: 9/45] Don't tear down greeter until pam_open_session finishes



commit efc53714006058ce219d4dac748e63b18e72c684
Author: Ray Strode <rstrode redhat com>
Date:   Mon Mar 9 15:41:12 2009 -0400

    Don't tear down greeter until pam_open_session finishes
    
    Some PAM modules ask questions at that late stage of the game,
    and so we need a greeter to forward the questions on to the
    user.

 daemon/gdm-factory-slave.c   |   37 ++++++++++++++++++++--
 daemon/gdm-product-slave.c   |   30 +++++++++++++++++-
 daemon/gdm-session-direct.c  |   70 ++++++++++++++++++++++++++++++++++++++++++
 daemon/gdm-session-private.h |    5 +++
 daemon/gdm-session-relay.c   |   68 ++++++++++++++++++++++++++++++++++++++++
 daemon/gdm-session-worker.c  |   16 ++++++++--
 daemon/gdm-session.c         |   50 ++++++++++++++++++++++++++++++
 daemon/gdm-session.h         |    9 +++++
 daemon/gdm-simple-slave.c    |   33 +++++++++++++++++++-
 9 files changed, 310 insertions(+), 8 deletions(-)
---
diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c
index 826612e..ef6d236 100644
--- a/daemon/gdm-factory-slave.c
+++ b/daemon/gdm-factory-slave.c
@@ -278,9 +278,7 @@ on_session_accredited (GdmSession      *session,
 {
         g_debug ("GdmFactorySlave:  session user verified");
 
-        gdm_session_start_session (session, service_name);
-
-        gdm_greeter_server_reset (slave->priv->greeter_server);
+        gdm_session_open_session (session, service_name);
 }
 
 static void
@@ -298,6 +296,31 @@ on_session_accreditation_failed (GdmSession      *session,
 }
 
 static void
+on_session_opened (GdmSession      *session,
+                   const char      *service_name,
+                   GdmFactorySlave *slave)
+{
+        g_debug ("GdmFactorySlave: session opened");
+
+        gdm_session_start_session (session, service_name);
+
+        gdm_greeter_server_reset (slave->priv->greeter_server);
+}
+
+static void
+on_session_open_failed (GdmSession      *session,
+                        const char      *service_name,
+                        const char      *message,
+                        GdmFactorySlave *slave)
+{
+        g_debug ("GdmFactorySlave: could not open session: %s", message);
+
+        gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to open session"));
+
+        queue_greeter_reset (slave);
+}
+
+static void
 on_session_session_started (GdmSession      *session,
                             GdmFactorySlave *slave)
 {
@@ -767,6 +790,14 @@ gdm_factory_slave_start (GdmSlave *slave)
                           G_CALLBACK (on_session_accreditation_failed),
                           slave);
         g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session,
+                          "session-opened",
+                          G_CALLBACK (on_session_opened),
+                          slave);
+        g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session,
+                          "session-open-failed",
+                          G_CALLBACK (on_session_open_failed),
+                          slave);
+        g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session,
                           "info",
                           G_CALLBACK (on_session_info),
                           slave);
diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c
index dd2e1bc..93d83a1 100644
--- a/daemon/gdm-product-slave.c
+++ b/daemon/gdm-product-slave.c
@@ -635,6 +635,27 @@ on_session_accreditation_failed (GdmSession      *session,
 }
 
 static void
+on_session_opened (GdmSession      *session,
+                   const char      *service_name,
+                   GdmProductSlave *slave)
+{
+        send_dbus_string_method (slave->priv->session_relay_connection,
+                                 "SessionOpened", service_name);
+}
+
+static void
+on_session_open_failed (GdmSession      *session,
+                        const char      *service_name,
+                        const char      *message,
+                        GdmProductSlave *slave)
+{
+        send_dbus_string_string_method (slave->priv->session_relay_connection,
+                                        "SessionOpenFailed",
+                                        service_name,
+                                        message);
+}
+
+static void
 on_session_info (GdmSession      *session,
                  const char      *service_name,
                  const char      *text,
@@ -1051,7 +1072,14 @@ create_new_session (GdmProductSlave *slave)
                           "accreditation-failed",
                           G_CALLBACK (on_session_accreditation_failed),
                           slave);
-
+        g_signal_connect (slave->priv->session,
+                          "session-opened",
+                          G_CALLBACK (on_session_opened),
+                          slave);
+        g_signal_connect (slave->priv->session,
+                          "session-open-failed",
+                          G_CALLBACK (on_session_open_failed),
+                          slave);
         g_signal_connect (slave->priv->session,
                           "info",
                           G_CALLBACK (on_session_info),
diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c
index e0b5f32..738267a 100644
--- a/daemon/gdm-session-direct.c
+++ b/daemon/gdm-session-direct.c
@@ -940,6 +940,58 @@ gdm_session_direct_handle_problem (GdmSessionDirect *session,
 }
 
 static DBusHandlerResult
+gdm_session_direct_handle_session_opened (GdmSessionDirect *session,
+                                          GdmSessionConversation *conversation,
+                                          DBusMessage      *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+
+        g_debug ("GdmSessionDirect: Handling SessionOpened");
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error, DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+
+        g_debug ("GdmSessionDirect: Emitting 'session-opened' signal");
+
+        _gdm_session_session_opened (GDM_SESSION (session), 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_direct_handle_open_failed (GdmSessionDirect *session,
+                                       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 ("GdmSessionDirect: Emitting 'session-open-failed' signal");
+        _gdm_session_session_open_failed (GDM_SESSION (session), conversation->service_name, text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
 gdm_session_direct_handle_session_started (GdmSessionDirect *session,
                                            GdmSessionConversation *conversation,
                                            DBusMessage      *message)
@@ -1206,6 +1258,10 @@ session_worker_message (DBusConnection *connection,
                 return gdm_session_direct_handle_accreditation_failed (session, conversation, message);
         } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) {
                 return gdm_session_direct_handle_username_changed (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionOpened")) {
+                return gdm_session_direct_handle_session_opened (session, conversation, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "OpenFailed")) {
+                return gdm_session_direct_handle_open_failed (session, conversation, message);
         } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) {
                 return gdm_session_direct_handle_session_started (session, conversation, message);
         } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartFailed")) {
@@ -2189,6 +2245,19 @@ setup_session_environment (GdmSessionDirect *session)
 }
 
 static void
+gdm_session_direct_open_session (GdmSession *session,
+                                 const char *service_name)
+{
+        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+        GdmSessionConversation *conversation;
+
+        g_return_if_fail (session != NULL);
+
+        conversation = find_conversation_by_name (impl, service_name);
+        send_dbus_void_signal (conversation, "OpenSession");
+}
+
+static void
 gdm_session_direct_start_session (GdmSession *session,
                                   const char *service_name)
 {
@@ -2663,6 +2732,7 @@ gdm_session_iface_init (GdmSessionIface *iface)
         iface->authenticate = gdm_session_direct_authenticate;
         iface->authorize = gdm_session_direct_authorize;
         iface->accredit = gdm_session_direct_accredit;
+        iface->open_session = gdm_session_direct_open_session;
         iface->close = gdm_session_direct_close;
 
         iface->cancel = gdm_session_direct_cancel;
diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h
index 860c09c..36781dd 100644
--- a/daemon/gdm-session-private.h
+++ b/daemon/gdm-session-private.h
@@ -54,6 +54,11 @@ void             _gdm_session_accredited                   (GdmSession   *sessio
 void             _gdm_session_accreditation_failed         (GdmSession   *session,
                                                             const char   *service_name,
                                                             const char   *text);
+void             _gdm_session_session_opened               (GdmSession   *session,
+                                                            const char   *service_name);
+void             _gdm_session_session_open_failed          (GdmSession   *session,
+                                                            const char   *service_name,
+                                                            const char   *message);
 void             _gdm_session_session_started              (GdmSession   *session,
                                                             const char   *service_name,
                                                             int           pid);
diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c
index 6e15f75..3bf8ed7 100644
--- a/daemon/gdm-session-relay.c
+++ b/daemon/gdm-session-relay.c
@@ -247,6 +247,14 @@ gdm_session_relay_accredit (GdmSession *session,
 }
 
 static void
+gdm_session_relay_open_session (GdmSession *session,
+                                const char *service_name)
+{
+        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
+        send_dbus_string_signal (impl, "OpenSession", service_name);
+}
+
+static void
 gdm_session_relay_answer_query (GdmSession *session,
                                 const char *service_name,
                                 const char *text)
@@ -678,6 +686,61 @@ handle_accreditation_failed (GdmSessionRelay *session_relay,
 
         return DBUS_HANDLER_RESULT_HANDLED;
 }
+static DBusHandlerResult
+handle_session_opened (GdmSessionRelay *session_relay,
+                       DBusConnection  *connection,
+                       DBusMessage     *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        char        *service_name;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &service_name,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+        dbus_error_free (&error);
+
+        g_debug ("GdmSessionRelay: Session Opened");
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        _gdm_session_session_opened (GDM_SESSION (session_relay), service_name);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+handle_session_open_failed (GdmSessionRelay *session_relay,
+                            DBusConnection  *connection,
+                            DBusMessage     *message)
+{
+        DBusMessage *reply;
+        DBusError    error;
+        char        *service_name;
+
+        dbus_error_init (&error);
+        if (! dbus_message_get_args (message, &error,
+                                     DBUS_TYPE_STRING, &service_name,
+                                     DBUS_TYPE_INVALID)) {
+                g_warning ("ERROR: %s", error.message);
+        }
+        dbus_error_free (&error);
+
+        g_debug ("GdmSessionRelay: Session Open Failed");
+
+        reply = dbus_message_new_method_return (message);
+        dbus_connection_send (connection, reply, NULL);
+        dbus_message_unref (reply);
+
+        _gdm_session_session_open_failed (GDM_SESSION (session_relay), service_name, NULL);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+}
 
 static DBusHandlerResult
 handle_session_started (GdmSessionRelay *session_relay,
@@ -794,6 +857,10 @@ session_handle_child_message (DBusConnection *connection,
                 return handle_accredited (session_relay, connection, message);
         } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "AccreditationFailed")) {
                 return handle_accreditation_failed (session_relay, connection, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionOpened")) {
+                return handle_session_opened (session_relay, connection, message);
+        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionOpenFailed")) {
+                return handle_session_open_failed (session_relay, connection, message);
         } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStarted")) {
                 return handle_session_started (session_relay, connection, message);
         } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStopped")) {
@@ -1193,6 +1260,7 @@ gdm_session_iface_init (GdmSessionIface *iface)
         iface->authenticate = gdm_session_relay_authenticate;
         iface->authorize = gdm_session_relay_authorize;
         iface->accredit = gdm_session_relay_accredit;
+        iface->open_session = gdm_session_relay_open_session;
         iface->close = gdm_session_relay_close;
 
         iface->cancel = gdm_session_relay_cancel;
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index bcd4f93..867ce67 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -2442,13 +2442,13 @@ do_open_session (GdmSessionWorker *worker)
         res = gdm_session_worker_open_user_session (worker, &error);
         if (! res) {
                 send_dbus_string_method (worker->priv->connection,
-                                         "StartFailed",
+                                         "OpenFailed",
                                          error->message);
                 g_error_free (error);
                 return;
         }
 
-        queue_state_change (worker);
+        send_dbus_void_method (worker->priv->connection, "SessionOpened");
 }
 
 static void
@@ -2564,7 +2564,7 @@ on_start_program (GdmSessionWorker *worker,
         const char *text;
         dbus_bool_t res;
 
-        if (worker->priv->state != GDM_SESSION_WORKER_STATE_ACCREDITED) {
+        if (worker->priv->state != GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
                 g_debug ("GdmSessionWorker: ignoring spurious start program while in state %s", get_state_name (worker->priv->state));
                 return;
         }
@@ -2723,6 +2723,14 @@ on_establish_credentials (GdmSessionWorker *worker,
 }
 
 static void
+on_open_session (GdmSessionWorker *worker,
+                 DBusMessage      *message)
+{
+        /* FIXME: return error if not in ACCREDITED state */
+        queue_state_change (worker);
+}
+
+static void
 on_reauthenticate (GdmSessionWorker *worker,
                    DBusMessage      *message)
 {
@@ -2794,6 +2802,8 @@ worker_dbus_handle_message (DBusConnection *connection,
                 on_authorize (worker, message);
         } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "EstablishCredentials")) {
                 on_establish_credentials (worker, message);
+        } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "OpenSession")) {
+                on_open_session (worker, message);
         } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "StartProgram")) {
                 on_start_program (worker, message);
         } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "Reauthenticate")) {
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 9ee34af..8858071 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -46,6 +46,8 @@ enum {
         PROBLEM,
         INFO_QUERY,
         SECRET_INFO_QUERY,
+        SESSION_OPENED,
+        SESSION_OPEN_FAILED,
         SESSION_STARTED,
         SESSION_START_FAILED,
         SESSION_EXITED,
@@ -207,6 +209,15 @@ gdm_session_cancel (GdmSession *session)
 }
 
 void
+gdm_session_open_session (GdmSession *session,
+                          const char *service_name)
+{
+        g_return_if_fail (GDM_IS_SESSION (session));
+
+        GDM_SESSION_GET_IFACE (session)->open_session (session, service_name);
+}
+
+void
 gdm_session_start_session (GdmSession *session,
                            const char *service_name)
 {
@@ -391,6 +402,28 @@ gdm_session_class_init (gpointer g_iface)
                               G_TYPE_NONE,
                               2,
                               G_TYPE_STRING, G_TYPE_STRING);
+        signals [SESSION_OPENED] =
+                g_signal_new ("session-opened",
+                              iface_type,
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GdmSessionIface, session_opened),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__STRING,
+                              G_TYPE_NONE,
+                              1,
+                              G_TYPE_STRING);
+        signals [SESSION_OPEN_FAILED] =
+                g_signal_new ("session-open-failed",
+                              iface_type,
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GdmSessionIface, session_open_failed),
+                              NULL,
+                              NULL,
+                              gdm_marshal_VOID__STRING_STRING,
+                              G_TYPE_NONE,
+                              2,
+                              G_TYPE_STRING, G_TYPE_STRING);
         signals [SESSION_STARTED] =
                 g_signal_new ("session-started",
                               iface_type,
@@ -616,6 +649,23 @@ _gdm_session_problem (GdmSession   *session,
 }
 
 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)
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index c45a770..22c2ccb 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -62,6 +62,8 @@ struct _GdmSessionIface
         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);
@@ -115,6 +117,11 @@ struct _GdmSessionIface
         void (* problem)                     (GdmSession   *session,
                                               const char   *service_name,
                                               const char   *problem);
+        void (* session_opened)              (GdmSession   *session,
+                                              const char   *service_name);
+        void (* session_open_failed)         (GdmSession   *session,
+                                              const char   *service_name,
+                                              const char   *message);
         void (* session_started)             (GdmSession   *session,
                                               const char   *service_name,
                                               int           pid);
@@ -160,6 +167,8 @@ void     gdm_session_authorize                   (GdmSession *session,
 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);
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 6eadf62..4c68974 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -423,7 +423,7 @@ on_session_accredited (GdmSession     *session,
                        const char     *service_name,
                        GdmSimpleSlave *slave)
 {
-        queue_start_session (slave, service_name);
+        gdm_session_open_session (session, service_name);
 }
 
 static void
@@ -463,6 +463,29 @@ on_session_accreditation_failed (GdmSession     *session,
 }
 
 static void
+on_session_opened (GdmSession     *session,
+                   const char     *service_name,
+                   GdmSimpleSlave *slave)
+{
+        queue_start_session (slave, service_name);
+}
+
+static void
+on_session_open_failed (GdmSession     *session,
+                        const char     *service_name,
+                        const char     *message,
+                        GdmSimpleSlave *slave)
+{
+        if (slave->priv->greeter_server != NULL) {
+                gdm_greeter_server_problem (slave->priv->greeter_server,
+                                            service_name,
+                                            _("Unable to open session"));
+        }
+
+        gdm_session_stop_conversation (session, service_name);
+}
+
+static void
 on_session_info (GdmSession     *session,
                  const char     *service_name,
                  const char     *text,
@@ -694,6 +717,14 @@ create_new_session (GdmSimpleSlave *slave)
                           G_CALLBACK (on_session_accreditation_failed),
                           slave);
         g_signal_connect (slave->priv->session,
+                          "session-opened",
+                          G_CALLBACK (on_session_opened),
+                          slave);
+        g_signal_connect (slave->priv->session,
+                          "session-open-failed",
+                          G_CALLBACK (on_session_open_failed),
+                          slave);
+        g_signal_connect (slave->priv->session,
                           "info",
                           G_CALLBACK (on_session_info),
                           slave);



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