From 09ec9b11ccfa932401406e07b45b4035adcfb167 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mar 03 2009 23:05:34 +0000 Subject: Regen patch to get rid of fuzz --- diff --git a/gdm-2.25.2-multistack-but-boring.patch b/gdm-2.25.2-multistack-but-boring.patch index 411f95f..67a1b54 100644 --- a/gdm-2.25.2-multistack-but-boring.patch +++ b/gdm-2.25.2-multistack-but-boring.patch @@ -1,1115 +1,716 @@ -From 0b295480d3f0955d7133c39c0c4b2ec3bd2f3084 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 11:00:08 -0500 -Subject: [PATCH 01/65] Drop session "Open" in favor of "StartConversation" - -We want to eventually support having multiple -simultaneous PAM conversations in one login -screen (so, e.g., username/password, smart card, and -fingerprint all work at the same time). - -This commit refactors the session code to be in terms -of a conversation object. With this change, it should -be easier later to have multiple conversation objects. - -The conversation is named by the pam service the login -screen is talking to. ---- - daemon/gdm-factory-slave.c | 13 +- - daemon/gdm-product-slave.c | 47 ++++++--- - daemon/gdm-session-direct.c | 250 ++++++++++++++++++++++++++---------------- - daemon/gdm-session-private.h | 3 +- - daemon/gdm-session-relay.c | 29 +++-- - daemon/gdm-session.c | 20 ++-- - daemon/gdm-session.h | 9 +- - daemon/gdm-simple-slave.c | 3 - - daemon/test-session.c | 13 +- - 9 files changed, 240 insertions(+), 147 deletions(-) - -diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c -index d09c913..6497293 100644 ---- a/daemon/gdm-factory-slave.c -+++ b/daemon/gdm-factory-slave.c -@@ -180,10 +180,11 @@ on_session_secret_info_query (GdmSession *session, +diff -up gdm-2.25.2/common/gdm-marshal.list.multistack-but-boring gdm-2.25.2/common/gdm-marshal.list +--- gdm-2.25.2/common/gdm-marshal.list.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/common/gdm-marshal.list 2009-03-03 17:45:05.814016242 -0500 +@@ -5,3 +5,4 @@ VOID:STRING,STRING + VOID:UINT,UINT + VOID:STRING,INT + VOID:DOUBLE ++BOOLEAN:STRING +diff -up gdm-2.25.2/configure.ac.multistack-but-boring gdm-2.25.2/configure.ac +--- gdm-2.25.2/configure.ac.multistack-but-boring 2009-03-03 17:45:05.512009633 -0500 ++++ gdm-2.25.2/configure.ac 2009-03-03 17:45:05.748016423 -0500 +@@ -18,6 +18,22 @@ AC_PROG_CXX + AM_PROG_CC_C_O + AC_PROG_LIBTOOL() + ++## increment if the plugin interface has additions, changes, removals. ++LT_CURRENT=1 ++ ++## increment any time the source changes; set to ++## 0 if you increment CURRENT ++LT_REVISION=0 ++ ++## increment if any interfaces have been added; set to 0 ++## if any interfaces have been changed or removed. removal has ++## precedence over adding, so set to 0 if both happened. ++LT_AGE=0 ++ ++AC_SUBST(LT_CURRENT) ++AC_SUBST(LT_REVISION) ++AC_SUBST(LT_AGE) ++ + AC_HEADER_STDC + + AC_SUBST(VERSION) +@@ -51,6 +67,7 @@ GNOME_PANEL_REQUIRED_VERSION=2.0.0 + LIBXKLAVIER_REQUIRED_VERSION=3.5 + #FONTCONFIG_REQUIRED_VERSION=2.6.0 + FONTCONFIG_REQUIRED_VERSION=2.5.0 ++NSS_REQUIRED_VERSION=3.11.1 + + EXTRA_COMPILE_WARNINGS(yes) + +@@ -74,6 +91,12 @@ PKG_CHECK_MODULES(DAEMON, + AC_SUBST(DAEMON_CFLAGS) + AC_SUBST(DAEMON_LIBS) + ++PKG_CHECK_MODULES(NSS, ++ nss >= $NSS_REQUIRED_VERSION ++) ++AC_SUBST(NSS_CFLAGS) ++AC_SUBST(NSS_LIBS) ++ + PKG_CHECK_MODULES(XLIB, x11 xau, , + [AC_PATH_XTRA + if test "x$no_x" = xyes; then +@@ -200,6 +223,15 @@ AC_ARG_WITH(dmconfdir, + AC_SUBST(dmconfdir) + + dnl --------------------------------------------------------------------------- ++dnl - Configuration file stuff ++dnl --------------------------------------------------------------------------- ++AC_ARG_WITH(extensionsdatadir, ++ AS_HELP_STRING([--with-extensions-datadir], ++ [directory where extensions store data, default=DATADIR/gdm/simple-greeter/extensions]), ++ extensionsdatadir=${withval}, extensionsdatadir=${datadir}/gdm/simple-greeter/extensions) ++AC_SUBST(extensionsdatadir) ++ ++dnl --------------------------------------------------------------------------- + dnl - Configure arguments + dnl --------------------------------------------------------------------------- + +@@ -1292,6 +1324,22 @@ AC_SUBST(GDM_SPOOL_DIR) + + + dnl --------------------------------------------------------------------------- ++dnl - Directory for simple greeter plugins ++dnl --------------------------------------------------------------------------- ++ ++AC_ARG_WITH(simple-greeter-plugins-dir, ++ AS_HELP_STRING([--with-simple-greeter-plugins-dir=], ++ [simple greeter plugins directory])) ++ ++if ! test -z "$with_simple_greeter_plugins_dir"; then ++ GDM_SIMPLE_GREETER_PLUGINS_DIR=$with_simple_greeter_plugins_dir ++else ++ GDM_SIMPLE_GREETER_PLUGINS_DIR=${libdir}/gdm/simple-greeter/plugins ++fi ++ ++AC_SUBST(GDM_SIMPLE_GREETER_PLUGINS_DIR) ++ ++dnl --------------------------------------------------------------------------- + dnl - Finish + dnl --------------------------------------------------------------------------- + +@@ -1420,6 +1468,12 @@ docs/Makefile + gui/Makefile + gui/simple-greeter/Makefile + gui/simple-greeter/libnotificationarea/Makefile ++gui/simple-greeter/libgdmsimplegreeter/Makefile ++gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc ++gui/simple-greeter/plugins/Makefile ++gui/simple-greeter/plugins/password/Makefile ++gui/simple-greeter/plugins/fingerprint/Makefile ++gui/simple-greeter/plugins/smartcard/Makefile + gui/simple-chooser/Makefile + gui/user-switch-applet/Makefile + utils/Makefile +diff -up gdm-2.25.2/daemon/gdm-factory-slave.c.multistack-but-boring gdm-2.25.2/daemon/gdm-factory-slave.c +--- gdm-2.25.2/daemon/gdm-factory-slave.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-factory-slave.c 2009-03-03 17:45:05.618017661 -0500 +@@ -144,63 +144,71 @@ on_greeter_session_died (GdmGreeterSessi + + static void + on_session_info (GdmSession *session, ++ const char *service_name, + const char *text, + GdmFactorySlave *slave) + { + g_debug ("GdmFactorySlave: Info: %s", text); +- gdm_greeter_server_info (slave->priv->greeter_server, text); ++ gdm_greeter_server_info (slave->priv->greeter_server, service_name, text); + } + + static void + on_session_problem (GdmSession *session, ++ const char *service_name, + const char *text, + GdmFactorySlave *slave) + { + g_debug ("GdmFactorySlave: Problem: %s", text); +- gdm_greeter_server_problem (slave->priv->greeter_server, text); ++ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, text); + } + + static void + on_session_info_query (GdmSession *session, ++ const char *service_name, + const char *text, + GdmFactorySlave *slave) + { + + g_debug ("GdmFactorySlave: Info query: %s", text); +- gdm_greeter_server_info_query (slave->priv->greeter_server, text); ++ gdm_greeter_server_info_query (slave->priv->greeter_server, service_name, text); + } + + static void + on_session_secret_info_query (GdmSession *session, ++ const char *service_name, + const char *text, + GdmFactorySlave *slave) + { + g_debug ("GdmFactorySlave: Secret info query: %s", text); +- gdm_greeter_server_secret_info_query (slave->priv->greeter_server, text); ++ gdm_greeter_server_secret_info_query (slave->priv->greeter_server, service_name, text); } static void -on_session_opened (GdmSession *session, - GdmFactorySlave *slave) +on_session_conversation_started (GdmSession *session, -+ GdmFactorySlave *slave, -+ const char *service_name) ++ const char *service_name, ++ GdmFactorySlave *slave) { - g_debug ("GdmFactorySlave: session opened"); + g_debug ("GdmFactorySlave: session conversation started"); - gdm_greeter_server_ready (slave->priv->greeter_server); +- gdm_greeter_server_ready (slave->priv->greeter_server); ++ gdm_greeter_server_ready (slave->priv->greeter_server, ++ service_name); } -@@ -367,7 +368,7 @@ on_session_relay_connected (GdmSessionRelay *session, - { - g_debug ("GdmFactorySlave: Relay Connected"); -- gdm_session_open (GDM_SESSION (slave->priv->session)); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), "gdm"); + static void + on_session_setup_complete (GdmSession *session, ++ const char *service_name, + GdmFactorySlave *slave) + { +- gdm_session_authenticate (session); ++ gdm_session_authenticate (session, service_name); } static void -@@ -694,8 +695,8 @@ gdm_factory_slave_start (GdmSlave *slave) + on_session_setup_failed (GdmSession *session, ++ const char *service_name, + const char *message, + GdmFactorySlave *slave) + { +- gdm_greeter_server_problem (slave->priv->greeter_server, _("Unable to initialize login system")); ++ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to initialize login system")); - GDM_FACTORY_SLAVE (slave)->priv->session = gdm_session_relay_new (); - g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, -- "opened", -- G_CALLBACK (on_session_opened), -+ "conversation-started", -+ G_CALLBACK (on_session_conversation_started), - slave); - g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, - "setup-complete", -diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c -index 9adcb09..15a2820 100644 ---- a/daemon/gdm-product-slave.c -+++ b/daemon/gdm-product-slave.c -@@ -246,19 +246,21 @@ relay_session_started (GdmProductSlave *slave, + queue_greeter_reset (slave); } +@@ -222,23 +230,26 @@ on_session_reset_failed (GdmSession static void --relay_session_opened (GdmProductSlave *slave) -+relay_session_conversation_started (GdmProductSlave *slave, -+ const char *service_name) + on_session_authenticated (GdmSession *session, ++ const char *service_name, + GdmFactorySlave *slave) { -- send_dbus_void_method (slave->priv->session_relay_connection, -- "Opened"); -+ send_dbus_string_method (slave->priv->session_relay_connection, -+ "ConversationStarted", service_name); +- gdm_session_authorize (session); ++ gdm_session_authorize (session, service_name); } static void --on_session_opened (GdmSession *session, -- GdmProductSlave *slave) -+on_session_conversation_started (GdmSession *session, -+ const char *service_name, -+ GdmProductSlave *slave) + on_session_authentication_failed (GdmSession *session, ++ const char *service_name, + const char *message, + GdmFactorySlave *slave) { -- g_debug ("GdmProductSlave: session opened"); -+ g_debug ("GdmProductSlave: session conversation started"); +- gdm_greeter_server_problem (slave->priv->greeter_server, _("Unable to authenticate user")); ++ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to authenticate user")); -- relay_session_opened (slave); -+ relay_session_conversation_started (slave, service_name); + queue_greeter_reset (slave); } static void -@@ -784,10 +786,27 @@ on_relay_user_selected (GdmProductSlave *slave, + on_session_authorized (GdmSession *session, ++ const char *service_name, + GdmFactorySlave *slave) + { + int flag; +@@ -246,39 +257,42 @@ on_session_authorized (GdmSession * + /* FIXME: check for migration? */ + flag = GDM_SESSION_CRED_ESTABLISH; + +- gdm_session_accredit (session, flag); ++ gdm_session_accredit (session, service_name, flag); } static void --on_relay_open (GdmProductSlave *slave, -- DBusMessage *message) -+on_relay_start_conversation (GdmProductSlave *slave, -+ DBusMessage *message) + on_session_authorization_failed (GdmSession *session, ++ const char *service_name, + const char *message, + GdmFactorySlave *slave) { -- gdm_session_open (GDM_SESSION (slave->priv->session)); -+ DBusError error; -+ char *service_name; -+ dbus_bool_t res; -+ -+ dbus_error_init (&error); -+ res = dbus_message_get_args (message, -+ &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID); -+ if (res) { -+ g_debug ("GdmProductSlave: Started conversation with %s service", service_name); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), -+ service_name); -+ } else { -+ g_warning ("Unable to get arguments: %s", error.message); -+ } -+ -+ dbus_error_free (&error); +- gdm_greeter_server_problem (slave->priv->greeter_server, _("Unable to authorize user")); ++ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to authorize user")); + + queue_greeter_reset (slave); } static void -@@ -832,8 +851,8 @@ create_new_session (GdmProductSlave *slave) - g_free (display_device); + on_session_accredited (GdmSession *session, ++ const char *service_name, + GdmFactorySlave *slave) + { + g_debug ("GdmFactorySlave: session user verified"); - g_signal_connect (slave->priv->session, -- "opened", -- G_CALLBACK (on_session_opened), -+ "conversation-started", -+ G_CALLBACK (on_session_conversation_started), - slave); - g_signal_connect (slave->priv->session, - "setup-complete", -@@ -991,8 +1010,8 @@ relay_dbus_handle_message (DBusConnection *connection, - on_relay_user_selected (slave, message); - } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "StartSession")) { - on_relay_start_session (slave, message); -- } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Open")) { -- on_relay_open (slave, message); -+ } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "StartConversation")) { -+ on_relay_start_conversation (slave, message); - } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Cancelled")) { - on_relay_cancelled (slave, message); - } else { -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 34a126f..a76051b 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -61,6 +61,15 @@ - #define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin" - #endif - -+typedef struct -+{ -+ GdmSessionDirect *session; -+ GdmSessionWorkerJob *job; -+ GPid worker_pid; -+ char *service_name; -+ DBusConnection *worker_connection; -+} GdmSessionConversation; -+ - struct _GdmSessionDirectPrivate - { - /* per open scope */ -@@ -74,10 +83,9 @@ struct _GdmSessionDirectPrivate - char *user_x11_authority_file; - - DBusMessage *message_pending_reply; -- DBusConnection *worker_connection; - -- GdmSessionWorkerJob *job; -- GPid session_pid; -+ GdmSessionConversation *conversation; -+ - guint32 is_authenticated : 1; - guint32 is_running : 1; - -@@ -147,6 +155,7 @@ send_dbus_string_signal (GdmSessionDirect *session, - { - DBusMessage *message; - DBusMessageIter iter; -+ GdmSessionConversation *conversation; - - g_return_if_fail (session != NULL); - -@@ -157,7 +166,8 @@ send_dbus_string_signal (GdmSessionDirect *session, - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text); +- gdm_session_start_session (session); ++ gdm_session_start_session (session, service_name); -- if (! send_dbus_message (session->priv->worker_connection, message)) { -+ conversation = session->priv->conversation; -+ if (! send_dbus_message (conversation->worker_connection, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", name); - } + gdm_greeter_server_reset (slave->priv->greeter_server); + } -@@ -169,6 +179,7 @@ send_dbus_void_signal (GdmSessionDirect *session, - const char *name) + static void + on_session_accreditation_failed (GdmSession *session, ++ const char *service_name, + const char *message, + GdmFactorySlave *slave) { - DBusMessage *message; -+ GdmSessionConversation *conversation; - - g_return_if_fail (session != NULL); - -@@ -176,7 +187,8 @@ send_dbus_void_signal (GdmSessionDirect *session, - GDM_SESSION_DBUS_INTERFACE, - name); + g_debug ("GdmFactorySlave: could not successfully authenticate user: %s", + message); -- if (! send_dbus_message (session->priv->worker_connection, message)) { -+ conversation = session->priv->conversation; -+ if (! send_dbus_message (conversation->worker_connection, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", name); - } +- gdm_greeter_server_problem (slave->priv->greeter_server, _("Unable to establish credentials")); ++ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to establish credentials")); -@@ -188,22 +200,32 @@ on_authentication_failed (GdmSession *session, - const char *message) + queue_greeter_reset (slave); + } +@@ -366,37 +380,48 @@ on_session_relay_connected (GdmSessionRe + GdmFactorySlave *slave) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- gdm_session_record_failed (impl->priv->session_pid, -- impl->priv->selected_user, -- impl->priv->display_hostname, -- impl->priv->display_name, -- impl->priv->display_device); -+ GdmSessionConversation *conversation; + g_debug ("GdmFactorySlave: Relay Connected"); ++} + -+ conversation = impl->priv->conversation; -+ if (conversation != NULL) { -+ gdm_session_record_failed (conversation->worker_pid, -+ impl->priv->selected_user, -+ impl->priv->display_hostname, -+ impl->priv->display_name, -+ impl->priv->display_device); -+ } ++static void ++on_greeter_start_conversation (GdmGreeterServer *greeter_server, ++ const char *service_name, ++ GdmFactorySlave *slave) ++{ ++ g_debug ("GdmFactorySlave: start conversation"); + +- gdm_session_open (GDM_SESSION (slave->priv->session)); ++ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), service_name); } static void - on_session_started (GdmSession *session) + on_greeter_begin_verification (GdmGreeterServer *greeter_server, ++ const char *service_name, + GdmFactorySlave *slave) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- gdm_session_record_login (impl->priv->session_pid, -- impl->priv->selected_user, -- impl->priv->display_hostname, -- impl->priv->display_name, -- impl->priv->display_device); -+ GdmSessionConversation *conversation; -+ -+ conversation = impl->priv->conversation; -+ if (conversation != NULL) { -+ gdm_session_record_login (conversation->worker_pid, -+ impl->priv->selected_user, -+ impl->priv->display_hostname, -+ impl->priv->display_name, -+ impl->priv->display_device); -+ } + g_debug ("GdmFactorySlave: begin verification"); + gdm_session_setup (GDM_SESSION (slave->priv->session), +- "gdm"); ++ service_name); } static void -@@ -211,11 +233,16 @@ on_session_start_failed (GdmSession *session, - const char *message) + on_greeter_begin_verification_for_user (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *username, + GdmFactorySlave *slave) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- gdm_session_record_login (impl->priv->session_pid, -- impl->priv->selected_user, -- impl->priv->display_hostname, -- impl->priv->display_name, -- impl->priv->display_device); -+ GdmSessionConversation *conversation; -+ -+ conversation = impl->priv->conversation; -+ if (conversation != NULL) { -+ gdm_session_record_login (conversation->worker_pid, -+ impl->priv->selected_user, -+ impl->priv->display_hostname, -+ impl->priv->display_name, -+ impl->priv->display_device); -+ } + g_debug ("GdmFactorySlave: begin verification for user"); + gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), +- "gdm", ++ service_name, + username); } static void -@@ -223,11 +250,16 @@ on_session_exited (GdmSession *session, - int exit_code) + on_greeter_answer (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text, + GdmFactorySlave *slave) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- gdm_session_record_logout (impl->priv->session_pid, -- impl->priv->selected_user, -- impl->priv->display_hostname, -- impl->priv->display_name, -- impl->priv->display_device); -+ GdmSessionConversation *conversation; -+ -+ conversation = impl->priv->conversation; -+ if (conversation != NULL) { -+ gdm_session_record_logout (conversation->worker_pid, -+ impl->priv->selected_user, -+ impl->priv->display_hostname, -+ impl->priv->display_name, -+ impl->priv->display_device); -+ } + g_debug ("GdmFactorySlave: Greeter answer"); +- gdm_session_answer_query (GDM_SESSION (slave->priv->session), text); ++ gdm_session_answer_query (GDM_SESSION (slave->priv->session), service_name, text); } - static DBusHandlerResult -@@ -734,6 +766,7 @@ static void - cancel_pending_query (GdmSessionDirect *session) - { - DBusMessage *reply; -+ GdmSessionConversation *conversation; - - if (session->priv->message_pending_reply == NULL) { - return; -@@ -744,8 +777,9 @@ cancel_pending_query (GdmSessionDirect *session) - reply = dbus_message_new_error (session->priv->message_pending_reply, - GDM_SESSION_DBUS_ERROR_CANCEL, - "Operation cancelled"); -- dbus_connection_send (session->priv->worker_connection, reply, NULL); -- dbus_connection_flush (session->priv->worker_connection); -+ conversation = session->priv->conversation; -+ dbus_connection_send (conversation->worker_connection, reply, NULL); -+ dbus_connection_flush (conversation->worker_connection); - - dbus_message_unref (reply); - dbus_message_unref (session->priv->message_pending_reply); -@@ -758,6 +792,7 @@ answer_pending_query (GdmSessionDirect *session, - { - DBusMessage *reply; - DBusMessageIter iter; -+ GdmSessionConversation *conversation; - - g_assert (session->priv->message_pending_reply != NULL); - -@@ -765,7 +800,8 @@ answer_pending_query (GdmSessionDirect *session, - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &answer); - -- dbus_connection_send (session->priv->worker_connection, reply, NULL); -+ conversation = session->priv->conversation; -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - dbus_message_unref (session->priv->message_pending_reply); -@@ -923,7 +959,7 @@ gdm_session_direct_handle_session_started (GdmSessionDirect *session, - g_debug ("GdmSessionDirect: Emitting 'session-started' signal with pid '%d'", - pid); - -- session->priv->session_pid = pid; -+ session->priv->conversation->worker_pid = pid; - session->priv->is_running = TRUE; - - _gdm_session_session_started (GDM_SESSION (session), pid); -@@ -1439,16 +1475,18 @@ handle_connection (DBusServer *server, - void *user_data) - { - GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); -+ GdmSessionConversation *conversation; - - g_debug ("GdmSessionDirect: Handing new connection"); - -- if (session->priv->worker_connection == NULL) { -+ conversation = session->priv->conversation; -+ if (conversation->worker_connection == NULL) { - DBusObjectPathVTable vtable = { &session_unregister_handler, - &session_message_handler, - NULL, NULL, NULL, NULL - }; + static void +@@ -493,6 +518,10 @@ run_greeter (GdmFactorySlave *slave) -- session->priv->worker_connection = new_connection; -+ conversation->worker_connection = new_connection; - dbus_connection_ref (new_connection); - dbus_connection_setup_with_g_main (new_connection, NULL); + slave->priv->greeter_server = gdm_greeter_server_new (display_id); + g_signal_connect (slave->priv->greeter_server, ++ "start-conversation", ++ G_CALLBACK (on_greeter_start_conversation), ++ slave); ++ g_signal_connect (slave->priv->greeter_server, + "begin-verification", + G_CALLBACK (on_greeter_begin_verification), + slave); +@@ -694,8 +723,8 @@ gdm_factory_slave_start (GdmSlave *slave -@@ -1465,8 +1503,9 @@ handle_connection (DBusServer *server, - &vtable, - session); + GDM_FACTORY_SLAVE (slave)->priv->session = gdm_session_relay_new (); + g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, +- "opened", +- G_CALLBACK (on_session_opened), ++ "conversation-started", ++ G_CALLBACK (on_session_conversation_started), + slave); + g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, + "setup-complete", +diff -up gdm-2.25.2/daemon/gdm-greeter-server.c.multistack-but-boring gdm-2.25.2/daemon/gdm-greeter-server.c +--- gdm-2.25.2/daemon/gdm-greeter-server.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-greeter-server.c 2009-03-03 17:45:05.783016614 -0500 +@@ -43,6 +43,7 @@ + #include + #include -- g_debug ("GdmSessionDirect: Emitting opened signal"); -- _gdm_session_opened (GDM_SESSION (session)); -+ g_debug ("GdmSessionDirect: Emitting conversation-started signal"); -+ _gdm_session_conversation_started (GDM_SESSION (session), -+ conversation->service_name); - } - } ++#include "gdm-marshal.h" + #include "gdm-greeter-server.h" -@@ -1536,8 +1575,6 @@ gdm_session_direct_init (GdmSessionDirect *session) - G_CALLBACK (on_session_exited), - NULL); + #define GDM_GREETER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/GreeterServer" +@@ -69,6 +70,7 @@ enum { + }; -- session->priv->session_pid = -1; -- - session->priv->environment = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, -@@ -1548,15 +1585,15 @@ gdm_session_direct_init (GdmSessionDirect *session) + enum { ++ START_CONVERSATION, + BEGIN_AUTO_LOGIN, + BEGIN_VERIFICATION, + BEGIN_VERIFICATION_FOR_USER, +@@ -155,6 +157,46 @@ send_dbus_string_and_int_signal (GdmGree } static void --worker_stopped (GdmSessionWorkerJob *job, -- GdmSessionDirect *session) -+worker_stopped (GdmSessionWorkerJob *job, -+ GdmSessionConversation *conversation) - { - g_debug ("GdmSessionDirect: Worker job stopped"); - } - - static void - worker_started (GdmSessionWorkerJob *job, -- GdmSessionDirect *session) -+ GdmSessionConversation *conversation) - { - g_debug ("GdmSessionDirect: Worker job started"); - } -@@ -1564,106 +1601,118 @@ worker_started (GdmSessionWorkerJob *job, - static void - worker_exited (GdmSessionWorkerJob *job, - int code, -- GdmSessionDirect *session) -+ GdmSessionConversation *conversation) - { - g_debug ("GdmSessionDirect: Worker job exited: %d", code); ++send_dbus_string_string_signal (GdmGreeterServer *greeter_server, ++ const char *name, ++ const char *text1, ++ const char *text2) ++{ ++ DBusMessage *message; ++ DBusMessageIter iter; ++ const char *str; ++ ++ g_return_if_fail (greeter_server != NULL); ++ ++ message = dbus_message_new_signal (GDM_GREETER_SERVER_DBUS_PATH, ++ GDM_GREETER_SERVER_DBUS_INTERFACE, ++ name); ++ ++ dbus_message_iter_init_append (message, &iter); ++ ++ if (text1 != NULL) { ++ str = text1; ++ } else { ++ str = ""; ++ } ++ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str); ++ ++ if (text2 != NULL) { ++ str = text2; ++ } else { ++ str = ""; ++ } ++ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str); ++ ++ g_debug ("GreeterServer: Sending %s (%s)", name, str); ++ if (! send_dbus_message (greeter_server->priv->greeter_connection, message)) { ++ g_debug ("GreeterServer: Could not send %s signal", name); ++ } ++ ++ dbus_message_unref (message); ++} ++ ++static void + send_dbus_string_signal (GdmGreeterServer *greeter_server, + const char *name, + const char *text) +@@ -207,34 +249,38 @@ send_dbus_void_signal (GdmGreeterServer -- if (!session->priv->is_authenticated) { -+ if (!conversation->session->priv->is_authenticated) { - char *msg; + gboolean + gdm_greeter_server_info_query (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text) + { +- send_dbus_string_signal (greeter_server, "InfoQuery", text); ++ send_dbus_string_string_signal (greeter_server, "InfoQuery", service_name, text); - msg = g_strdup_printf (_("worker exited with status %d"), code); -- _gdm_session_authentication_failed (GDM_SESSION (session), msg); -+ _gdm_session_authentication_failed (GDM_SESSION (conversation->session), msg); - g_free (msg); -- } else if (session->priv->is_running) { -- _gdm_session_session_exited (GDM_SESSION (session), code); -+ } else if (conversation->session->priv->is_running) { -+ _gdm_session_session_exited (GDM_SESSION (conversation->session), code); - } + return TRUE; } - static void - worker_died (GdmSessionWorkerJob *job, - int signum, -- GdmSessionDirect *session) -+ GdmSessionConversation *conversation) + gboolean + gdm_greeter_server_secret_info_query (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text) { - g_debug ("GdmSessionDirect: Worker job died: %d", signum); - -- if (!session->priv->is_authenticated) { -+ if (!conversation->session->priv->is_authenticated) { - char *msg; - - msg = g_strdup_printf (_("worker exited with status %d"), signum); -- _gdm_session_authentication_failed (GDM_SESSION (session), msg); -+ _gdm_session_authentication_failed (GDM_SESSION (conversation->session), msg); - g_free (msg); -- } else if (session->priv->is_running) { -- _gdm_session_session_died (GDM_SESSION (session), signum); -+ } else if (conversation->session->priv->is_running) { -+ _gdm_session_session_died (GDM_SESSION (conversation->session), signum); - } +- send_dbus_string_signal (greeter_server, "SecretInfoQuery", text); ++ send_dbus_string_string_signal (greeter_server, "SecretInfoQuery", service_name, text); + return TRUE; } --static gboolean --start_worker (GdmSessionDirect *session) -+static GdmSessionConversation * -+start_conversation (GdmSessionDirect *session, -+ const char *service_name) + gboolean + gdm_greeter_server_info (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text) { -- gboolean res; -+ GdmSessionConversation *conversation; - -- session->priv->job = gdm_session_worker_job_new (); -- gdm_session_worker_job_set_server_address (session->priv->job, session->priv->server_address); -- g_signal_connect (session->priv->job, -+ conversation = g_new0 (GdmSessionConversation, 1); -+ conversation->session = session; -+ 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, session->priv->server_address); -+ g_signal_connect (conversation->job, - "stopped", - G_CALLBACK (worker_stopped), -- session); -- g_signal_connect (session->priv->job, -+ conversation); -+ g_signal_connect (conversation->job, - "started", - G_CALLBACK (worker_started), -- session); -- g_signal_connect (session->priv->job, -+ conversation); -+ g_signal_connect (conversation->job, - "exited", - G_CALLBACK (worker_exited), -- session); -- g_signal_connect (session->priv->job, -+ conversation); -+ g_signal_connect (conversation->job, - "died", - G_CALLBACK (worker_died), -- session); -+ conversation); - -- res = gdm_session_worker_job_start (session->priv->job); -+ if (!gdm_session_worker_job_start (conversation->job)) { -+ g_object_unref (conversation->job); -+ g_free (conversation->service_name); -+ g_free (conversation); -+ return NULL; -+ } - -- return res; -+ return conversation; +- send_dbus_string_signal (greeter_server, "Info", text); ++ send_dbus_string_string_signal (greeter_server, "Info", service_name, text); + return TRUE; } - static void --stop_worker (GdmSessionDirect *session) -+stop_conversation (GdmSessionConversation *conversation) + gboolean + gdm_greeter_server_problem (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text) { -- g_signal_handlers_disconnect_by_func (session->priv->job, -+ g_signal_handlers_disconnect_by_func (conversation->job, - G_CALLBACK (worker_stopped), -- session); -- g_signal_handlers_disconnect_by_func (session->priv->job, -+ conversation); -+ g_signal_handlers_disconnect_by_func (conversation->job, - G_CALLBACK (worker_started), -- session); -- g_signal_handlers_disconnect_by_func (session->priv->job, -+ conversation); -+ g_signal_handlers_disconnect_by_func (conversation->job, - G_CALLBACK (worker_exited), -- session); -- g_signal_handlers_disconnect_by_func (session->priv->job, -+ conversation); -+ g_signal_handlers_disconnect_by_func (conversation->job, - G_CALLBACK (worker_died), -- session); -+ conversation); - -- cancel_pending_query (session); -+ cancel_pending_query (conversation->session); - -- if (session->priv->worker_connection != NULL) { -- dbus_connection_close (session->priv->worker_connection); -- session->priv->worker_connection = NULL; -+ if (conversation->worker_connection != NULL) { -+ dbus_connection_close (conversation->worker_connection); -+ conversation->worker_connection = NULL; - } +- send_dbus_string_signal (greeter_server, "Problem", text); ++ send_dbus_string_string_signal (greeter_server, "Problem", service_name, text); + return TRUE; + } -- gdm_session_worker_job_stop (session->priv->job); -- g_object_unref (session->priv->job); -- session->priv->job = NULL; -+ gdm_session_worker_job_stop (conversation->job); -+ g_object_unref (conversation->job); -+ g_free (conversation->service_name); -+ g_free (conversation); +@@ -246,9 +292,18 @@ gdm_greeter_server_reset (GdmGreeterServ } - static void --gdm_session_direct_open (GdmSession *session) -+gdm_session_direct_start_conversation (GdmSession *session, -+ const char *service_name) + gboolean +-gdm_greeter_server_ready (GdmGreeterServer *greeter_server) ++gdm_greeter_server_ready (GdmGreeterServer *greeter_server, ++ const char *service_name) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - - g_return_if_fail (session != NULL); - -- g_debug ("GdmSessionDirect: Opening session"); -+ g_debug ("GdmSessionDirect: starting conversation"); - -- start_worker (impl); -+ impl->priv->conversation = start_conversation (impl, service_name); +- send_dbus_void_signal (greeter_server, "Ready"); ++ send_dbus_string_signal (greeter_server, "Ready", service_name); ++ return TRUE; ++} ++ ++gboolean ++gdm_greeter_server_conversation_stopped (GdmGreeterServer *greeter_server, ++ const char *service_name) ++{ ++ send_dbus_string_signal (greeter_server, "ConversationStopped", service_name); + return TRUE; } - static void -@@ -1676,6 +1725,7 @@ send_setup (GdmSessionDirect *session, - const char *display_device; - const char *display_hostname; - const char *display_x11_authority_file; -+ GdmSessionConversation *conversation; - - g_assert (service_name != NULL); +@@ -289,9 +344,10 @@ gdm_greeter_server_request_timed_login ( + } -@@ -1713,7 +1763,8 @@ send_setup (GdmSessionDirect *session, - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file); + void +-gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server) ++gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server, ++ const char *service_name) + { +- send_dbus_void_signal (greeter_server, "UserAuthorized"); ++ send_dbus_string_signal (greeter_server, "UserAuthorized", service_name); + } -- if (! send_dbus_message (session->priv->worker_connection, message)) { -+ conversation = session->priv->conversation; -+ if (! send_dbus_message (conversation->worker_connection, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "Setup"); - } + /* Note: Use abstract sockets like dbus does by default on Linux. Abstract +@@ -323,11 +379,49 @@ generate_address (void) + } -@@ -1731,6 +1782,7 @@ send_setup_for_user (GdmSessionDirect *session, - const char *display_hostname; - const char *display_x11_authority_file; - const char *selected_user; -+ GdmSessionConversation *conversation; - - g_assert (service_name != NULL); - -@@ -1774,7 +1826,8 @@ send_setup_for_user (GdmSessionDirect *session, - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &selected_user); - -- if (! send_dbus_message (session->priv->worker_connection, message)) { -+ conversation = session->priv->conversation; -+ if (! send_dbus_message (conversation->worker_connection, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForUser"); - } - -@@ -1788,7 +1841,8 @@ gdm_session_direct_setup (GdmSession *session, - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - - g_return_if_fail (session != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); -+ g_return_if_fail (impl->priv->conversation != NULL); -+ g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - - send_setup (impl, service_name); - gdm_session_direct_defaults_changed (impl); -@@ -1802,7 +1856,8 @@ gdm_session_direct_setup_for_user (GdmSession *session, - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - - g_return_if_fail (session != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); -+ g_return_if_fail (impl->priv->conversation != NULL); -+ g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - g_return_if_fail (username != NULL); - - gdm_session_direct_select_user (session, username); -@@ -1817,7 +1872,8 @@ gdm_session_direct_authenticate (GdmSession *session) - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - - g_return_if_fail (session != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); -+ g_return_if_fail (impl->priv->conversation != NULL); -+ g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - - send_dbus_void_signal (impl, "Authenticate"); - } -@@ -1828,7 +1884,8 @@ gdm_session_direct_authorize (GdmSession *session) - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - - g_return_if_fail (session != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); -+ g_return_if_fail (impl->priv->conversation != NULL); -+ g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - - send_dbus_void_signal (impl, "Authorize"); - } -@@ -1840,7 +1897,8 @@ gdm_session_direct_accredit (GdmSession *session, - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - - g_return_if_fail (session != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); -+ g_return_if_fail (impl->priv->conversation != NULL); -+ g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - - switch (cred_flag) { - case GDM_SESSION_CRED_ESTABLISH: -@@ -1861,6 +1919,7 @@ send_environment_variable (const char *key, + static DBusHandlerResult ++handle_start_conversation (GdmGreeterServer *greeter_server, ++ DBusConnection *connection, ++ DBusMessage *message) ++{ ++ DBusMessage *reply; ++ DBusError error; ++ const 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 ("GreeterServer: StartConversation"); ++ ++ reply = dbus_message_new_method_return (message); ++ dbus_connection_send (connection, reply, NULL); ++ dbus_message_unref (reply); ++ ++ g_signal_emit (greeter_server, signals [START_CONVERSATION], 0, service_name); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ ++static DBusHandlerResult + handle_begin_verification (GdmGreeterServer *greeter_server, + DBusConnection *connection, + DBusMessage *message) { - DBusMessage *message; - DBusMessageIter iter; -+ GdmSessionConversation *conversation; + DBusMessage *reply; ++ DBusError error; ++ const 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); - message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, - GDM_SESSION_DBUS_INTERFACE, -@@ -1870,7 +1929,8 @@ send_environment_variable (const char *key, - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value); + g_debug ("GreeterServer: BeginVerification"); -- if (! send_dbus_message (session->priv->worker_connection, message)) { -+ conversation = session->priv->conversation; -+ if (! send_dbus_message (conversation->worker_connection, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable"); - } +@@ -335,7 +429,7 @@ handle_begin_verification (GdmGreeterSer + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); -@@ -2026,16 +2086,17 @@ gdm_session_direct_close (GdmSession *session) +- g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION], 0); ++ g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION], 0, service_name); - g_debug ("GdmSessionDirect: Closing session"); + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -349,7 +443,6 @@ handle_begin_auto_login (GdmGreeterServe + DBusError error; + const char *text; -- if (impl->priv->job != NULL) { -+ if (impl->priv->conversation != NULL) { - if (impl->priv->is_running) { -- gdm_session_record_logout (impl->priv->session_pid, -+ gdm_session_record_logout (impl->priv->conversation->worker_pid, - impl->priv->selected_user, - impl->priv->display_hostname, - impl->priv->display_name, - impl->priv->display_device); - } +- + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &text, +@@ -376,13 +469,16 @@ handle_begin_verification_for_user (GdmG + DBusMessage *reply; + DBusError error; + const char *text; ++ const char *service_name; -- stop_worker (impl); -+ stop_conversation (impl->priv->conversation); -+ impl->priv->conversation = NULL; + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_INVALID)) { + g_warning ("ERROR: %s", error.message); } ++ dbus_error_free (&error); - g_free (impl->priv->selected_user); -@@ -2064,7 +2125,6 @@ gdm_session_direct_close (GdmSession *session) - - g_hash_table_remove_all (impl->priv->environment); - -- impl->priv->session_pid = -1; - impl->priv->is_authenticated = FALSE; - impl->priv->is_running = FALSE; - } -@@ -2408,7 +2468,7 @@ gdm_session_direct_constructor (GType type, - static void - gdm_session_iface_init (GdmSessionIface *iface) - { -- iface->open = gdm_session_direct_open; -+ iface->start_conversation = gdm_session_direct_start_conversation; - iface->setup = gdm_session_direct_setup; - iface->setup_for_user = gdm_session_direct_setup_for_user; - iface->authenticate = gdm_session_direct_authenticate; -diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h -index 6a6fcfc..074aa6f 100644 ---- a/daemon/gdm-session-private.h -+++ b/daemon/gdm-session-private.h -@@ -27,7 +27,8 @@ - G_BEGIN_DECLS + g_debug ("GreeterServer: BeginVerificationForUser for '%s'", text); - /* state changes */ --void _gdm_session_opened (GdmSession *session); -+void _gdm_session_conversation_started (GdmSession *session, -+ const char *service_name); - void _gdm_session_setup_complete (GdmSession *session); - void _gdm_session_setup_failed (GdmSession *session, - const char *message); -diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c -index b57bf89..35b4738 100644 ---- a/daemon/gdm-session-relay.c -+++ b/daemon/gdm-session-relay.c -@@ -180,10 +180,11 @@ send_dbus_void_signal (GdmSessionRelay *session_relay, - } +@@ -390,7 +486,7 @@ handle_begin_verification_for_user (GdmG + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); - static void --gdm_session_relay_open (GdmSession *session) -+gdm_session_relay_start_conversation (GdmSession *session, -+ const char *service_name) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -- send_dbus_void_signal (impl, "Open"); -+ send_dbus_string_signal (impl, "StartConversation", service_name); - } +- g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION_FOR_USER], 0, text); ++ g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION_FOR_USER], 0, service_name, text); - static void -@@ -664,22 +665,28 @@ handle_session_stopped (GdmSessionRelay *session_relay, + return DBUS_HANDLER_RESULT_HANDLED; } - - static DBusHandlerResult --handle_opened (GdmSessionRelay *session_relay, -+handle_conversation_started (GdmSessionRelay *session_relay, - DBusConnection *connection, - DBusMessage *message) - { +@@ -403,13 +499,16 @@ handle_answer_query (GdmGreeterServer *g DBusMessage *reply; DBusError error; -+ char *service_name; + const char *text; ++ const char *service_name; dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, + if (! dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } + DBUS_TYPE_STRING, &text, + DBUS_TYPE_INVALID)) { + g_warning ("ERROR: %s", error.message); + } ++ dbus_error_free (&error); -- g_debug ("GdmSessionRelay: Opened"); -+ g_debug ("GdmSessionRelay: Conversation Started"); + g_debug ("GreeterServer: AnswerQuery"); - reply = dbus_message_new_method_return (message); +@@ -417,7 +516,7 @@ handle_answer_query (GdmGreeterServer *g dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); -- _gdm_session_opened (GDM_SESSION (session_relay)); -+ _gdm_session_conversation_started (GDM_SESSION (session_relay), service_name); +- g_signal_emit (greeter_server, signals [QUERY_ANSWER], 0, text); ++ g_signal_emit (greeter_server, signals [QUERY_ANSWER], 0, service_name, text); return DBUS_HANDLER_RESULT_HANDLED; } -@@ -719,8 +726,8 @@ session_handle_child_message (DBusConnection *connection, - return handle_session_started (session_relay, connection, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStopped")) { - return handle_session_stopped (session_relay, connection, message); -- } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Opened")) { -- return handle_opened (session_relay, connection, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "ConversationStarted")) { -+ return handle_conversation_started (session_relay, connection, message); +@@ -614,9 +713,11 @@ handle_start_session_when_ready (GdmGree + DBusMessage *reply; + DBusError error; + gboolean should_start_session; ++ char *service_name; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, + DBUS_TYPE_BOOLEAN, &should_start_session, + DBUS_TYPE_INVALID)) { + g_warning ("ERROR: %s", error.message); +@@ -630,9 +731,9 @@ handle_start_session_when_ready (GdmGree + dbus_message_unref (reply); + + if (should_start_session) { +- g_signal_emit (greeter_server, signals [START_SESSION_WHEN_READY], 0); ++ g_signal_emit (greeter_server, signals [START_SESSION_WHEN_READY], 0, service_name); + } else { +- g_signal_emit (greeter_server, signals [START_SESSION_LATER] ,0); ++ g_signal_emit (greeter_server, signals [START_SESSION_LATER] ,0, service_name); } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -@@ -749,7 +756,8 @@ do_introspect (DBusConnection *connection, + return DBUS_HANDLER_RESULT_HANDLED; +@@ -645,7 +746,9 @@ greeter_handle_child_message (DBusConnec + { + GdmGreeterServer *greeter_server = GDM_GREETER_SERVER (user_data); + +- if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginVerification")) { ++ if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "StartConversation")) { ++ return handle_start_conversation (greeter_server, connection, message); ++ } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginVerification")) { + return handle_begin_verification (greeter_server, connection, message); + } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginVerificationForUser")) { + return handle_begin_verification_for_user (greeter_server, connection, message); +@@ -699,13 +802,23 @@ do_introspect (DBusConnection *connectio /* interface */ xml = g_string_append (xml, - " \n" -- " \n" -+ " \n" + " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" + " \n" + " \n" ++ " \n" + " \n" " \n" - " \n" + " \n" ++ " \n" + " \n" " \n" -@@ -810,7 +818,8 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - -- " \n" -+ " \n" -+ " \n" + " \n" ++ " \n" + " \n" + " \n" + " \n" +@@ -728,18 +841,23 @@ do_introspect (DBusConnection *connectio + " \n" + " \n" + " \n" ++ " \n" + " \n" + " \n" + " \n" ++ " \n" + " \n" " \n" - " \n" + " \n" ++ " \n" + " \n" " \n" -@@ -1106,7 +1115,7 @@ static void - gdm_session_iface_init (GdmSessionIface *iface) - { - -- iface->open = gdm_session_relay_open; -+ iface->start_conversation = gdm_session_relay_start_conversation; - iface->setup = gdm_session_relay_setup; - iface->setup_for_user = gdm_session_relay_setup_for_user; - iface->authenticate = gdm_session_relay_authenticate; -diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c -index feb7938..0073294 100644 ---- a/daemon/gdm-session.c -+++ b/daemon/gdm-session.c -@@ -28,7 +28,7 @@ - #include "gdm-session-private.h" - - enum { -- OPENED = 0, -+ CONVERSATION_STARTED = 0, - SETUP_COMPLETE, - SETUP_FAILED, - RESET_COMPLETE, -@@ -78,11 +78,12 @@ gdm_session_get_type (void) - } - - void --gdm_session_open (GdmSession *session) -+gdm_session_start_conversation (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); - -- GDM_SESSION_GET_IFACE (session)->open (session); -+ GDM_SESSION_GET_IFACE (session)->start_conversation (session, service_name); - } - - void -@@ -203,14 +204,14 @@ gdm_session_class_init (gpointer g_iface) - { - GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); - -- signals [OPENED] = -- g_signal_new ("opened", -+ signals [CONVERSATION_STARTED] = -+ g_signal_new ("conversation-started", - iface_type, - G_SIGNAL_RUN_FIRST, -- G_STRUCT_OFFSET (GdmSessionIface, opened), -+ G_STRUCT_OFFSET (GdmSessionIface, conversation_started), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, - 0); - signals [SETUP_COMPLETE] = -@@ -608,10 +609,11 @@ _gdm_session_session_died (GdmSession *session, - } - - void --_gdm_session_opened (GdmSession *session) -+_gdm_session_conversation_started (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); -- g_signal_emit (session, signals [OPENED], 0); -+ g_signal_emit (session, signals [CONVERSATION_STARTED], 0, service_name); - } - - void -diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h -index dfb7e27..77e0cf6 100644 ---- a/daemon/gdm-session.h -+++ b/daemon/gdm-session.h -@@ -45,7 +45,8 @@ struct _GdmSessionIface - GTypeInterface base_iface; - - /* Methods */ -- void (* open) (GdmSession *session); -+ void (* start_conversation) (GdmSession *session, -+ const char *service_name); - void (* setup) (GdmSession *session, - const char *service_name); - void (* setup_for_user) (GdmSession *session, -@@ -103,7 +104,8 @@ struct _GdmSessionIface - int exit_code); - void (* session_died) (GdmSession *session, - int signal_number); -- void (* opened) (GdmSession *session); -+ void (* conversation_started) (GdmSession *session, -+ const char *service_name); - void (* closed) (GdmSession *session); - void (* selected_user_changed) (GdmSession *session, - const char *text); -@@ -118,7 +120,8 @@ struct _GdmSessionIface - - GType gdm_session_get_type (void) G_GNUC_CONST; - --void gdm_session_open (GdmSession *session); -+void gdm_session_start_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, -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index 6a00931..111d4cf 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -171,7 +171,6 @@ reset_session (GdmSimpleSlave *slave) - { - destroy_session (slave); - create_new_session (slave); -- gdm_session_open (GDM_SESSION (slave->priv->session)); - } - - static gboolean -@@ -813,8 +812,6 @@ on_greeter_connected (GdmGreeterServer *greeter_server, - - g_debug ("GdmSimpleSlave: Greeter connected"); - -- gdm_session_open (GDM_SESSION (slave->priv->session)); -- - g_object_get (slave, - "display-is-local", &display_is_local, - NULL); -diff --git a/daemon/test-session.c b/daemon/test-session.c -index c6a158c..d9fa26e 100644 ---- a/daemon/test-session.c -+++ b/daemon/test-session.c -@@ -33,12 +33,13 @@ - static GMainLoop *loop; - - static void --on_open (GdmSession *session, -- const char *username) -+on_conversation_started (GdmSession *session, -+ const char *service_name, -+ const char *username) - { - g_debug ("Got opened: calling setup..."); - -- gdm_session_setup (session, "gdm"); -+ gdm_session_setup (session, service_name); - } - - static void -@@ -256,11 +257,11 @@ main (int argc, - username = argv[1]; - } - -- gdm_session_open (GDM_SESSION (session)); -+ gdm_session_start_conversation (GDM_SESSION (session), "gdm"); - - g_signal_connect (session, -- "opened", -- G_CALLBACK (on_open), -+ "conversation-started", -+ G_CALLBACK (on_conversation_started), - username); - g_signal_connect (session, - "setup-complete", --- -1.6.1 - - -From 6a9f8abd1dfc0a2995935652669c32dd8e598ed2 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 13:01:48 -0500 -Subject: [PATCH 02/65] Make greeter explicitly request PAM conversation - -Now the greeter has to say what PAM stack it wants the slave to -run. When that stack is ready, we emit the Ready signal as -before, but now the Ready signal carries a string argument -saying which service is ready to converse. - -When we support multiple PAM stacks, the greeter will call -StartConversation for each stack, and will keep the UI -associated with each stack disabled until the Ready signals -come back one-by-one. ---- - daemon/gdm-factory-slave.c | 3 +- - daemon/gdm-greeter-server.c | 53 ++++++++++++++++++++++++++++-- - daemon/gdm-greeter-server.h | 5 ++- - daemon/gdm-simple-slave.c | 30 +++++++++++++--- - gui/simple-greeter/gdm-greeter-client.c | 18 ++++++---- - gui/simple-greeter/gdm-greeter-client.h | 4 ++- - gui/simple-greeter/gdm-greeter-session.c | 3 ++ - 7 files changed, 97 insertions(+), 19 deletions(-) - -diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c -index 6497293..d1bb5dd 100644 ---- a/daemon/gdm-factory-slave.c -+++ b/daemon/gdm-factory-slave.c -@@ -186,7 +186,8 @@ on_session_conversation_started (GdmSession *session, - { - g_debug ("GdmFactorySlave: session conversation started"); - -- gdm_greeter_server_ready (slave->priv->greeter_server); -+ gdm_greeter_server_ready (slave->priv->greeter_server, -+ service_name); - } - - static void -diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c -index 2e01d33..06c80a0 100644 ---- a/daemon/gdm-greeter-server.c -+++ b/daemon/gdm-greeter-server.c -@@ -69,6 +69,7 @@ enum { - }; - - enum { -+ START_CONVERSATION, - BEGIN_AUTO_LOGIN, - BEGIN_VERIFICATION, - BEGIN_VERIFICATION_FOR_USER, -@@ -246,9 +247,10 @@ gdm_greeter_server_reset (GdmGreeterServer *greeter_server) - } - - gboolean --gdm_greeter_server_ready (GdmGreeterServer *greeter_server) -+gdm_greeter_server_ready (GdmGreeterServer *greeter_server, -+ const char *service_name) - { -- send_dbus_void_signal (greeter_server, "Ready"); -+ send_dbus_string_signal (greeter_server, "Ready", service_name); - return TRUE; - } - -@@ -323,6 +325,34 @@ generate_address (void) - } - - static DBusHandlerResult -+handle_start_conversation (GdmGreeterServer *greeter_server, -+ DBusConnection *connection, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ const 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 ("GreeterServer: StartConversation"); -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ g_signal_emit (greeter_server, signals [START_CONVERSATION], 0, service_name); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+static DBusHandlerResult - handle_begin_verification (GdmGreeterServer *greeter_server, - DBusConnection *connection, - DBusMessage *message) -@@ -645,7 +675,9 @@ greeter_handle_child_message (DBusConnection *connection, - { - GdmGreeterServer *greeter_server = GDM_GREETER_SERVER (user_data); - -- if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginVerification")) { -+ if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "StartConversation")) { -+ return handle_start_conversation (greeter_server, connection, message); -+ } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginVerification")) { - return handle_begin_verification (greeter_server, connection, message); - } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "BeginVerificationForUser")) { - return handle_begin_verification_for_user (greeter_server, connection, message); -@@ -699,7 +731,11 @@ do_introspect (DBusConnection *connection, - /* interface */ - xml = g_string_append (xml, - " \n" -+ " \n" + " \n" + " \n" -+ " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -760,6 +796,7 @@ do_introspect (DBusConnection *connection, + " \n" + " \n" + " \n" ++ " \n" + " \n" + " \n" + " \n" +@@ -752,7 +870,6 @@ do_introspect (DBusConnection *connectio + " \n" + " \n" + " \n" +- " \n" + " \n" + " \n" + " \n" +@@ -760,10 +877,15 @@ do_introspect (DBusConnection *connectio " \n" " \n" " \n" + " \n" ++ " \n" ++ " \n" ++ " \n" " \n" " \n" " \n" -@@ -1122,6 +1159,16 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) + " \n" ++ " \n" + " \n" + " \n"); + +@@ -1122,6 +1244,16 @@ gdm_greeter_server_class_init (GdmGreete "group name", GDM_GROUPNAME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); @@ -1126,1956 +727,1665 @@ index 2e01d33..06c80a0 100644 signals [BEGIN_VERIFICATION] = g_signal_new ("begin-verification", G_OBJECT_CLASS_TYPE (object_class), -diff --git a/daemon/gdm-greeter-server.h b/daemon/gdm-greeter-server.h -index 6e92100..7333db1 100644 ---- a/daemon/gdm-greeter-server.h -+++ b/daemon/gdm-greeter-server.h -@@ -45,6 +45,8 @@ typedef struct - { - GObjectClass parent_class; +@@ -1129,9 +1261,9 @@ gdm_greeter_server_class_init (GdmGreete + G_STRUCT_OFFSET (GdmGreeterServerClass, begin_verification), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); + signals [BEGIN_AUTO_LOGIN] = + g_signal_new ("begin-auto-login", + G_OBJECT_CLASS_TYPE (object_class), +@@ -1150,10 +1282,10 @@ gdm_greeter_server_class_init (GdmGreete + G_STRUCT_OFFSET (GdmGreeterServerClass, begin_verification_for_user), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [QUERY_ANSWER] = + g_signal_new ("query-answer", + G_OBJECT_CLASS_TYPE (object_class), +@@ -1161,10 +1293,10 @@ gdm_greeter_server_class_init (GdmGreete + G_STRUCT_OFFSET (GdmGreeterServerClass, query_answer), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [SESSION_SELECTED] = + g_signal_new ("session-selected", + G_OBJECT_CLASS_TYPE (object_class), +@@ -1258,9 +1390,9 @@ gdm_greeter_server_class_init (GdmGreete + G_STRUCT_OFFSET (GdmGreeterServerClass, start_session_when_ready), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); + + signals [START_SESSION_LATER] = + g_signal_new ("start-session-later", +@@ -1269,9 +1401,9 @@ gdm_greeter_server_class_init (GdmGreete + G_STRUCT_OFFSET (GdmGreeterServerClass, start_session_later), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); + } + + static void +diff -up gdm-2.25.2/daemon/gdm-greeter-server.h.multistack-but-boring gdm-2.25.2/daemon/gdm-greeter-server.h +--- gdm-2.25.2/daemon/gdm-greeter-server.h.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-greeter-server.h 2009-03-03 17:45:05.699016255 -0500 +@@ -45,11 +45,16 @@ typedef struct + { + GObjectClass parent_class; + void (* start_conversation) (GdmGreeterServer *greeter_server, + const char *service_name); void (* begin_auto_login) (GdmGreeterServer *greeter_server); - void (* begin_verification) (GdmGreeterServer *greeter_server); +- void (* begin_verification) (GdmGreeterServer *greeter_server); ++ void (* begin_verification) (GdmGreeterServer *greeter_server, ++ const char *service_name); void (* begin_verification_for_user)(GdmGreeterServer *greeter_server, -@@ -85,7 +87,8 @@ gboolean gdm_greeter_server_info (GdmGreeterServer * ++ const char *service_name, + const char *username); + void (* query_answer) (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text); + void (* session_selected) (GdmGreeterServer *greeter_server, + const char *name); +@@ -64,7 +69,8 @@ typedef struct + void (* cancelled) (GdmGreeterServer *greeter_server); + void (* connected) (GdmGreeterServer *greeter_server); + void (* disconnected) (GdmGreeterServer *greeter_server); +- void (* start_session_when_ready) (GdmGreeterServer *greeter_server); ++ void (* start_session_when_ready) (GdmGreeterServer *greeter_server, ++ const char *service_name); + void (* start_session_later) (GdmGreeterServer *greeter_server); + } GdmGreeterServerClass; + +@@ -75,17 +81,23 @@ gboolean gdm_greeter_server_s + gboolean gdm_greeter_server_stop (GdmGreeterServer *greeter_server); + char * gdm_greeter_server_get_address (GdmGreeterServer *greeter_server); + +- + gboolean gdm_greeter_server_info_query (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text); + gboolean gdm_greeter_server_secret_info_query (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text); + gboolean gdm_greeter_server_info (GdmGreeterServer *greeter_server, ++ const char *service_name, + const char *text); gboolean gdm_greeter_server_problem (GdmGreeterServer *greeter_server, ++ const char *service_name, const char *text); gboolean gdm_greeter_server_reset (GdmGreeterServer *greeter_server); -gboolean gdm_greeter_server_ready (GdmGreeterServer *greeter_server); +gboolean gdm_greeter_server_ready (GdmGreeterServer *greeter_server, + const char *service_name); ++gboolean gdm_greeter_server_conversation_stopped (GdmGreeterServer *greeter_server, ++ const char *service_name); void gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server, const char *text); void gdm_greeter_server_default_language_name_changed (GdmGreeterServer *greeter_server, -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index 111d4cf..eab5c8d 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -475,8 +475,9 @@ on_session_secret_info_query (GdmSession *session, - } +@@ -98,8 +110,8 @@ void gdm_greeter_server_d + void gdm_greeter_server_request_timed_login (GdmGreeterServer *greeter_server, + const char *username, + int delay); +-void gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server); +- ++void gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server, ++ const char *service_name); - static void --on_session_opened (GdmSession *session, -- GdmSimpleSlave *slave) -+on_session_conversation_started (GdmSession *session, -+ const char *service_name, -+ GdmSimpleSlave *slave) - { - gboolean res; - gboolean enabled; -@@ -485,7 +486,8 @@ on_session_opened (GdmSession *session, + G_END_DECLS - g_debug ("GdmSimpleSlave: session opened"); - if (slave->priv->greeter_server != NULL) { -- res = gdm_greeter_server_ready (slave->priv->greeter_server); -+ res = gdm_greeter_server_ready (slave->priv->greeter_server, -+ service_name); - if (! res) { - g_warning ("Unable to send ready"); - } -@@ -501,8 +503,10 @@ on_session_opened (GdmSession *session, - gdm_greeter_server_request_timed_login (slave->priv->greeter_server, username, delay); - } else { - g_debug ("GdmSimpleSlave: begin auto login for user '%s'", username); -+ /* service_name will be "gdm-autologin" -+ */ - gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), -- "gdm-autologin", -+ service_name, - username); - } +diff -up gdm-2.25.2/daemon/gdm-product-slave.c.multistack-but-boring gdm-2.25.2/daemon/gdm-product-slave.c +--- gdm-2.25.2/daemon/gdm-product-slave.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-product-slave.c 2009-03-03 17:45:05.585016670 -0500 +@@ -79,6 +79,8 @@ struct GdmProductSlavePrivate -@@ -594,8 +598,8 @@ create_new_session (GdmSimpleSlave *slave) - g_free (display_hostname); + DBusGProxy *product_display_proxy; + DBusGConnection *connection; ++ ++ char *start_session_service_name; + }; - g_signal_connect (slave->priv->session, -- "opened", -- G_CALLBACK (on_session_opened), -+ "conversation-started", -+ G_CALLBACK (on_session_conversation_started), - slave); - g_signal_connect (slave->priv->session, - "setup-complete", -@@ -726,6 +730,16 @@ on_greeter_session_died (GdmGreeterSession *greeter, - } + enum { +@@ -93,6 +95,68 @@ static void gdm_product_slave_finali + G_DEFINE_TYPE (GdmProductSlave, gdm_product_slave, GDM_TYPE_SLAVE) - static void -+on_greeter_start_conversation (GdmGreeterServer *greeter_server, -+ const char *service_name, -+ GdmSimpleSlave *slave) + static gboolean ++send_dbus_string_string_method (DBusConnection *connection, ++ const char *method, ++ const char *payload1, ++ const char *payload2) +{ -+ g_debug ("GdmSimpleSlave: starting conversation with '%s' pam service'", service_name); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), -+ service_name); -+} ++ DBusError error; ++ DBusMessage *message; ++ DBusMessage *reply; ++ DBusMessageIter iter; ++ const char *str; + -+static void - on_greeter_begin_verification (GdmGreeterServer *greeter_server, - GdmSimpleSlave *slave) - { -@@ -895,6 +909,10 @@ start_greeter (GdmSimpleSlave *slave) - - slave->priv->greeter_server = gdm_greeter_server_new (display_id); - g_signal_connect (slave->priv->greeter_server, -+ "start-conversation", -+ G_CALLBACK (on_greeter_start_conversation), -+ slave); -+ g_signal_connect (slave->priv->greeter_server, - "begin-auto-login", - G_CALLBACK (on_greeter_begin_auto_login), - slave); -diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c -index 461b85c..1e2c55d 100644 ---- a/gui/simple-greeter/gdm-greeter-client.c -+++ b/gui/simple-greeter/gdm-greeter-client.c -@@ -237,11 +237,7 @@ static void - on_ready (GdmGreeterClient *client, - DBusMessage *message) - { -- g_debug ("GdmGreeterClient: Ready"); -- -- g_signal_emit (client, -- gdm_greeter_client_signals[READY], -- 0); -+ emit_string_signal_for_message (client, "Ready", message, READY); ++ g_debug ("GdmProductSlave: Calling %s", method); ++ message = dbus_message_new_method_call (NULL, ++ RELAY_SERVER_DBUS_PATH, ++ RELAY_SERVER_DBUS_INTERFACE, ++ method); ++ if (message == NULL) { ++ g_warning ("Couldn't allocate the D-Bus message"); ++ return FALSE; ++ } ++ ++ dbus_message_iter_init_append (message, &iter); ++ ++ if (payload1 != NULL) { ++ str = payload1; ++ } else { ++ str = ""; ++ } ++ dbus_message_iter_append_basic (&iter, ++ DBUS_TYPE_STRING, ++ &str); ++ if (payload2 != NULL) { ++ str = payload2; ++ } else { ++ str = ""; ++ } ++ dbus_message_iter_append_basic (&iter, ++ DBUS_TYPE_STRING, ++ &str); ++ dbus_error_init (&error); ++ reply = dbus_connection_send_with_reply_and_block (connection, ++ message, ++ -1, ++ &error); ++ ++ dbus_message_unref (message); ++ ++ if (dbus_error_is_set (&error)) { ++ g_warning ("%s %s raised: %s\n", ++ method, ++ error.name, ++ error.message); ++ return FALSE; ++ } ++ if (reply != NULL) { ++ dbus_message_unref (reply); ++ } ++ dbus_connection_flush (connection); ++ ++ return TRUE; ++} ++static gboolean + send_dbus_string_method (DBusConnection *connection, + const char *method, + const char *payload) +@@ -246,19 +310,21 @@ relay_session_started (GdmProductSlave * } static void -@@ -400,6 +396,14 @@ send_dbus_void_method (DBusConnection *connection, +-relay_session_opened (GdmProductSlave *slave) ++relay_session_conversation_started (GdmProductSlave *slave, ++ const char *service_name) + { +- send_dbus_void_method (slave->priv->session_relay_connection, +- "Opened"); ++ send_dbus_string_method (slave->priv->session_relay_connection, ++ "ConversationStarted", service_name); } - void -+gdm_greeter_client_call_start_conversation (GdmGreeterClient *client, -+ const char *service_name) -+{ -+ send_dbus_string_method (client->priv->connection, -+ "StartConversation", service_name); -+} -+ -+void - gdm_greeter_client_call_begin_auto_login (GdmGreeterClient *client, - const char *username) + static void +-on_session_opened (GdmSession *session, +- GdmProductSlave *slave) ++on_session_conversation_started (GdmSession *session, ++ const char *service_name, ++ GdmProductSlave *slave) { -@@ -879,9 +883,9 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) - G_STRUCT_OFFSET (GdmGreeterClientClass, ready), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); - - gdm_greeter_client_signals[RESET] = - g_signal_new ("reset", -diff --git a/gui/simple-greeter/gdm-greeter-client.h b/gui/simple-greeter/gdm-greeter-client.h -index 08deabd..88b0281 100644 ---- a/gui/simple-greeter/gdm-greeter-client.h -+++ b/gui/simple-greeter/gdm-greeter-client.h -@@ -84,13 +84,15 @@ GQuark gdm_greeter_client_error_quark (void); - GdmGreeterClient * gdm_greeter_client_new (void); +- g_debug ("GdmProductSlave: session opened"); ++ g_debug ("GdmProductSlave: session conversation started"); - gboolean gdm_greeter_client_start (GdmGreeterClient *client, -- GError **error); -+ GError **error); - void gdm_greeter_client_stop (GdmGreeterClient *client); +- relay_session_opened (slave); ++ relay_session_conversation_started (slave, service_name); + } - gboolean gdm_greeter_client_get_display_is_local (GdmGreeterClient *client); + static void +@@ -354,7 +420,8 @@ setup_session (GdmProductSlave *slave) + g_free (display_device); + g_free (auth_file); - char * gdm_greeter_client_call_get_display_id (GdmGreeterClient *client); +- gdm_session_start_session (GDM_SESSION (slave->priv->session)); ++ gdm_session_start_session (GDM_SESSION (slave->priv->session), ++ slave->priv->start_session_service_name); -+void gdm_greeter_client_call_start_conversation (GdmGreeterClient *client, -+ const char *service_name); - void gdm_greeter_client_call_begin_auto_login (GdmGreeterClient *client, - const char *username); - void gdm_greeter_client_call_begin_verification (GdmGreeterClient *client); -diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c -index 83375b2..8681828 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -84,6 +84,7 @@ on_problem (GdmGreeterClient *client, + return TRUE; + } +@@ -506,96 +573,112 @@ on_session_reset_failed (GdmSession static void - on_ready (GdmGreeterClient *client, -+ const char *service_name, - GdmGreeterSession *session) + on_session_authenticated (GdmSession *session, ++ const char *service_name, + GdmProductSlave *slave) { - g_debug ("GdmGreeterSession: Ready"); -@@ -377,6 +378,8 @@ gdm_greeter_session_start (GdmGreeterSession *session, - toggle_panel (session, TRUE); - toggle_login_window (session, TRUE); - -+ gdm_greeter_client_call_start_conversation (session->priv->client, "gdm"); -+ - gdm_profile_end (NULL); - - return res; --- -1.6.1 - - -From ed43a24257accc3996fab4cdf7d1bc99a03ea219 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 13:55:48 -0500 -Subject: [PATCH 03/65] Refactor send_dbus_ functions in session-direct - -Previously they were in terms of the session or -dbus connection, but we really want them in terms -of the conversation. ---- - daemon/gdm-session-direct.c | 64 +++++++++++++++++++++++++------------------ - 1 files changed, 37 insertions(+), 27 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index a76051b..c392ae6 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -124,40 +124,39 @@ G_DEFINE_TYPE_WITH_CODE (GdmSessionDirect, - gdm_session_iface_init)) +- send_dbus_void_method (slave->priv->session_relay_connection, +- "Authenticated"); ++ send_dbus_string_method (slave->priv->session_relay_connection, ++ "Authenticated", service_name); + } - static gboolean --send_dbus_message (DBusConnection *connection, -- DBusMessage *message) -+send_dbus_message (GdmSessionConversation *conversation, -+ DBusMessage *message) + static void + on_session_authentication_failed (GdmSession *session, ++ const char *service_name, + const char *message, + GdmProductSlave *slave) { - gboolean is_connected; - gboolean sent; - - g_return_val_if_fail (message != NULL, FALSE); - -- if (connection == NULL) { -+ if (conversation->worker_connection == NULL) { - g_warning ("There is no valid connection"); - return FALSE; - } - -- is_connected = dbus_connection_get_is_connected (connection); -+ is_connected = dbus_connection_get_is_connected (conversation->worker_connection); - if (! is_connected) { - g_warning ("Not connected!"); - return FALSE; - } - -- sent = dbus_connection_send (connection, message, NULL); -+ sent = dbus_connection_send (conversation->worker_connection, message, NULL); - - return sent; +- send_dbus_string_method (slave->priv->session_relay_connection, +- "AuthenticationFailed", +- message); ++ send_dbus_string_string_method (slave->priv->session_relay_connection, ++ "AuthenticationFailed", ++ service_name, ++ message); } static void --send_dbus_string_signal (GdmSessionDirect *session, -+send_dbus_string_signal (GdmSessionConversation *conversation, - const char *name, - const char *text) + on_session_authorized (GdmSession *session, ++ const char *service_name, + GdmProductSlave *slave) { - DBusMessage *message; - DBusMessageIter iter; -- GdmSessionConversation *conversation; - -- g_return_if_fail (session != NULL); -+ g_return_if_fail (conversation != NULL); - - message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, - GDM_SESSION_DBUS_INTERFACE, -@@ -166,8 +165,7 @@ send_dbus_string_signal (GdmSessionDirect *session, - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text); - -- conversation = session->priv->conversation; -- if (! send_dbus_message (conversation->worker_connection, message)) { -+ if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", name); - } - -@@ -175,20 +173,18 @@ send_dbus_string_signal (GdmSessionDirect *session, +- send_dbus_void_method (slave->priv->session_relay_connection, +- "Authorized"); ++ send_dbus_string_method (slave->priv->session_relay_connection, ++ "Authorized", service_name); } static void --send_dbus_void_signal (GdmSessionDirect *session, -- const char *name) -+send_dbus_void_signal (GdmSessionConversation *conversation, -+ const char *name) + on_session_authorization_failed (GdmSession *session, ++ const char *service_name, + const char *message, + GdmProductSlave *slave) { - DBusMessage *message; -- GdmSessionConversation *conversation; - -- g_return_if_fail (session != NULL); -+ g_return_if_fail (conversation != NULL); - - message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, - GDM_SESSION_DBUS_INTERFACE, - name); - -- conversation = session->priv->conversation; -- if (! send_dbus_message (conversation->worker_connection, message)) { -+ if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", name); - } - -@@ -1764,7 +1760,7 @@ send_setup (GdmSessionDirect *session, - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file); - - conversation = session->priv->conversation; -- if (! send_dbus_message (conversation->worker_connection, message)) { -+ if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "Setup"); - } - -@@ -1827,7 +1823,7 @@ send_setup_for_user (GdmSessionDirect *session, - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &selected_user); - - conversation = session->priv->conversation; -- if (! send_dbus_message (conversation->worker_connection, message)) { -+ if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForUser"); - } +- send_dbus_string_method (slave->priv->session_relay_connection, +- "AuthorizationFailed", +- message); ++ send_dbus_string_string_method (slave->priv->session_relay_connection, ++ "AuthorizationFailed", ++ service_name, ++ message); + } -@@ -1870,24 +1866,28 @@ static void - gdm_session_direct_authenticate (GdmSession *session) + static void + on_session_accredited (GdmSession *session, ++ const char *service_name, + GdmProductSlave *slave) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - - g_return_if_fail (session != NULL); - g_return_if_fail (impl->priv->conversation != NULL); - g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - -- send_dbus_void_signal (impl, "Authenticate"); -+ conversation = impl->priv->conversation; -+ send_dbus_void_signal (conversation, "Authenticate"); +- send_dbus_void_method (slave->priv->session_relay_connection, +- "Accredited"); ++ send_dbus_string_method (slave->priv->session_relay_connection, ++ "Accredited", service_name); } static void - gdm_session_direct_authorize (GdmSession *session) + on_session_accreditation_failed (GdmSession *session, ++ const char *service_name, + const char *message, + GdmProductSlave *slave) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; +- send_dbus_string_method (slave->priv->session_relay_connection, +- "AccreditationFailed", +- message); ++ send_dbus_string_string_method (slave->priv->session_relay_connection, ++ "AccreditationFailed", ++ service_name, ++ message); + } - g_return_if_fail (session != NULL); - g_return_if_fail (impl->priv->conversation != NULL); - g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); + static void + on_session_info (GdmSession *session, ++ const char *service_name, + const char *text, + GdmProductSlave *slave) + { +- send_dbus_string_method (slave->priv->session_relay_connection, +- "Info", +- text); ++ send_dbus_string_string_method (slave->priv->session_relay_connection, ++ "Info", ++ service_name, ++ text); + } -- send_dbus_void_signal (impl, "Authorize"); -+ conversation = impl->priv->conversation; -+ send_dbus_void_signal (conversation, "Authorize"); + static void + on_session_problem (GdmSession *session, ++ const char *service_name, + const char *text, + GdmProductSlave *slave) + { +- send_dbus_string_method (slave->priv->session_relay_connection, +- "Problem", +- text); ++ send_dbus_string_string_method (slave->priv->session_relay_connection, ++ "Problem", ++ service_name, ++ text); } static void -@@ -1895,17 +1895,19 @@ gdm_session_direct_accredit (GdmSession *session, - int cred_flag) + on_session_info_query (GdmSession *session, ++ const char *service_name, + const char *text, + GdmProductSlave *slave) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; +- send_dbus_string_method (slave->priv->session_relay_connection, +- "InfoQuery", +- text); ++ send_dbus_string_string_method (slave->priv->session_relay_connection, ++ "InfoQuery", ++ service_name, text); + } - g_return_if_fail (session != NULL); - g_return_if_fail (impl->priv->conversation != NULL); - g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); + static void + on_session_secret_info_query (GdmSession *session, ++ const char *service_name, + const char *text, + GdmProductSlave *slave) + { +- send_dbus_string_method (slave->priv->session_relay_connection, +- "SecretInfoQuery", +- text); ++ send_dbus_string_string_method (slave->priv->session_relay_connection, ++ "SecretInfoQuery", ++ service_name, ++ text); + } -+ conversation = impl->priv->conversation; - switch (cred_flag) { - case GDM_SESSION_CRED_ESTABLISH: -- send_dbus_void_signal (impl, "EstablishCredentials"); -+ send_dbus_void_signal (conversation, "EstablishCredentials"); - break; - case GDM_SESSION_CRED_REFRESH: -- send_dbus_void_signal (impl, "RefreshCredentials"); -+ send_dbus_void_signal (conversation, "RefreshCredentials"); - break; - default: - g_assert_not_reached (); -@@ -1930,7 +1932,7 @@ send_environment_variable (const char *key, - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value); - - conversation = session->priv->conversation; -- if (! send_dbus_message (conversation->worker_connection, message)) { -+ if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable"); - } - -@@ -2060,6 +2062,7 @@ static void - gdm_session_direct_start_session (GdmSession *session) + static void +@@ -656,36 +739,92 @@ static void + on_relay_authenticate (GdmProductSlave *slave, + DBusMessage *message) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - char *command; - char *program; - -@@ -2073,7 +2076,8 @@ gdm_session_direct_start_session (GdmSession *session) - setup_session_environment (impl); - send_environment (impl); +- g_debug ("GdmProductSlave: Relay Authenticate"); ++ DBusError error; ++ char *service_name; ++ dbus_bool_t res; -- send_dbus_string_signal (impl, "StartProgram", program); -+ conversation = impl->priv->conversation; -+ send_dbus_string_signal (conversation, "StartProgram", program); - g_free (program); +- gdm_session_authenticate (GDM_SESSION (slave->priv->session)); ++ dbus_error_init (&error); ++ res = dbus_message_get_args (message, ++ &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID); ++ if (res) { ++ g_debug ("GdmProductSlave: Relay Authenticate"); ++ gdm_session_authenticate (GDM_SESSION (slave->priv->session), service_name); ++ } else { ++ g_warning ("Unable to get arguments: %s", error.message); ++ dbus_error_free (&error); ++ } ++ dbus_error_free (&error); } -@@ -2163,6 +2167,7 @@ gdm_session_direct_select_session (GdmSession *session, - const char *text) + static void + on_relay_authorize (GdmProductSlave *slave, + DBusMessage *message) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - - g_free (impl->priv->selected_session); - -@@ -2172,7 +2177,8 @@ gdm_session_direct_select_session (GdmSession *session, - impl->priv->selected_session = g_strdup (text); - } +- g_debug ("GdmProductSlave: Relay Authorize"); ++ DBusError error; ++ char *service_name; ++ dbus_bool_t res; -- send_dbus_string_signal (impl, "SetSessionName", -+ conversation = impl->priv->conversation; -+ send_dbus_string_signal (conversation, "SetSessionName", - get_session_name (impl)); +- gdm_session_authorize (GDM_SESSION (slave->priv->session)); ++ dbus_error_init (&error); ++ res = dbus_message_get_args (message, ++ &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID); ++ if (res) { ++ g_debug ("GdmProductSlave: Relay Authorize"); ++ gdm_session_authorize (GDM_SESSION (slave->priv->session), service_name); ++ } else { ++ g_warning ("Unable to get arguments: %s", error.message); ++ dbus_error_free (&error); ++ } ++ dbus_error_free (&error); } -@@ -2181,6 +2187,7 @@ gdm_session_direct_select_language (GdmSession *session, - const char *text) + static void + on_relay_establish_credentials (GdmProductSlave *slave, + DBusMessage *message) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - - g_free (impl->priv->selected_language); - -@@ -2190,7 +2197,8 @@ gdm_session_direct_select_language (GdmSession *session, - impl->priv->selected_language = g_strdup (text); - } +- g_debug ("GdmProductSlave: Relay EstablishCredentials"); ++ DBusError error; ++ char *service_name; ++ dbus_bool_t res; -- send_dbus_string_signal (impl, "SetLanguageName", -+ conversation = impl->priv->conversation; -+ send_dbus_string_signal (conversation, "SetLanguageName", - get_language_name (impl)); +- gdm_session_accredit (GDM_SESSION (slave->priv->session), GDM_SESSION_CRED_ESTABLISH); ++ dbus_error_init (&error); ++ res = dbus_message_get_args (message, ++ &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID); ++ if (res) { ++ g_debug ("GdmProductSlave: Relay EstablishCredentials"); ++ gdm_session_accredit (GDM_SESSION (slave->priv->session), service_name, GDM_SESSION_CRED_ESTABLISH); ++ } else { ++ g_warning ("Unable to get arguments: %s", error.message); ++ dbus_error_free (&error); ++ } ++ dbus_error_free (&error); } -@@ -2199,6 +2207,7 @@ gdm_session_direct_select_layout (GdmSession *session, - const char *text) + static void + on_relay_refresh_credentials (GdmProductSlave *slave, + DBusMessage *message) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; +- g_debug ("GdmProductSlave: Relay RefreshCredentials"); ++ DBusError error; ++ char *service_name; ++ dbus_bool_t res; - g_free (impl->priv->selected_layout); +- gdm_session_accredit (GDM_SESSION (slave->priv->session), GDM_SESSION_CRED_REFRESH); ++ dbus_error_init (&error); ++ res = dbus_message_get_args (message, ++ &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID); ++ if (res) { ++ g_debug ("GdmProductSlave: Relay RefreshCredentials"); ++ gdm_session_accredit (GDM_SESSION (slave->priv->session), service_name, GDM_SESSION_CRED_REFRESH); ++ } else { ++ g_warning ("Unable to get arguments: %s", error.message); ++ dbus_error_free (&error); ++ } ++ dbus_error_free (&error); + } -@@ -2208,7 +2217,8 @@ gdm_session_direct_select_layout (GdmSession *session, - impl->priv->selected_layout = g_strdup (text); - } + static void +@@ -694,16 +833,18 @@ on_relay_answer_query (GdmProductSlave * + { + DBusError error; + const char *text; ++ const char *service_name; + dbus_bool_t res; -- send_dbus_string_signal (impl, "SetLayoutName", -+ conversation = impl->priv->conversation; -+ send_dbus_string_signal (conversation, "SetLayoutName", - get_layout_name (impl)); + dbus_error_init (&error); + res = dbus_message_get_args (message, + &error, ++ DBUS_TYPE_STRING, &service_name, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_INVALID); + if (res) { + g_debug ("GdmProductSlave: Relay AnswerQuery"); +- gdm_session_answer_query (GDM_SESSION (slave->priv->session), text); ++ gdm_session_answer_query (GDM_SESSION (slave->priv->session), service_name, text); + } else { + g_warning ("Unable to get arguments: %s", error.message); + dbus_error_free (&error); +@@ -784,17 +925,52 @@ on_relay_user_selected (GdmProductSlave } --- -1.6.1 - - -From dd908a665638a10a6df281eee764ca9a131ab95b Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 13:57:04 -0500 -Subject: [PATCH 04/65] Clean up stop_conversation - -We now keep a pointer to the session object around -separate from the conversation. This is so we -can free it but still get at the session. ---- - daemon/gdm-session-direct.c | 6 +++++- - 1 files changed, 5 insertions(+), 1 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index c392ae6..59f3fd6 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1672,6 +1672,10 @@ start_conversation (GdmSessionDirect *session, static void - stop_conversation (GdmSessionConversation *conversation) +-on_relay_open (GdmProductSlave *slave, +- DBusMessage *message) ++on_relay_start_conversation (GdmProductSlave *slave, ++ DBusMessage *message) { -+ GdmSessionDirect *session; +- gdm_session_open (GDM_SESSION (slave->priv->session)); ++ DBusError error; ++ char *service_name; ++ dbus_bool_t res; + -+ session = conversation->session; ++ dbus_error_init (&error); ++ res = dbus_message_get_args (message, ++ &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID); ++ if (res) { ++ g_debug ("GdmProductSlave: Started conversation with %s service", service_name); ++ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), ++ service_name); ++ } else { ++ g_warning ("Unable to get arguments: %s", error.message); ++ } + - g_signal_handlers_disconnect_by_func (conversation->job, - G_CALLBACK (worker_stopped), - conversation); -@@ -1685,7 +1689,7 @@ stop_conversation (GdmSessionConversation *conversation) - G_CALLBACK (worker_died), - conversation); - -- cancel_pending_query (conversation->session); -+ cancel_pending_query (session); - - if (conversation->worker_connection != NULL) { - dbus_connection_close (conversation->worker_connection); --- -1.6.1 - - -From d17f2ffa75d51a0bcec99ebce110a15a3c792ec3 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 14:28:58 -0500 -Subject: [PATCH 05/65] Properly record worker pid when starting job - -We had the variable but we weren't initializing -it and we need it. ---- - daemon/gdm-session-direct.c | 2 ++ - daemon/gdm-session-worker-job.c | 7 +++++++ - daemon/gdm-session-worker-job.h | 2 ++ - 3 files changed, 11 insertions(+), 0 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 59f3fd6..1ddef8c 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1666,6 +1666,8 @@ start_conversation (GdmSessionDirect *session, - return NULL; - } ++ dbus_error_free (&error); + } -+ conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job); + static void + on_relay_start_session (GdmProductSlave *slave, + DBusMessage *message) + { +- gdm_product_slave_create_server (slave); ++ DBusError error; ++ const char *service_name; ++ dbus_bool_t res; ++ ++ dbus_error_init (&error); + - return conversation; ++ res = dbus_message_get_args (message, ++ &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID); ++ if (res) { ++ g_debug ("GdmProductSlave: Relay StartSession"); ++ g_free (slave->priv->start_session_service_name); ++ slave->priv->start_session_service_name = g_strdup (service_name); ++ gdm_product_slave_create_server (slave); ++ } else { ++ g_warning ("Unable to get arguments: %s", error.message); ++ dbus_error_free (&error); ++ } } -diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c -index bb30245..1a7cf36 100644 ---- a/daemon/gdm-session-worker-job.c -+++ b/daemon/gdm-session-worker-job.c -@@ -270,6 +270,13 @@ gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job) - return TRUE; - } + static void +@@ -832,8 +1008,8 @@ create_new_session (GdmProductSlave *sla + g_free (display_device); -+GPid -+gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job) -+{ -+ g_return_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job)); -+ return session_worker_job->priv->pid; -+} -+ - void - gdm_session_worker_job_set_server_address (GdmSessionWorkerJob *session_worker_job, - const char *address) -diff --git a/daemon/gdm-session-worker-job.h b/daemon/gdm-session-worker-job.h -index d42eb37..9cb08ce 100644 ---- a/daemon/gdm-session-worker-job.h -+++ b/daemon/gdm-session-worker-job.h -@@ -61,6 +61,8 @@ void gdm_session_worker_job_set_server_address (GdmSessionWor - gboolean gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job); - gboolean gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job); + g_signal_connect (slave->priv->session, +- "opened", +- G_CALLBACK (on_session_opened), ++ "conversation-started", ++ G_CALLBACK (on_session_conversation_started), + slave); + g_signal_connect (slave->priv->session, + "setup-complete", +@@ -991,8 +1167,8 @@ relay_dbus_handle_message (DBusConnectio + on_relay_user_selected (slave, message); + } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "StartSession")) { + on_relay_start_session (slave, message); +- } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Open")) { +- on_relay_open (slave, message); ++ } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "StartConversation")) { ++ on_relay_start_conversation (slave, message); + } else if (dbus_message_is_signal (message, RELAY_SERVER_DBUS_INTERFACE, "Cancelled")) { + on_relay_cancelled (slave, message); + } else { +diff -up gdm-2.25.2/daemon/gdm-session.c.multistack-but-boring gdm-2.25.2/daemon/gdm-session.c +--- gdm-2.25.2/daemon/gdm-session.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-session.c 2009-03-03 17:45:05.704022039 -0500 +@@ -24,11 +24,13 @@ + #include + #include -+GPid gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job); -+ - G_END_DECLS ++#include "gdm-marshal.h" + #include "gdm-session.h" + #include "gdm-session-private.h" - #endif /* __GDM_SESSION_WORKER_JOB_H */ --- -1.6.1 - - -From e816e596e049420602d68655099255fca20d623c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 14:30:40 -0500 -Subject: [PATCH 06/65] When starting session record its pid - -When writing out logout records we need the -pid of the running session. We store that -on the session object when the session gets -started and write out the logout record when -the session ends. ---- - daemon/gdm-session-direct.c | 34 +++++++++++++--------------------- - 1 files changed, 13 insertions(+), 21 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 1ddef8c..1d4ab63 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -88,6 +88,7 @@ struct _GdmSessionDirectPrivate + enum { +- OPENED = 0, ++ CONVERSATION_STARTED = 0, ++ CONVERSATION_STOPPED, + SETUP_COMPLETE, + SETUP_FAILED, + RESET_COMPLETE, +@@ -78,11 +80,21 @@ gdm_session_get_type (void) + } - guint32 is_authenticated : 1; - guint32 is_running : 1; -+ GPid session_pid; - - /* object lifetime scope */ - char *id; -@@ -246,16 +247,12 @@ on_session_exited (GdmSession *session, - int exit_code) + void +-gdm_session_open (GdmSession *session) ++gdm_session_start_conversation (GdmSession *session, ++ const char *service_name) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- GdmSessionConversation *conversation; - -- conversation = impl->priv->conversation; -- if (conversation != NULL) { -- gdm_session_record_logout (conversation->worker_pid, -- impl->priv->selected_user, -- impl->priv->display_hostname, -- impl->priv->display_name, -- impl->priv->display_device); -- } -+ gdm_session_record_logout (impl->priv->session_pid, -+ impl->priv->selected_user, -+ impl->priv->display_hostname, -+ impl->priv->display_name, -+ impl->priv->display_device); - } - - static DBusHandlerResult -@@ -955,7 +952,7 @@ gdm_session_direct_handle_session_started (GdmSessionDirect *session, - g_debug ("GdmSessionDirect: Emitting 'session-started' signal with pid '%d'", - pid); - -- session->priv->conversation->worker_pid = pid; -+ session->priv->session_pid = pid; - session->priv->is_running = TRUE; - - _gdm_session_session_started (GDM_SESSION (session), pid); -@@ -2096,17 +2093,12 @@ gdm_session_direct_close (GdmSession *session) - - g_debug ("GdmSessionDirect: Closing session"); - -- if (impl->priv->conversation != NULL) { -- if (impl->priv->is_running) { -- gdm_session_record_logout (impl->priv->conversation->worker_pid, -- impl->priv->selected_user, -- impl->priv->display_hostname, -- impl->priv->display_name, -- impl->priv->display_device); -- } -- -- stop_conversation (impl->priv->conversation); -- impl->priv->conversation = NULL; -+ if (impl->priv->is_running) { -+ gdm_session_record_logout (impl->priv->session_pid, -+ impl->priv->selected_user, -+ impl->priv->display_hostname, -+ impl->priv->display_name, -+ impl->priv->display_device); - } - - g_free (impl->priv->selected_user); --- -1.6.1 - - -From 1f60a95dc2d40f5f0ed9350cb5440ebd95b7654d Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 15:18:31 -0500 -Subject: [PATCH 07/65] Store multiple conversations in the session - -We keep multiple conversations in the session now, keyed off of -PAM service is at the other end. Much of the guts still -only operate on the first conversation added though. ---- - daemon/gdm-session-direct.c | 99 ++++++++++++++++++++++++++++++++++++++---- - 1 files changed, 89 insertions(+), 10 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 1d4ab63..5a93103 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -85,6 +85,7 @@ struct _GdmSessionDirectPrivate - DBusMessage *message_pending_reply; - - GdmSessionConversation *conversation; -+ GHashTable *conversations; - - guint32 is_authenticated : 1; - guint32 is_running : 1; -@@ -1462,6 +1463,42 @@ allow_user_function (DBusConnection *connection, - return FALSE; - } + g_return_if_fail (GDM_IS_SESSION (session)); -+static GdmSessionConversation * -+find_conversation_by_name (GdmSessionDirect *session, -+ const char *service_name) -+{ -+ GdmSessionConversation *conversation; -+ -+ conversation = g_hash_table_lookup (session->priv->conversations, service_name); -+ -+ if (conversation == NULL) { -+ g_warning ("Tried to look up non-existant conversation"); -+ } -+ -+ return conversation; +- GDM_SESSION_GET_IFACE (session)->open (session); ++ GDM_SESSION_GET_IFACE (session)->start_conversation (session, service_name); +} + -+static GdmSessionConversation * -+find_conversation_by_pid (GdmSessionDirect *session, -+ GPid pid) ++void ++gdm_session_stop_conversation (GdmSession *session, ++ const char *service_name) +{ -+ GHashTableIter iter; -+ gpointer key, value; -+ -+ g_hash_table_iter_init (&iter, session->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 void - handle_connection (DBusServer *server, - DBusConnection *new_connection, -@@ -1469,10 +1506,22 @@ handle_connection (DBusServer *server, - { - GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); - GdmSessionConversation *conversation; -+ gulong pid; - - g_debug ("GdmSessionDirect: Handing new connection"); - -- conversation = session->priv->conversation; -+ if (!dbus_connection_get_unix_process_id (new_connection, &pid)) { -+ g_warning ("Unable to read pid on new worker connection"); -+ return; -+ } -+ -+ conversation = find_conversation_by_pid (session, (GPid) pid); -+ -+ if (conversation == NULL) { -+ g_warning ("New worker connection is from unknown source"); -+ return; -+ } ++ g_return_if_fail (GDM_IS_SESSION (session)); + - if (conversation->worker_connection == NULL) { - DBusObjectPathVTable vtable = { &session_unregister_handler, - &session_message_handler, -@@ -1568,6 +1617,10 @@ gdm_session_direct_init (GdmSessionDirect *session) - G_CALLBACK (on_session_exited), - NULL); ++ GDM_SESSION_GET_IFACE (session)->stop_conversation (session, service_name); + } -+ session->priv->conversations = g_hash_table_new_full (g_str_hash, -+ g_str_equal, -+ (GDestroyNotify) g_free, -+ NULL); - session->priv->environment = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, -@@ -1696,6 +1749,8 @@ stop_conversation (GdmSessionConversation *conversation) - } + void +@@ -113,37 +125,41 @@ gdm_session_setup_for_user (GdmSession * + } - gdm_session_worker_job_stop (conversation->job); -+ g_hash_table_remove (session->priv->conversations, conversation); -+ - g_object_unref (conversation->job); - g_free (conversation->service_name); - g_free (conversation); -@@ -1706,12 +1761,20 @@ gdm_session_direct_start_conversation (GdmSession *session, - const char *service_name) + void +-gdm_session_authenticate (GdmSession *session) ++gdm_session_authenticate (GdmSession *session, ++ const char *service_name) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - - g_return_if_fail (session != NULL); - - g_debug ("GdmSessionDirect: starting conversation"); + g_return_if_fail (GDM_IS_SESSION (session)); -- impl->priv->conversation = start_conversation (impl, service_name); -+ conversation = start_conversation (impl, service_name); -+ -+ g_hash_table_insert (impl->priv->conversations, -+ g_strdup (service_name), conversation); -+ -+ if (impl->priv->conversation != NULL) { -+ impl->priv->conversation = conversation; -+ } +- GDM_SESSION_GET_IFACE (session)->authenticate (session); ++ GDM_SESSION_GET_IFACE (session)->authenticate (session, service_name); } - static void -@@ -1762,8 +1825,8 @@ send_setup (GdmSessionDirect *session, - 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 = session->priv->conversation; -- if (! send_dbus_message (conversation, message)) { -+ conversation = find_conversation_by_name (session, service_name); -+ if (conversation != NULL && ! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "Setup"); - } - -@@ -1825,8 +1888,8 @@ send_setup_for_user (GdmSessionDirect *session, - 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 = session->priv->conversation; -- if (! send_dbus_message (conversation, message)) { -+ conversation = find_conversation_by_name (session, service_name); -+ if (conversation != NULL && ! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForUser"); - } - -@@ -1840,8 +1903,6 @@ gdm_session_direct_setup (GdmSession *session, - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - - g_return_if_fail (session != NULL); -- g_return_if_fail (impl->priv->conversation != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - - send_setup (impl, service_name); - gdm_session_direct_defaults_changed (impl); -@@ -1855,8 +1916,6 @@ gdm_session_direct_setup_for_user (GdmSession *session, - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - - g_return_if_fail (session != NULL); -- g_return_if_fail (impl->priv->conversation != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - g_return_if_fail (username != NULL); + void +-gdm_session_authorize (GdmSession *session) ++gdm_session_authorize (GdmSession *session, ++ const char *service_name) + { + g_return_if_fail (GDM_IS_SESSION (session)); - gdm_session_direct_select_user (session, username); -@@ -2085,6 +2144,24 @@ gdm_session_direct_start_session (GdmSession *session) +- GDM_SESSION_GET_IFACE (session)->authorize (session); ++ GDM_SESSION_GET_IFACE (session)->authorize (session, service_name); } - static void -+stop_all_conversations (GdmSessionDirect *session) -+{ -+ GHashTableIter iter; -+ gpointer key, value; -+ -+ g_hash_table_iter_init (&iter, session->priv->conversations); -+ while (g_hash_table_iter_next (&iter, &key, &value)) { -+ GdmSessionConversation *conversation; -+ -+ conversation = (GdmSessionConversation *) value; -+ -+ stop_conversation (conversation); -+ } -+ -+ g_hash_table_remove_all (session->priv->conversations); -+} -+ -+static void - gdm_session_direct_close (GdmSession *session) + void + gdm_session_accredit (GdmSession *session, ++ const char *service_name, + int flag) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -@@ -2101,6 +2178,8 @@ gdm_session_direct_close (GdmSession *session) - impl->priv->display_device); - } - -+ stop_all_conversations (impl); -+ - g_free (impl->priv->selected_user); - impl->priv->selected_user = NULL; + g_return_if_fail (GDM_IS_SESSION (session)); --- -1.6.1 - - -From 9b5d9c73cd1b53f674825b8b5595b1e92630a8e5 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 22 Jan 2009 08:52:01 -0500 -Subject: [PATCH 08/65] Propagate service name to more layers - -This is more prep work to get multiple concurrent -PAM stacks going. ---- - daemon/gdm-factory-slave.c | 49 ++- - daemon/gdm-greeter-server.c | 120 ++++++-- - daemon/gdm-greeter-server.h | 17 +- - daemon/gdm-product-slave.c | 233 ++++++++++++--- - daemon/gdm-session-direct.c | 481 ++++++++++++++++++------------ - daemon/gdm-session-private.h | 22 ++- - daemon/gdm-session-relay.c | 117 ++++++-- - daemon/gdm-session-worker.c | 27 ++ - daemon/gdm-session.c | 151 ++++++---- - daemon/gdm-session.h | 44 ++- - daemon/gdm-simple-slave.c | 75 ++++-- - daemon/test-session.c | 22 +- - gui/simple-greeter/gdm-greeter-client.c | 183 +++++++++--- - gui/simple-greeter/gdm-greeter-client.h | 16 +- - gui/simple-greeter/gdm-greeter-session.c | 11 +- - 15 files changed, 1122 insertions(+), 446 deletions(-) - -diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c -index d1bb5dd..3251ec2 100644 ---- a/daemon/gdm-factory-slave.c -+++ b/daemon/gdm-factory-slave.c -@@ -144,45 +144,49 @@ on_greeter_session_died (GdmGreeterSession *greeter, +- GDM_SESSION_GET_IFACE (session)->accredit (session, flag); ++ GDM_SESSION_GET_IFACE (session)->accredit (session, service_name, flag); + } - static void - on_session_info (GdmSession *session, -+ const char *service_name, - const char *text, - GdmFactorySlave *slave) + void + gdm_session_answer_query (GdmSession *session, ++ const char *service_name, + const char *text) { - g_debug ("GdmFactorySlave: Info: %s", text); -- gdm_greeter_server_info (slave->priv->greeter_server, text); -+ gdm_greeter_server_info (slave->priv->greeter_server, service_name, text); + g_return_if_fail (GDM_IS_SESSION (session)); + +- GDM_SESSION_GET_IFACE (session)->answer_query (session, text); ++ GDM_SESSION_GET_IFACE (session)->answer_query (session, service_name, text); } - static void - on_session_problem (GdmSession *session, -+ const char *service_name, - const char *text, - GdmFactorySlave *slave) - { - g_debug ("GdmFactorySlave: Problem: %s", text); -- gdm_greeter_server_problem (slave->priv->greeter_server, text); -+ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, text); + void +@@ -191,11 +207,12 @@ gdm_session_cancel (GdmSession *session) } - static void - on_session_info_query (GdmSession *session, -+ const char *service_name, - const char *text, - GdmFactorySlave *slave) + void +-gdm_session_start_session (GdmSession *session) ++gdm_session_start_session (GdmSession *session, ++ const char *service_name) { + g_return_if_fail (GDM_IS_SESSION (session)); - g_debug ("GdmFactorySlave: Info query: %s", text); -- gdm_greeter_server_info_query (slave->priv->greeter_server, text); -+ gdm_greeter_server_info_query (slave->priv->greeter_server, service_name, text); +- GDM_SESSION_GET_IFACE (session)->start_session (session); ++ GDM_SESSION_GET_IFACE (session)->start_session (session, service_name); } static void - on_session_secret_info_query (GdmSession *session, -+ const char *service_name, - const char *text, - GdmFactorySlave *slave) +@@ -203,16 +220,26 @@ gdm_session_class_init (gpointer g_iface { - g_debug ("GdmFactorySlave: Secret info query: %s", text); -- gdm_greeter_server_secret_info_query (slave->priv->greeter_server, text); -+ gdm_greeter_server_secret_info_query (slave->priv->greeter_server, service_name, text); - } + GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); - static void - on_session_conversation_started (GdmSession *session, -- GdmFactorySlave *slave, -- const char *service_name) -+ const char *service_name, -+ GdmFactorySlave *slave) - { - g_debug ("GdmFactorySlave: session conversation started"); - -@@ -192,17 +196,19 @@ on_session_conversation_started (GdmSession *session, +- signals [OPENED] = +- g_signal_new ("opened", ++ signals [CONVERSATION_STARTED] = ++ g_signal_new ("conversation-started", + iface_type, + G_SIGNAL_RUN_FIRST, +- G_STRUCT_OFFSET (GdmSessionIface, opened), ++ G_STRUCT_OFFSET (GdmSessionIface, conversation_started), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); ++ signals [CONVERSATION_STOPPED] = ++ g_signal_new ("conversation-stopped", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmSessionIface, conversation_stopped), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, ++ 1, G_TYPE_STRING); + signals [SETUP_COMPLETE] = + g_signal_new ("setup-complete", + iface_type, +@@ -220,9 +247,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, setup_complete), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, ++ G_TYPE_STRING); + signals [SETUP_FAILED] = + g_signal_new ("setup-failed", + iface_type, +@@ -230,10 +258,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, setup_failed), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [RESET_COMPLETE] = + g_signal_new ("reset-complete", + iface_type, +@@ -262,9 +290,9 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, authenticated), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); + signals [AUTHENTICATION_FAILED] = + g_signal_new ("authentication-failed", + iface_type, +@@ -272,10 +300,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, authentication_failed), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [AUTHORIZED] = + g_signal_new ("authorized", + iface_type, +@@ -283,9 +311,9 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, authorized), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); + signals [AUTHORIZATION_FAILED] = + g_signal_new ("authorization-failed", + iface_type, +@@ -293,10 +321,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, authorization_failed), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [ACCREDITED] = + g_signal_new ("accredited", + iface_type, +@@ -304,9 +332,9 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, accredited), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); + signals [ACCREDITATION_FAILED] = + g_signal_new ("accreditation-failed", + iface_type, +@@ -314,10 +342,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, accreditation_failed), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); - static void - on_session_setup_complete (GdmSession *session, -+ const char *service_name, - GdmFactorySlave *slave) - { -- gdm_session_authenticate (session); -+ gdm_session_authenticate (session, service_name); + signals [INFO_QUERY] = + g_signal_new ("info-query", +@@ -326,10 +354,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, info_query), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [SECRET_INFO_QUERY] = + g_signal_new ("secret-info-query", + iface_type, +@@ -337,10 +365,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, secret_info_query), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [INFO] = + g_signal_new ("info", + iface_type, +@@ -348,10 +376,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, info), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [PROBLEM] = + g_signal_new ("problem", + iface_type, +@@ -359,10 +387,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, problem), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [SESSION_STARTED] = + g_signal_new ("session-started", + iface_type, +@@ -370,10 +398,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, session_started), + NULL, + NULL, +- g_cclosure_marshal_VOID__INT, ++ gdm_marshal_VOID__STRING_INT, + G_TYPE_NONE, +- 1, +- G_TYPE_INT); ++ 2, ++ G_TYPE_STRING, G_TYPE_INT); + signals [SESSION_START_FAILED] = + g_signal_new ("session-start-failed", + iface_type, +@@ -381,10 +409,10 @@ gdm_session_class_init (gpointer g_iface + G_STRUCT_OFFSET (GdmSessionIface, session_start_failed), + NULL, + NULL, +- g_cclosure_marshal_VOID__STRING, ++ gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, +- 1, +- G_TYPE_STRING); ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [SESSION_EXITED] = + g_signal_new ("session-exited", + iface_type, +@@ -464,19 +492,21 @@ gdm_session_class_init (gpointer g_iface } - static void - on_session_setup_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmFactorySlave *slave) + void +-_gdm_session_setup_complete (GdmSession *session) ++_gdm_session_setup_complete (GdmSession *session, ++ const char *service_name) { -- gdm_greeter_server_problem (slave->priv->greeter_server, _("Unable to initialize login system")); -+ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to initialize login system")); + g_return_if_fail (GDM_IS_SESSION (session)); - queue_greeter_reset (slave); +- g_signal_emit (session, signals [SETUP_COMPLETE], 0); ++ g_signal_emit (session, signals [SETUP_COMPLETE], 0, service_name); } -@@ -224,23 +230,26 @@ on_session_reset_failed (GdmSession *session, - static void - on_session_authenticated (GdmSession *session, -+ const char *service_name, - GdmFactorySlave *slave) + void + _gdm_session_setup_failed (GdmSession *session, ++ const char *service_name, + const char *text) { -- gdm_session_authorize (session); -+ gdm_session_authorize (session, service_name); + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [SETUP_FAILED], 0, text); ++ g_signal_emit (session, signals [SETUP_FAILED], 0, service_name, text); } - static void - on_session_authentication_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmFactorySlave *slave) - { -- gdm_greeter_server_problem (slave->priv->greeter_server, _("Unable to authenticate user")); -+ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to authenticate user")); - - queue_greeter_reset (slave); + void +@@ -496,99 +526,111 @@ _gdm_session_reset_failed (GdmSession } - static void - on_session_authorized (GdmSession *session, -+ const char *service_name, - GdmFactorySlave *slave) - { - int flag; -@@ -248,39 +257,42 @@ on_session_authorized (GdmSession *session, - /* FIXME: check for migration? */ - flag = GDM_SESSION_CRED_ESTABLISH; + void +-_gdm_session_authenticated (GdmSession *session) ++_gdm_session_authenticated (GdmSession *session, ++ const char *service_name) + { + g_return_if_fail (GDM_IS_SESSION (session)); -- gdm_session_accredit (session, flag); -+ gdm_session_accredit (session, service_name, flag); +- g_signal_emit (session, signals [AUTHENTICATED], 0); ++ g_signal_emit (session, signals [AUTHENTICATED], 0, service_name); } - static void - on_session_authorization_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmFactorySlave *slave) + void + _gdm_session_authentication_failed (GdmSession *session, ++ const char *service_name, + const char *text) { -- gdm_greeter_server_problem (slave->priv->greeter_server, _("Unable to authorize user")); -+ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to authorize user")); - - queue_greeter_reset (slave); + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [AUTHENTICATION_FAILED], 0, text); ++ g_signal_emit (session, signals [AUTHENTICATION_FAILED], 0, service_name, text); } - static void - on_session_accredited (GdmSession *session, -+ const char *service_name, - GdmFactorySlave *slave) + void +-_gdm_session_authorized (GdmSession *session) ++_gdm_session_authorized (GdmSession *session, ++ const char *service_name) { - g_debug ("GdmFactorySlave: session user verified"); - -- gdm_session_start_session (session); -+ gdm_session_start_session (session, service_name); + g_return_if_fail (GDM_IS_SESSION (session)); - gdm_greeter_server_reset (slave->priv->greeter_server); +- g_signal_emit (session, signals [AUTHORIZED], 0); ++ g_signal_emit (session, signals [AUTHORIZED], 0, service_name); } - static void - on_session_accreditation_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmFactorySlave *slave) + void + _gdm_session_authorization_failed (GdmSession *session, ++ const char *service_name, + const char *text) { - g_debug ("GdmFactorySlave: could not successfully authenticate user: %s", - message); - -- gdm_greeter_server_problem (slave->priv->greeter_server, _("Unable to establish credentials")); -+ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to establish credentials")); - - queue_greeter_reset (slave); + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [AUTHORIZATION_FAILED], 0, text); ++ g_signal_emit (session, signals [AUTHORIZATION_FAILED], 0, service_name, text); } -@@ -374,31 +386,34 @@ on_session_relay_connected (GdmSessionRelay *session, - static void - on_greeter_begin_verification (GdmGreeterServer *greeter_server, -+ const char *service_name, - GdmFactorySlave *slave) + void +-_gdm_session_accredited (GdmSession *session) ++_gdm_session_accredited (GdmSession *session, ++ const char *service_name) { - g_debug ("GdmFactorySlave: begin verification"); - gdm_session_setup (GDM_SESSION (slave->priv->session), -- "gdm"); -+ service_name); + g_return_if_fail (GDM_IS_SESSION (session)); + +- g_signal_emit (session, signals [ACCREDITED], 0); ++ g_signal_emit (session, signals [ACCREDITED], 0, service_name); } - static void - on_greeter_begin_verification_for_user (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *username, - GdmFactorySlave *slave) + void + _gdm_session_accreditation_failed (GdmSession *session, ++ const char *service_name, + const char *text) { - g_debug ("GdmFactorySlave: begin verification for user"); - gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), -- "gdm", -+ service_name, - username); + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [ACCREDITATION_FAILED], 0, text); ++ g_signal_emit (session, signals [ACCREDITATION_FAILED], 0, service_name, text); } - static void - on_greeter_answer (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text, - GdmFactorySlave *slave) + void + _gdm_session_info_query (GdmSession *session, ++ const char *service_name, + const char *text) { - g_debug ("GdmFactorySlave: Greeter answer"); -- gdm_session_answer_query (GDM_SESSION (slave->priv->session), text); -+ gdm_session_answer_query (GDM_SESSION (slave->priv->session), service_name, text); + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [INFO_QUERY], 0, text); ++ g_signal_emit (session, signals [INFO_QUERY], 0, service_name, text); } - static void -diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c -index 06c80a0..0ac0a09 100644 ---- a/daemon/gdm-greeter-server.c -+++ b/daemon/gdm-greeter-server.c -@@ -43,6 +43,7 @@ - #include - #include - -+#include "gdm-marshal.h" - #include "gdm-greeter-server.h" - - #define GDM_GREETER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/GreeterServer" -@@ -156,6 +157,46 @@ send_dbus_string_and_int_signal (GdmGreeterServer *greeter_server, + 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, text); ++ g_signal_emit (session, signals [SECRET_INFO_QUERY], 0, service_name, text); } - static void -+send_dbus_string_string_signal (GdmGreeterServer *greeter_server, -+ const char *name, -+ const char *text1, -+ const char *text2) -+{ -+ DBusMessage *message; -+ DBusMessageIter iter; -+ const char *str; -+ -+ g_return_if_fail (greeter_server != NULL); -+ -+ message = dbus_message_new_signal (GDM_GREETER_SERVER_DBUS_PATH, -+ GDM_GREETER_SERVER_DBUS_INTERFACE, -+ name); -+ -+ dbus_message_iter_init_append (message, &iter); -+ -+ if (text1 != NULL) { -+ str = text1; -+ } else { -+ str = ""; -+ } -+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str); -+ -+ if (text2 != NULL) { -+ str = text2; -+ } else { -+ str = ""; -+ } -+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str); -+ -+ g_debug ("GreeterServer: Sending %s (%s)", name, str); -+ if (! send_dbus_message (greeter_server->priv->greeter_connection, message)) { -+ g_debug ("GreeterServer: Could not send %s signal", name); -+ } -+ -+ dbus_message_unref (message); -+} -+ -+static void - send_dbus_string_signal (GdmGreeterServer *greeter_server, - const char *name, - const char *text) -@@ -208,34 +249,38 @@ send_dbus_void_signal (GdmGreeterServer *greeter_server, - - gboolean - gdm_greeter_server_info_query (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text) + void + _gdm_session_info (GdmSession *session, ++ const char *service_name, + const char *text) { -- send_dbus_string_signal (greeter_server, "InfoQuery", text); -+ send_dbus_string_string_signal (greeter_server, "InfoQuery", service_name, text); - - return TRUE; + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [INFO], 0, text); ++ g_signal_emit (session, signals [INFO], 0, service_name, text); } - gboolean - gdm_greeter_server_secret_info_query (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text) + void + _gdm_session_problem (GdmSession *session, ++ const char *service_name, + const char *text) { -- send_dbus_string_signal (greeter_server, "SecretInfoQuery", text); -+ send_dbus_string_string_signal (greeter_server, "SecretInfoQuery", service_name, text); - return TRUE; + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [PROBLEM], 0, text); ++ g_signal_emit (session, signals [PROBLEM], 0, service_name, text); } - gboolean - gdm_greeter_server_info (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text) + void + _gdm_session_session_started (GdmSession *session, ++ const char *service_name, + int pid) { -- send_dbus_string_signal (greeter_server, "Info", text); -+ send_dbus_string_string_signal (greeter_server, "Info", service_name, text); - return TRUE; + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [SESSION_STARTED], 0, pid); ++ g_signal_emit (session, signals [SESSION_STARTED], 0, service_name, pid); } - gboolean - gdm_greeter_server_problem (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text) + void + _gdm_session_session_start_failed (GdmSession *session, ++ const char *service_name, + const char *text) { -- send_dbus_string_signal (greeter_server, "Problem", text); -+ send_dbus_string_string_signal (greeter_server, "Problem", service_name, text); - return TRUE; + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [SESSION_START_FAILED], 0, text); ++ g_signal_emit (session, signals [SESSION_START_FAILED], 0, service_name, text); } -@@ -291,9 +336,10 @@ gdm_greeter_server_request_timed_login (GdmGreeterServer *greeter_server, + void +@@ -608,10 +650,19 @@ _gdm_session_session_died (GdmSession } void --gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server) -+gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server, -+ const char *service_name) +-_gdm_session_opened (GdmSession *session) ++_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) { -- send_dbus_void_signal (greeter_server, "UserAuthorized"); -+ send_dbus_string_signal (greeter_server, "UserAuthorized", service_name); + g_return_if_fail (GDM_IS_SESSION (session)); +- g_signal_emit (session, signals [OPENED], 0); ++ g_signal_emit (session, signals [CONVERSATION_STOPPED], 0, service_name); } - /* Note: Use abstract sockets like dbus does by default on Linux. Abstract -@@ -358,6 +404,16 @@ handle_begin_verification (GdmGreeterServer *greeter_server, - DBusMessage *message) - { - DBusMessage *reply; -+ DBusError error; -+ const char *service_name; + void +diff -up gdm-2.25.2/daemon/gdm-session-direct.c.multistack-but-boring gdm-2.25.2/daemon/gdm-session-direct.c +--- gdm-2.25.2/daemon/gdm-session-direct.c.multistack-but-boring 2009-03-03 17:45:05.519009518 -0500 ++++ gdm-2.25.2/daemon/gdm-session-direct.c 2009-03-03 17:45:05.702016205 -0500 +@@ -63,6 +63,16 @@ + #define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin" + #endif + ++typedef struct ++{ ++ GdmSessionDirect *session; ++ GdmSessionWorkerJob *job; ++ GPid worker_pid; ++ char *service_name; ++ DBusConnection *worker_connection; ++ DBusMessage *message_pending_reply; ++} GdmSessionConversation; + -+ 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); + struct _GdmSessionDirectPrivate + { + /* per open scope */ +@@ -75,13 +85,13 @@ struct _GdmSessionDirectPrivate + char *selected_user; + char *user_x11_authority_file; - g_debug ("GreeterServer: BeginVerification"); +- DBusMessage *message_pending_reply; +- DBusConnection *worker_connection; ++ GHashTable *conversations; ++ ++ GList *pending_connections; -@@ -365,7 +421,7 @@ handle_begin_verification (GdmGreeterServer *greeter_server, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); +- GdmSessionWorkerJob *job; +- GPid session_pid; + guint32 is_authenticated : 1; + guint32 is_running : 1; ++ GPid session_pid; -- g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION], 0); -+ g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION], 0, service_name); + /* object lifetime scope */ + char *id; +@@ -118,39 +128,39 @@ G_DEFINE_TYPE_WITH_CODE (GdmSessionDirec + gdm_session_iface_init)) - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -379,7 +435,6 @@ handle_begin_auto_login (GdmGreeterServer *greeter_server, - DBusError error; - const char *text; + static gboolean +-send_dbus_message (DBusConnection *connection, +- DBusMessage *message) ++send_dbus_message (GdmSessionConversation *conversation, ++ DBusMessage *message) + { + gboolean is_connected; + gboolean sent; -- - dbus_error_init (&error); - if (! dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &text, -@@ -406,13 +461,16 @@ handle_begin_verification_for_user (GdmGreeterServer *greeter_server, - DBusMessage *reply; - DBusError error; - const char *text; -+ const char *service_name; + g_return_val_if_fail (message != NULL, FALSE); - dbus_error_init (&error); - if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, - DBUS_TYPE_STRING, &text, - DBUS_TYPE_INVALID)) { - g_warning ("ERROR: %s", error.message); +- if (connection == NULL) { ++ if (conversation->worker_connection == NULL) { + g_warning ("There is no valid connection"); + return FALSE; } -+ dbus_error_free (&error); - g_debug ("GreeterServer: BeginVerificationForUser for '%s'", text); +- is_connected = dbus_connection_get_is_connected (connection); ++ is_connected = dbus_connection_get_is_connected (conversation->worker_connection); + if (! is_connected) { + g_warning ("Not connected!"); + return FALSE; + } -@@ -420,7 +478,7 @@ handle_begin_verification_for_user (GdmGreeterServer *greeter_server, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); +- sent = dbus_connection_send (connection, message, NULL); ++ sent = dbus_connection_send (conversation->worker_connection, message, NULL); -- g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION_FOR_USER], 0, text); -+ g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION_FOR_USER], 0, service_name, text); + return sent; + } - return DBUS_HANDLER_RESULT_HANDLED; + static void +-send_dbus_string_signal (GdmSessionDirect *session, ++send_dbus_string_signal (GdmSessionConversation *conversation, + const char *name, + const char *text) + { + DBusMessage *message; + DBusMessageIter iter; + +- g_return_if_fail (session != NULL); ++ g_return_if_fail (conversation != NULL); + + message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, + GDM_SESSION_DBUS_INTERFACE, +@@ -159,7 +169,7 @@ send_dbus_string_signal (GdmSessionDirec + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text); + +- if (! send_dbus_message (session->priv->worker_connection, message)) { ++ if (! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", name); + } + +@@ -167,57 +177,90 @@ send_dbus_string_signal (GdmSessionDirec } -@@ -433,13 +491,16 @@ handle_answer_query (GdmGreeterServer *greeter_server, - DBusMessage *reply; - DBusError error; - const char *text; -+ const char *service_name; - dbus_error_init (&error); - if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, - DBUS_TYPE_STRING, &text, - DBUS_TYPE_INVALID)) { - g_warning ("ERROR: %s", error.message); + static void +-send_dbus_void_signal (GdmSessionDirect *session, +- const char *name) ++send_dbus_void_signal (GdmSessionConversation *conversation, ++ const char *name) + { + DBusMessage *message; + +- g_return_if_fail (session != NULL); ++ g_return_if_fail (conversation != NULL); + + message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, + GDM_SESSION_DBUS_INTERFACE, + name); + +- if (! send_dbus_message (session->priv->worker_connection, message)) { ++ if (! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", name); } -+ dbus_error_free (&error); - g_debug ("GreeterServer: AnswerQuery"); + dbus_message_unref (message); + } -@@ -447,7 +508,7 @@ handle_answer_query (GdmGreeterServer *greeter_server, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); ++static GdmSessionConversation * ++find_conversation_by_name (GdmSessionDirect *session, ++ const char *service_name) ++{ ++ GdmSessionConversation *conversation; ++ ++ conversation = g_hash_table_lookup (session->priv->conversations, service_name); ++ ++ if (conversation == NULL) { ++ g_warning ("Tried to look up non-existant conversation"); ++ } ++ ++ return conversation; ++} ++ + static void + on_authentication_failed (GdmSession *session, ++ const char *service_name, + const char *message) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +- gdm_session_record_failed (impl->priv->session_pid, +- impl->priv->selected_user, +- impl->priv->display_hostname, +- impl->priv->display_name, +- impl->priv->display_device); ++ GdmSessionConversation *conversation; ++ ++ conversation = find_conversation_by_name (impl, service_name); ++ if (conversation != NULL) { ++ gdm_session_record_failed (conversation->worker_pid, ++ impl->priv->selected_user, ++ impl->priv->display_hostname, ++ impl->priv->display_name, ++ impl->priv->display_device); ++ } + } -- g_signal_emit (greeter_server, signals [QUERY_ANSWER], 0, text); -+ g_signal_emit (greeter_server, signals [QUERY_ANSWER], 0, service_name, text); + static void +-on_session_started (GdmSession *session) ++on_session_started (GdmSession *session, ++ const char *service_name) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +- gdm_session_record_login (impl->priv->session_pid, +- impl->priv->selected_user, +- impl->priv->display_hostname, +- impl->priv->display_name, +- impl->priv->display_device); ++ GdmSessionConversation *conversation; ++ ++ conversation = find_conversation_by_name (impl, service_name); ++ if (conversation != NULL) { ++ gdm_session_record_login (conversation->worker_pid, ++ impl->priv->selected_user, ++ impl->priv->display_hostname, ++ impl->priv->display_name, ++ impl->priv->display_device); ++ } + } - return DBUS_HANDLER_RESULT_HANDLED; + static void + on_session_start_failed (GdmSession *session, ++ const char *service_name, + const char *message) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +- gdm_session_record_login (impl->priv->session_pid, +- impl->priv->selected_user, +- impl->priv->display_hostname, +- impl->priv->display_name, +- impl->priv->display_device); ++ GdmSessionConversation *conversation; ++ ++ conversation = find_conversation_by_name (impl, service_name); ++ if (conversation != NULL) { ++ gdm_session_record_login (conversation->worker_pid, ++ impl->priv->selected_user, ++ impl->priv->display_hostname, ++ impl->priv->display_name, ++ impl->priv->display_device); ++ } } -@@ -644,9 +705,11 @@ handle_start_session_when_ready (GdmGreeterServer *greeter_server, + + static void +@@ -225,6 +268,7 @@ on_session_exited (GdmSession *session, + int exit_code) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ + gdm_session_record_logout (impl->priv->session_pid, + impl->priv->selected_user, + impl->priv->display_hostname, +@@ -234,7 +278,7 @@ on_session_exited (GdmSession *session, + + static DBusHandlerResult + gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { DBusMessage *reply; - DBusError error; - gboolean should_start_session; -+ char *service_name; +@@ -242,17 +286,17 @@ gdm_session_direct_handle_setup_complete + g_debug ("GdmSessionDirect: Emitting 'setup-complete' signal"); - dbus_error_init (&error); - if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, - DBUS_TYPE_BOOLEAN, &should_start_session, - DBUS_TYPE_INVALID)) { - g_warning ("ERROR: %s", error.message); -@@ -660,9 +723,9 @@ handle_start_session_when_ready (GdmGreeterServer *greeter_server, + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); - if (should_start_session) { -- g_signal_emit (greeter_server, signals [START_SESSION_WHEN_READY], 0); -+ g_signal_emit (greeter_server, signals [START_SESSION_WHEN_READY], 0, service_name); - } else { -- g_signal_emit (greeter_server, signals [START_SESSION_LATER] ,0); -+ g_signal_emit (greeter_server, signals [START_SESSION_LATER] ,0, service_name); - } +- _gdm_session_setup_complete (GDM_SESSION (session)); ++ _gdm_session_setup_complete (GDM_SESSION (session), conversation->service_name); return DBUS_HANDLER_RESULT_HANDLED; -@@ -735,13 +798,16 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -764,18 +830,23 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -801,6 +872,7 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n"); + } -@@ -1176,9 +1248,9 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) - G_STRUCT_OFFSET (GdmGreeterServerClass, begin_verification), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); - signals [BEGIN_AUTO_LOGIN] = - g_signal_new ("begin-auto-login", - G_OBJECT_CLASS_TYPE (object_class), -@@ -1197,10 +1269,10 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) - G_STRUCT_OFFSET (GdmGreeterServerClass, begin_verification_for_user), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [QUERY_ANSWER] = - g_signal_new ("query-answer", - G_OBJECT_CLASS_TYPE (object_class), -@@ -1208,10 +1280,10 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) - G_STRUCT_OFFSET (GdmGreeterServerClass, query_answer), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [SESSION_SELECTED] = - g_signal_new ("session-selected", - G_OBJECT_CLASS_TYPE (object_class), -@@ -1305,9 +1377,9 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) - G_STRUCT_OFFSET (GdmGreeterServerClass, start_session_when_ready), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); + static DBusHandlerResult + gdm_session_direct_handle_setup_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -267,12 +311,12 @@ gdm_session_direct_handle_setup_failed ( + } - signals [START_SESSION_LATER] = - g_signal_new ("start-session-later", -@@ -1316,9 +1388,9 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) - G_STRUCT_OFFSET (GdmGreeterServerClass, start_session_later), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + + g_debug ("GdmSessionDirect: Emitting 'setup-failed' signal"); + +- _gdm_session_setup_failed (GDM_SESSION (session), NULL); ++ _gdm_session_setup_failed (GDM_SESSION (session), conversation->service_name, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; } +@@ -280,7 +324,7 @@ gdm_session_direct_handle_setup_failed ( - static void -diff --git a/daemon/gdm-greeter-server.h b/daemon/gdm-greeter-server.h -index 7333db1..6d0dd87 100644 ---- a/daemon/gdm-greeter-server.h -+++ b/daemon/gdm-greeter-server.h -@@ -48,10 +48,13 @@ typedef struct - void (* start_conversation) (GdmGreeterServer *greeter_server, - const char *service_name); - void (* begin_auto_login) (GdmGreeterServer *greeter_server); -- void (* begin_verification) (GdmGreeterServer *greeter_server); -+ void (* begin_verification) (GdmGreeterServer *greeter_server, -+ const char *service_name); - void (* begin_verification_for_user)(GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *username); - void (* query_answer) (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text); - void (* session_selected) (GdmGreeterServer *greeter_server, - const char *name); -@@ -66,7 +69,8 @@ typedef struct - void (* cancelled) (GdmGreeterServer *greeter_server); - void (* connected) (GdmGreeterServer *greeter_server); - void (* disconnected) (GdmGreeterServer *greeter_server); -- void (* start_session_when_ready) (GdmGreeterServer *greeter_server); -+ void (* start_session_when_ready) (GdmGreeterServer *greeter_server, -+ const char *service_name); - void (* start_session_later) (GdmGreeterServer *greeter_server); - } GdmGreeterServerClass; + static DBusHandlerResult + gdm_session_direct_handle_reset_complete (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -288,7 +332,7 @@ gdm_session_direct_handle_reset_complete + g_debug ("GdmSessionDirect: Emitting 'reset-complete' signal"); -@@ -77,14 +81,17 @@ gboolean gdm_greeter_server_start (GdmGreeterServer * - gboolean gdm_greeter_server_stop (GdmGreeterServer *greeter_server); - char * gdm_greeter_server_get_address (GdmGreeterServer *greeter_server); + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); -- - gboolean gdm_greeter_server_info_query (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text); - gboolean gdm_greeter_server_secret_info_query (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text); - gboolean gdm_greeter_server_info (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text); - gboolean gdm_greeter_server_problem (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text); - gboolean gdm_greeter_server_reset (GdmGreeterServer *greeter_server); - gboolean gdm_greeter_server_ready (GdmGreeterServer *greeter_server, -@@ -101,8 +108,8 @@ void gdm_greeter_server_default_session_name_changed (GdmGreeterS - void gdm_greeter_server_request_timed_login (GdmGreeterServer *greeter_server, - const char *username, - int delay); --void gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server); -- -+void gdm_greeter_server_user_authorized (GdmGreeterServer *greeter_server, -+ const char *service_name); + _gdm_session_reset_complete (GDM_SESSION (session)); +@@ -298,7 +342,7 @@ gdm_session_direct_handle_reset_complete - G_END_DECLS + static DBusHandlerResult + gdm_session_direct_handle_reset_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -313,7 +357,7 @@ gdm_session_direct_handle_reset_failed ( + } -diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c -index 15a2820..dd2e1bc 100644 ---- a/daemon/gdm-product-slave.c -+++ b/daemon/gdm-product-slave.c -@@ -79,6 +79,8 @@ struct GdmProductSlavePrivate + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); - DBusGProxy *product_display_proxy; - DBusGConnection *connection; -+ -+ char *start_session_service_name; - }; + g_debug ("GdmSessionDirect: Emitting 'reset-failed' signal"); +@@ -325,7 +369,7 @@ gdm_session_direct_handle_reset_failed ( - enum { -@@ -93,6 +95,68 @@ static void gdm_product_slave_finalize (GObject *object); - G_DEFINE_TYPE (GdmProductSlave, gdm_product_slave, GDM_TYPE_SLAVE) + static DBusHandlerResult + gdm_session_direct_handle_authenticated (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -333,17 +377,17 @@ gdm_session_direct_handle_authenticated + g_debug ("GdmSessionDirect: Emitting 'authenticated' signal"); - static gboolean -+send_dbus_string_string_method (DBusConnection *connection, -+ const char *method, -+ const char *payload1, -+ const char *payload2) -+{ -+ DBusError error; -+ DBusMessage *message; -+ DBusMessage *reply; -+ DBusMessageIter iter; -+ const char *str; -+ -+ g_debug ("GdmProductSlave: Calling %s", method); -+ message = dbus_message_new_method_call (NULL, -+ RELAY_SERVER_DBUS_PATH, -+ RELAY_SERVER_DBUS_INTERFACE, -+ method); -+ if (message == NULL) { -+ g_warning ("Couldn't allocate the D-Bus message"); -+ return FALSE; -+ } -+ -+ dbus_message_iter_init_append (message, &iter); -+ -+ if (payload1 != NULL) { -+ str = payload1; -+ } else { -+ str = ""; -+ } -+ dbus_message_iter_append_basic (&iter, -+ DBUS_TYPE_STRING, -+ &str); -+ if (payload2 != NULL) { -+ str = payload2; -+ } else { -+ str = ""; -+ } -+ dbus_message_iter_append_basic (&iter, -+ DBUS_TYPE_STRING, -+ &str); -+ dbus_error_init (&error); -+ reply = dbus_connection_send_with_reply_and_block (connection, -+ message, -+ -1, -+ &error); -+ -+ dbus_message_unref (message); -+ -+ if (dbus_error_is_set (&error)) { -+ g_warning ("%s %s raised: %s\n", -+ method, -+ error.name, -+ error.message); -+ return FALSE; -+ } -+ if (reply != NULL) { -+ dbus_message_unref (reply); -+ } -+ dbus_connection_flush (connection); -+ -+ return TRUE; -+} -+static gboolean - send_dbus_string_method (DBusConnection *connection, - const char *method, - const char *payload) -@@ -356,7 +420,8 @@ setup_session (GdmProductSlave *slave) - g_free (display_device); - g_free (auth_file); + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); -- gdm_session_start_session (GDM_SESSION (slave->priv->session)); -+ gdm_session_start_session (GDM_SESSION (slave->priv->session), -+ slave->priv->start_session_service_name); +- _gdm_session_authenticated (GDM_SESSION (session)); ++ _gdm_session_authenticated (GDM_SESSION (session), conversation->service_name); - return TRUE; + return DBUS_HANDLER_RESULT_HANDLED; } -@@ -508,96 +573,112 @@ on_session_reset_failed (GdmSession *session, - static void - on_session_authenticated (GdmSession *session, -+ const char *service_name, - GdmProductSlave *slave) + static DBusHandlerResult + gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { -- send_dbus_void_method (slave->priv->session_relay_connection, -- "Authenticated"); -+ send_dbus_string_method (slave->priv->session_relay_connection, -+ "Authenticated", service_name); - } + DBusMessage *reply; +@@ -358,19 +402,19 @@ gdm_session_direct_handle_authentication + } - static void - on_session_authentication_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmProductSlave *slave) - { -- send_dbus_string_method (slave->priv->session_relay_connection, -- "AuthenticationFailed", -- message); -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "AuthenticationFailed", -+ service_name, -+ message); - } + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); - static void - on_session_authorized (GdmSession *session, -+ const char *service_name, - GdmProductSlave *slave) - { -- send_dbus_void_method (slave->priv->session_relay_connection, -- "Authorized"); -+ send_dbus_string_method (slave->priv->session_relay_connection, -+ "Authorized", service_name); - } + g_debug ("GdmSessionDirect: Emitting 'authentication-failed' signal"); - static void - on_session_authorization_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmProductSlave *slave) - { -- send_dbus_string_method (slave->priv->session_relay_connection, -- "AuthorizationFailed", -- message); -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "AuthorizationFailed", -+ service_name, -+ message); +- _gdm_session_authentication_failed (GDM_SESSION (session), NULL); ++ _gdm_session_authentication_failed (GDM_SESSION (session), conversation->service_name, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; } - static void - on_session_accredited (GdmSession *session, -+ const char *service_name, - GdmProductSlave *slave) + static DBusHandlerResult + gdm_session_direct_handle_authorized (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { -- send_dbus_void_method (slave->priv->session_relay_connection, -- "Accredited"); -+ send_dbus_string_method (slave->priv->session_relay_connection, -+ "Accredited", service_name); + DBusMessage *reply; +@@ -378,17 +422,17 @@ gdm_session_direct_handle_authorized (Gd + g_debug ("GdmSessionDirect: Emitting 'authorized' signal"); + + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_authorized (GDM_SESSION (session)); ++ _gdm_session_authorized (GDM_SESSION (session), conversation->service_name); + + return DBUS_HANDLER_RESULT_HANDLED; } - static void - on_session_accreditation_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmProductSlave *slave) + static DBusHandlerResult + gdm_session_direct_handle_authorization_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { -- send_dbus_string_method (slave->priv->session_relay_connection, -- "AccreditationFailed", -- message); -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "AccreditationFailed", -+ service_name, -+ message); + DBusMessage *reply; +@@ -403,19 +447,19 @@ gdm_session_direct_handle_authorization_ + } + + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + + g_debug ("GdmSessionDirect: Emitting 'authorization-failed' signal"); + +- _gdm_session_authorization_failed (GDM_SESSION (session), NULL); ++ _gdm_session_authorization_failed (GDM_SESSION (session), conversation->service_name, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; } - static void - on_session_info (GdmSession *session, -+ const char *service_name, - const char *text, - GdmProductSlave *slave) + static DBusHandlerResult + gdm_session_direct_handle_accredited (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { -- send_dbus_string_method (slave->priv->session_relay_connection, -- "Info", -- text); -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "Info", -+ service_name, -+ text); + DBusMessage *reply; +@@ -423,17 +467,17 @@ gdm_session_direct_handle_accredited (Gd + g_debug ("GdmSessionDirect: Emitting 'accredited' signal"); + + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_accredited (GDM_SESSION (session)); ++ _gdm_session_accredited (GDM_SESSION (session), conversation->service_name); + + return DBUS_HANDLER_RESULT_HANDLED; } - static void - on_session_problem (GdmSession *session, -+ const char *service_name, - const char *text, - GdmProductSlave *slave) + static DBusHandlerResult + gdm_session_direct_handle_accreditation_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { -- send_dbus_string_method (slave->priv->session_relay_connection, -- "Problem", -- text); -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "Problem", -+ service_name, -+ text); + DBusMessage *reply; +@@ -448,12 +492,12 @@ gdm_session_direct_handle_accreditation_ + } + + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + + g_debug ("GdmSessionDirect: Emitting 'accreditation-failed' signal"); + +- _gdm_session_accreditation_failed (GDM_SESSION (session), NULL); ++ _gdm_session_accreditation_failed (GDM_SESSION (session), conversation->service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; } +@@ -753,7 +797,7 @@ gdm_session_direct_select_user (GdmSessi - static void - on_session_info_query (GdmSession *session, -+ const char *service_name, - const char *text, - GdmProductSlave *slave) + static DBusHandlerResult + gdm_session_direct_handle_username_changed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { -- send_dbus_string_method (slave->priv->session_relay_connection, -- "InfoQuery", -- text); -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "InfoQuery", -+ service_name, text); + DBusMessage *reply; +@@ -768,7 +812,7 @@ gdm_session_direct_handle_username_chang + } + + reply = dbus_message_new_method_return (message); +- dbus_connection_send (connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + + g_debug ("GdmSessionDirect: changing username from '%s' to '%s'", +@@ -785,59 +829,61 @@ gdm_session_direct_handle_username_chang } static void - on_session_secret_info_query (GdmSession *session, -+ const char *service_name, - const char *text, - GdmProductSlave *slave) +-cancel_pending_query (GdmSessionDirect *session) ++cancel_pending_query (GdmSessionConversation *conversation) { -- send_dbus_string_method (slave->priv->session_relay_connection, -- "SecretInfoQuery", -- text); -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "SecretInfoQuery", -+ service_name, -+ text); - } + DBusMessage *reply; - static void -@@ -658,36 +739,92 @@ static void - on_relay_authenticate (GdmProductSlave *slave, - DBusMessage *message) - { -- g_debug ("GdmProductSlave: Relay Authenticate"); -+ DBusError error; -+ char *service_name; -+ dbus_bool_t res; +- if (session->priv->message_pending_reply == NULL) { ++ if (conversation->message_pending_reply == NULL) { + return; + } -- gdm_session_authenticate (GDM_SESSION (slave->priv->session)); -+ dbus_error_init (&error); -+ res = dbus_message_get_args (message, -+ &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID); -+ if (res) { -+ g_debug ("GdmProductSlave: Relay Authenticate"); -+ gdm_session_authenticate (GDM_SESSION (slave->priv->session), service_name); -+ } else { -+ g_warning ("Unable to get arguments: %s", error.message); -+ dbus_error_free (&error); -+ } -+ dbus_error_free (&error); - } + g_debug ("GdmSessionDirect: Cancelling pending query"); - static void - on_relay_authorize (GdmProductSlave *slave, - DBusMessage *message) - { -- g_debug ("GdmProductSlave: Relay Authorize"); -+ DBusError error; -+ char *service_name; -+ dbus_bool_t res; +- reply = dbus_message_new_error (session->priv->message_pending_reply, ++ reply = dbus_message_new_error (conversation->message_pending_reply, + GDM_SESSION_DBUS_ERROR_CANCEL, + "Operation cancelled"); +- dbus_connection_send (session->priv->worker_connection, reply, NULL); +- dbus_connection_flush (session->priv->worker_connection); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); ++ dbus_connection_flush (conversation->worker_connection); -- gdm_session_authorize (GDM_SESSION (slave->priv->session)); -+ dbus_error_init (&error); -+ res = dbus_message_get_args (message, -+ &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID); -+ if (res) { -+ g_debug ("GdmProductSlave: Relay Authorize"); -+ gdm_session_authorize (GDM_SESSION (slave->priv->session), service_name); -+ } else { -+ g_warning ("Unable to get arguments: %s", error.message); -+ dbus_error_free (&error); -+ } -+ dbus_error_free (&error); + dbus_message_unref (reply); +- dbus_message_unref (session->priv->message_pending_reply); +- session->priv->message_pending_reply = NULL; ++ dbus_message_unref (conversation->message_pending_reply); ++ conversation->message_pending_reply = NULL; } static void - on_relay_establish_credentials (GdmProductSlave *slave, - DBusMessage *message) + answer_pending_query (GdmSessionDirect *session, ++ const char *service_name, + const char *answer) { -- g_debug ("GdmProductSlave: Relay EstablishCredentials"); -+ DBusError error; -+ char *service_name; -+ dbus_bool_t res; + DBusMessage *reply; + DBusMessageIter iter; ++ GdmSessionConversation *conversation; -- gdm_session_accredit (GDM_SESSION (slave->priv->session), GDM_SESSION_CRED_ESTABLISH); -+ dbus_error_init (&error); -+ res = dbus_message_get_args (message, -+ &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID); -+ if (res) { -+ g_debug ("GdmProductSlave: Relay EstablishCredentials"); -+ gdm_session_accredit (GDM_SESSION (slave->priv->session), service_name, GDM_SESSION_CRED_ESTABLISH); -+ } else { -+ g_warning ("Unable to get arguments: %s", error.message); -+ dbus_error_free (&error); -+ } -+ dbus_error_free (&error); - } +- g_assert (session->priv->message_pending_reply != NULL); ++ conversation = find_conversation_by_name (session, service_name); - static void - on_relay_refresh_credentials (GdmProductSlave *slave, - DBusMessage *message) - { -- g_debug ("GdmProductSlave: Relay RefreshCredentials"); -+ DBusError error; -+ char *service_name; -+ dbus_bool_t res; +- reply = dbus_message_new_method_return (session->priv->message_pending_reply); ++ 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); -- gdm_session_accredit (GDM_SESSION (slave->priv->session), GDM_SESSION_CRED_REFRESH); -+ dbus_error_init (&error); -+ res = dbus_message_get_args (message, -+ &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID); -+ if (res) { -+ g_debug ("GdmProductSlave: Relay RefreshCredentials"); -+ gdm_session_accredit (GDM_SESSION (slave->priv->session), service_name, GDM_SESSION_CRED_REFRESH); -+ } else { -+ g_warning ("Unable to get arguments: %s", error.message); -+ dbus_error_free (&error); -+ } -+ dbus_error_free (&error); +- dbus_connection_send (session->priv->worker_connection, reply, NULL); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + +- dbus_message_unref (session->priv->message_pending_reply); +- session->priv->message_pending_reply = NULL; ++ dbus_message_unref (conversation->message_pending_reply); ++ conversation->message_pending_reply = NULL; } static void -@@ -696,16 +833,18 @@ on_relay_answer_query (GdmProductSlave *slave, +-set_pending_query (GdmSessionDirect *session, +- DBusMessage *message) ++set_pending_query (GdmSessionConversation *conversation, ++ DBusMessage *message) { - DBusError error; - const char *text; -+ const char *service_name; - dbus_bool_t res; +- g_assert (session->priv->message_pending_reply == NULL); ++ g_assert (conversation->message_pending_reply == NULL); - dbus_error_init (&error); - res = dbus_message_get_args (message, - &error, -+ DBUS_TYPE_STRING, &service_name, - DBUS_TYPE_STRING, &text, - DBUS_TYPE_INVALID); - if (res) { - g_debug ("GdmProductSlave: Relay AnswerQuery"); -- gdm_session_answer_query (GDM_SESSION (slave->priv->session), text); -+ gdm_session_answer_query (GDM_SESSION (slave->priv->session), service_name, text); - } else { - g_warning ("Unable to get arguments: %s", error.message); - dbus_error_free (&error); -@@ -813,7 +952,25 @@ static void - on_relay_start_session (GdmProductSlave *slave, - DBusMessage *message) - { -- gdm_product_slave_create_server (slave); -+ DBusError error; -+ const char *service_name; -+ dbus_bool_t res; -+ -+ dbus_error_init (&error); -+ -+ res = dbus_message_get_args (message, -+ &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID); -+ if (res) { -+ g_debug ("GdmProductSlave: Relay StartSession"); -+ g_free (slave->priv->start_session_service_name); -+ slave->priv->start_session_service_name = g_strdup (service_name); -+ gdm_product_slave_create_server (slave); -+ } else { -+ g_warning ("Unable to get arguments: %s", error.message); -+ dbus_error_free (&error); -+ } +- session->priv->message_pending_reply = dbus_message_ref (message); ++ conversation->message_pending_reply = dbus_message_ref (message); } - static void -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 5a93103..a12e333 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -84,9 +84,10 @@ struct _GdmSessionDirectPrivate - - DBusMessage *message_pending_reply; - -- GdmSessionConversation *conversation; - GHashTable *conversations; + static DBusHandlerResult + gdm_session_direct_handle_info_query (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusError error; +@@ -850,17 +896,17 @@ gdm_session_direct_handle_info_query (Gd + g_warning ("ERROR: %s", error.message); + } -+ GList *pending_connections; -+ - guint32 is_authenticated : 1; - guint32 is_running : 1; - GPid session_pid; -@@ -193,14 +194,30 @@ send_dbus_void_signal (GdmSessionConversation *conversation, - dbus_message_unref (message); - } +- set_pending_query (session, message); ++ set_pending_query (conversation, message); -+static GdmSessionConversation * -+find_conversation_by_name (GdmSessionDirect *session, -+ const char *service_name) -+{ -+ GdmSessionConversation *conversation; -+ -+ conversation = g_hash_table_lookup (session->priv->conversations, service_name); -+ -+ if (conversation == NULL) { -+ g_warning ("Tried to look up non-existant conversation"); -+ } -+ -+ return conversation; -+} -+ - static void - on_authentication_failed (GdmSession *session, -+ const char *service_name, - const char *message) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; + g_debug ("GdmSessionDirect: Emitting 'info-query' signal"); +- _gdm_session_info_query (GDM_SESSION (session), text); ++ _gdm_session_info_query (GDM_SESSION (session), conversation->service_name, text); -- conversation = impl->priv->conversation; -+ conversation = find_conversation_by_name (impl, service_name); - if (conversation != NULL) { - gdm_session_record_failed (conversation->worker_pid, - impl->priv->selected_user, -@@ -211,12 +228,13 @@ on_authentication_failed (GdmSession *session, + return DBUS_HANDLER_RESULT_HANDLED; } - static void --on_session_started (GdmSession *session) -+on_session_started (GdmSession *session, -+ const char *service_name) + static DBusHandlerResult + gdm_session_direct_handle_secret_info_query (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; + DBusError error; +@@ -873,17 +919,17 @@ gdm_session_direct_handle_secret_info_qu + g_warning ("ERROR: %s", error.message); + } -- conversation = impl->priv->conversation; -+ conversation = find_conversation_by_name (impl, service_name); - if (conversation != NULL) { - gdm_session_record_login (conversation->worker_pid, - impl->priv->selected_user, -@@ -228,12 +246,13 @@ on_session_started (GdmSession *session) +- set_pending_query (session, message); ++ set_pending_query (conversation, message); - static void - on_session_start_failed (GdmSession *session, -+ const char *service_name, - const char *message) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; + g_debug ("GdmSessionDirect: Emitting 'secret-info-query' signal"); +- _gdm_session_secret_info_query (GDM_SESSION (session), text); ++ _gdm_session_secret_info_query (GDM_SESSION (session), conversation->service_name, text); -- conversation = impl->priv->conversation; -+ conversation = find_conversation_by_name (impl, service_name); - if (conversation != NULL) { - gdm_session_record_login (conversation->worker_pid, - impl->priv->selected_user, -@@ -258,7 +277,7 @@ on_session_exited (GdmSession *session, + return DBUS_HANDLER_RESULT_HANDLED; + } static DBusHandlerResult - gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_info (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -266,17 +285,17 @@ gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, - g_debug ("GdmSessionDirect: Emitting 'setup-complete' signal"); - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_setup_complete (GDM_SESSION (session)); -+ _gdm_session_setup_complete (GDM_SESSION (session), conversation->service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_setup_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -291,12 +310,12 @@ gdm_session_direct_handle_setup_failed (GdmSessionDirect *session, +@@ -898,27 +944,27 @@ gdm_session_direct_handle_info (GdmSessi } reply = dbus_message_new_method_return (message); @@ -3083,80 +2393,41 @@ index 5a93103..a12e333 100644 + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); - g_debug ("GdmSessionDirect: Emitting 'setup-failed' signal"); - -- _gdm_session_setup_failed (GDM_SESSION (session), NULL); -+ _gdm_session_setup_failed (GDM_SESSION (session), conversation->service_name, NULL); + g_debug ("GdmSessionDirect: Emitting 'info' signal"); +- _gdm_session_info (GDM_SESSION (session), text); ++ _gdm_session_info (GDM_SESSION (session), conversation->service_name, text); return DBUS_HANDLER_RESULT_HANDLED; } -@@ -304,7 +323,7 @@ gdm_session_direct_handle_setup_failed (GdmSessionDirect *session, - - static DBusHandlerResult - gdm_session_direct_handle_reset_complete (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -312,7 +331,7 @@ gdm_session_direct_handle_reset_complete (GdmSessionDirect *session, - g_debug ("GdmSessionDirect: Emitting 'reset-complete' signal"); - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - _gdm_session_reset_complete (GDM_SESSION (session)); -@@ -322,7 +341,7 @@ gdm_session_direct_handle_reset_complete (GdmSessionDirect *session, static DBusHandlerResult - gdm_session_direct_handle_reset_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -337,7 +356,7 @@ gdm_session_direct_handle_reset_failed (GdmSessionDirect *session, - } - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - g_debug ("GdmSessionDirect: Emitting 'reset-failed' signal"); -@@ -349,7 +368,7 @@ gdm_session_direct_handle_reset_failed (GdmSessionDirect *session, - static DBusHandlerResult - gdm_session_direct_handle_authenticated (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -357,17 +376,17 @@ gdm_session_direct_handle_authenticated (GdmSessionDirect *session, - g_debug ("GdmSessionDirect: Emitting 'authenticated' signal"); + g_debug ("GdmSessionDirect: worker cancelling pending query"); +- cancel_pending_query (session); ++ cancel_pending_query (conversation); reply = dbus_message_new_method_return (message); - dbus_connection_send (connection, reply, NULL); + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); -- _gdm_session_authenticated (GDM_SESSION (session)); -+ _gdm_session_authenticated (GDM_SESSION (session), conversation->service_name); - return DBUS_HANDLER_RESULT_HANDLED; - } +@@ -926,7 +972,7 @@ gdm_session_direct_handle_cancel_pending static DBusHandlerResult - gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_problem (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -382,19 +401,19 @@ gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session, +@@ -941,18 +987,18 @@ gdm_session_direct_handle_problem (GdmSe } reply = dbus_message_new_method_return (message); @@ -3164,43 +2435,21 @@ index 5a93103..a12e333 100644 + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); - g_debug ("GdmSessionDirect: Emitting 'authentication-failed' signal"); - -- _gdm_session_authentication_failed (GDM_SESSION (session), NULL); -+ _gdm_session_authentication_failed (GDM_SESSION (session), conversation->service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_authorized (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -402,17 +421,17 @@ gdm_session_direct_handle_authorized (GdmSessionDirect *session, - g_debug ("GdmSessionDirect: Emitting 'authorized' signal"); - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authorized (GDM_SESSION (session)); -+ _gdm_session_authorized (GDM_SESSION (session), conversation->service_name); + g_debug ("GdmSessionDirect: Emitting 'problem' signal"); +- _gdm_session_problem (GDM_SESSION (session), text); ++ _gdm_session_problem (GDM_SESSION (session), conversation->service_name, text); return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult - gdm_session_direct_handle_authorization_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_session_started (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -427,19 +446,19 @@ gdm_session_direct_handle_authorization_failed (GdmSessionDirect *session, +@@ -971,7 +1017,7 @@ gdm_session_direct_handle_session_starte } reply = dbus_message_new_method_return (message); @@ -3208,43 +2457,47 @@ index 5a93103..a12e333 100644 + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); - g_debug ("GdmSessionDirect: Emitting 'authorization-failed' signal"); + g_debug ("GdmSessionDirect: Emitting 'session-started' signal with pid '%d'", +@@ -980,14 +1026,14 @@ gdm_session_direct_handle_session_starte + session->priv->session_pid = pid; + session->priv->is_running = TRUE; -- _gdm_session_authorization_failed (GDM_SESSION (session), NULL); -+ _gdm_session_authorization_failed (GDM_SESSION (session), conversation->service_name, NULL); +- _gdm_session_session_started (GDM_SESSION (session), pid); ++ _gdm_session_session_started (GDM_SESSION (session), conversation->service_name, pid); return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult - gdm_session_direct_handle_accredited (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_start_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -447,17 +466,17 @@ gdm_session_direct_handle_accredited (GdmSessionDirect *session, - g_debug ("GdmSessionDirect: Emitting 'accredited' signal"); +@@ -1002,18 +1048,18 @@ gdm_session_direct_handle_start_failed ( + } reply = dbus_message_new_method_return (message); - dbus_connection_send (connection, reply, NULL); + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); -- _gdm_session_accredited (GDM_SESSION (session)); -+ _gdm_session_accredited (GDM_SESSION (session), conversation->service_name); + g_debug ("GdmSessionDirect: Emitting 'session-start-failed' signal"); +- _gdm_session_session_start_failed (GDM_SESSION (session), text); ++ _gdm_session_session_start_failed (GDM_SESSION (session), conversation->service_name, text); return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult - gdm_session_direct_handle_accreditation_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_session_exited (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -472,12 +491,12 @@ gdm_session_direct_handle_accreditation_failed (GdmSessionDirect *session, +@@ -1028,7 +1074,7 @@ gdm_session_direct_handle_session_exited } reply = dbus_message_new_method_return (message); @@ -3252,23 +2505,17 @@ index 5a93103..a12e333 100644 + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); - g_debug ("GdmSessionDirect: Emitting 'accreditation-failed' signal"); - -- _gdm_session_accreditation_failed (GDM_SESSION (session), NULL); -+ _gdm_session_accreditation_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -725,7 +744,7 @@ gdm_session_direct_select_user (GdmSession *session, + g_debug ("GdmSessionDirect: Emitting 'session-exited' signal with exit code '%d'", +@@ -1042,7 +1088,7 @@ gdm_session_direct_handle_session_exited static DBusHandlerResult - gdm_session_direct_handle_username_changed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_session_died (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -740,7 +759,7 @@ gdm_session_direct_handle_username_changed (GdmSessionDirect *session, +@@ -1057,7 +1103,7 @@ gdm_session_direct_handle_session_died ( } reply = dbus_message_new_method_return (message); @@ -3276,77 +2523,17 @@ index 5a93103..a12e333 100644 + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); - g_debug ("GdmSessionDirect: changing username from '%s' to '%s'", -@@ -771,7 +790,7 @@ cancel_pending_query (GdmSessionDirect *session) - reply = dbus_message_new_error (session->priv->message_pending_reply, - GDM_SESSION_DBUS_ERROR_CANCEL, - "Operation cancelled"); -- conversation = session->priv->conversation; -+ conversation = NULL; - dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_connection_flush (conversation->worker_connection); - -@@ -782,6 +801,7 @@ cancel_pending_query (GdmSessionDirect *session) - - static void - answer_pending_query (GdmSessionDirect *session, -+ const char *service_name, - const char *answer) - { - DBusMessage *reply; -@@ -794,7 +814,7 @@ answer_pending_query (GdmSessionDirect *session, - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &answer); - -- conversation = session->priv->conversation; -+ conversation = find_conversation_by_name (session, service_name); - dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - -@@ -813,7 +833,7 @@ set_pending_query (GdmSessionDirect *session, - - static DBusHandlerResult - gdm_session_direct_handle_info_query (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusError error; -@@ -829,14 +849,14 @@ gdm_session_direct_handle_info_query (GdmSessionDirect *session, - set_pending_query (session, message); - - g_debug ("GdmSessionDirect: Emitting 'info-query' signal"); -- _gdm_session_info_query (GDM_SESSION (session), text); -+ _gdm_session_info_query (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_secret_info_query (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusError error; -@@ -852,14 +872,14 @@ gdm_session_direct_handle_secret_info_query (GdmSessionDirect *session, - set_pending_query (session, message); - - g_debug ("GdmSessionDirect: Emitting 'secret-info-query' signal"); -- _gdm_session_secret_info_query (GDM_SESSION (session), text); -+ _gdm_session_secret_info_query (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } + g_debug ("GdmSessionDirect: Emitting 'session-died' signal with signal number '%d'", +@@ -1071,7 +1117,7 @@ gdm_session_direct_handle_session_died ( static DBusHandlerResult - gdm_session_direct_handle_info (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_saved_language_name_read (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -874,18 +894,18 @@ gdm_session_direct_handle_info (GdmSessionDirect *session, +@@ -1086,7 +1132,7 @@ gdm_session_direct_handle_saved_language } reply = dbus_message_new_method_return (message); @@ -3354,181 +2541,35 @@ index 5a93103..a12e333 100644 + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); - g_debug ("GdmSessionDirect: Emitting 'info' signal"); -- _gdm_session_info (GDM_SESSION (session), text); -+ _gdm_session_info (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } + if (strcmp (language_name, +@@ -1104,7 +1150,7 @@ gdm_session_direct_handle_saved_language static DBusHandlerResult - gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_saved_layout_name_read (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -894,7 +914,7 @@ gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, - cancel_pending_query (session); +@@ -1119,7 +1165,7 @@ gdm_session_direct_handle_saved_layout_n + } reply = dbus_message_new_method_return (message); - dbus_connection_send (connection, reply, NULL); + dbus_connection_send (conversation->worker_connection, reply, NULL); dbus_message_unref (reply); - return DBUS_HANDLER_RESULT_HANDLED; -@@ -902,7 +922,7 @@ gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, + if (strcmp (layout_name, +@@ -1137,7 +1183,7 @@ gdm_session_direct_handle_saved_layout_n static DBusHandlerResult - gdm_session_direct_handle_problem (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) + gdm_session_direct_handle_saved_session_name_read (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) { DBusMessage *reply; -@@ -917,18 +937,18 @@ gdm_session_direct_handle_problem (GdmSessionDirect *session, - } - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - g_debug ("GdmSessionDirect: Emitting 'problem' signal"); -- _gdm_session_problem (GDM_SESSION (session), text); -+ _gdm_session_problem (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_session_started (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -947,7 +967,7 @@ gdm_session_direct_handle_session_started (GdmSessionDirect *session, - } - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - g_debug ("GdmSessionDirect: Emitting 'session-started' signal with pid '%d'", -@@ -956,14 +976,14 @@ gdm_session_direct_handle_session_started (GdmSessionDirect *session, - session->priv->session_pid = pid; - session->priv->is_running = TRUE; - -- _gdm_session_session_started (GDM_SESSION (session), pid); -+ _gdm_session_session_started (GDM_SESSION (session), conversation->service_name, pid); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_start_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -978,18 +998,18 @@ gdm_session_direct_handle_start_failed (GdmSessionDirect *session, - } - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - g_debug ("GdmSessionDirect: Emitting 'session-start-failed' signal"); -- _gdm_session_session_start_failed (GDM_SESSION (session), text); -+ _gdm_session_session_start_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_session_exited (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1004,7 +1024,7 @@ gdm_session_direct_handle_session_exited (GdmSessionDirect *session, - } - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - g_debug ("GdmSessionDirect: Emitting 'session-exited' signal with exit code '%d'", -@@ -1018,7 +1038,7 @@ gdm_session_direct_handle_session_exited (GdmSessionDirect *session, - - static DBusHandlerResult - gdm_session_direct_handle_session_died (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1033,7 +1053,7 @@ gdm_session_direct_handle_session_died (GdmSessionDirect *session, - } - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - g_debug ("GdmSessionDirect: Emitting 'session-died' signal with signal number '%d'", -@@ -1047,7 +1067,7 @@ gdm_session_direct_handle_session_died (GdmSessionDirect *session, - - static DBusHandlerResult - gdm_session_direct_handle_saved_language_name_read (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1062,7 +1082,7 @@ gdm_session_direct_handle_saved_language_name_read (GdmSessionDirect *session, - } - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - if (strcmp (language_name, -@@ -1080,7 +1100,7 @@ gdm_session_direct_handle_saved_language_name_read (GdmSessionDirect *session, - - static DBusHandlerResult - gdm_session_direct_handle_saved_layout_name_read (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1095,7 +1115,7 @@ gdm_session_direct_handle_saved_layout_name_read (GdmSessionDirect *session, - } - - reply = dbus_message_new_method_return (message); -- dbus_connection_send (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - if (strcmp (layout_name, -@@ -1113,7 +1133,7 @@ gdm_session_direct_handle_saved_layout_name_read (GdmSessionDirect *session, - - static DBusHandlerResult - gdm_session_direct_handle_saved_session_name_read (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1128,7 +1148,7 @@ gdm_session_direct_handle_saved_session_name_read (GdmSessionDirect *session, +@@ -1152,7 +1198,7 @@ gdm_session_direct_handle_saved_session_ } reply = dbus_message_new_method_return (message); @@ -3537,7 +2578,7 @@ index 5a93103..a12e333 100644 dbus_message_unref (reply); if (! get_session_command_for_name (session_name, NULL)) { -@@ -1156,66 +1176,69 @@ session_worker_message (DBusConnection *connection, +@@ -1180,66 +1226,69 @@ session_worker_message (DBusConnection * DBusMessage *message, void *user_data) { @@ -3637,7 +2678,7 @@ index 5a93103..a12e333 100644 } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -@@ -1449,6 +1472,27 @@ session_unregister_handler (DBusConnection *connection, +@@ -1473,6 +1522,27 @@ session_unregister_handler (DBusConnecti g_debug ("session_unregister_handler"); } @@ -3665,25 +2706,21 @@ index 5a93103..a12e333 100644 static dbus_bool_t allow_user_function (DBusConnection *connection, unsigned long uid, -@@ -1463,40 +1507,83 @@ allow_user_function (DBusConnection *connection, +@@ -1487,41 +1557,108 @@ allow_user_function (DBusConnection *con return FALSE; } --static GdmSessionConversation * --find_conversation_by_name (GdmSessionDirect *session, -- const char *service_name) +static gboolean +register_worker (GdmSessionDirect *session, + DBusConnection *connection) - { - GdmSessionConversation *conversation; ++{ ++ GdmSessionConversation *conversation; + DBusObjectPathVTable vtable = { &session_unregister_handler, + &session_message_handler, + NULL, NULL, NULL, NULL }; + GList *connection_node; + gulong pid; - -- conversation = g_hash_table_lookup (session->priv->conversations, service_name); ++ + g_debug ("GdmSessionDirect: Authenticating new connection"); + + connection_node = g_list_find (session->priv->pending_connections, connection); @@ -3704,15 +2741,13 @@ index 5a93103..a12e333 100644 + } + + conversation = find_conversation_by_pid (session, (GPid) pid); - - if (conversation == NULL) { -- g_warning ("Tried to look up non-existant conversation"); ++ ++ if (conversation == NULL) { + g_warning ("GdmSessionDirect: New worker connection is from unknown source"); + dbus_connection_unref (connection); + return FALSE; - } - -- return conversation; ++ } ++ + conversation->worker_connection = connection; + + g_debug ("GdmSessionDirect: worker connection is %p", connection); @@ -3729,72 +2764,47 @@ index 5a93103..a12e333 100644 + g_debug ("GdmSessionDirect: Conversation started"); + + return TRUE; - } - --static GdmSessionConversation * --find_conversation_by_pid (GdmSessionDirect *session, -- GPid pid) ++} ++ +static DBusHandlerResult +on_message (DBusConnection *connection, DBusMessage *message, void *user_data) - { -- GHashTableIter iter; -- gpointer key, value; ++{ + GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); - -- g_hash_table_iter_init (&iter, session->priv->conversations); -- while (g_hash_table_iter_next (&iter, &key, &value)) { -- GdmSessionConversation *conversation; ++ + g_debug ("GdmSessionDirect: got message"); - -- conversation = (GdmSessionConversation *) value; ++ + if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Hello")) { + DBusMessage *reply; - -- if (conversation->worker_pid == pid) { -- return conversation; ++ + if (register_worker (session, 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 NULL; ++ } ++ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - ++} ++ static void -@@ -1505,50 +1592,23 @@ handle_connection (DBusServer *server, + handle_connection (DBusServer *server, + DBusConnection *new_connection, void *user_data) { GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); -- GdmSessionConversation *conversation; -- gulong pid; - g_debug ("GdmSessionDirect: Handing new connection"); -- if (!dbus_connection_get_unix_process_id (new_connection, &pid)) { -- g_warning ("Unable to read pid on new worker connection"); -- return; -- } -- -- conversation = find_conversation_by_pid (session, (GPid) pid); -- -- if (conversation == NULL) { -- g_warning ("New worker connection is from unknown source"); -- return; -- } -- -- if (conversation->worker_connection == NULL) { +- if (session->priv->worker_connection == NULL) { - DBusObjectPathVTable vtable = { &session_unregister_handler, - &session_message_handler, - NULL, NULL, NULL, NULL - }; - -- conversation->worker_connection = new_connection; +- session->priv->worker_connection = new_connection; - dbus_connection_ref (new_connection); - dbus_connection_setup_with_g_main (new_connection, NULL); - @@ -3810,6 +2820,10 @@ index 5a93103..a12e333 100644 - GDM_SESSION_DBUS_PATH, - &vtable, - session); +- +- g_debug ("GdmSessionDirect: Emitting opened signal"); +- _gdm_session_opened (GDM_SESSION (session)); +- } + /* 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). @@ -3819,11 +2833,7 @@ index 5a93103..a12e333 100644 + dbus_connection_ref (new_connection)); + dbus_connection_setup_with_g_main (new_connection, NULL); + dbus_connection_set_exit_on_disconnect (new_connection, FALSE); - -- g_debug ("GdmSessionDirect: Emitting conversation-started signal"); -- _gdm_session_conversation_started (GDM_SESSION (session), -- conversation->service_name); -- } ++ + dbus_connection_set_unix_user_function (new_connection, + allow_user_function, + session, @@ -3832,208 +2842,557 @@ index 5a93103..a12e333 100644 } static gboolean -@@ -1655,7 +1715,7 @@ worker_exited (GdmSessionWorkerJob *job, - char *msg; - - msg = g_strdup_printf (_("worker exited with status %d"), code); -- _gdm_session_authentication_failed (GDM_SESSION (conversation->session), msg); -+ _gdm_session_authentication_failed (GDM_SESSION (conversation->session), conversation->service_name, msg); - g_free (msg); - } else if (conversation->session->priv->is_running) { - _gdm_session_session_exited (GDM_SESSION (conversation->session), code); -@@ -1673,7 +1733,7 @@ worker_died (GdmSessionWorkerJob *job, - char *msg; +@@ -1567,6 +1704,17 @@ setup_server (GdmSessionDirect *session) + } - msg = g_strdup_printf (_("worker exited with status %d"), signum); -- _gdm_session_authentication_failed (GDM_SESSION (conversation->session), msg); -+ _gdm_session_authentication_failed (GDM_SESSION (conversation->session), conversation->service_name, msg); - g_free (msg); - } else if (conversation->session->priv->is_running) { - _gdm_session_session_died (GDM_SESSION (conversation->session), signum); -@@ -1771,10 +1831,6 @@ gdm_session_direct_start_conversation (GdmSession *session, + static void ++free_conversation (GdmSessionConversation *conversation) ++{ ++ if (conversation->job != NULL) { ++ g_warning ("Freeing conversation with active job"); ++ } ++ ++ g_free (conversation->service_name); ++ g_free (conversation); ++} ++ ++static void + gdm_session_direct_init (GdmSessionDirect *session) + { + session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, +@@ -1590,8 +1738,11 @@ gdm_session_direct_init (GdmSessionDirec + G_CALLBACK (on_session_exited), + NULL); - g_hash_table_insert (impl->priv->conversations, - g_strdup (service_name), conversation); +- session->priv->session_pid = -1; - -- if (impl->priv->conversation != NULL) { -- impl->priv->conversation = conversation; -- } ++ session->priv->conversations = g_hash_table_new_full (g_str_hash, ++ g_str_equal, ++ (GDestroyNotify) g_free, ++ (GDestroyNotify) ++ free_conversation); + session->priv->environment = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, +@@ -1602,15 +1753,8 @@ gdm_session_direct_init (GdmSessionDirec } static void -@@ -1925,45 +1981,50 @@ gdm_session_direct_setup_for_user (GdmSession *session, +-worker_stopped (GdmSessionWorkerJob *job, +- GdmSessionDirect *session) +-{ +- g_debug ("GdmSessionDirect: Worker job stopped"); +-} +- +-static void + worker_started (GdmSessionWorkerJob *job, +- GdmSessionDirect *session) ++ GdmSessionConversation *conversation) + { + g_debug ("GdmSessionDirect: Worker job started"); } - +@@ -1618,106 +1762,161 @@ worker_started (GdmSessionWorkerJob *job static void --gdm_session_direct_authenticate (GdmSession *session) -+gdm_session_direct_authenticate (GdmSession *session, -+ const char *service_name) + worker_exited (GdmSessionWorkerJob *job, + int code, +- GdmSessionDirect *session) ++ GdmSessionConversation *conversation) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; + g_debug ("GdmSessionDirect: Worker job exited: %d", code); - g_return_if_fail (session != NULL); -- g_return_if_fail (impl->priv->conversation != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); +- if (!session->priv->is_authenticated) { ++ g_object_ref (conversation); ++ if (!conversation->session->priv->is_authenticated) { + char *msg; -- conversation = impl->priv->conversation; -- send_dbus_void_signal (conversation, "Authenticate"); -+ conversation = find_conversation_by_name (impl, service_name); -+ if (conversation != NULL) { -+ send_dbus_void_signal (conversation, "Authenticate"); -+ } + msg = g_strdup_printf (_("worker exited with status %d"), code); +- _gdm_session_authentication_failed (GDM_SESSION (session), msg); ++ _gdm_session_authentication_failed (GDM_SESSION (conversation->session), conversation->service_name, msg); + g_free (msg); +- } else if (session->priv->is_running) { +- _gdm_session_session_exited (GDM_SESSION (session), code); ++ } else if (conversation->session->priv->is_running) { ++ _gdm_session_session_exited (GDM_SESSION (conversation->session), code); + } ++ ++ g_debug ("GdmSessionDirect: Emitting conversation-stopped signal"); ++ _gdm_session_conversation_stopped (GDM_SESSION (conversation->session), ++ conversation->service_name); ++ g_object_unref (conversation); } static void --gdm_session_direct_authorize (GdmSession *session) -+gdm_session_direct_authorize (GdmSession *session, -+ const char *service_name) + worker_died (GdmSessionWorkerJob *job, + int signum, +- GdmSessionDirect *session) ++ GdmSessionConversation *conversation) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; - - g_return_if_fail (session != NULL); -- g_return_if_fail (impl->priv->conversation != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); + g_debug ("GdmSessionDirect: Worker job died: %d", signum); -- conversation = impl->priv->conversation; -- send_dbus_void_signal (conversation, "Authorize"); -+ conversation = find_conversation_by_name (impl, service_name); -+ if (conversation != NULL) { -+ send_dbus_void_signal (conversation, "Authorize"); -+ } - } +- if (!session->priv->is_authenticated) { ++ g_object_ref (conversation); ++ if (!conversation->session->priv->is_authenticated) { + char *msg; - static void - gdm_session_direct_accredit (GdmSession *session, -+ const char *service_name, - int cred_flag) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; + msg = g_strdup_printf (_("worker exited with status %d"), signum); +- _gdm_session_authentication_failed (GDM_SESSION (session), msg); ++ _gdm_session_authentication_failed (GDM_SESSION (conversation->session), conversation->service_name, msg); + g_free (msg); +- } else if (session->priv->is_running) { +- _gdm_session_session_died (GDM_SESSION (session), signum); ++ } else if (conversation->session->priv->is_running) { ++ _gdm_session_session_died (GDM_SESSION (conversation->session), signum); + } +-} +- +-static gboolean +-start_worker (GdmSessionDirect *session) +-{ +- gboolean res; - g_return_if_fail (session != NULL); -- g_return_if_fail (impl->priv->conversation != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); +- session->priv->job = gdm_session_worker_job_new (); +- gdm_session_worker_job_set_server_address (session->priv->job, session->priv->server_address); +- g_signal_connect (session->priv->job, +- "stopped", +- G_CALLBACK (worker_stopped), +- session); +- g_signal_connect (session->priv->job, ++ g_debug ("GdmSessionDirect: Emitting conversation-stopped signal"); ++ _gdm_session_conversation_stopped (GDM_SESSION (conversation->session), ++ conversation->service_name); ++ g_object_unref (conversation); ++} ++ ++static GdmSessionConversation * ++start_conversation (GdmSessionDirect *session, ++ const char *service_name) ++{ ++ GdmSessionConversation *conversation; ++ char *job_name; ++ ++ conversation = g_new0 (GdmSessionConversation, 1); ++ conversation->session = session; ++ 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, session->priv->server_address); ++ g_signal_connect (conversation->job, + "started", + G_CALLBACK (worker_started), +- session); +- g_signal_connect (session->priv->job, ++ conversation); ++ g_signal_connect (conversation->job, + "exited", + G_CALLBACK (worker_exited), +- session); +- g_signal_connect (session->priv->job, ++ conversation); ++ g_signal_connect (conversation->job, + "died", + G_CALLBACK (worker_died), +- session); ++ conversation); -- conversation = impl->priv->conversation; -+ conversation = find_conversation_by_name (impl, service_name); -+ if (conversation == NULL) { -+ return; +- res = gdm_session_worker_job_start (session->priv->job); ++ job_name = g_strdup_printf ("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); + +- return res; ++ conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job); + - switch (cred_flag) { - case GDM_SESSION_CRED_ESTABLISH: - send_dbus_void_signal (conversation, "EstablishCredentials"); -@@ -1977,13 +2038,12 @@ gdm_session_direct_accredit (GdmSession *session, ++ return conversation; } static void --send_environment_variable (const char *key, -- const char *value, -- GdmSessionDirect *session) -+send_environment_variable (const char *key, -+ const char *value, -+ GdmSessionConversation *conversation) +-stop_worker (GdmSessionDirect *session) ++stop_conversation (GdmSessionConversation *conversation) { - DBusMessage *message; - DBusMessageIter iter; -- GdmSessionConversation *conversation; +- g_signal_handlers_disconnect_by_func (session->priv->job, +- G_CALLBACK (worker_stopped), +- session); +- g_signal_handlers_disconnect_by_func (session->priv->job, ++ GdmSessionDirect *session; ++ ++ session = conversation->session; ++ ++ g_signal_handlers_disconnect_by_func (conversation->job, + G_CALLBACK (worker_started), +- session); +- g_signal_handlers_disconnect_by_func (session->priv->job, ++ conversation); ++ g_signal_handlers_disconnect_by_func (conversation->job, + G_CALLBACK (worker_exited), +- session); +- g_signal_handlers_disconnect_by_func (session->priv->job, ++ conversation); ++ g_signal_handlers_disconnect_by_func (conversation->job, + G_CALLBACK (worker_died), +- session); ++ conversation); - message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, - GDM_SESSION_DBUS_INTERFACE, -@@ -1993,7 +2053,6 @@ send_environment_variable (const char *key, - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value); +- cancel_pending_query (session); ++ if (conversation->worker_connection != NULL) { ++ dbus_connection_remove_filter (conversation->worker_connection, on_message, session); -- conversation = session->priv->conversation; - if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable"); +- if (session->priv->worker_connection != NULL) { +- dbus_connection_close (session->priv->worker_connection); +- session->priv->worker_connection = NULL; ++ dbus_connection_close (conversation->worker_connection); ++ conversation->worker_connection = NULL; } -@@ -2002,12 +2061,13 @@ send_environment_variable (const char *key, + +- gdm_session_worker_job_stop (session->priv->job); +- g_object_unref (session->priv->job); +- session->priv->job = NULL; ++ gdm_session_worker_job_stop (conversation->job); ++ ++ g_object_unref (conversation->job); ++ conversation->job = NULL; ++ ++ g_debug ("GdmSessionDirect: Emitting conversation-stopped signal"); ++ _gdm_session_conversation_stopped (GDM_SESSION (session), ++ conversation->service_name); } static void --send_environment (GdmSessionDirect *session) -+send_environment (GdmSessionDirect *session, -+ GdmSessionConversation *conversation) +-gdm_session_direct_open (GdmSession *session) ++gdm_session_direct_start_conversation (GdmSession *session, ++ const char *service_name) { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; - g_hash_table_foreach (session->priv->environment, - (GHFunc) send_environment_variable, -- session); -+ conversation); - } + g_return_if_fail (session != NULL); - static const char * -@@ -2121,7 +2181,8 @@ setup_session_environment (GdmSessionDirect *session) +- g_debug ("GdmSessionDirect: Opening session"); ++ g_debug ("GdmSessionDirect: starting conversation"); + +- start_worker (impl); ++ conversation = start_conversation (impl, service_name); ++ ++ g_hash_table_insert (impl->priv->conversations, ++ g_strdup (service_name), conversation); ++} ++ ++static void ++gdm_session_direct_stop_conversation (GdmSession *session, ++ const char *service_name) ++{ ++ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; ++ ++ g_return_if_fail (session != NULL); ++ ++ g_debug ("GdmSessionDirect: stopping conversation"); ++ ++ conversation = find_conversation_by_name (impl, service_name); ++ ++ if (conversation != NULL) { ++ stop_conversation (conversation); ++ g_hash_table_remove (impl->priv->conversations, service_name); ++ } } static void --gdm_session_direct_start_session (GdmSession *session) -+gdm_session_direct_start_session (GdmSession *session, -+ const char *service_name) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; -@@ -2135,10 +2196,11 @@ gdm_session_direct_start_session (GdmSession *session) - program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command); - g_free (command); +@@ -1730,6 +1929,7 @@ send_setup (GdmSessionDirect *session, + const char *display_device; + const char *display_hostname; + const char *display_x11_authority_file; ++ GdmSessionConversation *conversation; -+ conversation = find_conversation_by_name (impl, service_name); -+ - setup_session_environment (impl); -- send_environment (impl); -+ send_environment (impl, conversation); + g_assert (service_name != NULL); -- conversation = impl->priv->conversation; - send_dbus_string_signal (conversation, "StartProgram", program); - g_free (program); - } -@@ -2180,6 +2242,11 @@ gdm_session_direct_close (GdmSession *session) +@@ -1767,7 +1967,8 @@ send_setup (GdmSessionDirect *session, + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file); + +- if (! send_dbus_message (session->priv->worker_connection, message)) { ++ conversation = find_conversation_by_name (session, service_name); ++ if (conversation != NULL && ! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", "Setup"); + } - stop_all_conversations (impl); +@@ -1785,6 +1986,7 @@ send_setup_for_user (GdmSessionDirect *s + const char *display_hostname; + const char *display_x11_authority_file; + const char *selected_user; ++ GdmSessionConversation *conversation; -+ g_list_foreach (impl->priv->pending_connections, -+ (GFunc) dbus_connection_unref, NULL); -+ g_list_free (impl->priv->pending_connections); -+ impl->priv->pending_connections = NULL; -+ - g_free (impl->priv->selected_user); - impl->priv->selected_user = NULL; + g_assert (service_name != NULL); -@@ -2212,13 +2279,14 @@ gdm_session_direct_close (GdmSession *session) +@@ -1828,7 +2030,8 @@ send_setup_for_user (GdmSessionDirect *s + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &selected_user); - static void - gdm_session_direct_answer_query (GdmSession *session, -+ const char *service_name, - const char *text) - { +- if (! send_dbus_message (session->priv->worker_connection, message)) { ++ conversation = find_conversation_by_name (session, service_name); ++ if (conversation != NULL && ! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForUser"); + } + +@@ -1842,7 +2045,6 @@ gdm_session_direct_setup (GdmSession *se GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); g_return_if_fail (session != NULL); +- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); -- answer_pending_query (impl, text); -+ answer_pending_query (impl, service_name, text); + send_setup (impl, service_name); + gdm_session_direct_defaults_changed (impl); +@@ -1856,7 +2058,6 @@ gdm_session_direct_setup_for_user (GdmSe + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); + + g_return_if_fail (session != NULL); +- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); + g_return_if_fail (username != NULL); + + gdm_session_direct_select_user (session, username); +@@ -1866,42 +2067,56 @@ gdm_session_direct_setup_for_user (GdmSe + } + + static void +-gdm_session_direct_authenticate (GdmSession *session) ++gdm_session_direct_authenticate (GdmSession *session, ++ const char *service_name) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + + g_return_if_fail (session != NULL); +- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); + +- send_dbus_void_signal (impl, "Authenticate"); ++ conversation = find_conversation_by_name (impl, service_name); ++ if (conversation != NULL) { ++ send_dbus_void_signal (conversation, "Authenticate"); ++ } + } + + static void +-gdm_session_direct_authorize (GdmSession *session) ++gdm_session_direct_authorize (GdmSession *session, ++ const char *service_name) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + + g_return_if_fail (session != NULL); +- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); + +- send_dbus_void_signal (impl, "Authorize"); ++ conversation = find_conversation_by_name (impl, service_name); ++ if (conversation != NULL) { ++ send_dbus_void_signal (conversation, "Authorize"); ++ } + } + + static void + gdm_session_direct_accredit (GdmSession *session, ++ const char *service_name, + int cred_flag) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + + g_return_if_fail (session != NULL); +- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection)); ++ ++ conversation = find_conversation_by_name (impl, service_name); ++ if (conversation == NULL) { ++ return; ++ } + + switch (cred_flag) { + case GDM_SESSION_CRED_ESTABLISH: +- send_dbus_void_signal (impl, "EstablishCredentials"); ++ send_dbus_void_signal (conversation, "EstablishCredentials"); + break; + case GDM_SESSION_CRED_REFRESH: +- send_dbus_void_signal (impl, "RefreshCredentials"); ++ send_dbus_void_signal (conversation, "RefreshCredentials"); + break; + default: + g_assert_not_reached (); +@@ -1909,9 +2124,9 @@ gdm_session_direct_accredit (GdmSession + } + + static void +-send_environment_variable (const char *key, +- const char *value, +- GdmSessionDirect *session) ++send_environment_variable (const char *key, ++ const char *value, ++ GdmSessionConversation *conversation) + { + DBusMessage *message; + DBusMessageIter iter; +@@ -1924,7 +2139,7 @@ send_environment_variable (const char + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value); + +- if (! send_dbus_message (session->priv->worker_connection, message)) { ++ if (! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable"); + } + +@@ -1932,12 +2147,13 @@ send_environment_variable (const char + } + + static void +-send_environment (GdmSessionDirect *session) ++send_environment (GdmSessionDirect *session, ++ GdmSessionConversation *conversation) + { + + g_hash_table_foreach (session->priv->environment, + (GHFunc) send_environment_variable, +- session); ++ conversation); + } + + static const char * +@@ -2052,9 +2268,11 @@ setup_session_environment (GdmSessionDir + } + + static void +-gdm_session_direct_start_session (GdmSession *session) ++gdm_session_direct_start_session (GdmSession *session, ++ const char *service_name) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + char *command; + char *program; + +@@ -2065,14 +2283,38 @@ gdm_session_direct_start_session (GdmSes + program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command); + g_free (command); + ++ conversation = find_conversation_by_name (impl, service_name); ++ + setup_session_environment (impl); +- send_environment (impl); ++ send_environment (impl, conversation); + +- send_dbus_string_signal (impl, "StartProgram", program); ++ send_dbus_string_signal (conversation, "StartProgram", program); + g_free (program); + } + + static void ++stop_all_conversations (GdmSessionDirect *session) ++{ ++ GHashTableIter iter; ++ gpointer key, value; ++ ++ if (session->priv->conversations == NULL) { ++ return; ++ } ++ ++ g_hash_table_iter_init (&iter, session->priv->conversations); ++ while (g_hash_table_iter_next (&iter, &key, &value)) { ++ GdmSessionConversation *conversation; ++ ++ conversation = (GdmSessionConversation *) value; ++ ++ stop_conversation (conversation); ++ } ++ ++ g_hash_table_remove_all (session->priv->conversations); ++} ++ ++static void + gdm_session_direct_close (GdmSession *session) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +@@ -2081,18 +2323,21 @@ gdm_session_direct_close (GdmSession *se + + g_debug ("GdmSessionDirect: Closing session"); + +- if (impl->priv->job != NULL) { +- if (impl->priv->is_running) { +- gdm_session_record_logout (impl->priv->session_pid, +- impl->priv->selected_user, +- impl->priv->display_hostname, +- impl->priv->display_name, +- impl->priv->display_device); +- } +- +- stop_worker (impl); ++ if (impl->priv->is_running) { ++ gdm_session_record_logout (impl->priv->session_pid, ++ impl->priv->selected_user, ++ impl->priv->display_hostname, ++ impl->priv->display_name, ++ impl->priv->display_device); + } + ++ stop_all_conversations (impl); ++ ++ g_list_foreach (impl->priv->pending_connections, ++ (GFunc) dbus_connection_unref, NULL); ++ g_list_free (impl->priv->pending_connections); ++ impl->priv->pending_connections = NULL; ++ + g_free (impl->priv->selected_user); + impl->priv->selected_user = NULL; + +@@ -2119,30 +2364,28 @@ gdm_session_direct_close (GdmSession *se + + g_hash_table_remove_all (impl->priv->environment); + +- impl->priv->session_pid = -1; + impl->priv->is_authenticated = FALSE; + impl->priv->is_running = FALSE; + } + + static void + gdm_session_direct_answer_query (GdmSession *session, ++ const char *service_name, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); + + g_return_if_fail (session != NULL); + +- answer_pending_query (impl, text); ++ answer_pending_query (impl, service_name, text); } static void -@@ -2244,7 +2312,8 @@ gdm_session_direct_select_session (GdmSession *session, + gdm_session_direct_cancel (GdmSession *session) + { +- GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +- + g_return_if_fail (session != NULL); + +- cancel_pending_query (impl); ++ stop_all_conversations (GDM_SESSION_DIRECT (session)); + } + + char * +@@ -2158,6 +2401,8 @@ gdm_session_direct_select_session (GdmSe const char *text) { GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- GdmSessionConversation *conversation; + GHashTableIter iter; + gpointer key, value; g_free (impl->priv->selected_session); -@@ -2254,9 +2323,15 @@ gdm_session_direct_select_session (GdmSession *session, +@@ -2167,8 +2412,15 @@ gdm_session_direct_select_session (GdmSe impl->priv->selected_session = g_strdup (text); } -- conversation = impl->priv->conversation; -- send_dbus_string_signal (conversation, "SetSessionName", +- send_dbus_string_signal (impl, "SetSessionName", - get_session_name (impl)); + g_hash_table_iter_init (&iter, impl->priv->conversations); + while (g_hash_table_iter_next (&iter, &key, &value)) { @@ -4047,22 +3406,20 @@ index 5a93103..a12e333 100644 } static void -@@ -2264,7 +2339,8 @@ gdm_session_direct_select_language (GdmSession *session, +@@ -2176,6 +2428,8 @@ gdm_session_direct_select_language (GdmS const char *text) { GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- GdmSessionConversation *conversation; + GHashTableIter iter; + gpointer key, value; g_free (impl->priv->selected_language); -@@ -2274,9 +2350,15 @@ gdm_session_direct_select_language (GdmSession *session, +@@ -2185,8 +2439,15 @@ gdm_session_direct_select_language (GdmS impl->priv->selected_language = g_strdup (text); } -- conversation = impl->priv->conversation; -- send_dbus_string_signal (conversation, "SetLanguageName", +- send_dbus_string_signal (impl, "SetLanguageName", - get_language_name (impl)); + g_hash_table_iter_init (&iter, impl->priv->conversations); + while (g_hash_table_iter_next (&iter, &key, &value)) { @@ -4076,22 +3433,20 @@ index 5a93103..a12e333 100644 } static void -@@ -2284,7 +2366,8 @@ gdm_session_direct_select_layout (GdmSession *session, +@@ -2194,6 +2455,8 @@ gdm_session_direct_select_layout (GdmSes const char *text) { GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- GdmSessionConversation *conversation; + GHashTableIter iter; + gpointer key, value; g_free (impl->priv->selected_layout); -@@ -2294,9 +2377,15 @@ gdm_session_direct_select_layout (GdmSession *session, +@@ -2203,8 +2466,15 @@ gdm_session_direct_select_layout (GdmSes impl->priv->selected_layout = g_strdup (text); } -- conversation = impl->priv->conversation; -- send_dbus_string_signal (conversation, "SetLayoutName", +- send_dbus_string_signal (impl, "SetLayoutName", - get_layout_name (impl)); + g_hash_table_iter_init (&iter, impl->priv->conversations); + while (g_hash_table_iter_next (&iter, &key, &value)) { @@ -4105,50 +3460,199 @@ index 5a93103..a12e333 100644 } static void -diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h -index 074aa6f..de6e54a 100644 ---- a/daemon/gdm-session-private.h -+++ b/daemon/gdm-session-private.h -@@ -29,24 +29,34 @@ G_BEGIN_DECLS - /* state changes */ - void _gdm_session_conversation_started (GdmSession *session, - const char *service_name); --void _gdm_session_setup_complete (GdmSession *session); -+void _gdm_session_setup_complete (GdmSession *session, -+ const char *service_name); - void _gdm_session_setup_failed (GdmSession *session, -+ const char *service_name, - const char *message); - void _gdm_session_reset_complete (GdmSession *session); - void _gdm_session_reset_failed (GdmSession *session, - const char *message); --void _gdm_session_authenticated (GdmSession *session); -+void _gdm_session_authenticated (GdmSession *session, -+ const char *service_name); - void _gdm_session_authentication_failed (GdmSession *session, -+ const char *service_name, - const char *text); --void _gdm_session_authorized (GdmSession *session); -+void _gdm_session_authorized (GdmSession *session, -+ const char *service_name); - void _gdm_session_authorization_failed (GdmSession *session, -+ const char *service_name, - const char *text); --void _gdm_session_accredited (GdmSession *session); -+void _gdm_session_accredited (GdmSession *session, -+ const char *service_name); - void _gdm_session_accreditation_failed (GdmSession *session, -+ const char *service_name, - const char *text); - void _gdm_session_session_started (GdmSession *session, -+ const char *service_name, - int pid); +@@ -2463,7 +2733,8 @@ gdm_session_direct_constructor (GType + static void + gdm_session_iface_init (GdmSessionIface *iface) + { +- iface->open = gdm_session_direct_open; ++ iface->start_conversation = gdm_session_direct_start_conversation; ++ iface->stop_conversation = gdm_session_direct_stop_conversation; + iface->setup = gdm_session_direct_setup; + iface->setup_for_user = gdm_session_direct_setup_for_user; + iface->authenticate = gdm_session_direct_authenticate; +diff -up gdm-2.25.2/daemon/gdm-session.h.multistack-but-boring gdm-2.25.2/daemon/gdm-session.h +--- gdm-2.25.2/daemon/gdm-session.h.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-session.h 2009-03-03 17:45:05.705018251 -0500 +@@ -45,18 +45,25 @@ struct _GdmSessionIface + GTypeInterface base_iface; + + /* Methods */ +- void (* open) (GdmSession *session); ++ void (* start_conversation) (GdmSession *session, ++ const char *service_name); ++ void (* stop_conversation) (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 (* reset) (GdmSession *session); +- void (* authenticate) (GdmSession *session); +- void (* authorize) (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 (* answer_query) (GdmSession *session, ++ const char *service_name, + const char *text); + void (* select_language) (GdmSession *session, + const char *text); +@@ -66,44 +73,62 @@ struct _GdmSessionIface + const char *text); + void (* select_user) (GdmSession *session, + const char *text); +- void (* start_session) (GdmSession *session); ++ void (* start_session) (GdmSession *session, ++ const char *service_name); + void (* close) (GdmSession *session); + void (* cancel) (GdmSession *session); + + /* Signals */ +- void (* setup_complete) (GdmSession *session); ++ void (* setup_complete) (GdmSession *session, ++ const char *service_name); + void (* setup_failed) (GdmSession *session, ++ const char *service_name, + const char *message); + void (* reset_complete) (GdmSession *session); + void (* reset_failed) (GdmSession *session, + const char *message); +- void (* authenticated) (GdmSession *session); ++ void (* authenticated) (GdmSession *session, ++ const char *service_name); + void (* authentication_failed) (GdmSession *session, ++ const char *service_name, + const char *message); +- void (* authorized) (GdmSession *session); ++ void (* authorized) (GdmSession *session, ++ const char *service_name); + void (* authorization_failed) (GdmSession *session, ++ const char *service_name, + const char *message); +- void (* accredited) (GdmSession *session); ++ void (* accredited) (GdmSession *session, ++ const char *service_name); + void (* accreditation_failed) (GdmSession *session, ++ const char *service_name, + const char *message); + + void (* info_query) (GdmSession *session, ++ const char *service_name, + const char *query_text); + void (* secret_info_query) (GdmSession *session, ++ const char *service_name, + const char *query_text); + void (* info) (GdmSession *session, ++ const char *service_name, + const char *info); + void (* problem) (GdmSession *session, ++ const char *service_name, + const char *problem); + void (* session_started) (GdmSession *session, ++ const char *service_name, + int pid); + void (* session_start_failed) (GdmSession *session, ++ const char *service_name, + const char *message); + void (* session_exited) (GdmSession *session, + int exit_code); + void (* session_died) (GdmSession *session, + int signal_number); +- void (* opened) (GdmSession *session); ++ void (* conversation_started) (GdmSession *session, ++ const char *service_name); ++ void (* conversation_stopped) (GdmSession *session, ++ const char *service_name); + void (* closed) (GdmSession *session); + void (* selected_user_changed) (GdmSession *session, + const char *text); +@@ -118,21 +143,29 @@ struct _GdmSessionIface + + GType gdm_session_get_type (void) G_GNUC_CONST; + +-void gdm_session_open (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_reset (GdmSession *session); +-void gdm_session_authenticate (GdmSession *session); +-void gdm_session_authorize (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_start_session (GdmSession *session); ++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_session (GdmSession *session, + const char *session_name); +diff -up gdm-2.25.2/daemon/gdm-session-private.h.multistack-but-boring gdm-2.25.2/daemon/gdm-session-private.h +--- gdm-2.25.2/daemon/gdm-session-private.h.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-session-private.h 2009-03-03 17:45:05.703022544 -0500 +@@ -27,25 +27,38 @@ + G_BEGIN_DECLS + + /* state changes */ +-void _gdm_session_opened (GdmSession *session); +-void _gdm_session_setup_complete (GdmSession *session); ++void _gdm_session_conversation_started (GdmSession *session, ++ const char *service_name); ++void _gdm_session_conversation_stopped (GdmSession *session, ++ const char *service_name); ++void _gdm_session_setup_complete (GdmSession *session, ++ const char *service_name); + void _gdm_session_setup_failed (GdmSession *session, ++ const char *service_name, + const char *message); + void _gdm_session_reset_complete (GdmSession *session); + void _gdm_session_reset_failed (GdmSession *session, + const char *message); +-void _gdm_session_authenticated (GdmSession *session); ++void _gdm_session_authenticated (GdmSession *session, ++ const char *service_name); + void _gdm_session_authentication_failed (GdmSession *session, ++ const char *service_name, + const char *text); +-void _gdm_session_authorized (GdmSession *session); ++void _gdm_session_authorized (GdmSession *session, ++ const char *service_name); + void _gdm_session_authorization_failed (GdmSession *session, ++ const char *service_name, + const char *text); +-void _gdm_session_accredited (GdmSession *session); ++void _gdm_session_accredited (GdmSession *session, ++ const char *service_name); + void _gdm_session_accreditation_failed (GdmSession *session, ++ const char *service_name, + const char *text); + void _gdm_session_session_started (GdmSession *session, ++ const char *service_name, + int pid); void _gdm_session_session_start_failed (GdmSession *session, + const char *service_name, const char *message); void _gdm_session_session_exited (GdmSession *session, int exit_code); -@@ -67,12 +77,16 @@ void _gdm_session_selected_user_changed (GdmSession *sessio +@@ -66,12 +79,16 @@ void _gdm_session_selected_u /* call and response stuff */ void _gdm_session_info_query (GdmSession *session, @@ -4165,11 +3669,24 @@ index 074aa6f..de6e54a 100644 const char *text); G_END_DECLS -diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c -index 35b4738..36e86b5 100644 ---- a/daemon/gdm-session-relay.c -+++ b/daemon/gdm-session-relay.c -@@ -212,31 +212,34 @@ gdm_session_relay_setup_for_user (GdmSession *session, +diff -up gdm-2.25.2/daemon/gdm-session-relay.c.multistack-but-boring gdm-2.25.2/daemon/gdm-session-relay.c +--- gdm-2.25.2/daemon/gdm-session-relay.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-session-relay.c 2009-03-03 17:45:05.612016364 -0500 +@@ -180,10 +180,11 @@ send_dbus_void_signal (GdmSessionRelay * + } + + static void +-gdm_session_relay_open (GdmSession *session) ++gdm_session_relay_start_conversation (GdmSession *session, ++ const char *service_name) + { + GdmSessionRelay *impl = GDM_SESSION_RELAY (session); +- send_dbus_void_signal (impl, "Open"); ++ send_dbus_string_signal (impl, "StartConversation", service_name); + } + + static void +@@ -211,31 +212,34 @@ gdm_session_relay_setup_for_user (GdmSes } static void @@ -4210,7 +3727,7 @@ index 35b4738..36e86b5 100644 break; default: g_assert_not_reached (); -@@ -245,10 +248,11 @@ gdm_session_relay_accredit (GdmSession *session, +@@ -244,10 +248,11 @@ gdm_session_relay_accredit (GdmSession * static void gdm_session_relay_answer_query (GdmSession *session, @@ -4223,7 +3740,22 @@ index 35b4738..36e86b5 100644 } static void -@@ -334,10 +338,12 @@ handle_info_query (GdmSessionRelay *session_relay, +@@ -291,11 +296,12 @@ gdm_session_relay_cancel (GdmSession *se + } + + static void +-gdm_session_relay_start_session (GdmSession *session) ++gdm_session_relay_start_session (GdmSession *session, ++ const char *service_name) + { + GdmSessionRelay *impl = GDM_SESSION_RELAY (session); + +- send_dbus_void_signal (impl, "StartSession"); ++ send_dbus_string_signal (impl, "StartSession", service_name); + } + + /* Note: Use abstract sockets like dbus does by default on Linux. Abstract +@@ -333,10 +339,12 @@ handle_info_query (GdmSessionRelay *sess { DBusMessage *reply; DBusError error; @@ -4237,7 +3769,7 @@ index 35b4738..36e86b5 100644 DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID)) { g_warning ("ERROR: %s", error.message); -@@ -349,7 +355,7 @@ handle_info_query (GdmSessionRelay *session_relay, +@@ -348,7 +356,7 @@ handle_info_query (GdmSessionRelay *sess dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4246,7 +3778,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -361,12 +367,14 @@ handle_secret_info_query (GdmSessionRelay *session_relay, +@@ -360,12 +368,14 @@ handle_secret_info_query (GdmSessionRela { DBusMessage *reply; DBusError error; @@ -4262,7 +3794,7 @@ index 35b4738..36e86b5 100644 DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID)) { g_warning ("ERROR: %s", error.message); -@@ -378,7 +386,7 @@ handle_secret_info_query (GdmSessionRelay *session_relay, +@@ -377,7 +387,7 @@ handle_secret_info_query (GdmSessionRela dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4271,7 +3803,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -390,12 +398,14 @@ handle_info (GdmSessionRelay *session_relay, +@@ -389,12 +399,14 @@ handle_info (GdmSessionRelay *session_re { DBusMessage *reply; DBusError error; @@ -4287,7 +3819,7 @@ index 35b4738..36e86b5 100644 DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID)) { g_warning ("ERROR: %s", error.message); -@@ -407,7 +417,7 @@ handle_info (GdmSessionRelay *session_relay, +@@ -406,7 +418,7 @@ handle_info (GdmSessionRelay *session_re dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4296,7 +3828,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -419,12 +429,14 @@ handle_problem (GdmSessionRelay *session_relay, +@@ -418,12 +430,14 @@ handle_problem (GdmSessionRelay *session { DBusMessage *reply; DBusError error; @@ -4312,7 +3844,7 @@ index 35b4738..36e86b5 100644 DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID)) { g_warning ("ERROR: %s", error.message); -@@ -436,7 +448,7 @@ handle_problem (GdmSessionRelay *session_relay, +@@ -435,7 +449,7 @@ handle_problem (GdmSessionRelay *session dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4321,7 +3853,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -448,8 +460,15 @@ handle_setup_complete (GdmSessionRelay *session_relay, +@@ -447,8 +461,15 @@ handle_setup_complete (GdmSessionRelay * { DBusMessage *reply; DBusError error; @@ -4337,7 +3869,7 @@ index 35b4738..36e86b5 100644 g_debug ("GdmSessionRelay: SetupComplete"); -@@ -457,7 +476,7 @@ handle_setup_complete (GdmSessionRelay *session_relay, +@@ -456,7 +477,7 @@ handle_setup_complete (GdmSessionRelay * dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4346,7 +3878,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -469,8 +488,15 @@ handle_setup_failed (GdmSessionRelay *session_relay, +@@ -468,8 +489,15 @@ handle_setup_failed (GdmSessionRelay *se { DBusMessage *reply; DBusError error; @@ -4362,7 +3894,7 @@ index 35b4738..36e86b5 100644 g_debug ("GdmSessionRelay: SetupFailed"); -@@ -478,7 +504,7 @@ handle_setup_failed (GdmSessionRelay *session_relay, +@@ -477,7 +505,7 @@ handle_setup_failed (GdmSessionRelay *se dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4371,7 +3903,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -491,8 +517,15 @@ handle_authenticated (GdmSessionRelay *session_relay, +@@ -490,8 +518,15 @@ handle_authenticated (GdmSessionRelay *s { DBusMessage *reply; DBusError error; @@ -4387,7 +3919,7 @@ index 35b4738..36e86b5 100644 g_debug ("GdmSessionRelay: Authenticated"); -@@ -500,7 +533,7 @@ handle_authenticated (GdmSessionRelay *session_relay, +@@ -499,7 +534,7 @@ handle_authenticated (GdmSessionRelay *s dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4396,7 +3928,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -512,8 +545,15 @@ handle_authentication_failed (GdmSessionRelay *session_relay, +@@ -511,8 +546,15 @@ handle_authentication_failed (GdmSession { DBusMessage *reply; DBusError error; @@ -4412,7 +3944,7 @@ index 35b4738..36e86b5 100644 g_debug ("GdmSessionRelay: AuthenticationFailed"); -@@ -521,7 +561,7 @@ handle_authentication_failed (GdmSessionRelay *session_relay, +@@ -520,7 +562,7 @@ handle_authentication_failed (GdmSession dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4421,7 +3953,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -533,8 +573,15 @@ handle_authorized (GdmSessionRelay *session_relay, +@@ -532,8 +574,15 @@ handle_authorized (GdmSessionRelay *sess { DBusMessage *reply; DBusError error; @@ -4437,7 +3969,7 @@ index 35b4738..36e86b5 100644 g_debug ("GdmSessionRelay: Authorized"); -@@ -542,7 +589,7 @@ handle_authorized (GdmSessionRelay *session_relay, +@@ -541,7 +590,7 @@ handle_authorized (GdmSessionRelay *sess dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4446,7 +3978,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -554,8 +601,15 @@ handle_authorization_failed (GdmSessionRelay *session_relay, +@@ -553,8 +602,15 @@ handle_authorization_failed (GdmSessionR { DBusMessage *reply; DBusError error; @@ -4462,7 +3994,7 @@ index 35b4738..36e86b5 100644 g_debug ("GdmSessionRelay: AuthorizationFailed"); -@@ -563,7 +617,7 @@ handle_authorization_failed (GdmSessionRelay *session_relay, +@@ -562,7 +618,7 @@ handle_authorization_failed (GdmSessionR dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4471,7 +4003,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -575,8 +629,15 @@ handle_accredited (GdmSessionRelay *session_relay, +@@ -574,8 +630,15 @@ handle_accredited (GdmSessionRelay *sess { DBusMessage *reply; DBusError error; @@ -4487,7 +4019,7 @@ index 35b4738..36e86b5 100644 g_debug ("GdmSessionRelay: Accredited"); -@@ -584,7 +645,7 @@ handle_accredited (GdmSessionRelay *session_relay, +@@ -583,7 +646,7 @@ handle_accredited (GdmSessionRelay *sess dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4496,7 +4028,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -596,8 +657,15 @@ handle_accreditation_failed (GdmSessionRelay *session_relay, +@@ -595,8 +658,15 @@ handle_accreditation_failed (GdmSessionR { DBusMessage *reply; DBusError error; @@ -4512,7 +4044,7 @@ index 35b4738..36e86b5 100644 g_debug ("GdmSessionRelay: AccreditationFailed"); -@@ -605,7 +673,7 @@ handle_accreditation_failed (GdmSessionRelay *session_relay, +@@ -604,7 +674,7 @@ handle_accreditation_failed (GdmSessionR dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -4521,7 +4053,7 @@ index 35b4738..36e86b5 100644 return DBUS_HANDLER_RESULT_HANDLED; } -@@ -617,6 +685,7 @@ handle_session_started (GdmSessionRelay *session_relay, +@@ -616,6 +686,7 @@ handle_session_started (GdmSessionRelay { DBusMessage *reply; DBusError error; @@ -4529,7 +4061,7 @@ index 35b4738..36e86b5 100644 int pid; dbus_error_init (&error); -@@ -624,6 +693,7 @@ handle_session_started (GdmSessionRelay *session_relay, +@@ -623,6 +694,7 @@ handle_session_started (GdmSessionRelay pid = 0; if (! dbus_message_get_args (message, &error, @@ -4537,7 +4069,7 @@ index 35b4738..36e86b5 100644 DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID)) { g_warning ("ERROR: %s", error.message); -@@ -636,6 +706,7 @@ handle_session_started (GdmSessionRelay *session_relay, +@@ -635,6 +707,7 @@ handle_session_started (GdmSessionRelay dbus_message_unref (reply); _gdm_session_session_started (GDM_SESSION (session_relay), @@ -4545,610 +4077,350 @@ index 35b4738..36e86b5 100644 pid); return DBUS_HANDLER_RESULT_HANDLED; -diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c -index 565420a..27fce28 100644 ---- a/daemon/gdm-session-worker.c -+++ b/daemon/gdm-session-worker.c -@@ -2568,6 +2568,28 @@ worker_dbus_filter_function (DBusConnection *connection, - return DBUS_HANDLER_RESULT_HANDLED; +@@ -664,22 +737,28 @@ handle_session_stopped (GdmSessionRelay } -+static void -+send_hello (GdmSessionWorker *worker) -+{ -+ DBusMessage *message, *reply; -+ DBusError error; -+ -+ message = dbus_message_new_method_call (NULL, -+ GDM_SESSION_DBUS_PATH, -+ GDM_SESSION_DBUS_INTERFACE, -+ "Hello"); -+ -+ dbus_error_init (&error); -+ reply = dbus_connection_send_with_reply_and_block (worker->priv->connection, -+ message, -1, &error); -+ dbus_message_unref (message); -+ dbus_error_free (&error); -+ -+ if (reply != NULL) { -+ dbus_message_unref (reply); + static DBusHandlerResult +-handle_opened (GdmSessionRelay *session_relay, ++handle_conversation_started (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); + } -+} -+ - static GObject * - gdm_session_worker_constructor (GType type, - guint n_construct_properties, -@@ -2594,6 +2616,11 @@ gdm_session_worker_constructor (GType type, - exit (1); - } -+ /* Send an initial Hello message so that the session can associate -+ * the conversation we manage with our pid. -+ */ -+ send_hello (worker); -+ - dbus_connection_setup_with_g_main (worker->priv->connection, NULL); - dbus_connection_set_exit_on_disconnect (worker->priv->connection, TRUE); +- g_debug ("GdmSessionRelay: Opened"); ++ g_debug ("GdmSessionRelay: Conversation Started"); -diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c -index 0073294..5f6ff5d 100644 ---- a/daemon/gdm-session.c -+++ b/daemon/gdm-session.c -@@ -24,6 +24,7 @@ - #include - #include + reply = dbus_message_new_method_return (message); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); -+#include "gdm-marshal.h" - #include "gdm-session.h" - #include "gdm-session-private.h" +- _gdm_session_opened (GDM_SESSION (session_relay)); ++ _gdm_session_conversation_started (GDM_SESSION (session_relay), service_name); -@@ -114,37 +115,41 @@ gdm_session_setup_for_user (GdmSession *session, + return DBUS_HANDLER_RESULT_HANDLED; } +@@ -719,8 +798,8 @@ session_handle_child_message (DBusConnec + return handle_session_started (session_relay, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStopped")) { + return handle_session_stopped (session_relay, connection, message); +- } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Opened")) { +- return handle_opened (session_relay, connection, message); ++ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "ConversationStarted")) { ++ return handle_conversation_started (session_relay, connection, message); + } - void --gdm_session_authenticate (GdmSession *session) -+gdm_session_authenticate (GdmSession *session, -+ const char *service_name) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +@@ -749,7 +828,8 @@ do_introspect (DBusConnection *connectio + /* interface */ + xml = g_string_append (xml, + " \n" +- " \n" ++ " \n" ++ " \n" + " \n" + " \n" + " \n" +@@ -810,7 +890,8 @@ do_introspect (DBusConnection *connectio + " \n" + " \n" + +- " \n" ++ " \n" ++ " \n" + " \n" + " \n" + " \n" +@@ -1106,7 +1187,7 @@ static void + gdm_session_iface_init (GdmSessionIface *iface) { - g_return_if_fail (GDM_IS_SESSION (session)); -- GDM_SESSION_GET_IFACE (session)->authenticate (session); -+ GDM_SESSION_GET_IFACE (session)->authenticate (session, service_name); +- iface->open = gdm_session_relay_open; ++ iface->start_conversation = gdm_session_relay_start_conversation; + iface->setup = gdm_session_relay_setup; + iface->setup_for_user = gdm_session_relay_setup_for_user; + iface->authenticate = gdm_session_relay_authenticate; +diff -up gdm-2.25.2/daemon/gdm-session-worker.c.multistack-but-boring gdm-2.25.2/daemon/gdm-session-worker.c +--- gdm-2.25.2/daemon/gdm-session-worker.c.multistack-but-boring 2008-11-18 17:19:05.000000000 -0500 ++++ gdm-2.25.2/daemon/gdm-session-worker.c 2009-03-03 17:45:05.594019175 -0500 +@@ -2568,6 +2568,28 @@ worker_dbus_filter_function (DBusConnect + return DBUS_HANDLER_RESULT_HANDLED; } - void --gdm_session_authorize (GdmSession *session) -+gdm_session_authorize (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); ++static void ++send_hello (GdmSessionWorker *worker) ++{ ++ DBusMessage *message, *reply; ++ DBusError error; ++ ++ message = dbus_message_new_method_call (NULL, ++ GDM_SESSION_DBUS_PATH, ++ GDM_SESSION_DBUS_INTERFACE, ++ "Hello"); ++ ++ dbus_error_init (&error); ++ reply = dbus_connection_send_with_reply_and_block (worker->priv->connection, ++ message, -1, &error); ++ dbus_message_unref (message); ++ dbus_error_free (&error); ++ ++ if (reply != NULL) { ++ dbus_message_unref (reply); ++ } ++} ++ + static GObject * + gdm_session_worker_constructor (GType type, + guint n_construct_properties, +@@ -2594,6 +2616,11 @@ gdm_session_worker_constructor (GType + exit (1); + } -- GDM_SESSION_GET_IFACE (session)->authorize (session); -+ GDM_SESSION_GET_IFACE (session)->authorize (session, service_name); ++ /* Send an initial Hello message so that the session can associate ++ * the conversation we manage with our pid. ++ */ ++ send_hello (worker); ++ + dbus_connection_setup_with_g_main (worker->priv->connection, NULL); + dbus_connection_set_exit_on_disconnect (worker->priv->connection, TRUE); + +diff -up gdm-2.25.2/daemon/gdm-session-worker-job.c.multistack-but-boring gdm-2.25.2/daemon/gdm-session-worker-job.c +--- gdm-2.25.2/daemon/gdm-session-worker-job.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-session-worker-job.c 2009-03-03 17:45:05.650016435 -0500 +@@ -68,7 +68,6 @@ enum { + + enum { + STARTED, +- STOPPED, + EXITED, + DIED, + LAST_SIGNAL +@@ -124,6 +123,37 @@ listify_hash (const char *key, } - void - gdm_session_accredit (GdmSession *session, -+ const char *service_name, - int flag) + static GPtrArray * ++get_job_arguments (GdmSessionWorkerJob *job, ++ const char *name) ++{ ++ GPtrArray *args; ++ GError *error; ++ char **argv; ++ int i; ++ ++ args = NULL; ++ argv = NULL; ++ error = NULL; ++ if (! g_shell_parse_argv (job->priv->command, NULL, &argv, &error)) { ++ g_warning ("Could not parse command: %s", error->message); ++ g_error_free (error); ++ goto out; ++ } ++ ++ args = g_ptr_array_new (); ++ g_ptr_array_add (args, g_strdup (argv[0])); ++ g_ptr_array_add (args, g_strdup (name)); ++ for (i = 1; argv[i] != NULL; i++) { ++ g_ptr_array_add (args, g_strdup (argv[i])); ++ } ++ g_strfreev (argv); ++ ++ g_ptr_array_add (args, NULL); ++out: ++ return args; ++} ++ ++static GPtrArray * + get_job_environment (GdmSessionWorkerJob *job) { - g_return_if_fail (GDM_IS_SESSION (session)); - -- GDM_SESSION_GET_IFACE (session)->accredit (session, flag); -+ GDM_SESSION_GET_IFACE (session)->accredit (session, service_name, flag); + GPtrArray *env; +@@ -145,31 +175,31 @@ get_job_environment (GdmSessionWorkerJob } - void - gdm_session_answer_query (GdmSession *session, -+ const char *service_name, - const char *text) + static gboolean +-gdm_session_worker_job_spawn (GdmSessionWorkerJob *session_worker_job) ++gdm_session_worker_job_spawn (GdmSessionWorkerJob *session_worker_job, ++ const char *name) { - g_return_if_fail (GDM_IS_SESSION (session)); +- gchar **argv; + GError *error; + gboolean ret; ++ GPtrArray *args; + GPtrArray *env; -- GDM_SESSION_GET_IFACE (session)->answer_query (session, text); -+ GDM_SESSION_GET_IFACE (session)->answer_query (session, service_name, text); - } + ret = FALSE; - void -@@ -192,11 +197,12 @@ gdm_session_cancel (GdmSession *session) - } +- g_debug ("GdmSessionWorkerJob: Running session_worker_job process: %s", session_worker_job->priv->command); ++ g_debug ("GdmSessionWorkerJob: Running session_worker_job process: %s %s", ++ name != NULL? name : "", session_worker_job->priv->command); - void --gdm_session_start_session (GdmSession *session) -+gdm_session_start_session (GdmSession *session, -+ const char *service_name) +- argv = NULL; +- if (! g_shell_parse_argv (session_worker_job->priv->command, NULL, &argv, &error)) { +- g_warning ("Could not parse command: %s", error->message); +- g_error_free (error); +- goto out; +- } ++ args = get_job_arguments (session_worker_job, name); + ++ if (args == NULL) { ++ return FALSE; ++ } + env = get_job_environment (session_worker_job); + + error = NULL; + ret = g_spawn_async_with_pipes (NULL, +- argv, ++ (char **) args->pdata, + (char **)env->pdata, +- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, ++ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_FILE_AND_ARGV_ZERO, + (GSpawnChildSetupFunc)session_worker_job_child_setup, + session_worker_job, + &session_worker_job->priv->pid, +@@ -178,6 +208,9 @@ gdm_session_worker_job_spawn (GdmSession + NULL, + &error); + ++ g_ptr_array_foreach (args, (GFunc)g_free, NULL); ++ g_ptr_array_free (args, TRUE); ++ + g_ptr_array_foreach (env, (GFunc)g_free, NULL); + g_ptr_array_free (env, TRUE); + +@@ -194,7 +227,6 @@ gdm_session_worker_job_spawn (GdmSession + (GChildWatchFunc)session_worker_job_child_watch, + session_worker_job); + +- g_strfreev (argv); + out: + + return ret; +@@ -207,13 +239,14 @@ gdm_session_worker_job_spawn (GdmSession + * Starts a local X session_worker_job. Handles retries and fatal errors properly. + */ + gboolean +-gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job) ++gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job, ++ const char *name) { - g_return_if_fail (GDM_IS_SESSION (session)); + gboolean res; -- GDM_SESSION_GET_IFACE (session)->start_session (session); -+ GDM_SESSION_GET_IFACE (session)->start_session (session, service_name); + g_debug ("GdmSessionWorkerJob: Starting worker..."); + +- res = gdm_session_worker_job_spawn (session_worker_job); ++ res = gdm_session_worker_job_spawn (session_worker_job, name); + + if (res) { + +@@ -261,6 +294,7 @@ gdm_session_worker_job_stop (GdmSessionW + g_debug ("GdmSessionWorkerJob: Stopping job pid:%d", session_worker_job->priv->pid); + + res = gdm_signal_pid (session_worker_job->priv->pid, SIGTERM); ++ + if (res < 0) { + g_warning ("Unable to kill session worker process"); + } else { +@@ -270,6 +304,13 @@ gdm_session_worker_job_stop (GdmSessionW + return TRUE; } - static void -@@ -213,7 +219,7 @@ gdm_session_class_init (gpointer g_iface) - NULL, - g_cclosure_marshal_VOID__STRING, ++GPid ++gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job) ++{ ++ g_return_val_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job), 0); ++ return session_worker_job->priv->pid; ++} ++ + void + gdm_session_worker_job_set_server_address (GdmSessionWorkerJob *session_worker_job, + const char *address) +@@ -363,16 +404,6 @@ gdm_session_worker_job_class_init (GdmSe + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); - signals [SETUP_COMPLETE] = - g_signal_new ("setup-complete", - iface_type, -@@ -221,9 +227,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, setup_complete), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, -+ G_TYPE_STRING); - signals [SETUP_FAILED] = - g_signal_new ("setup-failed", - iface_type, -@@ -231,10 +238,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, setup_failed), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [RESET_COMPLETE] = - g_signal_new ("reset-complete", - iface_type, -@@ -263,9 +270,9 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, authenticated), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); - signals [AUTHENTICATION_FAILED] = - g_signal_new ("authentication-failed", - iface_type, -@@ -273,10 +280,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, authentication_failed), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [AUTHORIZED] = - g_signal_new ("authorized", - iface_type, -@@ -284,9 +291,9 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, authorized), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); - signals [AUTHORIZATION_FAILED] = - g_signal_new ("authorization-failed", - iface_type, -@@ -294,10 +301,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, authorization_failed), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [ACCREDITED] = - g_signal_new ("accredited", - iface_type, -@@ -305,9 +312,9 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, accredited), - NULL, - NULL, + 0); +- signals [STOPPED] = +- g_signal_new ("stopped", +- G_OBJECT_CLASS_TYPE (object_class), +- G_SIGNAL_RUN_FIRST, +- G_STRUCT_OFFSET (GdmSessionWorkerJobClass, stopped), +- NULL, +- NULL, - g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, +- G_TYPE_NONE, - 0); -+ 1, G_TYPE_STRING); - signals [ACCREDITATION_FAILED] = - g_signal_new ("accreditation-failed", - iface_type, -@@ -315,10 +322,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, accreditation_failed), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); + signals [EXITED] = + g_signal_new ("exited", + G_OBJECT_CLASS_TYPE (object_class), +diff -up gdm-2.25.2/daemon/gdm-session-worker-job.h.multistack-but-boring gdm-2.25.2/daemon/gdm-session-worker-job.h +--- gdm-2.25.2/daemon/gdm-session-worker-job.h.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/gdm-session-worker-job.h 2009-03-03 17:45:05.651016418 -0500 +@@ -46,7 +46,6 @@ typedef struct + GObjectClass parent_class; - signals [INFO_QUERY] = - g_signal_new ("info-query", -@@ -327,10 +334,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, info_query), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [SECRET_INFO_QUERY] = - g_signal_new ("secret-info-query", - iface_type, -@@ -338,10 +345,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, secret_info_query), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [INFO] = - g_signal_new ("info", - iface_type, -@@ -349,10 +356,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, info), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [PROBLEM] = - g_signal_new ("problem", - iface_type, -@@ -360,10 +367,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, problem), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [SESSION_STARTED] = - g_signal_new ("session-started", - iface_type, -@@ -371,10 +378,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, session_started), - NULL, - NULL, -- g_cclosure_marshal_VOID__INT, -+ gdm_marshal_VOID__STRING_INT, - G_TYPE_NONE, -- 1, -- G_TYPE_INT); -+ 2, -+ G_TYPE_STRING, G_TYPE_INT); - signals [SESSION_START_FAILED] = - g_signal_new ("session-start-failed", - iface_type, -@@ -382,10 +389,10 @@ gdm_session_class_init (gpointer g_iface) - G_STRUCT_OFFSET (GdmSessionIface, session_start_failed), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ gdm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, -- 1, -- G_TYPE_STRING); -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [SESSION_EXITED] = - g_signal_new ("session-exited", - iface_type, -@@ -465,19 +472,21 @@ gdm_session_class_init (gpointer g_iface) - } + void (* started) (GdmSessionWorkerJob *session_worker_job); +- void (* stopped) (GdmSessionWorkerJob *session_worker_job); + void (* exited) (GdmSessionWorkerJob *session_worker_job, + int exit_code); - void --_gdm_session_setup_complete (GdmSession *session) -+_gdm_session_setup_complete (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); +@@ -58,9 +57,12 @@ GType gdm_session_work + GdmSessionWorkerJob * gdm_session_worker_job_new (void); + void gdm_session_worker_job_set_server_address (GdmSessionWorkerJob *session_worker_job, + const char *server_address); +-gboolean gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job); ++gboolean gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job, ++ const char *name); + gboolean gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job); -- g_signal_emit (session, signals [SETUP_COMPLETE], 0); -+ g_signal_emit (session, signals [SETUP_COMPLETE], 0, service_name); - } ++GPid gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job); ++ + G_END_DECLS - void - _gdm_session_setup_failed (GdmSession *session, -+ const char *service_name, - const char *text) + #endif /* __GDM_SESSION_WORKER_JOB_H */ +diff -up gdm-2.25.2/daemon/gdm-simple-slave.c.multistack-but-boring gdm-2.25.2/daemon/gdm-simple-slave.c +--- gdm-2.25.2/daemon/gdm-simple-slave.c.multistack-but-boring 2009-03-03 17:45:05.485038503 -0500 ++++ gdm-2.25.2/daemon/gdm-simple-slave.c 2009-03-03 17:45:05.707017170 -0500 +@@ -68,6 +68,8 @@ struct GdmSimpleSlavePrivate + guint greeter_reset_id; + guint start_session_id; + ++ char *start_session_service_name; ++ + int ping_interval; + + GPid server_pid; +@@ -99,6 +101,7 @@ static void start_greeter (GdmSimpl + + static void + on_session_started (GdmSession *session, ++ const char *service_name, + int pid, + GdmSimpleSlave *slave) { - g_return_if_fail (GDM_IS_SESSION (session)); -- g_signal_emit (session, signals [SETUP_FAILED], 0, text); -+ g_signal_emit (session, signals [SETUP_FAILED], 0, service_name, text); +@@ -172,7 +175,6 @@ reset_session (GdmSimpleSlave *slave) + { + destroy_session (slave); + create_new_session (slave); +- gdm_session_open (GDM_SESSION (slave->priv->session)); } - void -@@ -497,99 +506,111 @@ _gdm_session_reset_failed (GdmSession *session, - } + static gboolean +@@ -203,23 +205,25 @@ queue_greeter_reset (GdmSimpleSlave *sla - void --_gdm_session_authenticated (GdmSession *session) -+_gdm_session_authenticated (GdmSession *session, -+ const char *service_name) + static void + on_session_setup_complete (GdmSession *session, ++ const char *service_name, + GdmSimpleSlave *slave) { - g_return_if_fail (GDM_IS_SESSION (session)); - -- g_signal_emit (session, signals [AUTHENTICATED], 0); -+ 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, text); -+ g_signal_emit (session, signals [AUTHENTICATION_FAILED], 0, service_name, text); - } - - void --_gdm_session_authorized (GdmSession *session) -+_gdm_session_authorized (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); - -- g_signal_emit (session, signals [AUTHORIZED], 0); -+ 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, text); -+ g_signal_emit (session, signals [AUTHORIZATION_FAILED], 0, service_name, text); - } - - void --_gdm_session_accredited (GdmSession *session) -+_gdm_session_accredited (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); - -- g_signal_emit (session, signals [ACCREDITED], 0); -+ 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, text); -+ 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, text); -+ 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, text); -+ 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, text); -+ 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, text); -+ g_signal_emit (session, signals [PROBLEM], 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, pid); -+ 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, text); -+ g_signal_emit (session, signals [SESSION_START_FAILED], 0, service_name, text); - } - - void -diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h -index 77e0cf6..db5fc4a 100644 ---- a/daemon/gdm-session.h -+++ b/daemon/gdm-session.h -@@ -53,11 +53,15 @@ struct _GdmSessionIface - const char *service_name, - const char *username); - void (* reset) (GdmSession *session); -- void (* authenticate) (GdmSession *session); -- void (* authorize) (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 (* answer_query) (GdmSession *session, -+ const char *service_name, - const char *text); - void (* select_language) (GdmSession *session, - const char *text); -@@ -67,38 +71,53 @@ struct _GdmSessionIface - const char *text); - void (* select_user) (GdmSession *session, - const char *text); -- void (* start_session) (GdmSession *session); -+ void (* start_session) (GdmSession *session, -+ const char *service_name); - void (* close) (GdmSession *session); - void (* cancel) (GdmSession *session); - - /* Signals */ -- void (* setup_complete) (GdmSession *session); -+ void (* setup_complete) (GdmSession *session, -+ const char *service_name); - void (* setup_failed) (GdmSession *session, -+ const char *service_name, - const char *message); - void (* reset_complete) (GdmSession *session); - void (* reset_failed) (GdmSession *session, - const char *message); -- void (* authenticated) (GdmSession *session); -+ void (* authenticated) (GdmSession *session, -+ const char *service_name); - void (* authentication_failed) (GdmSession *session, -+ const char *service_name, - const char *message); -- void (* authorized) (GdmSession *session); -+ void (* authorized) (GdmSession *session, -+ const char *service_name); - void (* authorization_failed) (GdmSession *session, -+ const char *service_name, - const char *message); -- void (* accredited) (GdmSession *session); -+ void (* accredited) (GdmSession *session, -+ const char *service_name); - void (* accreditation_failed) (GdmSession *session, -+ const char *service_name, - const char *message); - - void (* info_query) (GdmSession *session, -+ const char *service_name, - const char *query_text); - void (* secret_info_query) (GdmSession *session, -+ const char *service_name, - const char *query_text); - void (* info) (GdmSession *session, -+ const char *service_name, - const char *info); - void (* problem) (GdmSession *session, -+ const char *service_name, - const char *problem); - void (* session_started) (GdmSession *session, -+ const char *service_name, - int pid); - void (* session_start_failed) (GdmSession *session, -+ const char *service_name, - const char *message); - void (* session_exited) (GdmSession *session, - int exit_code); -@@ -128,14 +147,19 @@ void gdm_session_setup_for_user (GdmSession *session, - const char *service_name, - const char *username); - void gdm_session_reset (GdmSession *session); --void gdm_session_authenticate (GdmSession *session); --void gdm_session_authorize (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_start_session (GdmSession *session); -+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_session (GdmSession *session, - const char *session_name); -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index eab5c8d..3a24d8d 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -68,6 +68,8 @@ struct GdmSimpleSlavePrivate - guint greeter_reset_id; - guint start_session_id; - -+ char *start_session_service_name; -+ - int ping_interval; - - GPid server_pid; -@@ -98,6 +100,7 @@ static void start_greeter (GdmSimpleSlave *slave); - - static void - on_session_started (GdmSession *session, -+ const char *service_name, - int pid, - GdmSimpleSlave *slave) - { -@@ -201,18 +204,21 @@ queue_greeter_reset (GdmSimpleSlave *slave) - - static void - on_session_setup_complete (GdmSession *session, -+ const char *service_name, - GdmSimpleSlave *slave) - { -- gdm_session_authenticate (session); -+ gdm_session_authenticate (session, service_name); +- gdm_session_authenticate (session); ++ gdm_session_authenticate (session, service_name); } static void @@ -5163,7 +4435,13 @@ index eab5c8d..3a24d8d 100644 _("Unable to initialize login system")); } -@@ -237,18 +243,21 @@ on_session_reset_failed (GdmSession *session, +- destroy_session (slave); +- queue_greeter_reset (slave); ++ gdm_session_stop_conversation (session, service_name); + } + + static void +@@ -239,26 +243,30 @@ on_session_reset_failed (GdmSession static void on_session_authenticated (GdmSession *session, @@ -5185,8 +4463,10 @@ index eab5c8d..3a24d8d 100644 + service_name, _("Unable to authenticate user")); } - destroy_session (slave); -@@ -256,7 +265,8 @@ on_session_authentication_failed (GdmSession *session, +- destroy_session (slave); +- queue_greeter_reset (slave); ++ ++ gdm_session_stop_conversation (session, service_name); } static void @@ -5196,7 +4476,7 @@ index eab5c8d..3a24d8d 100644 { if (slave->priv->start_session_when_ready) { char *ssid; -@@ -277,7 +287,7 @@ gdm_simple_slave_accredit_when_ready (GdmSimpleSlave *slave) +@@ -279,7 +287,7 @@ gdm_simple_slave_accredit_when_ready (Gd g_free (ssid); g_free (username); @@ -5205,7 +4485,7 @@ index eab5c8d..3a24d8d 100644 } else { slave->priv->waiting_to_start_session = TRUE; } -@@ -285,24 +295,27 @@ gdm_simple_slave_accredit_when_ready (GdmSimpleSlave *slave) +@@ -287,29 +295,31 @@ gdm_simple_slave_accredit_when_ready (Gd static void on_session_authorized (GdmSession *session, @@ -5236,7 +4516,13 @@ index eab5c8d..3a24d8d 100644 _("Unable to authorize user")); } -@@ -383,31 +396,38 @@ start_session_timeout (GdmSimpleSlave *slave) +- destroy_session (slave); +- queue_greeter_reset (slave); ++ gdm_session_stop_conversation (session, service_name); + } + + static gboolean +@@ -385,31 +395,38 @@ start_session_timeout (GdmSimpleSlave *s g_free (auth_file); @@ -5278,7 +4564,7 @@ index eab5c8d..3a24d8d 100644 const char *message, GdmSimpleSlave *slave) { -@@ -422,6 +442,7 @@ on_session_accreditation_failed (GdmSession *session, +@@ -424,6 +441,7 @@ on_session_accreditation_failed (GdmSess if (! migrated) { if (slave->priv->greeter_server != NULL) { gdm_greeter_server_problem (slave->priv->greeter_server, @@ -5286,7 +4572,15 @@ index eab5c8d..3a24d8d 100644 _("Unable establish credentials")); } } -@@ -437,41 +458,45 @@ on_session_accreditation_failed (GdmSession *session, +@@ -432,62 +450,67 @@ on_session_accreditation_failed (GdmSess + when Xorg exits it switches to the VT it was + started from. That interferes with fast + user switching. */ +- destroy_session (slave); + +- queue_greeter_reset (slave); ++ gdm_session_stop_conversation (session, service_name); + } static void on_session_info (GdmSession *session, @@ -5336,21 +4630,119 @@ index eab5c8d..3a24d8d 100644 } static void -@@ -741,11 +766,12 @@ on_greeter_start_conversation (GdmGreeterServer *greeter_server, - +-on_session_opened (GdmSession *session, +- GdmSimpleSlave *slave) ++on_session_conversation_started (GdmSession *session, ++ const char *service_name, ++ GdmSimpleSlave *slave) + { + gboolean res; + gboolean enabled; + char *username; + int delay; + +- g_debug ("GdmSimpleSlave: session opened"); ++ g_debug ("GdmSimpleSlave: conversation started"); + if (slave->priv->greeter_server != NULL) { +- res = gdm_greeter_server_ready (slave->priv->greeter_server); ++ res = gdm_greeter_server_ready (slave->priv->greeter_server, ++ service_name); + if (! res) { + g_warning ("Unable to send ready"); + } +@@ -503,8 +526,10 @@ on_session_opened (GdmSession *sessi + gdm_greeter_server_request_timed_login (slave->priv->greeter_server, username, delay); + } else { + g_debug ("GdmSimpleSlave: begin auto login for user '%s'", username); ++ /* service_name will be "gdm-autologin" ++ */ + gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), +- "gdm-autologin", ++ service_name, + username); + } + +@@ -512,6 +537,23 @@ on_session_opened (GdmSession *sessi + } + + static void ++on_session_conversation_stopped (GdmSession *session, ++ const char *service_name, ++ GdmSimpleSlave *slave) ++{ ++ gboolean res; ++ g_debug ("GdmSimpleSlave: conversation stopped"); ++ ++ if (slave->priv->greeter_server != NULL) { ++ res = gdm_greeter_server_conversation_stopped (slave->priv->greeter_server, ++ service_name); ++ if (! res) { ++ g_warning ("Unable to send conversation stopped"); ++ } ++ } ++} ++ ++static void + on_session_selected_user_changed (GdmSession *session, + const char *text, + GdmSimpleSlave *slave) +@@ -596,8 +638,12 @@ create_new_session (GdmSimpleSlave *slav + g_free (display_hostname); + + g_signal_connect (slave->priv->session, +- "opened", +- G_CALLBACK (on_session_opened), ++ "conversation-started", ++ G_CALLBACK (on_session_conversation_started), ++ slave); ++ g_signal_connect (slave->priv->session, ++ "conversation-stopped", ++ G_CALLBACK (on_session_conversation_stopped), + slave); + g_signal_connect (slave->priv->session, + "setup-complete", +@@ -728,12 +774,29 @@ on_greeter_session_died (GdmGreeterSessi + } + static void ++on_greeter_start_conversation (GdmGreeterServer *greeter_server, ++ const char *service_name, ++ GdmSimpleSlave *slave) ++{ ++ g_debug ("GdmSimpleSlave: starting conversation with '%s' pam service'", service_name); ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } ++ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), ++ service_name); ++} ++ ++static void on_greeter_begin_verification (GdmGreeterServer *greeter_server, + const char *service_name, GdmSimpleSlave *slave) { g_debug ("GdmSimpleSlave: begin verification"); ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } gdm_session_setup (GDM_SESSION (slave->priv->session), - "gdm"); + service_name); } static void -@@ -761,21 +787,23 @@ on_greeter_begin_auto_login (GdmGreeterServer *greeter_server, +@@ -742,6 +805,9 @@ on_greeter_begin_auto_login (GdmGreeterS + GdmSimpleSlave *slave) + { + g_debug ("GdmSimpleSlave: begin auto login for user '%s'", username); ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } + gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), + "gdm-autologin", + username); +@@ -749,21 +815,29 @@ on_greeter_begin_auto_login (GdmGreeterS static void on_greeter_begin_verification_for_user (GdmGreeterServer *greeter_server, @@ -5359,6 +4751,9 @@ index eab5c8d..3a24d8d 100644 GdmSimpleSlave *slave) { g_debug ("GdmSimpleSlave: begin verification"); ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), - "gdm", + service_name, @@ -5372,11 +4767,68 @@ index eab5c8d..3a24d8d 100644 GdmSimpleSlave *slave) { - gdm_session_answer_query (GDM_SESSION (slave->priv->session), text); ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } + gdm_session_answer_query (GDM_SESSION (slave->priv->session), service_name, text); } static void -@@ -838,18 +866,20 @@ on_greeter_connected (GdmGreeterServer *greeter_server, +@@ -771,6 +845,9 @@ on_greeter_session_selected (GdmGreeterS + const char *text, + GdmSimpleSlave *slave) + { ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } + gdm_session_select_session (GDM_SESSION (slave->priv->session), text); + } + +@@ -779,6 +856,9 @@ on_greeter_language_selected (GdmGreeter + const char *text, + GdmSimpleSlave *slave) + { ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } + gdm_session_select_language (GDM_SESSION (slave->priv->session), text); + } + +@@ -787,6 +867,9 @@ on_greeter_layout_selected (GdmGreeterSe + const char *text, + GdmSimpleSlave *slave) + { ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } + gdm_session_select_layout (GDM_SESSION (slave->priv->session), text); + } + +@@ -803,7 +886,11 @@ on_greeter_cancel (GdmGreeterServer *gre + GdmSimpleSlave *slave) + { + g_debug ("GdmSimpleSlave: Greeter cancelled"); ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } + reset_session (slave); ++ queue_greeter_reset (slave); + } + + static void +@@ -813,8 +900,9 @@ on_greeter_connected (GdmGreeterServer * + gboolean display_is_local; + + g_debug ("GdmSimpleSlave: Greeter connected"); +- +- gdm_session_open (GDM_SESSION (slave->priv->session)); ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } + + g_object_get (slave, + "display-is-local", &display_is_local, +@@ -828,21 +916,29 @@ on_greeter_connected (GdmGreeterServer * static void on_start_session_when_ready (GdmGreeterServer *session, @@ -5384,6 +4836,9 @@ index eab5c8d..3a24d8d 100644 GdmSimpleSlave *slave) { g_debug ("GdmSimpleSlave: Will start session when ready"); ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } slave->priv->start_session_when_ready = TRUE; if (slave->priv->waiting_to_start_session) { @@ -5398,10 +4853,16 @@ index eab5c8d..3a24d8d 100644 GdmSimpleSlave *slave) { g_debug ("GdmSimpleSlave: Will start session when ready and told"); -@@ -861,6 +891,15 @@ setup_server (GdmSimpleSlave *slave) ++ if (slave->priv->greeter_reset_id > 0) { ++ return; ++ } + slave->priv->start_session_when_ready = FALSE; + } + +@@ -850,6 +946,15 @@ static void + setup_server (GdmSimpleSlave *slave) { /* Set the busy cursor */ - gdm_slave_set_busy_cursor (GDM_SLAVE (slave)); + + /* The root window has a background that may be useful + * to cross fade or transition from when setting the @@ -5411,14 +4872,38 @@ index eab5c8d..3a24d8d 100644 + */ + gdm_slave_save_root_windows (GDM_SLAVE (slave)); + - } + gdm_slave_set_busy_cursor (GDM_SLAVE (slave)); + + /* The root window has a background that may be useful +@@ -908,6 +1013,10 @@ start_greeter (GdmSimpleSlave *slave) + + slave->priv->greeter_server = gdm_greeter_server_new (display_id); + g_signal_connect (slave->priv->greeter_server, ++ "start-conversation", ++ G_CALLBACK (on_greeter_start_conversation), ++ slave); ++ g_signal_connect (slave->priv->greeter_server, + "begin-auto-login", + G_CALLBACK (on_greeter_begin_auto_login), + slave); +diff -up gdm-2.25.2/daemon/test-session.c.multistack-but-boring gdm-2.25.2/daemon/test-session.c +--- gdm-2.25.2/daemon/test-session.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/daemon/test-session.c 2009-03-03 17:45:05.601017034 -0500 +@@ -33,20 +33,22 @@ + static GMainLoop *loop; static void -diff --git a/daemon/test-session.c b/daemon/test-session.c -index d9fa26e..3cf8483 100644 ---- a/daemon/test-session.c -+++ b/daemon/test-session.c -@@ -44,10 +44,11 @@ on_conversation_started (GdmSession *session, +-on_open (GdmSession *session, +- const char *username) ++on_conversation_started (GdmSession *session, ++ const char *service_name, ++ const char *username) + { + g_debug ("Got opened: calling setup..."); + +- gdm_session_setup (session, "gdm"); ++ gdm_session_setup (session, service_name); + } static void on_session_setup_complete (GdmSession *session, @@ -5431,7 +4916,7 @@ index d9fa26e..3cf8483 100644 } static void -@@ -79,10 +80,11 @@ on_session_reset_failed (GdmSession *session, +@@ -78,10 +80,11 @@ on_session_reset_failed (GdmSession *ses static void on_session_authenticated (GdmSession *session, @@ -5444,7 +4929,7 @@ index d9fa26e..3cf8483 100644 } static void -@@ -97,14 +99,16 @@ on_session_authentication_failed (GdmSession *session, +@@ -96,14 +99,16 @@ on_session_authentication_failed (GdmSes static void on_session_authorized (GdmSession *session, @@ -5462,7 +4947,7 @@ index d9fa26e..3cf8483 100644 const char *message, gpointer data) { -@@ -115,6 +119,7 @@ on_session_authorization_failed (GdmSession *session, +@@ -114,6 +119,7 @@ on_session_authorization_failed (GdmSess static void on_session_accredited (GdmSession *session, @@ -5470,7 +4955,7 @@ index d9fa26e..3cf8483 100644 gpointer data) { char *username; -@@ -125,12 +130,13 @@ on_session_accredited (GdmSession *session, +@@ -124,12 +130,13 @@ on_session_accredited (GdmSession *sessi username ? username : "", username ? " " : ""); g_free (username); @@ -5485,7 +4970,7 @@ index d9fa26e..3cf8483 100644 const char *message, gpointer data) { -@@ -165,6 +171,7 @@ on_session_died (GdmSession *session, +@@ -164,6 +171,7 @@ on_session_died (GdmSession *session, static void on_info_query (GdmSession *session, @@ -5493,7 +4978,7 @@ index d9fa26e..3cf8483 100644 const char *query_text) { char answer[1024]; -@@ -178,12 +185,13 @@ on_info_query (GdmSession *session, +@@ -177,12 +185,13 @@ on_info_query (GdmSession *session, gdm_session_close (session); g_main_loop_quit (loop); } else { @@ -5508,7 +4993,7 @@ index d9fa26e..3cf8483 100644 const char *info) { g_print ("\n** NOTE: %s\n", info); -@@ -191,6 +199,7 @@ on_info (GdmSession *session, +@@ -190,6 +199,7 @@ on_info (GdmSession *session, static void on_problem (GdmSession *session, @@ -5516,7 +5001,7 @@ index d9fa26e..3cf8483 100644 const char *problem) { g_print ("\n** WARNING: %s\n", problem); -@@ -198,6 +207,7 @@ on_problem (GdmSession *session, +@@ -197,6 +207,7 @@ on_problem (GdmSession *session, static void on_secret_info_query (GdmSession *session, @@ -5524,7 +5009,7 @@ index d9fa26e..3cf8483 100644 const char *query_text) { char answer[1024]; -@@ -222,7 +232,7 @@ on_secret_info_query (GdmSession *session, +@@ -221,7 +232,7 @@ on_secret_info_query (GdmSession *sessio g_print ("\n"); @@ -5533,49 +5018,151 @@ index d9fa26e..3cf8483 100644 } static void -diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c -index 1e2c55d..ee7019d 100644 ---- a/gui/simple-greeter/gdm-greeter-client.c -+++ b/gui/simple-greeter/gdm-greeter-client.c -@@ -134,6 +134,37 @@ emit_string_and_int_signal_for_message (GdmGreeterClient *client, - } +@@ -256,11 +267,11 @@ main (int argc, + username = argv[1]; + } - static void -+emit_string_and_string_signal_for_message (GdmGreeterClient *client, -+ const char *name, -+ DBusMessage *message, -+ int signal) -+{ -+ DBusError error; -+ char *text1; -+ char *text2; -+ dbus_bool_t res; -+ -+ dbus_error_init (&error); -+ res = dbus_message_get_args (message, -+ &error, -+ DBUS_TYPE_STRING, &text1, -+ DBUS_TYPE_STRING, &text2, -+ DBUS_TYPE_INVALID); -+ if (res) { +- gdm_session_open (GDM_SESSION (session)); ++ gdm_session_start_conversation (GDM_SESSION (session), "gdm"); + + g_signal_connect (session, +- "opened", +- G_CALLBACK (on_open), ++ "conversation-started", ++ G_CALLBACK (on_conversation_started), + username); + g_signal_connect (session, + "setup-complete", +diff -up gdm-2.25.2/gui/simple-greeter/gdm-chooser-widget.c.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-chooser-widget.c +--- gdm-2.25.2/gui/simple-greeter/gdm-chooser-widget.c.multistack-but-boring 2008-09-08 20:53:24.000000000 -0400 ++++ gdm-2.25.2/gui/simple-greeter/gdm-chooser-widget.c 2009-03-03 17:45:05.794016293 -0500 +@@ -93,6 +93,7 @@ struct GdmChooserWidgetPrivate + guint32 should_hide_inactive_items : 1; + guint32 emit_activated_after_resize_animation : 1; + guint32 was_fully_grown : 1; ++ guint32 is_loaded : 1; + + GdmChooserWidgetPosition separator_position; + GdmChooserWidgetState state; +@@ -2132,13 +2133,30 @@ gdm_chooser_widget_lookup_item (GdmChoos + } + g_free (active_item_id); + +- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, +- CHOOSER_IMAGE_COLUMN, image, +- CHOOSER_NAME_COLUMN, name, +- CHOOSER_PRIORITY_COLUMN, priority, +- CHOOSER_ITEM_IS_IN_USE_COLUMN, is_in_use, +- CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate, +- -1); ++ if (image != NULL) { ++ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, ++ CHOOSER_IMAGE_COLUMN, image, -1); ++ } + -+ g_debug ("GdmGreeterClient: Received %s (%s, %s)", name, text1, text2); ++ if (name != NULL) { ++ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, ++ CHOOSER_NAME_COLUMN, name, -1); ++ } + -+ g_signal_emit (client, -+ gdm_greeter_client_signals[signal], -+ 0, text1, text2); -+ } else { -+ g_warning ("Unable to get arguments: %s", error.message); -+ dbus_error_free (&error); ++ if (priority != NULL) { ++ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, ++ CHOOSER_PRIORITY_COLUMN, priority, -1); + } -+ dbus_error_free (&error); -+} + -+static void ++ if (is_in_use != NULL) { ++ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, ++ CHOOSER_ITEM_IS_IN_USE_COLUMN, is_in_use, -1); ++ } ++ ++ if (is_separate != NULL) { ++ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, ++ CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate, -1); ++ } + + return TRUE; + } +@@ -2485,8 +2503,16 @@ gdm_chooser_widget_propagate_pending_key + gdm_scrollable_widget_replay_queued_key_events (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget)); + } + ++gboolean ++gdm_chooser_widget_is_loaded (GdmChooserWidget *widget) ++{ ++ return widget->priv->is_loaded; ++} ++ + void + gdm_chooser_widget_loaded (GdmChooserWidget *widget) + { ++ widget->priv->is_loaded = TRUE; ++ + g_signal_emit (widget, signals[LOADED], 0); + } +diff -up gdm-2.25.2/gui/simple-greeter/gdm-chooser-widget.h.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-chooser-widget.h +--- gdm-2.25.2/gui/simple-greeter/gdm-chooser-widget.h.multistack-but-boring 2008-09-08 20:36:20.000000000 -0400 ++++ gdm-2.25.2/gui/simple-greeter/gdm-chooser-widget.h 2009-03-03 17:45:05.760016365 -0500 +@@ -136,6 +136,10 @@ int gdm_chooser_widget_get_nu + void gdm_chooser_widget_activate_if_one_item (GdmChooserWidget *widget); + void gdm_chooser_widget_propagate_pending_key_events (GdmChooserWidget *widget); + ++gboolean gdm_chooser_widget_is_loaded (GdmChooserWidget *widget); ++ ++/* Protected ++ */ + void gdm_chooser_widget_loaded (GdmChooserWidget *widget); + + G_END_DECLS +diff -up gdm-2.25.2/gui/simple-greeter/gdm-greeter-client.c.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-greeter-client.c +--- gdm-2.25.2/gui/simple-greeter/gdm-greeter-client.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/gui/simple-greeter/gdm-greeter-client.c 2009-03-03 17:45:05.709016229 -0500 +@@ -64,6 +64,7 @@ enum { + INFO_QUERY, + SECRET_INFO_QUERY, + READY, ++ CONVERSATION_STOPPED, + RESET, + SELECTED_USER_CHANGED, + DEFAULT_LANGUAGE_NAME_CHANGED, +@@ -134,6 +135,37 @@ emit_string_and_int_signal_for_message ( + } + + static void ++emit_string_and_string_signal_for_message (GdmGreeterClient *client, ++ const char *name, ++ DBusMessage *message, ++ int signal) ++{ ++ DBusError error; ++ char *text1; ++ char *text2; ++ dbus_bool_t res; ++ ++ dbus_error_init (&error); ++ res = dbus_message_get_args (message, ++ &error, ++ DBUS_TYPE_STRING, &text1, ++ DBUS_TYPE_STRING, &text2, ++ DBUS_TYPE_INVALID); ++ if (res) { ++ ++ g_debug ("GdmGreeterClient: Received %s (%s, %s)", name, text1, text2); ++ ++ g_signal_emit (client, ++ gdm_greeter_client_signals[signal], ++ 0, text1, text2); ++ } else { ++ g_warning ("Unable to get arguments: %s", error.message); ++ dbus_error_free (&error); ++ } ++ dbus_error_free (&error); ++} ++ ++static void emit_string_signal_for_message (GdmGreeterClient *client, const char *name, DBusMessage *message, -@@ -200,37 +231,35 @@ static void +@@ -200,48 +232,49 @@ static void on_user_authorized (GdmGreeterClient *client, DBusMessage *message) { @@ -5618,7 +5205,25 @@ index 1e2c55d..ee7019d 100644 } static void -@@ -307,14 +336,22 @@ send_dbus_string_method (DBusConnection *connection, + on_ready (GdmGreeterClient *client, + DBusMessage *message) + { +- g_debug ("GdmGreeterClient: Ready"); ++ emit_string_signal_for_message (client, "Ready", message, READY); ++} + +- g_signal_emit (client, +- gdm_greeter_client_signals[READY], +- 0); ++static void ++on_conversation_stopped (GdmGreeterClient *client, ++ DBusMessage *message) ++{ ++ emit_string_signal_for_message (client, "ConversationStopped", message, CONVERSATION_STOPPED); + } + + static void +@@ -311,14 +344,22 @@ send_dbus_string_method (DBusConnection } static gboolean @@ -5644,7 +5249,7 @@ index 1e2c55d..ee7019d 100644 g_debug ("GdmGreeterClient: Calling %s", method); message = dbus_message_new_method_call (NULL, -@@ -328,8 +365,77 @@ send_dbus_bool_method (DBusConnection *connection, +@@ -332,8 +373,77 @@ send_dbus_bool_method (DBusConnection *c dbus_message_iter_init_append (message, &iter); dbus_message_iter_append_basic (&iter, @@ -5723,7 +5328,22 @@ index 1e2c55d..ee7019d 100644 dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, -@@ -412,37 +518,44 @@ gdm_greeter_client_call_begin_auto_login (GdmGreeterClient *client, +@@ -400,6 +510,14 @@ send_dbus_void_method (DBusConnection *c + } + + void ++gdm_greeter_client_call_start_conversation (GdmGreeterClient *client, ++ const char *service_name) ++{ ++ send_dbus_string_method (client->priv->connection, ++ "StartConversation", service_name); ++} ++ ++void + gdm_greeter_client_call_begin_auto_login (GdmGreeterClient *client, + const char *username) + { +@@ -408,37 +526,44 @@ gdm_greeter_client_call_begin_auto_login } void @@ -5780,7 +5400,16 @@ index 1e2c55d..ee7019d 100644 } void -@@ -835,10 +948,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) +@@ -643,6 +768,8 @@ client_dbus_handle_message (DBusConnecti + on_problem (client, message); + } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Ready")) { + on_ready (client, message); ++ } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "ConversationStopped")) { ++ on_conversation_stopped (client, message); + } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Reset")) { + on_reset (client, message); + } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "SelectedUserChanged")) { +@@ -831,10 +958,10 @@ gdm_greeter_client_class_init (GdmGreete G_STRUCT_OFFSET (GdmGreeterClientClass, info_query), NULL, NULL, @@ -5794,7 +5423,7 @@ index 1e2c55d..ee7019d 100644 gdm_greeter_client_signals[SECRET_INFO_QUERY] = g_signal_new ("secret-info-query", -@@ -847,10 +960,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) +@@ -843,10 +970,10 @@ gdm_greeter_client_class_init (GdmGreete G_STRUCT_OFFSET (GdmGreeterClientClass, secret_info_query), NULL, NULL, @@ -5808,7 +5437,7 @@ index 1e2c55d..ee7019d 100644 gdm_greeter_client_signals[INFO] = g_signal_new ("info", -@@ -859,10 +972,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) +@@ -855,10 +982,10 @@ gdm_greeter_client_class_init (GdmGreete G_STRUCT_OFFSET (GdmGreeterClientClass, info), NULL, NULL, @@ -5822,7 +5451,7 @@ index 1e2c55d..ee7019d 100644 gdm_greeter_client_signals[PROBLEM] = g_signal_new ("problem", -@@ -871,10 +984,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) +@@ -867,10 +994,10 @@ gdm_greeter_client_class_init (GdmGreete G_STRUCT_OFFSET (GdmGreeterClientClass, problem), NULL, NULL, @@ -5836,11 +5465,45 @@ index 1e2c55d..ee7019d 100644 gdm_greeter_client_signals[READY] = g_signal_new ("ready", -diff --git a/gui/simple-greeter/gdm-greeter-client.h b/gui/simple-greeter/gdm-greeter-client.h -index 88b0281..2f857dc 100644 ---- a/gui/simple-greeter/gdm-greeter-client.h -+++ b/gui/simple-greeter/gdm-greeter-client.h -@@ -45,17 +45,22 @@ typedef struct +@@ -879,9 +1006,20 @@ gdm_greeter_client_class_init (GdmGreete + G_STRUCT_OFFSET (GdmGreeterClientClass, ready), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); ++ ++ gdm_greeter_client_signals[CONVERSATION_STOPPED] = ++ g_signal_new ("conversation-stopped", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmGreeterClientClass, conversation_stopped), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, ++ 1, G_TYPE_STRING); + + gdm_greeter_client_signals[RESET] = + g_signal_new ("reset", +@@ -952,8 +1090,9 @@ gdm_greeter_client_class_init (GdmGreete + G_STRUCT_OFFSET (GdmGreeterClientClass, user_authorized), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, +- G_TYPE_NONE, 0); ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, ++ 1, G_TYPE_STRING); + } + + static void +diff -up gdm-2.25.2/gui/simple-greeter/gdm-greeter-client.h.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-greeter-client.h +--- gdm-2.25.2/gui/simple-greeter/gdm-greeter-client.h.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/gui/simple-greeter/gdm-greeter-client.h 2009-03-03 17:45:05.710016213 -0500 +@@ -45,17 +45,24 @@ typedef struct GObjectClass parent_class; void (* info_query) (GdmGreeterClient *client, @@ -5861,10 +5524,12 @@ index 88b0281..2f857dc 100644 - void (* ready) (GdmGreeterClient *client); + void (* ready) (GdmGreeterClient *client, + const char *service_name); ++ void (* conversation_stopped) (GdmGreeterClient *client, ++ const char *service_name); void (* reset) (GdmGreeterClient *client); void (* selected_user_changed) (GdmGreeterClient *client, const char *username); -@@ -69,7 +74,8 @@ typedef struct +@@ -69,7 +76,8 @@ typedef struct void (* timed_login_requested) (GdmGreeterClient *client, const char *username, int delay); @@ -5874,8 +5539,20 @@ index 88b0281..2f857dc 100644 } GdmGreeterClientClass; #define GDM_GREETER_CLIENT_ERROR (gdm_greeter_client_error_quark ()) -@@ -95,8 +101,10 @@ void gdm_greeter_client_call_start_conversation (GdmGreeter - const char *service_name); +@@ -84,17 +92,21 @@ GQuark gdm_greeter_client_er + GdmGreeterClient * gdm_greeter_client_new (void); + + gboolean gdm_greeter_client_start (GdmGreeterClient *client, +- GError **error); ++ GError **error); + void gdm_greeter_client_stop (GdmGreeterClient *client); + + gboolean gdm_greeter_client_get_display_is_local (GdmGreeterClient *client); + + char * gdm_greeter_client_call_get_display_id (GdmGreeterClient *client); + ++void gdm_greeter_client_call_start_conversation (GdmGreeterClient *client, ++ const char *service_name); void gdm_greeter_client_call_begin_auto_login (GdmGreeterClient *client, const char *username); -void gdm_greeter_client_call_begin_verification (GdmGreeterClient *client); @@ -5886,7 +5563,7 @@ index 88b0281..2f857dc 100644 const char *username); void gdm_greeter_client_call_cancel (GdmGreeterClient *client); void gdm_greeter_client_call_disconnect (GdmGreeterClient *client); -@@ -111,9 +119,11 @@ void gdm_greeter_client_call_select_layout (GdmGreeter +@@ -109,9 +121,11 @@ void gdm_greeter_client_ca void gdm_greeter_client_call_select_session (GdmGreeterClient *client, const char *text); void gdm_greeter_client_call_answer_query (GdmGreeterClient *client, @@ -5898,606 +5575,992 @@ index 88b0281..2f857dc 100644 gboolean should_start_session); -diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c -index 8681828..e625c24 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -64,6 +64,7 @@ static gpointer session_object = NULL; +diff -up gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.c.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.c +--- gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.c.multistack-but-boring 2008-11-18 17:19:05.000000000 -0500 ++++ gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.c 2009-03-03 17:45:05.816016419 -0500 +@@ -1,7 +1,7 @@ + /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann +- * Copyright (C) 2008 Red Hat, Inc. ++ * Copyright (C) 2008, 2009 Red Hat, Inc. + * + * 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 +@@ -17,6 +17,9 @@ + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ++ * Written by: William Jon McCann ++ * Ray Strode ++ * + */ - static void - on_info (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { -@@ -74,6 +75,7 @@ on_info (GdmGreeterClient *client, + #include "config.h" +@@ -60,12 +63,16 @@ + #include + #endif - static void - on_problem (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { -@@ -160,6 +162,7 @@ on_user_authorized (GdmGreeterClient *client, ++#include "gdm-marshal.h" ++ + #include "gdm-settings-client.h" + #include "gdm-settings-keys.h" + #include "gdm-profile.h" - static void - on_info_query (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { -@@ -170,6 +173,7 @@ on_info_query (GdmGreeterClient *client, ++#include "gdm-greeter-client.h" + #include "gdm-greeter-login-window.h" + #include "gdm-user-chooser-widget.h" ++#include "gdm-task-list.h" - static void - on_secret_info_query (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { -@@ -191,7 +195,8 @@ static void - on_begin_verification (GdmGreeterLoginWindow *login_window, - GdmGreeterSession *session) + #ifdef HAVE_PAM + #include +@@ -111,7 +118,9 @@ struct GdmGreeterLoginWindowPrivate { -- gdm_greeter_client_call_begin_verification (session->priv->client); -+ gdm_greeter_client_call_begin_verification (session->priv->client, -+ "gdm"); - } + GladeXML *xml; + GtkWidget *user_chooser; ++ GtkWidget *conversation_list; + GtkWidget *auth_banner_label; ++ GtkWidget *auth_page_box; + guint display_is_local : 1; + guint is_interactive : 1; + GConfClient *client; +@@ -139,6 +148,7 @@ enum { + }; + + enum { ++ START_CONVERSATION, + BEGIN_AUTO_LOGIN, + BEGIN_VERIFICATION, + BEGIN_VERIFICATION_FOR_USER, +@@ -160,6 +170,9 @@ static void restart_timed_login_time + static void on_user_unchosen (GdmUserChooserWidget *user_chooser, + GdmGreeterLoginWindow *login_window); + ++static void gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_window, ++ const char *service_name); ++ + G_DEFINE_TYPE (GdmGreeterLoginWindow, gdm_greeter_login_window, GTK_TYPE_WINDOW) static void -@@ -200,6 +205,7 @@ on_begin_verification_for_user (GdmGreeterLoginWindow *login_window, - GdmGreeterSession *session) +@@ -184,9 +197,6 @@ set_sensitive (GdmGreeterLoginWindow *lo { - gdm_greeter_client_call_begin_verification_for_user (session->priv->client, -+ "gdm", - username); - } + GtkWidget *box; -@@ -209,6 +215,7 @@ on_query_answer (GdmGreeterLoginWindow *login_window, - GdmGreeterSession *session) - { - gdm_greeter_client_call_answer_query (session->priv->client, -+ "gdm", - text); - } - -@@ -265,7 +272,7 @@ static void - on_start_session (GdmGreeterLoginWindow *login_window, - GdmGreeterSession *session) - { -- gdm_greeter_client_call_start_session_when_ready (session->priv->client, TRUE); -+ gdm_greeter_client_call_start_session_when_ready (session->priv->client, "gdm", TRUE); - } - - static void --- -1.6.1 - - -From 37c3657589bc1d29ac7af31b4dbaff74aa07f5a5 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 28 Jan 2009 15:12:04 -0500 -Subject: [PATCH 09/65] Move messages pending replies to conversations - ---- - daemon/gdm-session-direct.c | 40 ++++++++++++++++++---------------------- - 1 files changed, 18 insertions(+), 22 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index a12e333..b15b727 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -68,6 +68,7 @@ typedef struct - GPid worker_pid; - char *service_name; - DBusConnection *worker_connection; -+ DBusMessage *message_pending_reply; - } GdmSessionConversation; - - struct _GdmSessionDirectPrivate -@@ -82,8 +83,6 @@ struct _GdmSessionDirectPrivate - char *selected_user; - char *user_x11_authority_file; - -- DBusMessage *message_pending_reply; +- box = glade_xml_get_widget (login_window->priv->xml, "auth-input-box"); +- gtk_widget_set_sensitive (box, sensitive); - - GHashTable *conversations; - - GList *pending_connections; -@@ -776,27 +775,25 @@ gdm_session_direct_handle_username_changed (GdmSessionDirect *session, - } + box = glade_xml_get_widget (login_window->priv->xml, "buttonbox"); + gtk_widget_set_sensitive (box, sensitive); +@@ -196,27 +206,43 @@ set_sensitive (GdmGreeterLoginWindow *lo static void --cancel_pending_query (GdmSessionDirect *session) -+cancel_pending_query (GdmSessionConversation *conversation) + set_focus (GdmGreeterLoginWindow *login_window) { - DBusMessage *reply; -- GdmSessionConversation *conversation; - -- if (session->priv->message_pending_reply == NULL) { -+ if (conversation->message_pending_reply == NULL) { - return; - } - - g_debug ("GdmSessionDirect: Cancelling pending query"); - -- reply = dbus_message_new_error (session->priv->message_pending_reply, -+ reply = dbus_message_new_error (conversation->message_pending_reply, - GDM_SESSION_DBUS_ERROR_CANCEL, - "Operation cancelled"); -- conversation = NULL; - dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_connection_flush (conversation->worker_connection); - - dbus_message_unref (reply); -- dbus_message_unref (session->priv->message_pending_reply); -- session->priv->message_pending_reply = NULL; -+ dbus_message_unref (conversation->message_pending_reply); -+ conversation->message_pending_reply = NULL; - } - - static void -@@ -808,27 +805,26 @@ answer_pending_query (GdmSessionDirect *session, - DBusMessageIter iter; - GdmSessionConversation *conversation; - -- g_assert (session->priv->message_pending_reply != NULL); -+ conversation = find_conversation_by_name (session, service_name); - -- reply = dbus_message_new_method_return (session->priv->message_pending_reply); -+ 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); +- GtkWidget *entry; +- +- entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); ++ GdmTask *task; -- conversation = find_conversation_by_name (session, service_name); - dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); + gdk_window_focus (GTK_WIDGET (login_window)->window, GDK_CURRENT_TIME); -- dbus_message_unref (session->priv->message_pending_reply); -- session->priv->message_pending_reply = NULL; -+ dbus_message_unref (conversation->message_pending_reply); -+ conversation->message_pending_reply = NULL; +- if (GTK_WIDGET_REALIZED (entry) && ! GTK_WIDGET_HAS_FOCUS (entry)) { +- gtk_widget_grab_focus (entry); ++ task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); ++ ++ if (gdm_conversation_focus (GDM_CONVERSATION (task))) { ++ char *name; ++ name = gdm_task_get_name (task); ++ g_debug ("GdmGreeterLoginWindow: focusing task %s", name); ++ g_free (name); + } else if (GTK_WIDGET_REALIZED (login_window->priv->user_chooser) && ! GTK_WIDGET_HAS_FOCUS (login_window->priv->user_chooser)) { + gtk_widget_grab_focus (login_window->priv->user_chooser); + } ++ g_object_unref (task); ++} ++ ++static gboolean ++set_task_conversation_message (GdmTaskList *task_list, ++ GdmTask *task, ++ const char *message) ++{ ++ ++ gdm_conversation_set_message (GDM_CONVERSATION (task), message); ++ return FALSE; } static void --set_pending_query (GdmSessionDirect *session, -- DBusMessage *message) -+set_pending_query (GdmSessionConversation *conversation, -+ DBusMessage *message) + set_message (GdmGreeterLoginWindow *login_window, + const char *text) { -- g_assert (session->priv->message_pending_reply == NULL); -+ g_assert (conversation->message_pending_reply == NULL); +- GtkWidget *label; ++ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); -- session->priv->message_pending_reply = dbus_message_ref (message); -+ conversation->message_pending_reply = dbus_message_ref (message); +- label = glade_xml_get_widget (login_window->priv->xml, "auth-message-label"); +- gtk_label_set_text (GTK_LABEL (label), text); ++ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ (GdmTaskListForeachFunc) ++ set_task_conversation_message, ++ (gpointer) text); } - static DBusHandlerResult -@@ -846,7 +842,7 @@ gdm_session_direct_handle_info_query (GdmSessionDirect *session, - g_warning ("ERROR: %s", error.message); - } - -- set_pending_query (session, message); -+ set_pending_query (conversation, message); - - g_debug ("GdmSessionDirect: Emitting 'info-query' signal"); - _gdm_session_info_query (GDM_SESSION (session), conversation->service_name, text); -@@ -869,7 +865,7 @@ gdm_session_direct_handle_secret_info_query (GdmSessionDirect *session, - g_warning ("ERROR: %s", error.message); - } - -- set_pending_query (session, message); -+ set_pending_query (conversation, message); - - g_debug ("GdmSessionDirect: Emitting 'secret-info-query' signal"); - _gdm_session_secret_info_query (GDM_SESSION (session), conversation->service_name, text); -@@ -911,7 +907,7 @@ gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, - DBusMessage *reply; - - g_debug ("GdmSessionDirect: worker cancelling pending query"); -- cancel_pending_query (session); -+ cancel_pending_query (conversation); - - reply = dbus_message_new_method_return (message); - dbus_connection_send (conversation->worker_connection, reply, NULL); -@@ -1801,7 +1797,7 @@ stop_conversation (GdmSessionConversation *conversation) - G_CALLBACK (worker_died), - conversation); - -- cancel_pending_query (session); -+ cancel_pending_query (conversation); - - if (conversation->worker_connection != NULL) { - dbus_connection_close (conversation->worker_connection); --- -1.6.1 - - -From d693910b078cc8077ee504fe39bde63e74c891f1 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 28 Jan 2009 15:15:10 -0500 -Subject: [PATCH 10/65] Remove filter on worker connection at end of conv - ---- - daemon/gdm-session-direct.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index b15b727..a243ead 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1800,6 +1800,8 @@ stop_conversation (GdmSessionConversation *conversation) - cancel_pending_query (conversation); - - 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; - } --- -1.6.1 - - -From 6fa05c7cd02e5db1d2df056197bbd41cd237c6b9 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 28 Jan 2009 15:16:02 -0500 -Subject: [PATCH 11/65] Pass service name to StartSession in relay session - ---- - daemon/gdm-session-relay.c | 5 +++-- - 1 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c -index 36e86b5..6e15f75 100644 ---- a/daemon/gdm-session-relay.c -+++ b/daemon/gdm-session-relay.c -@@ -296,11 +296,12 @@ gdm_session_relay_cancel (GdmSession *session) + static void +@@ -382,30 +408,76 @@ get_show_restart_buttons (GdmGreeterLogi } static void --gdm_session_relay_start_session (GdmSession *session) -+gdm_session_relay_start_session (GdmSession *session, -+ const char *service_name) +-on_login_button_clicked_answer_query (GtkButton *button, +- GdmGreeterLoginWindow *login_window) ++on_login_button_clicked_timed_login (GtkButton *button, ++ GdmGreeterLoginWindow *login_window) { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); - -- send_dbus_void_signal (impl, "StartSession"); -+ send_dbus_string_signal (impl, "StartSession", service_name); - } +- GtkWidget *entry; +- const char *text; +- + set_busy (login_window); + set_sensitive (login_window, FALSE); - /* Note: Use abstract sockets like dbus does by default on Linux. Abstract --- -1.6.1 - - -From ccc1a816780e0e42ae124d471d6eb365c3c35e01 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 28 Jan 2009 15:16:30 -0500 -Subject: [PATCH 12/65] change g_return_if_fail to g_return_val_if_fail - ---- - daemon/gdm-session-worker-job.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c -index 1a7cf36..7328c0e 100644 ---- a/daemon/gdm-session-worker-job.c -+++ b/daemon/gdm-session-worker-job.c -@@ -273,7 +273,7 @@ gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job) - GPid - gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job) - { -- g_return_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job)); -+ g_return_val_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job), 0); - return session_worker_job->priv->pid; +- entry = glade_xml_get_widget (login_window->priv->xml, "auth-prompt-entry"); +- text = gtk_entry_get_text (GTK_ENTRY (entry)); +- + _gdm_greeter_login_window_set_interactive (login_window, TRUE); +- g_signal_emit (login_window, signals[QUERY_ANSWER], 0, text); } --- -1.6.1 - - -From 5d4aebec04b11866e9fdaf02fe59e271d3d762cb Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 28 Jan 2009 15:16:51 -0500 -Subject: [PATCH 13/65] Fix cancel operation - ---- - daemon/gdm-session-direct.c | 11 ++++++++++- - gui/simple-greeter/gdm-greeter-session.c | 1 + - 2 files changed, 11 insertions(+), 1 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index a243ead..55ea4ee 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -2291,10 +2291,19 @@ static void - gdm_session_direct_cancel (GdmSession *session) + static void +-on_login_button_clicked_timed_login (GtkButton *button, +- GdmGreeterLoginWindow *login_window) ++hide_task_actions (GdmTask *task) { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GHashTableIter iter; -+ gpointer key, value; - - g_return_if_fail (session != NULL); - -- cancel_pending_query (impl); -+ g_hash_table_iter_init (&iter, impl->priv->conversations); -+ while (g_hash_table_iter_next (&iter, &key, &value)) { -+ GdmSessionConversation *conversation; +- set_busy (login_window); +- set_sensitive (login_window, FALSE); ++ GtkActionGroup *actions; + -+ conversation = (GdmSessionConversation *) value; ++ actions = gdm_conversation_get_actions (GDM_CONVERSATION (task)); + -+ cancel_pending_query (conversation); ++ if (actions != NULL) { ++ gtk_action_group_set_visible (actions, FALSE); ++ gtk_action_group_set_sensitive (actions, FALSE); ++ g_object_unref (actions); + } - } - - char * -diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c -index e625c24..ea9e6d1 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -259,6 +259,7 @@ on_cancelled (GdmGreeterLoginWindow *login_window, - { - gdm_greeter_panel_hide_user_options (GDM_GREETER_PANEL (session->priv->panel)); - gdm_greeter_client_call_cancel (session->priv->client); -+ gdm_greeter_client_call_start_conversation (session->priv->client, "gdm"); - } - - static void --- -1.6.1 - - -From f60c338339301925e35eabb327346cc35213c37e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 28 Jan 2009 18:01:53 -0500 -Subject: [PATCH 14/65] Handle Start Conversation for relay session - ---- - daemon/gdm-factory-slave.c | 14 +++++++++++++- - 1 files changed, 13 insertions(+), 1 deletions(-) - -diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c -index 3251ec2..826612e 100644 ---- a/daemon/gdm-factory-slave.c -+++ b/daemon/gdm-factory-slave.c -@@ -380,8 +380,16 @@ on_session_relay_connected (GdmSessionRelay *session, - GdmFactorySlave *slave) - { - g_debug ("GdmFactorySlave: Relay Connected"); +} + +static void -+on_greeter_start_conversation (GdmGreeterServer *greeter_server, -+ const char *service_name, -+ GdmFactorySlave *slave) ++grab_default_button_for_task (GdmTask *task) +{ -+ g_debug ("GdmFactorySlave: start conversation"); ++ GtkActionGroup *actions; ++ GtkAction *action; ++ GSList *proxies, *node; ++ ++ actions = gdm_conversation_get_actions (GDM_CONVERSATION (task)); ++ ++ if (actions == NULL) { ++ return; ++ } ++ ++ action = gtk_action_group_get_action (actions, GDM_CONVERSATION_DEFAULT_ACTION); ++ g_object_unref (actions); ++ ++ if (action == NULL) { ++ return; ++ } ++ ++ proxies = gtk_action_get_proxies (action); ++ for (node = proxies; node != NULL; node = node->next) { ++ GtkWidget *widget; ++ ++ widget = GTK_WIDGET (node->data); ++ ++ if (GTK_WIDGET_CAN_DEFAULT (widget) && ++ GTK_WIDGET_VISIBLE (widget)) { ++ gtk_widget_grab_default (widget); ++ break; ++ } ++ } -- gdm_session_start_conversation (GDM_SESSION (slave->priv->session), "gdm"); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), service_name); +- _gdm_greeter_login_window_set_interactive (login_window, TRUE); ++} ++ ++static void ++show_task_actions (GdmTask *task) ++{ ++ GtkActionGroup *actions; ++ ++ actions = gdm_conversation_get_actions (GDM_CONVERSATION (task)); ++ ++ if (actions != NULL) { ++ gtk_action_group_set_sensitive (actions, TRUE); ++ gtk_action_group_set_visible (actions, TRUE); ++ g_object_unref (actions); ++ } } static void -@@ -510,6 +518,10 @@ run_greeter (GdmFactorySlave *slave) +@@ -413,6 +485,7 @@ set_log_in_button_mode (GdmGreeterLoginW + int mode) + { + GtkWidget *button; ++ GdmTask *task; - slave->priv->greeter_server = gdm_greeter_server_new (display_id); - g_signal_connect (slave->priv->greeter_server, -+ "start-conversation", -+ G_CALLBACK (on_greeter_start_conversation), -+ slave); -+ g_signal_connect (slave->priv->greeter_server, - "begin-verification", - G_CALLBACK (on_greeter_begin_verification), - slave); --- -1.6.1 - - -From d55500e9fa9c88a917b263f7477fb29ac4f727e2 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 30 Jan 2009 23:57:31 -0500 -Subject: [PATCH 15/65] Add limited support for multiple pam stacks - -This hard codes 3 pam stacks and doesn't handle -switching between them very well yet. ---- - gui/simple-greeter/Makefile.am | 4 + - gui/simple-greeter/gdm-greeter-login-window.c | 84 ++++++++-- - gui/simple-greeter/gdm-greeter-login-window.glade | 39 ++++- - gui/simple-greeter/gdm-greeter-login-window.h | 11 +- - gui/simple-greeter/gdm-greeter-session.c | 30 +++- - gui/simple-greeter/gdm-task-list.c | 201 +++++++++++++++++++++ - gui/simple-greeter/gdm-task-list.h | 61 +++++++ - 7 files changed, 402 insertions(+), 28 deletions(-) - create mode 100644 gui/simple-greeter/gdm-task-list.c - create mode 100644 gui/simple-greeter/gdm-task-list.h - -diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am -index 9b5834d..e2d3996 100644 ---- a/gui/simple-greeter/Makefile.am -+++ b/gui/simple-greeter/Makefile.am -@@ -83,6 +83,8 @@ test_greeter_login_window_SOURCES = \ - gdm-user-chooser-widget.c \ - gdm-user-chooser-dialog.h \ - gdm-user-chooser-dialog.c \ -+ gdm-task-list.h \ -+ gdm-task-list.c \ - $(NULL) + button = glade_xml_get_widget (login_window->priv->xml, "log-in-button"); + gtk_widget_grab_default (button); +@@ -425,14 +498,27 @@ set_log_in_button_mode (GdmGreeterLoginW - test_greeter_login_window_LDADD = \ -@@ -316,6 +318,8 @@ gdm_simple_greeter_SOURCES = \ - gdm-session-option-widget.c \ - gdm-user-chooser-widget.h \ - gdm-user-chooser-widget.c \ -+ gdm-task-list.h \ -+ gdm-task-list.c \ - $(NULL) + switch (mode) { + case LOGIN_BUTTON_HIDDEN: ++ task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); ++ if (task != NULL) { ++ hide_task_actions (task); ++ g_object_unref (task); ++ } ++ + gtk_widget_hide (button); + break; + case LOGIN_BUTTON_ANSWER_QUERY: +- login_window->priv->login_button_handler_id = g_signal_connect (button, "clicked", G_CALLBACK (on_login_button_clicked_answer_query), login_window); +- gtk_widget_show (button); ++ task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); ++ if (task != NULL) { ++ show_task_actions (task); ++ grab_default_button_for_task (task); ++ g_object_unref (task); ++ } ++ ++ gtk_widget_hide (button); + break; + case LOGIN_BUTTON_TIMED_LOGIN: + login_window->priv->login_button_handler_id = g_signal_connect (button, "clicked", G_CALLBACK (on_login_button_clicked_timed_login), login_window); ++ + gtk_widget_show (button); + break; + default: +@@ -528,6 +614,7 @@ switch_mode (GdmGreeterLoginWindow *logi + GtkWidget *box; + gboolean show_restart_buttons; + gboolean show_suspend_button; ++ int number_of_tasks; - gdm_simple_greeter_LDADD = \ -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index a3e1411..f3daccb 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -60,12 +60,16 @@ - #include - #endif + show_restart_buttons = get_show_restart_buttons (login_window); + show_suspend_button = can_suspend (login_window); +@@ -557,7 +644,8 @@ switch_mode (GdmGreeterLoginWindow *logi + show_widget (login_window, "disconnect-button", + ! login_window->priv->display_is_local); -+#include "gdm-marshal.h" +- show_widget (login_window, "auth-input-box", FALSE); ++ show_widget (login_window, "auth-page-box", FALSE); ++ show_widget (login_window, "conversation-list", FALSE); + + add_sensitize_power_buttons_timeout (login_window); + sensitize_widget (login_window, "shutdown-button", FALSE); +@@ -576,6 +664,11 @@ switch_mode (GdmGreeterLoginWindow *logi + show_widget (login_window, "restart-button", FALSE); + show_widget (login_window, "suspend-button", FALSE); + show_widget (login_window, "disconnect-button", FALSE); ++ show_widget (login_window, "auth-page-box", TRUE); + - #include "gdm-settings-client.h" - #include "gdm-settings-keys.h" - #include "gdm-profile.h" ++ number_of_tasks = gdm_task_list_get_number_of_tasks (GDM_TASK_LIST (login_window->priv->conversation_list)); ++ show_widget (login_window, "conversation-list", number_of_tasks > 1); ++ + default_name = "log-in-button"; + break; + default: +@@ -655,25 +748,54 @@ do_suspend (GdmGreeterLoginWindow *login + g_object_unref (proxy); + } -+#include "gdm-greeter-client.h" - #include "gdm-greeter-login-window.h" - #include "gdm-user-chooser-widget.h" -+#include "gdm-task-list.h" +-static void +-delete_entry_text (GtkWidget *entry) ++static gboolean ++task_has_service_name (GdmTaskList *task_list, ++ GdmTask *task, ++ const char *service_name) ++{ ++ char *task_service_name; ++ gboolean has_service_name; ++ ++ task_service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (task)); ++ ++ has_service_name = strcmp (service_name, task_service_name) == 0; ++ g_free (task_service_name); ++ ++ return has_service_name; ++} ++ ++GdmTask * ++find_task_with_service_name (GdmGreeterLoginWindow *login_window, ++ const char *service_name) ++{ ++ GdmTask *task; ++ ++ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ (GdmTaskListForeachFunc) ++ task_has_service_name, ++ (gpointer) service_name); ++ ++ return task; ++} ++ ++static gboolean ++reset_task (GdmTaskList *task_list, ++ GdmTask *task, ++ GdmGreeterLoginWindow *login_window) + { +- const char *typed_text; +- char *null_text; ++ char *name; - #ifdef HAVE_PAM - #include -@@ -111,6 +115,7 @@ struct GdmGreeterLoginWindowPrivate +- /* try to scrub out any secret info */ +- typed_text = gtk_entry_get_text (GTK_ENTRY (entry)); +- null_text = g_strnfill (strlen (typed_text) + 1, '\b'); +- gtk_entry_set_text (GTK_ENTRY (entry), null_text); +- gtk_entry_set_text (GTK_ENTRY (entry), ""); ++ name = gdm_task_get_name (task); ++ g_debug ("Resetting task '%s'", name); ++ g_free (name); ++ ++ gdm_conversation_reset (GDM_CONVERSATION (task)); ++ return FALSE; + } + + static void + reset_dialog (GdmGreeterLoginWindow *login_window) { - GladeXML *xml; - GtkWidget *user_chooser; -+ GtkWidget *conversation_list; - GtkWidget *auth_banner_label; - guint display_is_local : 1; - guint is_interactive : 1; -@@ -139,6 +144,7 @@ enum { - }; +- GtkWidget *entry; +- GtkWidget *label; +- + g_debug ("GdmGreeterLoginWindow: Resetting dialog"); + set_busy (login_window); + set_sensitive (login_window, FALSE); +@@ -697,18 +819,15 @@ reset_dialog (GdmGreeterLoginWindow *log + login_window->priv->start_session_handler_id = 0; + } - enum { -+ START_CONVERSATION, - BEGIN_AUTO_LOGIN, - BEGIN_VERIFICATION, - BEGIN_VERIFICATION_FOR_USER, -@@ -395,7 +401,7 @@ on_login_button_clicked_answer_query (GtkButton *button, - text = gtk_entry_get_text (GTK_ENTRY (entry)); +- entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); ++ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ (GdmTaskListForeachFunc) ++ reset_task, ++ login_window); - _gdm_greeter_login_window_set_interactive (login_window, TRUE); -- g_signal_emit (login_window, signals[QUERY_ANSWER], 0, text); -+ g_signal_emit (login_window, signals[QUERY_ANSWER], 0, "gdm", text); +- delete_entry_text (entry); +- +- gtk_entry_set_visibility (GTK_ENTRY (entry), TRUE); + set_message (login_window, ""); +- +- label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label"); +- gtk_label_set_text (GTK_LABEL (label), ""); +- + switch_mode (login_window, MODE_SELECTION); + ++ gtk_widget_set_sensitive (login_window->priv->conversation_list, TRUE); + set_sensitive (login_window, TRUE); + set_ready (login_window); + set_focus (GDM_GREETER_LOGIN_WINDOW (login_window)); +@@ -716,21 +835,61 @@ reset_dialog (GdmGreeterLoginWindow *log } static void -@@ -751,26 +757,32 @@ gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window) +-do_cancel (GdmGreeterLoginWindow *login_window) ++restart_conversations (GdmGreeterLoginWindow *login_window) + { +- /* need to wait for response from backend */ +- set_message (login_window, _("Cancelling...")); + set_busy (login_window); + set_sensitive (login_window, FALSE); + g_signal_emit (login_window, signals[CANCELLED], 0); + } ++static void ++do_cancel (GdmGreeterLoginWindow *login_window) ++{ ++ /* need to wait for response from backend */ ++ set_message (login_window, _("Cancelling...")); ++ restart_conversations (login_window); ++} ++ ++static void ++on_can_set_task_ready (GtkWidget *user_chooser, ++ GdmTask *task) ++{ ++ g_signal_handlers_disconnect_by_func (user_chooser, ++ on_can_set_task_ready, ++ task); ++ gdm_conversation_set_ready (GDM_CONVERSATION (task)); ++ g_object_unref (task); ++} ++ ++static void ++set_task_ready_when_loaded (GdmGreeterLoginWindow *login_window, ++ GdmTask *task) ++{ ++ g_signal_connect (login_window->priv->user_chooser, ++ "loaded", ++ G_CALLBACK (on_can_set_task_ready), ++ g_object_ref (task)); ++} ++ gboolean - gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text) +-gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window) ++gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, ++ const char *service_name) { ++ GdmTask *task; ++ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - g_debug ("GdmGreeterLoginWindow: info: %s", text); - -- set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); -+ if (strcmp (service_name, gdm_task_list_get_active_task (login_window->priv->conversation_list)) == 0) { -+ set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); +- reset_dialog (login_window); ++ task = find_task_with_service_name (login_window, service_name); ++ ++ if (task != NULL) { ++ if (gdm_chooser_widget_is_loaded (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser))) { ++ gdm_conversation_set_ready (GDM_CONVERSATION (task)); ++ } else { ++ ++ set_task_ready_when_loaded (login_window, task); ++ } ++ g_object_unref (task); + } - return TRUE; + set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE); + set_ready (GDM_GREETER_LOGIN_WINDOW (login_window)); +@@ -740,37 +899,112 @@ gdm_greeter_login_window_ready (GdmGreet } gboolean - gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text) +-gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window) ++gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_window, ++ const char *service_name) { ++ GdmTask *task; ++ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - g_debug ("GdmGreeterLoginWindow: problem: %s", text); ++ g_debug ("GdmGreeterLoginWindow: conversation '%s' has stopped", service_name); ++ ++ task = find_task_with_service_name (login_window, service_name); ++ ++ if (task != NULL) { ++ gdm_conversation_reset (GDM_CONVERSATION (task)); ++ g_object_unref (task); ++ } ++ ++ /* If every conversation has failed, then just start over. ++ */ ++ task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); ++ ++ if (!gdm_task_is_enabled (task)) { ++ g_debug ("GdmGreeterLoginWindow: No conversations left, starting over"); ++ restart_conversations (login_window); ++ } ++ g_object_unref (task); ++ ++ return TRUE; ++} ++ ++static gboolean ++restart_task_conversation (GdmTaskList *task_list, ++ GdmTask *task, ++ GdmGreeterLoginWindow *login_window) ++{ ++ char *service_name; ++ ++ service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (task)); ++ if (service_name != NULL) { ++ char *name; ++ ++ name = gdm_task_get_name (task); ++ g_debug ("GdmGreeterLoginWindow: restarting '%s' conversation", name); ++ g_free (name); ++ ++ g_signal_emit (login_window, signals[START_CONVERSATION], 0, service_name); ++ g_free (service_name); ++ } ++ ++ return FALSE; ++} ++ ++gboolean ++gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window) ++{ ++ g_debug ("GdmGreeterLoginWindow: window reset"); ++ ++ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); + reset_dialog (GDM_GREETER_LOGIN_WINDOW (login_window)); + ++ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ (GdmTaskListForeachFunc) ++ restart_task_conversation, ++ login_window); ++ + return TRUE; + } + + gboolean + gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text) + { +- g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); ++ GdmTask *task; + ++ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); + g_debug ("GdmGreeterLoginWindow: info: %s", text); + +- set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); ++ task = find_task_with_service_name (login_window, service_name); ++ ++ if (task != NULL) { ++ gdm_conversation_set_message (GDM_CONVERSATION (task), ++ text); ++ g_object_unref (task); ++ } + + return TRUE; + } + + gboolean + gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text) + { +- g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); ++ GdmTask *task; + ++ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); + g_debug ("GdmGreeterLoginWindow: problem: %s", text); - set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); -+ if (strcmp (service_name, gdm_task_list_get_active_task (login_window->priv->conversation_list)) == 0) { -+ set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); ++ task = find_task_with_service_name (login_window, service_name); ++ ++ if (task != NULL) { ++ gdm_conversation_set_message (GDM_CONVERSATION (task), ++ text); ++ g_object_unref (task); + } ++ gdk_window_beep (GTK_WIDGET (login_window)->window); return TRUE; -@@ -846,6 +858,7 @@ gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_ +@@ -808,11 +1042,21 @@ gdm_greeter_login_window_request_timed_l + } + + static void +-gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_window) ++on_ready_to_start_session (GdmGreeterLoginWindow *login_window, ++ GParamSpec *param_spec, ++ char *service_name) ++{ ++ gdm_greeter_login_window_start_session_when_ready (login_window, service_name); ++ g_free (service_name); ++} ++ ++static void ++gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_window, ++ const char *service_name) + { + if (login_window->priv->is_interactive) { + g_debug ("GdmGreeterLoginWindow: starting session"); +- g_signal_emit (login_window, signals[START_SESSION], 0); ++ g_signal_emit (login_window, signals[START_SESSION], 0, service_name); + } else { + g_debug ("GdmGreeterLoginWindow: not starting session since " + "user hasn't had an opportunity to pick language " +@@ -822,8 +1066,8 @@ gdm_greeter_login_window_start_session_w + */ + login_window->priv->start_session_handler_id = + g_signal_connect (login_window, "notify::is-interactive", +- G_CALLBACK (gdm_greeter_login_window_start_session_when_ready), +- NULL); ++ G_CALLBACK (on_ready_to_start_session), ++ g_strdup (service_name)); + + /* FIXME: If the user wasn't asked any questions by pam but + * pam still authorized them (passwd -d, or the questions got +@@ -846,24 +1090,25 @@ gdm_greeter_login_window_start_session_w gboolean gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, + const char *service_name, const char *text) { - GtkWidget *entry; -@@ -853,6 +866,10 @@ gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, +- GtkWidget *entry; +- GtkWidget *label; ++ GdmTask *task; g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); -+ if (strcmp (service_name, gdm_task_list_get_active_task (login_window->priv->conversation_list)) != 0) { -+ return TRUE; -+ } -+ g_debug ("GdmGreeterLoginWindow: info query: %s", text); - entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); -@@ -875,6 +892,7 @@ gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, +- entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); +- delete_entry_text (entry); +- gtk_entry_set_visibility (GTK_ENTRY (entry), TRUE); +- set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY); + +- label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label"); +- gtk_label_set_text (GTK_LABEL (label), text); ++ task = find_task_with_service_name (login_window, service_name); ++ ++ if (task != NULL) { ++ gdm_conversation_ask_question (GDM_CONVERSATION (task), ++ text); ++ g_object_unref (task); ++ } + +- show_widget (login_window, "auth-input-box", TRUE); ++ set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY); + set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE); + set_ready (GDM_GREETER_LOGIN_WINDOW (login_window)); + set_focus (GDM_GREETER_LOGIN_WINDOW (login_window)); +@@ -875,22 +1120,23 @@ gdm_greeter_login_window_info_query (Gdm gboolean gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, + const char *service_name, const char *text) { - GtkWidget *entry; -@@ -1347,7 +1365,10 @@ on_user_chosen (GdmUserChooserWidget *user_chooser, - 0, user_name); - - if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) { -- g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0); -+ const char *service_name; -+ -+ service_name = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); -+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, service_name); - } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_GUEST) == 0) { - /* FIXME: handle guest account stuff */ - } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_AUTO) == 0) { -@@ -1361,7 +1382,10 @@ on_user_chosen (GdmUserChooserWidget *user_chooser, - set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); - set_message (login_window, _("Select language and click Log In")); - } else { -- g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, user_name); -+ const char *service_name; +- GtkWidget *entry; +- GtkWidget *label; + -+ service_name = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); -+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, service_name, user_name); - } ++ GdmTask *task; - switch_mode (login_window, MODE_AUTHENTICATION); -@@ -1505,6 +1529,21 @@ create_computer_info (GdmGreeterLoginWindow *login_window) - #define INVISIBLE_CHAR_BULLET 0x2022 - #define INVISIBLE_CHAR_NONE 0 + g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); -+static void -+on_task_activated (GdmGreeterLoginWindow *login_window, -+ const char *name) +- entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); +- delete_entry_text (entry); +- gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE); +- set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY); ++ task = find_task_with_service_name (login_window, service_name); + +- label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label"); +- gtk_label_set_text (GTK_LABEL (label), text); ++ if (task != NULL) { ++ gdm_conversation_ask_secret (GDM_CONVERSATION (task), ++ text); ++ g_object_unref (task); ++ } + +- show_widget (login_window, "auth-input-box", TRUE); ++ set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY); + set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE); + set_ready (GDM_GREETER_LOGIN_WINDOW (login_window)); + set_focus (GDM_GREETER_LOGIN_WINDOW (login_window)); +@@ -901,13 +1147,16 @@ gdm_greeter_login_window_secret_info_que + } + + void +-gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window) ++gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window, ++ const char *service_name) + { + g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); + +- g_debug ("GdmGreeterLoginWindow: user now authorized"); ++ g_debug ("GdmGreeterLoginWindow: user now authorized via service %s", ++ service_name); + +- gdm_greeter_login_window_start_session_when_ready (login_window); ++ gdm_greeter_login_window_start_session_when_ready (login_window, ++ service_name); + } + + static void +@@ -1330,43 +1579,180 @@ on_users_loaded (GdmUserChooserWidget * + gdm_chooser_widget_activate_if_one_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser)); + } + ++static gboolean ++begin_task_verification (GdmTaskList *task_list, ++ GdmTask *task, ++ GdmGreeterLoginWindow *login_window) +{ -+ g_debug ("GdmGreeterLoginWindow: starting conversation with '%s'", name); -+ g_signal_emit (login_window, signals[START_CONVERSATION], 0, name); ++ char *service_name; ++ ++ service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (task)); ++ if (service_name != NULL) { ++ g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, service_name); ++ g_free (service_name); ++ } ++ ++ return FALSE; +} + -+static void -+on_task_deactivated (GdmGreeterLoginWindow *login_window, -+ const char *name) + static void +-on_user_chosen (GdmUserChooserWidget *user_chooser, +- GdmGreeterLoginWindow *login_window) ++begin_verification (GdmGreeterLoginWindow *login_window) +{ -+ g_debug ("GdmGreeterLoginWindow: conversation '%s' now in background", name); ++ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ (GdmTaskListForeachFunc) ++ begin_task_verification, ++ login_window); ++ ++ switch_mode (login_window, MODE_AUTHENTICATION); +} + - static GtkWidget * - custom_widget_constructor (GladeXML *xml, - char *func_name, -@@ -1527,6 +1566,8 @@ custom_widget_constructor (GladeXML *xml, ++static gboolean ++begin_task_verification_for_selected_user (GdmTaskList *task_list, ++ GdmTask *task, ++ GdmGreeterLoginWindow *login_window) + { + char *user_name; ++ char *service_name; - if (strcmp (name, "user-chooser") == 0) { - widget = gdm_user_chooser_widget_new (); -+ } else if (strcmp (name, "conversation-list") == 0) { -+ widget = gdm_task_list_new (); - } + user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser)); +- g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); + + if (user_name == NULL) { +- return; ++ return TRUE; ++ } ++ ++ service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (task)); ++ if (service_name != NULL) { ++ g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, service_name, user_name); ++ g_free (service_name); + } + ++ g_free (user_name); ++ return FALSE; ++} ++ ++static void ++begin_verification_for_selected_user (GdmGreeterLoginWindow *login_window) ++{ ++ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ (GdmTaskListForeachFunc) ++ begin_task_verification_for_selected_user, ++ login_window); ++} ++ ++static void ++on_user_chosen (GdmGreeterLoginWindow *login_window, ++ const char *user_name) ++{ ++ g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); ++ + g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED], + 0, user_name); + +- if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) { +- g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0); +- } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_GUEST) == 0) { +- /* FIXME: handle guest account stuff */ +- } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_AUTO) == 0) { +- g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, +- login_window->priv->timed_login_username); +- +- login_window->priv->timed_login_enabled = TRUE; +- restart_timed_login_timeout (login_window); +- +- /* just wait for the user to select language and stuff */ +- set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); +- set_message (login_window, _("Select language and click Log In")); +- } else { +- g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, user_name); ++ begin_verification_for_selected_user (login_window); ++ ++ switch_mode (login_window, MODE_AUTHENTICATION); ++} ++ ++static void ++begin_auto_login (GdmGreeterLoginWindow *login_window) ++{ ++ g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, ++ login_window->priv->timed_login_username); ++ ++ login_window->priv->timed_login_enabled = TRUE; ++ restart_timed_login_timeout (login_window); ++ ++ /* just wait for the user to select language and stuff */ ++ set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); ++ set_message (login_window, _("Select language and click Log In")); ++ ++ switch_mode (login_window, MODE_AUTHENTICATION); ++} ++ ++static gboolean ++reset_task_if_not_given (GdmTaskList *task_list, ++ GdmTask *task, ++ GdmTask *given_task) ++{ ++ if (task == given_task) { ++ return FALSE; + } + ++ gdm_conversation_reset (GDM_CONVERSATION (task)); ++ return FALSE; ++} ++ ++static void ++reset_every_task_but_given_task (GdmGreeterLoginWindow *login_window, ++ GdmTask *task) ++{ ++ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ (GdmTaskListForeachFunc) ++ reset_task_if_not_given, ++ task); ++} ++ ++static void ++begin_single_service_verification (GdmGreeterLoginWindow *login_window, ++ const char *service_name) ++{ ++ GdmTask *task; ++ ++ task = find_task_with_service_name (login_window, service_name); ++ ++ if (task == NULL) { ++ g_debug ("GdmGreeterLoginWindow: %s has no task associated with it", service_name); ++ return; ++ } ++ g_debug ("GdmGreeterLoginWindow: Beginning %s auth conversation", service_name); ++ ++ /* FIXME: we should probably give the plugin more say for ++ * what happens here. ++ */ ++ g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, service_name); ++ + switch_mode (login_window, MODE_AUTHENTICATION); ++ gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), task); + +- g_free (user_name); ++ reset_every_task_but_given_task (login_window, task); ++ ++ g_object_unref (task); ++} ++ ++static void ++on_user_chooser_activated (GdmUserChooserWidget *user_chooser, ++ GdmGreeterLoginWindow *login_window) ++{ ++ char *user_name; ++ char *item_id; ++ ++ user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser)); ++ ++ if (user_name != NULL) { ++ g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); ++ on_user_chosen (login_window, user_name); ++ g_free (user_name); ++ return; ++ } ++ ++ item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (user_chooser)); ++ g_debug ("GdmGreeterLoginWindow: item chosen '%s'", item_id); ++ ++ if (strcmp (item_id, GDM_USER_CHOOSER_USER_OTHER) == 0) { ++ g_debug ("GdmGreeterLoginWindow: Starting all auth conversations"); ++ g_free (item_id); ++ ++ begin_verification (login_window); ++ } else if (strcmp (item_id, GDM_USER_CHOOSER_USER_AUTO) == 0) { ++ g_debug ("GdmGreeterLoginWindow: Starting auto login"); ++ g_free (item_id); ++ ++ begin_auto_login (login_window); ++ } else { ++ ++ begin_single_service_verification (login_window, item_id); ++ g_free (item_id); ++ } + } + + static void +@@ -1505,6 +1891,69 @@ create_computer_info (GdmGreeterLoginWin + #define INVISIBLE_CHAR_BULLET 0x2022 + #define INVISIBLE_CHAR_NONE 0 + ++static void ++on_task_activated (GdmGreeterLoginWindow *login_window, ++ GdmTask *task) ++{ ++ GtkWidget *container; ++ char *name; ++ ++ name = gdm_task_get_name (task); ++ g_debug ("GdmGreeterLoginWindow: task '%s' activated", name); ++ g_free (name); ++ ++ container = g_object_get_data (G_OBJECT (task), ++ "gdm-greeter-login-window-page-container"); ++ ++ if (container == NULL) { ++ GtkWidget *page; ++ ++ container = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); ++ gtk_container_add (GTK_CONTAINER (login_window->priv->auth_page_box), ++ container); ++ ++ page = gdm_conversation_get_page (GDM_CONVERSATION (task)); ++ if (page != NULL) { ++ gtk_container_add (GTK_CONTAINER (container), page); ++ gtk_widget_show (page); ++ } ++ g_object_set_data (G_OBJECT (task), ++ "gdm-greeter-login-window-page-container", ++ container); ++ } ++ ++ gtk_widget_show (container); ++ set_log_in_button_mode (login_window, login_window->priv->dialog_mode); ++} ++ ++static void ++on_task_deactivated (GdmGreeterLoginWindow *login_window, ++ GdmTask *task) ++{ ++ GtkWidget *container; ++ char *name; ++ GtkActionGroup *actions; ++ ++ name = gdm_task_get_name (task); ++ g_debug ("GdmGreeterLoginWindow: task '%s' now in background", name); ++ g_free (name); ++ ++ container = g_object_get_data (G_OBJECT (task), ++ "gdm-greeter-login-window-page-container"); ++ ++ if (container != NULL) { ++ gtk_widget_hide (container); ++ } ++ ++ actions = gdm_conversation_get_actions (GDM_CONVERSATION (task)); ++ ++ if (actions != NULL) { ++ gtk_action_group_set_sensitive (actions, FALSE); ++ gtk_action_group_set_visible (actions, FALSE); ++ g_object_unref (actions); ++ } ++} ++ + static GtkWidget * + custom_widget_constructor (GladeXML *xml, + char *func_name, +@@ -1527,6 +1976,8 @@ custom_widget_constructor (GladeXML + + if (strcmp (name, "user-chooser") == 0) { + widget = gdm_user_chooser_widget_new (); ++ } else if (strcmp (name, "conversation-list") == 0) { ++ widget = gdm_task_list_new (); + } gdm_profile_end (NULL); -@@ -1600,6 +1641,18 @@ load_theme (GdmGreeterLoginWindow *login_window) +@@ -1537,7 +1988,6 @@ custom_widget_constructor (GladeXML + static void + load_theme (GdmGreeterLoginWindow *login_window) + { +- GtkWidget *entry; + GtkWidget *button; + GtkWidget *box; + GtkWidget *image; +@@ -1591,7 +2041,7 @@ load_theme (GdmGreeterLoginWindow *login + login_window); + g_signal_connect (login_window->priv->user_chooser, + "activated", +- G_CALLBACK (on_user_chosen), ++ G_CALLBACK (on_user_chooser_activated), + login_window); + g_signal_connect (login_window->priv->user_chooser, + "deactivated", +@@ -1600,8 +2050,20 @@ load_theme (GdmGreeterLoginWindow *login gtk_widget_show (login_window->priv->user_chooser); @@ -6511,17 +6574,34 @@ index a3e1411..f3daccb 100644 + "deactivated", + G_CALLBACK (on_task_deactivated), + login_window); -+ gtk_widget_show (login_window->priv->conversation_list); + login_window->priv->auth_banner_label = glade_xml_get_widget (login_window->priv->xml, "auth-banner-label"); /*make_label_small_italic (login_window->priv->auth_banner_label);*/ ++ login_window->priv->auth_page_box = glade_xml_get_widget (login_window->priv->xml, "auth-page-box"); -@@ -1757,6 +1810,15 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) - widget_class->key_press_event = gdm_greeter_login_window_key_press_event; - widget_class->size_request = gdm_greeter_login_window_size_request; - -+ signals [START_CONVERSATION] = -+ g_signal_new ("start-conversation", + button = glade_xml_get_widget (login_window->priv->xml, "suspend-button"); + g_signal_connect (button, "clicked", G_CALLBACK (suspend_button_clicked), login_window); +@@ -1617,14 +2079,6 @@ load_theme (GdmGreeterLoginWindow *login + button = glade_xml_get_widget (login_window->priv->xml, "shutdown-button"); + g_signal_connect (button, "clicked", G_CALLBACK (shutdown_button_clicked), login_window); + +- entry = glade_xml_get_widget (login_window->priv->xml, "auth-prompt-entry"); +- /* Only change the invisible character if it '*' otherwise assume it is OK */ +- if ('*' == gtk_entry_get_invisible_char (GTK_ENTRY (entry))) { +- gunichar invisible_char; +- invisible_char = INVISIBLE_CHAR_BLACK_CIRCLE; +- gtk_entry_set_invisible_char (GTK_ENTRY (entry), invisible_char); +- } +- + create_computer_info (login_window); + + box = glade_xml_get_widget (login_window->priv->xml, "computer-info-event-box"); +@@ -1757,6 +2211,15 @@ gdm_greeter_login_window_class_init (Gdm + widget_class->key_press_event = gdm_greeter_login_window_key_press_event; + widget_class->size_request = gdm_greeter_login_window_size_request; + ++ signals [START_CONVERSATION] = ++ g_signal_new ("start-conversation", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, start_conversation), @@ -6532,7 +6612,7 @@ index a3e1411..f3daccb 100644 signals [BEGIN_AUTO_LOGIN] = g_signal_new ("begin-auto-login", G_TYPE_FROM_CLASS (object_class), -@@ -1773,9 +1835,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) +@@ -1773,9 +2236,9 @@ gdm_greeter_login_window_class_init (Gdm G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, begin_verification), NULL, NULL, @@ -6544,7 +6624,7 @@ index a3e1411..f3daccb 100644 signals [BEGIN_VERIFICATION_FOR_USER] = g_signal_new ("begin-verification-for-user", G_TYPE_FROM_CLASS (object_class), -@@ -1783,9 +1845,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) +@@ -1783,9 +2246,9 @@ gdm_greeter_login_window_class_init (Gdm G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, begin_verification_for_user), NULL, NULL, @@ -6556,7 +6636,7 @@ index a3e1411..f3daccb 100644 signals [QUERY_ANSWER] = g_signal_new ("query-answer", G_TYPE_FROM_CLASS (object_class), -@@ -1793,9 +1855,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) +@@ -1793,9 +2256,9 @@ gdm_greeter_login_window_class_init (Gdm G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, query_answer), NULL, NULL, @@ -6568,3561 +6648,788 @@ index a3e1411..f3daccb 100644 signals [USER_SELECTED] = g_signal_new ("user-selected", G_TYPE_FROM_CLASS (object_class), -diff --git a/gui/simple-greeter/gdm-greeter-login-window.glade b/gui/simple-greeter/gdm-greeter-login-window.glade -index 0fb0ad8..a3ae5ba 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.glade -+++ b/gui/simple-greeter/gdm-greeter-login-window.glade -@@ -654,11 +654,38 @@ - 10 - - -- -+ - True -- 0 -- 0 -- Tue, 18 Nov 2008 21:55:38 GMT -+ False -+ 0 -+ -+ -+ -+ True -+ 0 -+ 0 -+ Tue, 18 Nov 2008 21:55:38 GMT -+ -+ -+ 0 -+ True -+ True -+ -+ -+ -+ -+ -+ True -+ 0 -+ 0 -+ Fri, 30 Jan 2009 16:03:30 GMT -+ -+ -+ 0 -+ False -+ False -+ -+ - - - 0 -@@ -779,10 +806,6 @@ - - - -- -- -- -- - - - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.h b/gui/simple-greeter/gdm-greeter-login-window.h -index 817d0a2..559b26b 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.h -+++ b/gui/simple-greeter/gdm-greeter-login-window.h -@@ -46,12 +46,17 @@ typedef struct - GtkWindowClass parent_class; - - /* signals */ -+ void (* start_conversation) (GdmGreeterLoginWindow *login_window, -+ const char *service_name); - void (* begin_auto_login) (GdmGreeterLoginWindow *login_window, - const char *username); -- void (* begin_verification) (GdmGreeterLoginWindow *login_window); -+ void (* begin_verification) (GdmGreeterLoginWindow *login_window, -+ const char *service_name); - void (* begin_verification_for_user) (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *username); - void (* query_answer) (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text); - void (* user_selected) (GdmGreeterLoginWindow *login_window, - const char *text); -@@ -68,12 +73,16 @@ GtkWidget * gdm_greeter_login_window_new (gboolean displa - gboolean gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window); - gboolean gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window); - gboolean gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text); - gboolean gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text); - gboolean gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text); - gboolean gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text); - - void gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, -diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c -index ea9e6d1..79f367c 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -70,7 +70,7 @@ on_info (GdmGreeterClient *client, - { - g_debug ("GdmGreeterSession: Info: %s", text); - -- gdm_greeter_login_window_info (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), text); -+ gdm_greeter_login_window_info (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name, text); - } - - static void -@@ -81,7 +81,7 @@ on_problem (GdmGreeterClient *client, - { - g_debug ("GdmGreeterSession: Problem: %s", text); - -- gdm_greeter_login_window_problem (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), text); -+ gdm_greeter_login_window_problem (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name, text); - } - - static void -@@ -168,7 +168,7 @@ on_info_query (GdmGreeterClient *client, - { - g_debug ("GdmGreeterSession: Info query: %s", text); - -- gdm_greeter_login_window_info_query (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), text); -+ gdm_greeter_login_window_info_query (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name, text); - } - - static void -@@ -179,10 +179,18 @@ on_secret_info_query (GdmGreeterClient *client, - { - g_debug ("GdmGreeterSession: Secret info query: %s", text); +@@ -1833,9 +2296,9 @@ gdm_greeter_login_window_class_init (Gdm + G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, start_session), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); -- gdm_greeter_login_window_secret_info_query (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), text); -+ gdm_greeter_login_window_secret_info_query (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name, text); + g_object_class_install_property (object_class, + PROP_DISPLAY_IS_LOCAL, +@@ -1888,6 +2351,232 @@ on_gconf_key_changed (GConfClient + } } - static void -+on_start_conversation (GdmGreeterLoginWindow *login_window, -+ const char *service_name, -+ GdmGreeterSession *session) -+{ -+ gdm_greeter_client_call_start_conversation (session->priv->client, -+ service_name); -+} +static void - on_begin_auto_login (GdmGreeterLoginWindow *login_window, - const char *username, - GdmGreeterSession *session) -@@ -193,29 +201,32 @@ on_begin_auto_login (GdmGreeterLoginWindow *login_window, - - static void - on_begin_verification (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - GdmGreeterSession *session) - { - gdm_greeter_client_call_begin_verification (session->priv->client, -- "gdm"); -+ service_name); - } - - static void - on_begin_verification_for_user (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *username, - GdmGreeterSession *session) - { - gdm_greeter_client_call_begin_verification_for_user (session->priv->client, -- "gdm", -+ service_name, - username); - } - - static void - on_query_answer (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { - gdm_greeter_client_call_answer_query (session->priv->client, -- "gdm", -+ service_name, - text); - } - -@@ -330,7 +341,10 @@ toggle_login_window (GdmGreeterSession *session, - is_local = gdm_greeter_client_get_display_is_local (session->priv->client); - g_debug ("GdmGreeterSession: Starting a login window local:%d", is_local); - session->priv->login_window = gdm_greeter_login_window_new (is_local); -- -+ g_signal_connect (session->priv->login_window, -+ "start-conversation", -+ G_CALLBACK (on_start_conversation), -+ session); - g_signal_connect (session->priv->login_window, - "begin-auto-login", - G_CALLBACK (on_begin_auto_login), -diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c -new file mode 100644 -index 0000000..d522858 ---- /dev/null -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -0,0 +1,201 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written by: Ray Strode -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include ++on_conversation_answer (GdmGreeterLoginWindow *login_window, ++ const char *text, ++ GdmConversation *conversation) ++{ ++ if (text != NULL) { ++ char *service_name; + -+#include "gdm-task-list.h" ++ service_name = gdm_conversation_get_service_name (conversation); ++ if (service_name != NULL) { ++ g_signal_emit (login_window, signals[QUERY_ANSWER], 0, service_name, text); ++ g_free (service_name); ++ } ++ } + -+#define GDM_TASK_LIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_TASK_LIST, GdmTaskListPrivate)) ++ set_sensitive (login_window, TRUE); ++ set_ready (login_window); ++} + -+typedef struct ++static void ++on_conversation_cancel (GdmGreeterLoginWindow *login_window, ++ GdmConversation *conversation) +{ -+ GtkWidget *radio_button; -+ char *name; -+} GdmTask; ++ do_cancel (login_window); ++} + -+struct GdmTaskListPrivate ++static gboolean ++on_conversation_chose_user (GdmGreeterLoginWindow *login_window, ++ const char *username, ++ GdmConversation *conversation) +{ -+ GtkWidget *box; -+ GList *tasks; -+}; ++ if (!gdm_chooser_widget_is_loaded (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser))) { ++ char *name; + -+enum { -+ ACTIVATED = 0, -+ DEACTIVATED, -+ NUMBER_OF_SIGNALS -+}; ++ name = gdm_task_get_name (GDM_TASK (conversation)); ++ g_warning ("Task %s is trying to choose user before list is loaded", name); ++ g_free (name); ++ return FALSE; ++ } + -+static guint signals[NUMBER_OF_SIGNALS]; ++ /* If we're already authenticating then we can't pick a user ++ */ ++ if (login_window->priv->dialog_mode == MODE_AUTHENTICATION) { ++ return FALSE; ++ } + -+static void gdm_task_list_class_init (GdmTaskListClass *klass); -+static void gdm_task_list_init (GdmTaskList *task_list); -+static void gdm_task_list_finalize (GObject *object); ++ if (gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ GDM_TASK (conversation))) { ++ gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), ++ username); ++ } + -+G_DEFINE_TYPE (GdmTaskList, gdm_task_list, GTK_TYPE_ALIGNMENT); ++ return TRUE; ++} + -+static void -+on_task_toggled (GdmTaskList *widget, -+ GtkRadioButton *radio_button) ++void ++gdm_greeter_login_window_remove_extension (GdmGreeterLoginWindow *login_window, ++ GdmGreeterExtension *extension) +{ -+ GdmTask *task; -+ -+ task = g_object_get_data (G_OBJECT (radio_button), "gdm-task"); ++ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); ++ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION (extension)); + -+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_button))) { -+ g_signal_emit (widget, signals[ACTIVATED], 0, task->name); -+ } else { -+ g_signal_emit (widget, signals[DEACTIVATED], 0, task->name); ++ if (!GDM_IS_CONVERSATION (extension)) { ++ return; + } +} + +static void -+add_task (GdmTaskList *task_list, -+ const char *name, -+ const char *icon_name) ++on_button_action_label_changed (GtkWidget *button) +{ -+ GdmTask *task; -+ GtkWidget *image; -+ -+ task = g_slice_new0 (GdmTask); ++ GtkAction *action; ++ char *text; + -+ task->name = g_strdup (name); -+ if (task_list->priv->tasks == NULL) { -+ task->radio_button = gtk_radio_button_new (NULL); -+ } else { -+ task->radio_button = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (((GdmTask *) task_list->priv->tasks->data)->radio_button)); -+ } ++ action = gtk_widget_get_action (button); + -+ g_object_set (task->radio_button, "draw-indicator", FALSE, NULL); -+ g_object_set_data (G_OBJECT (task->radio_button), "gdm-task", task); -+ g_signal_connect_swapped (task->radio_button, -+ "toggled", G_CALLBACK (on_task_toggled), task_list); -+ image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_DND); -+ gtk_widget_show (image); -+ gtk_container_add (GTK_CONTAINER (task->radio_button), image); -+ gtk_widget_show (task->radio_button); -+ gtk_container_add (GTK_CONTAINER (task->radio_button), task_list->priv->box); ++ g_object_get (G_OBJECT (action), "label", &text, NULL); + -+ gtk_container_add (GTK_CONTAINER (task_list->priv->box), task->radio_button); -+ task_list->priv->tasks = g_list_append (task_list->priv->tasks, task); ++ gtk_button_set_label (GTK_BUTTON (button), text); ++ g_free (text); +} + +static void -+gdm_task_list_class_init (GdmTaskListClass *klass) ++on_button_action_icon_name_changed (GtkWidget *button) +{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ -+ object_class->finalize = gdm_task_list_finalize; -+ -+ signals [ACTIVATED] = g_signal_new ("activated", -+ G_TYPE_FROM_CLASS (object_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmTaskListClass, activated), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); ++ GtkAction *action; ++ GtkWidget *image; + -+ signals [DEACTIVATED] = g_signal_new ("deactivated", -+ G_TYPE_FROM_CLASS (object_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmTaskListClass, deactivated), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); ++ action = gtk_widget_get_action (button); + -+ g_type_class_add_private (klass, sizeof (GdmTaskListPrivate)); ++ image = gtk_action_create_icon (GTK_ACTION (action), GTK_ICON_SIZE_BUTTON); ++ gtk_button_set_image (GTK_BUTTON (button), image); +} + +static void -+gdm_task_list_init (GdmTaskList *widget) ++on_button_action_tooltip_changed (GtkWidget *button) +{ -+ widget->priv = GDM_TASK_LIST_GET_PRIVATE (widget); ++ GtkAction *action; ++ char *text; + -+ gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 0, 0); -+ gtk_alignment_set (GTK_ALIGNMENT (widget), 0.0, 0.0, 0, 0); ++ action = gtk_widget_get_action (button); + -+ widget->priv->box = gtk_hbox_new (FALSE, 2); -+ gtk_widget_show (widget->priv->box); -+ gtk_container_add (GTK_CONTAINER (widget), -+ widget->priv->box); ++ g_object_get (G_OBJECT (action), "tooltip", &text, NULL); + -+ add_task (widget, "password-auth", "dialog-password"); -+ add_task (widget, "fingerprint-auth", "stock_allow-effects"); -+ add_task (widget, "smartcard-auth", "badge-small"); ++ gtk_widget_set_tooltip_text (button, text); ++ g_free (text); +} + -+static void -+gdm_task_list_finalize (GObject *object) ++GtkWidget * ++create_button_from_action (GtkAction *action) +{ -+ GdmTaskList *widget; -+ -+ g_return_if_fail (object != NULL); -+ g_return_if_fail (GDM_IS_TASK_LIST (object)); ++ GtkWidget *button; + -+ widget = GDM_TASK_LIST (object); ++ button = gtk_button_new (); + -+ g_return_if_fail (widget->priv != NULL); ++ gtk_action_connect_proxy (GTK_ACTION (action), button); + -+ G_OBJECT_CLASS (gdm_task_list_parent_class)->finalize (object); -+} ++ g_signal_connect_swapped (action, ++ "notify::label", ++ G_CALLBACK (on_button_action_label_changed), ++ button); ++ g_signal_connect_swapped (action, ++ "notify::icon-name", ++ G_CALLBACK (on_button_action_icon_name_changed), ++ button); ++ g_signal_connect_swapped (action, ++ "notify::tooltip", ++ G_CALLBACK (on_button_action_tooltip_changed), ++ button); + -+GtkWidget * -+gdm_task_list_new (void) -+{ -+ GObject *object; ++ on_button_action_label_changed (button); ++ on_button_action_icon_name_changed (button); ++ on_button_action_tooltip_changed (button); + -+ object = g_object_new (GDM_TYPE_TASK_LIST, NULL); ++ if (strcmp (gtk_action_get_name (action), ++ GDM_CONVERSATION_DEFAULT_ACTION) == 0) { ++ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); ++ } + -+ return GTK_WIDGET (object); ++ return button; +} + -+const char * -+gdm_task_list_get_active_task (GdmTaskList *widget) ++static void ++create_buttons_for_actions (GdmGreeterLoginWindow *login_window, ++ GtkActionGroup *actions) +{ ++ GList *action_list; + GList *node; ++ GtkWidget *box; + -+ for (node = widget->priv->tasks; node != NULL; node = node->next) { -+ GdmTask *task; ++ action_list = gtk_action_group_list_actions (actions); + -+ task = node->data; ++ box = glade_xml_get_widget (login_window->priv->xml, "buttonbox"); ++ for (node = action_list; node != NULL; node = node->next) { ++ GtkAction *action; ++ GtkWidget *button; + -+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (task->radio_button)) ) { -+ return task->name; -+ } ++ action = node->data; ++ ++ button = create_button_from_action (action); ++ gtk_container_add (GTK_CONTAINER (box), button); + } + -+ return NULL; ++ g_list_free (action_list); +} -diff --git a/gui/simple-greeter/gdm-task-list.h b/gui/simple-greeter/gdm-task-list.h -new file mode 100644 -index 0000000..90c31cf ---- /dev/null -+++ b/gui/simple-greeter/gdm-task-list.h -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written by: Ray Strode -+ */ + -+#ifndef __GDM_TASK_LIST_H -+#define __GDM_TASK_LIST_H ++void ++gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, ++ GdmGreeterExtension *extension) ++{ ++ char *name; ++ char *description; ++ char *service_name; ++ GtkActionGroup *actions; + -+#include -+#include ++ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); ++ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION (extension)); + -+G_BEGIN_DECLS ++ if (!GDM_IS_CONVERSATION (extension)) { ++ return; ++ } + -+#define GDM_TYPE_TASK_LIST (gdm_task_list_get_type ()) -+#define GDM_TASK_LIST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_TASK_LIST, GdmTaskList)) -+#define GDM_TASK_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_TASK_LIST, GdmTaskListClass)) -+#define GDM_IS_TASK_LIST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_TASK_LIST)) -+#define GDM_IS_TASK_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_TASK_LIST)) -+#define GDM_TASK_LIST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_TASK_LIST, GdmTaskListClass)) ++ actions = gdm_conversation_get_actions (GDM_CONVERSATION (extension)); + -+typedef struct GdmTaskListPrivate GdmTaskListPrivate; ++ create_buttons_for_actions (login_window, actions); ++ hide_task_actions (GDM_TASK (extension)); + -+typedef struct -+{ -+ GtkAlignment parent; -+ GdmTaskListPrivate *priv; -+} GdmTaskList; ++ g_object_unref (actions); + -+typedef struct -+{ -+ GtkAlignmentClass parent_class; ++ g_signal_connect_swapped (GDM_CONVERSATION (extension), ++ "answer", ++ G_CALLBACK (on_conversation_answer), ++ login_window); ++ g_signal_connect_swapped (GDM_CONVERSATION (extension), ++ "cancel", ++ G_CALLBACK (on_conversation_cancel), ++ login_window); ++ g_signal_connect_swapped (GDM_CONVERSATION (extension), ++ "user-chosen", ++ G_CALLBACK (on_conversation_chose_user), ++ login_window); + -+ void (* deactivated) (GdmTaskList *widget, -+ const char *name); -+ void (* activated) (GdmTaskList *widget, -+ const char *name); -+} GdmTaskListClass; ++ name = gdm_task_get_name (GDM_TASK (extension)); ++ description = gdm_task_get_description (GDM_TASK (extension)); + ++ g_debug ("GdmGreeterLoginWindow: new extension '%s - %s' added", ++ name, description); + -+GType gdm_task_list_get_type (void); -+GtkWidget * gdm_task_list_new (void); ++ gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ GDM_TASK (extension)); + -+const char * gdm_task_list_get_active_task (GdmTaskList *widget); -+G_END_DECLS ++ service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (extension)); + -+#endif /* __GDM_TASK_LIST_H */ --- -1.6.1 - - -From 0389551de0b71716cb47f337431648f5e9702bd7 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 1 Feb 2009 12:33:52 -0500 -Subject: [PATCH 16/65] Add some casts to drop some warnings - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index f3daccb..fe186e7 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -764,7 +764,7 @@ gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window, - - g_debug ("GdmGreeterLoginWindow: info: %s", text); - -- if (strcmp (service_name, gdm_task_list_get_active_task (login_window->priv->conversation_list)) == 0) { -+ if (strcmp (service_name, gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list))) == 0) { - set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); - } - -@@ -780,7 +780,7 @@ gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, - - g_debug ("GdmGreeterLoginWindow: problem: %s", text); - -- if (strcmp (service_name, gdm_task_list_get_active_task (login_window->priv->conversation_list)) == 0) { -+ if (strcmp (service_name, gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list))) == 0) { - set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); - } - gdk_window_beep (GTK_WIDGET (login_window)->window); -@@ -866,7 +866,7 @@ gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, - - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - -- if (strcmp (service_name, gdm_task_list_get_active_task (login_window->priv->conversation_list)) != 0) { -+ if (strcmp (service_name, gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list))) != 0) { - return TRUE; - } - --- -1.6.1 - - -From 97853e0ace98a3aec0eafbf875739dfc1aee1ace Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 1 Feb 2009 12:35:30 -0500 -Subject: [PATCH 17/65] Add tasks from login window instead of task list - -This is just a refactoring to move it closer to -being able to be loaded dynamically, instead of -hard coded. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 7 +++++++ - gui/simple-greeter/gdm-task-list.c | 12 ++++-------- - gui/simple-greeter/gdm-task-list.h | 3 +++ - 3 files changed, 14 insertions(+), 8 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index fe186e7..a0d76a9 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -1653,6 +1653,13 @@ load_theme (GdmGreeterLoginWindow *login_window) - login_window); - gtk_widget_show (login_window->priv->conversation_list); - -+ gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ "password-auth", "dialog-password"); -+ gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ "fingerprint-auth", "stock_allow-effects"); -+ gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ "smartcard-auth", "badge-small"); ++ if (gdm_task_is_choosable (GDM_TASK (extension))) { ++ gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser), ++ service_name, NULL, name, description, ~0, ++ FALSE, TRUE); ++ } + - login_window->priv->auth_banner_label = glade_xml_get_widget (login_window->priv->xml, "auth-banner-label"); - /*make_label_small_italic (login_window->priv->auth_banner_label);*/ - -diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c -index d522858..ef72f0c 100644 ---- a/gui/simple-greeter/gdm-task-list.c -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -78,10 +78,10 @@ on_task_toggled (GdmTaskList *widget, - } - } - --static void --add_task (GdmTaskList *task_list, -- const char *name, -- const char *icon_name) -+void -+gdm_task_list_add_task (GdmTaskList *task_list, -+ const char *name, -+ const char *icon_name) - { - GdmTask *task; - GtkWidget *image; -@@ -151,10 +151,6 @@ gdm_task_list_init (GdmTaskList *widget) - gtk_widget_show (widget->priv->box); - gtk_container_add (GTK_CONTAINER (widget), - widget->priv->box); ++ g_free (name); ++ g_free (description); ++ ++ g_debug ("GdmGreeterLoginWindow: starting conversation with '%s'", service_name); ++ g_signal_emit (login_window, signals[START_CONVERSATION], 0, service_name); ++ g_free (service_name); ++} ++ + static gboolean + on_window_state_event (GtkWidget *widget, + GdkEventWindowState *event, +diff -up gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.glade.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.glade +--- gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.glade.multistack-but-boring 2008-11-18 17:34:37.000000000 -0500 ++++ gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.glade 2009-03-03 17:45:05.661016533 -0500 +@@ -611,30 +611,29 @@ + + + +- +- True +- +- False +- False +- GTK_JUSTIFY_CENTER +- True +- False +- 0.5 +- 0.5 +- 0 +- 0 +- PANGO_ELLIPSIZE_NONE +- -1 +- False +- 0 +- +- +- 0 +- True +- True +- ++ ++ True ++ ++ False ++ False ++ GTK_JUSTIFY_CENTER ++ True ++ False ++ 0.5 ++ 0.5 ++ 0 ++ 0 ++ PANGO_ELLIPSIZE_NONE ++ -1 ++ False ++ 0 ++ ++ ++ 0 ++ False ++ False ++ + - -- add_task (widget, "password-auth", "dialog-password"); -- add_task (widget, "fingerprint-auth", "stock_allow-effects"); -- add_task (widget, "smartcard-auth", "badge-small"); - } + + + True +@@ -654,42 +653,17 @@ + 10 - static void -diff --git a/gui/simple-greeter/gdm-task-list.h b/gui/simple-greeter/gdm-task-list.h -index 90c31cf..ade21b6 100644 ---- a/gui/simple-greeter/gdm-task-list.h -+++ b/gui/simple-greeter/gdm-task-list.h -@@ -56,6 +56,9 @@ GType gdm_task_list_get_type (void); - GtkWidget * gdm_task_list_new (void); - - const char * gdm_task_list_get_active_task (GdmTaskList *widget); -+void gdm_task_list_add_task (GdmTaskList *widget, -+ const char *name, -+ const char *icon_name); - G_END_DECLS + +- +- True +- 0 +- 0 +- Tue, 18 Nov 2008 21:55:38 GMT +- +- +- 0 +- True +- True +- +- +- +- +- ++ + True + False +- 6 ++ 0 - #endif /* __GDM_TASK_LIST_H */ --- -1.6.1 - - -From a6769c7e07b3f76a331c9b0c8b69d679806c39bb Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 1 Feb 2009 12:36:17 -0500 -Subject: [PATCH 18/65] Clean up list of tasks on task list finalization - ---- - gui/simple-greeter/gdm-task-list.c | 5 +++-- - 1 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c -index ef72f0c..e0fd3d4 100644 ---- a/gui/simple-greeter/gdm-task-list.c -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -86,7 +86,7 @@ gdm_task_list_add_task (GdmTaskList *task_list, - GdmTask *task; - GtkWidget *image; + +- ++ + True +- +- False +- False +- GTK_JUSTIFY_LEFT +- False +- False +- 0.5 +- 0.5 +- 0 +- 0 +- PANGO_ELLIPSIZE_NONE +- -1 +- False +- 0 ++ 0 ++ 0 ++ Fri, 30 Jan 2009 16:03:30 GMT + + + 0 +@@ -699,17 +673,11 @@ + -- task = g_slice_new0 (GdmTask); -+ task = g_new0 (GdmTask, 1); + +- ++ + True +- True +- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK +- True +- True +- 0 +- +- True +- • +- True ++ 0 ++ 0 ++ Tue, 18 Nov 2008 21:55:38 GMT + + + 0 +@@ -718,46 +686,21 @@ + + - task->name = g_strdup (name); - if (task_list->priv->tasks == NULL) { -@@ -163,7 +163,8 @@ gdm_task_list_finalize (GObject *object) +- +- +- + + + 0 +- False +- False ++ True ++ True + + - widget = GDM_TASK_LIST (object); + +- ++ + True + False + 0 +- + +- +- True +- +- False +- False +- GTK_JUSTIFY_LEFT +- False +- False +- 0.5 +- 0.5 +- 0 +- 0 +- PANGO_ELLIPSIZE_NONE +- -1 +- False +- 0 +- +- +- 0 +- True +- True +- ++ + + + +@@ -779,10 +722,6 @@ + + + +- +- +- +- + + + +diff -up gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.h.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.h +--- gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.h.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/gui/simple-greeter/gdm-greeter-login-window.h 2009-03-03 17:45:05.713016373 -0500 +@@ -23,6 +23,9 @@ + #define __GDM_GREETER_LOGIN_WINDOW_H -- g_return_if_fail (widget->priv != NULL); -+ g_list_foreach (widget->priv->tasks, (GFunc) g_free, NULL); -+ g_list_free (widget->priv->tasks); + #include ++#include "gdm-conversation.h" ++#include "gdm-task.h" ++#include "gdm-greeter-extension.h" - G_OBJECT_CLASS (gdm_task_list_parent_class)->finalize (object); - } --- -1.6.1 - - -From 2f2785b5a68a97e7bc774569f5f39a565b23b115 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 4 Feb 2009 10:55:03 -0500 -Subject: [PATCH 19/65] Rename session worker to the service it's managing - -This way if a pam module gets hung up and causes -GDM to stall, there's a chance the reporter will -bypass GDM when filing the report. ---- - daemon/gdm-session-direct.c | 7 ++++- - daemon/gdm-session-worker-job.c | 63 ++++++++++++++++++++++++++++++-------- - daemon/gdm-session-worker-job.h | 3 +- - 3 files changed, 57 insertions(+), 16 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 55ea4ee..d25b988 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1741,6 +1741,7 @@ start_conversation (GdmSessionDirect *session, - const char *service_name) - { - GdmSessionConversation *conversation; -+ char *job_name; + G_BEGIN_DECLS - conversation = g_new0 (GdmSessionConversation, 1); - conversation->session = session; -@@ -1765,12 +1766,16 @@ start_conversation (GdmSessionDirect *session, - G_CALLBACK (worker_died), - conversation); +@@ -33,6 +36,8 @@ G_BEGIN_DECLS + #define GDM_IS_GREETER_LOGIN_WINDOW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_GREETER_LOGIN_WINDOW)) + #define GDM_GREETER_LOGIN_WINDOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_GREETER_LOGIN_WINDOW, GdmGreeterLoginWindowClass)) -- if (!gdm_session_worker_job_start (conversation->job)) { -+ job_name = g_strdup_printf ("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); ++#define GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION(e) (GDM_IS_CONVERSATION(e) && GDM_IS_TASK(e)) ++ + typedef struct GdmGreeterLoginWindowPrivate GdmGreeterLoginWindowPrivate; - conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job); + typedef struct +@@ -46,18 +51,24 @@ typedef struct + GtkWindowClass parent_class; -diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c -index 7328c0e..c079762 100644 ---- a/daemon/gdm-session-worker-job.c -+++ b/daemon/gdm-session-worker-job.c -@@ -124,6 +124,37 @@ listify_hash (const char *key, - } + /* signals */ ++ void (* start_conversation) (GdmGreeterLoginWindow *login_window, ++ const char *service_name); + void (* begin_auto_login) (GdmGreeterLoginWindow *login_window, + const char *username); +- void (* begin_verification) (GdmGreeterLoginWindow *login_window); ++ void (* begin_verification) (GdmGreeterLoginWindow *login_window, ++ const char *service_name); + void (* begin_verification_for_user) (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *username); + void (* query_answer) (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text); + void (* user_selected) (GdmGreeterLoginWindow *login_window, + const char *text); + void (* cancelled) (GdmGreeterLoginWindow *login_window); + void (* disconnected) (GdmGreeterLoginWindow *login_window); +- void (* start_session) (GdmGreeterLoginWindow *login_window); ++ void (* start_session) (GdmGreeterLoginWindow *login_window, ++ const char *sevice_name); - static GPtrArray * -+get_job_arguments (GdmSessionWorkerJob *job, -+ const char *name) -+{ -+ GPtrArray *args; -+ GError *error; -+ char **argv; -+ int i; -+ -+ args = NULL; -+ argv = NULL; -+ error = NULL; -+ if (! g_shell_parse_argv (job->priv->command, NULL, &argv, &error)) { -+ g_warning ("Could not parse command: %s", error->message); -+ g_error_free (error); -+ goto out; -+ } -+ -+ args = g_ptr_array_new (); -+ g_ptr_array_add (args, g_strdup (argv[0])); -+ g_ptr_array_add (args, g_strdup (name)); -+ for (i = 1; argv[i] != NULL; i++) { -+ g_ptr_array_add (args, g_strdup (argv[i])); -+ } -+ g_strfreev (argv); -+ -+ g_ptr_array_add (args, NULL); -+out: -+ return args; -+} -+ -+static GPtrArray * - get_job_environment (GdmSessionWorkerJob *job) - { - GPtrArray *env; -@@ -145,31 +176,31 @@ get_job_environment (GdmSessionWorkerJob *job) - } - - static gboolean --gdm_session_worker_job_spawn (GdmSessionWorkerJob *session_worker_job) -+gdm_session_worker_job_spawn (GdmSessionWorkerJob *session_worker_job, -+ const char *name) - { -- gchar **argv; - GError *error; - gboolean ret; -+ GPtrArray *args; - GPtrArray *env; - - ret = FALSE; - -- g_debug ("GdmSessionWorkerJob: Running session_worker_job process: %s", session_worker_job->priv->command); -+ g_debug ("GdmSessionWorkerJob: Running session_worker_job process: %s %s", -+ name != NULL? name : "", session_worker_job->priv->command); - -- argv = NULL; -- if (! g_shell_parse_argv (session_worker_job->priv->command, NULL, &argv, &error)) { -- g_warning ("Could not parse command: %s", error->message); -- g_error_free (error); -- goto out; -- } -+ args = get_job_arguments (session_worker_job, name); - -+ if (args == NULL) { -+ return FALSE; -+ } - env = get_job_environment (session_worker_job); - - error = NULL; - ret = g_spawn_async_with_pipes (NULL, -- argv, -+ (char **) args->pdata, - (char **)env->pdata, -- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, -+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_FILE_AND_ARGV_ZERO, - (GSpawnChildSetupFunc)session_worker_job_child_setup, - session_worker_job, - &session_worker_job->priv->pid, -@@ -178,6 +209,9 @@ gdm_session_worker_job_spawn (GdmSessionWorkerJob *session_worker_job) - NULL, - &error); - -+ g_ptr_array_foreach (args, (GFunc)g_free, NULL); -+ g_ptr_array_free (args, TRUE); -+ - g_ptr_array_foreach (env, (GFunc)g_free, NULL); - g_ptr_array_free (env, TRUE); - -@@ -194,7 +228,6 @@ gdm_session_worker_job_spawn (GdmSessionWorkerJob *session_worker_job) - (GChildWatchFunc)session_worker_job_child_watch, - session_worker_job); - -- g_strfreev (argv); - out: - - return ret; -@@ -207,13 +240,14 @@ gdm_session_worker_job_spawn (GdmSessionWorkerJob *session_worker_job) - * Starts a local X session_worker_job. Handles retries and fatal errors properly. - */ - gboolean --gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job) -+gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job, -+ const char *name) - { - gboolean res; - - g_debug ("GdmSessionWorkerJob: Starting worker..."); - -- res = gdm_session_worker_job_spawn (session_worker_job); -+ res = gdm_session_worker_job_spawn (session_worker_job, name); - - if (res) { - -@@ -261,6 +295,7 @@ gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job) - g_debug ("GdmSessionWorkerJob: Stopping job pid:%d", session_worker_job->priv->pid); - - res = gdm_signal_pid (session_worker_job->priv->pid, SIGTERM); -+ - if (res < 0) { - g_warning ("Unable to kill session worker process"); - } else { -diff --git a/daemon/gdm-session-worker-job.h b/daemon/gdm-session-worker-job.h -index 9cb08ce..5b3be46 100644 ---- a/daemon/gdm-session-worker-job.h -+++ b/daemon/gdm-session-worker-job.h -@@ -58,7 +58,8 @@ GType gdm_session_worker_job_get_type (void); - GdmSessionWorkerJob * gdm_session_worker_job_new (void); - void gdm_session_worker_job_set_server_address (GdmSessionWorkerJob *session_worker_job, - const char *server_address); --gboolean gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job); -+gboolean gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job, -+ const char *name); - gboolean gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job); - - GPid gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job); --- -1.6.1 - - -From 34a4f90e837bdbb996d3b1dc8fd92753d1dd10b6 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 5 Feb 2009 15:20:25 -0500 -Subject: [PATCH 20/65] Queue a greeter reset when the user clicks cancel - ---- - daemon/gdm-simple-slave.c | 37 +++++++++++++++++++++++++++++++++++++ - 1 files changed, 37 insertions(+), 0 deletions(-) - -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index 3a24d8d..a6ae0ae 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -760,6 +760,9 @@ on_greeter_start_conversation (GdmGreeterServer *greeter_server, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: starting conversation with '%s' pam service'", service_name); -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - gdm_session_start_conversation (GDM_SESSION (slave->priv->session), - service_name); - } -@@ -770,6 +773,9 @@ on_greeter_begin_verification (GdmGreeterServer *greeter_server, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: begin verification"); -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - gdm_session_setup (GDM_SESSION (slave->priv->session), - service_name); - } -@@ -780,6 +786,9 @@ on_greeter_begin_auto_login (GdmGreeterServer *greeter_server, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: begin auto login for user '%s'", username); -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), - "gdm-autologin", - username); -@@ -792,6 +801,9 @@ on_greeter_begin_verification_for_user (GdmGreeterServer *greeter_server, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: begin verification"); -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), - service_name, - username); -@@ -803,6 +815,9 @@ on_greeter_answer (GdmGreeterServer *greeter_server, - const char *text, - GdmSimpleSlave *slave) - { -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - gdm_session_answer_query (GDM_SESSION (slave->priv->session), service_name, text); - } - -@@ -811,6 +826,9 @@ on_greeter_session_selected (GdmGreeterServer *greeter_server, - const char *text, - GdmSimpleSlave *slave) - { -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - gdm_session_select_session (GDM_SESSION (slave->priv->session), text); - } - -@@ -819,6 +837,9 @@ on_greeter_language_selected (GdmGreeterServer *greeter_server, - const char *text, - GdmSimpleSlave *slave) - { -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - gdm_session_select_language (GDM_SESSION (slave->priv->session), text); - } - -@@ -827,6 +848,9 @@ on_greeter_layout_selected (GdmGreeterServer *greeter_server, - const char *text, - GdmSimpleSlave *slave) - { -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - gdm_session_select_layout (GDM_SESSION (slave->priv->session), text); - } - -@@ -843,7 +867,11 @@ on_greeter_cancel (GdmGreeterServer *greeter_server, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: Greeter cancelled"); -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - reset_session (slave); -+ queue_greeter_reset (slave); - } - - static void -@@ -853,6 +881,9 @@ on_greeter_connected (GdmGreeterServer *greeter_server, - gboolean display_is_local; - - g_debug ("GdmSimpleSlave: Greeter connected"); -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - - g_object_get (slave, - "display-is-local", &display_is_local, -@@ -870,6 +901,9 @@ on_start_session_when_ready (GdmGreeterServer *session, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: Will start session when ready"); -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - slave->priv->start_session_when_ready = TRUE; - - if (slave->priv->waiting_to_start_session) { -@@ -883,6 +917,9 @@ on_start_session_later (GdmGreeterServer *session, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: Will start session when ready and told"); -+ if (slave->priv->greeter_reset_id > 0) { -+ return; -+ } - slave->priv->start_session_when_ready = FALSE; - } - --- -1.6.1 - - -From 48910d04a95487b38dc17c668cba5bfccba8fd10 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 5 Feb 2009 16:57:39 -0500 -Subject: [PATCH 21/65] Don't bother cancelling worker through D-Bus when stopping - -It's just going to get sent SIGTERM anyway. ---- - daemon/gdm-session-direct.c | 19 +++++-------------- - 1 files changed, 5 insertions(+), 14 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index d25b988..68e4084 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1802,8 +1802,6 @@ stop_conversation (GdmSessionConversation *conversation) - G_CALLBACK (worker_died), - conversation); - -- cancel_pending_query (conversation); -- - if (conversation->worker_connection != NULL) { - dbus_connection_remove_filter (conversation->worker_connection, on_message, session); - -@@ -2214,6 +2212,10 @@ stop_all_conversations (GdmSessionDirect *session) - GHashTableIter iter; - gpointer key, value; - -+ if (session->priv->conversations == NULL) { -+ return; -+ } -+ - g_hash_table_iter_init (&iter, session->priv->conversations); - while (g_hash_table_iter_next (&iter, &key, &value)) { - GdmSessionConversation *conversation; -@@ -2295,20 +2297,9 @@ gdm_session_direct_answer_query (GdmSession *session, - static void - gdm_session_direct_cancel (GdmSession *session) - { -- GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- GHashTableIter iter; -- gpointer key, value; -- - g_return_if_fail (session != NULL); - -- g_hash_table_iter_init (&iter, impl->priv->conversations); -- while (g_hash_table_iter_next (&iter, &key, &value)) { -- GdmSessionConversation *conversation; -- -- conversation = (GdmSessionConversation *) value; -- -- cancel_pending_query (conversation); -- } -+ stop_all_conversations (GDM_SESSION_DIRECT (session)); - } - - char * --- -1.6.1 - - -From 69d70473c757ffa19e3827103e78c13b33ba14de Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 5 Feb 2009 17:16:55 -0500 -Subject: [PATCH 22/65] Fix mistake in user authorized client signal marshaler - ---- - gui/simple-greeter/gdm-greeter-client.c | 5 +++-- - 1 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c -index ee7019d..0bd27a9 100644 ---- a/gui/simple-greeter/gdm-greeter-client.c -+++ b/gui/simple-greeter/gdm-greeter-client.c -@@ -1069,8 +1069,9 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) - G_STRUCT_OFFSET (GdmGreeterClientClass, user_authorized), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -- G_TYPE_NONE, 0); -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); - } - - static void --- -1.6.1 - - -From 6f6a6f4ab7b28470417e52f33aa3baccf7e6dd79 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 15:35:00 -0500 -Subject: [PATCH 23/65] Drop "stopped" signal from worker-job class - -It was unused, dead code. ---- - daemon/gdm-session-direct.c | 14 -------------- - daemon/gdm-session-worker-job.c | 11 ----------- - daemon/gdm-session-worker-job.h | 1 - - 3 files changed, 0 insertions(+), 26 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 68e4084..cbcc8d1 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1687,13 +1687,6 @@ gdm_session_direct_init (GdmSessionDirect *session) - } - - static void --worker_stopped (GdmSessionWorkerJob *job, -- GdmSessionConversation *conversation) --{ -- g_debug ("GdmSessionDirect: Worker job stopped"); --} -- --static void - worker_started (GdmSessionWorkerJob *job, - GdmSessionConversation *conversation) - { -@@ -1750,10 +1743,6 @@ start_conversation (GdmSessionDirect *session, - conversation->job = gdm_session_worker_job_new (); - gdm_session_worker_job_set_server_address (conversation->job, session->priv->server_address); - g_signal_connect (conversation->job, -- "stopped", -- G_CALLBACK (worker_stopped), -- conversation); -- g_signal_connect (conversation->job, - "started", - G_CALLBACK (worker_started), - conversation); -@@ -1790,9 +1779,6 @@ stop_conversation (GdmSessionConversation *conversation) - session = conversation->session; - - g_signal_handlers_disconnect_by_func (conversation->job, -- G_CALLBACK (worker_stopped), -- conversation); -- g_signal_handlers_disconnect_by_func (conversation->job, - G_CALLBACK (worker_started), - conversation); - g_signal_handlers_disconnect_by_func (conversation->job, -diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c -index c079762..ac2aa02 100644 ---- a/daemon/gdm-session-worker-job.c -+++ b/daemon/gdm-session-worker-job.c -@@ -68,7 +68,6 @@ enum { - - enum { - STARTED, -- STOPPED, - EXITED, - DIED, - LAST_SIGNAL -@@ -405,16 +404,6 @@ gdm_session_worker_job_class_init (GdmSessionWorkerJobClass *klass) - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); -- signals [STOPPED] = -- g_signal_new ("stopped", -- G_OBJECT_CLASS_TYPE (object_class), -- G_SIGNAL_RUN_FIRST, -- G_STRUCT_OFFSET (GdmSessionWorkerJobClass, stopped), -- NULL, -- NULL, -- g_cclosure_marshal_VOID__VOID, -- G_TYPE_NONE, -- 0); - signals [EXITED] = - g_signal_new ("exited", - G_OBJECT_CLASS_TYPE (object_class), -diff --git a/daemon/gdm-session-worker-job.h b/daemon/gdm-session-worker-job.h -index 5b3be46..4833f23 100644 ---- a/daemon/gdm-session-worker-job.h -+++ b/daemon/gdm-session-worker-job.h -@@ -46,7 +46,6 @@ typedef struct - GObjectClass parent_class; - - void (* started) (GdmSessionWorkerJob *session_worker_job); -- void (* stopped) (GdmSessionWorkerJob *session_worker_job); - void (* exited) (GdmSessionWorkerJob *session_worker_job, - int exit_code); - --- -1.6.1 - - -From aa5bd199dbb1274ef7acb155a4e8751ee4c68970 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 16:23:48 -0500 -Subject: [PATCH 24/65] Add a plugin based extension system to greeter - -This allows plugins to drive which PAM conversations -get run. This commit just adds one plugin "password" -which does the one PAM conversation we've traditionally -run. ---- - configure.ac | 36 ++ - daemon/gdm-session-direct.c | 18 +- - gui/simple-greeter/Makefile.am | 15 + - gui/simple-greeter/gdm-greeter-login-window.c | 652 ++++++++++++++++---- - gui/simple-greeter/gdm-greeter-login-window.glade | 144 +---- - gui/simple-greeter/gdm-greeter-login-window.h | 19 +- - gui/simple-greeter/gdm-greeter-plugin.c | 251 ++++++++ - gui/simple-greeter/gdm-greeter-plugin.h | 61 ++ - gui/simple-greeter/gdm-greeter-session.c | 76 +++- - gui/simple-greeter/gdm-plugin-manager.c | 478 ++++++++++++++ - gui/simple-greeter/gdm-plugin-manager.h | 66 ++ - gui/simple-greeter/gdm-task-list.c | 166 ++++-- - gui/simple-greeter/gdm-task-list.h | 34 +- - gui/simple-greeter/libgdmsimplegreeter/Makefile.am | 46 ++ - .../libgdmsimplegreeter/gdm-conversation.c | 147 +++++ - .../libgdmsimplegreeter/gdm-conversation.h | 87 +++ - .../libgdmsimplegreeter/gdm-greeter-extension.c | 93 +++ - .../libgdmsimplegreeter/gdm-greeter-extension.h | 55 ++ - gui/simple-greeter/libgdmsimplegreeter/gdm-task.c | 117 ++++ - gui/simple-greeter/libgdmsimplegreeter/gdm-task.h | 62 ++ - .../libgdmsimplegreeter/gdmsimplegreeter.pc.in | 11 + - gui/simple-greeter/plugins/Makefile.am | 1 + - gui/simple-greeter/plugins/password/Makefile.am | 40 ++ - .../plugins/password/gdm-password-extension.c | 316 ++++++++++ - .../plugins/password/gdm-password-extension.h | 56 ++ - gui/simple-greeter/plugins/password/page.ui | 56 ++ - gui/simple-greeter/plugins/password/plugin.c | 40 ++ - 27 files changed, 2839 insertions(+), 304 deletions(-) - create mode 100644 gui/simple-greeter/gdm-greeter-plugin.c - create mode 100644 gui/simple-greeter/gdm-greeter-plugin.h - create mode 100644 gui/simple-greeter/gdm-plugin-manager.c - create mode 100644 gui/simple-greeter/gdm-plugin-manager.h - create mode 100644 gui/simple-greeter/libgdmsimplegreeter/Makefile.am - create mode 100644 gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c - create mode 100644 gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h - create mode 100644 gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.c - create mode 100644 gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.h - create mode 100644 gui/simple-greeter/libgdmsimplegreeter/gdm-task.c - create mode 100644 gui/simple-greeter/libgdmsimplegreeter/gdm-task.h - create mode 100644 gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc.in - create mode 100644 gui/simple-greeter/plugins/Makefile.am - create mode 100644 gui/simple-greeter/plugins/password/Makefile.am - create mode 100644 gui/simple-greeter/plugins/password/gdm-password-extension.c - create mode 100644 gui/simple-greeter/plugins/password/gdm-password-extension.h - create mode 100644 gui/simple-greeter/plugins/password/page.ui - create mode 100644 gui/simple-greeter/plugins/password/plugin.c - -diff --git a/configure.ac b/configure.ac -index 2674271..cc2576f 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -18,6 +18,22 @@ AC_PROG_CXX - AM_PROG_CC_C_O - AC_PROG_LIBTOOL() - -+## increment if the plugin interface has additions, changes, removals. -+LT_CURRENT=1 -+ -+## increment any time the source changes; set to -+## 0 if you increment CURRENT -+LT_REVISION=0 -+ -+## increment if any interfaces have been added; set to 0 -+## if any interfaces have been changed or removed. removal has -+## precedence over adding, so set to 0 if both happened. -+LT_AGE=0 -+ -+AC_SUBST(LT_CURRENT) -+AC_SUBST(LT_REVISION) -+AC_SUBST(LT_AGE) -+ - AC_HEADER_STDC - - AC_SUBST(VERSION) -@@ -1274,6 +1290,22 @@ fi - AC_SUBST(GDM_XAUTH_DIR) - - dnl --------------------------------------------------------------------------- -+dnl - Directory for simple greeter plugins -+dnl --------------------------------------------------------------------------- -+ -+AC_ARG_WITH(simple-greeter-plugins-dir, -+ AS_HELP_STRING([--with-simple-greeter-plugins-dir=], -+ [simple greeter plugins directory])) -+ -+if ! test -z "$with_simple_greeter_plugins_dir"; then -+ GDM_SIMPLE_GREETER_PLUGINS_DIR=$with_simple_greeter_plugins_dir -+else -+ GDM_SIMPLE_GREETER_PLUGINS_DIR=${libdir}/gdm/simple-greeter/plugins -+fi -+ -+AC_SUBST(GDM_SIMPLE_GREETER_PLUGINS_DIR) -+ -+dnl --------------------------------------------------------------------------- - dnl - Finish - dnl --------------------------------------------------------------------------- - -@@ -1402,6 +1434,10 @@ docs/Makefile - gui/Makefile - gui/simple-greeter/Makefile - gui/simple-greeter/libnotificationarea/Makefile -+gui/simple-greeter/libgdmsimplegreeter/Makefile -+gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc -+gui/simple-greeter/plugins/Makefile -+gui/simple-greeter/plugins/password/Makefile - gui/simple-chooser/Makefile - gui/user-switch-applet/Makefile - utils/Makefile -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index cbcc8d1..099f884 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1650,6 +1650,17 @@ setup_server (GdmSessionDirect *session) - } - - static void -+free_conversation (GdmSessionConversation *conversation) -+{ -+ if (conversation->job != NULL) { -+ g_warning ("Freeing conversation with active job"); -+ } -+ -+ g_free (conversation->service_name); -+ g_free (conversation); -+} -+ -+static void - gdm_session_direct_init (GdmSessionDirect *session) - { - session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, -@@ -1676,7 +1687,8 @@ gdm_session_direct_init (GdmSessionDirect *session) - session->priv->conversations = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, -- NULL); -+ (GDestroyNotify) -+ free_conversation); - session->priv->environment = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, -@@ -1796,11 +1808,9 @@ stop_conversation (GdmSessionConversation *conversation) - } - - gdm_session_worker_job_stop (conversation->job); -- g_hash_table_remove (session->priv->conversations, conversation); - - g_object_unref (conversation->job); -- g_free (conversation->service_name); -- g_free (conversation); -+ conversation->job = NULL; - } - - static void -diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am -index e2d3996..a9e4d65 100644 ---- a/gui/simple-greeter/Makefile.am -+++ b/gui/simple-greeter/Makefile.am -@@ -2,11 +2,14 @@ NULL = - - SUBDIRS = \ - libnotificationarea \ -+ libgdmsimplegreeter \ -+ plugins \ - $(NULL) - - AM_CPPFLAGS = \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ -+ -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ - -DDMCONFDIR=\""$(dmconfdir)"\" \ - -DGDMCONFDIR=\"$(gdmconfdir)\" \ - -DDATADIR=\""$(datadir)"\" \ -@@ -17,6 +20,7 @@ AM_CPPFLAGS = \ - -DLIBEXECDIR=\""$(libexecdir)"\" \ - -DSBINDIR=\""$(sbindir)"\" \ - -DAT_SPI_REGISTRYD_DIR="\"$(AT_SPI_REGISTRYD_DIR)\"" \ -+ -DGDM_SIMPLE_GREETER_PLUGINS_DIR="\"$(GDM_SIMPLE_GREETER_PLUGINS_DIR)\""\ - $(DISABLE_DEPRECATED_CFLAGS) \ - $(GTK_CFLAGS) \ - $(SIMPLE_GREETER_CFLAGS) \ -@@ -85,10 +89,15 @@ test_greeter_login_window_SOURCES = \ - gdm-user-chooser-dialog.c \ - gdm-task-list.h \ - gdm-task-list.c \ -+ gdm-plugin-manager.h \ -+ gdm-plugin-manager.c \ -+ gdm-greeter-plugin.h \ -+ gdm-greeter-plugin.c \ - $(NULL) - - test_greeter_login_window_LDADD = \ - $(top_builddir)/common/libgdmcommon.la \ -+ $(top_builddir)/gui/simple-greeter/libgdmsimplegreeter/libgdmsimplegreeter.la \ - libgdmuser.la \ - $(COMMON_LIBS) \ - $(SIMPLE_GREETER_LIBS) \ -@@ -140,6 +149,7 @@ test_greeter_panel_SOURCES = \ - test_greeter_panel_LDADD = \ - $(top_builddir)/common/libgdmcommon.la \ - $(top_builddir)/gui/simple-greeter/libnotificationarea/libnotificationarea.la \ -+ $(top_builddir)/gui/simple-greeter/libgdmsimplegreeter/libgdmsimplegreeter.la \ - $(SIMPLE_GREETER_LIBS) \ - $(GTK_LIBS) \ - $(GCONF_LIBS) \ -@@ -312,10 +322,14 @@ gdm_simple_greeter_SOURCES = \ - gdm-language-chooser-dialog.c \ - gdm-language-option-widget.h \ - gdm-language-option-widget.c \ -+ gdm-plugin-manager.h \ -+ gdm-plugin-manager.c \ - gdm-sessions.h \ - gdm-sessions.c \ - gdm-session-option-widget.h \ - gdm-session-option-widget.c \ -+ gdm-greeter-plugin.h \ -+ gdm-greeter-plugin.c \ - gdm-user-chooser-widget.h \ - gdm-user-chooser-widget.c \ - gdm-task-list.h \ -@@ -326,6 +340,7 @@ gdm_simple_greeter_LDADD = \ - $(top_builddir)/common/libgdmcommon.la \ - libgdmuser.la \ - $(top_builddir)/gui/simple-greeter/libnotificationarea/libnotificationarea.la \ -+ $(top_builddir)/gui/simple-greeter/libgdmsimplegreeter/libgdmsimplegreeter.la \ - $(COMMON_LIBS) \ - $(EXTRA_GREETER_LIBS) \ - $(SIMPLE_GREETER_LIBS) \ -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index a0d76a9..ea96abc 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -1,7 +1,7 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2007 William Jon McCann -- * Copyright (C) 2008 Red Hat, Inc. -+ * Copyright (C) 2008, 2009 Red Hat, Inc. - * - * 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 -@@ -17,6 +17,9 @@ - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * -+ * Written by: William Jon McCann -+ * Ray Strode -+ * - */ - - #include "config.h" -@@ -117,6 +120,7 @@ struct GdmGreeterLoginWindowPrivate - GtkWidget *user_chooser; - GtkWidget *conversation_list; - GtkWidget *auth_banner_label; -+ GtkWidget *auth_page_box; - guint display_is_local : 1; - guint is_interactive : 1; - GConfClient *client; -@@ -166,6 +170,9 @@ static void restart_timed_login_timeout (GdmGreeterLoginWindow *login_window - static void on_user_unchosen (GdmUserChooserWidget *user_chooser, - GdmGreeterLoginWindow *login_window); - -+static void gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_window, -+ const char *service_name); -+ - G_DEFINE_TYPE (GdmGreeterLoginWindow, gdm_greeter_login_window, GTK_TYPE_WINDOW) - - static void -@@ -190,9 +197,6 @@ set_sensitive (GdmGreeterLoginWindow *login_window, - { - GtkWidget *box; - -- box = glade_xml_get_widget (login_window->priv->xml, "auth-input-box"); -- gtk_widget_set_sensitive (box, sensitive); -- - box = glade_xml_get_widget (login_window->priv->xml, "buttonbox"); - gtk_widget_set_sensitive (box, sensitive); - -@@ -202,27 +206,43 @@ set_sensitive (GdmGreeterLoginWindow *login_window, - static void - set_focus (GdmGreeterLoginWindow *login_window) - { -- GtkWidget *entry; -- -- entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); -+ GdmTask *task; - - gdk_window_focus (GTK_WIDGET (login_window)->window, GDK_CURRENT_TIME); - -- if (GTK_WIDGET_REALIZED (entry) && ! GTK_WIDGET_HAS_FOCUS (entry)) { -- gtk_widget_grab_focus (entry); -+ task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); -+ -+ if (gdm_conversation_focus (GDM_CONVERSATION (task))) { -+ char *name; -+ name = gdm_task_get_name (task); -+ g_debug ("GdmGreeterLoginWindow: focusing task %s", name); -+ g_free (name); - } else if (GTK_WIDGET_REALIZED (login_window->priv->user_chooser) && ! GTK_WIDGET_HAS_FOCUS (login_window->priv->user_chooser)) { - gtk_widget_grab_focus (login_window->priv->user_chooser); - } -+ g_object_unref (task); -+} -+ -+static gboolean -+set_task_conversation_message (GdmTaskList *task_list, -+ GdmTask *task, -+ const char *message) -+{ -+ -+ gdm_conversation_set_message (GDM_CONVERSATION (task), message); -+ return FALSE; - } - - static void - set_message (GdmGreeterLoginWindow *login_window, - const char *text) - { -- GtkWidget *label; -+ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); - -- label = glade_xml_get_widget (login_window->priv->xml, "auth-message-label"); -- gtk_label_set_text (GTK_LABEL (label), text); -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ set_task_conversation_message, -+ (gpointer) text); - } - - static void -@@ -388,30 +408,76 @@ get_show_restart_buttons (GdmGreeterLoginWindow *login_window) - } - - static void --on_login_button_clicked_answer_query (GtkButton *button, -- GdmGreeterLoginWindow *login_window) -+on_login_button_clicked_timed_login (GtkButton *button, -+ GdmGreeterLoginWindow *login_window) - { -- GtkWidget *entry; -- const char *text; -- - set_busy (login_window); - set_sensitive (login_window, FALSE); - -- entry = glade_xml_get_widget (login_window->priv->xml, "auth-prompt-entry"); -- text = gtk_entry_get_text (GTK_ENTRY (entry)); -- - _gdm_greeter_login_window_set_interactive (login_window, TRUE); -- g_signal_emit (login_window, signals[QUERY_ANSWER], 0, "gdm", text); - } - - static void --on_login_button_clicked_timed_login (GtkButton *button, -- GdmGreeterLoginWindow *login_window) -+hide_task_actions (GdmTask *task) - { -- set_busy (login_window); -- set_sensitive (login_window, FALSE); -+ GtkActionGroup *actions; - -- _gdm_greeter_login_window_set_interactive (login_window, TRUE); -+ actions = gdm_conversation_get_actions (GDM_CONVERSATION (task)); -+ -+ if (actions != NULL) { -+ gtk_action_group_set_visible (actions, FALSE); -+ gtk_action_group_set_sensitive (actions, FALSE); -+ g_object_unref (actions); -+ } -+} -+ -+static void -+grab_default_button_for_task (GdmTask *task) -+{ -+ GtkActionGroup *actions; -+ GtkAction *action; -+ GSList *proxies, *node; -+ -+ actions = gdm_conversation_get_actions (GDM_CONVERSATION (task)); -+ -+ if (actions == NULL) { -+ return; -+ } -+ -+ action = gtk_action_group_get_action (actions, GDM_CONVERSATION_DEFAULT_ACTION); -+ g_object_unref (actions); -+ -+ if (action == NULL) { -+ return; -+ } -+ -+ proxies = gtk_action_get_proxies (action); -+ for (node = proxies; node != NULL; node = node->next) { -+ GtkWidget *widget; -+ -+ widget = GTK_WIDGET (node->data); -+ -+ if (GTK_WIDGET_CAN_DEFAULT (widget) && -+ GTK_WIDGET_VISIBLE (widget)) { -+ gtk_widget_grab_default (widget); -+ break; -+ } -+ } -+ -+} -+ -+static void -+show_task_actions (GdmTask *task) -+{ -+ GtkActionGroup *actions; -+ -+ actions = gdm_conversation_get_actions (GDM_CONVERSATION (task)); -+ -+ if (actions != NULL) { -+ gtk_action_group_set_sensitive (actions, TRUE); -+ gtk_action_group_set_visible (actions, TRUE); -+ g_object_unref (actions); -+ } - } - - static void -@@ -419,6 +485,7 @@ set_log_in_button_mode (GdmGreeterLoginWindow *login_window, - int mode) - { - GtkWidget *button; -+ GdmTask *task; - - button = glade_xml_get_widget (login_window->priv->xml, "log-in-button"); - gtk_widget_grab_default (button); -@@ -431,14 +498,27 @@ set_log_in_button_mode (GdmGreeterLoginWindow *login_window, - - switch (mode) { - case LOGIN_BUTTON_HIDDEN: -+ task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); -+ if (task != NULL) { -+ hide_task_actions (task); -+ g_object_unref (task); -+ } -+ - gtk_widget_hide (button); - break; - case LOGIN_BUTTON_ANSWER_QUERY: -- login_window->priv->login_button_handler_id = g_signal_connect (button, "clicked", G_CALLBACK (on_login_button_clicked_answer_query), login_window); -- gtk_widget_show (button); -+ task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); -+ if (task != NULL) { -+ show_task_actions (task); -+ grab_default_button_for_task (task); -+ g_object_unref (task); -+ } -+ -+ gtk_widget_hide (button); - break; - case LOGIN_BUTTON_TIMED_LOGIN: - login_window->priv->login_button_handler_id = g_signal_connect (button, "clicked", G_CALLBACK (on_login_button_clicked_timed_login), login_window); -+ - gtk_widget_show (button); - break; - default: -@@ -563,7 +643,7 @@ switch_mode (GdmGreeterLoginWindow *login_window, - show_widget (login_window, "disconnect-button", - ! login_window->priv->display_is_local); - -- show_widget (login_window, "auth-input-box", FALSE); -+ show_widget (login_window, "auth-page-box", FALSE); - - add_sensitize_power_buttons_timeout (login_window); - sensitize_widget (login_window, "shutdown-button", FALSE); -@@ -582,6 +662,7 @@ switch_mode (GdmGreeterLoginWindow *login_window, - show_widget (login_window, "restart-button", FALSE); - show_widget (login_window, "suspend-button", FALSE); - show_widget (login_window, "disconnect-button", FALSE); -+ show_widget (login_window, "auth-page-box", TRUE); - default_name = "log-in-button"; - break; - default: -@@ -661,25 +742,40 @@ do_suspend (GdmGreeterLoginWindow *login_window) - g_object_unref (proxy); - } - --static void --delete_entry_text (GtkWidget *entry) -+static gboolean -+task_has_service_name (GdmTaskList *task_list, -+ GdmTask *task, -+ const char *service_name) - { -- const char *typed_text; -- char *null_text; -+ char *task_service_name; -+ gboolean has_service_name; -+ -+ task_service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (task)); -+ -+ has_service_name = strcmp (service_name, task_service_name) == 0; -+ g_free (task_service_name); - -- /* try to scrub out any secret info */ -- typed_text = gtk_entry_get_text (GTK_ENTRY (entry)); -- null_text = g_strnfill (strlen (typed_text) + 1, '\b'); -- gtk_entry_set_text (GTK_ENTRY (entry), null_text); -- gtk_entry_set_text (GTK_ENTRY (entry), ""); -+ return has_service_name; -+} -+ -+static gboolean -+reset_task (GdmTaskList *task_list, -+ GdmTask *task, -+ GdmGreeterLoginWindow *login_window) -+{ -+ char *name; -+ -+ name = gdm_task_get_name (task); -+ g_debug ("Resetting task '%s'", name); -+ g_free (name); -+ -+ gdm_conversation_reset (GDM_CONVERSATION (task)); -+ return FALSE; - } - - static void - reset_dialog (GdmGreeterLoginWindow *login_window) - { -- GtkWidget *entry; -- GtkWidget *label; -- - g_debug ("GdmGreeterLoginWindow: Resetting dialog"); - set_busy (login_window); - set_sensitive (login_window, FALSE); -@@ -703,16 +799,12 @@ reset_dialog (GdmGreeterLoginWindow *login_window) - login_window->priv->start_session_handler_id = 0; - } - -- entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ reset_task, -+ login_window); - -- delete_entry_text (entry); -- -- gtk_entry_set_visibility (GTK_ENTRY (entry), TRUE); - set_message (login_window, ""); -- -- label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label"); -- gtk_label_set_text (GTK_LABEL (label), ""); -- - switch_mode (login_window, MODE_SELECTION); - - set_sensitive (login_window, TRUE); -@@ -732,11 +824,22 @@ do_cancel (GdmGreeterLoginWindow *login_window) - } - - gboolean --gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window) -+gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, -+ const char *service_name) - { -+ GdmTask *task; -+ - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - -- reset_dialog (login_window); -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) service_name); -+ -+ if (task != NULL) { -+ gdm_conversation_set_ready (GDM_CONVERSATION (task)); -+ g_object_unref (task); -+ } - - set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE); - set_ready (GDM_GREETER_LOGIN_WINDOW (login_window)); -@@ -745,13 +848,41 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window) - return TRUE; - } - -+static gboolean -+restart_task_conversation (GdmTaskList *task_list, -+ GdmTask *task, -+ GdmGreeterLoginWindow *login_window) -+{ -+ char *service_name; -+ -+ service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (task)); -+ if (service_name != NULL) { -+ char *name; -+ -+ name = gdm_task_get_name (task); -+ g_debug ("GdmGreeterLoginWindow: restarting '%s' conversation", name); -+ g_free (name); -+ -+ g_signal_emit (login_window, signals[START_CONVERSATION], 0, service_name); -+ g_free (service_name); -+ } -+ -+ return FALSE; -+} -+ - gboolean - gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window) - { -- g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); -+ g_debug ("GdmGreeterLoginWindow: window reset"); - -+ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - reset_dialog (GDM_GREETER_LOGIN_WINDOW (login_window)); - -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ restart_task_conversation, -+ login_window); -+ - return TRUE; - } - -@@ -760,12 +891,20 @@ gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window, - const char *service_name, - const char *text) - { -- g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); -+ GdmTask *task; - -+ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - g_debug ("GdmGreeterLoginWindow: info: %s", text); - -- if (strcmp (service_name, gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list))) == 0) { -- set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) service_name); -+ -+ if (task != NULL) { -+ gdm_conversation_set_message (GDM_CONVERSATION (task), -+ text); -+ g_object_unref (task); - } - - return TRUE; -@@ -776,13 +915,22 @@ gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, - const char *service_name, - const char *text) - { -- g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); -+ GdmTask *task; - -+ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - g_debug ("GdmGreeterLoginWindow: problem: %s", text); - -- if (strcmp (service_name, gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list))) == 0) { -- set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) service_name); -+ -+ if (task != NULL) { -+ gdm_conversation_set_message (GDM_CONVERSATION (task), -+ text); -+ g_object_unref (task); - } -+ - gdk_window_beep (GTK_WIDGET (login_window)->window); - - return TRUE; -@@ -820,11 +968,21 @@ gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_windo - } - - static void --gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_window) -+on_ready_to_start_session (GdmGreeterLoginWindow *login_window, -+ GParamSpec *param_spec, -+ char *service_name) -+{ -+ gdm_greeter_login_window_start_session_when_ready (login_window, service_name); -+ g_free (service_name); -+} -+ -+static void -+gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_window, -+ const char *service_name) - { - if (login_window->priv->is_interactive) { - g_debug ("GdmGreeterLoginWindow: starting session"); -- g_signal_emit (login_window, signals[START_SESSION], 0); -+ g_signal_emit (login_window, signals[START_SESSION], 0, service_name); - } else { - g_debug ("GdmGreeterLoginWindow: not starting session since " - "user hasn't had an opportunity to pick language " -@@ -834,8 +992,8 @@ gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_ - */ - login_window->priv->start_session_handler_id = - g_signal_connect (login_window, "notify::is-interactive", -- G_CALLBACK (gdm_greeter_login_window_start_session_when_ready), -- NULL); -+ G_CALLBACK (on_ready_to_start_session), -+ g_strdup (service_name)); - - /* FIXME: If the user wasn't asked any questions by pam but - * pam still authorized them (passwd -d, or the questions got -@@ -861,26 +1019,24 @@ gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, - const char *service_name, - const char *text) - { -- GtkWidget *entry; -- GtkWidget *label; -+ GdmTask *task; - - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - -- if (strcmp (service_name, gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list))) != 0) { -- return TRUE; -- } -- - g_debug ("GdmGreeterLoginWindow: info query: %s", text); - -- entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); -- delete_entry_text (entry); -- gtk_entry_set_visibility (GTK_ENTRY (entry), TRUE); -- set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY); -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) service_name); - -- label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label"); -- gtk_label_set_text (GTK_LABEL (label), text); -+ if (task != NULL) { -+ gdm_conversation_ask_question (GDM_CONVERSATION (task), -+ text); -+ g_object_unref (task); -+ } - -- show_widget (login_window, "auth-input-box", TRUE); -+ set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY); - set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE); - set_ready (GDM_GREETER_LOGIN_WINDOW (login_window)); - set_focus (GDM_GREETER_LOGIN_WINDOW (login_window)); -@@ -895,20 +1051,23 @@ gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, - const char *service_name, - const char *text) - { -- GtkWidget *entry; -- GtkWidget *label; -+ -+ GdmTask *task; - - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - -- entry = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-entry"); -- delete_entry_text (entry); -- gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE); -- set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY); -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) service_name); - -- label = glade_xml_get_widget (GDM_GREETER_LOGIN_WINDOW (login_window)->priv->xml, "auth-prompt-label"); -- gtk_label_set_text (GTK_LABEL (label), text); -+ if (task != NULL) { -+ gdm_conversation_ask_secret (GDM_CONVERSATION (task), -+ text); -+ g_object_unref (task); -+ } - -- show_widget (login_window, "auth-input-box", TRUE); -+ set_log_in_button_mode (login_window, LOGIN_BUTTON_ANSWER_QUERY); - set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE); - set_ready (GDM_GREETER_LOGIN_WINDOW (login_window)); - set_focus (GDM_GREETER_LOGIN_WINDOW (login_window)); -@@ -919,13 +1078,16 @@ gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, - } - - void --gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window) -+gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); - -- g_debug ("GdmGreeterLoginWindow: user now authorized"); -+ g_debug ("GdmGreeterLoginWindow: user now authorized via service %s", -+ service_name); - -- gdm_greeter_login_window_start_session_when_ready (login_window); -+ gdm_greeter_login_window_start_session_when_ready (login_window, -+ service_name); - } - - static void -@@ -1348,6 +1510,46 @@ on_users_loaded (GdmUserChooserWidget *user_chooser, - gdm_chooser_widget_activate_if_one_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser)); - } - -+static gboolean -+begin_task_verification (GdmTaskList *task_list, -+ GdmTask *task, -+ GdmGreeterLoginWindow *login_window) -+{ -+ char *service_name; -+ -+ service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (task)); -+ if (service_name != NULL) { -+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, service_name); -+ g_free (service_name); -+ } -+ -+ return FALSE; -+} -+ -+static gboolean -+begin_task_verification_for_selected_user (GdmTaskList *task_list, -+ GdmTask *task, -+ GdmGreeterLoginWindow *login_window) -+{ -+ char *user_name; -+ char *service_name; -+ -+ user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser)); -+ -+ if (user_name == NULL) { -+ return TRUE; -+ } -+ -+ service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (task)); -+ if (service_name != NULL) { -+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, service_name, user_name); -+ g_free (service_name); -+ } -+ -+ g_free (user_name); -+ return FALSE; -+} -+ - static void - on_user_chosen (GdmUserChooserWidget *user_chooser, - GdmGreeterLoginWindow *login_window) -@@ -1365,10 +1567,10 @@ on_user_chosen (GdmUserChooserWidget *user_chooser, - 0, user_name); - - if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) { -- const char *service_name; -- -- service_name = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); -- g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, service_name); -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ begin_task_verification, -+ login_window); - } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_GUEST) == 0) { - /* FIXME: handle guest account stuff */ - } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_AUTO) == 0) { -@@ -1382,10 +1584,10 @@ on_user_chosen (GdmUserChooserWidget *user_chooser, - set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); - set_message (login_window, _("Select language and click Log In")); - } else { -- const char *service_name; -- -- service_name = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); -- g_signal_emit (login_window, signals[BEGIN_VERIFICATION_FOR_USER], 0, service_name, user_name); -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ begin_task_verification_for_selected_user, -+ login_window); - } - - switch_mode (login_window, MODE_AUTHENTICATION); -@@ -1531,17 +1733,65 @@ create_computer_info (GdmGreeterLoginWindow *login_window) - - static void - on_task_activated (GdmGreeterLoginWindow *login_window, -- const char *name) -+ GdmTask *task) - { -- g_debug ("GdmGreeterLoginWindow: starting conversation with '%s'", name); -- g_signal_emit (login_window, signals[START_CONVERSATION], 0, name); -+ GtkWidget *container; -+ char *name; -+ -+ name = gdm_task_get_name (task); -+ g_debug ("GdmGreeterLoginWindow: task '%s' activated", name); -+ g_free (name); -+ -+ container = g_object_get_data (G_OBJECT (task), -+ "gdm-greeter-login-window-page-container"); -+ -+ if (container == NULL) { -+ GtkWidget *page; -+ -+ container = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); -+ gtk_container_add (GTK_CONTAINER (login_window->priv->auth_page_box), -+ container); -+ -+ page = gdm_conversation_get_page (GDM_CONVERSATION (task)); -+ if (page != NULL) { -+ gtk_container_add (GTK_CONTAINER (container), page); -+ gtk_widget_show (page); -+ } -+ g_object_set_data (G_OBJECT (task), -+ "gdm-greeter-login-window-page-container", -+ container); -+ } -+ -+ gtk_widget_show (container); -+ set_log_in_button_mode (login_window, login_window->priv->dialog_mode); - } - - static void - on_task_deactivated (GdmGreeterLoginWindow *login_window, -- const char *name) -+ GdmTask *task) - { -- g_debug ("GdmGreeterLoginWindow: conversation '%s' now in background", name); -+ GtkWidget *container; -+ char *name; -+ GtkActionGroup *actions; -+ -+ name = gdm_task_get_name (task); -+ g_debug ("GdmGreeterLoginWindow: task '%s' now in background", name); -+ g_free (name); -+ -+ container = g_object_get_data (G_OBJECT (task), -+ "gdm-greeter-login-window-page-container"); -+ -+ if (container != NULL) { -+ gtk_widget_hide (container); -+ } -+ -+ actions = gdm_conversation_get_actions (GDM_CONVERSATION (task)); -+ -+ if (actions != NULL) { -+ gtk_action_group_set_sensitive (actions, FALSE); -+ gtk_action_group_set_visible (actions, FALSE); -+ g_object_unref (actions); -+ } - } - - static GtkWidget * -@@ -1578,7 +1828,6 @@ custom_widget_constructor (GladeXML *xml, - static void - load_theme (GdmGreeterLoginWindow *login_window) - { -- GtkWidget *entry; - GtkWidget *button; - GtkWidget *box; - GtkWidget *image; -@@ -1653,15 +1902,9 @@ load_theme (GdmGreeterLoginWindow *login_window) - login_window); - gtk_widget_show (login_window->priv->conversation_list); - -- gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- "password-auth", "dialog-password"); -- gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- "fingerprint-auth", "stock_allow-effects"); -- gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- "smartcard-auth", "badge-small"); -- - login_window->priv->auth_banner_label = glade_xml_get_widget (login_window->priv->xml, "auth-banner-label"); - /*make_label_small_italic (login_window->priv->auth_banner_label);*/ -+ login_window->priv->auth_page_box = glade_xml_get_widget (login_window->priv->xml, "auth-page-box"); - - button = glade_xml_get_widget (login_window->priv->xml, "suspend-button"); - g_signal_connect (button, "clicked", G_CALLBACK (suspend_button_clicked), login_window); -@@ -1677,14 +1920,6 @@ load_theme (GdmGreeterLoginWindow *login_window) - button = glade_xml_get_widget (login_window->priv->xml, "shutdown-button"); - g_signal_connect (button, "clicked", G_CALLBACK (shutdown_button_clicked), login_window); - -- entry = glade_xml_get_widget (login_window->priv->xml, "auth-prompt-entry"); -- /* Only change the invisible character if it '*' otherwise assume it is OK */ -- if ('*' == gtk_entry_get_invisible_char (GTK_ENTRY (entry))) { -- gunichar invisible_char; -- invisible_char = INVISIBLE_CHAR_BLACK_CIRCLE; -- gtk_entry_set_invisible_char (GTK_ENTRY (entry), invisible_char); -- } -- - create_computer_info (login_window); - - box = glade_xml_get_widget (login_window->priv->xml, "computer-info-event-box"); -@@ -1902,9 +2137,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) - G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, start_session), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); - - g_object_class_install_property (object_class, - PROP_DISPLAY_IS_LOCAL, -@@ -1957,6 +2192,187 @@ on_gconf_key_changed (GConfClient *client, - } - } - -+static void -+on_conversation_answer (GdmGreeterLoginWindow *login_window, -+ const char *text, -+ GdmConversation *conversation) -+{ -+ if (text != NULL) { -+ char *service_name; -+ -+ service_name = gdm_conversation_get_service_name (conversation); -+ if (service_name != NULL) { -+ g_signal_emit (login_window, signals[QUERY_ANSWER], 0, service_name, text); -+ g_free (service_name); -+ } -+ } -+ -+ set_sensitive (login_window, TRUE); -+ set_ready (login_window); -+} -+ -+void -+gdm_greeter_login_window_remove_extension (GdmGreeterLoginWindow *login_window, -+ GdmGreeterExtension *extension) -+{ -+ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); -+ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION (extension)); -+ -+ if (!GDM_IS_CONVERSATION (extension)) { -+ return; -+ } -+} -+ -+static void -+on_button_action_label_changed (GtkWidget *button) -+{ -+ GtkAction *action; -+ char *text; -+ -+ action = gtk_widget_get_action (button); -+ -+ g_object_get (G_OBJECT (action), "label", &text, NULL); -+ -+ gtk_button_set_label (GTK_BUTTON (button), text); -+ g_free (text); -+} -+ -+static void -+on_button_action_icon_name_changed (GtkWidget *button) -+{ -+ GtkAction *action; -+ GtkWidget *image; -+ -+ action = gtk_widget_get_action (button); -+ -+ image = gtk_action_create_icon (GTK_ACTION (action), GTK_ICON_SIZE_BUTTON); -+ gtk_button_set_image (GTK_BUTTON (button), image); -+} -+ -+static void -+on_button_action_tooltip_changed (GtkWidget *button) -+{ -+ GtkAction *action; -+ char *text; -+ -+ action = gtk_widget_get_action (button); -+ -+ g_object_get (G_OBJECT (action), "tooltip", &text, NULL); -+ -+ gtk_widget_set_tooltip_text (button, text); -+ g_free (text); -+} -+ -+GtkWidget * -+create_button_from_action (GtkAction *action) -+{ -+ GtkWidget *button; -+ -+ button = gtk_button_new (); -+ -+ gtk_action_connect_proxy (GTK_ACTION (action), button); -+ -+ g_signal_connect_swapped (action, -+ "notify::label", -+ G_CALLBACK (on_button_action_label_changed), -+ button); -+ g_signal_connect_swapped (action, -+ "notify::icon-name", -+ G_CALLBACK (on_button_action_icon_name_changed), -+ button); -+ g_signal_connect_swapped (action, -+ "notify::tooltip", -+ G_CALLBACK (on_button_action_tooltip_changed), -+ button); -+ -+ on_button_action_label_changed (button); -+ on_button_action_icon_name_changed (button); -+ on_button_action_tooltip_changed (button); -+ -+ if (strcmp (gtk_action_get_name (action), -+ GDM_CONVERSATION_DEFAULT_ACTION) == 0) { -+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); -+ } -+ -+ return button; -+} -+ -+static void -+create_buttons_for_actions (GdmGreeterLoginWindow *login_window, -+ GtkActionGroup *actions) -+{ -+ GList *action_list; -+ GList *node; -+ GtkWidget *box; -+ -+ action_list = gtk_action_group_list_actions (actions); -+ -+ box = glade_xml_get_widget (login_window->priv->xml, "buttonbox"); -+ for (node = action_list; node != NULL; node = node->next) { -+ GtkAction *action; -+ GtkWidget *button; -+ -+ action = node->data; -+ -+ button = create_button_from_action (action); -+ gtk_container_add (GTK_CONTAINER (box), button); -+ } -+ -+ g_list_free (action_list); -+} -+ -+void -+gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, -+ GdmGreeterExtension *extension) -+{ -+ char *name; -+ char *description; -+ char *service_name; -+ GtkActionGroup *actions; -+ -+ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window)); -+ g_return_if_fail (GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION (extension)); -+ -+ if (!GDM_IS_CONVERSATION (extension)) { -+ return; -+ } -+ -+ actions = gdm_conversation_get_actions (GDM_CONVERSATION (extension)); -+ -+ create_buttons_for_actions (login_window, actions); -+ hide_task_actions (GDM_TASK (extension)); -+ -+ g_object_unref (actions); -+ -+ g_signal_connect_swapped (GDM_CONVERSATION (extension), -+ "answer", -+ G_CALLBACK (on_conversation_answer), -+ login_window); -+ -+ name = gdm_task_get_name (GDM_TASK (extension)); -+ description = gdm_task_get_description (GDM_TASK (extension)); -+ -+ g_debug ("GdmGreeterLoginWindow: new extension '%s - %s' added", -+ name, description); -+ -+ g_free (name); -+ g_free (description); -+ -+ if (gdm_task_list_get_number_of_tasks (GDM_TASK_LIST (login_window->priv->conversation_list)) == 0) { -+ gtk_widget_hide (login_window->priv->conversation_list); -+ } else { -+ gtk_widget_show (login_window->priv->conversation_list); -+ } -+ -+ gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ GDM_TASK (extension)); -+ -+ service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (extension)); -+ g_debug ("GdmGreeterLoginWindow: starting conversation with '%s'", service_name); -+ g_signal_emit (login_window, signals[START_CONVERSATION], 0, service_name); -+ g_free (service_name); -+} -+ - static gboolean - on_window_state_event (GtkWidget *widget, - GdkEventWindowState *event, -diff --git a/gui/simple-greeter/gdm-greeter-login-window.glade b/gui/simple-greeter/gdm-greeter-login-window.glade -index a3ae5ba..9933437 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.glade -+++ b/gui/simple-greeter/gdm-greeter-login-window.glade -@@ -611,30 +611,29 @@ - - - -- -- True -- -- False -- False -- GTK_JUSTIFY_CENTER -- True -- False -- 0.5 -- 0.5 -- 0 -- 0 -- PANGO_ELLIPSIZE_NONE -- -1 -- False -- 0 -- -- -- 0 -- True -- True -- -+ -+ True -+ -+ False -+ False -+ GTK_JUSTIFY_CENTER -+ True -+ False -+ 0.5 -+ 0.5 -+ 0 -+ 0 -+ PANGO_ELLIPSIZE_NONE -+ -1 -+ False -+ 0 -+ -+ -+ 0 -+ False -+ False -+ - -- - - - True -@@ -660,20 +659,6 @@ - 0 - - -- -- True -- 0 -- 0 -- Tue, 18 Nov 2008 21:55:38 GMT -- -- -- 0 -- True -- True -- -- -- -- - - True - 0 -@@ -686,57 +671,13 @@ - False - - -- -- -- 0 -- True -- True -- -- -- -- -- -- True -- False -- 6 - - -- -- True -- -- False -- False -- GTK_JUSTIFY_LEFT -- False -- False -- 0.5 -- 0.5 -- 0 -- 0 -- PANGO_ELLIPSIZE_NONE -- -1 -- False -- 0 -- -- -- 0 -- False -- False -- -- -- -- -- -+ - True -- True -- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK -- True -- True -- 0 -- -- True -- • -- True -+ 0 -+ 0 -+ Tue, 18 Nov 2008 21:55:38 GMT - - - 0 -@@ -745,46 +686,21 @@ - - - -- -- -- - - - 0 -- False -- False -+ True -+ True - - - - -- -+ - True - False - 0 -- - -- -- True -- -- False -- False -- GTK_JUSTIFY_LEFT -- False -- False -- 0.5 -- 0.5 -- 0 -- 0 -- PANGO_ELLIPSIZE_NONE -- -1 -- False -- 0 -- -- -- 0 -- True -- True -- -+ - - - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.h b/gui/simple-greeter/gdm-greeter-login-window.h -index 559b26b..eda7f89 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.h -+++ b/gui/simple-greeter/gdm-greeter-login-window.h -@@ -23,6 +23,9 @@ - #define __GDM_GREETER_LOGIN_WINDOW_H - - #include -+#include "gdm-conversation.h" -+#include "gdm-task.h" -+#include "gdm-greeter-extension.h" - - G_BEGIN_DECLS - -@@ -33,6 +36,8 @@ G_BEGIN_DECLS - #define GDM_IS_GREETER_LOGIN_WINDOW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_GREETER_LOGIN_WINDOW)) - #define GDM_GREETER_LOGIN_WINDOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_GREETER_LOGIN_WINDOW, GdmGreeterLoginWindowClass)) - -+#define GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION(e) (GDM_IS_CONVERSATION(e) && GDM_IS_TASK(e)) -+ - typedef struct GdmGreeterLoginWindowPrivate GdmGreeterLoginWindowPrivate; - - typedef struct -@@ -62,7 +67,8 @@ typedef struct - const char *text); - void (* cancelled) (GdmGreeterLoginWindow *login_window); - void (* disconnected) (GdmGreeterLoginWindow *login_window); -- void (* start_session) (GdmGreeterLoginWindow *login_window); -+ void (* start_session) (GdmGreeterLoginWindow *login_window, -+ const char *sevice_name); - - } GdmGreeterLoginWindowClass; - -@@ -71,7 +77,8 @@ GtkWidget * gdm_greeter_login_window_new (gboolean displa - - - gboolean gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window); --gboolean gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window); -+gboolean gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, -+ const char *service_name); - gboolean gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, - const char *service_name, - const char *text); -@@ -88,7 +95,13 @@ gboolean gdm_greeter_login_window_problem (GdmGreeterLogin - void gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, - const char *username, - int delay); --void gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window); -+void gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window, -+ const char *service_name); -+ -+void gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, -+ GdmGreeterExtension *extension); -+void gdm_greeter_login_window_remove_extension (GdmGreeterLoginWindow *login_window, -+ GdmGreeterExtension *extension); - - G_END_DECLS - -diff --git a/gui/simple-greeter/gdm-greeter-plugin.c b/gui/simple-greeter/gdm-greeter-plugin.c -new file mode 100644 -index 0000000..821b679 ---- /dev/null -+++ b/gui/simple-greeter/gdm-greeter-plugin.c -@@ -0,0 +1,251 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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 -+ * -+ * Written by: Ray Strode -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "gdm-greeter-extension.h" -+#include "gdm-greeter-plugin.h" -+ -+#define GDM_GREETER_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_PLUGIN, GdmGreeterPluginPrivate)) -+ -+enum { -+ PROP_0, -+ PROP_FILENAME, -+}; -+ -+enum { -+ LOADED, -+ LOAD_FAILED, -+ UNLOADED, -+ LAST_SIGNAL -+}; -+ -+struct _GdmGreeterPluginPrivate { -+ GObject parent; -+ -+ GModule *module; -+ char *filename; -+ -+ GdmGreeterExtension *extension; -+}; -+ -+static void gdm_greeter_plugin_finalize (GObject *object); -+ -+static guint signals[LAST_SIGNAL] = { 0 }; -+ -+G_DEFINE_TYPE (GdmGreeterPlugin, gdm_greeter_plugin, G_TYPE_OBJECT) -+ -+static void -+gdm_greeter_plugin_set_property (GObject *object, -+ guint param_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ GdmGreeterPlugin *plugin; -+ -+ plugin = GDM_GREETER_PLUGIN (object); -+ switch (param_id) { -+ case PROP_FILENAME: -+ plugin->priv->filename = g_strdup (g_value_get_string (value)); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); -+ break; -+ } -+} -+ -+static void -+gdm_greeter_plugin_get_property (GObject *object, -+ guint param_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ GdmGreeterPlugin *plugin; -+ -+ plugin = GDM_GREETER_PLUGIN (object); -+ -+ switch (param_id) { -+ case PROP_FILENAME: -+ g_value_set_string (value, plugin->priv->filename); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); -+ break; -+ } -+} -+ -+static void -+gdm_greeter_plugin_class_init (GdmGreeterPluginClass *class) -+{ -+ GObjectClass *gobject_class; -+ -+ gobject_class = G_OBJECT_CLASS (class); -+ -+ gobject_class->set_property = gdm_greeter_plugin_set_property; -+ gobject_class->get_property = gdm_greeter_plugin_get_property; -+ gobject_class->finalize = gdm_greeter_plugin_finalize; -+ -+ g_object_class_install_property (gobject_class, -+ PROP_FILENAME, -+ g_param_spec_string ("filename", -+ "Filename", -+ "The full path to the plugin.", -+ NULL, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -+ -+ signals [LOADED] = -+ g_signal_new ("loaded", -+ G_TYPE_FROM_CLASS (class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmGreeterPluginClass, loaded), -+ NULL, NULL, -+ g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); -+ signals [LOAD_FAILED] = -+ g_signal_new ("load-failed", -+ G_TYPE_FROM_CLASS (class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmGreeterPluginClass, load_failed), -+ NULL, NULL, -+ g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); -+ signals [UNLOADED] = -+ g_signal_new ("unloaded", -+ G_TYPE_FROM_CLASS (class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmGreeterPluginClass, unloaded), -+ NULL, NULL, -+ g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); -+ -+ g_type_class_add_private (class, sizeof (GdmGreeterPluginPrivate)); -+} -+ -+GdmGreeterPlugin * -+gdm_greeter_plugin_new (const char *filename) -+{ -+ GObject *object; -+ -+ object = g_object_new (GDM_TYPE_GREETER_PLUGIN, -+ "filename", filename, NULL); -+ -+ return GDM_GREETER_PLUGIN (object); -+} -+ -+void -+gdm_greeter_plugin_load (GdmGreeterPlugin *plugin) -+{ -+ GModule *module; -+ GdmGreeterExtension *extension; -+ union { -+ gpointer symbol; -+ GdmGreeterPluginGetExtensionFunc invoke; -+ } get_extension; -+ -+ module = g_module_open (plugin->priv->filename, G_MODULE_BIND_LOCAL); -+ -+ if (module == NULL) { -+ g_signal_emit (plugin, signals [LOAD_FAILED], 0); -+ return; -+ } -+ -+ if (!g_module_symbol (module, -+ "gdm_greeter_plugin_get_extension", -+ &get_extension.symbol) || -+ !get_extension.symbol) { -+ g_warning ("plugin %s lacks gdm_greeter_plugin_get_extension()", -+ plugin->priv->filename); -+ g_module_close (module); -+ g_signal_emit (plugin, signals [LOAD_FAILED], 0); -+ return; -+ } -+ -+ extension = get_extension.invoke (); -+ -+ if (!extension) { -+ g_warning ("plugin %s didn't return extension when asked", -+ plugin->priv->filename); -+ g_module_close (module); -+ g_signal_emit (plugin, signals [LOAD_FAILED], 0); -+ } -+ -+ if (!GDM_IS_GREETER_EXTENSION (extension)) { -+ g_warning ("plugin %s returned bogus extension when asked", -+ plugin->priv->filename); -+ g_module_close (module); -+ g_signal_emit (plugin, signals [LOAD_FAILED], 0); -+ } -+ -+ plugin->priv->module = module; -+ plugin->priv->extension = extension; -+ -+ g_signal_emit (plugin, signals [LOADED], 0); -+} -+ -+void -+gdm_greeter_plugin_unload (GdmGreeterPlugin *plugin) -+{ -+ if (plugin->priv->extension != NULL) { -+ g_object_unref (plugin->priv->extension); -+ plugin->priv->extension = NULL; -+ } -+ -+ if (plugin->priv->module != NULL) { -+ g_module_close (plugin->priv->module); -+ plugin->priv->module = NULL; -+ } -+} -+ -+const char * -+gdm_greeter_plugin_get_filename (GdmGreeterPlugin *plugin) -+{ -+ return plugin->priv->filename; -+} -+ -+GdmGreeterExtension * -+gdm_greeter_plugin_get_extension (GdmGreeterPlugin *plugin) -+{ -+ return g_object_ref (plugin->priv->extension); -+} -+ -+static void -+gdm_greeter_plugin_init (GdmGreeterPlugin *plugin) -+{ -+ plugin->priv = GDM_GREETER_PLUGIN_GET_PRIVATE (plugin); -+} -+ -+static void -+gdm_greeter_plugin_finalize (GObject *object) -+{ -+ GdmGreeterPlugin *plugin; -+ -+ plugin = GDM_GREETER_PLUGIN (object); -+ -+ gdm_greeter_plugin_unload (plugin); -+} -+ -diff --git a/gui/simple-greeter/gdm-greeter-plugin.h b/gui/simple-greeter/gdm-greeter-plugin.h -new file mode 100644 -index 0000000..904c231 ---- /dev/null -+++ b/gui/simple-greeter/gdm-greeter-plugin.h -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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 -+ */ -+ -+#ifndef __GDM_GREETER_PLUGIN -+#define __GDM_GREETER_PLUGIN -+ -+#include -+#include -+ -+#include "gdm-greeter-extension.h" -+ -+G_BEGIN_DECLS -+ -+#define GDM_TYPE_GREETER_PLUGIN (gdm_greeter_plugin_get_type ()) -+#define GDM_GREETER_PLUGIN(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDM_TYPE_GREETER_PLUGIN, GdmGreeterPlugin)) -+#define GDM_IS_GREETER_PLUGIN(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDM_TYPE_GREETER_PLUGIN)) -+ -+typedef struct _GdmGreeterPlugin GdmGreeterPlugin; -+typedef struct _GdmGreeterPluginPrivate GdmGreeterPluginPrivate; -+typedef struct _GdmGreeterPluginClass GdmGreeterPluginClass; -+ -+struct _GdmGreeterPlugin -+{ -+ GObject parent; -+ GdmGreeterPluginPrivate *priv; -+}; -+ -+struct _GdmGreeterPluginClass -+{ -+ GObjectClass parent_class; -+ -+ void (* loaded) (GdmGreeterPlugin *plugin); -+ void (* load_failed) (GdmGreeterPlugin *plugin); -+ void (* unloaded) (GdmGreeterPlugin *plugin); -+}; -+ -+GType gdm_greeter_plugin_get_type (void) G_GNUC_CONST; -+GdmGreeterPlugin *gdm_greeter_plugin_new (const char *filename); -+void gdm_greeter_plugin_load (GdmGreeterPlugin *plugin); -+void gdm_greeter_plugin_unload (GdmGreeterPlugin *plugin); -+const char *gdm_greeter_plugin_get_filename (GdmGreeterPlugin *plugin); -+GdmGreeterExtension *gdm_greeter_plugin_get_extension (GdmGreeterPlugin *plugin); -+ -+G_END_DECLS -+ -+#endif -diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c -index 79f367c..d8fd861 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -38,6 +38,8 @@ - #include "gdm-greeter-panel.h" - #include "gdm-greeter-login-window.h" - -+#include "gdm-plugin-manager.h" -+ - #include "gdm-profile.h" - - #define GDM_GREETER_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_SESSION, GdmGreeterSessionPrivate)) -@@ -45,9 +47,11 @@ - struct GdmGreeterSessionPrivate - { - GdmGreeterClient *client; -+ GdmPluginManager *plugin_manager; - - GtkWidget *login_window; - GtkWidget *panel; -+ - }; - - enum { -@@ -91,7 +95,8 @@ on_ready (GdmGreeterClient *client, - { - g_debug ("GdmGreeterSession: Ready"); - -- gdm_greeter_login_window_ready (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window)); -+ gdm_greeter_login_window_ready (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), -+ service_name); - } - - static void -@@ -154,10 +159,11 @@ on_timed_login_requested (GdmGreeterClient *client, - - static void - on_user_authorized (GdmGreeterClient *client, -+ const char *service_name, - GdmGreeterSession *session) - { - g_debug ("GdmGreeterSession: user authorized"); -- gdm_greeter_login_window_user_authorized (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window)); -+ gdm_greeter_login_window_user_authorized (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name); - } - - static void -@@ -270,7 +276,6 @@ on_cancelled (GdmGreeterLoginWindow *login_window, - { - gdm_greeter_panel_hide_user_options (GDM_GREETER_PANEL (session->priv->panel)); - gdm_greeter_client_call_cancel (session->priv->client); -- gdm_greeter_client_call_start_conversation (session->priv->client, "gdm"); - } - - static void -@@ -282,9 +287,10 @@ on_disconnected (GdmGreeterLoginWindow *login_window, - - static void - on_start_session (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - GdmGreeterSession *session) - { -- gdm_greeter_client_call_start_session_when_ready (session->priv->client, "gdm", TRUE); -+ gdm_greeter_client_call_start_session_when_ready (session->priv->client, service_name, TRUE); - } - - static void -@@ -400,8 +406,6 @@ gdm_greeter_session_start (GdmGreeterSession *session, - toggle_panel (session, TRUE); - toggle_login_window (session, TRUE); - -- gdm_greeter_client_call_start_conversation (session->priv->client, "gdm"); -- - gdm_profile_end (NULL); - - return res; -@@ -511,6 +515,64 @@ gdm_greeter_session_event_handler (GdkEvent *event, - } + } GdmGreeterLoginWindowClass; - static void -+on_plugins_loaded (GdmGreeterSession *session) -+{ -+ g_debug ("GdmGreeterSession: done loading plugins"); -+} -+ -+static void -+on_plugin_removed (GdmGreeterSession *session, -+ GdmGreeterPlugin *plugin) -+{ -+ GdmGreeterExtension *extension; -+ -+ extension = gdm_greeter_plugin_get_extension (plugin); -+ -+ if (GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION (extension)) { -+ gdm_greeter_login_window_remove_extension (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), extension); -+ } -+ g_object_unref (extension); -+} -+ -+static void -+on_plugin_added (GdmGreeterSession *session, -+ GdmGreeterPlugin *plugin) -+{ -+ GdmGreeterExtension *extension; -+ -+ extension = gdm_greeter_plugin_get_extension (plugin); -+ -+ if (GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION (extension)) { -+ gdm_greeter_login_window_add_extension (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), extension); -+ } -+ g_object_unref (extension); -+} -+ -+static void -+load_plugins (GdmGreeterSession *session) -+{ -+ g_debug ("GdmGreeterSession: loading plugins"); -+ -+ session->priv->plugin_manager = gdm_plugin_manager_ref_default (); -+ -+ g_signal_connect_swapped (session->priv->plugin_manager, -+ "plugins-loaded", -+ G_CALLBACK (on_plugins_loaded), -+ session); -+ -+ g_signal_connect_swapped (session->priv->plugin_manager, -+ "plugin-added", -+ G_CALLBACK (on_plugin_added), -+ session); -+ -+ g_signal_connect_swapped (session->priv->plugin_manager, -+ "plugin-removed", -+ G_CALLBACK (on_plugin_removed), -+ session); -+ -+} -+ -+static void - gdm_greeter_session_init (GdmGreeterSession *session) - { - gdm_profile_start (NULL); -@@ -573,6 +635,8 @@ gdm_greeter_session_init (GdmGreeterSession *session) - gdk_event_handler_set ((GdkEventFunc) gdm_greeter_session_event_handler, - session, NULL); +@@ -66,20 +77,33 @@ GtkWidget * gdm_greeter_login_wi -+ -+ load_plugins (session); - gdm_profile_end (NULL); - } -diff --git a/gui/simple-greeter/gdm-plugin-manager.c b/gui/simple-greeter/gdm-plugin-manager.c -new file mode 100644 -index 0000000..49e442c ---- /dev/null -+++ b/gui/simple-greeter/gdm-plugin-manager.c -@@ -0,0 +1,478 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written By: Ray Strode -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "gdm-plugin-manager.h" -+#include "gdm-greeter-extension.h" -+ -+#define GDM_PLUGIN_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_PLUGIN_MANAGER, GdmPluginManagerPrivate)) -+ -+typedef struct -+{ -+ GModule *module; -+ char *filename; -+ GdmGreeterExtension *extension; -+} GdmPluginManagerPlugin; -+ -+typedef struct -+{ -+ GdmPluginManager *manager; -+ GCancellable *cancellable; -+} GdmPluginManagerOperation; -+ -+struct GdmPluginManagerPrivate -+{ -+ GHashTable *plugins; -+ -+ GFileMonitor *plugin_dir_monitor; -+ GList *pending_operations; -+}; -+ -+enum { -+ PLUGINS_LOADED, -+ PLUGIN_ADDED, -+ PLUGIN_REMOVED, -+ LAST_SIGNAL -+}; -+ -+static guint signals [LAST_SIGNAL] = { 0, }; -+ -+static void gdm_plugin_manager_class_init (GdmPluginManagerClass *klass); -+static void gdm_plugin_manager_init (GdmPluginManager *plugin_manager); -+static void gdm_plugin_manager_finalize (GObject *object); -+ -+static GObject *plugin_manager_object = NULL; -+ -+G_DEFINE_TYPE (GdmPluginManager, gdm_plugin_manager, G_TYPE_OBJECT) -+ -+static GdmPluginManagerOperation * -+start_operation (GdmPluginManager *manager) -+{ -+ GdmPluginManagerOperation *operation; -+ -+ operation = g_new0 (GdmPluginManagerOperation, 1); -+ operation->cancellable = g_cancellable_new (); -+ operation->manager = manager; -+ -+ return operation; -+} -+ -+static void -+free_operation (GdmPluginManagerOperation *operation) -+{ -+ if (operation->cancellable != NULL) { -+ g_object_unref (operation->cancellable); -+ operation->cancellable = NULL; -+ } -+ g_free (operation); -+} -+ -+static void -+cancel_operation (GdmPluginManagerOperation *operation) -+{ -+ if (operation->cancellable != NULL && -+ !g_cancellable_is_cancelled (operation->cancellable)) { -+ g_cancellable_cancel (operation->cancellable); -+ } -+ -+ free_operation (operation); -+} -+ -+static void -+gdm_plugin_manager_track_operation (GdmPluginManager *manager, -+ GdmPluginManagerOperation *operation) -+{ -+ manager->priv->pending_operations = -+ g_list_prepend (manager->priv->pending_operations, operation); -+} -+ -+static void -+gdm_plugin_manager_untrack_operation (GdmPluginManager *manager, -+ GdmPluginManagerOperation *operation) -+{ -+ manager->priv->pending_operations = -+ g_list_remove (manager->priv->pending_operations, operation); -+} + gboolean gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window); +-gboolean gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window); ++gboolean gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, ++ const char *service_name); ++gboolean gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_window, ++ const char *service_name); + gboolean gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text); + gboolean gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text); + gboolean gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text); + gboolean gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text); + + void gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, + const char *username, + int delay); +-void gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window); ++void gdm_greeter_login_window_user_authorized (GdmGreeterLoginWindow *login_window, ++ const char *service_name); + -+static void -+gdm_plugin_manager_cancel_pending_operations (GdmPluginManager *manager) -+{ -+ GList *node; ++void gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, ++ GdmGreeterExtension *extension); ++void gdm_greeter_login_window_remove_extension (GdmGreeterLoginWindow *login_window, ++ GdmGreeterExtension *extension); + + G_END_DECLS + +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/gdm-greeter-plugin.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/gdm-greeter-plugin.c 2009-03-03 17:45:05.729023372 -0500 +@@ -0,0 +1,255 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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 ++ * ++ * Written by: Ray Strode ++ */ + -+ node = manager->priv->pending_operations; -+ while (node != NULL) { -+ GList *next_node; -+ GdmPluginManagerOperation *operation; ++#include + -+ operation = node->data; -+ next_node = node->next; ++#include ++#include ++#include ++#include + -+ cancel_operation (operation); -+ manager->priv->pending_operations = -+ g_list_delete_link (manager->priv->pending_operations, -+ node); ++#include ++#include + -+ node = next_node; -+ } -+} ++#include "gdm-greeter-extension.h" ++#include "gdm-greeter-plugin.h" + -+static void -+gdm_plugin_manager_class_init (GdmPluginManagerClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++#define GDM_GREETER_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_PLUGIN, GdmGreeterPluginPrivate)) + -+ object_class->finalize = gdm_plugin_manager_finalize; ++enum { ++ PROP_0, ++ PROP_FILENAME, ++}; + -+ signals [PLUGINS_LOADED] = -+ g_signal_new ("plugins-loaded", -+ G_TYPE_FROM_CLASS (klass), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmPluginManagerClass, plugins_loaded), -+ NULL, NULL, -+ g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); -+ signals [PLUGIN_ADDED] = -+ g_signal_new ("plugin-added", -+ G_TYPE_FROM_CLASS (klass), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmPluginManagerClass, plugin_added), -+ NULL, NULL, -+ g_cclosure_marshal_VOID__OBJECT, -+ G_TYPE_NONE, 1, GDM_TYPE_GREETER_PLUGIN); -+ signals [PLUGIN_REMOVED] = -+ g_signal_new ("plugin-removed", -+ G_TYPE_FROM_CLASS (klass), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmPluginManagerClass, plugin_removed), -+ NULL, NULL, -+ g_cclosure_marshal_VOID__OBJECT, -+ G_TYPE_NONE, 1, GDM_TYPE_GREETER_PLUGIN); ++enum { ++ LOADED, ++ LOAD_FAILED, ++ UNLOADED, ++ LAST_SIGNAL ++}; + -+ g_type_class_add_private (klass, sizeof (GdmPluginManagerPrivate)); -+} ++struct _GdmGreeterPluginPrivate { ++ GObject parent; + -+static void -+on_plugin_loaded (GdmPluginManager *manager, -+ GdmGreeterPlugin *plugin) -+{ -+ g_debug ("GdmPluginManager: plugin '%s' loaded.", -+ gdm_greeter_plugin_get_filename (plugin)); -+ g_signal_emit (manager, signals [PLUGIN_ADDED], 0, plugin); -+} ++ GModule *module; ++ char *filename; + -+static void -+on_plugin_load_failed (GdmPluginManager *manager, -+ GdmGreeterPlugin *plugin) -+{ -+ const char *filename; ++ GdmGreeterExtension *extension; ++}; + -+ g_debug ("GdmPluginManager: plugin '%s' could not be loaded.", -+ gdm_greeter_plugin_get_filename (plugin)); -+ filename = gdm_greeter_plugin_get_filename (plugin); -+ g_hash_table_remove (manager->priv->plugins, filename); -+} ++static void gdm_greeter_plugin_finalize (GObject *object); + -+static void -+on_plugin_unloaded (GdmPluginManager *manager, -+ GdmGreeterPlugin *plugin) -+{ -+ const char *filename; ++static guint signals[LAST_SIGNAL] = { 0 }; + -+ filename = gdm_greeter_plugin_get_filename (plugin); -+ g_hash_table_remove (manager->priv->plugins, filename); -+} ++G_DEFINE_TYPE (GdmGreeterPlugin, gdm_greeter_plugin, G_TYPE_OBJECT) + +static void -+load_plugin (GdmPluginManager *manager, -+ const char *filename) ++gdm_greeter_plugin_set_property (GObject *object, ++ guint param_id, ++ const GValue *value, ++ GParamSpec *pspec) +{ + GdmGreeterPlugin *plugin; + -+ g_debug ("GdmPluginManager: loading plugin '%s'", filename); -+ -+ plugin = gdm_greeter_plugin_new (filename); -+ -+ g_signal_connect_swapped (plugin, "loaded", -+ G_CALLBACK (on_plugin_loaded), -+ manager); -+ g_signal_connect_swapped (plugin, "load-failed", -+ G_CALLBACK (on_plugin_load_failed), -+ manager); -+ g_signal_connect_swapped (plugin, "unloaded", -+ G_CALLBACK (on_plugin_unloaded), -+ manager); -+ g_hash_table_insert (manager->priv->plugins, -+ g_strdup (filename), plugin); -+ -+ gdm_greeter_plugin_load (plugin); -+} -+ -+static void -+on_plugin_info_read (GFileEnumerator *enumerator, -+ GAsyncResult *result, -+ GdmPluginManagerOperation *operation) -+{ -+ GdmPluginManager *manager; -+ GFile *plugin_dir_file; -+ GList *file_list, *node; -+ GError *error; -+ -+ manager = operation->manager; -+ error = NULL; -+ file_list = g_file_enumerator_next_files_finish (enumerator, -+ result, &error); -+ plugin_dir_file = g_file_enumerator_get_container (enumerator); -+ if (error != NULL) { -+ char *plugin_dir; -+ -+ plugin_dir = g_file_get_parse_name (plugin_dir_file); -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { -+ g_debug ("GdmPluginManager: Cancelled reading plugin directory %s", -+ plugin_dir); -+ } else { -+ g_warning ("GdmPluginManager: Unable to read plugin directory %s: %s", -+ plugin_dir, error->message); -+ } -+ g_free (plugin_dir); -+ g_error_free (error); -+ g_object_unref (plugin_dir_file); -+ gdm_plugin_manager_untrack_operation (manager, operation); -+ return; -+ } -+ -+#ifndef PLUGIN_ORDERING_FIGURED_OUT -+ node = file_list; -+ while (node != NULL) { -+ GFileInfo *info; -+ GFile *file; -+ char *path; -+ GList *next_node; -+ -+ next_node = node->next; -+ -+ info = (GFileInfo *) node->data; -+ -+ file = g_file_get_child (plugin_dir_file, -+ g_file_info_get_name (info)); -+ path = g_file_get_path (file); -+ -+ if (g_str_has_suffix (path, "password.so")) { -+ file_list = g_list_delete_link (file_list, node); -+ file_list = g_list_prepend (file_list, info); -+ next_node = NULL; -+ } -+ g_free (path); -+ g_object_unref (file); -+ -+ node = next_node; -+ } -+#endif -+ -+ node = file_list; -+ while (node != NULL) { -+ GFileInfo *info; -+ GFile *file; -+ char *path; -+ -+ info = (GFileInfo *) node->data; -+ -+ file = g_file_get_child (plugin_dir_file, -+ g_file_info_get_name (info)); -+ path = g_file_get_path (file); -+ -+ if (g_str_has_suffix (path, G_MODULE_SUFFIX)) { -+ load_plugin (manager, path); -+ } -+ g_free (path); -+ g_object_unref (file); -+ -+ node = node->next; ++ plugin = GDM_GREETER_PLUGIN (object); ++ switch (param_id) { ++ case PROP_FILENAME: ++ plugin->priv->filename = g_strdup (g_value_get_string (value)); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); ++ break; + } -+ g_object_unref (plugin_dir_file); -+ -+ gdm_plugin_manager_untrack_operation (manager, operation); -+ g_signal_emit (manager, signals [PLUGINS_LOADED], 0); -+ -+ g_list_free (file_list); +} + +static void -+on_plugin_dir_opened (GFile *plugin_dir_file, -+ GAsyncResult *result, -+ GdmPluginManagerOperation *open_operation) ++gdm_greeter_plugin_get_property (GObject *object, ++ guint param_id, ++ GValue *value, ++ GParamSpec *pspec) +{ -+ GdmPluginManager *manager; -+ GFileEnumerator *enumerator; -+ GError *error; -+ GdmPluginManagerOperation *operation; ++ GdmGreeterPlugin *plugin; + -+ manager = open_operation->manager; -+ gdm_plugin_manager_untrack_operation (manager, open_operation); ++ plugin = GDM_GREETER_PLUGIN (object); + -+ error = NULL; -+ enumerator = g_file_enumerate_children_finish (plugin_dir_file, -+ result, &error); ++ switch (param_id) { ++ case PROP_FILENAME: ++ g_value_set_string (value, plugin->priv->filename); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); ++ break; ++ } ++} + -+ if (enumerator == NULL) { -+ char *plugin_dir; ++static void ++gdm_greeter_plugin_class_init (GdmGreeterPluginClass *class) ++{ ++ GObjectClass *gobject_class; + -+ plugin_dir = g_file_get_parse_name (plugin_dir_file); ++ gobject_class = G_OBJECT_CLASS (class); + -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { -+ g_debug ("GdmPluginManager: Cancelled opening plugin directory %s", -+ plugin_dir); -+ } else { -+ g_warning ("GdmPluginManager: Unable to open plugin directory %s: %s", -+ plugin_dir, error->message); -+ } -+ g_free (plugin_dir); -+ g_error_free (error); -+ return; -+ } ++ gobject_class->set_property = gdm_greeter_plugin_set_property; ++ gobject_class->get_property = gdm_greeter_plugin_get_property; ++ gobject_class->finalize = gdm_greeter_plugin_finalize; + -+ operation = start_operation (manager); ++ g_object_class_install_property (gobject_class, ++ PROP_FILENAME, ++ g_param_spec_string ("filename", ++ "Filename", ++ "The full path to the plugin.", ++ NULL, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + -+ g_file_enumerator_next_files_async (enumerator, G_MAXINT, -+ G_PRIORITY_DEFAULT, -+ operation->cancellable, -+ (GAsyncReadyCallback) -+ on_plugin_info_read, -+ operation); ++ signals [LOADED] = ++ g_signal_new ("loaded", ++ G_TYPE_FROM_CLASS (class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmGreeterPluginClass, loaded), ++ NULL, NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); ++ signals [LOAD_FAILED] = ++ g_signal_new ("load-failed", ++ G_TYPE_FROM_CLASS (class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmGreeterPluginClass, load_failed), ++ NULL, NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); ++ signals [UNLOADED] = ++ g_signal_new ("unloaded", ++ G_TYPE_FROM_CLASS (class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmGreeterPluginClass, unloaded), ++ NULL, NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); + -+ gdm_plugin_manager_track_operation (manager, operation); ++ g_type_class_add_private (class, sizeof (GdmGreeterPluginPrivate)); +} + -+static void -+load_plugins_in_dir (GdmPluginManager *manager, -+ const char *plugin_dir) ++GdmGreeterPlugin * ++gdm_greeter_plugin_new (const char *filename) +{ -+ GFile *plugin_dir_file; -+ GdmPluginManagerOperation *operation; ++ GObject *object; + -+ g_debug ("GdmPluginManager: loading plugins in dir '%s'", plugin_dir); ++ object = g_object_new (GDM_TYPE_GREETER_PLUGIN, ++ "filename", filename, NULL); + -+ operation = start_operation (manager); -+ plugin_dir_file = g_file_new_for_path (plugin_dir); -+ g_file_enumerate_children_async (plugin_dir_file, "standard::*", -+ G_FILE_QUERY_INFO_NONE, -+ G_PRIORITY_DEFAULT, -+ operation->cancellable, -+ (GAsyncReadyCallback) -+ on_plugin_dir_opened, -+ operation); -+ g_object_unref (plugin_dir_file); -+ gdm_plugin_manager_track_operation (manager, operation); ++ return GDM_GREETER_PLUGIN (object); +} + -+static void -+on_plugin_dir_changed (GFileMonitor *monitor, -+ GFile *file, -+ GFile *other_file, -+ GFileMonitorEvent event_type, -+ GdmPluginManagerOperation *operation) ++void ++gdm_greeter_plugin_load (GdmGreeterPlugin *plugin) +{ -+} ++ GModule *module; ++ GdmGreeterExtension *extension; ++ union { ++ gpointer symbol; ++ GdmGreeterPluginGetExtensionFunc invoke; ++ } get_extension; + -+static void -+watch_plugin_dir (GdmPluginManager *manager, -+ const char *plugin_dir) -+{ + -+ GdmPluginManagerOperation *operation; -+ GFile *file; -+ GError *error; ++ module = g_module_open (plugin->priv->filename, G_MODULE_BIND_LOCAL); + -+ operation = start_operation (manager); ++ if (module == NULL) { ++ g_warning ("plugin %s couldn't be opened: %s", ++ plugin->priv->filename, ++ g_module_error ()); ++ g_signal_emit (plugin, signals [LOAD_FAILED], 0); ++ return; ++ } + -+ file = g_file_new_for_path (plugin_dir); -+ manager->priv->plugin_dir_monitor = g_file_monitor_directory (file, -+ G_FILE_MONITOR_NONE, -+ operation->cancellable, -+ &error); -+ if (manager->priv->plugin_dir_monitor != NULL) { -+ g_signal_connect (manager->priv->plugin_dir_monitor, -+ "changed", -+ G_CALLBACK (on_plugin_dir_changed), -+ operation); -+ gdm_plugin_manager_track_operation (manager, operation); -+ } else { -+ g_warning ("Unable to monitor %s: %s", -+ plugin_dir, error->message); -+ g_error_free (error); -+ free_operation (operation); ++ if (!g_module_symbol (module, ++ "gdm_greeter_plugin_get_extension", ++ &get_extension.symbol) || ++ !get_extension.symbol) { ++ g_warning ("plugin %s lacks gdm_greeter_plugin_get_extension()", ++ plugin->priv->filename); ++ g_module_close (module); ++ g_signal_emit (plugin, signals [LOAD_FAILED], 0); ++ return; + } -+ g_object_unref (file); -+} + -+static void -+gdm_plugin_manager_init (GdmPluginManager *manager) -+{ -+ manager->priv = GDM_PLUGIN_MANAGER_GET_PRIVATE (manager); ++ extension = get_extension.invoke (); + -+ manager->priv->plugins = g_hash_table_new_full (g_str_hash, -+ g_str_equal, -+ g_free, -+ g_object_unref); -+ watch_plugin_dir (manager, GDM_SIMPLE_GREETER_PLUGINS_DIR); -+ load_plugins_in_dir (manager, GDM_SIMPLE_GREETER_PLUGINS_DIR); -+} ++ if (!extension) { ++ g_warning ("plugin %s didn't return extension when asked", ++ plugin->priv->filename); ++ g_module_close (module); ++ g_signal_emit (plugin, signals [LOAD_FAILED], 0); ++ } + -+static void -+gdm_plugin_manager_finalize (GObject *object) -+{ -+ GdmPluginManager *manager; ++ if (!GDM_IS_GREETER_EXTENSION (extension)) { ++ g_warning ("plugin %s returned bogus extension when asked", ++ plugin->priv->filename); ++ g_module_close (module); ++ g_signal_emit (plugin, signals [LOAD_FAILED], 0); ++ } + -+ manager = GDM_PLUGIN_MANAGER (object); ++ plugin->priv->module = module; ++ plugin->priv->extension = extension; + -+ g_hash_table_destroy (manager->priv->plugins); -+ g_file_monitor_cancel (manager->priv->plugin_dir_monitor); ++ g_signal_emit (plugin, signals [LOADED], 0); ++} + -+ gdm_plugin_manager_cancel_pending_operations (manager); ++void ++gdm_greeter_plugin_unload (GdmGreeterPlugin *plugin) ++{ ++ if (plugin->priv->extension != NULL) { ++ g_object_unref (plugin->priv->extension); ++ plugin->priv->extension = NULL; ++ } + -+ G_OBJECT_CLASS (gdm_plugin_manager_parent_class)->finalize (object); ++ if (plugin->priv->module != NULL) { ++ g_module_close (plugin->priv->module); ++ plugin->priv->module = NULL; ++ } +} + -+GdmPluginManager * -+gdm_plugin_manager_ref_default (void) ++const char * ++gdm_greeter_plugin_get_filename (GdmGreeterPlugin *plugin) +{ -+ if (plugin_manager_object != NULL) { -+ g_object_ref (plugin_manager_object); -+ } else { -+ plugin_manager_object = g_object_new (GDM_TYPE_PLUGIN_MANAGER, NULL); -+ g_object_add_weak_pointer (plugin_manager_object, -+ (gpointer *) &plugin_manager_object); -+ } ++ return plugin->priv->filename; ++} + -+ return GDM_PLUGIN_MANAGER (plugin_manager_object); ++GdmGreeterExtension * ++gdm_greeter_plugin_get_extension (GdmGreeterPlugin *plugin) ++{ ++ return g_object_ref (plugin->priv->extension); +} + -+GdmGreeterPlugin * -+gdm_plugin_manager_get_plugin (GdmPluginManager *manager, -+ const char *name) ++static void ++gdm_greeter_plugin_init (GdmGreeterPlugin *plugin) +{ -+ return g_hash_table_lookup (manager->priv->plugins, name); ++ plugin->priv = GDM_GREETER_PLUGIN_GET_PRIVATE (plugin); ++} ++ ++static void ++gdm_greeter_plugin_finalize (GObject *object) ++{ ++ GdmGreeterPlugin *plugin; ++ ++ plugin = GDM_GREETER_PLUGIN (object); ++ ++ gdm_greeter_plugin_unload (plugin); +} -diff --git a/gui/simple-greeter/gdm-plugin-manager.h b/gui/simple-greeter/gdm-plugin-manager.h -new file mode 100644 -index 0000000..f181140 ---- /dev/null -+++ b/gui/simple-greeter/gdm-plugin-manager.h -@@ -0,0 +1,66 @@ ++ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/gdm-greeter-plugin.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/gdm-greeter-plugin.h 2009-03-03 17:45:05.664034851 -0500 +@@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -10138,427 +7445,321 @@ index 0000000..f181140 + * + * 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. -+ * -+ * Written by: Ray Strode -+ * ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + -+#ifndef __GDM_PLUGIN_MANAGER_H -+#define __GDM_PLUGIN_MANAGER_H ++#ifndef __GDM_GREETER_PLUGIN ++#define __GDM_GREETER_PLUGIN + +#include ++#include + -+#include "gdm-greeter-plugin.h" ++#include "gdm-greeter-extension.h" + +G_BEGIN_DECLS + -+#define GDM_TYPE_PLUGIN_MANAGER (gdm_plugin_manager_get_type ()) -+#define GDM_PLUGIN_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_PLUGIN_MANAGER, GdmPluginManager)) -+#define GDM_PLUGIN_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_PLUGIN_MANAGER, GdmPluginManagerClass)) -+#define GDM_IS_PLUGIN_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_PLUGIN_MANAGER)) -+#define GDM_IS_PLUGIN_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_PLUGIN_MANAGER)) -+#define GDM_PLUGIN_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_PLUGIN_MANAGER, GdmPluginManagerClass)) ++#define GDM_TYPE_GREETER_PLUGIN (gdm_greeter_plugin_get_type ()) ++#define GDM_GREETER_PLUGIN(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDM_TYPE_GREETER_PLUGIN, GdmGreeterPlugin)) ++#define GDM_IS_GREETER_PLUGIN(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDM_TYPE_GREETER_PLUGIN)) + -+typedef struct GdmPluginManagerPrivate GdmPluginManagerPrivate; ++typedef struct _GdmGreeterPlugin GdmGreeterPlugin; ++typedef struct _GdmGreeterPluginPrivate GdmGreeterPluginPrivate; ++typedef struct _GdmGreeterPluginClass GdmGreeterPluginClass; + -+typedef struct ++struct _GdmGreeterPlugin +{ + GObject parent; -+ GdmPluginManagerPrivate *priv; -+} GdmPluginManager; ++ GdmGreeterPluginPrivate *priv; ++}; + -+typedef struct ++struct _GdmGreeterPluginClass +{ + GObjectClass parent_class; + -+ void (* plugins_loaded) (GdmPluginManager *plugin_manager); -+ void (* plugin_added) (GdmPluginManager *plugin_manager, -+ GdmGreeterPlugin *plugin); -+ void (* plugin_removed) (GdmPluginManager *plugin_manager, -+ GdmGreeterPlugin *plugin); -+} GdmPluginManagerClass; -+ -+GType gdm_plugin_manager_get_type (void); -+ -+GdmPluginManager *gdm_plugin_manager_ref_default (void); ++ void (* loaded) (GdmGreeterPlugin *plugin); ++ void (* load_failed) (GdmGreeterPlugin *plugin); ++ void (* unloaded) (GdmGreeterPlugin *plugin); ++}; + -+GdmGreeterPlugin *gdm_plugin_manager_get_plugin (GdmPluginManager *plugin, -+ const char *name); ++GType gdm_greeter_plugin_get_type (void) G_GNUC_CONST; ++GdmGreeterPlugin *gdm_greeter_plugin_new (const char *filename); ++void gdm_greeter_plugin_load (GdmGreeterPlugin *plugin); ++void gdm_greeter_plugin_unload (GdmGreeterPlugin *plugin); ++const char *gdm_greeter_plugin_get_filename (GdmGreeterPlugin *plugin); ++GdmGreeterExtension *gdm_greeter_plugin_get_extension (GdmGreeterPlugin *plugin); + +G_END_DECLS + -+#endif /* __GDM_PLUGIN_MANAGER_H */ -diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c -index e0fd3d4..71e103e 100644 ---- a/gui/simple-greeter/gdm-task-list.c -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -37,12 +37,6 @@ ++#endif +diff -up gdm-2.25.2/gui/simple-greeter/gdm-greeter-session.c.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-greeter-session.c +--- gdm-2.25.2/gui/simple-greeter/gdm-greeter-session.c.multistack-but-boring 2008-08-26 15:04:00.000000000 -0400 ++++ gdm-2.25.2/gui/simple-greeter/gdm-greeter-session.c 2009-03-03 17:45:05.714016287 -0500 +@@ -38,6 +38,8 @@ + #include "gdm-greeter-panel.h" + #include "gdm-greeter-login-window.h" - #define GDM_TASK_LIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_TASK_LIST, GdmTaskListPrivate)) ++#include "gdm-plugin-manager.h" ++ + #include "gdm-profile.h" --typedef struct --{ -- GtkWidget *radio_button; -- char *name; --} GdmTask; -- - struct GdmTaskListPrivate + #define GDM_GREETER_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_SESSION, GdmGreeterSessionPrivate)) +@@ -45,9 +47,11 @@ + struct GdmGreeterSessionPrivate { - GtkWidget *box; -@@ -59,54 +53,123 @@ static guint signals[NUMBER_OF_SIGNALS]; + GdmGreeterClient *client; ++ GdmPluginManager *plugin_manager; - static void gdm_task_list_class_init (GdmTaskListClass *klass); - static void gdm_task_list_init (GdmTaskList *task_list); --static void gdm_task_list_finalize (GObject *object); -+static void gdm_task_list_finalize (GObject *object); + GtkWidget *login_window; + GtkWidget *panel; ++ + }; - G_DEFINE_TYPE (GdmTaskList, gdm_task_list, GTK_TYPE_ALIGNMENT); + enum { +@@ -64,31 +68,46 @@ static gpointer session_object = NULL; static void - on_task_toggled (GdmTaskList *widget, -- GtkRadioButton *radio_button) -+ GtkRadioButton *button) + on_info (GdmGreeterClient *client, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) { - GdmTask *task; + g_debug ("GdmGreeterSession: Info: %s", text); -- task = g_object_get_data (G_OBJECT (radio_button), "gdm-task"); -+ task = g_object_get_data (G_OBJECT (button), "gdm-task"); +- gdm_greeter_login_window_info (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), text); ++ gdm_greeter_login_window_info (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name, text); + } -- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_button))) { -- g_signal_emit (widget, signals[ACTIVATED], 0, task->name); -+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { -+ g_signal_emit (widget, signals[ACTIVATED], 0, task); - } else { -- g_signal_emit (widget, signals[DEACTIVATED], 0, task->name); -+ g_signal_emit (widget, signals[DEACTIVATED], 0, task); -+ } -+} -+ -+GdmTask * -+gdm_task_list_foreach_task (GdmTaskList *task_list, -+ GdmTaskListForeachFunc search_func, -+ gpointer data) -+{ -+ GList *node; -+ -+ for (node = task_list->priv->tasks; node != NULL; node = node->next) { -+ GdmTask *task; -+ -+ task = node->data; -+ -+ if (search_func (task_list, task, data)) { -+ return g_object_ref (task); -+ } - } -+ -+ return NULL; -+} -+ -+static void -+on_task_enabled (GdmTaskList *task_list, -+ GdmTask *task) -+{ -+ GtkWidget *button; -+ -+ button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); -+ -+ gtk_widget_set_sensitive (button, TRUE); -+ + static void + on_problem (GdmGreeterClient *client, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) + { + g_debug ("GdmGreeterSession: Problem: %s", text); + +- gdm_greeter_login_window_problem (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), text); ++ gdm_greeter_login_window_problem (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name, text); + } + + static void + on_ready (GdmGreeterClient *client, ++ const char *service_name, + GdmGreeterSession *session) + { + g_debug ("GdmGreeterSession: Ready"); + +- gdm_greeter_login_window_ready (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window)); ++ gdm_greeter_login_window_ready (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), ++ service_name); +} + +static void -+on_task_disabled (GdmTaskList *task_list, -+ GdmTask *task) ++on_conversation_stopped (GdmGreeterClient *client, ++ const char *service_name, ++ GdmGreeterSession *session) +{ -+ GtkWidget *button; -+ -+ button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); ++ g_debug ("GdmGreeterSession: Conversation '%s' stopped", service_name); + -+ gtk_widget_set_sensitive (button, FALSE); ++ gdm_greeter_login_window_conversation_stopped (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), ++ service_name); } - void - gdm_task_list_add_task (GdmTaskList *task_list, -- const char *name, -- const char *icon_name) -+ GdmTask *task) + static void +@@ -151,33 +170,44 @@ on_timed_login_requested (GdmGreeterClie + + static void + on_user_authorized (GdmGreeterClient *client, ++ const char *service_name, + GdmGreeterSession *session) { -- GdmTask *task; - GtkWidget *image; -+ GtkWidget *button; -+ GIcon *icon; -+ char *description; + g_debug ("GdmGreeterSession: user authorized"); +- gdm_greeter_login_window_user_authorized (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window)); ++ gdm_greeter_login_window_user_authorized (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name); + } -- task = g_new0 (GdmTask, 1); -- -- task->name = g_strdup (name); - if (task_list->priv->tasks == NULL) { -- task->radio_button = gtk_radio_button_new (NULL); -+ button = gtk_radio_button_new (NULL); - } else { -- task->radio_button = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (((GdmTask *) task_list->priv->tasks->data)->radio_button)); -+ GdmTask *previous_task; -+ GtkRadioButton *previous_button; -+ -+ previous_task = GDM_TASK (task_list->priv->tasks->data); -+ previous_button = GTK_RADIO_BUTTON (g_object_get_data (G_OBJECT (previous_task), "gdm-task-list-button")); -+ button = gtk_radio_button_new_from_widget (previous_button); - } -+ g_object_set_data (G_OBJECT (task), "gdm-task-list-button", button); -+ -+ g_object_set (G_OBJECT (button), "draw-indicator", FALSE, NULL); -+ g_object_set_data (G_OBJECT (button), "gdm-task", task); -+ g_signal_connect_swapped (button, "toggled", -+ G_CALLBACK (on_task_toggled), -+ task_list); -+ -+ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); -+ gtk_widget_set_sensitive (button, gdm_task_is_enabled (task)); -+ -+ g_signal_connect_swapped (G_OBJECT (task), "enabled", -+ G_CALLBACK (on_task_enabled), -+ task_list); -+ -+ g_signal_connect_swapped (G_OBJECT (task), "disabled", -+ G_CALLBACK (on_task_disabled), -+ task_list); -+ -+ icon = gdm_task_get_icon (task); -+ image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_SMALL_TOOLBAR); -+ g_object_unref (icon); + static void + on_info_query (GdmGreeterClient *client, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) + { + g_debug ("GdmGreeterSession: Info query: %s", text); -- g_object_set (task->radio_button, "draw-indicator", FALSE, NULL); -- g_object_set_data (G_OBJECT (task->radio_button), "gdm-task", task); -- g_signal_connect_swapped (task->radio_button, -- "toggled", G_CALLBACK (on_task_toggled), task_list); -- image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_DND); - gtk_widget_show (image); -- gtk_container_add (GTK_CONTAINER (task->radio_button), image); -- gtk_widget_show (task->radio_button); -- gtk_container_add (GTK_CONTAINER (task->radio_button), task_list->priv->box); -+ gtk_container_add (GTK_CONTAINER (button), image); -+ description = gdm_task_get_description (task); -+ gtk_widget_set_tooltip_text (button, description); -+ g_free (description); -+ gtk_widget_show (button); +- gdm_greeter_login_window_info_query (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), text); ++ gdm_greeter_login_window_info_query (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name, text); + } -- gtk_container_add (GTK_CONTAINER (task_list->priv->box), task->radio_button); -+ gtk_container_add (GTK_CONTAINER (task_list->priv->box), button); - task_list->priv->tasks = g_list_append (task_list->priv->tasks, task); -+ -+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { -+ g_signal_emit (task_list, signals[ACTIVATED], 0, task); -+ } + static void + on_secret_info_query (GdmGreeterClient *client, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) + { + g_debug ("GdmGreeterSession: Secret info query: %s", text); + +- gdm_greeter_login_window_secret_info_query (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), text); ++ gdm_greeter_login_window_secret_info_query (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name, text); } static void -@@ -122,9 +185,9 @@ gdm_task_list_class_init (GdmTaskListClass *klass) - G_STRUCT_OFFSET (GdmTaskListClass, activated), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, -- 1, G_TYPE_STRING); -+ 1, G_TYPE_OBJECT); - - signals [DEACTIVATED] = g_signal_new ("deactivated", - G_TYPE_FROM_CLASS (object_class), -@@ -132,22 +195,19 @@ gdm_task_list_class_init (GdmTaskListClass *klass) - G_STRUCT_OFFSET (GdmTaskListClass, deactivated), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -+ g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, -- 1, G_TYPE_STRING); -+ 1, G_TYPE_OBJECT); - - g_type_class_add_private (klass, sizeof (GdmTaskListPrivate)); --} -- --static void --gdm_task_list_init (GdmTaskList *widget) -+} static void gdm_task_list_init (GdmTaskList *widget) ++on_start_conversation (GdmGreeterLoginWindow *login_window, ++ const char *service_name, ++ GdmGreeterSession *session) ++{ ++ gdm_greeter_client_call_start_conversation (session->priv->client, ++ service_name); ++} ++static void + on_begin_auto_login (GdmGreeterLoginWindow *login_window, + const char *username, + GdmGreeterSession *session) +@@ -188,26 +218,32 @@ on_begin_auto_login (GdmGreeterLoginWind + + static void + on_begin_verification (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + GdmGreeterSession *session) { - widget->priv = GDM_TASK_LIST_GET_PRIVATE (widget); - - gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 0, 0); - gtk_alignment_set (GTK_ALIGNMENT (widget), 0.0, 0.0, 0, 0); +- gdm_greeter_client_call_begin_verification (session->priv->client); ++ gdm_greeter_client_call_begin_verification (session->priv->client, ++ service_name); + } -- widget->priv->box = gtk_hbox_new (FALSE, 2); -+ widget->priv->box = gtk_hbox_new (TRUE, 2); - gtk_widget_show (widget->priv->box); - gtk_container_add (GTK_CONTAINER (widget), - widget->priv->box); -@@ -179,20 +239,28 @@ gdm_task_list_new (void) - return GTK_WIDGET (object); + static void + on_begin_verification_for_user (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *username, + GdmGreeterSession *session) + { + gdm_greeter_client_call_begin_verification_for_user (session->priv->client, ++ service_name, + username); } --const char * --gdm_task_list_get_active_task (GdmTaskList *widget) -+gboolean -+gdm_task_list_task_is_active (GdmTaskList *task_list, -+ GdmTask *task) + static void + on_query_answer (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) { -- GList *node; -+ GtkWidget *button; + gdm_greeter_client_call_answer_query (session->priv->client, ++ service_name, + text); + } -- for (node = widget->priv->tasks; node != NULL; node = node->next) { -- GdmTask *task; -+ button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); +@@ -262,9 +298,10 @@ on_disconnected (GdmGreeterLoginWindow * -- task = node->data; -+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); -+} + static void + on_start_session (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + GdmGreeterSession *session) + { +- gdm_greeter_client_call_start_session_when_ready (session->priv->client, TRUE); ++ gdm_greeter_client_call_start_session_when_ready (session->priv->client, service_name, TRUE); + } -- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (task->radio_button)) ) { -- return task->name; -- } -- } -+GdmTask * -+gdm_task_list_get_active_task (GdmTaskList *widget) + static void +@@ -321,7 +358,10 @@ toggle_login_window (GdmGreeterSession * + is_local = gdm_greeter_client_get_display_is_local (session->priv->client); + g_debug ("GdmGreeterSession: Starting a login window local:%d", is_local); + session->priv->login_window = gdm_greeter_login_window_new (is_local); +- ++ g_signal_connect (session->priv->login_window, ++ "start-conversation", ++ G_CALLBACK (on_start_conversation), ++ session); + g_signal_connect (session->priv->login_window, + "begin-auto-login", + G_CALLBACK (on_begin_auto_login), +@@ -486,6 +526,64 @@ gdm_greeter_session_event_handler (GdkEv + } + + static void ++on_plugins_loaded (GdmGreeterSession *session) +{ -+ return gdm_task_list_foreach_task (widget, -+ (GdmTaskListForeachFunc) -+ gdm_task_list_task_is_active, -+ NULL); ++ g_debug ("GdmGreeterSession: done loading plugins"); +} - -- return NULL; -+int -+gdm_task_list_get_number_of_tasks (GdmTaskList *widget) ++ ++static void ++on_plugin_removed (GdmGreeterSession *session, ++ GdmGreeterPlugin *plugin) +{ -+ return g_list_length (widget->priv->tasks); - } -diff --git a/gui/simple-greeter/gdm-task-list.h b/gui/simple-greeter/gdm-task-list.h -index ade21b6..e8cc2f4 100644 ---- a/gui/simple-greeter/gdm-task-list.h -+++ b/gui/simple-greeter/gdm-task-list.h -@@ -22,8 +22,11 @@ - #define __GDM_TASK_LIST_H - - #include -+#include - #include - -+#include "gdm-task.h" ++ GdmGreeterExtension *extension; + - G_BEGIN_DECLS - - #define GDM_TYPE_TASK_LIST (gdm_task_list_get_type ()) -@@ -34,31 +37,42 @@ G_BEGIN_DECLS - #define GDM_TASK_LIST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_TASK_LIST, GdmTaskListClass)) - - typedef struct GdmTaskListPrivate GdmTaskListPrivate; -+typedef struct _GdmTaskList GdmTaskList; - --typedef struct -+typedef gboolean (* GdmTaskListForeachFunc) (GdmTaskList *task_list, -+ GdmTask *task, -+ gpointer data); ++ extension = gdm_greeter_plugin_get_extension (plugin); + -+struct _GdmTaskList - { - GtkAlignment parent; - GdmTaskListPrivate *priv; --} GdmTaskList; -+}; - - typedef struct - { - GtkAlignmentClass parent_class; - - void (* deactivated) (GdmTaskList *widget, -- const char *name); -+ GdmTask *task); - void (* activated) (GdmTaskList *widget, -- const char *name); -+ GdmTask *task); - } GdmTaskListClass; - -+GType gdm_task_list_get_type (void); -+GtkWidget * gdm_task_list_new (void); ++ if (GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION (extension)) { ++ gdm_greeter_login_window_remove_extension (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), extension); ++ } ++ g_object_unref (extension); ++} + - --GType gdm_task_list_get_type (void); --GtkWidget * gdm_task_list_new (void); -+gboolean gdm_task_list_task_is_active (GdmTaskList *task_list, -+ GdmTask *task); -+GdmTask * gdm_task_list_get_active_task (GdmTaskList *widget); -+GdmTask * gdm_task_list_foreach_task (GdmTaskList *widget, -+ GdmTaskListForeachFunc foreach_func, -+ gpointer data); -+void gdm_task_list_add_task (GdmTaskList *widget, -+ GdmTask *task); - --const char * gdm_task_list_get_active_task (GdmTaskList *widget); --void gdm_task_list_add_task (GdmTaskList *widget, -- const char *name, -- const char *icon_name); -+int gdm_task_list_get_number_of_tasks (GdmTaskList *widget); - G_END_DECLS - - #endif /* __GDM_TASK_LIST_H */ -diff --git a/gui/simple-greeter/libgdmsimplegreeter/Makefile.am b/gui/simple-greeter/libgdmsimplegreeter/Makefile.am -new file mode 100644 -index 0000000..1ef5725 ---- /dev/null -+++ b/gui/simple-greeter/libgdmsimplegreeter/Makefile.am -@@ -0,0 +1,46 @@ -+NULL = ++static void ++on_plugin_added (GdmGreeterSession *session, ++ GdmGreeterPlugin *plugin) ++{ ++ GdmGreeterExtension *extension; + -+AM_CPPFLAGS = \ -+ -I. \ -+ -I.. \ -+ -DBINDIR=\"$(bindir)\" \ -+ -DDATADIR=\"$(datadir)\" \ -+ -DLIBDIR=\"$(libdir)\" \ -+ -DLIBEXECDIR=\"$(libexecdir)\" \ -+ -DLOGDIR=\"$(logdir)\" \ -+ -DPIXMAPDIR=\"$(pixmapdir)\" \ -+ -DSBINDIR=\"$(sbindir)\" \ -+ $(GTK_CFLAGS) \ -+ $(NULL) ++ extension = gdm_greeter_plugin_get_extension (plugin); + -+lib_LTLIBRARIES = \ -+ libgdmsimplegreeter.la \ -+ $(NULL) ++ if (GDM_IS_GREETER_LOGIN_WINDOW_EXTENSION (extension)) { ++ gdm_greeter_login_window_add_extension (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), extension); ++ } ++ g_object_unref (extension); ++} + -+libgdmsimplegreeter_la_SOURCES = \ -+ gdm-task.h \ -+ gdm-task.c \ -+ gdm-conversation.h \ -+ gdm-conversation.c \ -+ gdm-greeter-extension.h \ -+ gdm-greeter-extension.c \ -+ $(NULL) ++static void ++load_plugins (GdmGreeterSession *session) ++{ ++ g_debug ("GdmGreeterSession: loading plugins"); + -+libgdmsimplegreeter_la_LIBADD = \ -+ $(GTK_LIBS) \ -+ $(NULL) ++ session->priv->plugin_manager = gdm_plugin_manager_ref_default (); + -+libgdmsimplegreeter_la_LDFLAGS = \ -+ -export-symbols-regex '^[^_].*' \ -+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -+ -no-undefined \ -+ $(NULL) ++ g_signal_connect_swapped (session->priv->plugin_manager, ++ "plugins-loaded", ++ G_CALLBACK (on_plugins_loaded), ++ session); + -+headersdir = $(includedir)/gdm/simple-greeter -+headers_HEADERS = gdm-greeter-extension.h ++ g_signal_connect_swapped (session->priv->plugin_manager, ++ "plugin-added", ++ G_CALLBACK (on_plugin_added), ++ session); + -+pkgconfigdir = $(libdir)/pkgconfig -+pkgconfig_DATA = gdmsimplegreeter.pc ++ g_signal_connect_swapped (session->priv->plugin_manager, ++ "plugin-removed", ++ G_CALLBACK (on_plugin_removed), ++ session); + -+EXTRA_DIST = gdmsimplegreeter.pc -+MAINTAINERCLEANFILES = Makefile.in -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c -new file mode 100644 -index 0000000..e21c56b ---- /dev/null -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c -@@ -0,0 +1,147 @@ ++} ++ ++static void + gdm_greeter_session_init (GdmGreeterSession *session) + { + gdm_profile_start (NULL); +@@ -514,6 +612,10 @@ gdm_greeter_session_init (GdmGreeterSess + G_CALLBACK (on_ready), + session); + g_signal_connect (session->priv->client, ++ "conversation-stopped", ++ G_CALLBACK (on_conversation_stopped), ++ session); ++ g_signal_connect (session->priv->client, + "reset", + G_CALLBACK (on_reset), + session); +@@ -548,6 +650,8 @@ gdm_greeter_session_init (GdmGreeterSess + gdk_event_handler_set ((GdkEventFunc) gdm_greeter_session_event_handler, + session, NULL); + ++ ++ load_plugins (session); + gdm_profile_end (NULL); + } + +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/gdm-plugin-manager.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/gdm-plugin-manager.c 2009-03-03 17:45:05.667016434 -0500 +@@ -0,0 +1,478 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -10577,335 +7778,472 @@ index 0000000..e21c56b + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Written By: Ray Strode -+ * + */ + ++#include "config.h" ++ +#include ++#include ++#include +#include ++#include + -+#include ++#include "gdm-plugin-manager.h" ++#include "gdm-greeter-extension.h" + -+#include "gdm-conversation.h" -+#include "gdm-task.h" ++#define GDM_PLUGIN_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_PLUGIN_MANAGER, GdmPluginManagerPrivate)) ++ ++typedef struct ++{ ++ GModule *module; ++ char *filename; ++ GdmGreeterExtension *extension; ++} GdmPluginManagerPlugin; ++ ++typedef struct ++{ ++ GdmPluginManager *manager; ++ GCancellable *cancellable; ++} GdmPluginManagerOperation; ++ ++struct GdmPluginManagerPrivate ++{ ++ GHashTable *plugins; + ++ GFileMonitor *plugin_dir_monitor; ++ GList *pending_operations; ++}; + +enum { -+ ANSWER, ++ PLUGINS_LOADED, ++ PLUGIN_ADDED, ++ PLUGIN_REMOVED, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0, }; + -+static void gdm_conversation_class_init (gpointer g_iface); ++static void gdm_plugin_manager_class_init (GdmPluginManagerClass *klass); ++static void gdm_plugin_manager_init (GdmPluginManager *plugin_manager); ++static void gdm_plugin_manager_finalize (GObject *object); + -+GType -+gdm_conversation_get_type (void) -+{ -+ static GType type = 0; ++static GObject *plugin_manager_object = NULL; + -+ if (!type) { -+ type = g_type_register_static_simple (G_TYPE_INTERFACE, -+ "GdmConversation", -+ sizeof (GdmConversationIface), -+ (GClassInitFunc) gdm_conversation_class_init, -+ 0, NULL, 0); ++G_DEFINE_TYPE (GdmPluginManager, gdm_plugin_manager, G_TYPE_OBJECT) + -+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); -+ g_type_interface_add_prerequisite (type, GDM_TYPE_TASK); -+ } ++static GdmPluginManagerOperation * ++start_operation (GdmPluginManager *manager) ++{ ++ GdmPluginManagerOperation *operation; + -+ return type; ++ operation = g_new0 (GdmPluginManagerOperation, 1); ++ operation->cancellable = g_cancellable_new (); ++ operation->manager = manager; ++ ++ return operation; +} + +static void -+gdm_conversation_class_init (gpointer g_iface) ++free_operation (GdmPluginManagerOperation *operation) +{ -+ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); -+ -+ signals [ANSWER] = -+ g_signal_new ("answer", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmConversationIface, answer), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); ++ if (operation->cancellable != NULL) { ++ g_object_unref (operation->cancellable); ++ operation->cancellable = NULL; ++ } ++ g_free (operation); +} + -+void -+gdm_conversation_set_message (GdmConversation *conversation, -+ const char *message) ++static void ++cancel_operation (GdmPluginManagerOperation *operation) +{ -+ GDM_CONVERSATION_GET_IFACE (conversation)->set_message (conversation, message); -+} ++ if (operation->cancellable != NULL && ++ !g_cancellable_is_cancelled (operation->cancellable)) { ++ g_cancellable_cancel (operation->cancellable); ++ } + -+void -+gdm_conversation_ask_question (GdmConversation *conversation, -+ const char *message) -+{ -+ GDM_CONVERSATION_GET_IFACE (conversation)->ask_question (conversation, message); ++ free_operation (operation); +} + -+void -+gdm_conversation_ask_secret (GdmConversation *conversation, -+ const char *message) ++static void ++gdm_plugin_manager_track_operation (GdmPluginManager *manager, ++ GdmPluginManagerOperation *operation) +{ -+ GDM_CONVERSATION_GET_IFACE (conversation)->ask_secret (conversation, message); ++ manager->priv->pending_operations = ++ g_list_prepend (manager->priv->pending_operations, operation); +} + -+void -+gdm_conversation_reset (GdmConversation *conversation) ++static void ++gdm_plugin_manager_untrack_operation (GdmPluginManager *manager, ++ GdmPluginManagerOperation *operation) +{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->reset (conversation); ++ manager->priv->pending_operations = ++ g_list_remove (manager->priv->pending_operations, operation); +} + -+void -+gdm_conversation_set_ready (GdmConversation *conversation) ++static void ++gdm_plugin_manager_cancel_pending_operations (GdmPluginManager *manager) +{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->set_ready (conversation); ++ GList *node; ++ ++ node = manager->priv->pending_operations; ++ while (node != NULL) { ++ GList *next_node; ++ GdmPluginManagerOperation *operation; ++ ++ operation = node->data; ++ next_node = node->next; ++ ++ cancel_operation (operation); ++ manager->priv->pending_operations = ++ g_list_delete_link (manager->priv->pending_operations, ++ node); ++ ++ node = next_node; ++ } +} + -+char * -+gdm_conversation_get_service_name (GdmConversation *conversation) ++static void ++gdm_plugin_manager_class_init (GdmPluginManagerClass *klass) +{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->get_service_name (conversation); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = gdm_plugin_manager_finalize; ++ ++ signals [PLUGINS_LOADED] = ++ g_signal_new ("plugins-loaded", ++ G_TYPE_FROM_CLASS (klass), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmPluginManagerClass, plugins_loaded), ++ NULL, NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); ++ signals [PLUGIN_ADDED] = ++ g_signal_new ("plugin-added", ++ G_TYPE_FROM_CLASS (klass), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmPluginManagerClass, plugin_added), ++ NULL, NULL, ++ g_cclosure_marshal_VOID__OBJECT, ++ G_TYPE_NONE, 1, GDM_TYPE_GREETER_PLUGIN); ++ signals [PLUGIN_REMOVED] = ++ g_signal_new ("plugin-removed", ++ G_TYPE_FROM_CLASS (klass), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmPluginManagerClass, plugin_removed), ++ NULL, NULL, ++ g_cclosure_marshal_VOID__OBJECT, ++ G_TYPE_NONE, 1, GDM_TYPE_GREETER_PLUGIN); ++ ++ g_type_class_add_private (klass, sizeof (GdmPluginManagerPrivate)); +} + -+GtkWidget * -+gdm_conversation_get_page (GdmConversation *conversation) ++static void ++on_plugin_loaded (GdmPluginManager *manager, ++ GdmGreeterPlugin *plugin) +{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->get_page (conversation); ++ g_debug ("GdmPluginManager: plugin '%s' loaded.", ++ gdm_greeter_plugin_get_filename (plugin)); ++ g_signal_emit (manager, signals [PLUGIN_ADDED], 0, plugin); +} + -+GtkActionGroup * -+gdm_conversation_get_actions (GdmConversation *conversation) ++static void ++on_plugin_load_failed (GdmPluginManager *manager, ++ GdmGreeterPlugin *plugin) +{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->get_actions (conversation); ++ const char *filename; ++ ++ g_debug ("GdmPluginManager: plugin '%s' could not be loaded.", ++ gdm_greeter_plugin_get_filename (plugin)); ++ filename = gdm_greeter_plugin_get_filename (plugin); ++ g_hash_table_remove (manager->priv->plugins, filename); +} + -+gboolean -+gdm_conversation_focus (GdmConversation *conversation) ++static void ++on_plugin_unloaded (GdmPluginManager *manager, ++ GdmGreeterPlugin *plugin) +{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->focus (conversation); ++ const char *filename; ++ ++ filename = gdm_greeter_plugin_get_filename (plugin); ++ g_hash_table_remove (manager->priv->plugins, filename); +} + -+void -+gdm_conversation_request_answer (GdmConversation *conversation) ++static void ++load_plugin (GdmPluginManager *manager, ++ const char *filename) +{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->request_answer (conversation); ++ GdmGreeterPlugin *plugin; ++ ++ g_debug ("GdmPluginManager: loading plugin '%s'", filename); ++ ++ plugin = gdm_greeter_plugin_new (filename); ++ ++ g_signal_connect_swapped (plugin, "loaded", ++ G_CALLBACK (on_plugin_loaded), ++ manager); ++ g_signal_connect_swapped (plugin, "load-failed", ++ G_CALLBACK (on_plugin_load_failed), ++ manager); ++ g_signal_connect_swapped (plugin, "unloaded", ++ G_CALLBACK (on_plugin_unloaded), ++ manager); ++ g_hash_table_insert (manager->priv->plugins, ++ g_strdup (filename), plugin); ++ ++ gdm_greeter_plugin_load (plugin); +} + -+/* protected -+ */ -+void -+gdm_conversation_answer (GdmConversation *conversation, -+ const char *answer) ++static void ++on_plugin_info_read (GFileEnumerator *enumerator, ++ GAsyncResult *result, ++ GdmPluginManagerOperation *operation) +{ -+ g_signal_emit (conversation, signals [ANSWER], 0, answer); -+} ++ GdmPluginManager *manager; ++ GFile *plugin_dir_file; ++ GList *file_list, *node; ++ GError *error; ++ ++ manager = operation->manager; ++ error = NULL; ++ file_list = g_file_enumerator_next_files_finish (enumerator, ++ result, &error); ++ plugin_dir_file = g_file_enumerator_get_container (enumerator); ++ if (error != NULL) { ++ char *plugin_dir; ++ ++ plugin_dir = g_file_get_parse_name (plugin_dir_file); ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { ++ g_debug ("GdmPluginManager: Cancelled reading plugin directory %s", ++ plugin_dir); ++ } else { ++ g_warning ("GdmPluginManager: Unable to read plugin directory %s: %s", ++ plugin_dir, error->message); ++ } ++ g_free (plugin_dir); ++ g_error_free (error); ++ g_object_unref (plugin_dir_file); ++ gdm_plugin_manager_untrack_operation (manager, operation); ++ return; ++ } ++ ++#ifndef PLUGIN_ORDERING_FIGURED_OUT ++ node = file_list; ++ while (node != NULL) { ++ GFileInfo *info; ++ GFile *file; ++ char *path; ++ GList *next_node; ++ ++ next_node = node->next; ++ ++ info = (GFileInfo *) node->data; ++ ++ file = g_file_get_child (plugin_dir_file, ++ g_file_info_get_name (info)); ++ path = g_file_get_path (file); ++ ++ if (g_str_has_suffix (path, "password.so")) { ++ file_list = g_list_delete_link (file_list, node); ++ file_list = g_list_prepend (file_list, info); ++ next_node = NULL; ++ } ++ g_free (path); ++ g_object_unref (file); + -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h -new file mode 100644 -index 0000000..f1910cf ---- /dev/null -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (C) Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written by: Ray Strode -+ */ ++ node = next_node; ++ } ++#endif + ++ node = file_list; ++ while (node != NULL) { ++ GFileInfo *info; ++ GFile *file; ++ char *path; + -+#ifndef __GDM_CONVERSATION_H -+#define __GDM_CONVERSATION_H ++ info = (GFileInfo *) node->data; + -+#include -+#include ++ file = g_file_get_child (plugin_dir_file, ++ g_file_info_get_name (info)); ++ path = g_file_get_path (file); + -+G_BEGIN_DECLS ++ if (g_str_has_suffix (path, G_MODULE_SUFFIX)) { ++ load_plugin (manager, path); ++ } ++ g_free (path); ++ g_object_unref (file); + -+#define GDM_TYPE_CONVERSATION (gdm_conversation_get_type ()) -+#define GDM_CONVERSATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_CONVERSATION, GdmConversation)) -+#define GDM_CONVERSATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_CONVERSATION, GdmConversationIface)) -+#define GDM_IS_CONVERSATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_CONVERSATION)) -+#define GDM_CONVERSATION_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDM_TYPE_CONVERSATION, GdmConversationIface)) ++ node = node->next; ++ } ++ g_object_unref (plugin_dir_file); + -+#define GDM_CONVERSATION_DEFAULT_ACTION "default-action" ++ gdm_plugin_manager_untrack_operation (manager, operation); ++ g_signal_emit (manager, signals [PLUGINS_LOADED], 0); + -+typedef struct _GdmConversation GdmConversation; -+typedef struct _GdmConversationIface GdmConversationIface; ++ g_list_free (file_list); ++} + -+struct _GdmConversationIface ++static void ++on_plugin_dir_opened (GFile *plugin_dir_file, ++ GAsyncResult *result, ++ GdmPluginManagerOperation *open_operation) +{ -+ GTypeInterface base_iface; ++ GdmPluginManager *manager; ++ GFileEnumerator *enumerator; ++ GError *error; ++ GdmPluginManagerOperation *operation; + -+ /* methods */ -+ void (* set_message) (GdmConversation *conversation, -+ const char *message); -+ void (* ask_question) (GdmConversation *conversation, -+ const char *message); -+ void (* ask_secret) (GdmConversation *conversation, -+ const char *message); -+ void (* reset) (GdmConversation *conversation); -+ void (* set_ready) (GdmConversation *conversation); -+ char * (* get_service_name) (GdmConversation *conversation); -+ GtkWidget * (* get_page) (GdmConversation *conversation); -+ GtkActionGroup * (* get_actions) (GdmConversation *conversation); -+ void (* request_answer) (GdmConversation *conversation); -+ gboolean (* focus) (GdmConversation *conversation); ++ manager = open_operation->manager; ++ gdm_plugin_manager_untrack_operation (manager, open_operation); + -+ /* signals */ -+ char * (* answer) (GdmConversation *conversation); -+}; ++ error = NULL; ++ enumerator = g_file_enumerate_children_finish (plugin_dir_file, ++ result, &error); + -+GType gdm_conversation_get_type (void) G_GNUC_CONST; ++ if (enumerator == NULL) { ++ char *plugin_dir; + -+void gdm_conversation_set_message (GdmConversation *conversation, -+ const char *message); -+void gdm_conversation_ask_question (GdmConversation *conversation, -+ const char *message); -+void gdm_conversation_ask_secret (GdmConversation *conversation, -+ const char *message); -+void gdm_conversation_reset (GdmConversation *converastion); -+void gdm_conversation_set_ready (GdmConversation *converastion); -+char *gdm_conversation_get_service_name (GdmConversation *conversation); -+GtkWidget *gdm_conversation_get_page (GdmConversation *conversation); -+GtkActionGroup *gdm_conversation_get_actions (GdmConversation *conversation); -+void gdm_conversation_request_answer (GdmConversation *conversation); -+gboolean gdm_conversation_focus (GdmConversation *conversation); ++ plugin_dir = g_file_get_parse_name (plugin_dir_file); + -+/* protected -+ */ -+void gdm_conversation_answer (GdmConversation *conversation, -+ const char *answer); ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { ++ g_debug ("GdmPluginManager: Cancelled opening plugin directory %s", ++ plugin_dir); ++ } else { ++ g_warning ("GdmPluginManager: Unable to open plugin directory %s: %s", ++ plugin_dir, error->message); ++ } ++ g_free (plugin_dir); ++ g_error_free (error); ++ return; ++ } + -+G_END_DECLS ++ operation = start_operation (manager); + -+#endif /* __GDM_CONVERSATION_H */ -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.c b/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.c -new file mode 100644 -index 0000000..a71d3f7 ---- /dev/null -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.c -@@ -0,0 +1,93 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written By: Ray Strode -+ * -+ */ ++ g_file_enumerator_next_files_async (enumerator, G_MAXINT, ++ G_PRIORITY_DEFAULT, ++ operation->cancellable, ++ (GAsyncReadyCallback) ++ on_plugin_info_read, ++ operation); + -+#include -+#include ++ gdm_plugin_manager_track_operation (manager, operation); ++} + -+#include "gdm-greeter-extension.h" ++static void ++load_plugins_in_dir (GdmPluginManager *manager, ++ const char *plugin_dir) ++{ ++ GFile *plugin_dir_file; ++ GdmPluginManagerOperation *operation; + -+enum { -+ LOADED, -+ LOAD_FAILED, -+ LAST_SIGNAL -+}; ++ g_debug ("GdmPluginManager: loading plugins in dir '%s'", plugin_dir); + -+static guint signals [LAST_SIGNAL] = { 0, }; ++ operation = start_operation (manager); ++ plugin_dir_file = g_file_new_for_path (plugin_dir); ++ g_file_enumerate_children_async (plugin_dir_file, "standard::*", ++ G_FILE_QUERY_INFO_NONE, ++ G_PRIORITY_DEFAULT, ++ operation->cancellable, ++ (GAsyncReadyCallback) ++ on_plugin_dir_opened, ++ operation); ++ g_object_unref (plugin_dir_file); ++ gdm_plugin_manager_track_operation (manager, operation); ++} + -+static void gdm_greeter_extension_class_init (gpointer g_iface); ++static void ++on_plugin_dir_changed (GFileMonitor *monitor, ++ GFile *file, ++ GFile *other_file, ++ GFileMonitorEvent event_type, ++ GdmPluginManagerOperation *operation) ++{ ++} + -+GType -+gdm_greeter_extension_get_type (void) ++static void ++watch_plugin_dir (GdmPluginManager *manager, ++ const char *plugin_dir) +{ -+ static GType greeter_extension_type = 0; + -+ if (!greeter_extension_type) { -+ greeter_extension_type = g_type_register_static_simple (G_TYPE_INTERFACE, -+ "GdmGreeterExtension", -+ sizeof (GdmGreeterExtensionIface), -+ (GClassInitFunc) gdm_greeter_extension_class_init, -+ 0, NULL, 0); ++ GdmPluginManagerOperation *operation; ++ GFile *file; ++ GError *error; + -+ g_type_interface_add_prerequisite (greeter_extension_type, G_TYPE_OBJECT); ++ operation = start_operation (manager); ++ ++ file = g_file_new_for_path (plugin_dir); ++ manager->priv->plugin_dir_monitor = g_file_monitor_directory (file, ++ G_FILE_MONITOR_NONE, ++ operation->cancellable, ++ &error); ++ if (manager->priv->plugin_dir_monitor != NULL) { ++ g_signal_connect (manager->priv->plugin_dir_monitor, ++ "changed", ++ G_CALLBACK (on_plugin_dir_changed), ++ operation); ++ gdm_plugin_manager_track_operation (manager, operation); ++ } else { ++ g_warning ("Unable to monitor %s: %s", ++ plugin_dir, error->message); ++ g_error_free (error); ++ free_operation (operation); + } ++ g_object_unref (file); ++} + -+ return greeter_extension_type; ++static void ++gdm_plugin_manager_init (GdmPluginManager *manager) ++{ ++ manager->priv = GDM_PLUGIN_MANAGER_GET_PRIVATE (manager); ++ ++ manager->priv->plugins = g_hash_table_new_full (g_str_hash, ++ g_str_equal, ++ g_free, ++ g_object_unref); ++ watch_plugin_dir (manager, GDM_SIMPLE_GREETER_PLUGINS_DIR); ++ load_plugins_in_dir (manager, GDM_SIMPLE_GREETER_PLUGINS_DIR); +} + +static void -+gdm_greeter_extension_class_init (gpointer g_iface) ++gdm_plugin_manager_finalize (GObject *object) +{ -+ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); ++ GdmPluginManager *manager; + -+ signals [LOADED] = -+ g_signal_new ("loaded", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmGreeterExtensionIface, loaded), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); ++ manager = GDM_PLUGIN_MANAGER (object); ++ ++ g_hash_table_destroy (manager->priv->plugins); ++ g_file_monitor_cancel (manager->priv->plugin_dir_monitor); + -+ signals [LOADED] = -+ g_signal_new ("load_failed", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmGreeterExtensionIface, load_failed), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__POINTER, -+ G_TYPE_NONE, -+ 1, G_TYPE_POINTER); ++ gdm_plugin_manager_cancel_pending_operations (manager); ++ ++ G_OBJECT_CLASS (gdm_plugin_manager_parent_class)->finalize (object); +} + -+void -+gdm_greeter_extension_loaded (GdmGreeterExtension *extension) ++GdmPluginManager * ++gdm_plugin_manager_ref_default (void) +{ -+ g_signal_emit (extension, signals [LOADED], 0); ++ if (plugin_manager_object != NULL) { ++ g_object_ref (plugin_manager_object); ++ } else { ++ plugin_manager_object = g_object_new (GDM_TYPE_PLUGIN_MANAGER, NULL); ++ g_object_add_weak_pointer (plugin_manager_object, ++ (gpointer *) &plugin_manager_object); ++ } ++ ++ return GDM_PLUGIN_MANAGER (plugin_manager_object); +} + -+void -+gdm_greeter_extension_load_failed (GdmGreeterExtension *extension, -+ GError *error) ++GdmGreeterPlugin * ++gdm_plugin_manager_get_plugin (GdmPluginManager *manager, ++ const char *name) +{ -+ g_signal_emit (extension, signals [LOAD_FAILED], 0, error); ++ return g_hash_table_lookup (manager->priv->plugins, name); +} -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.h b/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.h -new file mode 100644 -index 0000000..283ba0e ---- /dev/null -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.h -@@ -0,0 +1,55 @@ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/gdm-plugin-manager.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/gdm-plugin-manager.h 2009-03-03 17:45:05.668022004 -0500 +@@ -0,0 +1,66 @@ +/* -+ * Copyright 2009 Red Hat, Inc. * ++ * Copyright (C) 2009 Red Hat, Inc. + * + * 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 @@ -10921,50 +8259,59 @@ index 0000000..283ba0e + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * -+ * Written by: Ray Strode ++ * Written by: Ray Strode ++ * + */ + -+#ifndef __GDM_GREETER_EXTENSION_H -+#define __GDM_GREETER_EXTENSION_H ++#ifndef __GDM_PLUGIN_MANAGER_H ++#define __GDM_PLUGIN_MANAGER_H + +#include + ++#include "gdm-greeter-plugin.h" ++ +G_BEGIN_DECLS + -+#define GDM_TYPE_GREETER_EXTENSION (gdm_greeter_extension_get_type ()) -+#define GDM_GREETER_EXTENSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_GREETER_EXTENSION, GdmGreeterExtension)) -+#define GDM_GREETER_EXTENSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_GREETER_EXTENSION, GdmGreeterExtensionClass)) -+#define GDM_IS_GREETER_EXTENSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_GREETER_EXTENSION)) -+#define GDM_GREETER_EXTENSION_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDM_TYPE_GREETER_EXTENSION, GdmGreeterExtensionIface)) ++#define GDM_TYPE_PLUGIN_MANAGER (gdm_plugin_manager_get_type ()) ++#define GDM_PLUGIN_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_PLUGIN_MANAGER, GdmPluginManager)) ++#define GDM_PLUGIN_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_PLUGIN_MANAGER, GdmPluginManagerClass)) ++#define GDM_IS_PLUGIN_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_PLUGIN_MANAGER)) ++#define GDM_IS_PLUGIN_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_PLUGIN_MANAGER)) ++#define GDM_PLUGIN_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_PLUGIN_MANAGER, GdmPluginManagerClass)) + -+typedef struct _GdmGreeterExtension GdmGreeterExtension; -+typedef struct _GdmGreeterExtensionIface GdmGreeterExtensionIface; ++typedef struct GdmPluginManagerPrivate GdmPluginManagerPrivate; + -+struct _GdmGreeterExtensionIface ++typedef struct +{ -+ GTypeInterface base_iface; ++ GObject parent; ++ GdmPluginManagerPrivate *priv; ++} GdmPluginManager; + -+ void (* loaded) (GdmGreeterExtension *extension); -+ void (* load_failed) (GdmGreeterExtension *extension, -+ GError *error); -+}; ++typedef struct ++{ ++ GObjectClass parent_class; + -+GType gdm_greeter_extension_get_type (void) G_GNUC_CONST; ++ void (* plugins_loaded) (GdmPluginManager *plugin_manager); ++ void (* plugin_added) (GdmPluginManager *plugin_manager, ++ GdmGreeterPlugin *plugin); ++ void (* plugin_removed) (GdmPluginManager *plugin_manager, ++ GdmGreeterPlugin *plugin); ++} GdmPluginManagerClass; + -+void gdm_greeter_extension_loaded (GdmGreeterExtension *extension); -+void gdm_greeter_extension_load_failed (GdmGreeterExtension *extension, -+ GError *error); ++GType gdm_plugin_manager_get_type (void); + -+typedef GdmGreeterExtension * (* GdmGreeterPluginGetExtensionFunc) (void); ++GdmPluginManager *gdm_plugin_manager_ref_default (void); ++ ++GdmGreeterPlugin *gdm_plugin_manager_get_plugin (GdmPluginManager *plugin, ++ const char *name); + +G_END_DECLS -+#endif /* __GDM_GREETER_EXTENSION_H */ -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c -new file mode 100644 -index 0000000..f72fa78 ---- /dev/null -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c -@@ -0,0 +1,117 @@ ++ ++#endif /* __GDM_PLUGIN_MANAGER_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/gdm-task-list.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/gdm-task-list.c 2009-03-03 17:45:05.799016489 -0500 +@@ -0,0 +1,329 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -10982,250 +8329,322 @@ index 0000000..f72fa78 + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * -+ * Written By: Ray Strode -+ * ++ * Written by: Ray Strode + */ + -+#include -+#include ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "gdm-task-list.h" ++ ++#define GDM_TASK_LIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_TASK_LIST, GdmTaskListPrivate)) ++ ++struct GdmTaskListPrivate ++{ ++ GtkWidget *box; ++ GList *tasks; ++}; ++ ++enum { ++ ACTIVATED = 0, ++ DEACTIVATED, ++ NUMBER_OF_SIGNALS ++}; ++ ++static guint signals[NUMBER_OF_SIGNALS]; ++ ++static void gdm_task_list_class_init (GdmTaskListClass *klass); ++static void gdm_task_list_init (GdmTaskList *task_list); ++static void gdm_task_list_finalize (GObject *object); ++ ++G_DEFINE_TYPE (GdmTaskList, gdm_task_list, GTK_TYPE_ALIGNMENT); ++ ++static void ++on_task_toggled (GdmTaskList *widget, ++ GtkRadioButton *button) ++{ ++ GdmTask *task; ++ ++ task = g_object_get_data (G_OBJECT (button), "gdm-task"); ++ ++ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { ++ g_signal_emit (widget, signals[ACTIVATED], 0, task); ++ } else { ++ g_signal_emit (widget, signals[DEACTIVATED], 0, task); ++ } ++} ++ ++GdmTask * ++gdm_task_list_foreach_task (GdmTaskList *task_list, ++ GdmTaskListForeachFunc search_func, ++ gpointer data) ++{ ++ GList *node; ++ ++ for (node = task_list->priv->tasks; node != NULL; node = node->next) { ++ GdmTask *task; ++ ++ task = node->data; ++ ++ if (search_func (task_list, task, data)) { ++ return g_object_ref (task); ++ } ++ } ++ ++ return NULL; ++} ++ ++static void ++on_task_enabled (GdmTaskList *task_list, ++ GdmTask *task) ++{ ++ GtkWidget *button; ++ GList *task_node; ++ ++ button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); ++ ++ gtk_widget_set_sensitive (button, TRUE); ++ ++ /* Sort the list such that the tasks the user clicks last end ++ * up first. This doesn't change the order in which the tasks ++ * appear in the UI, but will affect which tasks we implicitly ++ * activate if the currently active task gets disabled. ++ */ ++ task_node = g_list_find (task_list->priv->tasks, task); ++ if (task_node != NULL) { ++ task_list->priv->tasks = g_list_delete_link (task_list->priv->tasks, task_node); ++ task_list->priv->tasks = g_list_prepend (task_list->priv->tasks, ++ task); ++ } ++} ++ ++static void ++activate_first_available_task (GdmTaskList *task_list) ++{ ++ GList *node; ++ ++ node = task_list->priv->tasks; ++ while (node != NULL) { ++ GdmTask *task; ++ ++ task = GDM_TASK (node->data); ++ ++ if (gdm_task_list_set_active_task (task_list, task)) { ++ break; ++ } ++ ++ node = node->next; ++ } ++ ++} ++ ++static void ++on_task_disabled (GdmTaskList *task_list, ++ GdmTask *task) ++{ ++ GtkWidget *button; ++ gboolean was_active; ++ ++ button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); ++ was_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); ++ ++ gtk_widget_set_sensitive (button, FALSE); ++ ++ if (was_active) { ++ activate_first_available_task (task_list); ++ } ++} ++ ++void ++gdm_task_list_add_task (GdmTaskList *task_list, ++ GdmTask *task) ++{ ++ GtkWidget *image; ++ GtkWidget *button; ++ GIcon *icon; ++ char *description; ++ ++ if (task_list->priv->tasks == NULL) { ++ button = gtk_radio_button_new (NULL); ++ } else { ++ GdmTask *previous_task; ++ GtkRadioButton *previous_button; ++ ++ previous_task = GDM_TASK (task_list->priv->tasks->data); ++ previous_button = GTK_RADIO_BUTTON (g_object_get_data (G_OBJECT (previous_task), "gdm-task-list-button")); ++ button = gtk_radio_button_new_from_widget (previous_button); ++ } ++ g_object_set_data (G_OBJECT (task), "gdm-task-list-button", button); ++ ++ g_object_set (G_OBJECT (button), "draw-indicator", FALSE, NULL); ++ g_object_set_data (G_OBJECT (button), "gdm-task", task); ++ g_signal_connect_swapped (button, "toggled", ++ G_CALLBACK (on_task_toggled), ++ task_list); ++ ++ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); ++ gtk_widget_set_sensitive (button, gdm_task_is_enabled (task)); + -+#include "gdm-task.h" ++ g_signal_connect_swapped (G_OBJECT (task), "enabled", ++ G_CALLBACK (on_task_enabled), ++ task_list); + -+enum { -+ ENABLED, -+ DISABLED, -+ LAST_SIGNAL -+}; ++ g_signal_connect_swapped (G_OBJECT (task), "disabled", ++ G_CALLBACK (on_task_disabled), ++ task_list); + -+static guint signals [LAST_SIGNAL] = { 0, }; -+static void gdm_task_class_init (gpointer g_iface); ++ icon = gdm_task_get_icon (task); ++ image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_SMALL_TOOLBAR); ++ g_object_unref (icon); + -+GType -+gdm_task_get_type (void) -+{ -+ static GType task_type = 0; ++ gtk_widget_show (image); ++ gtk_container_add (GTK_CONTAINER (button), image); ++ description = gdm_task_get_description (task); ++ gtk_widget_set_tooltip_text (button, description); ++ g_free (description); ++ gtk_widget_show (button); + -+ if (!task_type) { -+ task_type = g_type_register_static_simple (G_TYPE_INTERFACE, -+ "GdmTask", -+ sizeof (GdmTaskIface), -+ (GClassInitFunc) gdm_task_class_init, -+ 0, NULL, 0); ++ gtk_container_add (GTK_CONTAINER (task_list->priv->box), button); ++ task_list->priv->tasks = g_list_append (task_list->priv->tasks, task); + -+ g_type_interface_add_prerequisite (task_type, G_TYPE_OBJECT); ++ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { ++ g_signal_emit (task_list, signals[ACTIVATED], 0, task); + } -+ -+ return task_type; +} + -+GIcon * -+gdm_task_get_icon (GdmTask *task) ++static void ++gdm_task_list_class_init (GdmTaskListClass *klass) +{ -+ return GDM_TASK_GET_IFACE (task)->get_icon (task); -+} ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); + -+char * -+gdm_task_get_description (GdmTask *task) -+{ -+ return GDM_TASK_GET_IFACE (task)->get_description (task); -+} ++ object_class->finalize = gdm_task_list_finalize; + -+char * -+gdm_task_get_name (GdmTask *task) -+{ -+ return GDM_TASK_GET_IFACE (task)->get_name (task); -+} ++ signals [ACTIVATED] = g_signal_new ("activated", ++ G_TYPE_FROM_CLASS (object_class), ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmTaskListClass, activated), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__OBJECT, ++ G_TYPE_NONE, ++ 1, G_TYPE_OBJECT); + -+void -+gdm_task_set_enabled (GdmTask *task, -+ gboolean should_enable) ++ signals [DEACTIVATED] = g_signal_new ("deactivated", ++ G_TYPE_FROM_CLASS (object_class), ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmTaskListClass, deactivated), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__OBJECT, ++ G_TYPE_NONE, ++ 1, G_TYPE_OBJECT); ++ ++ g_type_class_add_private (klass, sizeof (GdmTaskListPrivate)); ++} static void gdm_task_list_init (GdmTaskList *widget) +{ -+ g_object_set_data (G_OBJECT (task), "gdm-task-is-disabled", GINT_TO_POINTER (!should_enable)); ++ widget->priv = GDM_TASK_LIST_GET_PRIVATE (widget); + -+ if (should_enable) { -+ g_signal_emit (G_OBJECT (task), signals [ENABLED], 0); -+ } else { -+ g_signal_emit (G_OBJECT (task), signals [DISABLED], 0); -+ } -+} ++ gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 0, 0); ++ gtk_alignment_set (GTK_ALIGNMENT (widget), 0.0, 0.0, 0, 0); + -+gboolean -+gdm_task_is_enabled (GdmTask *task) -+{ -+ return !g_object_get_data (G_OBJECT (task), "gdm-task-is-disabled"); ++ widget->priv->box = gtk_hbox_new (TRUE, 2); ++ gtk_widget_show (widget->priv->box); ++ gtk_container_add (GTK_CONTAINER (widget), ++ widget->priv->box); +} + +static void -+gdm_task_class_init (gpointer g_iface) ++gdm_task_list_finalize (GObject *object) +{ -+ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); -+ -+ signals [ENABLED] = -+ g_signal_new ("enabled", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmTaskIface, enabled), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, -+ 0); -+ -+ signals [DISABLED] = -+ g_signal_new ("disabled", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmTaskIface, disabled), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, -+ 0); -+} -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h -new file mode 100644 -index 0000000..9894e65 ---- /dev/null -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written by: Ray Strode -+ */ -+ -+ -+#ifndef __GDM_TASK_H -+#define __GDM_TASK_H ++ GdmTaskList *widget; + -+#include -+#include ++ g_return_if_fail (object != NULL); ++ g_return_if_fail (GDM_IS_TASK_LIST (object)); + -+G_BEGIN_DECLS ++ widget = GDM_TASK_LIST (object); + -+#define GDM_TYPE_TASK (gdm_task_get_type ()) -+#define GDM_TASK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_TASK, GdmTask)) -+#define GDM_TASK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_TASK, GdmTaskIface)) -+#define GDM_IS_TASK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_TASK)) -+#define GDM_TASK_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDM_TYPE_TASK, GdmTaskIface)) ++ g_list_foreach (widget->priv->tasks, (GFunc) g_free, NULL); ++ g_list_free (widget->priv->tasks); + -+typedef struct _GdmTask GdmTask; -+typedef struct _GdmTaskIface GdmTaskIface; ++ G_OBJECT_CLASS (gdm_task_list_parent_class)->finalize (object); ++} + -+struct _GdmTaskIface ++GtkWidget * ++gdm_task_list_new (void) +{ -+ GTypeInterface base_iface; ++ GObject *object; + -+ /* methods */ -+ GIcon * (* get_icon) (GdmTask *task); -+ char * (* get_description) (GdmTask *task); -+ char * (* get_name) (GdmTask *task); -+ /* signals */ -+ void (* enabled) (GdmTask *task); -+ void (* disabled) (GdmTask *task); -+}; ++ object = g_object_new (GDM_TYPE_TASK_LIST, NULL); + -+GType gdm_task_get_type (void) G_GNUC_CONST; ++ return GTK_WIDGET (object); ++} + -+GIcon *gdm_task_get_icon (GdmTask *task); -+char *gdm_task_get_description (GdmTask *task); -+char *gdm_task_get_name (GdmTask *task); -+void gdm_task_set_enabled (GdmTask *task, -+ gboolean should_enable); -+gboolean gdm_task_is_enabled (GdmTask *task); -+G_END_DECLS ++gboolean ++gdm_task_list_task_is_active (GdmTaskList *task_list, ++ GdmTask *task) ++{ ++ GtkWidget *button; + -+#endif /* __GDM_TASK_H */ -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc.in b/gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc.in -new file mode 100644 -index 0000000..a429d99 ---- /dev/null -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc.in -@@ -0,0 +1,11 @@ -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+libdir=@libdir@ -+includedir=@includedir@ -+pluginsdir=@GDM_SIMPLE_GREETER_PLUGINS_DIR@ ++ button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); + -+Name: GDM Simple Greeter -+Description: Library for GDM Simple Greeter Plugins -+Version: @VERSION@ -+Libs: -L${libdir} -lgdmsimplegreeter -+Cflags: -I${includedir}/gdm/simple-greeter -diff --git a/gui/simple-greeter/plugins/Makefile.am b/gui/simple-greeter/plugins/Makefile.am -new file mode 100644 -index 0000000..c0390db ---- /dev/null -+++ b/gui/simple-greeter/plugins/Makefile.am -@@ -0,0 +1 @@ -+SUBDIRS = password -diff --git a/gui/simple-greeter/plugins/password/Makefile.am b/gui/simple-greeter/plugins/password/Makefile.am -new file mode 100644 -index 0000000..18b9801 ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/Makefile.am -@@ -0,0 +1,40 @@ -+NULL = ++ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); ++} + -+AM_CPPFLAGS = \ -+ -I$(top_srcdir)/common \ -+ -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ -+ -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ -+ -DDMCONFDIR=\""$(dmconfdir)"\" \ -+ -DGDMCONFDIR=\"$(gdmconfdir)\" \ -+ -DDATADIR=\""$(datadir)"\" \ -+ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -+ -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ -+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ -+ -DLIBEXECDIR=\""$(libexecdir)"\" \ -+ -DSBINDIR=\""$(sbindir)"\" \ -+ $(DISABLE_DEPRECATED_CFLAGS) \ -+ $(GTK_CFLAGS) \ -+ $(SIMPLE_GREETER_CFLAGS) \ -+ $(POLKIT_GNOME_CFLAGS) \ -+ $(NULL) ++GdmTask * ++gdm_task_list_get_active_task (GdmTaskList *widget) ++{ ++ return gdm_task_list_foreach_task (widget, ++ (GdmTaskListForeachFunc) ++ gdm_task_list_task_is_active, ++ NULL); ++} + -+plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) -+plugin_LTLIBRARIES = password.la ++gboolean ++gdm_task_list_set_active_task (GdmTaskList *widget, ++ GdmTask *task) ++{ ++ GtkWidget *button; ++ gboolean was_sensitive; ++ gboolean was_activated; + -+password_la_CFLAGS = \ -+ $(SIMPLE_GREETER_CFLAGS) \ -+ $(NULL) ++ was_sensitive = GTK_WIDGET_SENSITIVE (widget); ++ gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE); + -+password_la_LDFLAGS = -module -avoid-version -export-dynamic -+password_la_LIBADD = ../../../../common/libgdmcommon.la \ -+ ../../libgdmsimplegreeter/libgdmsimplegreeter.la -+password_la_SOURCES = \ -+ gdm-password-extension.h \ -+ gdm-password-extension.c \ -+ plugin.c ++ button = GTK_WIDGET (g_object_get_data (G_OBJECT (task), ++ "gdm-task-list-button")); ++ ++ was_activated = FALSE; ++ if (GTK_WIDGET_IS_SENSITIVE (button)) { ++ if (gtk_widget_activate (button)) { ++ was_activated = TRUE; ++ } ++ } + -+EXTRA_DIST = gdm-password ++ gtk_widget_set_sensitive (GTK_WIDGET (widget), was_sensitive); ++ return was_activated; ++} + -+MAINTAINERCLEANFILES = \ -+ *~ \ -+ Makefile.in -diff --git a/gui/simple-greeter/plugins/password/gdm-password-extension.c b/gui/simple-greeter/plugins/password/gdm-password-extension.c -new file mode 100644 -index 0000000..80c9ea7 ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/gdm-password-extension.c -@@ -0,0 +1,316 @@ ++int ++gdm_task_list_get_number_of_tasks (GdmTaskList *widget) ++{ ++ return g_list_length (widget->priv->tasks); ++} +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/gdm-task-list.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/gdm-task-list.h 2009-03-03 17:45:05.731016704 -0500 +@@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -11243,437 +8662,327 @@ index 0000000..80c9ea7 + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * -+ * Written By: Ray Strode -+ * ++ * Written by: Ray Strode + */ + -+#include -+#include "gdm-password-extension.h" -+#include "gdm-conversation.h" -+#include "gdm-task.h" ++#ifndef __GDM_TASK_LIST_H ++#define __GDM_TASK_LIST_H + -+#include ++#include +#include -+#include -+ -+struct _GdmPasswordExtensionPrivate -+{ -+ GIcon *icon; -+ GtkWidget *page; -+ GtkActionGroup *actions; -+ -+ GtkWidget *message_label; -+ GtkWidget *prompt_label; -+ GtkWidget *prompt_entry; ++#include + -+ guint answer_pending : 1; -+}; ++#include "gdm-task.h" + -+static void gdm_password_extension_finalize (GObject *object); ++G_BEGIN_DECLS + -+static void gdm_task_iface_init (GdmTaskIface *iface); -+static void gdm_conversation_iface_init (GdmConversationIface *iface); -+static void gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface); ++#define GDM_TYPE_TASK_LIST (gdm_task_list_get_type ()) ++#define GDM_TASK_LIST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_TASK_LIST, GdmTaskList)) ++#define GDM_TASK_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_TASK_LIST, GdmTaskListClass)) ++#define GDM_IS_TASK_LIST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_TASK_LIST)) ++#define GDM_IS_TASK_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_TASK_LIST)) ++#define GDM_TASK_LIST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_TASK_LIST, GdmTaskListClass)) + -+G_DEFINE_TYPE_WITH_CODE (GdmPasswordExtension, -+ gdm_password_extension, -+ G_TYPE_OBJECT, -+ G_IMPLEMENT_INTERFACE (GDM_TYPE_GREETER_EXTENSION, -+ gdm_greeter_extension_iface_init) -+ G_IMPLEMENT_INTERFACE (GDM_TYPE_TASK, -+ gdm_task_iface_init) -+ G_IMPLEMENT_INTERFACE (GDM_TYPE_CONVERSATION, -+ gdm_conversation_iface_init)); ++typedef struct GdmTaskListPrivate GdmTaskListPrivate; ++typedef struct _GdmTaskList GdmTaskList; + -+static void -+gdm_password_extension_set_message (GdmConversation *conversation, -+ const char *message) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ gtk_widget_show (extension->priv->message_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->message_label), message); -+} ++typedef gboolean (* GdmTaskListForeachFunc) (GdmTaskList *task_list, ++ GdmTask *task, ++ gpointer data); + -+static void -+gdm_password_extension_ask_question (GdmConversation *conversation, -+ const char *message) ++struct _GdmTaskList +{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ gtk_widget_show (extension->priv->prompt_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); -+ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); -+ gtk_widget_show (extension->priv->prompt_entry); -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ extension->priv->answer_pending = TRUE; -+} ++ GtkAlignment parent; ++ GdmTaskListPrivate *priv; ++}; + -+static void -+gdm_password_extension_ask_secret (GdmConversation *conversation, -+ const char *message) ++typedef struct +{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ gtk_widget_show (extension->priv->prompt_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); -+ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), FALSE); -+ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+ gtk_widget_show (extension->priv->prompt_entry); -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ extension->priv->answer_pending = TRUE; -+} ++ GtkAlignmentClass parent_class; + -+static void -+gdm_password_extension_reset (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ gtk_widget_hide (extension->priv->prompt_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); ++ void (* deactivated) (GdmTaskList *widget, ++ GdmTask *task); ++ void (* activated) (GdmTaskList *widget, ++ GdmTask *task); ++} GdmTaskListClass; + -+ gtk_widget_hide (extension->priv->prompt_entry); -+ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); -+ extension->priv->answer_pending = FALSE; ++GType gdm_task_list_get_type (void); ++GtkWidget * gdm_task_list_new (void); + -+ gdm_task_set_enabled (GDM_TASK (conversation), FALSE); -+} + -+static void -+gdm_password_extension_set_ready (GdmConversation *conversation) -+{ -+ gdm_task_set_enabled (GDM_TASK (conversation), TRUE); -+} ++gboolean gdm_task_list_task_is_active (GdmTaskList *task_list, ++ GdmTask *task); ++GdmTask * gdm_task_list_get_active_task (GdmTaskList *widget); ++gboolean gdm_task_list_set_active_task (GdmTaskList *widget, ++ GdmTask *task); ++GdmTask * gdm_task_list_foreach_task (GdmTaskList *widget, ++ GdmTaskListForeachFunc foreach_func, ++ gpointer data); ++void gdm_task_list_add_task (GdmTaskList *widget, ++ GdmTask *task); + -+char * -+gdm_password_extension_get_service_name (GdmConversation *conversation) -+{ -+ return g_strdup ("gdm"); -+} ++int gdm_task_list_get_number_of_tasks (GdmTaskList *widget); ++G_END_DECLS + -+GtkWidget * -+gdm_password_extension_get_page (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ return extension->priv->page; -+} ++#endif /* __GDM_TASK_LIST_H */ +diff -up gdm-2.25.2/gui/simple-greeter/gdm-user-chooser-widget.c.multistack-but-boring gdm-2.25.2/gui/simple-greeter/gdm-user-chooser-widget.c +--- gdm-2.25.2/gui/simple-greeter/gdm-user-chooser-widget.c.multistack-but-boring 2008-09-24 10:05:37.000000000 -0400 ++++ gdm-2.25.2/gui/simple-greeter/gdm-user-chooser-widget.c 2009-03-03 17:45:05.795016346 -0500 +@@ -233,9 +233,30 @@ gdm_user_chooser_widget_set_show_user_au + char * + gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget) + { ++ char *active_item_id; ++ gboolean isnt_user; + -+GtkActionGroup * -+gdm_password_extension_get_actions (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ return g_object_ref (extension->priv->actions); -+} + g_return_val_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget), NULL); + +- return gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget)); ++ active_item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget)); ++ if (active_item_id == NULL) { ++ g_debug ("GdmUserChooserWidget: no active item in list"); ++ return NULL; ++ } + -+void -+gdm_password_extension_request_answer (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ const char *text; ++ gdm_chooser_widget_lookup_item (GDM_CHOOSER_WIDGET (widget), active_item_id, ++ NULL, NULL, NULL, NULL, NULL, ++ &isnt_user); + -+ if (!extension->priv->answer_pending) { -+ gdm_conversation_answer (conversation, NULL); -+ return; ++ if (isnt_user) { ++ g_debug ("GdmUserChooserWidget: active item '%s' isn't a user", active_item_id); ++ g_free (active_item_id); ++ return NULL; + } + -+ extension->priv->answer_pending = FALSE; -+ text = gtk_entry_get_text (GTK_ENTRY (extension->priv->prompt_entry)); -+ gdm_conversation_answer (conversation, text); ++ g_debug ("GdmUserChooserWidget: active item '%s' is a user", active_item_id); ++ ++ return active_item_id; + } + + void +@@ -340,7 +361,7 @@ add_user (GdmUserChooserWidget *widget, + return; + } + +- size = get_icon_height_for_widget (widget); ++ size = get_icon_height_for_widget (GTK_WIDGET (widget)); + pixbuf = gdm_user_render_icon (user, size); + if (pixbuf == NULL && widget->priv->stock_person_pixbuf != NULL) { + pixbuf = g_object_ref (widget->priv->stock_person_pixbuf); +@@ -580,7 +601,7 @@ get_stock_person_pixbuf (GdmUserChooserW + GdkPixbuf *pixbuf; + int size; + +- size = get_icon_height_for_widget (widget); ++ size = get_icon_height_for_widget (GTK_WIDGET (widget)); + + pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme, + DEFAULT_USER_ICON, +@@ -597,7 +618,7 @@ get_logged_in_pixbuf (GdmUserChooserWidg + GdkPixbuf *pixbuf; + int size; + +- size = get_icon_height_for_widget (widget); ++ size = get_icon_height_for_widget (GTK_WIDGET (widget)); + + pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme, + "emblem-default", +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c 2009-03-03 17:45:05.818018271 -0500 +@@ -0,0 +1,186 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ * ++ */ ++ ++#include ++#include ++ ++#include + -+ gtk_widget_hide (extension->priv->prompt_entry); -+ gtk_widget_hide (extension->priv->prompt_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); -+ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+} ++#include "gdm-conversation.h" ++#include "gdm-marshal.h" ++#include "gdm-task.h" + -+gboolean -+gdm_password_extension_focus (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ if (!extension->priv->answer_pending) { -+ gdm_conversation_answer (conversation, NULL); -+ return FALSE; -+ } ++enum { ++ ANSWER, ++ USER_CHOSEN, ++ CANCEL, ++ LAST_SIGNAL ++}; + -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ return TRUE; -+} ++static guint signals [LAST_SIGNAL] = { 0, }; + -+GIcon * -+gdm_password_extension_get_icon (GdmTask *task) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (task); -+ return g_object_ref (extension->priv->icon); -+} ++static void gdm_conversation_class_init (gpointer g_iface); + -+char * -+gdm_password_extension_get_name (GdmTask *task) ++GType ++gdm_conversation_get_type (void) +{ -+ return g_strdup (_("Password Authentication")); -+} ++ static GType type = 0; + -+char * -+gdm_password_extension_get_description (GdmTask *task) -+{ -+ return g_strdup (_("Log into session with username and password")); ++ if (!type) { ++ type = g_type_register_static_simple (G_TYPE_INTERFACE, ++ "GdmConversation", ++ sizeof (GdmConversationIface), ++ (GClassInitFunc) gdm_conversation_class_init, ++ 0, NULL, 0); ++ ++ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); ++ g_type_interface_add_prerequisite (type, GDM_TYPE_TASK); ++ } ++ ++ return type; +} + +static void -+gdm_task_iface_init (GdmTaskIface *iface) ++gdm_conversation_class_init (gpointer g_iface) +{ -+ iface->get_icon = gdm_password_extension_get_icon; -+ iface->get_description = gdm_password_extension_get_description; -+ iface->get_name = gdm_password_extension_get_name; ++ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); ++ ++ signals [ANSWER] = ++ g_signal_new ("answer", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmConversationIface, answer), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, ++ 1, G_TYPE_STRING); ++ signals [USER_CHOSEN] = ++ g_signal_new ("user-chosen", ++ iface_type, ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmConversationIface, user_chosen), ++ NULL, ++ NULL, ++ gdm_marshal_BOOLEAN__STRING, ++ G_TYPE_BOOLEAN, ++ 1, G_TYPE_STRING); ++ signals [CANCEL] = ++ g_signal_new ("cancel", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmConversationIface, cancel), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); +} + -+static void -+gdm_conversation_iface_init (GdmConversationIface *iface) ++void ++gdm_conversation_set_message (GdmConversation *conversation, ++ const char *message) +{ -+ iface->set_message = gdm_password_extension_set_message; -+ iface->ask_question = gdm_password_extension_ask_question; -+ iface->ask_secret = gdm_password_extension_ask_secret; -+ iface->reset = gdm_password_extension_reset; -+ iface->set_ready = gdm_password_extension_set_ready; -+ iface->get_service_name = gdm_password_extension_get_service_name; -+ iface->get_page = gdm_password_extension_get_page; -+ iface->get_actions = gdm_password_extension_get_actions; -+ iface->request_answer = gdm_password_extension_request_answer; -+ iface->focus = gdm_password_extension_focus; ++ GDM_CONVERSATION_GET_IFACE (conversation)->set_message (conversation, message); +} + -+static void -+gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) ++void ++gdm_conversation_ask_question (GdmConversation *conversation, ++ const char *message) +{ ++ GDM_CONVERSATION_GET_IFACE (conversation)->ask_question (conversation, message); +} + -+static void -+gdm_password_extension_class_init (GdmPasswordExtensionClass *extension_class) ++void ++gdm_conversation_ask_secret (GdmConversation *conversation, ++ const char *message) +{ -+ GObjectClass *object_class; -+ -+ object_class = G_OBJECT_CLASS (extension_class); -+ -+ object_class->finalize = gdm_password_extension_finalize; -+ -+ g_type_class_add_private (extension_class, -+ sizeof (GdmPasswordExtensionPrivate)); ++ GDM_CONVERSATION_GET_IFACE (conversation)->ask_secret (conversation, message); +} + -+static void -+gdm_password_extension_finalize (GObject *object) ++void ++gdm_conversation_reset (GdmConversation *conversation) +{ ++ return GDM_CONVERSATION_GET_IFACE (conversation)->reset (conversation); +} + -+static void -+on_activate_log_in (GdmPasswordExtension *extension) ++void ++gdm_conversation_set_ready (GdmConversation *conversation) +{ -+ gdm_password_extension_request_answer (GDM_CONVERSATION (extension)); ++ return GDM_CONVERSATION_GET_IFACE (conversation)->set_ready (conversation); +} + -+static void -+create_page (GdmPasswordExtension *extension) ++char * ++gdm_conversation_get_service_name (GdmConversation *conversation) +{ -+ GtkBuilder *builder; -+ GObject *object; -+ GError *error; -+ -+ builder = gtk_builder_new (); -+ -+ error = NULL; -+ gtk_builder_add_from_file (builder, -+ "/usr/share/gdm/simple-greeter/extensions/password/page.ui", -+ &error); -+ -+ if (error != NULL) { -+ g_warning ("Could not load UI file: %s", error->message); -+ g_error_free (error); -+ return; -+ } -+ -+ object = gtk_builder_get_object (builder, "page"); -+ g_object_ref (object); -+ -+ extension->priv->page = GTK_WIDGET (object); -+ -+ object = gtk_builder_get_object (builder, "auth-prompt-label"); -+ g_object_ref (object); -+ extension->priv->prompt_label = GTK_WIDGET (object); -+ gtk_widget_hide (extension->priv->prompt_label); -+ -+ object = gtk_builder_get_object (builder, "auth-prompt-entry"); -+ g_object_ref (object); -+ extension->priv->prompt_entry = GTK_WIDGET (object); -+ gtk_widget_hide (extension->priv->prompt_entry); -+ -+ object = gtk_builder_get_object (builder, "auth-message-label"); -+ g_object_ref (object); -+ extension->priv->message_label = GTK_WIDGET (object); -+ gtk_widget_show (extension->priv->message_label); -+ -+ g_object_unref (builder); ++ return GDM_CONVERSATION_GET_IFACE (conversation)->get_service_name (conversation); +} + -+static void -+create_actions (GdmPasswordExtension *extension) ++GtkWidget * ++gdm_conversation_get_page (GdmConversation *conversation) +{ -+ GtkAction *action; -+ -+ extension->priv->actions = gtk_action_group_new ("gdm-password-extension"); -+ -+ action = gtk_action_new (GDM_CONVERSATION_DEFAULT_ACTION, -+ _("Log In"), -+ _("Log into the currently selected sesson"), -+ NULL); -+ g_signal_connect_swapped (action, "activate", -+ G_CALLBACK (on_activate_log_in), extension); -+ g_object_set (G_OBJECT (action), "icon-name", "go-home", NULL); -+ gtk_action_group_add_action (extension->priv->actions, -+ action); ++ return GDM_CONVERSATION_GET_IFACE (conversation)->get_page (conversation); +} + -+static void -+gdm_password_extension_init (GdmPasswordExtension *extension) ++GtkActionGroup * ++gdm_conversation_get_actions (GdmConversation *conversation) +{ -+ extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension, -+ GDM_TYPE_PASSWORD_EXTENSION, -+ GdmPasswordExtensionPrivate); -+ -+ extension->priv->icon = g_themed_icon_new ("dialog-password"); -+ create_page (extension); -+ create_actions (extension); -+ -+ gdm_password_extension_reset (GDM_CONVERSATION (extension)); ++ return GDM_CONVERSATION_GET_IFACE (conversation)->get_actions (conversation); +} -diff --git a/gui/simple-greeter/plugins/password/gdm-password-extension.h b/gui/simple-greeter/plugins/password/gdm-password-extension.h -new file mode 100644 -index 0000000..99fe17b ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/gdm-password-extension.h -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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, 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 -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written By: Ray Strode -+ */ -+ -+#ifndef __GDM_PASSWORD_EXTENSION_H -+#define __GDM_PASSWORD_EXTENSION_H -+ -+#include -+#include "gdm-greeter-extension.h" + -+G_BEGIN_DECLS -+ -+#define GDM_TYPE_PASSWORD_EXTENSION (gdm_password_extension_get_type ()) -+#define GDM_PASSWORD_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_PASSWORD_EXTENSION, GdmPasswordExtension)) -+#define GDM_PASSWORD_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_PASSWORD_EXTENSION, GdmPasswordExtensionClass)) -+#define GDM_IS_PASSWORD_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_PASSWORD_EXTENSION)) -+#define GDM_IS_PASSWORD_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_PASSWORD_EXTENSION)) -+#define GDM_PASSWORD_EXTENSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_PASSWORD_EXTENSION, GdmPasswordExtensionClass)) ++gboolean ++gdm_conversation_focus (GdmConversation *conversation) ++{ ++ return GDM_CONVERSATION_GET_IFACE (conversation)->focus (conversation); ++} + -+typedef struct _GdmPasswordExtensionPrivate GdmPasswordExtensionPrivate; ++void ++gdm_conversation_request_answer (GdmConversation *conversation) ++{ ++ return GDM_CONVERSATION_GET_IFACE (conversation)->request_answer (conversation); ++} + -+typedef struct ++/* protected ++ */ ++void ++gdm_conversation_answer (GdmConversation *conversation, ++ const char *answer) +{ -+ GObject parent; -+ GdmPasswordExtensionPrivate *priv; -+} GdmPasswordExtension; ++ g_signal_emit (conversation, signals [ANSWER], 0, answer); ++} + -+typedef struct ++void ++gdm_conversation_cancel (GdmConversation *conversation) +{ -+ GObjectClass parent_class; -+} GdmPasswordExtensionClass; ++ g_signal_emit (conversation, signals [CANCEL], 0); ++} + -+GType gdm_password_extension_get_type (void); ++gboolean ++gdm_conversation_choose_user (GdmConversation *conversation, ++ const char *username) ++{ ++ gboolean was_chosen; + -+GdmPasswordExtension *gdm_password_extension_new (void); ++ was_chosen = FALSE; + -+G_END_DECLS ++ g_signal_emit (conversation, signals [USER_CHOSEN], 0, username, &was_chosen); + -+#endif /* GDM_PASSWORD_EXTENSION_H */ -diff --git a/gui/simple-greeter/plugins/password/page.ui b/gui/simple-greeter/plugins/password/page.ui -new file mode 100644 -index 0000000..fe6da78 ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/page.ui -@@ -0,0 +1,56 @@ -+ -+ -+ -+ -+ True -+ vertical -+ -+ -+ True -+ -+ -+ True -+ -+ -+ False -+ False -+ 0 -+ -+ -+ -+ -+ True -+ True -+ True -+ -+ -+ 1 -+ -+ -+ -+ -+ True -+ True -+ 0 -+ -+ -+ -+ -+ True -+ -+ -+ True -+ -+ -+ 0 -+ -+ -+ -+ -+ True -+ True -+ 1 -+ -+ -+ -+ -diff --git a/gui/simple-greeter/plugins/password/plugin.c b/gui/simple-greeter/plugins/password/plugin.c -new file mode 100644 -index 0000000..9b87c67 ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/plugin.c -@@ -0,0 +1,40 @@ ++ return was_chosen; ++} +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h 2009-03-03 17:45:05.819016578 -0500 +@@ -0,0 +1,93 @@ +/* -+ * Copyright (C) 2009 Red Hat, Inc. ++ * Copyright (C) Red Hat, Inc. + * + * 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 @@ -11689,126 +8998,86 @@ index 0000000..9b87c67 + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * -+ * Written By: Ray Strode -+ * ++ * Written by: Ray Strode + */ + -+#include "gdm-password-extension.h" + -+#include ++#ifndef __GDM_CONVERSATION_H ++#define __GDM_CONVERSATION_H ++ ++#include +#include + -+GdmGreeterExtension * -+gdm_greeter_plugin_get_extension (void) -+{ -+ static GObject *extension; ++G_BEGIN_DECLS + -+ if (extension != NULL) { -+ g_object_ref (extension); -+ } else { -+ extension = g_object_new (GDM_TYPE_PASSWORD_EXTENSION, NULL); -+ g_object_add_weak_pointer (extension, (gpointer *) &extension); -+ } ++#define GDM_TYPE_CONVERSATION (gdm_conversation_get_type ()) ++#define GDM_CONVERSATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_CONVERSATION, GdmConversation)) ++#define GDM_CONVERSATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_CONVERSATION, GdmConversationIface)) ++#define GDM_IS_CONVERSATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_CONVERSATION)) ++#define GDM_CONVERSATION_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDM_TYPE_CONVERSATION, GdmConversationIface)) + -+ return GDM_GREETER_EXTENSION (extension); -+} --- -1.6.1 - - -From d979b62871f4519423fbb451f0dd010a30d40464 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 16:25:47 -0500 -Subject: [PATCH 25/65] Add fingerprint plugin - -This commit adds a plugin to initiate a conversation for -fingerprint scans. ---- - configure.ac | 1 + - gui/simple-greeter/plugins/Makefile.am | 2 +- - gui/simple-greeter/plugins/fingerprint/Makefile.am | 40 +++ - .../fingerprint/gdm-fingerprint-extension.c | 299 ++++++++++++++++++++ - .../fingerprint/gdm-fingerprint-extension.h | 56 ++++ - gui/simple-greeter/plugins/fingerprint/page.ui | 56 ++++ - gui/simple-greeter/plugins/fingerprint/plugin.c | 40 +++ - 7 files changed, 493 insertions(+), 1 deletions(-) - create mode 100644 gui/simple-greeter/plugins/fingerprint/Makefile.am - create mode 100644 gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c - create mode 100644 gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.h - create mode 100644 gui/simple-greeter/plugins/fingerprint/page.ui - create mode 100644 gui/simple-greeter/plugins/fingerprint/plugin.c - -diff --git a/configure.ac b/configure.ac -index cc2576f..5b2519a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1438,6 +1438,7 @@ gui/simple-greeter/libgdmsimplegreeter/Makefile - gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc - gui/simple-greeter/plugins/Makefile - gui/simple-greeter/plugins/password/Makefile -+gui/simple-greeter/plugins/fingerprint/Makefile - gui/simple-chooser/Makefile - gui/user-switch-applet/Makefile - utils/Makefile -diff --git a/gui/simple-greeter/plugins/Makefile.am b/gui/simple-greeter/plugins/Makefile.am -index c0390db..9811a68 100644 ---- a/gui/simple-greeter/plugins/Makefile.am -+++ b/gui/simple-greeter/plugins/Makefile.am -@@ -1 +1 @@ --SUBDIRS = password -+SUBDIRS = password fingerprint -diff --git a/gui/simple-greeter/plugins/fingerprint/Makefile.am b/gui/simple-greeter/plugins/fingerprint/Makefile.am -new file mode 100644 -index 0000000..6f2d727 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/Makefile.am -@@ -0,0 +1,40 @@ -+NULL = ++#define GDM_CONVERSATION_DEFAULT_ACTION "default-action" ++#define GDM_CONVERSATION_OTHER_USER "__other" + -+AM_CPPFLAGS = \ -+ -I$(top_srcdir)/common \ -+ -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ -+ -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ -+ -DDMCONFDIR=\""$(dmconfdir)"\" \ -+ -DGDMCONFDIR=\"$(gdmconfdir)\" \ -+ -DDATADIR=\""$(datadir)"\" \ -+ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -+ -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ -+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ -+ -DLIBEXECDIR=\""$(libexecdir)"\" \ -+ -DSBINDIR=\""$(sbindir)"\" \ -+ $(DISABLE_DEPRECATED_CFLAGS) \ -+ $(GTK_CFLAGS) \ -+ $(SIMPLE_GREETER_CFLAGS) \ -+ $(POLKIT_GNOME_CFLAGS) \ -+ $(NULL) ++typedef struct _GdmConversation GdmConversation; ++typedef struct _GdmConversationIface GdmConversationIface; + -+plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) -+plugin_LTLIBRARIES = fingerprint.la ++struct _GdmConversationIface ++{ ++ GTypeInterface base_iface; + -+fingerprint_la_CFLAGS = \ -+ $(SIMPLE_GREETER_CFLAGS) \ -+ $(NULL) ++ /* methods */ ++ void (* set_message) (GdmConversation *conversation, ++ const char *message); ++ void (* ask_question) (GdmConversation *conversation, ++ const char *message); ++ void (* ask_secret) (GdmConversation *conversation, ++ const char *message); ++ void (* reset) (GdmConversation *conversation); ++ void (* set_ready) (GdmConversation *conversation); ++ char * (* get_service_name) (GdmConversation *conversation); ++ GtkWidget * (* get_page) (GdmConversation *conversation); ++ GtkActionGroup * (* get_actions) (GdmConversation *conversation); ++ void (* request_answer) (GdmConversation *conversation); ++ gboolean (* focus) (GdmConversation *conversation); + -+fingerprint_la_LDFLAGS = -module -avoid-version -export-dynamic -+fingerprint_la_LIBADD = ../../../../common/libgdmcommon.la \ -+ ../../libgdmsimplegreeter/libgdmsimplegreeter.la -+fingerprint_la_SOURCES = \ -+ gdm-fingerprint-extension.h \ -+ gdm-fingerprint-extension.c \ -+ plugin.c ++ /* signals */ ++ char * (* answer) (GdmConversation *conversation); ++ void (* cancel) (GdmConversation *conversation); ++ gboolean (* user_chosen) (GdmConversation *conversation); ++}; + -+EXTRA_DIST = gdm-fingerprint ++GType gdm_conversation_get_type (void) G_GNUC_CONST; + -+MAINTAINERCLEANFILES = \ -+ *~ \ -+ Makefile.in -diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -new file mode 100644 -index 0000000..2a4027c ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -@@ -0,0 +1,299 @@ ++void gdm_conversation_set_message (GdmConversation *conversation, ++ const char *message); ++void gdm_conversation_ask_question (GdmConversation *conversation, ++ const char *message); ++void gdm_conversation_ask_secret (GdmConversation *conversation, ++ const char *message); ++void gdm_conversation_reset (GdmConversation *converastion); ++void gdm_conversation_set_ready (GdmConversation *converastion); ++char *gdm_conversation_get_service_name (GdmConversation *conversation); ++GtkWidget *gdm_conversation_get_page (GdmConversation *conversation); ++GtkActionGroup *gdm_conversation_get_actions (GdmConversation *conversation); ++void gdm_conversation_request_answer (GdmConversation *conversation); ++gboolean gdm_conversation_focus (GdmConversation *conversation); ++ ++/* protected ++ */ ++void gdm_conversation_answer (GdmConversation *conversation, ++ const char *answer); ++void gdm_conversation_cancel (GdmConversation *conversation); ++gboolean gdm_conversation_choose_user (GdmConversation *conversation, ++ const char *username); ++ ++G_END_DECLS ++ ++#endif /* __GDM_CONVERSATION_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.c 2009-03-03 17:45:05.675017070 -0500 +@@ -0,0 +1,93 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -11830,297 +9099,290 @@ index 0000000..2a4027c + * + */ + -+#include -+#include "gdm-fingerprint-extension.h" -+#include "gdm-conversation.h" -+#include "gdm-task.h" -+ -+#include -+#include -+#include -+ -+struct _GdmFingerprintExtensionPrivate -+{ -+ GIcon *icon; -+ GtkWidget *page; -+ GtkActionGroup *actions; -+ -+ GtkWidget *message_label; -+ GtkWidget *prompt_label; -+ GtkWidget *prompt_entry; -+ -+ guint answer_pending : 1; -+}; -+ -+static void gdm_fingerprint_extension_finalize (GObject *object); ++#include ++#include + -+static void gdm_task_iface_init (GdmTaskIface *iface); -+static void gdm_conversation_iface_init (GdmConversationIface *iface); -+static void gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface); ++#include "gdm-greeter-extension.h" + -+G_DEFINE_TYPE_WITH_CODE (GdmFingerprintExtension, -+ gdm_fingerprint_extension, -+ G_TYPE_OBJECT, -+ G_IMPLEMENT_INTERFACE (GDM_TYPE_GREETER_EXTENSION, -+ gdm_greeter_extension_iface_init) -+ G_IMPLEMENT_INTERFACE (GDM_TYPE_TASK, -+ gdm_task_iface_init) -+ G_IMPLEMENT_INTERFACE (GDM_TYPE_CONVERSATION, -+ gdm_conversation_iface_init)); ++enum { ++ LOADED, ++ LOAD_FAILED, ++ LAST_SIGNAL ++}; + -+static void -+gdm_fingerprint_extension_set_message (GdmConversation *conversation, -+ const char *message) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ gtk_widget_show (extension->priv->message_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->message_label), message); -+} ++static guint signals [LAST_SIGNAL] = { 0, }; + -+static void -+gdm_fingerprint_extension_ask_question (GdmConversation *conversation, -+ const char *message) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ gtk_widget_show (extension->priv->prompt_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); -+ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); -+ gtk_widget_show (extension->priv->prompt_entry); -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ extension->priv->answer_pending = TRUE; -+} ++static void gdm_greeter_extension_class_init (gpointer g_iface); + -+static void -+gdm_fingerprint_extension_ask_secret (GdmConversation *conversation, -+ const char *message) ++GType ++gdm_greeter_extension_get_type (void) +{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ gtk_widget_show (extension->priv->prompt_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); -+ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), FALSE); -+ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+ gtk_widget_show (extension->priv->prompt_entry); -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ extension->priv->answer_pending = TRUE; -+} ++ static GType greeter_extension_type = 0; + -+static void -+gdm_fingerprint_extension_reset (GdmConversation *conversation) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ gtk_widget_hide (extension->priv->prompt_label); -+ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); ++ if (!greeter_extension_type) { ++ greeter_extension_type = g_type_register_static_simple (G_TYPE_INTERFACE, ++ "GdmGreeterExtension", ++ sizeof (GdmGreeterExtensionIface), ++ (GClassInitFunc) gdm_greeter_extension_class_init, ++ 0, NULL, 0); + -+ gtk_widget_hide (extension->priv->prompt_entry); -+ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); -+ extension->priv->answer_pending = FALSE; ++ g_type_interface_add_prerequisite (greeter_extension_type, G_TYPE_OBJECT); ++ } + -+ gdm_task_set_enabled (GDM_TASK (conversation), FALSE); ++ return greeter_extension_type; +} + +static void -+gdm_fingerprint_extension_set_ready (GdmConversation *conversation) ++gdm_greeter_extension_class_init (gpointer g_iface) +{ -+ gdm_task_set_enabled (GDM_TASK (conversation), TRUE); -+} ++ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); + -+char * -+gdm_fingerprint_extension_get_service_name (GdmConversation *conversation) -+{ -+ return g_strdup ("fingerprint-auth"); -+} ++ signals [LOADED] = ++ g_signal_new ("loaded", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmGreeterExtensionIface, loaded), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); + -+GtkWidget * -+gdm_fingerprint_extension_get_page (GdmConversation *conversation) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ return extension->priv->page; ++ signals [LOADED] = ++ g_signal_new ("load_failed", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmGreeterExtensionIface, load_failed), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__POINTER, ++ G_TYPE_NONE, ++ 1, G_TYPE_POINTER); +} + -+GtkActionGroup * -+gdm_fingerprint_extension_get_actions (GdmConversation *conversation) ++void ++gdm_greeter_extension_loaded (GdmGreeterExtension *extension) +{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ -+ return g_object_ref (extension->priv->actions); ++ g_signal_emit (extension, signals [LOADED], 0); +} + +void -+gdm_fingerprint_extension_request_answer (GdmConversation *conversation) ++gdm_greeter_extension_load_failed (GdmGreeterExtension *extension, ++ GError *error) +{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ const char *text; ++ g_signal_emit (extension, signals [LOAD_FAILED], 0, error); ++} +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.h 2009-03-03 17:45:05.676019847 -0500 +@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2009 Red Hat, Inc. * ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written by: Ray Strode ++ */ + -+ if (!extension->priv->answer_pending) { -+ gdm_conversation_answer (conversation, NULL); -+ return; -+ } ++#ifndef __GDM_GREETER_EXTENSION_H ++#define __GDM_GREETER_EXTENSION_H + -+ extension->priv->answer_pending = FALSE; -+ text = gtk_entry_get_text (GTK_ENTRY (extension->priv->prompt_entry)); -+ gdm_conversation_answer (conversation, text); ++#include + -+ gtk_widget_hide (extension->priv->prompt_entry); -+ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); -+ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+} ++G_BEGIN_DECLS + -+gboolean -+gdm_fingerprint_extension_focus (GdmConversation *conversation) ++#define GDM_TYPE_GREETER_EXTENSION (gdm_greeter_extension_get_type ()) ++#define GDM_GREETER_EXTENSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_GREETER_EXTENSION, GdmGreeterExtension)) ++#define GDM_GREETER_EXTENSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_GREETER_EXTENSION, GdmGreeterExtensionClass)) ++#define GDM_IS_GREETER_EXTENSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_GREETER_EXTENSION)) ++#define GDM_GREETER_EXTENSION_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDM_TYPE_GREETER_EXTENSION, GdmGreeterExtensionIface)) ++ ++typedef struct _GdmGreeterExtension GdmGreeterExtension; ++typedef struct _GdmGreeterExtensionIface GdmGreeterExtensionIface; ++ ++struct _GdmGreeterExtensionIface +{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ GTypeInterface base_iface; + -+ if (!extension->priv->answer_pending) { -+ return FALSE; -+ } ++ void (* loaded) (GdmGreeterExtension *extension); ++ void (* load_failed) (GdmGreeterExtension *extension, ++ GError *error); ++}; + -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ return TRUE; -+} ++GType gdm_greeter_extension_get_type (void) G_GNUC_CONST; + -+GIcon * -+gdm_fingerprint_extension_get_icon (GdmTask *task) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (task); -+ return g_object_ref (extension->priv->icon); -+} ++void gdm_greeter_extension_loaded (GdmGreeterExtension *extension); ++void gdm_greeter_extension_load_failed (GdmGreeterExtension *extension, ++ GError *error); + -+char * -+gdm_fingerprint_extension_get_name (GdmTask *task) -+{ -+ return g_strdup (_("Fingerprint Authentication")); -+} ++typedef GdmGreeterExtension * (* GdmGreeterPluginGetExtensionFunc) (void); + -+char * -+gdm_fingerprint_extension_get_description (GdmTask *task) -+{ -+ return g_strdup (_("Log into session with fingerprint")); -+} ++G_END_DECLS ++#endif /* __GDM_GREETER_EXTENSION_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc.in +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc.in 2009-03-03 17:45:05.679016166 -0500 +@@ -0,0 +1,11 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@libdir@ ++includedir=@includedir@ ++pluginsdir=@GDM_SIMPLE_GREETER_PLUGINS_DIR@ + -+static void -+gdm_task_iface_init (GdmTaskIface *iface) -+{ -+ iface->get_icon = gdm_fingerprint_extension_get_icon; -+ iface->get_description = gdm_fingerprint_extension_get_description; -+ iface->get_name = gdm_fingerprint_extension_get_name; -+} ++Name: GDM Simple Greeter ++Description: Library for GDM Simple Greeter Plugins ++Version: @VERSION@ ++Libs: -L${libdir} -lgdmsimplegreeter ++Cflags: -I${includedir}/gdm/simple-greeter +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c 2009-03-03 17:45:05.772006668 -0500 +@@ -0,0 +1,123 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ * ++ */ + -+static void -+gdm_conversation_iface_init (GdmConversationIface *iface) -+{ -+ iface->set_message = gdm_fingerprint_extension_set_message; -+ iface->ask_question = gdm_fingerprint_extension_ask_question; -+ iface->ask_secret = gdm_fingerprint_extension_ask_secret; -+ iface->reset = gdm_fingerprint_extension_reset; -+ iface->set_ready = gdm_fingerprint_extension_set_ready; -+ iface->get_service_name = gdm_fingerprint_extension_get_service_name; -+ iface->get_page = gdm_fingerprint_extension_get_page; -+ iface->get_actions = gdm_fingerprint_extension_get_actions; -+ iface->request_answer = gdm_fingerprint_extension_request_answer; -+ iface->focus = gdm_fingerprint_extension_focus; -+} ++#include ++#include + -+static void -+gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) -+{ -+} ++#include "gdm-task.h" ++ ++enum { ++ ENABLED, ++ DISABLED, ++ LAST_SIGNAL ++}; + -+static void -+gdm_fingerprint_extension_class_init (GdmFingerprintExtensionClass *extension_class) ++static guint signals [LAST_SIGNAL] = { 0, }; ++static void gdm_task_class_init (gpointer g_iface); ++ ++GType ++gdm_task_get_type (void) +{ -+ GObjectClass *object_class; ++ static GType task_type = 0; + -+ object_class = G_OBJECT_CLASS (extension_class); ++ if (!task_type) { ++ task_type = g_type_register_static_simple (G_TYPE_INTERFACE, ++ "GdmTask", ++ sizeof (GdmTaskIface), ++ (GClassInitFunc) gdm_task_class_init, ++ 0, NULL, 0); + -+ object_class->finalize = gdm_fingerprint_extension_finalize; ++ g_type_interface_add_prerequisite (task_type, G_TYPE_OBJECT); ++ } + -+ g_type_class_add_private (extension_class, -+ sizeof (GdmFingerprintExtensionPrivate)); ++ return task_type; +} + -+static void -+gdm_fingerprint_extension_finalize (GObject *object) ++GIcon * ++gdm_task_get_icon (GdmTask *task) +{ ++ return GDM_TASK_GET_IFACE (task)->get_icon (task); +} + -+static void -+create_page (GdmFingerprintExtension *extension) ++char * ++gdm_task_get_description (GdmTask *task) +{ -+ GtkBuilder *builder; -+ GObject *object; -+ GError *error; ++ return GDM_TASK_GET_IFACE (task)->get_description (task); ++} + -+ builder = gtk_builder_new (); ++char * ++gdm_task_get_name (GdmTask *task) ++{ ++ return GDM_TASK_GET_IFACE (task)->get_name (task); ++} + -+ error = NULL; -+ gtk_builder_add_from_file (builder, -+ "/usr/share/gdm/simple-greeter/extensions/fingerprint/page.ui", -+ &error); ++void ++gdm_task_set_enabled (GdmTask *task, ++ gboolean should_enable) ++{ ++ g_object_set_data (G_OBJECT (task), "gdm-task-is-disabled", GINT_TO_POINTER (!should_enable)); + -+ if (error != NULL) { -+ g_warning ("Could not load UI file: %s", error->message); -+ g_error_free (error); -+ return; ++ if (should_enable) { ++ g_signal_emit (G_OBJECT (task), signals [ENABLED], 0); ++ } else { ++ g_signal_emit (G_OBJECT (task), signals [DISABLED], 0); + } -+ -+ object = gtk_builder_get_object (builder, "page"); -+ g_object_ref (object); -+ -+ extension->priv->page = GTK_WIDGET (object); -+ -+ object = gtk_builder_get_object (builder, "auth-prompt-label"); -+ g_object_ref (object); -+ extension->priv->prompt_label = GTK_WIDGET (object); -+ gtk_widget_hide (extension->priv->prompt_label); -+ -+ object = gtk_builder_get_object (builder, "auth-prompt-entry"); -+ g_object_ref (object); -+ extension->priv->prompt_entry = GTK_WIDGET (object); -+ gtk_widget_hide (extension->priv->prompt_entry); -+ -+ object = gtk_builder_get_object (builder, "auth-message-label"); -+ g_object_ref (object); -+ extension->priv->message_label = GTK_WIDGET (object); -+ gtk_widget_show (extension->priv->message_label); -+ -+ g_object_unref (builder); +} + -+static void -+create_actions (GdmFingerprintExtension *extension) ++gboolean ++gdm_task_is_enabled (GdmTask *task) +{ -+ GtkAction *action; ++ return !g_object_get_data (G_OBJECT (task), "gdm-task-is-disabled"); ++} + -+ extension->priv->actions = gtk_action_group_new ("gdm-fingerprint-extension"); ++gboolean ++gdm_task_is_choosable (GdmTask *task) ++{ ++ return GDM_TASK_GET_IFACE (task)->is_choosable (task); +} + +static void -+gdm_fingerprint_extension_init (GdmFingerprintExtension *extension) ++gdm_task_class_init (gpointer g_iface) +{ -+ extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension, -+ GDM_TYPE_FINGERPRINT_EXTENSION, -+ GdmFingerprintExtensionPrivate); ++ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); + -+ extension->priv->icon = g_themed_icon_new ("stock_allow-effects"); -+ create_page (extension); -+ create_actions (extension); -+ gdm_fingerprint_extension_reset (GDM_CONVERSATION (extension)); ++ signals [ENABLED] = ++ g_signal_new ("enabled", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmTaskIface, enabled), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, ++ 0); ++ ++ signals [DISABLED] = ++ g_signal_new ("disabled", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmTaskIface, disabled), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, ++ 0); +} -diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.h b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.h -new file mode 100644 -index 0000000..5d34b21 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.h -@@ -0,0 +1,56 @@ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h 2009-03-03 17:45:05.773013916 -0500 +@@ -0,0 +1,64 @@ +/* -+ * Copyright (C) 2009 Red Hat, Inc. ++ * Copyright (C) Red Hat, Inc. + * + * 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, or (at your option) -+ * any later version. ++ * the Free Software Foundation; either version 2 of the License, 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 @@ -12129,115 +9391,189 @@ index 0000000..5d34b21 + * + * 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. + * -+ * Written By: Ray Strode ++ * Written by: Ray Strode + */ + -+#ifndef __GDM_FINGERPRINT_EXTENSION_H -+#define __GDM_FINGERPRINT_EXTENSION_H ++ ++#ifndef __GDM_TASK_H ++#define __GDM_TASK_H + +#include -+#include "gdm-greeter-extension.h" ++#include + +G_BEGIN_DECLS + -+#define GDM_TYPE_FINGERPRINT_EXTENSION (gdm_fingerprint_extension_get_type ()) -+#define GDM_FINGERPRINT_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_FINGERPRINT_EXTENSION, GdmFingerprintExtension)) -+#define GDM_FINGERPRINT_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_FINGERPRINT_EXTENSION, GdmFingerprintExtensionClass)) -+#define GDM_IS_FINGERPRINT_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_FINGERPRINT_EXTENSION)) -+#define GDM_IS_FINGERPRINT_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_FINGERPRINT_EXTENSION)) -+#define GDM_FINGERPRINT_EXTENSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_FINGERPRINT_EXTENSION, GdmFingerprintExtensionClass)) -+ -+typedef struct _GdmFingerprintExtensionPrivate GdmFingerprintExtensionPrivate; ++#define GDM_TYPE_TASK (gdm_task_get_type ()) ++#define GDM_TASK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_TASK, GdmTask)) ++#define GDM_TASK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_TASK, GdmTaskIface)) ++#define GDM_IS_TASK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_TASK)) ++#define GDM_TASK_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDM_TYPE_TASK, GdmTaskIface)) + -+typedef struct -+{ -+ GObject parent; -+ GdmFingerprintExtensionPrivate *priv; -+} GdmFingerprintExtension; ++typedef struct _GdmTask GdmTask; ++typedef struct _GdmTaskIface GdmTaskIface; + -+typedef struct ++struct _GdmTaskIface +{ -+ GObjectClass parent_class; -+} GdmFingerprintExtensionClass; ++ GTypeInterface base_iface; + -+GType gdm_fingerprint_extension_get_type (void); ++ /* methods */ ++ GIcon * (* get_icon) (GdmTask *task); ++ char * (* get_description) (GdmTask *task); ++ char * (* get_name) (GdmTask *task); ++ gboolean (* is_choosable) (GdmTask *task); ++ /* signals */ ++ void (* enabled) (GdmTask *task); ++ void (* disabled) (GdmTask *task); ++}; + -+GdmFingerprintExtension *gdm_fingerprint_extension_new (void); ++GType gdm_task_get_type (void) G_GNUC_CONST; + ++GIcon *gdm_task_get_icon (GdmTask *task); ++char *gdm_task_get_description (GdmTask *task); ++char *gdm_task_get_name (GdmTask *task); ++void gdm_task_set_enabled (GdmTask *task, ++ gboolean should_enable); ++gboolean gdm_task_is_enabled (GdmTask *task); ++gboolean gdm_task_is_choosable (GdmTask *task); +G_END_DECLS + -+#endif /* GDM_FINGERPRINT_EXTENSION_H */ -diff --git a/gui/simple-greeter/plugins/fingerprint/page.ui b/gui/simple-greeter/plugins/fingerprint/page.ui -new file mode 100644 -index 0000000..fe6da78 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/page.ui -@@ -0,0 +1,56 @@ -+ -+ -+ -+ -+ True -+ vertical -+ -+ -+ True -+ -+ -+ True -+ -+ -+ False -+ False -+ 0 -+ -+ -+ -+ -+ True -+ True -+ True -+ -+ -+ 1 -+ -+ -+ -+ -+ True -+ True -+ 0 -+ -+ -+ -+ -+ True -+ -+ -+ True -+ -+ -+ 0 -+ -+ -+ -+ -+ True -+ True -+ 1 -+ -+ -+ -+ -diff --git a/gui/simple-greeter/plugins/fingerprint/plugin.c b/gui/simple-greeter/plugins/fingerprint/plugin.c -new file mode 100644 -index 0000000..5ea9925 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/plugin.c -@@ -0,0 +1,40 @@ ++#endif /* __GDM_TASK_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/Makefile.am +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/libgdmsimplegreeter/Makefile.am 2009-03-03 17:45:05.817016611 -0500 +@@ -0,0 +1,48 @@ ++NULL = ++ ++AM_CPPFLAGS = \ ++ -I. \ ++ -I.. \ ++ -I$(top_srcdir)/common \ ++ -DBINDIR=\"$(bindir)\" \ ++ -DDATADIR=\"$(datadir)\" \ ++ -DLIBDIR=\"$(libdir)\" \ ++ -DLIBEXECDIR=\"$(libexecdir)\" \ ++ -DLOGDIR=\"$(logdir)\" \ ++ -DPIXMAPDIR=\"$(pixmapdir)\" \ ++ -DSBINDIR=\"$(sbindir)\" \ ++ $(GTK_CFLAGS) \ ++ $(NULL) ++ ++lib_LTLIBRARIES = \ ++ libgdmsimplegreeter.la \ ++ $(NULL) ++ ++libgdmsimplegreeter_la_SOURCES = \ ++ gdm-task.h \ ++ gdm-task.c \ ++ gdm-conversation.h \ ++ gdm-conversation.c \ ++ gdm-greeter-extension.h \ ++ gdm-greeter-extension.c \ ++ $(NULL) ++ ++libgdmsimplegreeter_la_LIBADD = \ ++ $(GTK_LIBS) \ ++ $(top_builddir)/common/libgdmcommon.la \ ++ $(NULL) ++ ++libgdmsimplegreeter_la_LDFLAGS = \ ++ -export-symbols-regex '^[^_].*' \ ++ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ ++ -no-undefined \ ++ $(NULL) ++ ++headersdir = $(includedir)/gdm/simple-greeter ++headers_HEADERS = gdm-greeter-extension.h ++ ++pkgconfigdir = $(libdir)/pkgconfig ++pkgconfig_DATA = gdmsimplegreeter.pc ++ ++EXTRA_DIST = gdmsimplegreeter.pc ++MAINTAINERCLEANFILES = Makefile.in +diff -up gdm-2.25.2/gui/simple-greeter/Makefile.am.multistack-but-boring gdm-2.25.2/gui/simple-greeter/Makefile.am +--- gdm-2.25.2/gui/simple-greeter/Makefile.am.multistack-but-boring 2008-12-03 00:22:20.000000000 -0500 ++++ gdm-2.25.2/gui/simple-greeter/Makefile.am 2009-03-03 17:45:05.656016685 -0500 +@@ -2,11 +2,14 @@ NULL = + + SUBDIRS = \ + libnotificationarea \ ++ libgdmsimplegreeter \ ++ plugins \ + $(NULL) + + AM_CPPFLAGS = \ + -I$(top_srcdir)/common \ + -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ ++ -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ + -DDMCONFDIR=\""$(dmconfdir)"\" \ + -DGDMCONFDIR=\"$(gdmconfdir)\" \ + -DDATADIR=\""$(datadir)"\" \ +@@ -17,6 +20,7 @@ AM_CPPFLAGS = \ + -DLIBEXECDIR=\""$(libexecdir)"\" \ + -DSBINDIR=\""$(sbindir)"\" \ + -DAT_SPI_REGISTRYD_DIR="\"$(AT_SPI_REGISTRYD_DIR)\"" \ ++ -DGDM_SIMPLE_GREETER_PLUGINS_DIR="\"$(GDM_SIMPLE_GREETER_PLUGINS_DIR)\""\ + $(DISABLE_DEPRECATED_CFLAGS) \ + $(GTK_CFLAGS) \ + $(SIMPLE_GREETER_CFLAGS) \ +@@ -83,10 +87,17 @@ test_greeter_login_window_SOURCES = \ + gdm-user-chooser-widget.c \ + gdm-user-chooser-dialog.h \ + gdm-user-chooser-dialog.c \ ++ gdm-task-list.h \ ++ gdm-task-list.c \ ++ gdm-plugin-manager.h \ ++ gdm-plugin-manager.c \ ++ gdm-greeter-plugin.h \ ++ gdm-greeter-plugin.c \ + $(NULL) + + test_greeter_login_window_LDADD = \ + $(top_builddir)/common/libgdmcommon.la \ ++ $(top_builddir)/gui/simple-greeter/libgdmsimplegreeter/libgdmsimplegreeter.la \ + libgdmuser.la \ + $(COMMON_LIBS) \ + $(SIMPLE_GREETER_LIBS) \ +@@ -138,6 +149,7 @@ test_greeter_panel_SOURCES = \ + test_greeter_panel_LDADD = \ + $(top_builddir)/common/libgdmcommon.la \ + $(top_builddir)/gui/simple-greeter/libnotificationarea/libnotificationarea.la \ ++ $(top_builddir)/gui/simple-greeter/libgdmsimplegreeter/libgdmsimplegreeter.la \ + $(SIMPLE_GREETER_LIBS) \ + $(GTK_LIBS) \ + $(GCONF_LIBS) \ +@@ -310,18 +322,25 @@ gdm_simple_greeter_SOURCES = \ + gdm-language-chooser-dialog.c \ + gdm-language-option-widget.h \ + gdm-language-option-widget.c \ ++ gdm-plugin-manager.h \ ++ gdm-plugin-manager.c \ + gdm-sessions.h \ + gdm-sessions.c \ + gdm-session-option-widget.h \ + gdm-session-option-widget.c \ ++ gdm-greeter-plugin.h \ ++ gdm-greeter-plugin.c \ + gdm-user-chooser-widget.h \ + gdm-user-chooser-widget.c \ ++ gdm-task-list.h \ ++ gdm-task-list.c \ + $(NULL) + + gdm_simple_greeter_LDADD = \ + $(top_builddir)/common/libgdmcommon.la \ + libgdmuser.la \ + $(top_builddir)/gui/simple-greeter/libnotificationarea/libnotificationarea.la \ ++ $(top_builddir)/gui/simple-greeter/libgdmsimplegreeter/libgdmsimplegreeter.la \ + $(COMMON_LIBS) \ + $(EXTRA_GREETER_LIBS) \ + $(SIMPLE_GREETER_LIBS) \ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c 2009-03-03 17:45:05.781018672 -0500 +@@ -0,0 +1,304 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -12259,848 +9595,382 @@ index 0000000..5ea9925 + * + */ + ++#include +#include "gdm-fingerprint-extension.h" ++#include "gdm-conversation.h" ++#include "gdm-task.h" + ++#include +#include +#include + -+GdmGreeterExtension * -+gdm_greeter_plugin_get_extension (void) ++struct _GdmFingerprintExtensionPrivate +{ -+ static GObject *extension; ++ GIcon *icon; ++ GtkWidget *page; ++ GtkActionGroup *actions; + -+ if (extension != NULL) { -+ g_object_ref (extension); -+ } else { -+ extension = g_object_new (GDM_TYPE_FINGERPRINT_EXTENSION, NULL); -+ g_object_add_weak_pointer (extension, (gpointer *) &extension); -+ } ++ GtkWidget *message_label; ++ GtkWidget *prompt_label; ++ GtkWidget *prompt_entry; + -+ return GDM_GREETER_EXTENSION (extension); -+} --- -1.6.1 - - -From 86391cb7067920b99d92a27e0de600b26b1ec027 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 17:12:04 -0500 -Subject: [PATCH 26/65] fix debug message - ---- - daemon/gdm-simple-slave.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index a6ae0ae..1245bc9 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -509,7 +509,7 @@ on_session_conversation_started (GdmSession *session, - char *username; - int delay; - -- g_debug ("GdmSimpleSlave: session opened"); -+ g_debug ("GdmSimpleSlave: conversation started"); - if (slave->priv->greeter_server != NULL) { - res = gdm_greeter_server_ready (slave->priv->greeter_server, - service_name); --- -1.6.1 - - -From 6df2f0bc6b32b26eaa533976b1271d8933b1410a Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 17:44:37 -0500 -Subject: [PATCH 27/65] Drop duplicated entry introspection output - ---- - daemon/gdm-greeter-server.c | 1 - - 1 files changed, 0 insertions(+), 1 deletions(-) - -diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c -index 0ac0a09..dae34c5 100644 ---- a/daemon/gdm-greeter-server.c -+++ b/daemon/gdm-greeter-server.c -@@ -859,7 +859,6 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -- " \n" - " \n" - " \n" - " \n" --- -1.6.1 - - -From 1258c6b7826b125d1825cfb48ef0378744da77a4 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sat, 7 Feb 2009 11:36:40 -0500 -Subject: [PATCH 28/65] emit "ConversationStopped" signal at end of conv - -This will allow us to track when individual -PAM conversations fail, instead of doing one -giant reset. The reason this is useful is that -some PAM modules fail immediately for some users -(for instance the fingerprint PAM module fails if - a user hasn't enrolled their print). ---- - daemon/gdm-greeter-server.c | 13 +++++++++++++ - daemon/gdm-greeter-server.h | 2 ++ - daemon/gdm-session-direct.c | 36 ++++++++++++++++++++++++++++++++++++ - daemon/gdm-session-private.h | 2 ++ - daemon/gdm-session.c | 28 ++++++++++++++++++++++++++++ - daemon/gdm-session.h | 6 ++++++ - daemon/gdm-simple-slave.c | 34 ++++++++++++++++++++++++++-------- - 7 files changed, 113 insertions(+), 8 deletions(-) - -diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c -index dae34c5..5bf1f8a 100644 ---- a/daemon/gdm-greeter-server.c -+++ b/daemon/gdm-greeter-server.c -@@ -299,6 +299,13 @@ gdm_greeter_server_ready (GdmGreeterServer *greeter_server, - return TRUE; - } - -+gboolean -+gdm_greeter_server_conversation_stopped (GdmGreeterServer *greeter_server, -+ const char *service_name) -+{ -+ send_dbus_string_signal (greeter_server, "ConversationStopped", service_name); -+} ++ guint answer_pending : 1; ++}; + - void - gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server, - const char *username) -@@ -797,6 +804,9 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -+ " \n" -+ " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -868,6 +878,9 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -+ " \n" -+ " \n" -+ " \n" - " \n" - " \n" - " \n" -diff --git a/daemon/gdm-greeter-server.h b/daemon/gdm-greeter-server.h -index 6d0dd87..976f0b7 100644 ---- a/daemon/gdm-greeter-server.h -+++ b/daemon/gdm-greeter-server.h -@@ -96,6 +96,8 @@ gboolean gdm_greeter_server_problem (GdmGreeterServer * - gboolean gdm_greeter_server_reset (GdmGreeterServer *greeter_server); - gboolean gdm_greeter_server_ready (GdmGreeterServer *greeter_server, - const char *service_name); -+gboolean gdm_greeter_server_conversation_stopped (GdmGreeterServer *greeter_server, -+ const char *service_name); - void gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server, - const char *text); - void gdm_greeter_server_default_language_name_changed (GdmGreeterServer *greeter_server, -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 099f884..2fc39f3 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1712,6 +1712,7 @@ worker_exited (GdmSessionWorkerJob *job, - { - g_debug ("GdmSessionDirect: Worker job exited: %d", code); - -+ g_object_ref (conversation); - if (!conversation->session->priv->is_authenticated) { - char *msg; - -@@ -1721,6 +1722,11 @@ worker_exited (GdmSessionWorkerJob *job, - } else if (conversation->session->priv->is_running) { - _gdm_session_session_exited (GDM_SESSION (conversation->session), code); - } ++static void gdm_fingerprint_extension_finalize (GObject *object); + -+ g_debug ("GdmSessionDirect: Emitting conversation-stopped signal"); -+ _gdm_session_conversation_stopped (GDM_SESSION (conversation->session), -+ conversation->service_name); -+ g_object_unref (conversation); - } - - static void -@@ -1730,6 +1736,7 @@ worker_died (GdmSessionWorkerJob *job, - { - g_debug ("GdmSessionDirect: Worker job died: %d", signum); - -+ g_object_ref (conversation); - if (!conversation->session->priv->is_authenticated) { - char *msg; - -@@ -1739,6 +1746,11 @@ worker_died (GdmSessionWorkerJob *job, - } else if (conversation->session->priv->is_running) { - _gdm_session_session_died (GDM_SESSION (conversation->session), signum); - } ++static void gdm_task_iface_init (GdmTaskIface *iface); ++static void gdm_conversation_iface_init (GdmConversationIface *iface); ++static void gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface); + -+ g_debug ("GdmSessionDirect: Emitting conversation-stopped signal"); -+ _gdm_session_conversation_stopped (GDM_SESSION (conversation->session), -+ conversation->service_name); -+ g_object_unref (conversation); - } - - static GdmSessionConversation * -@@ -1811,6 +1823,10 @@ stop_conversation (GdmSessionConversation *conversation) - - g_object_unref (conversation->job); - conversation->job = NULL; ++G_DEFINE_TYPE_WITH_CODE (GdmFingerprintExtension, ++ gdm_fingerprint_extension, ++ G_TYPE_OBJECT, ++ G_IMPLEMENT_INTERFACE (GDM_TYPE_GREETER_EXTENSION, ++ gdm_greeter_extension_iface_init) ++ G_IMPLEMENT_INTERFACE (GDM_TYPE_TASK, ++ gdm_task_iface_init) ++ G_IMPLEMENT_INTERFACE (GDM_TYPE_CONVERSATION, ++ gdm_conversation_iface_init)); + -+ g_debug ("GdmSessionDirect: Emitting conversation-stopped signal"); -+ _gdm_session_conversation_stopped (GDM_SESSION (session), -+ conversation->service_name); - } - - static void -@@ -1831,6 +1847,25 @@ gdm_session_direct_start_conversation (GdmSession *session, - } - - static void -+gdm_session_direct_stop_conversation (GdmSession *session, -+ const char *service_name) ++static void ++gdm_fingerprint_extension_set_message (GdmConversation *conversation, ++ const char *message) ++{ ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ gtk_widget_show (extension->priv->message_label); ++ gtk_label_set_text (GTK_LABEL (extension->priv->message_label), message); ++} ++ ++static void ++gdm_fingerprint_extension_ask_question (GdmConversation *conversation, ++ const char *message) ++{ ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ gtk_widget_show (extension->priv->prompt_label); ++ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); ++ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); ++ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); ++ gtk_widget_show (extension->priv->prompt_entry); ++ gtk_widget_grab_focus (extension->priv->prompt_entry); ++ extension->priv->answer_pending = TRUE; ++} ++ ++static void ++gdm_fingerprint_extension_ask_secret (GdmConversation *conversation, ++ const char *message) +{ -+ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; -+ -+ g_return_if_fail (session != NULL); ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ gtk_widget_show (extension->priv->prompt_label); ++ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); ++ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), FALSE); ++ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); ++ gtk_widget_show (extension->priv->prompt_entry); ++ gtk_widget_grab_focus (extension->priv->prompt_entry); ++ extension->priv->answer_pending = TRUE; ++} + -+ g_debug ("GdmSessionDirect: stopping conversation"); ++static void ++gdm_fingerprint_extension_reset (GdmConversation *conversation) ++{ ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ gtk_widget_hide (extension->priv->prompt_label); ++ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); + -+ conversation = find_conversation_by_name (impl, service_name); ++ gtk_widget_hide (extension->priv->prompt_entry); ++ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); ++ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); ++ extension->priv->answer_pending = FALSE; + -+ if (conversation != NULL) { -+ stop_conversation (conversation); -+ g_hash_table_remove (impl->priv->conversations, service_name); -+ } ++ gdm_task_set_enabled (GDM_TASK (conversation), FALSE); +} + +static void - send_setup (GdmSessionDirect *session, - const char *service_name) - { -@@ -2644,6 +2679,7 @@ static void - gdm_session_iface_init (GdmSessionIface *iface) - { - iface->start_conversation = gdm_session_direct_start_conversation; -+ iface->stop_conversation = gdm_session_direct_stop_conversation; - iface->setup = gdm_session_direct_setup; - iface->setup_for_user = gdm_session_direct_setup_for_user; - iface->authenticate = gdm_session_direct_authenticate; -diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h -index de6e54a..860c09c 100644 ---- a/daemon/gdm-session-private.h -+++ b/daemon/gdm-session-private.h -@@ -29,6 +29,8 @@ G_BEGIN_DECLS - /* state changes */ - void _gdm_session_conversation_started (GdmSession *session, - const char *service_name); -+void _gdm_session_conversation_stopped (GdmSession *session, -+ const char *service_name); - void _gdm_session_setup_complete (GdmSession *session, - const char *service_name); - void _gdm_session_setup_failed (GdmSession *session, -diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c -index 5f6ff5d..9ee34af 100644 ---- a/daemon/gdm-session.c -+++ b/daemon/gdm-session.c -@@ -30,6 +30,7 @@ - - enum { - CONVERSATION_STARTED = 0, -+ CONVERSATION_STOPPED, - SETUP_COMPLETE, - SETUP_FAILED, - RESET_COMPLETE, -@@ -88,6 +89,15 @@ gdm_session_start_conversation (GdmSession *session, - } - - void -+gdm_session_stop_conversation (GdmSession *session, -+ const char *service_name) ++gdm_fingerprint_extension_set_ready (GdmConversation *conversation) +{ -+ g_return_if_fail (GDM_IS_SESSION (session)); ++ gdm_task_set_enabled (GDM_TASK (conversation), TRUE); ++} + -+ GDM_SESSION_GET_IFACE (session)->stop_conversation (session, service_name); ++char * ++gdm_fingerprint_extension_get_service_name (GdmConversation *conversation) ++{ ++ return g_strdup (PAMSERVICENAME); +} + -+void - gdm_session_close (GdmSession *session) - { - g_return_if_fail (GDM_IS_SESSION (session)); -@@ -220,6 +230,16 @@ gdm_session_class_init (gpointer g_iface) - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, - 1, G_TYPE_STRING); -+ signals [CONVERSATION_STOPPED] = -+ g_signal_new ("conversation-stopped", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmSessionIface, conversation_stopped), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); - signals [SETUP_COMPLETE] = - g_signal_new ("setup-complete", - iface_type, -@@ -638,6 +658,14 @@ _gdm_session_conversation_started (GdmSession *session, - } - - void -+_gdm_session_conversation_stopped (GdmSession *session, -+ const char *service_name) ++GtkWidget * ++gdm_fingerprint_extension_get_page (GdmConversation *conversation) +{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ g_signal_emit (session, signals [CONVERSATION_STOPPED], 0, service_name); ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ return extension->priv->page; ++} ++ ++GtkActionGroup * ++gdm_fingerprint_extension_get_actions (GdmConversation *conversation) ++{ ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ ++ return g_object_ref (extension->priv->actions); +} + +void - _gdm_session_closed (GdmSession *session) - { - g_return_if_fail (GDM_IS_SESSION (session)); -diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h -index db5fc4a..c45a770 100644 ---- a/daemon/gdm-session.h -+++ b/daemon/gdm-session.h -@@ -47,6 +47,8 @@ struct _GdmSessionIface - /* Methods */ - void (* start_conversation) (GdmSession *session, - const char *service_name); -+ void (* stop_conversation) (GdmSession *session, -+ const char *service_name); - void (* setup) (GdmSession *session, - const char *service_name); - void (* setup_for_user) (GdmSession *session, -@@ -125,6 +127,8 @@ struct _GdmSessionIface - int signal_number); - void (* conversation_started) (GdmSession *session, - const char *service_name); -+ void (* conversation_stopped) (GdmSession *session, -+ const char *service_name); - void (* closed) (GdmSession *session); - void (* selected_user_changed) (GdmSession *session, - const char *text); -@@ -141,6 +145,8 @@ 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, -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index 1245bc9..fba26ab 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -222,8 +222,7 @@ on_session_setup_failed (GdmSession *session, - _("Unable to initialize login system")); - } - -- destroy_session (slave); -- queue_greeter_reset (slave); -+ gdm_session_stop_conversation (session, service_name); - } - - static void -@@ -260,8 +259,8 @@ on_session_authentication_failed (GdmSession *session, - service_name, - _("Unable to authenticate user")); - } -- destroy_session (slave); -- queue_greeter_reset (slave); ++gdm_fingerprint_extension_request_answer (GdmConversation *conversation) ++{ ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ const char *text; + -+ gdm_session_stop_conversation (session, service_name); - } - - static void -@@ -319,8 +318,7 @@ on_session_authorization_failed (GdmSession *session, - _("Unable to authorize user")); - } - -- destroy_session (slave); -- queue_greeter_reset (slave); -+ gdm_session_stop_conversation (session, service_name); - } - - static gboolean -@@ -451,9 +449,8 @@ on_session_accreditation_failed (GdmSession *session, - when Xorg exits it switches to the VT it was - started from. That interferes with fast - user switching. */ -- destroy_session (slave); - -- queue_greeter_reset (slave); -+ gdm_session_stop_conversation (session, service_name); - } - - static void -@@ -539,6 +536,23 @@ on_session_conversation_started (GdmSession *session, - } - - static void -+on_session_conversation_stopped (GdmSession *session, -+ const char *service_name, -+ GdmSimpleSlave *slave) ++ if (!extension->priv->answer_pending) { ++ gdm_conversation_answer (conversation, NULL); ++ return; ++ } ++ ++ extension->priv->answer_pending = FALSE; ++ text = gtk_entry_get_text (GTK_ENTRY (extension->priv->prompt_entry)); ++ gdm_conversation_answer (conversation, text); ++ ++ gtk_widget_hide (extension->priv->prompt_entry); ++ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); ++ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); ++} ++ ++gboolean ++gdm_fingerprint_extension_focus (GdmConversation *conversation) +{ -+ gboolean res; -+ g_debug ("GdmSimpleSlave: conversation stopped"); ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); + -+ if (slave->priv->greeter_server != NULL) { -+ res = gdm_greeter_server_conversation_stopped (slave->priv->greeter_server, -+ service_name); -+ if (! res) { -+ g_warning ("Unable to send conversation stopped"); -+ } ++ if (!extension->priv->answer_pending) { ++ return FALSE; + } ++ ++ gtk_widget_grab_focus (extension->priv->prompt_entry); ++ return TRUE; +} + -+static void - on_session_selected_user_changed (GdmSession *session, - const char *text, - GdmSimpleSlave *slave) -@@ -627,6 +641,10 @@ create_new_session (GdmSimpleSlave *slave) - G_CALLBACK (on_session_conversation_started), - slave); - g_signal_connect (slave->priv->session, -+ "conversation-stopped", -+ G_CALLBACK (on_session_conversation_stopped), -+ slave); -+ g_signal_connect (slave->priv->session, - "setup-complete", - G_CALLBACK (on_session_setup_complete), - slave); --- -1.6.1 - - -From eb7b50c09cea1c5730c6d1c03a721538c979addc Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sat, 7 Feb 2009 13:54:24 -0500 -Subject: [PATCH 29/65] Cancel login conversations if any fails - -This gives us the same behavior we had before -the ConversationStopped signal was added. - -We'll improve upon this to only disable the -conversations that fail as they fail in -subsequent commits. ---- - gui/simple-greeter/gdm-greeter-client.c | 21 +++++++++++++++++++++ - gui/simple-greeter/gdm-greeter-client.h | 2 ++ - gui/simple-greeter/gdm-greeter-login-window.c | 11 +++++++++++ - gui/simple-greeter/gdm-greeter-login-window.h | 2 ++ - gui/simple-greeter/gdm-greeter-session.c | 15 +++++++++++++++ - 5 files changed, 51 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c -index 0bd27a9..a9321aa 100644 ---- a/gui/simple-greeter/gdm-greeter-client.c -+++ b/gui/simple-greeter/gdm-greeter-client.c -@@ -64,6 +64,7 @@ enum { - INFO_QUERY, - SECRET_INFO_QUERY, - READY, -+ CONVERSATION_STOPPED, - RESET, - SELECTED_USER_CHANGED, - DEFAULT_LANGUAGE_NAME_CHANGED, -@@ -270,6 +271,13 @@ on_ready (GdmGreeterClient *client, - } - - static void -+on_conversation_stopped (GdmGreeterClient *client, -+ DBusMessage *message) ++GIcon * ++gdm_fingerprint_extension_get_icon (GdmTask *task) +{ -+ emit_string_signal_for_message (client, "ConversationStopped", message, CONVERSATION_STOPPED); ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (task); ++ return g_object_ref (extension->priv->icon); +} + -+static void - on_reset (GdmGreeterClient *client, - DBusMessage *message) - { -@@ -760,6 +768,8 @@ client_dbus_handle_message (DBusConnection *connection, - on_problem (client, message); - } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Ready")) { - on_ready (client, message); -+ } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "ConversationStopped")) { -+ on_conversation_stopped (client, message); - } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Reset")) { - on_reset (client, message); - } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "SelectedUserChanged")) { -@@ -1000,6 +1010,17 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) - G_TYPE_NONE, - 1, G_TYPE_STRING); - -+ gdm_greeter_client_signals[CONVERSATION_STOPPED] = -+ g_signal_new ("conversation-stopped", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmGreeterClientClass, conversation_stopped), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); ++char * ++gdm_fingerprint_extension_get_name (GdmTask *task) ++{ ++ return g_strdup (_("Fingerprint Authentication")); ++} ++ ++char * ++gdm_fingerprint_extension_get_description (GdmTask *task) ++{ ++ return g_strdup (_("Log into session with fingerprint")); ++} + - gdm_greeter_client_signals[RESET] = - g_signal_new ("reset", - G_OBJECT_CLASS_TYPE (object_class), -diff --git a/gui/simple-greeter/gdm-greeter-client.h b/gui/simple-greeter/gdm-greeter-client.h -index 2f857dc..f879307 100644 ---- a/gui/simple-greeter/gdm-greeter-client.h -+++ b/gui/simple-greeter/gdm-greeter-client.h -@@ -61,6 +61,8 @@ typedef struct - const char *problem); - void (* ready) (GdmGreeterClient *client, - const char *service_name); -+ void (* conversation_stopped) (GdmGreeterClient *client, -+ const char *service_name); - void (* reset) (GdmGreeterClient *client); - void (* selected_user_changed) (GdmGreeterClient *client, - const char *username); -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index ea96abc..4766a78 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -848,6 +848,17 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - return TRUE; - } - +gboolean -+gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_window, -+ const char *service_name) ++gdm_fingerprint_extension_is_choosable (GdmTask *task) +{ -+ GdmTask *task; ++ return FALSE; ++} + -+ g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); -+ do_cancel (login_window); -+ return TRUE; ++static void ++gdm_task_iface_init (GdmTaskIface *iface) ++{ ++ iface->get_icon = gdm_fingerprint_extension_get_icon; ++ iface->get_description = gdm_fingerprint_extension_get_description; ++ iface->get_name = gdm_fingerprint_extension_get_name; ++ iface->is_choosable = gdm_fingerprint_extension_is_choosable; +} + - static gboolean - restart_task_conversation (GdmTaskList *task_list, - GdmTask *task, -diff --git a/gui/simple-greeter/gdm-greeter-login-window.h b/gui/simple-greeter/gdm-greeter-login-window.h -index eda7f89..c312a47 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.h -+++ b/gui/simple-greeter/gdm-greeter-login-window.h -@@ -79,6 +79,8 @@ GtkWidget * gdm_greeter_login_window_new (gboolean displa - gboolean gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window); - gboolean gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - const char *service_name); -+gboolean gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_window, -+ const char *service_name); - gboolean gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, - const char *service_name, - const char *text); -diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c -index d8fd861..7ce4adb 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -100,6 +100,17 @@ on_ready (GdmGreeterClient *client, - } - - static void -+on_conversation_stopped (GdmGreeterClient *client, -+ const char *service_name, -+ GdmGreeterSession *session) ++static void ++gdm_conversation_iface_init (GdmConversationIface *iface) +{ -+ g_debug ("GdmGreeterSession: Conversation '%s' stopped", service_name); ++ iface->set_message = gdm_fingerprint_extension_set_message; ++ iface->ask_question = gdm_fingerprint_extension_ask_question; ++ iface->ask_secret = gdm_fingerprint_extension_ask_secret; ++ iface->reset = gdm_fingerprint_extension_reset; ++ iface->set_ready = gdm_fingerprint_extension_set_ready; ++ iface->get_service_name = gdm_fingerprint_extension_get_service_name; ++ iface->get_page = gdm_fingerprint_extension_get_page; ++ iface->get_actions = gdm_fingerprint_extension_get_actions; ++ iface->request_answer = gdm_fingerprint_extension_request_answer; ++ iface->focus = gdm_fingerprint_extension_focus; ++} + -+ gdm_greeter_login_window_conversation_stopped (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), -+ service_name); ++static void ++gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) ++{ +} + +static void - on_reset (GdmGreeterClient *client, - GdmGreeterSession *session) - { -@@ -601,6 +612,10 @@ gdm_greeter_session_init (GdmGreeterSession *session) - G_CALLBACK (on_ready), - session); - g_signal_connect (session->priv->client, -+ "conversation-stopped", -+ G_CALLBACK (on_conversation_stopped), -+ session); -+ g_signal_connect (session->priv->client, - "reset", - G_CALLBACK (on_reset), - session); --- -1.6.1 - - -From bcf134e25c4c339aace68b04e48dca26c9567cb9 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sat, 7 Feb 2009 13:57:41 -0500 -Subject: [PATCH 30/65] If a conversation fails in the slave disable task - -If a conversation fails (say because the user -hasn't enrolled their fingerprint) then just disable -that task and keep the other plugins available. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 12 +++++++++++- - 1 files changed, 11 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 4766a78..d5f0253 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -855,7 +855,17 @@ gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_wind - GdmTask *task; - - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); -- do_cancel (login_window); ++gdm_fingerprint_extension_class_init (GdmFingerprintExtensionClass *extension_class) ++{ ++ GObjectClass *object_class; + -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) service_name); ++ object_class = G_OBJECT_CLASS (extension_class); + -+ if (task != NULL) { -+ gdm_conversation_reset (GDM_CONVERSATION (task)); -+ g_object_unref (task); -+ } ++ object_class->finalize = gdm_fingerprint_extension_finalize; + - return TRUE; - } - --- -1.6.1 - - -From 7dc4f58b55cef33de6d3a3f7d3efae4ca313ca5f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sat, 7 Feb 2009 14:11:19 -0500 -Subject: [PATCH 31/65] If a task gets disabled, jump to first task - -This way we don't show the user a page they -can't access. ---- - gui/simple-greeter/gdm-task-list.c | 31 +++++++++++++++++++++++++++++++ - 1 files changed, 31 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c -index 71e103e..445b6cc 100644 ---- a/gui/simple-greeter/gdm-task-list.c -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -105,14 +105,45 @@ on_task_enabled (GdmTaskList *task_list, - } - - static void -+activate_first_available_task (GdmTaskList *task_list) ++ g_type_class_add_private (extension_class, ++ sizeof (GdmFingerprintExtensionPrivate)); ++} ++ ++static void ++gdm_fingerprint_extension_finalize (GObject *object) +{ -+ GList *node; ++} + -+ node = task_list->priv->tasks; -+ while (node != NULL) { -+ GdmTask *task; -+ GtkWidget *button; ++static void ++create_page (GdmFingerprintExtension *extension) ++{ ++ GtkBuilder *builder; ++ GObject *object; ++ GError *error; + -+ task = GDM_TASK (node->data); ++ builder = gtk_builder_new (); + -+ button = GTK_WIDGET (g_object_get_data (G_OBJECT (task), -+ "gdm-task-list-button")); ++ error = NULL; ++ gtk_builder_add_from_file (builder, ++ PLUGINDATADIR "/page.ui", ++ &error); + -+ if (GTK_WIDGET_IS_SENSITIVE (button)) { -+ if (gtk_widget_activate (button)) { -+ break; -+ } -+ } -+ node = node->next; ++ if (error != NULL) { ++ g_warning ("Could not load UI file: %s", error->message); ++ g_error_free (error); ++ return; + } + ++ object = gtk_builder_get_object (builder, "page"); ++ g_object_ref (object); ++ ++ extension->priv->page = GTK_WIDGET (object); ++ ++ object = gtk_builder_get_object (builder, "auth-prompt-label"); ++ g_object_ref (object); ++ extension->priv->prompt_label = GTK_WIDGET (object); ++ gtk_widget_hide (extension->priv->prompt_label); ++ ++ object = gtk_builder_get_object (builder, "auth-prompt-entry"); ++ g_object_ref (object); ++ extension->priv->prompt_entry = GTK_WIDGET (object); ++ gtk_widget_hide (extension->priv->prompt_entry); ++ ++ object = gtk_builder_get_object (builder, "auth-message-label"); ++ g_object_ref (object); ++ extension->priv->message_label = GTK_WIDGET (object); ++ gtk_widget_show (extension->priv->message_label); ++ ++ g_object_unref (builder); +} + +static void - on_task_disabled (GdmTaskList *task_list, - GdmTask *task) - { - GtkWidget *button; -+ gboolean was_active; - - button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); -+ was_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); - - gtk_widget_set_sensitive (button, FALSE); ++create_actions (GdmFingerprintExtension *extension) ++{ ++ extension->priv->actions = gtk_action_group_new ("gdm-fingerprint-extension"); ++} + -+ if (was_active) { -+ activate_first_available_task (task_list); -+ } - } - - void --- -1.6.1 - - -From f6a60e2b59c067e222b2254b520c4bbbfc370d3e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sat, 7 Feb 2009 14:19:35 -0500 -Subject: [PATCH 32/65] When active task is disabled fall back to old task - -Previously we would just fall back to the first task -in the list. Now we fall back to the last task the -user clicked on. ---- - gui/simple-greeter/gdm-task-list.c | 12 ++++++++++++ - 1 files changed, 12 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c -index 445b6cc..bcf9072 100644 ---- a/gui/simple-greeter/gdm-task-list.c -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -97,11 +97,23 @@ on_task_enabled (GdmTaskList *task_list, - GdmTask *task) - { - GtkWidget *button; -+ GList *task_node; - - button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); - - gtk_widget_set_sensitive (button, TRUE); - -+ /* Sort the list such that the tasks the user clicks last end -+ * up first. This doesn't change the order in which the tasks -+ * appear in the UI, but will affect which tasks we implicitly -+ * activate if the currently active task gets disabled. -+ */ -+ task_node = g_list_find (task_list->priv->tasks, task); -+ if (task_node != NULL) { -+ task_list->priv->tasks = g_list_delete_link (task_list->priv->tasks, task_node); -+ task_list->priv->tasks = g_list_prepend (task_list->priv->tasks, -+ task); -+ } - } - - static void --- -1.6.1 - - -From 65c9af2e94a1b936ba45f650c45142bf656491ee Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sat, 7 Feb 2009 21:17:49 -0500 -Subject: [PATCH 33/65] Force session reset if all PAM conversations fail - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 22 +++++++++++++++++++--- - 1 files changed, 19 insertions(+), 3 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index d5f0253..e65331f 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -814,15 +814,21 @@ reset_dialog (GdmGreeterLoginWindow *login_window) - } - - static void --do_cancel (GdmGreeterLoginWindow *login_window) -+restart_conversations (GdmGreeterLoginWindow *login_window) - { -- /* need to wait for response from backend */ -- set_message (login_window, _("Cancelling...")); - set_busy (login_window); - set_sensitive (login_window, FALSE); - g_signal_emit (login_window, signals[CANCELLED], 0); - } - +static void -+do_cancel (GdmGreeterLoginWindow *login_window) ++gdm_fingerprint_extension_init (GdmFingerprintExtension *extension) ++{ ++ extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension, ++ GDM_TYPE_FINGERPRINT_EXTENSION, ++ GdmFingerprintExtensionPrivate); ++ ++ extension->priv->icon = g_themed_icon_new ("stock_allow-effects"); ++ create_page (extension); ++ create_actions (extension); ++ gdm_fingerprint_extension_reset (GDM_CONVERSATION (extension)); ++} +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.h 2009-03-03 17:45:05.691016317 -0500 +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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, 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 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ */ ++ ++#ifndef __GDM_FINGERPRINT_EXTENSION_H ++#define __GDM_FINGERPRINT_EXTENSION_H ++ ++#include ++#include "gdm-greeter-extension.h" ++ ++G_BEGIN_DECLS ++ ++#define GDM_TYPE_FINGERPRINT_EXTENSION (gdm_fingerprint_extension_get_type ()) ++#define GDM_FINGERPRINT_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_FINGERPRINT_EXTENSION, GdmFingerprintExtension)) ++#define GDM_FINGERPRINT_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_FINGERPRINT_EXTENSION, GdmFingerprintExtensionClass)) ++#define GDM_IS_FINGERPRINT_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_FINGERPRINT_EXTENSION)) ++#define GDM_IS_FINGERPRINT_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_FINGERPRINT_EXTENSION)) ++#define GDM_FINGERPRINT_EXTENSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_FINGERPRINT_EXTENSION, GdmFingerprintExtensionClass)) ++ ++typedef struct _GdmFingerprintExtensionPrivate GdmFingerprintExtensionPrivate; ++ ++typedef struct ++{ ++ GObject parent; ++ GdmFingerprintExtensionPrivate *priv; ++} GdmFingerprintExtension; ++ ++typedef struct +{ -+ /* need to wait for response from backend */ -+ set_message (login_window, _("Cancelling...")); -+ restart_conversations (login_window); -+} ++ GObjectClass parent_class; ++} GdmFingerprintExtensionClass; + - gboolean - gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - const char *service_name) -@@ -866,6 +872,16 @@ gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_wind - g_object_unref (task); - } - -+ /* If every conversation has failed, then just start over. -+ */ -+ task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); ++GType gdm_fingerprint_extension_get_type (void); + -+ if (gdm_task_is_enabled (task)) { -+ g_object_unref (task); -+ } else { -+ restart_conversations (login_window); -+ } ++GdmFingerprintExtension *gdm_fingerprint_extension_new (void); + - return TRUE; - } - --- -1.6.1 - - -From 35b3c07bf86d64c10f6704987a16d95e694b55f6 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 11 Feb 2009 08:47:52 -0500 -Subject: [PATCH 34/65] Add bare bones start of a smartcard plugin - ---- - configure.ac | 1 + - gui/simple-greeter/plugins/Makefile.am | 2 +- - gui/simple-greeter/plugins/smartcard/Makefile.am | 40 +++ - .../plugins/smartcard/gdm-smartcard-extension.c | 299 ++++++++++++++++++++ - .../plugins/smartcard/gdm-smartcard-extension.h | 56 ++++ - gui/simple-greeter/plugins/smartcard/page.ui | 56 ++++ - gui/simple-greeter/plugins/smartcard/plugin.c | 40 +++ - 7 files changed, 493 insertions(+), 1 deletions(-) - create mode 100644 gui/simple-greeter/plugins/smartcard/Makefile.am - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.h - create mode 100644 gui/simple-greeter/plugins/smartcard/page.ui - create mode 100644 gui/simple-greeter/plugins/smartcard/plugin.c - -diff --git a/configure.ac b/configure.ac -index 5b2519a..cf23c0c 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1439,6 +1439,7 @@ gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc - gui/simple-greeter/plugins/Makefile - gui/simple-greeter/plugins/password/Makefile - gui/simple-greeter/plugins/fingerprint/Makefile -+gui/simple-greeter/plugins/smartcard/Makefile - gui/simple-chooser/Makefile - gui/user-switch-applet/Makefile - utils/Makefile -diff --git a/gui/simple-greeter/plugins/Makefile.am b/gui/simple-greeter/plugins/Makefile.am -index 9811a68..3dd336f 100644 ---- a/gui/simple-greeter/plugins/Makefile.am -+++ b/gui/simple-greeter/plugins/Makefile.am -@@ -1 +1 @@ --SUBDIRS = password fingerprint -+SUBDIRS = password fingerprint smartcard -diff --git a/gui/simple-greeter/plugins/smartcard/Makefile.am b/gui/simple-greeter/plugins/smartcard/Makefile.am -new file mode 100644 -index 0000000..365d299 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/Makefile.am -@@ -0,0 +1,40 @@ ++G_END_DECLS ++ ++#endif /* GDM_FINGERPRINT_EXTENSION_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint 2009-03-03 17:45:05.749021505 -0500 +@@ -0,0 +1,10 @@ ++#%PAM-1.0 ++auth required pam_fprintd.so ++account required pam_nologin.so ++account include system-auth ++password include system-auth ++session required pam_loginuid.so ++session optional pam_console.so ++session optional pam_keyinit.so force revoke ++session required pam_namespace.so ++session include system-auth +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/Makefile.am +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/Makefile.am 2009-03-03 17:45:05.748016423 -0500 +@@ -0,0 +1,50 @@ +NULL = + ++extensiondir = $(extensionsdatadir)/fingerprint ++extension_DATA = page.ui ++ ++pamservicename = gdm-fingerprint ++ +AM_CPPFLAGS = \ + -I$(top_srcdir)/common \ + -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ + -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ + -DDMCONFDIR=\""$(dmconfdir)"\" \ + -DGDMCONFDIR=\"$(gdmconfdir)\" \ -+ -DDATADIR=\""$(datadir)"\" \ ++ -DPLUGINDATADIR=\""$(extensiondir)"\" \ ++ -DPAMSERVICENAME=\""$(pamservicename)"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" \ + -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ @@ -13112,32 +9982,143 @@ index 0000000..365d299 + $(POLKIT_GNOME_CFLAGS) \ + $(NULL) + ++ +plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) -+plugin_LTLIBRARIES = smartcard.la ++plugin_LTLIBRARIES = fingerprint.la + -+smartcard_la_CFLAGS = \ ++fingerprint_la_CFLAGS = \ + $(SIMPLE_GREETER_CFLAGS) \ + $(NULL) + -+smartcard_la_LDFLAGS = -module -avoid-version -export-dynamic -+smartcard_la_LIBADD = ../../../../common/libgdmcommon.la \ ++fingerprint_la_LDFLAGS = -module -avoid-version -export-dynamic ++fingerprint_la_LIBADD = ../../../../common/libgdmcommon.la \ + ../../libgdmsimplegreeter/libgdmsimplegreeter.la -+smartcard_la_SOURCES = \ -+ gdm-smartcard-extension.h \ -+ gdm-smartcard-extension.c \ ++fingerprint_la_SOURCES = \ ++ gdm-fingerprint-extension.h \ ++ gdm-fingerprint-extension.c \ + plugin.c + -+EXTRA_DIST = gdm-smartcard ++pamdir = $(PAM_PREFIX)/pam.d ++pam_DATA = $(pamservicename) ++ ++EXTRA_DIST = $(extension_DATA) $(pam_DATA) + +MAINTAINERCLEANFILES = \ + *~ \ + Makefile.in -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -new file mode 100644 -index 0000000..ac4ab96 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -0,0 +1,299 @@ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/page.ui +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/page.ui 2009-03-03 17:45:05.692016370 -0500 +@@ -0,0 +1,56 @@ ++ ++ ++ ++ ++ True ++ vertical ++ ++ ++ True ++ ++ ++ True ++ ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ ++ ++ 1 ++ ++ ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ ++ ++ True ++ ++ ++ 0 ++ ++ ++ ++ ++ True ++ True ++ 1 ++ ++ ++ ++ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/plugin.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/fingerprint/plugin.c 2009-03-03 17:45:05.693016982 -0500 +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ * ++ */ ++ ++#include "gdm-fingerprint-extension.h" ++ ++#include ++#include ++ ++GdmGreeterExtension * ++gdm_greeter_plugin_get_extension (void) ++{ ++ static GObject *extension; ++ ++ if (extension != NULL) { ++ g_object_ref (extension); ++ } else { ++ extension = g_object_new (GDM_TYPE_FINGERPRINT_EXTENSION, NULL); ++ g_object_add_weak_pointer (extension, (gpointer *) &extension); ++ } ++ ++ return GDM_GREETER_EXTENSION (extension); ++} +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/Makefile.am +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/Makefile.am 2009-03-03 17:45:05.820018029 -0500 +@@ -0,0 +1 @@ ++SUBDIRS = password +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/password/gdm-password-extension.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/password/gdm-password-extension.c 2009-03-03 17:45:05.775006759 -0500 +@@ -0,0 +1,323 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -13160,7 +10141,7 @@ index 0000000..ac4ab96 + */ + +#include -+#include "gdm-smartcard-extension.h" ++#include "gdm-password-extension.h" +#include "gdm-conversation.h" +#include "gdm-task.h" + @@ -13168,7 +10149,7 @@ index 0000000..ac4ab96 +#include +#include + -+struct _GdmSmartcardExtensionPrivate ++struct _GdmPasswordExtensionPrivate +{ + GIcon *icon; + GtkWidget *page; @@ -13181,14 +10162,14 @@ index 0000000..ac4ab96 + guint answer_pending : 1; +}; + -+static void gdm_smartcard_extension_finalize (GObject *object); ++static void gdm_password_extension_finalize (GObject *object); + +static void gdm_task_iface_init (GdmTaskIface *iface); +static void gdm_conversation_iface_init (GdmConversationIface *iface); +static void gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface); + -+G_DEFINE_TYPE_WITH_CODE (GdmSmartcardExtension, -+ gdm_smartcard_extension, ++G_DEFINE_TYPE_WITH_CODE (GdmPasswordExtension, ++ gdm_password_extension, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GDM_TYPE_GREETER_EXTENSION, + gdm_greeter_extension_iface_init) @@ -13198,19 +10179,19 @@ index 0000000..ac4ab96 + gdm_conversation_iface_init)); + +static void -+gdm_smartcard_extension_set_message (GdmConversation *conversation, -+ const char *message) ++gdm_password_extension_set_message (GdmConversation *conversation, ++ const char *message) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); + gtk_widget_show (extension->priv->message_label); + gtk_label_set_text (GTK_LABEL (extension->priv->message_label), message); +} + +static void -+gdm_smartcard_extension_ask_question (GdmConversation *conversation, -+ const char *message) ++gdm_password_extension_ask_question (GdmConversation *conversation, ++ const char *message) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); + gtk_widget_show (extension->priv->prompt_label); + gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); + gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); @@ -13221,10 +10202,10 @@ index 0000000..ac4ab96 +} + +static void -+gdm_smartcard_extension_ask_secret (GdmConversation *conversation, -+ const char *message) ++gdm_password_extension_ask_secret (GdmConversation *conversation, ++ const char *message) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); + gtk_widget_show (extension->priv->prompt_label); + gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); + gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), FALSE); @@ -13235,9 +10216,9 @@ index 0000000..ac4ab96 +} + +static void -+gdm_smartcard_extension_reset (GdmConversation *conversation) ++gdm_password_extension_reset (GdmConversation *conversation) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); + gtk_widget_hide (extension->priv->prompt_label); + gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); + @@ -13250,36 +10231,35 @@ index 0000000..ac4ab96 +} + +static void -+gdm_smartcard_extension_set_ready (GdmConversation *conversation) ++gdm_password_extension_set_ready (GdmConversation *conversation) +{ + gdm_task_set_enabled (GDM_TASK (conversation), TRUE); +} + +char * -+gdm_smartcard_extension_get_service_name (GdmConversation *conversation) ++gdm_password_extension_get_service_name (GdmConversation *conversation) +{ -+ return g_strdup ("smartcard-auth"); ++ return g_strdup (PAMSERVICENAME); +} + +GtkWidget * -+gdm_smartcard_extension_get_page (GdmConversation *conversation) ++gdm_password_extension_get_page (GdmConversation *conversation) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); + return extension->priv->page; +} + +GtkActionGroup * -+gdm_smartcard_extension_get_actions (GdmConversation *conversation) ++gdm_password_extension_get_actions (GdmConversation *conversation) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); -+ ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); + return g_object_ref (extension->priv->actions); +} + +void -+gdm_smartcard_extension_request_answer (GdmConversation *conversation) ++gdm_password_extension_request_answer (GdmConversation *conversation) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); + const char *text; + + if (!extension->priv->answer_pending) { @@ -13292,16 +10272,17 @@ index 0000000..ac4ab96 + gdm_conversation_answer (conversation, text); + + gtk_widget_hide (extension->priv->prompt_entry); ++ gtk_widget_hide (extension->priv->prompt_label); + gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); + gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); +} + +gboolean -+gdm_smartcard_extension_focus (GdmConversation *conversation) ++gdm_password_extension_focus (GdmConversation *conversation) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); -+ ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); + if (!extension->priv->answer_pending) { ++ gdm_conversation_answer (conversation, NULL); + return FALSE; + } + @@ -13310,45 +10291,52 @@ index 0000000..ac4ab96 +} + +GIcon * -+gdm_smartcard_extension_get_icon (GdmTask *task) ++gdm_password_extension_get_icon (GdmTask *task) +{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (task); ++ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (task); + return g_object_ref (extension->priv->icon); +} + +char * -+gdm_smartcard_extension_get_name (GdmTask *task) ++gdm_password_extension_get_name (GdmTask *task) +{ -+ return g_strdup (_("Smartcard Authentication")); ++ return g_strdup (_("Password Authentication")); +} + +char * -+gdm_smartcard_extension_get_description (GdmTask *task) ++gdm_password_extension_get_description (GdmTask *task) +{ -+ return g_strdup (_("Log into session with smartcard")); ++ return g_strdup (_("Log into session with username and password")); +} + -+static void -+gdm_task_iface_init (GdmTaskIface *iface) ++gboolean ++gdm_password_extension_is_choosable (GdmTask *task) +{ -+ iface->get_icon = gdm_smartcard_extension_get_icon; -+ iface->get_description = gdm_smartcard_extension_get_description; -+ iface->get_name = gdm_smartcard_extension_get_name; ++ return FALSE; +} + +static void -+gdm_conversation_iface_init (GdmConversationIface *iface) ++gdm_task_iface_init (GdmTaskIface *iface) +{ -+ iface->set_message = gdm_smartcard_extension_set_message; -+ iface->ask_question = gdm_smartcard_extension_ask_question; -+ iface->ask_secret = gdm_smartcard_extension_ask_secret; -+ iface->reset = gdm_smartcard_extension_reset; -+ iface->set_ready = gdm_smartcard_extension_set_ready; -+ iface->get_service_name = gdm_smartcard_extension_get_service_name; -+ iface->get_page = gdm_smartcard_extension_get_page; -+ iface->get_actions = gdm_smartcard_extension_get_actions; -+ iface->request_answer = gdm_smartcard_extension_request_answer; -+ iface->focus = gdm_smartcard_extension_focus; ++ iface->get_icon = gdm_password_extension_get_icon; ++ iface->get_description = gdm_password_extension_get_description; ++ iface->get_name = gdm_password_extension_get_name; ++ iface->is_choosable = gdm_password_extension_is_choosable; ++} ++ ++static void ++gdm_conversation_iface_init (GdmConversationIface *iface) ++{ ++ iface->set_message = gdm_password_extension_set_message; ++ iface->ask_question = gdm_password_extension_ask_question; ++ iface->ask_secret = gdm_password_extension_ask_secret; ++ iface->reset = gdm_password_extension_reset; ++ iface->set_ready = gdm_password_extension_set_ready; ++ iface->get_service_name = gdm_password_extension_get_service_name; ++ iface->get_page = gdm_password_extension_get_page; ++ iface->get_actions = gdm_password_extension_get_actions; ++ iface->request_answer = gdm_password_extension_request_answer; ++ iface->focus = gdm_password_extension_focus; +} + +static void @@ -13357,25 +10345,31 @@ index 0000000..ac4ab96 +} + +static void -+gdm_smartcard_extension_class_init (GdmSmartcardExtensionClass *extension_class) ++gdm_password_extension_class_init (GdmPasswordExtensionClass *extension_class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (extension_class); + -+ object_class->finalize = gdm_smartcard_extension_finalize; ++ object_class->finalize = gdm_password_extension_finalize; + + g_type_class_add_private (extension_class, -+ sizeof (GdmSmartcardExtensionPrivate)); ++ sizeof (GdmPasswordExtensionPrivate)); +} + +static void -+gdm_smartcard_extension_finalize (GObject *object) ++gdm_password_extension_finalize (GObject *object) +{ +} + +static void -+create_page (GdmSmartcardExtension *extension) ++on_activate_log_in (GdmPasswordExtension *extension) ++{ ++ gdm_password_extension_request_answer (GDM_CONVERSATION (extension)); ++} ++ ++static void ++create_page (GdmPasswordExtension *extension) +{ + GtkBuilder *builder; + GObject *object; @@ -13385,7 +10379,7 @@ index 0000000..ac4ab96 + + error = NULL; + gtk_builder_add_from_file (builder, -+ "/usr/share/gdm/simple-greeter/extensions/smartcard/page.ui", ++ PLUGINDATADIR "/page.ui", + &error); + + if (error != NULL) { @@ -13418,690 +10412,272 @@ index 0000000..ac4ab96 +} + +static void -+create_actions (GdmSmartcardExtension *extension) ++create_actions (GdmPasswordExtension *extension) +{ + GtkAction *action; + -+ extension->priv->actions = gtk_action_group_new ("gdm-smartcard-extension"); -+} -+ -+static void -+gdm_smartcard_extension_init (GdmSmartcardExtension *extension) -+{ -+ extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension, -+ GDM_TYPE_SMARTCARD_EXTENSION, -+ GdmSmartcardExtensionPrivate); -+ -+ extension->priv->icon = g_themed_icon_new ("apple-green"); -+ create_page (extension); -+ create_actions (extension); -+ gdm_smartcard_extension_reset (GDM_CONVERSATION (extension)); -+} -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.h b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.h -new file mode 100644 -index 0000000..285b51a ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.h -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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, 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 -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written By: Ray Strode -+ */ -+ -+#ifndef __GDM_SMARTCARD_EXTENSION_H -+#define __GDM_SMARTCARD_EXTENSION_H -+ -+#include -+#include "gdm-greeter-extension.h" -+ -+G_BEGIN_DECLS -+ -+#define GDM_TYPE_SMARTCARD_EXTENSION (gdm_smartcard_extension_get_type ()) -+#define GDM_SMARTCARD_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SMARTCARD_EXTENSION, GdmSmartcardExtension)) -+#define GDM_SMARTCARD_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SMARTCARD_EXTENSION, GdmSmartcardExtensionClass)) -+#define GDM_IS_SMARTCARD_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SMARTCARD_EXTENSION)) -+#define GDM_IS_SMARTCARD_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SMARTCARD_EXTENSION)) -+#define GDM_SMARTCARD_EXTENSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SMARTCARD_EXTENSION, GdmSmartcardExtensionClass)) -+ -+typedef struct _GdmSmartcardExtensionPrivate GdmSmartcardExtensionPrivate; -+ -+typedef struct -+{ -+ GObject parent; -+ GdmSmartcardExtensionPrivate *priv; -+} GdmSmartcardExtension; -+ -+typedef struct -+{ -+ GObjectClass parent_class; -+} GdmSmartcardExtensionClass; -+ -+GType gdm_smartcard_extension_get_type (void); -+ -+GdmSmartcardExtension *gdm_smartcard_extension_new (void); -+ -+G_END_DECLS -+ -+#endif /* GDM_SMARTCARD_EXTENSION_H */ -diff --git a/gui/simple-greeter/plugins/smartcard/page.ui b/gui/simple-greeter/plugins/smartcard/page.ui -new file mode 100644 -index 0000000..fe6da78 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/page.ui -@@ -0,0 +1,56 @@ -+ -+ -+ -+ -+ True -+ vertical -+ -+ -+ True -+ -+ -+ True -+ -+ -+ False -+ False -+ 0 -+ -+ -+ -+ -+ True -+ True -+ True -+ -+ -+ 1 -+ -+ -+ -+ -+ True -+ True -+ 0 -+ -+ -+ -+ -+ True -+ -+ -+ True -+ -+ -+ 0 -+ -+ -+ -+ -+ True -+ True -+ 1 -+ -+ -+ -+ -diff --git a/gui/simple-greeter/plugins/smartcard/plugin.c b/gui/simple-greeter/plugins/smartcard/plugin.c -new file mode 100644 -index 0000000..fffbd50 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/plugin.c -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2009 Red Hat, Inc. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written By: Ray Strode -+ * -+ */ -+ -+#include "gdm-smartcard-extension.h" -+ -+#include -+#include -+ -+GdmGreeterExtension * -+gdm_greeter_plugin_get_extension (void) -+{ -+ static GObject *extension; -+ -+ if (extension != NULL) { -+ g_object_ref (extension); -+ } else { -+ extension = g_object_new (GDM_TYPE_SMARTCARD_EXTENSION, NULL); -+ g_object_add_weak_pointer (extension, (gpointer *) &extension); -+ } -+ -+ return GDM_GREETER_EXTENSION (extension); -+} --- -1.6.1 - - -From 5c160d8feb0edf8523f5d75957ab8ba4bdea887f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 17 Feb 2009 17:38:22 -0500 -Subject: [PATCH 35/65] Add another message when plugin fails to load - ---- - gui/simple-greeter/gdm-greeter-plugin.c | 4 ++++ - 1 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-plugin.c b/gui/simple-greeter/gdm-greeter-plugin.c -index 821b679..02814a2 100644 ---- a/gui/simple-greeter/gdm-greeter-plugin.c -+++ b/gui/simple-greeter/gdm-greeter-plugin.c -@@ -167,9 +167,13 @@ gdm_greeter_plugin_load (GdmGreeterPlugin *plugin) - GdmGreeterPluginGetExtensionFunc invoke; - } get_extension; - -+ - module = g_module_open (plugin->priv->filename, G_MODULE_BIND_LOCAL); - - if (module == NULL) { -+ g_warning ("plugin %s couldn't be opened: %s", -+ plugin->priv->filename, -+ g_module_error ()); - g_signal_emit (plugin, signals [LOAD_FAILED], 0); - return; - } --- -1.6.1 - - -From 7f73245875240390f985971cef7d6ba107f48fd6 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 17 Feb 2009 17:39:24 -0500 -Subject: [PATCH 36/65] Add new gdm_task_list_set_active_task - -It will be useful to be able to select -a task from the greeter programmatically. ---- - gui/simple-greeter/gdm-task-list.c | 29 +++++++++++++++++++++-------- - gui/simple-greeter/gdm-task-list.h | 2 ++ - 2 files changed, 23 insertions(+), 8 deletions(-) - -diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c -index bcf9072..25831a6 100644 ---- a/gui/simple-greeter/gdm-task-list.c -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -124,18 +124,13 @@ activate_first_available_task (GdmTaskList *task_list) - node = task_list->priv->tasks; - while (node != NULL) { - GdmTask *task; -- GtkWidget *button; - - task = GDM_TASK (node->data); - -- button = GTK_WIDGET (g_object_get_data (G_OBJECT (task), -- "gdm-task-list-button")); -- -- if (GTK_WIDGET_IS_SENSITIVE (button)) { -- if (gtk_widget_activate (button)) { -- break; -- } -+ if (gdm_task_list_set_active_task (task_list, task)) { -+ break; - } -+ - node = node->next; - } - -@@ -302,6 +297,24 @@ gdm_task_list_get_active_task (GdmTaskList *widget) - NULL); - } - -+gboolean -+gdm_task_list_set_active_task (GdmTaskList *widget, -+ GdmTask *task) -+{ -+ GtkWidget *button; -+ -+ button = GTK_WIDGET (g_object_get_data (G_OBJECT (task), -+ "gdm-task-list-button")); -+ -+ if (GTK_WIDGET_IS_SENSITIVE (button)) { -+ if (gtk_widget_activate (button)) { -+ return TRUE; -+ } -+ } -+ -+ return FALSE; -+} ++ extension->priv->actions = gtk_action_group_new ("gdm-password-extension"); + - int - gdm_task_list_get_number_of_tasks (GdmTaskList *widget) - { -diff --git a/gui/simple-greeter/gdm-task-list.h b/gui/simple-greeter/gdm-task-list.h -index e8cc2f4..8bc0c0e 100644 ---- a/gui/simple-greeter/gdm-task-list.h -+++ b/gui/simple-greeter/gdm-task-list.h -@@ -66,6 +66,8 @@ GtkWidget * gdm_task_list_new (void); - gboolean gdm_task_list_task_is_active (GdmTaskList *task_list, - GdmTask *task); - GdmTask * gdm_task_list_get_active_task (GdmTaskList *widget); -+gboolean gdm_task_list_set_active_task (GdmTaskList *widget, -+ GdmTask *task); - GdmTask * gdm_task_list_foreach_task (GdmTaskList *widget, - GdmTaskListForeachFunc foreach_func, - gpointer data); --- -1.6.1 - - -From 62ce8e8321096be8b6842400e70a468e0824656c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 18 Feb 2009 12:32:39 -0500 -Subject: [PATCH 37/65] Add a way for plugins to start/stop pam - -The smartcard plugin is going to want to -start the conversation as soon as the card -gets plugged in. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 27 ++++++++++++++++ - .../libgdmsimplegreeter/gdm-conversation.c | 32 ++++++++++++++++++++ - .../libgdmsimplegreeter/gdm-conversation.h | 6 ++++ - 3 files changed, 65 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index e65331f..5f37d0c 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -2248,6 +2248,25 @@ on_conversation_answer (GdmGreeterLoginWindow *login_window, - set_ready (login_window); - } - -+static void -+on_conversation_cancel (GdmGreeterLoginWindow *login_window, -+ GdmConversation *conversation) -+{ -+ do_cancel (login_window); ++ action = gtk_action_new (GDM_CONVERSATION_DEFAULT_ACTION, ++ _("Log In"), ++ _("Log into the currently selected sesson"), ++ NULL); ++ g_signal_connect_swapped (action, "activate", ++ G_CALLBACK (on_activate_log_in), extension); ++ g_object_set (G_OBJECT (action), "icon-name", "go-home", NULL); ++ gtk_action_group_add_action (extension->priv->actions, ++ action); +} + +static void -+on_conversation_chose_user (GdmGreeterLoginWindow *login_window, -+ const char *username, -+ GdmConversation *conversation) ++gdm_password_extension_init (GdmPasswordExtension *extension) +{ -+ if (gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ GDM_TASK (conversation))) { -+ gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), -+ username); -+ } -+} ++ extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension, ++ GDM_TYPE_PASSWORD_EXTENSION, ++ GdmPasswordExtensionPrivate); + - void - gdm_greeter_login_window_remove_extension (GdmGreeterLoginWindow *login_window, - GdmGreeterExtension *extension) -@@ -2385,6 +2404,14 @@ gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, - "answer", - G_CALLBACK (on_conversation_answer), - login_window); -+ g_signal_connect_swapped (GDM_CONVERSATION (extension), -+ "cancel", -+ G_CALLBACK (on_conversation_cancel), -+ login_window); -+ g_signal_connect_swapped (GDM_CONVERSATION (extension), -+ "user-chosen", -+ G_CALLBACK (on_conversation_chose_user), -+ login_window); - - name = gdm_task_get_name (GDM_TASK (extension)); - description = gdm_task_get_description (GDM_TASK (extension)); -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c -index e21c56b..cef435c 100644 ---- a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c -@@ -30,6 +30,8 @@ - - enum { - ANSWER, -+ USER_CHOSEN, -+ CANCEL, - LAST_SIGNAL - }; - -@@ -71,6 +73,25 @@ gdm_conversation_class_init (gpointer g_iface) - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, - 1, G_TYPE_STRING); -+ signals [USER_CHOSEN] = -+ g_signal_new ("user-chosen", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmConversationIface, user_chosen), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); -+ signals [CANCEL] = -+ g_signal_new ("cancel", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmConversationIface, cancel), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); - } - - void -@@ -145,3 +166,14 @@ gdm_conversation_answer (GdmConversation *conversation, - g_signal_emit (conversation, signals [ANSWER], 0, answer); - } - -+void -+gdm_conversation_cancel (GdmConversation *conversation) -+{ -+ g_signal_emit (conversation, signals [CANCEL], 0); -+} -+void -+gdm_conversation_choose_user (GdmConversation *conversation, -+ const char *username) -+{ -+ g_signal_emit (conversation, signals [USER_CHOSEN], 0, username); ++ extension->priv->icon = g_themed_icon_new ("dialog-password"); ++ create_page (extension); ++ create_actions (extension); ++ ++ gdm_password_extension_reset (GDM_CONVERSATION (extension)); +} -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h -index f1910cf..fb4bf49 100644 ---- a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h -@@ -34,6 +34,7 @@ G_BEGIN_DECLS - #define GDM_CONVERSATION_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDM_TYPE_CONVERSATION, GdmConversationIface)) - - #define GDM_CONVERSATION_DEFAULT_ACTION "default-action" -+#define GDM_CONVERSATION_OTHER_USER "__other" - - typedef struct _GdmConversation GdmConversation; - typedef struct _GdmConversationIface GdmConversationIface; -@@ -59,6 +60,8 @@ struct _GdmConversationIface - - /* signals */ - char * (* answer) (GdmConversation *conversation); -+ void (* cancel) (GdmConversation *conversation); -+ void (* user_chosen) (GdmConversation *conversation); - }; - - GType gdm_conversation_get_type (void) G_GNUC_CONST; -@@ -81,6 +84,9 @@ gboolean gdm_conversation_focus (GdmConversation *conversation); - */ - void gdm_conversation_answer (GdmConversation *conversation, - const char *answer); -+void gdm_conversation_cancel (GdmConversation *conversation); -+void gdm_conversation_choose_user (GdmConversation *conversation, -+ const char *username); - - G_END_DECLS - --- -1.6.1 - - -From 3a3508b1fde4e244b10b16566cd171ad9557855e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 18 Feb 2009 12:48:37 -0500 -Subject: [PATCH 38/65] Add helper program to listen for smart card events - -This is a copy and paste of an old RHEL patch I did -a few years ago. ---- - configure.ac | 7 + - gui/simple-greeter/plugins/smartcard/Makefile.am | 22 + - .../plugins/smartcard/gdm-smartcard-extension.c | 91 ++ - .../plugins/smartcard/gdm-smartcard-manager.c | 1394 ++++++++++++++++++++ - .../plugins/smartcard/gdm-smartcard-manager.h | 86 ++ - .../plugins/smartcard/gdm-smartcard-worker.c | 167 +++ - .../plugins/smartcard/gdm-smartcard.c | 558 ++++++++ - .../plugins/smartcard/gdm-smartcard.h | 94 ++ - 8 files changed, 2419 insertions(+), 0 deletions(-) - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.c - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.h - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard.c - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard.h - -diff --git a/configure.ac b/configure.ac -index cf23c0c..8e99509 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -67,6 +67,7 @@ GNOME_PANEL_REQUIRED_VERSION=2.0.0 - LIBXKLAVIER_REQUIRED_VERSION=3.5 - #FONTCONFIG_REQUIRED_VERSION=2.6.0 - FONTCONFIG_REQUIRED_VERSION=2.5.0 -+NSS_REQUIRED_VERSION=3.11.1 - - EXTRA_COMPILE_WARNINGS(yes) - -@@ -89,6 +90,12 @@ PKG_CHECK_MODULES(DAEMON, - AC_SUBST(DAEMON_CFLAGS) - AC_SUBST(DAEMON_LIBS) - -+PKG_CHECK_MODULES(NSS, -+ nss >= $NSS_REQUIRED_VERSION -+) -+AC_SUBST(NSS_CFLAGS) -+AC_SUBST(NSS_LIBS) +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/password/gdm-password-extension.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/password/gdm-password-extension.h 2009-03-03 17:45:05.683016309 -0500 +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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, 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 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ */ + - PKG_CHECK_MODULES(XLIB, x11 xau, , - [AC_PATH_XTRA - if test "x$no_x" = xyes; then -diff --git a/gui/simple-greeter/plugins/smartcard/Makefile.am b/gui/simple-greeter/plugins/smartcard/Makefile.am -index 365d299..2dfe226 100644 ---- a/gui/simple-greeter/plugins/smartcard/Makefile.am -+++ b/gui/simple-greeter/plugins/smartcard/Makefile.am -@@ -11,6 +11,7 @@ AM_CPPFLAGS = \ - -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ - -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ - -DLIBEXECDIR=\""$(libexecdir)"\" \ -+ -DLIBDIR=\""$(libdir)"\" \ - -DSBINDIR=\""$(sbindir)"\" \ - $(DISABLE_DEPRECATED_CFLAGS) \ - $(GTK_CFLAGS) \ -@@ -25,6 +26,11 @@ smartcard_la_CFLAGS = \ - $(SIMPLE_GREETER_CFLAGS) \ - $(NULL) - -+libexec_PROGRAMS = \ -+ gdm-smartcard-worker \ -+ $(NULL) ++#ifndef __GDM_PASSWORD_EXTENSION_H ++#define __GDM_PASSWORD_EXTENSION_H + ++#include ++#include "gdm-greeter-extension.h" + - smartcard_la_LDFLAGS = -module -avoid-version -export-dynamic - smartcard_la_LIBADD = ../../../../common/libgdmcommon.la \ - ../../libgdmsimplegreeter/libgdmsimplegreeter.la -@@ -33,6 +39,22 @@ smartcard_la_SOURCES = \ - gdm-smartcard-extension.c \ - plugin.c - -+gdm_smartcard_worker_LDADD = ../../../../common/libgdmcommon.la \ -+ $(DAEMON_LIBS) \ -+ $(GTHREAD_LIBS) \ -+ $(NSS_LIBS) \ -+ $(NULL) -+gdm_smartcard_worker_CFLAGS = $(DAEMON_CFLAGS) \ -+ $(NSS_CFLAGS) \ -+ $(NULL) -+gdm_smartcard_worker_SOURCES = \ -+ gdm-smartcard.h \ -+ gdm-smartcard.c \ -+ gdm-smartcard-manager.h \ -+ gdm-smartcard-manager.c \ -+ gdm-smartcard-worker.c \ -+ $(NULL) ++G_BEGIN_DECLS + - EXTRA_DIST = gdm-smartcard - - MAINTAINERCLEANFILES = \ -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -index ac4ab96..efa0978 100644 ---- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -24,10 +24,20 @@ - #include "gdm-conversation.h" - #include "gdm-task.h" - -+#include -+#include -+#include -+#include -+#include ++#define GDM_TYPE_PASSWORD_EXTENSION (gdm_password_extension_get_type ()) ++#define GDM_PASSWORD_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_PASSWORD_EXTENSION, GdmPasswordExtension)) ++#define GDM_PASSWORD_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_PASSWORD_EXTENSION, GdmPasswordExtensionClass)) ++#define GDM_IS_PASSWORD_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_PASSWORD_EXTENSION)) ++#define GDM_IS_PASSWORD_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_PASSWORD_EXTENSION)) ++#define GDM_PASSWORD_EXTENSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_PASSWORD_EXTENSION, GdmPasswordExtensionClass)) + - #include - #include - #include - -+#ifndef GDM_SMARTCARD_WORKER_COMMAND -+#define GDM_SMARTCARD_WORKER_COMMAND LIBEXECDIR "/gdm-smartcard-worker" -+#endif ++typedef struct _GdmPasswordExtensionPrivate GdmPasswordExtensionPrivate; + - struct _GdmSmartcardExtensionPrivate - { - GIcon *icon; -@@ -38,6 +48,9 @@ struct _GdmSmartcardExtensionPrivate - GtkWidget *prompt_label; - GtkWidget *prompt_entry; - -+ GPid worker_pid; -+ int number_of_tokens; ++typedef struct ++{ ++ GObject parent; ++ GdmPasswordExtensionPrivate *priv; ++} GdmPasswordExtension; + - guint answer_pending : 1; - }; - -@@ -284,6 +297,83 @@ create_actions (GdmSmartcardExtension *extension) - - extension->priv->actions = gtk_action_group_new ("gdm-smartcard-extension"); - } -+static gboolean -+on_smartcard_event (GIOChannel *io_channel, -+ GIOCondition condition, -+ gpointer data) ++typedef struct +{ -+ GdmSmartcardExtension *extension; ++ GObjectClass parent_class; ++} GdmPasswordExtensionClass; + -+ extension = GDM_SMARTCARD_EXTENSION (data); ++GType gdm_password_extension_get_type (void); + -+ if (condition & G_IO_IN) { -+ char buffer[1024]; -+ ssize_t num_bytes; ++GdmPasswordExtension *gdm_password_extension_new (void); + -+ num_bytes = read (g_io_channel_unix_get_fd (io_channel), -+ buffer, sizeof (buffer)); ++G_END_DECLS + -+ if (num_bytes < 0 && errno != EINTR) -+ return FALSE; ++#endif /* GDM_PASSWORD_EXTENSION_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/password/gdm-password +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/password/gdm-password 2009-03-03 17:45:05.786023548 -0500 +@@ -0,0 +1,13 @@ ++#%PAM-1.0 ++auth required pam_env.so ++auth required pam_unix.so ++auth optional pam_gnome_keyring.so ++account required pam_nologin.so ++account include system-auth ++password include system-auth ++session required pam_loginuid.so ++session optional pam_console.so ++session optional pam_keyinit.so force revoke ++session required pam_namespace.so ++session optional pam_gnome_keyring.so auto_start ++session include system-auth +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/password/Makefile.am +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/password/Makefile.am 2009-03-03 17:45:05.821018082 -0500 +@@ -0,0 +1,44 @@ ++NULL = + -+ if (num_bytes != 1) { -+ g_debug ("buffer: %s\n", buffer); -+ return TRUE; -+ } ++extensiondir = $(extensionsdatadir)/password ++extension_DATA = page.ui + -+ if (buffer[0] == 'I') { -+ extension->priv->number_of_tokens++; -+ } else { -+ extension->priv->number_of_tokens--; -+ } ++AM_CPPFLAGS = \ ++ -I$(top_srcdir)/common \ ++ -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ ++ -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ ++ -DDMCONFDIR=\""$(dmconfdir)"\" \ ++ -DGDMCONFDIR=\"$(gdmconfdir)\" \ ++ -DPLUGINDATADIR=\""$(extensiondir)"\" \ ++ -DPAMSERVICENAME=\""gdm"\" \ ++ -DSYSCONFDIR=\""$(sysconfdir)"\" \ ++ -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ ++ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ ++ -DLIBEXECDIR=\""$(libexecdir)"\" \ ++ -DSBINDIR=\""$(sbindir)"\" \ ++ $(DISABLE_DEPRECATED_CFLAGS) \ ++ $(GTK_CFLAGS) \ ++ $(SIMPLE_GREETER_CFLAGS) \ ++ $(POLKIT_GNOME_CFLAGS) \ ++ $(NULL) ++ ++plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) ++plugin_LTLIBRARIES = password.la ++ ++password_la_CFLAGS = \ ++ $(SIMPLE_GREETER_CFLAGS) \ ++ $(NULL) + -+ if (extension->priv->number_of_tokens == 1) { -+ gdm_conversation_choose_user (GDM_CONVERSATION (extension), -+ GDM_CONVERSATION_OTHER_USER); -+ } else if (extension->priv->number_of_tokens == 0) { -+ gdm_conversation_cancel (GDM_CONVERSATION (extension)); -+ } ++password_la_LDFLAGS = -module -avoid-version -export-dynamic ++password_la_LIBADD = ../../../../common/libgdmcommon.la \ ++ ../../libgdmsimplegreeter/libgdmsimplegreeter.la ++password_la_SOURCES = \ ++ gdm-password-extension.h \ ++ gdm-password-extension.c \ ++ plugin.c + -+ return TRUE; -+ } ++EXTRA_DIST = $(extension_DATA) + -+ if (condition & G_IO_HUP) { -+ return FALSE; -+ } ++MAINTAINERCLEANFILES = \ ++ *~ \ ++ Makefile.in +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/password/page.ui +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/password/page.ui 2009-03-03 17:45:05.684016293 -0500 +@@ -0,0 +1,56 @@ ++ ++ ++ ++ ++ True ++ vertical ++ ++ ++ True ++ ++ ++ True ++ ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ ++ ++ 1 ++ ++ ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ ++ ++ True ++ ++ ++ 0 ++ ++ ++ ++ ++ True ++ True ++ 1 ++ ++ ++ ++ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/password/plugin.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/password/plugin.c 2009-03-03 17:45:05.685016276 -0500 +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ * ++ */ + -+ return TRUE; -+} ++#include "gdm-password-extension.h" + -+static void -+watch_for_smartcards (GdmSmartcardExtension *extension) -+{ -+ GError *error; -+ GIOChannel *io_channel; -+ char *args[] = { GDM_SMARTCARD_WORKER_COMMAND, NULL }; -+ GPid pid; -+ int stdout_fd; ++#include ++#include + -+ error = NULL; ++GdmGreeterExtension * ++gdm_greeter_plugin_get_extension (void) ++{ ++ static GObject *extension; + -+ if (!g_spawn_async_with_pipes (NULL, args, NULL, 0, -+ NULL, NULL, &pid, NULL, -+ &stdout_fd, NULL, &error)) { -+ g_debug ("could not start smart card manager: %s", error->message); -+ g_error_free (error); -+ return; ++ if (extension != NULL) { ++ g_object_ref (extension); ++ } else { ++ extension = g_object_new (GDM_TYPE_PASSWORD_EXTENSION, NULL); ++ g_object_add_weak_pointer (extension, (gpointer *) &extension); + } -+ fcntl (stdout_fd, F_SETFD, FD_CLOEXEC); -+ -+ io_channel = g_io_channel_unix_new (stdout_fd); -+ g_io_channel_set_flags (io_channel, G_IO_FLAG_NONBLOCK, NULL); -+ g_io_channel_set_encoding (io_channel, NULL, NULL); -+ g_io_channel_set_buffered (io_channel, FALSE); -+ g_io_add_watch (io_channel, G_IO_IN, on_smartcard_event, extension); -+ g_io_channel_set_close_on_unref (io_channel, TRUE); -+ g_io_channel_unref (io_channel); + -+ extension->priv->worker_pid = pid; ++ return GDM_GREETER_EXTENSION (extension); +} - - static void - gdm_smartcard_extension_init (GdmSmartcardExtension *extension) -@@ -293,6 +383,7 @@ gdm_smartcard_extension_init (GdmSmartcardExtension *extension) - GdmSmartcardExtensionPrivate); - - extension->priv->icon = g_themed_icon_new ("apple-green"); -+ watch_for_smartcards (extension); - create_page (extension); - create_actions (extension); - gdm_smartcard_extension_reset (GDM_CONVERSATION (extension)); -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.c -new file mode 100644 -index 0000000..e346a9c ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.c -@@ -0,0 +1,1394 @@ -+/* gdm-smartcard-manager.c - object for monitoring smartcard insertion and -+ * removal events +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard.c 2009-03-03 17:45:05.745016473 -0500 +@@ -0,0 +1,558 @@ ++/* gdm-smartcard.c - smartcard object + * -+ * Copyright (C) 2006, 2009 Red Hat, Inc. ++ * Copyright (C) 2006 Ray Strode + * + * 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 @@ -14117,4750 +10693,2998 @@ index 0000000..e346a9c + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. -+ * -+ * Written By: Ray Strode + */ -+#define _GNU_SOURCE -+#include "gdm-smartcard-manager.h" -+ +#define GDM_SMARTCARD_ENABLE_INTERNAL_API +#include "gdm-smartcard.h" + -+#include +#include -+#include -+#include -+#include -+#include -+#include +#include -+#include -+#include -+#include +#include + +#include +#include + -+#include ++#include +#include +#include ++#include +#include +#include + -+#ifndef GDM_SMARTCARD_MANAGER_DRIVER -+#define GDM_SMARTCARD_MANAGER_DRIVER LIBDIR"/pkcs11/libcoolkeypk11.so" -+#endif -+ -+#ifndef GDM_SMARTCARD_MANAGER_NSS_DB -+#define GDM_SMARTCARD_MANAGER_NSS_DB SYSCONFDIR"/pki/nssdb" -+#endif -+ -+#ifndef GDM_MAX_OPEN_FILE_DESCRIPTORS -+#define GDM_MAX_OPEN_FILE_DESCRIPTORS 1024 -+#endif -+ -+#ifndef GDM_OPEN_FILE_DESCRIPTORS_DIR -+#define GDM_OPEN_FILE_DESCRIPTORS_DIR "/proc/self/fd" -+#endif -+ -+typedef enum _GdmSmartcardManagerState GdmSmartcardManagerState; -+typedef struct _GdmSmartcardManagerWorker GdmSmartcardManagerWorker; -+ -+enum _GdmSmartcardManagerState { -+ GDM_SMARTCARD_MANAGER_STATE_STOPPED = 0, -+ GDM_SMARTCARD_MANAGER_STATE_STARTING, -+ GDM_SMARTCARD_MANAGER_STATE_STARTED, -+ GDM_SMARTCARD_MANAGER_STATE_STOPPING, -+}; -+ -+struct _GdmSmartcardManagerPrivate { -+ GdmSmartcardManagerState state; ++struct _GdmSmartcardPrivate { + SECMODModule *module; -+ char *module_path; -+ -+ GSource *smartcard_event_source; -+ GPid smartcard_event_watcher_pid; -+ GHashTable *smartcards; ++ GdmSmartcardState state; + -+ GThread *worker_thread; ++ CK_SLOT_ID slot_id; ++ int slot_series; + -+ guint poll_timeout_id; ++ PK11SlotInfo *slot; ++ char *name; + -+ guint32 is_unstoppable : 1; -+ guint32 nss_is_loaded : 1; ++ CERTCertificate *signing_certificate; ++ CERTCertificate *encryption_certificate; +}; + -+struct _GdmSmartcardManagerWorker { -+ SECMODModule *module; -+ GHashTable *smartcards; -+ gint write_fd; ++static void gdm_smartcard_finalize (GObject *object); ++static void gdm_smartcard_class_install_signals (GdmSmartcardClass *card_class); ++static void gdm_smartcard_class_install_properties (GdmSmartcardClass *card_class); ++static void gdm_smartcard_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec); ++static void gdm_smartcard_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec); ++static void gdm_smartcard_set_name (GdmSmartcard *card, const char *name); ++static void gdm_smartcard_set_slot_id (GdmSmartcard *card, ++ int slot_id); ++static void gdm_smartcard_set_slot_series (GdmSmartcard *card, ++ int slot_series); ++static void gdm_smartcard_set_module (GdmSmartcard *card, ++ SECMODModule *module); + -+ guint32 nss_is_loaded : 1; -+}; ++static PK11SlotInfo *gdm_smartcard_find_slot_from_id (GdmSmartcard *card, ++ int slot_id); + -+static void gdm_smartcard_manager_finalize (GObject *object); -+static void gdm_smartcard_manager_class_install_signals (GdmSmartcardManagerClass *service_class); -+static void gdm_smartcard_manager_class_install_properties (GdmSmartcardManagerClass *service_class); -+static void gdm_smartcard_manager_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec); -+static void gdm_smartcard_manager_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec); -+static void gdm_smartcard_manager_set_module_path (GdmSmartcardManager *manager, -+ const char *module_path); -+static void gdm_smartcard_manager_card_removed_handler (GdmSmartcardManager *manager, -+ GdmSmartcard *card); -+static void gdm_smartcard_manager_card_inserted_handler (GdmSmartcardManager *manager_class, -+ GdmSmartcard *card); -+static gboolean gdm_smartcard_manager_stop_now (GdmSmartcardManager *manager); -+static void gdm_smartcard_manager_queue_stop (GdmSmartcardManager *manager); ++static PK11SlotInfo *gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, ++ const char *card_name); ++static gboolean gdm_smartcard_fetch_certificates (GdmSmartcard *card); + -+static gboolean gdm_smartcard_manager_create_worker (GdmSmartcardManager *manager, -+ int *worker_fd, GThread **worker_thread); ++#ifndef GDM_SMARTCARD_DEFAULT_SLOT_ID ++#define GDM_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1) ++#endif + -+static GdmSmartcardManagerWorker * gdm_smartcard_manager_worker_new (gint write_fd); -+static void gdm_smartcard_manager_worker_free (GdmSmartcardManagerWorker *worker); -+static gboolean gdm_open_pipe (gint *write_fd, gint *read_fd); -+static gboolean sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes); -+static gboolean sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes); -+static GdmSmartcard *sc_read_smartcard (gint fd, SECMODModule *module); -+static gboolean sc_write_smartcard (gint fd, GdmSmartcard *card); ++#ifndef GDM_SMARTCARD_DEFAULT_SLOT_SERIES ++#define GDM_SMARTCARD_DEFAULT_SLOT_SERIES -1 ++#endif + +enum { + PROP_0 = 0, -+ PROP_MODULE_PATH, ++ PROP_NAME, ++ PROP_SLOT_ID, ++ PROP_SLOT_SERIES, ++ PROP_MODULE, + NUMBER_OF_PROPERTIES +}; + +enum { -+ SMARTCARD_INSERTED = 0, -+ SMARTCARD_REMOVED, -+ ERROR, ++ INSERTED, ++ REMOVED, + NUMBER_OF_SIGNALS +}; + -+static guint gdm_smartcard_manager_signals[NUMBER_OF_SIGNALS]; ++static guint gdm_smartcard_signals[NUMBER_OF_SIGNALS]; + -+G_DEFINE_TYPE (GdmSmartcardManager, -+ gdm_smartcard_manager, -+ G_TYPE_OBJECT); ++G_DEFINE_TYPE (GdmSmartcard, gdm_smartcard, G_TYPE_OBJECT); + +static void -+gdm_smartcard_manager_class_init (GdmSmartcardManagerClass *manager_class) ++gdm_smartcard_class_init (GdmSmartcardClass *card_class) +{ + GObjectClass *gobject_class; + -+ gobject_class = G_OBJECT_CLASS (manager_class); ++ gobject_class = G_OBJECT_CLASS (card_class); + -+ gobject_class->finalize = gdm_smartcard_manager_finalize; ++ gobject_class->finalize = gdm_smartcard_finalize; + -+ gdm_smartcard_manager_class_install_signals (manager_class); -+ gdm_smartcard_manager_class_install_properties (manager_class); ++ gdm_smartcard_class_install_signals (card_class); ++ gdm_smartcard_class_install_properties (card_class); + -+ g_type_class_add_private (manager_class, -+ sizeof (GdmSmartcardManagerPrivate)); ++ g_type_class_add_private (card_class, ++ sizeof (GdmSmartcardPrivate)); +} + +static void -+gdm_smartcard_manager_class_install_properties (GdmSmartcardManagerClass *card_class) ++gdm_smartcard_class_install_signals (GdmSmartcardClass *card_class) +{ + GObjectClass *object_class; -+ GParamSpec *param_spec; + + object_class = G_OBJECT_CLASS (card_class); -+ object_class->set_property = gdm_smartcard_manager_set_property; -+ object_class->get_property = gdm_smartcard_manager_get_property; -+ -+ param_spec = g_param_spec_string ("module-path", _("Module Path"), -+ _("path to smartcard PKCS #11 driver"), -+ NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); -+ g_object_class_install_property (object_class, PROP_MODULE_PATH, param_spec); -+} -+ -+static void -+gdm_smartcard_manager_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ GdmSmartcardManager *manager = GDM_SMARTCARD_MANAGER (object); + -+ switch (prop_id) { -+ case PROP_MODULE_PATH: -+ gdm_smartcard_manager_set_module_path (manager, -+ g_value_get_string (value)); -+ break; ++ gdm_smartcard_signals[INSERTED] = ++ g_signal_new ("inserted", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmSmartcardClass, ++ inserted), ++ NULL, NULL, g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); + -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } ++ gdm_smartcard_signals[REMOVED] = ++ g_signal_new ("removed", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmSmartcardClass, ++ removed), ++ NULL, NULL, g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); +} + +static void -+gdm_smartcard_manager_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) ++gdm_smartcard_class_install_properties (GdmSmartcardClass *card_class) +{ -+ GdmSmartcardManager *manager = GDM_SMARTCARD_MANAGER (object); -+ char *module_path; -+ -+ switch (prop_id) { -+ case PROP_MODULE_PATH: -+ module_path = gdm_smartcard_manager_get_module_path (manager); -+ g_value_set_string (value, module_path); -+ g_free (module_path); -+ break; ++ GObjectClass *object_class; ++ GParamSpec *param_spec; + -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} ++ object_class = G_OBJECT_CLASS (card_class); ++ object_class->set_property = gdm_smartcard_set_property; ++ object_class->get_property = gdm_smartcard_get_property; + -+char * -+gdm_smartcard_manager_get_module_path (GdmSmartcardManager *manager) -+{ -+ return manager->priv->module_path; -+} ++ param_spec = g_param_spec_ulong ("slot-id", _("Slot ID"), ++ _("The slot the card is in"), ++ 1, G_MAXULONG, ++ GDM_SMARTCARD_DEFAULT_SLOT_ID, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); ++ g_object_class_install_property (object_class, PROP_SLOT_ID, param_spec); + -+static void -+gdm_smartcard_manager_set_module_path (GdmSmartcardManager *manager, -+ const char *module_path) -+{ -+ if ((manager->priv->module_path == NULL) && (module_path == NULL)) { -+ return; -+ } ++ param_spec = g_param_spec_int ("slot-series", _("Slot Series"), ++ _("per-slot card identifier"), ++ -1, G_MAXINT, ++ GDM_SMARTCARD_DEFAULT_SLOT_SERIES, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); ++ g_object_class_install_property (object_class, PROP_SLOT_SERIES, param_spec); + -+ if (((manager->priv->module_path == NULL) || -+ (module_path == NULL) || -+ (strcmp (manager->priv->module_path, module_path) != 0))) { -+ g_free (manager->priv->module_path); -+ manager->priv->module_path = g_strdup (module_path); -+ g_object_notify (G_OBJECT (manager), "module-path"); -+ } -+} ++ param_spec = g_param_spec_string ("name", _("name"), ++ _("name"), NULL, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); ++ g_object_class_install_property (object_class, PROP_NAME, param_spec); + -+static void -+gdm_smartcard_manager_card_removed_handler (GdmSmartcardManager *manager, -+ GdmSmartcard *card) -+{ -+ g_debug ("informing smartcard of its removal"); -+ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_REMOVED); -+ g_debug ("done"); ++ param_spec = g_param_spec_pointer ("module", _("Module"), ++ _("smartcard driver"), ++ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); ++ g_object_class_install_property (object_class, PROP_MODULE, param_spec); +} + +static void -+gdm_smartcard_manager_card_inserted_handler (GdmSmartcardManager *manager, -+ GdmSmartcard *card) ++gdm_smartcard_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) +{ -+ g_debug ("informing smartcard of its insertion"); -+ -+ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_INSERTED); -+ g_debug ("done"); -+ -+} ++ GdmSmartcard *card = GDM_SMARTCARD (object); + -+static void -+gdm_smartcard_manager_class_install_signals (GdmSmartcardManagerClass *manager_class) -+{ -+ GObjectClass *object_class; ++ switch (prop_id) { ++ case PROP_NAME: ++ gdm_smartcard_set_name (card, g_value_get_string (value)); ++ break; + -+ object_class = G_OBJECT_CLASS (manager_class); ++ case PROP_SLOT_ID: ++ gdm_smartcard_set_slot_id (card, ++ g_value_get_ulong (value)); ++ break; + -+ gdm_smartcard_manager_signals[SMARTCARD_INSERTED] = -+ g_signal_new ("smartcard-inserted", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmSmartcardManagerClass, -+ smartcard_inserted), -+ NULL, NULL, g_cclosure_marshal_VOID__POINTER, -+ G_TYPE_NONE, 1, G_TYPE_POINTER); -+ manager_class->smartcard_inserted = gdm_smartcard_manager_card_inserted_handler; ++ case PROP_SLOT_SERIES: ++ gdm_smartcard_set_slot_series (card, ++ g_value_get_int (value)); ++ break; + -+ gdm_smartcard_manager_signals[SMARTCARD_REMOVED] = -+ g_signal_new ("smartcard-removed", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmSmartcardManagerClass, -+ smartcard_removed), -+ NULL, NULL, g_cclosure_marshal_VOID__POINTER, -+ G_TYPE_NONE, 1, G_TYPE_POINTER); -+ manager_class->smartcard_removed = gdm_smartcard_manager_card_removed_handler; ++ case PROP_MODULE: ++ gdm_smartcard_set_module (card, ++ (SECMODModule *) ++ g_value_get_pointer (value)); ++ break; + -+ gdm_smartcard_manager_signals[ERROR] = -+ g_signal_new ("error", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmSmartcardManagerClass, error), -+ NULL, NULL, g_cclosure_marshal_VOID__POINTER, -+ G_TYPE_NONE, 1, G_TYPE_POINTER); -+ manager_class->error = NULL; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } +} + -+static gboolean -+sc_slot_id_equal (CK_SLOT_ID *slot_id_1, -+ CK_SLOT_ID *slot_id_2) ++CK_SLOT_ID ++gdm_smartcard_get_slot_id (GdmSmartcard *card) +{ -+ g_assert (slot_id_1 != NULL); -+ g_assert (slot_id_2 != NULL); -+ -+ return *slot_id_1 == *slot_id_2; ++ return card->priv->slot_id; +} + -+static gboolean -+sc_slot_id_hash (CK_SLOT_ID *slot_id) -+{ -+ guint32 upper_bits, lower_bits; -+ gint temp; -+ -+ if (sizeof (CK_SLOT_ID) == sizeof (gint)) { -+ return g_int_hash (slot_id); -+ } -+ -+ upper_bits = ((*slot_id) >> 31) - 1; -+ lower_bits = (*slot_id) & 0xffffffff; -+ -+ /* The upper bits are almost certainly always zero, -+ * so let's degenerate to g_int_hash for the -+ * (very) common case -+ */ -+ temp = lower_bits + upper_bits; -+ return upper_bits + g_int_hash (&temp); ++GdmSmartcardState ++gdm_smartcard_get_state (GdmSmartcard *card) ++{ ++ return card->priv->state; +} + -+static void -+gdm_smartcard_manager_init (GdmSmartcardManager *manager) ++char * ++gdm_smartcard_get_name (GdmSmartcard *card) +{ -+ g_debug ("initializing smartcard manager"); ++ return g_strdup (card->priv->name); ++} + -+ manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, -+ GDM_TYPE_SMARTCARD_MANAGER, -+ GdmSmartcardManagerPrivate); -+ manager->priv->poll_timeout_id = 0; -+ manager->priv->is_unstoppable = FALSE; -+ manager->priv->module = NULL; ++gboolean ++gdm_smartcard_is_login_card (GdmSmartcard *card) ++{ ++ const char *login_card_name; ++ login_card_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME"); + -+ manager->priv->smartcards = -+ g_hash_table_new_full (g_str_hash, -+ g_str_equal, -+ (GDestroyNotify) g_free, -+ (GDestroyNotify) g_object_unref); ++ if ((login_card_name == NULL) || (card->priv->name == NULL)) { ++ return FALSE; ++ } + -+ if (!g_thread_supported()) { -+ g_thread_init (NULL); ++ if (strcmp (card->priv->name, login_card_name) == 0) { ++ return TRUE; + } + ++ return FALSE; +} + +static void -+gdm_smartcard_manager_finalize (GObject *object) ++gdm_smartcard_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) +{ -+ GdmSmartcardManager *manager; -+ GObjectClass *gobject_class; ++ GdmSmartcard *card = GDM_SMARTCARD (object); + -+ manager = GDM_SMARTCARD_MANAGER (object); -+ gobject_class = -+ G_OBJECT_CLASS (gdm_smartcard_manager_parent_class); ++ switch (prop_id) { ++ case PROP_NAME: ++ g_value_take_string (value, ++ gdm_smartcard_get_name (card)); ++ break; + -+ gdm_smartcard_manager_stop_now (manager); ++ case PROP_SLOT_ID: ++ g_value_set_ulong (value, ++ (gulong) gdm_smartcard_get_slot_id (card)); ++ break; + -+ g_hash_table_destroy (manager->priv->smartcards); -+ manager->priv->smartcards = NULL; ++ case PROP_SLOT_SERIES: ++ g_value_set_int (value, ++ gdm_smartcard_get_slot_series (card)); ++ break; + -+ gobject_class->finalize (object); ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } +} + -+GQuark -+gdm_smartcard_manager_error_quark (void) ++static void ++gdm_smartcard_set_name (GdmSmartcard *card, ++ const char *name) +{ -+ static GQuark error_quark = 0; -+ -+ if (error_quark == 0) { -+ error_quark = g_quark_from_static_string ("gdm-smartcard-manager-error-quark"); ++ if (name == NULL) { ++ return; + } + -+ return error_quark; -+} ++ if ((card->priv->name == NULL) || ++ (strcmp (card->priv->name, name) != 0)) { ++ g_free (card->priv->name); ++ card->priv->name = g_strdup (name); + -+GdmSmartcardManager * -+gdm_smartcard_manager_new (const char *module_path) -+{ -+ GdmSmartcardManager *instance; ++ if (card->priv->slot == NULL) { ++ card->priv->slot = gdm_smartcard_find_slot_from_card_name (card, ++ card->priv->name); + -+ instance = GDM_SMARTCARD_MANAGER (g_object_new (GDM_TYPE_SMARTCARD_MANAGER, -+ "module-path", module_path, -+ NULL)); ++ if (card->priv->slot != NULL) { ++ int slot_id, slot_series; + -+ return instance; -+} ++ slot_id = PK11_GetSlotID (card->priv->slot); ++ if (slot_id != card->priv->slot_id) { ++ gdm_smartcard_set_slot_id (card, slot_id); ++ } + -+static void -+gdm_smartcard_manager_emit_error (GdmSmartcardManager *manager, -+ GError *error) -+{ -+ manager->priv->is_unstoppable = TRUE; -+ g_signal_emit (manager, gdm_smartcard_manager_signals[ERROR], 0, -+ error); -+ manager->priv->is_unstoppable = FALSE; -+} ++ slot_series = PK11_GetSlotSeries (card->priv->slot); ++ if (slot_series != card->priv->slot_series) { ++ gdm_smartcard_set_slot_series (card, slot_series); ++ } + -+static void -+gdm_smartcard_manager_emit_smartcard_inserted (GdmSmartcardManager *manager, -+ GdmSmartcard *card) -+{ -+ manager->priv->is_unstoppable = TRUE; -+ g_signal_emit (manager, gdm_smartcard_manager_signals[SMARTCARD_INSERTED], 0, -+ card); -+ manager->priv->is_unstoppable = FALSE; ++ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_INSERTED); ++ } else { ++ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_REMOVED); ++ } ++ } ++ ++ g_object_notify (G_OBJECT (card), "name"); ++ } +} + +static void -+gdm_smartcard_manager_emit_smartcard_removed (GdmSmartcardManager *manager, -+ GdmSmartcard *card) ++gdm_smartcard_set_slot_id (GdmSmartcard *card, ++ int slot_id) +{ -+ GdmSmartcardManagerState old_state; ++ if (card->priv->slot_id != slot_id) { ++ card->priv->slot_id = slot_id; + -+ old_state = manager->priv->state; -+ manager->priv->is_unstoppable = TRUE; -+ g_signal_emit (manager, gdm_smartcard_manager_signals[SMARTCARD_REMOVED], 0, -+ card); -+ manager->priv->is_unstoppable = FALSE; -+} ++ if (card->priv->slot == NULL) { ++ card->priv->slot = gdm_smartcard_find_slot_from_id (card, ++ card->priv->slot_id); + -+static gboolean -+gdm_smartcard_manager_check_for_and_process_events (GIOChannel *io_channel, -+ GIOCondition condition, -+ GdmSmartcardManager *manager) -+{ -+ GdmSmartcard *card; -+ gboolean should_stop; -+ guchar event_type; -+ char *card_name; -+ gint fd; ++ if (card->priv->slot != NULL) { ++ const char *card_name; + -+ card = NULL; -+ should_stop = (condition & G_IO_HUP) || (condition & G_IO_ERR); ++ card_name = PK11_GetTokenName (card->priv->slot); ++ if ((card->priv->name == NULL) || ++ ((card_name != NULL) && ++ (strcmp (card_name, card->priv->name) != 0))) { ++ gdm_smartcard_set_name (card, card_name); ++ } + -+ if (should_stop) { -+ g_debug ("received %s on event socket, stopping " -+ "manager...", -+ (condition & G_IO_HUP) && (condition & G_IO_ERR)? -+ "error and hangup" : -+ (condition & G_IO_HUP)? -+ "hangup" : "error"); -+ } ++ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_INSERTED); ++ } else { ++ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_REMOVED); ++ } ++ } + -+ if (!(condition & G_IO_IN)) { -+ goto out; ++ g_object_notify (G_OBJECT (card), "slot-id"); + } ++} + -+ fd = g_io_channel_unix_get_fd (io_channel); -+ -+ event_type = '\0'; -+ if (!sc_read_bytes (fd, &event_type, 1)) { -+ should_stop = TRUE; -+ goto out; ++static void ++gdm_smartcard_set_slot_series (GdmSmartcard *card, ++ int slot_series) ++{ ++ if (card->priv->slot_series != slot_series) { ++ card->priv->slot_series = slot_series; ++ g_object_notify (G_OBJECT (card), "slot-series"); + } ++} + -+ card = sc_read_smartcard (fd, manager->priv->module); ++static void ++gdm_smartcard_set_module (GdmSmartcard *card, ++ SECMODModule *module) ++{ ++ gboolean should_notify; + -+ if (card == NULL) { -+ should_stop = TRUE; -+ goto out; ++ if (card->priv->module != module) { ++ should_notify = TRUE; ++ } else { ++ should_notify = FALSE; + } + -+ card_name = gdm_smartcard_get_name (card); -+ -+ switch (event_type) { -+ case 'I': -+ g_hash_table_replace (manager->priv->smartcards, -+ card_name, card); -+ card_name = NULL; -+ -+ gdm_smartcard_manager_emit_smartcard_inserted (manager, card); -+ card = NULL; -+ break; -+ -+ case 'R': -+ gdm_smartcard_manager_emit_smartcard_removed (manager, card); -+ if (!g_hash_table_remove (manager->priv->smartcards, card_name)) { -+ g_debug ("got removal event of unknown card!"); -+ } -+ g_free (card_name); -+ card_name = NULL; -+ card = NULL; -+ break; -+ -+ default: -+ g_free (card_name); -+ card_name = NULL; -+ g_object_unref (card); -+ -+ should_stop = TRUE; -+ break; ++ if (card->priv->module != NULL) { ++ SECMOD_DestroyModule (card->priv->module); ++ card->priv->module = NULL; + } + -+out: -+ if (should_stop) { -+ GError *error; -+ -+ error = g_error_new (GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, -+ "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source")); ++ if (module != NULL) { ++ card->priv->module = SECMOD_ReferenceModule (module); ++ } + -+ gdm_smartcard_manager_emit_error (manager, error); -+ g_error_free (error); -+ gdm_smartcard_manager_stop_now (manager); -+ return FALSE; ++ if (should_notify) { ++ g_object_notify (G_OBJECT (card), "module"); + } -+ -+ return TRUE; +} + -+static void -+gdm_smartcard_manager_event_processing_stopped_handler (GdmSmartcardManager *manager) ++int ++gdm_smartcard_get_slot_series (GdmSmartcard *card) +{ -+ manager->priv->smartcard_event_source = NULL; -+ gdm_smartcard_manager_stop_now (manager); ++ return card->priv->slot_series; +} + -+static gboolean -+gdm_open_pipe (gint *write_fd, -+ gint *read_fd) ++static void ++gdm_smartcard_init (GdmSmartcard *card) +{ -+ gint pipe_fds[2] = { -1, -1 }; + -+ g_assert (write_fd != NULL); -+ g_assert (read_fd != NULL); ++ g_debug ("initializing smartcard "); + -+ if (pipe (pipe_fds) < 0) { -+ return FALSE; -+ } ++ card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card, ++ GDM_TYPE_SMARTCARD, ++ GdmSmartcardPrivate); + -+ if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) { -+ close (pipe_fds[0]); -+ close (pipe_fds[1]); -+ return FALSE; ++ if (card->priv->slot != NULL) { ++ card->priv->name = g_strdup (PK11_GetTokenName (card->priv->slot)); + } ++} + -+ if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) { -+ close (pipe_fds[0]); -+ close (pipe_fds[1]); -+ return FALSE; -+ } ++static void gdm_smartcard_finalize (GObject *object) ++{ ++ GdmSmartcard *card; ++ GObjectClass *gobject_class; + -+ *read_fd = pipe_fds[0]; -+ *write_fd = pipe_fds[1]; ++ card = GDM_SMARTCARD (object); + -+ return TRUE; ++ g_free (card->priv->name); ++ ++ gdm_smartcard_set_module (card, NULL); ++ ++ gobject_class = G_OBJECT_CLASS (gdm_smartcard_parent_class); ++ ++ gobject_class->finalize (object); +} + -+static void -+gdm_smartcard_manager_stop_watching_for_events (GdmSmartcardManager *manager) ++GQuark gdm_smartcard_error_quark (void) +{ -+ if (manager->priv->smartcard_event_source != NULL) { -+ g_source_destroy (manager->priv->smartcard_event_source); -+ manager->priv->smartcard_event_source = NULL; -+ } ++ static GQuark error_quark = 0; + -+ if (manager->priv->worker_thread != NULL) { -+ SECMOD_CancelWait (manager->priv->module); -+ /* FIXME: The function above doesn't seem to -+ * always wake up WaitForAnyTokenEvent -+ */ -+ exit (0); -+ g_thread_join (manager->priv->worker_thread); -+ manager->priv->worker_thread = NULL; ++ if (error_quark == 0) { ++ error_quark = g_quark_from_static_string ("gdm-smartcard-error-quark"); + } ++ ++ return error_quark; +} + -+static gboolean -+sc_load_nss (GError **error) ++GdmSmartcard * ++_gdm_smartcard_new (SECMODModule *module, ++ CK_SLOT_ID slot_id, ++ int slot_series) +{ -+ SECStatus status = SECSuccess; -+ static const guint32 flags = -+ NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | -+ NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | -+ NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD; ++ GdmSmartcard *card; + -+ g_debug ("attempting to load NSS database '%s'", -+ GDM_SMARTCARD_MANAGER_NSS_DB); ++ g_return_val_if_fail (module != NULL, NULL); ++ g_return_val_if_fail (slot_id >= 1, NULL); ++ g_return_val_if_fail (slot_series > 0, NULL); ++ g_return_val_if_fail (sizeof (gulong) == sizeof (slot_id), NULL); + -+ status = NSS_Initialize (GDM_SMARTCARD_MANAGER_NSS_DB, -+ "", "", SECMOD_DB, flags); ++ card = GDM_SMARTCARD (g_object_new (GDM_TYPE_SMARTCARD, ++ "module", module, ++ "slot-id", (gulong) slot_id, ++ "slot-series", slot_series, ++ NULL)); ++ return card; ++} + -+ if (status != SECSuccess) { -+ gsize error_message_size; -+ char *error_message; ++GdmSmartcard * ++_gdm_smartcard_new_from_name (SECMODModule *module, ++ const char *name) ++{ ++ GdmSmartcard *card; + -+ error_message_size = PR_GetErrorTextLength (); ++ g_return_val_if_fail (module != NULL, NULL); ++ g_return_val_if_fail (name != NULL, NULL); + -+ if (error_message_size == 0) { -+ g_debug ("NSS security system could not be initialized"); -+ g_set_error (error, -+ GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_WITH_NSS, -+ _("NSS security system could not be initialized")); -+ goto out; ++ card = GDM_SMARTCARD (g_object_new (GDM_TYPE_SMARTCARD, ++ "module", module, ++ "name", name, ++ NULL)); ++ return card; ++} ++ ++void ++_gdm_smartcard_set_state (GdmSmartcard *card, ++ GdmSmartcardState state) ++{ ++ /* gdm_smartcard_fetch_certificates (card); */ ++ if (card->priv->state != state) { ++ card->priv->state = state; ++ ++ if (state == GDM_SMARTCARD_STATE_INSERTED) { ++ g_signal_emit (card, gdm_smartcard_signals[INSERTED], 0); ++ } else if (state == GDM_SMARTCARD_STATE_REMOVED) { ++ g_signal_emit (card, gdm_smartcard_signals[REMOVED], 0); ++ } else { ++ g_assert_not_reached (); + } ++ } ++} + -+ error_message = g_slice_alloc0 (error_message_size); -+ PR_GetErrorText (error_message); ++/* So we could conceivably make the closure data a pointer to the card ++ * or something similiar and then emit signals when we want passwords, ++ * but it's probably easier to just get the password up front and use ++ * it. So we just take the passed in g_malloc'd (well probably, who knows) ++ * and strdup it using NSPR's memory allocation routines. ++ */ ++static char * ++gdm_smartcard_password_handler (PK11SlotInfo *slot, ++ PRBool is_retrying, ++ const char *password) ++{ ++ if (is_retrying) { ++ return NULL; ++ } + -+ g_set_error (error, -+ GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_WITH_NSS, -+ "%s", error_message); -+ g_debug ("NSS security system could not be initialized - %s", -+ error_message); ++ return password != NULL? PL_strdup (password): NULL; ++} + -+ g_slice_free1 (error_message_size, error_message); ++gboolean ++gdm_smartcard_unlock (GdmSmartcard *card, ++ const char *password) ++{ ++ SECStatus status; + -+ goto out; -+ } ++ PK11_SetPasswordFunc ((PK11PasswordFunc) gdm_smartcard_password_handler); + -+ g_debug ("NSS database sucessfully loaded"); -+ return TRUE; ++ /* we pass PR_TRUE to load certificates ++ */ ++ status = PK11_Authenticate (card->priv->slot, PR_TRUE, (gpointer) password); + -+out: -+ g_debug ("NSS database couldn't be sucessfully loaded"); -+ return FALSE; ++ if (status != SECSuccess) { ++ g_debug ("could not unlock card - %d", status); ++ return FALSE; ++ } ++ return TRUE; +} + -+static SECMODModule * -+load_driver (char *module_path, -+ GError **error) ++static PK11SlotInfo * ++gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, ++ const char *card_name) +{ -+ SECMODModule *module; -+ char *module_spec; -+ gboolean module_explicitly_specified; -+ -+ g_debug ("attempting to load driver..."); ++ int i; + -+ module = NULL; -+ module_explicitly_specified = module_path != NULL; -+ if (module_explicitly_specified) { -+ module_spec = g_strdup_printf ("library=\"%s\"", module_path); -+ g_debug ("loading smartcard driver using spec '%s'", -+ module_spec); ++ for (i = 0; i < card->priv->module->slotCount; i++) { ++ const char *slot_card_name; + -+ module = SECMOD_LoadUserModule (module_spec, -+ NULL /* parent */, -+ FALSE /* recurse */); -+ g_free (module_spec); -+ module_spec = NULL; ++ slot_card_name = PK11_GetTokenName (card->priv->module->slots[i]); + -+ } else { -+ SECMODModuleList *modules, *tmp; ++ if ((slot_card_name != NULL) && ++ (strcmp (slot_card_name, card_name) == 0)) { ++ return card->priv->module->slots[i]; ++ } ++ } + -+ modules = SECMOD_GetDefaultModuleList (); ++ return NULL; ++} + -+ for (tmp = modules; tmp != NULL; tmp = tmp->next) { -+ if (!SECMOD_HasRemovableSlots (tmp->module) || -+ !tmp->module->loaded) -+ continue; ++static PK11SlotInfo * ++gdm_smartcard_find_slot_from_id (GdmSmartcard *card, ++ int slot_id) ++{ ++ int i; + -+ module = SECMOD_ReferenceModule (tmp->module); -+ break; ++ for (i = 0; i < card->priv->module->slotCount; i++) { ++ if (PK11_GetSlotID (card->priv->module->slots[i]) == slot_id) { ++ return card->priv->module->slots[i]; + } ++ } + -+ /* fallback to compiled in driver path -+ */ -+ if (module == NULL) { -+ module_path = GDM_SMARTCARD_MANAGER_DRIVER; -+ module_spec = g_strdup_printf ("library=\"%s\"", module_path); -+ g_debug ("loading smartcard driver using spec '%s'", -+ module_spec); ++ return NULL; ++} +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c 2009-03-03 17:45:05.820018029 -0500 +@@ -0,0 +1,440 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ * ++ */ + -+ module = SECMOD_LoadUserModule (module_spec, -+ NULL /* parent */, -+ FALSE /* recurse */); -+ g_free (module_spec); -+ module_spec = NULL; -+ } ++#include ++#include "gdm-smartcard-extension.h" ++#include "gdm-conversation.h" ++#include "gdm-task.h" + -+ } ++#include ++#include ++#include ++#include ++#include + -+ if (!module_explicitly_specified && module == NULL) { -+ g_set_error (error, -+ GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, -+ _("no suitable smartcard driver could be found")); -+ } else if (module == NULL || !module->loaded) { ++#include ++#include ++#include + -+ gsize error_message_size; -+ char *error_message; ++#ifndef GDM_SMARTCARD_WORKER_COMMAND ++#define GDM_SMARTCARD_WORKER_COMMAND LIBEXECDIR "/gdm-smartcard-worker" ++#endif + -+ if (module != NULL && !module->loaded) { -+ g_debug ("module found but not loaded?!"); -+ SECMOD_DestroyModule (module); -+ module = NULL; -+ } ++struct _GdmSmartcardExtensionPrivate ++{ ++ GIcon *icon; ++ GtkWidget *page; ++ GtkActionGroup *actions; ++ GtkAction *login_action; + -+ error_message_size = PR_GetErrorTextLength (); ++ GtkWidget *message_label; ++ GtkWidget *prompt_label; ++ GtkWidget *prompt_entry; + -+ if (error_message_size == 0) { -+ g_debug ("smartcard driver '%s' could not be loaded", -+ module_path); -+ g_set_error (error, -+ GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, -+ _("smartcard driver '%s' could not be " -+ "loaded"), module_path); -+ goto out; -+ } ++ GPid worker_pid; ++ int number_of_tokens; + -+ error_message = g_slice_alloc0 (error_message_size); -+ PR_GetErrorText (error_message); ++ guint answer_pending : 1; ++ guint select_when_ready : 1; ++}; + -+ g_set_error (error, -+ GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, -+ "%s", error_message); ++static void gdm_smartcard_extension_finalize (GObject *object); + -+ g_debug ("smartcard driver '%s' could not be loaded - %s", -+ module_path, error_message); -+ g_slice_free1 (error_message_size, error_message); -+ } ++static void gdm_task_iface_init (GdmTaskIface *iface); ++static void gdm_conversation_iface_init (GdmConversationIface *iface); ++static void gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface); + -+out: -+ return module; -+} ++G_DEFINE_TYPE_WITH_CODE (GdmSmartcardExtension, ++ gdm_smartcard_extension, ++ G_TYPE_OBJECT, ++ G_IMPLEMENT_INTERFACE (GDM_TYPE_GREETER_EXTENSION, ++ gdm_greeter_extension_iface_init) ++ G_IMPLEMENT_INTERFACE (GDM_TYPE_TASK, ++ gdm_task_iface_init) ++ G_IMPLEMENT_INTERFACE (GDM_TYPE_CONVERSATION, ++ gdm_conversation_iface_init)); + -+static void -+gdm_smartcard_manager_get_all_cards (GdmSmartcardManager *manager) ++static gboolean ++on_smartcard_event (GIOChannel *io_channel, ++ GIOCondition condition, ++ gpointer data) +{ -+ int i; -+ -+ for (i = 0; i < manager->priv->module->slotCount; i++) { -+ GdmSmartcard *card; -+ CK_SLOT_ID slot_id; -+ gint slot_series; -+ char *card_name; -+ -+ slot_id = PK11_GetSlotID (manager->priv->module->slots[i]); -+ slot_series = PK11_GetSlotSeries (manager->priv->module->slots[i]); ++ GdmSmartcardExtension *extension; + -+ card = _gdm_smartcard_new (manager->priv->module, -+ slot_id, slot_series); ++ extension = GDM_SMARTCARD_EXTENSION (data); + -+ card_name = gdm_smartcard_get_name (card); ++ if (condition & G_IO_IN) { ++ char buffer[1024]; ++ ssize_t num_bytes; + -+ g_hash_table_replace (manager->priv->smartcards, -+ card_name, card); -+ } -+} ++ num_bytes = read (g_io_channel_unix_get_fd (io_channel), ++ buffer, sizeof (buffer)); + -+gboolean -+gdm_smartcard_manager_start (GdmSmartcardManager *manager, -+ GError **error) -+{ -+ GError *watching_error; -+ gint worker_fd; -+ GPid worker_pid; -+ GIOChannel *io_channel; -+ GSource *source; -+ GIOFlags channel_flags; -+ GError *nss_error; ++ if (num_bytes < 0 && errno != EINTR) ++ return FALSE; + -+ if (manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STARTED) { -+ g_debug ("smartcard manager already started"); -+ return TRUE; -+ } ++ if (num_bytes != 1) { ++ g_debug ("buffer: %s\n", buffer); ++ return TRUE; ++ } + -+ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STARTING; ++ if (buffer[0] == 'I') { ++ extension->priv->number_of_tokens++; ++ } else { ++ extension->priv->number_of_tokens--; ++ } + -+ worker_fd = -1; -+ worker_pid = 0; ++ if (extension->priv->number_of_tokens == 1) { ++ if (!gdm_conversation_choose_user (GDM_CONVERSATION (extension), ++ PAMSERVICENAME)) { ++ g_debug ("could not choose smart card user, cancelling..."); ++ gdm_conversation_cancel (GDM_CONVERSATION (extension)); ++ extension->priv->select_when_ready = TRUE; ++ } else { ++ g_debug ("chose smart card user!"); ++ } ++ } else if (extension->priv->number_of_tokens == 0) { ++ gdm_conversation_cancel (GDM_CONVERSATION (extension)); ++ } + -+ nss_error = NULL; -+ if (!manager->priv->nss_is_loaded && !sc_load_nss (&nss_error)) { -+ g_propagate_error (error, nss_error); -+ goto out; ++ return TRUE; + } -+ manager->priv->nss_is_loaded = TRUE; + -+ if (manager->priv->module == NULL) { -+ manager->priv->module = load_driver (manager->priv->module_path, &nss_error); ++ if (condition & G_IO_HUP) { ++ return FALSE; + } + -+ if (manager->priv->module == NULL) { -+ g_propagate_error (error, nss_error); -+ goto out; -+ } ++ return TRUE; ++} + -+ if (!gdm_smartcard_manager_create_worker (manager, &worker_fd, &manager->priv->worker_thread)) { ++static void ++watch_for_smartcards (GdmSmartcardExtension *extension) ++{ ++ GError *error; ++ GIOChannel *io_channel; ++ char *args[] = { GDM_SMARTCARD_WORKER_COMMAND, NULL }; ++ GPid pid; ++ int stdout_fd; + -+ g_set_error (error, -+ GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, -+ _("could not watch for incoming card events - %s"), -+ g_strerror (errno)); ++ error = NULL; + -+ goto out; ++ if (!g_spawn_async_with_pipes (NULL, args, NULL, 0, ++ NULL, NULL, &pid, NULL, ++ &stdout_fd, NULL, &error)) { ++ g_debug ("could not start smart card manager: %s", error->message); ++ g_error_free (error); ++ return; + } ++ fcntl (stdout_fd, F_SETFD, FD_CLOEXEC); + -+ io_channel = g_io_channel_unix_new (worker_fd); -+ -+ channel_flags = g_io_channel_get_flags (io_channel); -+ watching_error = NULL; -+ -+ source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP); ++ io_channel = g_io_channel_unix_new (stdout_fd); ++ g_io_channel_set_flags (io_channel, G_IO_FLAG_NONBLOCK, NULL); ++ g_io_channel_set_encoding (io_channel, NULL, NULL); ++ g_io_channel_set_buffered (io_channel, FALSE); ++ g_io_add_watch (io_channel, G_IO_IN, on_smartcard_event, extension); ++ g_io_channel_set_close_on_unref (io_channel, TRUE); + g_io_channel_unref (io_channel); -+ io_channel = NULL; + -+ manager->priv->smartcard_event_source = source; ++ extension->priv->worker_pid = pid; ++} + -+ g_source_set_callback (manager->priv->smartcard_event_source, -+ (GSourceFunc) (GIOFunc) -+ gdm_smartcard_manager_check_for_and_process_events, -+ manager, -+ (GDestroyNotify) -+ gdm_smartcard_manager_event_processing_stopped_handler); -+ g_source_attach (manager->priv->smartcard_event_source, NULL); -+ g_source_unref (manager->priv->smartcard_event_source); ++static void ++gdm_smartcard_extension_set_message (GdmConversation *conversation, ++ const char *message) ++{ ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ gtk_widget_show (extension->priv->message_label); ++ gtk_label_set_text (GTK_LABEL (extension->priv->message_label), message); ++} + -+ /* populate the hash with cards that are already inserted -+ */ -+ gdm_smartcard_manager_get_all_cards (manager); ++static void ++gdm_smartcard_extension_ask_question (GdmConversation *conversation, ++ const char *message) ++{ ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ gtk_widget_show (extension->priv->prompt_label); ++ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); ++ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); ++ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); ++ gtk_widget_show (extension->priv->prompt_entry); ++ gtk_action_set_visible (extension->priv->login_action, TRUE); ++ gtk_widget_grab_focus (extension->priv->prompt_entry); ++ extension->priv->answer_pending = TRUE; ++} ++ ++static void ++gdm_smartcard_extension_ask_secret (GdmConversation *conversation, ++ const char *message) ++{ ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ gtk_widget_show (extension->priv->prompt_label); ++ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), message); ++ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), FALSE); ++ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); ++ gtk_widget_show (extension->priv->prompt_entry); ++ gtk_widget_grab_focus (extension->priv->prompt_entry); ++ gtk_action_set_visible (extension->priv->login_action, TRUE); ++ extension->priv->answer_pending = TRUE; ++} + -+ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STARTED; ++static void ++gdm_smartcard_extension_reset (GdmConversation *conversation) ++{ ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ gtk_widget_hide (extension->priv->prompt_label); ++ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); + -+out: -+ /* don't leave it in a half started state -+ */ -+ if (manager->priv->state != GDM_SMARTCARD_MANAGER_STATE_STARTED) { -+ g_debug ("smartcard manager could not be completely started"); -+ gdm_smartcard_manager_stop (manager); -+ } else { -+ g_debug ("smartcard manager started"); -+ } ++ gtk_widget_hide (extension->priv->prompt_entry); ++ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); ++ gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); ++ gtk_action_set_visible (extension->priv->login_action, FALSE); ++ extension->priv->answer_pending = FALSE; + -+ return manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STARTED; ++ gdm_task_set_enabled (GDM_TASK (conversation), FALSE); +} + -+static gboolean -+gdm_smartcard_manager_stop_now (GdmSmartcardManager *manager) ++static void ++gdm_smartcard_extension_set_ready (GdmConversation *conversation) +{ -+ if (manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STOPPED) { -+ return FALSE; -+ } -+ -+ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STOPPED; -+ gdm_smartcard_manager_stop_watching_for_events (manager); ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ gdm_task_set_enabled (GDM_TASK (conversation), TRUE); + -+ if (manager->priv->module != NULL) { -+ SECMOD_DestroyModule (manager->priv->module); -+ manager->priv->module = NULL; ++ if (extension->priv->worker_pid <= 0) { ++ watch_for_smartcards (extension); + } + -+ if (manager->priv->nss_is_loaded) { -+ NSS_Shutdown (); -+ manager->priv->nss_is_loaded = FALSE; ++ if (extension->priv->select_when_ready) { ++ if (gdm_conversation_choose_user (GDM_CONVERSATION (extension), ++ PAMSERVICENAME)) { ++ extension->priv->select_when_ready = FALSE; ++ } + } ++} + -+ g_debug ("smartcard manager stopped"); -+ -+ return FALSE; ++char * ++gdm_smartcard_extension_get_service_name (GdmConversation *conversation) ++{ ++ return g_strdup (PAMSERVICENAME); +} + -+static void -+gdm_smartcard_manager_queue_stop (GdmSmartcardManager *manager) ++GtkWidget * ++gdm_smartcard_extension_get_page (GdmConversation *conversation) +{ ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ return extension->priv->page; ++} + -+ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STOPPING; ++GtkActionGroup * ++gdm_smartcard_extension_get_actions (GdmConversation *conversation) ++{ ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); + -+ g_idle_add ((GSourceFunc) gdm_smartcard_manager_stop_now, manager); ++ return g_object_ref (extension->priv->actions); +} + +void -+gdm_smartcard_manager_stop (GdmSmartcardManager *manager) ++gdm_smartcard_extension_request_answer (GdmConversation *conversation) +{ -+ if (manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STOPPED) { -+ return; -+ } ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); ++ const char *text; + -+ if (manager->priv->is_unstoppable) { -+ gdm_smartcard_manager_queue_stop (manager); ++ if (!extension->priv->answer_pending) { ++ gdm_conversation_answer (conversation, NULL); + return; + } + -+ gdm_smartcard_manager_stop_now (manager); ++ extension->priv->answer_pending = FALSE; ++ text = gtk_entry_get_text (GTK_ENTRY (extension->priv->prompt_entry)); ++ gdm_conversation_answer (conversation, text); ++ ++ gtk_widget_hide (extension->priv->prompt_entry); ++ gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); ++ gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); ++ gtk_action_set_visible (extension->priv->login_action, FALSE); +} + -+static void -+gdm_smartcard_manager_check_for_login_card (CK_SLOT_ID slot_id, -+ GdmSmartcard *card, -+ gboolean *is_inserted) ++gboolean ++gdm_smartcard_extension_focus (GdmConversation *conversation) +{ -+ g_assert (is_inserted != NULL); ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); + -+ if (gdm_smartcard_is_login_card (card)) { -+ *is_inserted = TRUE; ++ if (!extension->priv->answer_pending) { ++ return FALSE; + } + ++ gtk_widget_grab_focus (extension->priv->prompt_entry); ++ return TRUE; +} + -+gboolean -+gdm_smartcard_manager_login_card_is_inserted (GdmSmartcardManager *manager) ++GIcon * ++gdm_smartcard_extension_get_icon (GdmTask *task) ++{ ++ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (task); ++ return g_object_ref (extension->priv->icon); ++} + ++char * ++gdm_smartcard_extension_get_name (GdmTask *task) +{ -+ gboolean is_inserted; ++ return g_strdup (_("Smartcard Authentication")); ++} + -+ is_inserted = FALSE; -+ g_hash_table_foreach (manager->priv->smartcards, -+ (GHFunc) -+ gdm_smartcard_manager_check_for_login_card, -+ &is_inserted); -+ return is_inserted; ++char * ++gdm_smartcard_extension_get_description (GdmTask *task) ++{ ++ return g_strdup (_("Log into session with smartcard")); +} + -+static GdmSmartcardManagerWorker * -+gdm_smartcard_manager_worker_new (gint write_fd) ++gboolean ++gdm_smartcard_extension_is_choosable (GdmTask *task) +{ -+ GdmSmartcardManagerWorker *worker; ++ return TRUE; ++} + -+ worker = g_slice_new0 (GdmSmartcardManagerWorker); -+ worker->write_fd = write_fd; -+ worker->module = NULL; ++static void ++gdm_task_iface_init (GdmTaskIface *iface) ++{ ++ iface->get_icon = gdm_smartcard_extension_get_icon; ++ iface->get_description = gdm_smartcard_extension_get_description; ++ iface->get_name = gdm_smartcard_extension_get_name; ++ iface->is_choosable = gdm_smartcard_extension_is_choosable; ++} + -+ worker->smartcards = -+ g_hash_table_new_full ((GHashFunc) sc_slot_id_hash, -+ (GEqualFunc) sc_slot_id_equal, -+ (GDestroyNotify) g_free, -+ (GDestroyNotify) g_object_unref); ++static void ++gdm_conversation_iface_init (GdmConversationIface *iface) ++{ ++ iface->set_message = gdm_smartcard_extension_set_message; ++ iface->ask_question = gdm_smartcard_extension_ask_question; ++ iface->ask_secret = gdm_smartcard_extension_ask_secret; ++ iface->reset = gdm_smartcard_extension_reset; ++ iface->set_ready = gdm_smartcard_extension_set_ready; ++ iface->get_service_name = gdm_smartcard_extension_get_service_name; ++ iface->get_page = gdm_smartcard_extension_get_page; ++ iface->get_actions = gdm_smartcard_extension_get_actions; ++ iface->request_answer = gdm_smartcard_extension_request_answer; ++ iface->focus = gdm_smartcard_extension_focus; ++} + -+ return worker; ++static void ++gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) ++{ +} + +static void -+gdm_smartcard_manager_worker_free (GdmSmartcardManagerWorker *worker) ++gdm_smartcard_extension_class_init (GdmSmartcardExtensionClass *extension_class) +{ -+ if (worker->smartcards != NULL) { -+ g_hash_table_destroy (worker->smartcards); -+ worker->smartcards = NULL; -+ } ++ GObjectClass *object_class; + -+ g_slice_free (GdmSmartcardManagerWorker, worker); ++ object_class = G_OBJECT_CLASS (extension_class); ++ ++ object_class->finalize = gdm_smartcard_extension_finalize; ++ ++ g_type_class_add_private (extension_class, ++ sizeof (GdmSmartcardExtensionPrivate)); +} + -+static gboolean -+sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes) ++static void ++gdm_smartcard_extension_finalize (GObject *object) +{ -+ size_t bytes_left; -+ size_t total_bytes_read; -+ ssize_t bytes_read; -+ -+ bytes_left = (size_t) num_bytes; -+ total_bytes_read = 0; ++} + -+ do { -+ bytes_read = read (fd, bytes + total_bytes_read, bytes_left); -+ g_assert (bytes_read <= (ssize_t) bytes_left); ++static void ++create_page (GdmSmartcardExtension *extension) ++{ ++ GtkBuilder *builder; ++ GObject *object; ++ GError *error; + -+ if (bytes_read <= 0) { -+ if ((bytes_read < 0) && (errno == EINTR || errno == EAGAIN)) { -+ continue; -+ } ++ builder = gtk_builder_new (); + -+ bytes_left = 0; -+ } else { -+ bytes_left -= bytes_read; -+ total_bytes_read += bytes_read; -+ } -+ } while (bytes_left > 0); ++ error = NULL; ++ gtk_builder_add_from_file (builder, ++ PLUGINDATADIR "/page.ui", ++ &error); + -+ if (total_bytes_read < (size_t) num_bytes) { -+ return FALSE; ++ if (error != NULL) { ++ g_warning ("Could not load UI file: %s", error->message); ++ g_error_free (error); ++ return; + } + -+ return TRUE; ++ object = gtk_builder_get_object (builder, "page"); ++ g_object_ref (object); ++ ++ extension->priv->page = GTK_WIDGET (object); ++ ++ object = gtk_builder_get_object (builder, "auth-prompt-label"); ++ g_object_ref (object); ++ extension->priv->prompt_label = GTK_WIDGET (object); ++ gtk_widget_hide (extension->priv->prompt_label); ++ ++ object = gtk_builder_get_object (builder, "auth-prompt-entry"); ++ g_object_ref (object); ++ extension->priv->prompt_entry = GTK_WIDGET (object); ++ gtk_widget_hide (extension->priv->prompt_entry); ++ ++ object = gtk_builder_get_object (builder, "auth-message-label"); ++ g_object_ref (object); ++ extension->priv->message_label = GTK_WIDGET (object); ++ gtk_widget_show (extension->priv->message_label); ++ ++ g_object_unref (builder); +} + -+static gboolean -+sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes) ++static void ++on_activate_log_in (GdmSmartcardExtension *extension) +{ -+ size_t bytes_left; -+ size_t total_bytes_written; -+ ssize_t bytes_written; -+ -+ bytes_left = (size_t) num_bytes; -+ total_bytes_written = 0; -+ -+ do { -+ bytes_written = write (fd, bytes + total_bytes_written, bytes_left); -+ g_assert (bytes_written <= (ssize_t) bytes_left); ++ gdm_smartcard_extension_request_answer (GDM_CONVERSATION (extension)); ++} + -+ if (bytes_written <= 0) { -+ if ((bytes_written < 0) && (errno == EINTR || errno == EAGAIN)) { -+ continue; -+ } ++static void ++create_actions (GdmSmartcardExtension *extension) ++{ ++ GtkAction *action; + -+ bytes_left = 0; -+ } else { -+ bytes_left -= bytes_written; -+ total_bytes_written += bytes_written; -+ } -+ } while (bytes_left > 0); ++ extension->priv->actions = gtk_action_group_new ("gdm-smartcard-extension"); + -+ if (total_bytes_written < (size_t) num_bytes) { -+ return FALSE; -+ } ++ action = gtk_action_new (GDM_CONVERSATION_DEFAULT_ACTION, ++ _("Log In"), ++ _("Log into the currently selected sesson"), ++ NULL); ++ g_signal_connect_swapped (action, "activate", ++ G_CALLBACK (on_activate_log_in), extension); ++ g_object_set (G_OBJECT (action), "icon-name", "go-home", NULL); ++ gtk_action_group_add_action (extension->priv->actions, ++ action); + -+ return TRUE; ++ gtk_action_set_visible (action, FALSE); ++ extension->priv->login_action = action; +} + -+static GdmSmartcard * -+sc_read_smartcard (gint fd, -+ SECMODModule *module) ++static void ++gdm_smartcard_extension_init (GdmSmartcardExtension *extension) +{ -+ GdmSmartcard *card; -+ char *card_name; -+ gsize card_name_size; -+ -+ card_name_size = 0; -+ if (!sc_read_bytes (fd, &card_name_size, sizeof (card_name_size))) { -+ return NULL; -+ } -+ -+ card_name = g_slice_alloc0 (card_name_size); -+ if (!sc_read_bytes (fd, card_name, card_name_size)) { -+ g_slice_free1 (card_name_size, card_name); -+ return NULL; -+ } -+ card = _gdm_smartcard_new_from_name (module, card_name); -+ g_slice_free1 (card_name_size, card_name); ++ extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension, ++ GDM_TYPE_SMARTCARD_EXTENSION, ++ GdmSmartcardExtensionPrivate); + -+ return card; ++ extension->priv->icon = g_themed_icon_new ("apple-green"); ++ create_page (extension); ++ create_actions (extension); ++ gdm_smartcard_extension_reset (GDM_CONVERSATION (extension)); +} +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.h 2009-03-03 17:45:05.726016228 -0500 +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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, 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 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ */ + -+static gboolean -+sc_write_smartcard (gint fd, -+ GdmSmartcard *card) -+{ -+ gsize card_name_size; -+ char *card_name; ++#ifndef __GDM_SMARTCARD_EXTENSION_H ++#define __GDM_SMARTCARD_EXTENSION_H + -+ card_name = gdm_smartcard_get_name (card); -+ card_name_size = strlen (card_name) + 1; ++#include ++#include "gdm-greeter-extension.h" + -+ if (!sc_write_bytes (fd, &card_name_size, sizeof (card_name_size))) { -+ g_free (card_name); -+ return FALSE; -+ } ++G_BEGIN_DECLS + -+ if (!sc_write_bytes (fd, card_name, card_name_size)) { -+ g_free (card_name); -+ return FALSE; -+ } -+ g_free (card_name); ++#define GDM_TYPE_SMARTCARD_EXTENSION (gdm_smartcard_extension_get_type ()) ++#define GDM_SMARTCARD_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SMARTCARD_EXTENSION, GdmSmartcardExtension)) ++#define GDM_SMARTCARD_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SMARTCARD_EXTENSION, GdmSmartcardExtensionClass)) ++#define GDM_IS_SMARTCARD_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SMARTCARD_EXTENSION)) ++#define GDM_IS_SMARTCARD_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SMARTCARD_EXTENSION)) ++#define GDM_SMARTCARD_EXTENSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SMARTCARD_EXTENSION, GdmSmartcardExtensionClass)) + -+ return TRUE; -+} ++typedef struct _GdmSmartcardExtensionPrivate GdmSmartcardExtensionPrivate; + -+static gboolean -+gdm_smartcard_manager_worker_emit_smartcard_removed (GdmSmartcardManagerWorker *worker, -+ GdmSmartcard *card, -+ GError **error) ++typedef struct +{ -+ g_debug ("card '%s' removed!", gdm_smartcard_get_name (card)); ++ GObject parent; ++ GdmSmartcardExtensionPrivate *priv; ++} GdmSmartcardExtension; + -+ if (!sc_write_bytes (worker->write_fd, "R", 1)) { -+ goto error_out; -+ } ++typedef struct ++{ ++ GObjectClass parent_class; ++} GdmSmartcardExtensionClass; + -+ if (!sc_write_smartcard (worker->write_fd, card)) { -+ goto error_out; -+ } ++GType gdm_smartcard_extension_get_type (void); + -+ return TRUE; ++GdmSmartcardExtension *gdm_smartcard_extension_new (void); + -+error_out: -+ g_set_error (error, GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, -+ "%s", g_strerror (errno)); -+ return FALSE; -+} ++G_END_DECLS + -+static gboolean -+gdm_smartcard_manager_worker_emit_smartcard_inserted (GdmSmartcardManagerWorker *worker, -+ GdmSmartcard *card, -+ GError **error) -+{ -+ GError *write_error; ++#endif /* GDM_SMARTCARD_EXTENSION_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard.h 2009-03-03 17:45:05.746016526 -0500 +@@ -0,0 +1,94 @@ ++/* securitycard.h - api for reading and writing data to a security card ++ * ++ * Copyright (C) 2006 Ray Strode ++ * ++ * 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, 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 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ */ ++#ifndef GDM_SMARTCARD_H ++#define GDM_SMARTCARD_H + -+ write_error = NULL; -+ g_debug ("card '%s' inserted!", gdm_smartcard_get_name (card)); -+ if (!sc_write_bytes (worker->write_fd, "I", 1)) { -+ goto error_out; -+ } ++#include ++#include + -+ if (!sc_write_smartcard (worker->write_fd, card)) { -+ goto error_out; -+ } ++#include + -+ return TRUE; ++G_BEGIN_DECLS ++#define GDM_TYPE_SMARTCARD (gdm_smartcard_get_type ()) ++#define GDM_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SMARTCARD, GdmSmartcard)) ++#define GDM_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SMARTCARD, GdmSmartcardClass)) ++#define GDM_IS_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SMARTCARD)) ++#define GDM_IS_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SMARTCARD)) ++#define GDM_SMARTCARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SMARTCARD, GdmSmartcardClass)) ++#define GDM_SMARTCARD_ERROR (gdm_smartcard_error_quark ()) ++typedef struct _GdmSmartcardClass GdmSmartcardClass; ++typedef struct _GdmSmartcard GdmSmartcard; ++typedef struct _GdmSmartcardPrivate GdmSmartcardPrivate; ++typedef enum _GdmSmartcardError GdmSmartcardError; ++typedef enum _GdmSmartcardState GdmSmartcardState; + -+error_out: -+ g_set_error (error, GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, -+ "%s", g_strerror (errno)); -+ return FALSE; -+} ++typedef struct _GdmSmartcardRequest GdmSmartcardRequest; + -+static gboolean -+gdm_smartcard_manager_worker_watch_for_and_process_event (GdmSmartcardManagerWorker *worker, -+ GError **error) -+{ -+ PK11SlotInfo *slot; -+ CK_SLOT_ID slot_id, *key; -+ gint slot_series, card_slot_series; -+ GdmSmartcard *card; -+ GError *processing_error; ++struct _GdmSmartcard { ++ GObject parent; + -+ g_debug ("waiting for card event"); ++ /*< private > */ ++ GdmSmartcardPrivate *priv; ++}; + -+ /* FIXME: we return FALSE quite a bit in this function without cleaning up -+ * resources. By returning FALSE we're going to ultimately exit anyway, but -+ * we should still be tidier about things. -+ */ ++struct _GdmSmartcardClass { ++ GObjectClass parent_class; + -+ slot = SECMOD_WaitForAnyTokenEvent (worker->module, 0, PR_SecondsToInterval (1)); -+ processing_error = NULL; ++ void (* inserted) (GdmSmartcard *card); ++ void (* removed) (GdmSmartcard *card); ++}; + -+ if (slot == NULL) { -+ int error_code; ++enum _GdmSmartcardError { ++ GDM_SMARTCARD_ERROR_GENERIC = 0, ++}; ++ ++enum _GdmSmartcardState { ++ GDM_SMARTCARD_STATE_INSERTED = 0, ++ GDM_SMARTCARD_STATE_REMOVED, ++}; + -+ error_code = PORT_GetError (); -+ if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT)) { -+ g_debug ("spurrious event occurred"); -+ return TRUE; -+ } ++GType gdm_smartcard_get_type (void) G_GNUC_CONST; ++GQuark gdm_smartcard_error_quark (void) G_GNUC_CONST; + -+ /* FIXME: is there a function to convert from a PORT error -+ * code to a translated string? -+ */ -+ g_set_error (error, GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_WITH_NSS, -+ _("encountered unexpected error while " -+ "waiting for smartcard events")); -+ return FALSE; -+ } ++CK_SLOT_ID gdm_smartcard_get_slot_id (GdmSmartcard *card); ++gint gdm_smartcard_get_slot_series (GdmSmartcard *card); ++GdmSmartcardState gdm_smartcard_get_state (GdmSmartcard *card); + -+ /* the slot id and series together uniquely identify a card. -+ * You can never have two cards with the same slot id at the -+ * same time, however (I think), so we can key off of it. -+ */ -+ slot_id = PK11_GetSlotID (slot); -+ slot_series = PK11_GetSlotSeries (slot); ++char *gdm_smartcard_get_name (GdmSmartcard *card); ++gboolean gdm_smartcard_is_login_card (GdmSmartcard *card); + -+ /* First check to see if there is a card that we're currently -+ * tracking in the slot. -+ */ -+ key = g_new (CK_SLOT_ID, 1); -+ *key = slot_id; -+ card = g_hash_table_lookup (worker->smartcards, key); ++gboolean gdm_smartcard_unlock (GdmSmartcard *card, ++ const char *password); + -+ if (card != NULL) { -+ card_slot_series = gdm_smartcard_get_slot_series (card); -+ } else { -+ card_slot_series = -1; -+ } ++/* don't under any circumstances call these functions */ ++#ifdef GDM_SMARTCARD_ENABLE_INTERNAL_API + -+ if (PK11_IsPresent (slot)) { -+ /* Now, check to see if their is a new card in the slot. -+ * If there was a different card in the slot now than -+ * there was before, then we need to emit a removed signal -+ * for the old card (we don't want unpaired insertion events). -+ */ -+ if ((card != NULL) && -+ card_slot_series != slot_series) { -+ if (!gdm_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { -+ g_propagate_error (error, processing_error); -+ return FALSE; -+ } -+ } ++GdmSmartcard *_gdm_smartcard_new (SECMODModule *module, ++ CK_SLOT_ID slot_id, ++ gint slot_series); ++GdmSmartcard *_gdm_smartcard_new_from_name (SECMODModule *module, ++ const char *name); + -+ card = _gdm_smartcard_new (worker->module, -+ slot_id, slot_series); ++void _gdm_smartcard_set_state (GdmSmartcard *card, ++ GdmSmartcardState state); ++#endif + -+ g_hash_table_replace (worker->smartcards, -+ key, card); -+ key = NULL; ++G_END_DECLS ++#endif /* GDM_SMARTCARD_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.c 2009-03-03 17:45:05.741016399 -0500 +@@ -0,0 +1,1394 @@ ++/* gdm-smartcard-manager.c - object for monitoring smartcard insertion and ++ * removal events ++ * ++ * Copyright (C) 2006, 2009 Red Hat, Inc. ++ * ++ * 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, 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 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ */ ++#define _GNU_SOURCE ++#include "gdm-smartcard-manager.h" + -+ if (!gdm_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) { -+ g_propagate_error (error, processing_error); -+ return FALSE; -+ } -+ } else { -+ /* if we aren't tracking the card, just discard the event. -+ * We don't want unpaired remove events. Note on startup -+ * NSS will generate an "insertion" event if a card is -+ * already inserted in the slot. -+ */ -+ if ((card != NULL)) { -+ /* FIXME: i'm not sure about this code. Maybe we -+ * shouldn't do this at all, or maybe we should do it -+ * n times (where n = slot_series - card_slot_series + 1) -+ * -+ * Right now, i'm just doing it once. -+ */ -+ if ((slot_series - card_slot_series) > 1) { ++#define GDM_SMARTCARD_ENABLE_INTERNAL_API ++#include "gdm-smartcard.h" + -+ if (!gdm_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { -+ g_propagate_error (error, processing_error); -+ return FALSE; -+ } -+ g_hash_table_remove (worker->smartcards, key); ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ card = _gdm_smartcard_new (worker->module, -+ slot_id, slot_series); -+ g_hash_table_replace (worker->smartcards, -+ key, card); -+ key = NULL; -+ if (!gdm_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) { -+ g_propagate_error (error, processing_error); -+ return FALSE; -+ } -+ } ++#include ++#include + -+ if (!gdm_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { -+ g_propagate_error (error, processing_error); -+ return FALSE; -+ } ++#include ++#include ++#include ++#include ++#include + -+ g_hash_table_remove (worker->smartcards, key); -+ card = NULL; -+ } else { -+ g_debug ("got spurious remove event"); -+ } -+ } ++#ifndef GDM_SMARTCARD_MANAGER_DRIVER ++#define GDM_SMARTCARD_MANAGER_DRIVER LIBDIR"/pkcs11/libcoolkeypk11.so" ++#endif + -+ g_free (key); -+ PK11_FreeSlot (slot); ++#ifndef GDM_SMARTCARD_MANAGER_NSS_DB ++#define GDM_SMARTCARD_MANAGER_NSS_DB SYSCONFDIR"/pki/nssdb" ++#endif + -+ return TRUE; -+} ++#ifndef GDM_MAX_OPEN_FILE_DESCRIPTORS ++#define GDM_MAX_OPEN_FILE_DESCRIPTORS 1024 ++#endif + -+static void -+gdm_smartcard_manager_worker_run (GdmSmartcardManagerWorker *worker) -+{ -+ GError *error; ++#ifndef GDM_OPEN_FILE_DESCRIPTORS_DIR ++#define GDM_OPEN_FILE_DESCRIPTORS_DIR "/proc/self/fd" ++#endif + ++typedef enum _GdmSmartcardManagerState GdmSmartcardManagerState; ++typedef struct _GdmSmartcardManagerWorker GdmSmartcardManagerWorker; + -+ error = NULL; ++enum _GdmSmartcardManagerState { ++ GDM_SMARTCARD_MANAGER_STATE_STOPPED = 0, ++ GDM_SMARTCARD_MANAGER_STATE_STARTING, ++ GDM_SMARTCARD_MANAGER_STATE_STARTED, ++ GDM_SMARTCARD_MANAGER_STATE_STOPPING, ++}; + -+ while (gdm_smartcard_manager_worker_watch_for_and_process_event (worker, &error)); ++struct _GdmSmartcardManagerPrivate { ++ GdmSmartcardManagerState state; ++ SECMODModule *module; ++ char *module_path; + -+ if (error != NULL) { -+ g_debug ("could not process card event - %s", error->message); -+ g_error_free (error); -+ } ++ GSource *smartcard_event_source; ++ GPid smartcard_event_watcher_pid; ++ GHashTable *smartcards; + -+ gdm_smartcard_manager_worker_free (worker); -+} ++ GThread *worker_thread; + -+static gboolean -+gdm_smartcard_manager_create_worker (GdmSmartcardManager *manager, -+ gint *worker_fd, -+ GThread **worker_thread) -+{ -+ GdmSmartcardManagerWorker *worker; -+ gint write_fd, read_fd; ++ guint poll_timeout_id; + -+ write_fd = -1; -+ read_fd = -1; -+ if (!gdm_open_pipe (&write_fd, &read_fd)) { -+ return FALSE; -+ } ++ guint32 is_unstoppable : 1; ++ guint32 nss_is_loaded : 1; ++}; + -+ worker = gdm_smartcard_manager_worker_new (write_fd); -+ worker->module = manager->priv->module; ++struct _GdmSmartcardManagerWorker { ++ SECMODModule *module; ++ GHashTable *smartcards; ++ gint write_fd; + -+ *worker_thread = g_thread_create ((GThreadFunc) -+ gdm_smartcard_manager_worker_run, -+ worker, TRUE, NULL); ++ guint32 nss_is_loaded : 1; ++}; + -+ if (*worker_thread == NULL) { -+ gdm_smartcard_manager_worker_free (worker); -+ return FALSE; -+ } ++static void gdm_smartcard_manager_finalize (GObject *object); ++static void gdm_smartcard_manager_class_install_signals (GdmSmartcardManagerClass *service_class); ++static void gdm_smartcard_manager_class_install_properties (GdmSmartcardManagerClass *service_class); ++static void gdm_smartcard_manager_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec); ++static void gdm_smartcard_manager_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec); ++static void gdm_smartcard_manager_set_module_path (GdmSmartcardManager *manager, ++ const char *module_path); ++static void gdm_smartcard_manager_card_removed_handler (GdmSmartcardManager *manager, ++ GdmSmartcard *card); ++static void gdm_smartcard_manager_card_inserted_handler (GdmSmartcardManager *manager_class, ++ GdmSmartcard *card); ++static gboolean gdm_smartcard_manager_stop_now (GdmSmartcardManager *manager); ++static void gdm_smartcard_manager_queue_stop (GdmSmartcardManager *manager); ++ ++static gboolean gdm_smartcard_manager_create_worker (GdmSmartcardManager *manager, ++ int *worker_fd, GThread **worker_thread); + -+ if (worker_fd) { -+ *worker_fd = read_fd; -+ } ++static GdmSmartcardManagerWorker * gdm_smartcard_manager_worker_new (gint write_fd); ++static void gdm_smartcard_manager_worker_free (GdmSmartcardManagerWorker *worker); ++static gboolean gdm_open_pipe (gint *write_fd, gint *read_fd); ++static gboolean sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes); ++static gboolean sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes); ++static GdmSmartcard *sc_read_smartcard (gint fd, SECMODModule *module); ++static gboolean sc_write_smartcard (gint fd, GdmSmartcard *card); + -+ return TRUE; -+} ++enum { ++ PROP_0 = 0, ++ PROP_MODULE_PATH, ++ NUMBER_OF_PROPERTIES ++}; + -+#ifdef GDM_SMARTCARD_MANAGER_ENABLE_TEST -+#include ++enum { ++ SMARTCARD_INSERTED = 0, ++ SMARTCARD_REMOVED, ++ ERROR, ++ NUMBER_OF_SIGNALS ++}; + -+static GMainLoop *event_loop; -+static gboolean should_exit_on_next_remove = FALSE; ++static guint gdm_smartcard_manager_signals[NUMBER_OF_SIGNALS]; + -+static gboolean -+on_timeout (GdmSmartcardManager *manager) ++G_DEFINE_TYPE (GdmSmartcardManager, ++ gdm_smartcard_manager, ++ G_TYPE_OBJECT); ++ ++static void ++gdm_smartcard_manager_class_init (GdmSmartcardManagerClass *manager_class) +{ -+ GError *error; -+ g_print ("Re-enabling manager.\n"); ++ GObjectClass *gobject_class; + -+ if (!gdm_smartcard_manager_start (manager, &error)) { -+ g_warning ("could not start smartcard manager - %s", -+ error->message); -+ g_error_free (error); -+ return 1; -+ } -+ g_print ("Please re-insert smartcard\n"); ++ gobject_class = G_OBJECT_CLASS (manager_class); + -+ should_exit_on_next_remove = TRUE; ++ gobject_class->finalize = gdm_smartcard_manager_finalize; + -+ return FALSE; ++ gdm_smartcard_manager_class_install_signals (manager_class); ++ gdm_smartcard_manager_class_install_properties (manager_class); ++ ++ g_type_class_add_private (manager_class, ++ sizeof (GdmSmartcardManagerPrivate)); +} + +static void -+on_device_inserted (GdmSmartcardManager *manager, -+ GdmSmartcard *card) ++gdm_smartcard_manager_class_install_properties (GdmSmartcardManagerClass *card_class) +{ -+ g_print ("smartcard inserted!\n"); -+ g_print ("Please remove it.\n"); ++ GObjectClass *object_class; ++ GParamSpec *param_spec; ++ ++ object_class = G_OBJECT_CLASS (card_class); ++ object_class->set_property = gdm_smartcard_manager_set_property; ++ object_class->get_property = gdm_smartcard_manager_get_property; ++ ++ param_spec = g_param_spec_string ("module-path", _("Module Path"), ++ _("path to smartcard PKCS #11 driver"), ++ NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); ++ g_object_class_install_property (object_class, PROP_MODULE_PATH, param_spec); +} + +static void -+on_device_removed (GdmSmartcardManager *manager, -+ GdmSmartcard *card) ++gdm_smartcard_manager_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) +{ -+ g_print ("smartcard removed!\n"); ++ GdmSmartcardManager *manager = GDM_SMARTCARD_MANAGER (object); + -+ if (should_exit_on_next_remove) { -+ g_main_loop_quit (event_loop); -+ } else { -+ g_print ("disabling manager for 2 seconds\n"); -+ gdm_smartcard_manager_stop (manager); -+ g_timeout_add (2000, (GSourceFunc) on_timeout, manager); ++ switch (prop_id) { ++ case PROP_MODULE_PATH: ++ gdm_smartcard_manager_set_module_path (manager, ++ g_value_get_string (value)); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; + } +} + -+int -+main (int argc, -+ char *argv[]) ++static void ++gdm_smartcard_manager_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) +{ -+ GdmSmartcardManager *manager; -+ GError *error; -+ -+ g_log_set_always_fatal (G_LOG_LEVEL_ERROR -+ | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); -+ -+ g_type_init (); -+ -+ g_message ("creating instance of 'smartcard manager' object..."); -+ manager = gdm_smartcard_manager_new (NULL); -+ g_message ("'smartcard manager' object created successfully"); -+ -+ g_signal_connect (manager, "smartcard-inserted", -+ G_CALLBACK (on_device_inserted), NULL); -+ -+ g_signal_connect (manager, "smartcard-removed", -+ G_CALLBACK (on_device_removed), NULL); ++ GdmSmartcardManager *manager = GDM_SMARTCARD_MANAGER (object); ++ char *module_path; + -+ g_message ("starting listener..."); ++ switch (prop_id) { ++ case PROP_MODULE_PATH: ++ module_path = gdm_smartcard_manager_get_module_path (manager); ++ g_value_set_string (value, module_path); ++ g_free (module_path); ++ break; + -+ error = NULL; -+ if (!gdm_smartcard_manager_start (manager, &error)) { -+ g_warning ("could not start smartcard manager - %s", -+ error->message); -+ g_error_free (error); -+ return 1; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; + } -+ -+ event_loop = g_main_loop_new (NULL, FALSE); -+ g_main_loop_run (event_loop); -+ g_main_loop_unref (event_loop); -+ event_loop = NULL; -+ -+ g_message ("destroying previously created 'smartcard manager' object..."); -+ g_object_unref (manager); -+ manager = NULL; -+ g_message ("'smartcard manager' object destroyed successfully"); -+ -+ return 0; +} -+#endif -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.h b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.h -new file mode 100644 -index 0000000..932a703 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.h -@@ -0,0 +1,86 @@ -+/* gdm-smartcard-manager.h - object for monitoring smartcard insertion and -+ * removal events -+ * -+ * Copyright (C) 2006, 2009 Red Hat, Inc. -+ * -+ * 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, 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 -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ * -+ * Written by: Ray Strode -+ */ -+#ifndef GDM_SMARTCARD_MANAGER_H -+#define GDM_SMARTCARD_MANAGER_H -+ -+#define GDM_SMARTCARD_ENABLE_INTERNAL_API -+#include "gdm-smartcard.h" -+ -+#include -+#include -+ -+G_BEGIN_DECLS -+#define GDM_TYPE_SMARTCARD_MANAGER (gdm_smartcard_manager_get_type ()) -+#define GDM_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SMARTCARD_MANAGER, GdmSmartcardManager)) -+#define GDM_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SMARTCARD_MANAGER, GdmSmartcardManagerClass)) -+#define GDM_IS_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SMARTCARD_MANAGER)) -+#define GDM_IS_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SMARTCARD_MANAGER)) -+#define GDM_SMARTCARD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SMARTCARD_MANAGER, GdmSmartcardManagerClass)) -+#define GDM_SMARTCARD_MANAGER_ERROR (gdm_smartcard_manager_error_quark ()) -+typedef struct _GdmSmartcardManager GdmSmartcardManager; -+typedef struct _GdmSmartcardManagerClass GdmSmartcardManagerClass; -+typedef struct _GdmSmartcardManagerPrivate GdmSmartcardManagerPrivate; -+typedef enum _GdmSmartcardManagerError GdmSmartcardManagerError; -+ -+struct _GdmSmartcardManager { -+ GObject parent; -+ -+ /*< private > */ -+ GdmSmartcardManagerPrivate *priv; -+}; + -+struct _GdmSmartcardManagerClass { -+ GObjectClass parent_class; ++char * ++gdm_smartcard_manager_get_module_path (GdmSmartcardManager *manager) ++{ ++ return manager->priv->module_path; ++} + -+ /* Signals */ -+ void (*smartcard_inserted) (GdmSmartcardManager *manager, -+ GdmSmartcard *token); -+ void (*smartcard_removed) (GdmSmartcardManager *manager, -+ GdmSmartcard *token); -+ void (*error) (GdmSmartcardManager *manager, -+ GError *error); -+}; ++static void ++gdm_smartcard_manager_set_module_path (GdmSmartcardManager *manager, ++ const char *module_path) ++{ ++ if ((manager->priv->module_path == NULL) && (module_path == NULL)) { ++ return; ++ } + -+enum _GdmSmartcardManagerError { -+ GDM_SMARTCARD_MANAGER_ERROR_GENERIC = 0, -+ GDM_SMARTCARD_MANAGER_ERROR_WITH_NSS, -+ GDM_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, -+ GDM_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, -+ GDM_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS -+}; ++ if (((manager->priv->module_path == NULL) || ++ (module_path == NULL) || ++ (strcmp (manager->priv->module_path, module_path) != 0))) { ++ g_free (manager->priv->module_path); ++ manager->priv->module_path = g_strdup (module_path); ++ g_object_notify (G_OBJECT (manager), "module-path"); ++ } ++} + -+GType gdm_smartcard_manager_get_type (void) G_GNUC_CONST; -+GQuark gdm_smartcard_manager_error_quark (void) G_GNUC_CONST; ++static void ++gdm_smartcard_manager_card_removed_handler (GdmSmartcardManager *manager, ++ GdmSmartcard *card) ++{ ++ g_debug ("informing smartcard of its removal"); ++ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_REMOVED); ++ g_debug ("done"); ++} + -+GdmSmartcardManager *gdm_smartcard_manager_new (const char *module); ++static void ++gdm_smartcard_manager_card_inserted_handler (GdmSmartcardManager *manager, ++ GdmSmartcard *card) ++{ ++ g_debug ("informing smartcard of its insertion"); + -+gboolean gdm_smartcard_manager_start (GdmSmartcardManager *manager, -+ GError **error); ++ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_INSERTED); ++ g_debug ("done"); + -+void gdm_smartcard_manager_stop (GdmSmartcardManager *manager); ++} + -+char *gdm_smartcard_manager_get_module_path (GdmSmartcardManager *manager); -+gboolean gdm_smartcard_manager_login_token_is_inserted (GdmSmartcardManager *manager); ++static void ++gdm_smartcard_manager_class_install_signals (GdmSmartcardManagerClass *manager_class) ++{ ++ GObjectClass *object_class; + -+G_END_DECLS -+#endif /* GDM_SMARTCARD_MANAGER_H */ -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c -new file mode 100644 -index 0000000..7fe4cf4 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c -@@ -0,0 +1,167 @@ -+#include "config.h" ++ object_class = G_OBJECT_CLASS (manager_class); + -+#include -+#include -+#include -+#include ++ gdm_smartcard_manager_signals[SMARTCARD_INSERTED] = ++ g_signal_new ("smartcard-inserted", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmSmartcardManagerClass, ++ smartcard_inserted), ++ NULL, NULL, g_cclosure_marshal_VOID__POINTER, ++ G_TYPE_NONE, 1, G_TYPE_POINTER); ++ manager_class->smartcard_inserted = gdm_smartcard_manager_card_inserted_handler; + -+#include ++ gdm_smartcard_manager_signals[SMARTCARD_REMOVED] = ++ g_signal_new ("smartcard-removed", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmSmartcardManagerClass, ++ smartcard_removed), ++ NULL, NULL, g_cclosure_marshal_VOID__POINTER, ++ G_TYPE_NONE, 1, G_TYPE_POINTER); ++ manager_class->smartcard_removed = gdm_smartcard_manager_card_removed_handler; + -+#include "gdm-smartcard-manager.h" -+#include "gdm-smartcard.h" ++ gdm_smartcard_manager_signals[ERROR] = ++ g_signal_new ("error", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmSmartcardManagerClass, error), ++ NULL, NULL, g_cclosure_marshal_VOID__POINTER, ++ G_TYPE_NONE, 1, G_TYPE_POINTER); ++ manager_class->error = NULL; ++} + -+#ifndef GDM_SMARTCARDS_CONF -+#define GDM_SMARTCARDS_CONF GDMCONFDIR "/smartcards.conf" -+#endif ++static gboolean ++sc_slot_id_equal (CK_SLOT_ID *slot_id_1, ++ CK_SLOT_ID *slot_id_2) ++{ ++ g_assert (slot_id_1 != NULL); ++ g_assert (slot_id_2 != NULL); + -+#ifndef GDM_SMARTCARDS_GROUP -+#define GDM_SMARTCARDS_GROUP "Smartcards" -+#endif ++ return *slot_id_1 == *slot_id_2; ++} + -+#ifndef GDM_SMARTCARDS_KEY_ENABLED -+#define GDM_SMARTCARDS_KEY_ENABLED "Enabled" -+#endif ++static gboolean ++sc_slot_id_hash (CK_SLOT_ID *slot_id) ++{ ++ guint32 upper_bits, lower_bits; ++ gint temp; + -+#ifndef GDM_SMARTCARDS_KEY_DRIVER -+#define GDM_SMARTCARDS_KEY_DRIVER "Driver" -+#endif ++ if (sizeof (CK_SLOT_ID) == sizeof (gint)) { ++ return g_int_hash (slot_id); ++ } + -+static GMainLoop *event_loop; -+static GdmSmartcardManager *manager; -+static int signal_pipe_fds[2] = { -1, -1 }; ++ upper_bits = ((*slot_id) >> 31) - 1; ++ lower_bits = (*slot_id) & 0xffffffff; + -+static void -+on_smartcard_event (const char *event_string) -+{ -+ g_debug ("smartcard event '%s' happened", event_string); -+ g_print ("%s", event_string); -+ fflush (stdout); ++ /* The upper bits are almost certainly always zero, ++ * so let's degenerate to g_int_hash for the ++ * (very) common case ++ */ ++ temp = lower_bits + upper_bits; ++ return upper_bits + g_int_hash (&temp); +} + +static void -+watch_for_smartcards (void) ++gdm_smartcard_manager_init (GdmSmartcardManager *manager) +{ -+ GError *error; -+ char *driver; -+ GKeyFile *cfg; ++ g_debug ("initializing smartcard manager"); + -+ cfg = g_key_file_new (); ++ manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, ++ GDM_TYPE_SMARTCARD_MANAGER, ++ GdmSmartcardManagerPrivate); ++ manager->priv->poll_timeout_id = 0; ++ manager->priv->is_unstoppable = FALSE; ++ manager->priv->module = NULL; + -+ error = NULL; -+ driver = NULL; -+ if (g_key_file_load_from_file (cfg, GDM_SMARTCARDS_CONF, G_KEY_FILE_NONE, &error)) { -+ if (!g_key_file_get_boolean (cfg, GDM_SMARTCARDS_GROUP, GDM_SMARTCARDS_KEY_ENABLED, &error)) { -+ g_debug ("smartcard support is not enabled"); -+ goto out; -+ } ++ manager->priv->smartcards = ++ g_hash_table_new_full (g_str_hash, ++ g_str_equal, ++ (GDestroyNotify) g_free, ++ (GDestroyNotify) g_object_unref); + -+ driver = g_key_file_get_string (cfg, GDM_SMARTCARDS_GROUP, GDM_SMARTCARDS_KEY_DRIVER, NULL); -+ g_debug ("smartcards driver is set to '%s'", -+ driver == NULL || driver[0] == '\0'? "" : driver); ++ if (!g_thread_supported()) { ++ g_thread_init (NULL); + } + -+ g_debug ("watching for smartcard insertion and removal events"); -+ manager = gdm_smartcard_manager_new (driver); -+ g_free (driver); ++} + -+ g_signal_connect_swapped (manager, -+ "smartcard-inserted", -+ G_CALLBACK (on_smartcard_event), -+ "I"); ++static void ++gdm_smartcard_manager_finalize (GObject *object) ++{ ++ GdmSmartcardManager *manager; ++ GObjectClass *gobject_class; + -+ g_signal_connect_swapped (manager, -+ "smartcard-removed", -+ G_CALLBACK (on_smartcard_event), -+ "R"); ++ manager = GDM_SMARTCARD_MANAGER (object); ++ gobject_class = ++ G_OBJECT_CLASS (gdm_smartcard_manager_parent_class); + -+ error = NULL; -+ if (!gdm_smartcard_manager_start (manager, &error)) { -+ g_object_unref (manager); -+ manager = NULL; ++ gdm_smartcard_manager_stop_now (manager); + -+ if (error != NULL) { -+ g_debug ("%s", error->message); -+ g_error_free (error); -+ } else { -+ g_debug ("could not start smartcard manager"); ++ g_hash_table_destroy (manager->priv->smartcards); ++ manager->priv->smartcards = NULL; + -+ } -+ goto out; -+ } -+out: -+ g_key_file_free (cfg); ++ gobject_class->finalize (object); +} + -+static void -+stop_watching_for_smartcards (void) ++GQuark ++gdm_smartcard_manager_error_quark (void) +{ -+ if (manager != NULL) { -+ gdm_smartcard_manager_stop (manager); -+ g_object_unref (manager); -+ manager = NULL; ++ static GQuark error_quark = 0; ++ ++ if (error_quark == 0) { ++ error_quark = g_quark_from_static_string ("gdm-smartcard-manager-error-quark"); + } ++ ++ return error_quark; +} + -+static void -+on_term_signal (int signal_number) ++GdmSmartcardManager * ++gdm_smartcard_manager_new (const char *module_path) +{ -+ close (signal_pipe_fds[1]); -+ signal_pipe_fds[1] = -1; ++ GdmSmartcardManager *instance; ++ ++ instance = GDM_SMARTCARD_MANAGER (g_object_new (GDM_TYPE_SMARTCARD_MANAGER, ++ "module-path", module_path, ++ NULL)); ++ ++ return instance; +} + -+static gboolean -+after_term_signal (GIOChannel *io_channel, -+ GIOCondition condition, -+ gpointer data) ++static void ++gdm_smartcard_manager_emit_error (GdmSmartcardManager *manager, ++ GError *error) +{ -+ g_main_loop_quit (event_loop); -+ return FALSE; ++ manager->priv->is_unstoppable = TRUE; ++ g_signal_emit (manager, gdm_smartcard_manager_signals[ERROR], 0, ++ error); ++ manager->priv->is_unstoppable = FALSE; +} + +static void -+on_debug_message (const char *log_domain, -+ GLogLevelFlags log_level, -+ const char *message, -+ gpointer user_data) ++gdm_smartcard_manager_emit_smartcard_inserted (GdmSmartcardManager *manager, ++ GdmSmartcard *card) +{ -+ g_printerr ("*** DEBUG: %s", message); ++ manager->priv->is_unstoppable = TRUE; ++ g_signal_emit (manager, gdm_smartcard_manager_signals[SMARTCARD_INSERTED], 0, ++ card); ++ manager->priv->is_unstoppable = FALSE; +} + -+int -+main (int argc, -+ char **argv) ++static void ++gdm_smartcard_manager_emit_smartcard_removed (GdmSmartcardManager *manager, ++ GdmSmartcard *card) +{ -+ GIOChannel *io_channel; ++ GdmSmartcardManagerState old_state; + -+ setlocale (LC_ALL, ""); ++ old_state = manager->priv->state; ++ manager->priv->is_unstoppable = TRUE; ++ g_signal_emit (manager, gdm_smartcard_manager_signals[SMARTCARD_REMOVED], 0, ++ card); ++ manager->priv->is_unstoppable = FALSE; ++} + -+ g_type_init (); ++static gboolean ++gdm_smartcard_manager_check_for_and_process_events (GIOChannel *io_channel, ++ GIOCondition condition, ++ GdmSmartcardManager *manager) ++{ ++ GdmSmartcard *card; ++ gboolean should_stop; ++ guchar event_type; ++ char *card_name; ++ gint fd; + -+ g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, on_debug_message, NULL); ++ card = NULL; ++ should_stop = (condition & G_IO_HUP) || (condition & G_IO_ERR); + -+ event_loop = g_main_loop_new (NULL, FALSE); ++ if (should_stop) { ++ g_debug ("received %s on event socket, stopping " ++ "manager...", ++ (condition & G_IO_HUP) && (condition & G_IO_ERR)? ++ "error and hangup" : ++ (condition & G_IO_HUP)? ++ "hangup" : "error"); ++ } + -+ watch_for_smartcards (); ++ if (!(condition & G_IO_IN)) { ++ goto out; ++ } ++ ++ fd = g_io_channel_unix_get_fd (io_channel); + -+ signal (SIGTERM, on_term_signal); -+ signal (SIGPIPE, on_term_signal); -+ if (pipe (signal_pipe_fds) != 0) { -+ return 1; ++ event_type = '\0'; ++ if (!sc_read_bytes (fd, &event_type, 1)) { ++ should_stop = TRUE; ++ goto out; + } -+ fcntl (signal_pipe_fds[0], F_SETFD, FD_CLOEXEC); -+ fcntl (signal_pipe_fds[1], F_SETFD, FD_CLOEXEC); + -+ io_channel = g_io_channel_unix_new (signal_pipe_fds[0]); -+ g_io_channel_set_flags (io_channel, G_IO_FLAG_NONBLOCK, NULL); -+ g_io_channel_set_encoding (io_channel, NULL, NULL); -+ g_io_channel_set_buffered (io_channel, FALSE); -+ g_io_add_watch (io_channel, G_IO_HUP, after_term_signal, NULL); -+ g_io_channel_set_close_on_unref (io_channel, TRUE); -+ g_io_channel_unref (io_channel); ++ card = sc_read_smartcard (fd, manager->priv->module); + -+ g_main_loop_run (event_loop); ++ if (card == NULL) { ++ should_stop = TRUE; ++ goto out; ++ } + -+ stop_watching_for_smartcards (); ++ card_name = gdm_smartcard_get_name (card); + -+ return 0; -+} -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard.c -new file mode 100644 -index 0000000..c0e2739 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard.c -@@ -0,0 +1,558 @@ -+/* gdm-smartcard.c - smartcard object -+ * -+ * Copyright (C) 2006 Ray Strode -+ * -+ * 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, 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 -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ */ -+#define GDM_SMARTCARD_ENABLE_INTERNAL_API -+#include "gdm-smartcard.h" ++ switch (event_type) { ++ case 'I': ++ g_hash_table_replace (manager->priv->smartcards, ++ card_name, card); ++ card_name = NULL; + -+#include -+#include -+#include ++ gdm_smartcard_manager_emit_smartcard_inserted (manager, card); ++ card = NULL; ++ break; + -+#include -+#include ++ case 'R': ++ gdm_smartcard_manager_emit_smartcard_removed (manager, card); ++ if (!g_hash_table_remove (manager->priv->smartcards, card_name)) { ++ g_debug ("got removal event of unknown card!"); ++ } ++ g_free (card_name); ++ card_name = NULL; ++ card = NULL; ++ break; + -+#include -+#include -+#include -+#include -+#include -+#include ++ default: ++ g_free (card_name); ++ card_name = NULL; ++ g_object_unref (card); + -+struct _GdmSmartcardPrivate { -+ SECMODModule *module; -+ GdmSmartcardState state; ++ should_stop = TRUE; ++ break; ++ } + -+ CK_SLOT_ID slot_id; -+ int slot_series; ++out: ++ if (should_stop) { ++ GError *error; + -+ PK11SlotInfo *slot; -+ char *name; ++ error = g_error_new (GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, ++ "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source")); + -+ CERTCertificate *signing_certificate; -+ CERTCertificate *encryption_certificate; -+}; ++ gdm_smartcard_manager_emit_error (manager, error); ++ g_error_free (error); ++ gdm_smartcard_manager_stop_now (manager); ++ return FALSE; ++ } + -+static void gdm_smartcard_finalize (GObject *object); -+static void gdm_smartcard_class_install_signals (GdmSmartcardClass *card_class); -+static void gdm_smartcard_class_install_properties (GdmSmartcardClass *card_class); -+static void gdm_smartcard_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec); -+static void gdm_smartcard_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec); -+static void gdm_smartcard_set_name (GdmSmartcard *card, const char *name); -+static void gdm_smartcard_set_slot_id (GdmSmartcard *card, -+ int slot_id); -+static void gdm_smartcard_set_slot_series (GdmSmartcard *card, -+ int slot_series); -+static void gdm_smartcard_set_module (GdmSmartcard *card, -+ SECMODModule *module); ++ return TRUE; ++} + -+static PK11SlotInfo *gdm_smartcard_find_slot_from_id (GdmSmartcard *card, -+ int slot_id); ++static void ++gdm_smartcard_manager_event_processing_stopped_handler (GdmSmartcardManager *manager) ++{ ++ manager->priv->smartcard_event_source = NULL; ++ gdm_smartcard_manager_stop_now (manager); ++} + -+static PK11SlotInfo *gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, -+ const char *card_name); -+static gboolean gdm_smartcard_fetch_certificates (GdmSmartcard *card); ++static gboolean ++gdm_open_pipe (gint *write_fd, ++ gint *read_fd) ++{ ++ gint pipe_fds[2] = { -1, -1 }; + -+#ifndef GDM_SMARTCARD_DEFAULT_SLOT_ID -+#define GDM_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1) -+#endif ++ g_assert (write_fd != NULL); ++ g_assert (read_fd != NULL); + -+#ifndef GDM_SMARTCARD_DEFAULT_SLOT_SERIES -+#define GDM_SMARTCARD_DEFAULT_SLOT_SERIES -1 -+#endif ++ if (pipe (pipe_fds) < 0) { ++ return FALSE; ++ } + -+enum { -+ PROP_0 = 0, -+ PROP_NAME, -+ PROP_SLOT_ID, -+ PROP_SLOT_SERIES, -+ PROP_MODULE, -+ NUMBER_OF_PROPERTIES -+}; ++ if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) { ++ close (pipe_fds[0]); ++ close (pipe_fds[1]); ++ return FALSE; ++ } + -+enum { -+ INSERTED, -+ REMOVED, -+ NUMBER_OF_SIGNALS -+}; ++ if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) { ++ close (pipe_fds[0]); ++ close (pipe_fds[1]); ++ return FALSE; ++ } + -+static guint gdm_smartcard_signals[NUMBER_OF_SIGNALS]; ++ *read_fd = pipe_fds[0]; ++ *write_fd = pipe_fds[1]; + -+G_DEFINE_TYPE (GdmSmartcard, gdm_smartcard, G_TYPE_OBJECT); ++ return TRUE; ++} + +static void -+gdm_smartcard_class_init (GdmSmartcardClass *card_class) ++gdm_smartcard_manager_stop_watching_for_events (GdmSmartcardManager *manager) +{ -+ GObjectClass *gobject_class; ++ if (manager->priv->smartcard_event_source != NULL) { ++ g_source_destroy (manager->priv->smartcard_event_source); ++ manager->priv->smartcard_event_source = NULL; ++ } + -+ gobject_class = G_OBJECT_CLASS (card_class); ++ if (manager->priv->worker_thread != NULL) { ++ SECMOD_CancelWait (manager->priv->module); ++ /* FIXME: The function above doesn't seem to ++ * always wake up WaitForAnyTokenEvent ++ */ ++ exit (0); ++ g_thread_join (manager->priv->worker_thread); ++ manager->priv->worker_thread = NULL; ++ } ++} + -+ gobject_class->finalize = gdm_smartcard_finalize; ++static gboolean ++sc_load_nss (GError **error) ++{ ++ SECStatus status = SECSuccess; ++ static const guint32 flags = ++ NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | ++ NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | ++ NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD; + -+ gdm_smartcard_class_install_signals (card_class); -+ gdm_smartcard_class_install_properties (card_class); ++ g_debug ("attempting to load NSS database '%s'", ++ GDM_SMARTCARD_MANAGER_NSS_DB); + -+ g_type_class_add_private (card_class, -+ sizeof (GdmSmartcardPrivate)); -+} ++ status = NSS_Initialize (GDM_SMARTCARD_MANAGER_NSS_DB, ++ "", "", SECMOD_DB, flags); + -+static void -+gdm_smartcard_class_install_signals (GdmSmartcardClass *card_class) -+{ -+ GObjectClass *object_class; ++ if (status != SECSuccess) { ++ gsize error_message_size; ++ char *error_message; + -+ object_class = G_OBJECT_CLASS (card_class); ++ error_message_size = PR_GetErrorTextLength (); + -+ gdm_smartcard_signals[INSERTED] = -+ g_signal_new ("inserted", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmSmartcardClass, -+ inserted), -+ NULL, NULL, g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); ++ if (error_message_size == 0) { ++ g_debug ("NSS security system could not be initialized"); ++ g_set_error (error, ++ GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_WITH_NSS, ++ _("NSS security system could not be initialized")); ++ goto out; ++ } ++ ++ error_message = g_slice_alloc0 (error_message_size); ++ PR_GetErrorText (error_message); ++ ++ g_set_error (error, ++ GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_WITH_NSS, ++ "%s", error_message); ++ g_debug ("NSS security system could not be initialized - %s", ++ error_message); ++ ++ g_slice_free1 (error_message_size, error_message); ++ ++ goto out; ++ } + -+ gdm_smartcard_signals[REMOVED] = -+ g_signal_new ("removed", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmSmartcardClass, -+ removed), -+ NULL, NULL, g_cclosure_marshal_VOID__VOID, -+ G_TYPE_NONE, 0); ++ g_debug ("NSS database sucessfully loaded"); ++ return TRUE; ++ ++out: ++ g_debug ("NSS database couldn't be sucessfully loaded"); ++ return FALSE; +} + -+static void -+gdm_smartcard_class_install_properties (GdmSmartcardClass *card_class) ++static SECMODModule * ++load_driver (char *module_path, ++ GError **error) +{ -+ GObjectClass *object_class; -+ GParamSpec *param_spec; -+ -+ object_class = G_OBJECT_CLASS (card_class); -+ object_class->set_property = gdm_smartcard_set_property; -+ object_class->get_property = gdm_smartcard_get_property; ++ SECMODModule *module; ++ char *module_spec; ++ gboolean module_explicitly_specified; + -+ param_spec = g_param_spec_ulong ("slot-id", _("Slot ID"), -+ _("The slot the card is in"), -+ 1, G_MAXULONG, -+ GDM_SMARTCARD_DEFAULT_SLOT_ID, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); -+ g_object_class_install_property (object_class, PROP_SLOT_ID, param_spec); ++ g_debug ("attempting to load driver..."); + -+ param_spec = g_param_spec_int ("slot-series", _("Slot Series"), -+ _("per-slot card identifier"), -+ -1, G_MAXINT, -+ GDM_SMARTCARD_DEFAULT_SLOT_SERIES, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); -+ g_object_class_install_property (object_class, PROP_SLOT_SERIES, param_spec); ++ module = NULL; ++ module_explicitly_specified = module_path != NULL; ++ if (module_explicitly_specified) { ++ module_spec = g_strdup_printf ("library=\"%s\"", module_path); ++ g_debug ("loading smartcard driver using spec '%s'", ++ module_spec); + -+ param_spec = g_param_spec_string ("name", _("name"), -+ _("name"), NULL, -+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); -+ g_object_class_install_property (object_class, PROP_NAME, param_spec); ++ module = SECMOD_LoadUserModule (module_spec, ++ NULL /* parent */, ++ FALSE /* recurse */); ++ g_free (module_spec); ++ module_spec = NULL; + -+ param_spec = g_param_spec_pointer ("module", _("Module"), -+ _("smartcard driver"), -+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); -+ g_object_class_install_property (object_class, PROP_MODULE, param_spec); -+} ++ } else { ++ SECMODModuleList *modules, *tmp; + -+static void -+gdm_smartcard_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ GdmSmartcard *card = GDM_SMARTCARD (object); ++ modules = SECMOD_GetDefaultModuleList (); + -+ switch (prop_id) { -+ case PROP_NAME: -+ gdm_smartcard_set_name (card, g_value_get_string (value)); -+ break; ++ for (tmp = modules; tmp != NULL; tmp = tmp->next) { ++ if (!SECMOD_HasRemovableSlots (tmp->module) || ++ !tmp->module->loaded) ++ continue; + -+ case PROP_SLOT_ID: -+ gdm_smartcard_set_slot_id (card, -+ g_value_get_ulong (value)); ++ module = SECMOD_ReferenceModule (tmp->module); + break; ++ } + -+ case PROP_SLOT_SERIES: -+ gdm_smartcard_set_slot_series (card, -+ g_value_get_int (value)); -+ break; ++ /* fallback to compiled in driver path ++ */ ++ if (module == NULL) { ++ module_path = GDM_SMARTCARD_MANAGER_DRIVER; ++ module_spec = g_strdup_printf ("library=\"%s\"", module_path); ++ g_debug ("loading smartcard driver using spec '%s'", ++ module_spec); + -+ case PROP_MODULE: -+ gdm_smartcard_set_module (card, -+ (SECMODModule *) -+ g_value_get_pointer (value)); -+ break; ++ module = SECMOD_LoadUserModule (module_spec, ++ NULL /* parent */, ++ FALSE /* recurse */); ++ g_free (module_spec); ++ module_spec = NULL; ++ } + -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } -+} + -+CK_SLOT_ID -+gdm_smartcard_get_slot_id (GdmSmartcard *card) -+{ -+ return card->priv->slot_id; -+} ++ if (!module_explicitly_specified && module == NULL) { ++ g_set_error (error, ++ GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, ++ _("no suitable smartcard driver could be found")); ++ } else if (module == NULL || !module->loaded) { + -+GdmSmartcardState -+gdm_smartcard_get_state (GdmSmartcard *card) -+{ -+ return card->priv->state; -+} ++ gsize error_message_size; ++ char *error_message; + -+char * -+gdm_smartcard_get_name (GdmSmartcard *card) -+{ -+ return g_strdup (card->priv->name); -+} ++ if (module != NULL && !module->loaded) { ++ g_debug ("module found but not loaded?!"); ++ SECMOD_DestroyModule (module); ++ module = NULL; ++ } + -+gboolean -+gdm_smartcard_is_login_card (GdmSmartcard *card) -+{ -+ const char *login_card_name; -+ login_card_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME"); ++ error_message_size = PR_GetErrorTextLength (); + -+ if ((login_card_name == NULL) || (card->priv->name == NULL)) { -+ return FALSE; -+ } ++ if (error_message_size == 0) { ++ g_debug ("smartcard driver '%s' could not be loaded", ++ module_path); ++ g_set_error (error, ++ GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, ++ _("smartcard driver '%s' could not be " ++ "loaded"), module_path); ++ goto out; ++ } + -+ if (strcmp (card->priv->name, login_card_name) == 0) { -+ return TRUE; ++ error_message = g_slice_alloc0 (error_message_size); ++ PR_GetErrorText (error_message); ++ ++ g_set_error (error, ++ GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, ++ "%s", error_message); ++ ++ g_debug ("smartcard driver '%s' could not be loaded - %s", ++ module_path, error_message); ++ g_slice_free1 (error_message_size, error_message); + } + -+ return FALSE; ++out: ++ return module; +} + +static void -+gdm_smartcard_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) ++gdm_smartcard_manager_get_all_cards (GdmSmartcardManager *manager) +{ -+ GdmSmartcard *card = GDM_SMARTCARD (object); ++ int i; + -+ switch (prop_id) { -+ case PROP_NAME: -+ g_value_take_string (value, -+ gdm_smartcard_get_name (card)); -+ break; ++ for (i = 0; i < manager->priv->module->slotCount; i++) { ++ GdmSmartcard *card; ++ CK_SLOT_ID slot_id; ++ gint slot_series; ++ char *card_name; + -+ case PROP_SLOT_ID: -+ g_value_set_ulong (value, -+ (gulong) gdm_smartcard_get_slot_id (card)); -+ break; ++ slot_id = PK11_GetSlotID (manager->priv->module->slots[i]); ++ slot_series = PK11_GetSlotSeries (manager->priv->module->slots[i]); + -+ case PROP_SLOT_SERIES: -+ g_value_set_int (value, -+ gdm_smartcard_get_slot_series (card)); -+ break; ++ card = _gdm_smartcard_new (manager->priv->module, ++ slot_id, slot_series); + -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ card_name = gdm_smartcard_get_name (card); ++ ++ g_hash_table_replace (manager->priv->smartcards, ++ card_name, card); + } +} + -+static void -+gdm_smartcard_set_name (GdmSmartcard *card, -+ const char *name) ++gboolean ++gdm_smartcard_manager_start (GdmSmartcardManager *manager, ++ GError **error) +{ -+ if (name == NULL) { -+ return; ++ GError *watching_error; ++ gint worker_fd; ++ GPid worker_pid; ++ GIOChannel *io_channel; ++ GSource *source; ++ GIOFlags channel_flags; ++ GError *nss_error; ++ ++ if (manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STARTED) { ++ g_debug ("smartcard manager already started"); ++ return TRUE; + } + -+ if ((card->priv->name == NULL) || -+ (strcmp (card->priv->name, name) != 0)) { -+ g_free (card->priv->name); -+ card->priv->name = g_strdup (name); ++ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STARTING; + -+ if (card->priv->slot == NULL) { -+ card->priv->slot = gdm_smartcard_find_slot_from_card_name (card, -+ card->priv->name); ++ worker_fd = -1; ++ worker_pid = 0; + -+ if (card->priv->slot != NULL) { -+ int slot_id, slot_series; ++ nss_error = NULL; ++ if (!manager->priv->nss_is_loaded && !sc_load_nss (&nss_error)) { ++ g_propagate_error (error, nss_error); ++ goto out; ++ } ++ manager->priv->nss_is_loaded = TRUE; + -+ slot_id = PK11_GetSlotID (card->priv->slot); -+ if (slot_id != card->priv->slot_id) { -+ gdm_smartcard_set_slot_id (card, slot_id); -+ } ++ if (manager->priv->module == NULL) { ++ manager->priv->module = load_driver (manager->priv->module_path, &nss_error); ++ } ++ ++ if (manager->priv->module == NULL) { ++ g_propagate_error (error, nss_error); ++ goto out; ++ } + -+ slot_series = PK11_GetSlotSeries (card->priv->slot); -+ if (slot_series != card->priv->slot_series) { -+ gdm_smartcard_set_slot_series (card, slot_series); -+ } ++ if (!gdm_smartcard_manager_create_worker (manager, &worker_fd, &manager->priv->worker_thread)) { + -+ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_INSERTED); -+ } else { -+ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_REMOVED); -+ } -+ } ++ g_set_error (error, ++ GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, ++ _("could not watch for incoming card events - %s"), ++ g_strerror (errno)); + -+ g_object_notify (G_OBJECT (card), "name"); ++ goto out; + } -+} + -+static void -+gdm_smartcard_set_slot_id (GdmSmartcard *card, -+ int slot_id) -+{ -+ if (card->priv->slot_id != slot_id) { -+ card->priv->slot_id = slot_id; ++ io_channel = g_io_channel_unix_new (worker_fd); + -+ if (card->priv->slot == NULL) { -+ card->priv->slot = gdm_smartcard_find_slot_from_id (card, -+ card->priv->slot_id); ++ channel_flags = g_io_channel_get_flags (io_channel); ++ watching_error = NULL; + -+ if (card->priv->slot != NULL) { -+ const char *card_name; ++ source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP); ++ g_io_channel_unref (io_channel); ++ io_channel = NULL; + -+ card_name = PK11_GetTokenName (card->priv->slot); -+ if ((card->priv->name == NULL) || -+ ((card_name != NULL) && -+ (strcmp (card_name, card->priv->name) != 0))) { -+ gdm_smartcard_set_name (card, card_name); -+ } ++ manager->priv->smartcard_event_source = source; + -+ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_INSERTED); -+ } else { -+ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_REMOVED); -+ } -+ } ++ g_source_set_callback (manager->priv->smartcard_event_source, ++ (GSourceFunc) (GIOFunc) ++ gdm_smartcard_manager_check_for_and_process_events, ++ manager, ++ (GDestroyNotify) ++ gdm_smartcard_manager_event_processing_stopped_handler); ++ g_source_attach (manager->priv->smartcard_event_source, NULL); ++ g_source_unref (manager->priv->smartcard_event_source); + -+ g_object_notify (G_OBJECT (card), "slot-id"); -+ } -+} ++ /* populate the hash with cards that are already inserted ++ */ ++ gdm_smartcard_manager_get_all_cards (manager); + -+static void -+gdm_smartcard_set_slot_series (GdmSmartcard *card, -+ int slot_series) -+{ -+ if (card->priv->slot_series != slot_series) { -+ card->priv->slot_series = slot_series; -+ g_object_notify (G_OBJECT (card), "slot-series"); ++ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STARTED; ++ ++out: ++ /* don't leave it in a half started state ++ */ ++ if (manager->priv->state != GDM_SMARTCARD_MANAGER_STATE_STARTED) { ++ g_debug ("smartcard manager could not be completely started"); ++ gdm_smartcard_manager_stop (manager); ++ } else { ++ g_debug ("smartcard manager started"); + } ++ ++ return manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STARTED; +} + -+static void -+gdm_smartcard_set_module (GdmSmartcard *card, -+ SECMODModule *module) ++static gboolean ++gdm_smartcard_manager_stop_now (GdmSmartcardManager *manager) +{ -+ gboolean should_notify; -+ -+ if (card->priv->module != module) { -+ should_notify = TRUE; -+ } else { -+ should_notify = FALSE; ++ if (manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STOPPED) { ++ return FALSE; + } + -+ if (card->priv->module != NULL) { -+ SECMOD_DestroyModule (card->priv->module); -+ card->priv->module = NULL; -+ } ++ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STOPPED; ++ gdm_smartcard_manager_stop_watching_for_events (manager); + -+ if (module != NULL) { -+ card->priv->module = SECMOD_ReferenceModule (module); ++ if (manager->priv->module != NULL) { ++ SECMOD_DestroyModule (manager->priv->module); ++ manager->priv->module = NULL; + } + -+ if (should_notify) { -+ g_object_notify (G_OBJECT (card), "module"); ++ if (manager->priv->nss_is_loaded) { ++ NSS_Shutdown (); ++ manager->priv->nss_is_loaded = FALSE; + } -+} + -+int -+gdm_smartcard_get_slot_series (GdmSmartcard *card) -+{ -+ return card->priv->slot_series; ++ g_debug ("smartcard manager stopped"); ++ ++ return FALSE; +} + +static void -+gdm_smartcard_init (GdmSmartcard *card) ++gdm_smartcard_manager_queue_stop (GdmSmartcardManager *manager) +{ + -+ g_debug ("initializing smartcard "); -+ -+ card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card, -+ GDM_TYPE_SMARTCARD, -+ GdmSmartcardPrivate); ++ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STOPPING; + -+ if (card->priv->slot != NULL) { -+ card->priv->name = g_strdup (PK11_GetTokenName (card->priv->slot)); -+ } ++ g_idle_add ((GSourceFunc) gdm_smartcard_manager_stop_now, manager); +} + -+static void gdm_smartcard_finalize (GObject *object) ++void ++gdm_smartcard_manager_stop (GdmSmartcardManager *manager) +{ -+ GdmSmartcard *card; -+ GObjectClass *gobject_class; -+ -+ card = GDM_SMARTCARD (object); -+ -+ g_free (card->priv->name); -+ -+ gdm_smartcard_set_module (card, NULL); ++ if (manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STOPPED) { ++ return; ++ } + -+ gobject_class = G_OBJECT_CLASS (gdm_smartcard_parent_class); ++ if (manager->priv->is_unstoppable) { ++ gdm_smartcard_manager_queue_stop (manager); ++ return; ++ } + -+ gobject_class->finalize (object); ++ gdm_smartcard_manager_stop_now (manager); +} + -+GQuark gdm_smartcard_error_quark (void) ++static void ++gdm_smartcard_manager_check_for_login_card (CK_SLOT_ID slot_id, ++ GdmSmartcard *card, ++ gboolean *is_inserted) +{ -+ static GQuark error_quark = 0; ++ g_assert (is_inserted != NULL); + -+ if (error_quark == 0) { -+ error_quark = g_quark_from_static_string ("gdm-smartcard-error-quark"); ++ if (gdm_smartcard_is_login_card (card)) { ++ *is_inserted = TRUE; + } + -+ return error_quark; +} + -+GdmSmartcard * -+_gdm_smartcard_new (SECMODModule *module, -+ CK_SLOT_ID slot_id, -+ int slot_series) -+{ -+ GdmSmartcard *card; ++gboolean ++gdm_smartcard_manager_login_card_is_inserted (GdmSmartcardManager *manager) + -+ g_return_val_if_fail (module != NULL, NULL); -+ g_return_val_if_fail (slot_id >= 1, NULL); -+ g_return_val_if_fail (slot_series > 0, NULL); -+ g_return_val_if_fail (sizeof (gulong) == sizeof (slot_id), NULL); ++{ ++ gboolean is_inserted; + -+ card = GDM_SMARTCARD (g_object_new (GDM_TYPE_SMARTCARD, -+ "module", module, -+ "slot-id", (gulong) slot_id, -+ "slot-series", slot_series, -+ NULL)); -+ return card; ++ is_inserted = FALSE; ++ g_hash_table_foreach (manager->priv->smartcards, ++ (GHFunc) ++ gdm_smartcard_manager_check_for_login_card, ++ &is_inserted); ++ return is_inserted; +} + -+GdmSmartcard * -+_gdm_smartcard_new_from_name (SECMODModule *module, -+ const char *name) ++static GdmSmartcardManagerWorker * ++gdm_smartcard_manager_worker_new (gint write_fd) +{ -+ GdmSmartcard *card; ++ GdmSmartcardManagerWorker *worker; + -+ g_return_val_if_fail (module != NULL, NULL); -+ g_return_val_if_fail (name != NULL, NULL); ++ worker = g_slice_new0 (GdmSmartcardManagerWorker); ++ worker->write_fd = write_fd; ++ worker->module = NULL; + -+ card = GDM_SMARTCARD (g_object_new (GDM_TYPE_SMARTCARD, -+ "module", module, -+ "name", name, -+ NULL)); -+ return card; ++ worker->smartcards = ++ g_hash_table_new_full ((GHashFunc) sc_slot_id_hash, ++ (GEqualFunc) sc_slot_id_equal, ++ (GDestroyNotify) g_free, ++ (GDestroyNotify) g_object_unref); ++ ++ return worker; +} + -+void -+_gdm_smartcard_set_state (GdmSmartcard *card, -+ GdmSmartcardState state) ++static void ++gdm_smartcard_manager_worker_free (GdmSmartcardManagerWorker *worker) +{ -+ /* gdm_smartcard_fetch_certificates (card); */ -+ if (card->priv->state != state) { -+ card->priv->state = state; -+ -+ if (state == GDM_SMARTCARD_STATE_INSERTED) { -+ g_signal_emit (card, gdm_smartcard_signals[INSERTED], 0); -+ } else if (state == GDM_SMARTCARD_STATE_REMOVED) { -+ g_signal_emit (card, gdm_smartcard_signals[REMOVED], 0); -+ } else { -+ g_assert_not_reached (); -+ } ++ if (worker->smartcards != NULL) { ++ g_hash_table_destroy (worker->smartcards); ++ worker->smartcards = NULL; + } ++ ++ g_slice_free (GdmSmartcardManagerWorker, worker); +} + -+/* So we could conceivably make the closure data a pointer to the card -+ * or something similiar and then emit signals when we want passwords, -+ * but it's probably easier to just get the password up front and use -+ * it. So we just take the passed in g_malloc'd (well probably, who knows) -+ * and strdup it using NSPR's memory allocation routines. -+ */ -+static char * -+gdm_smartcard_password_handler (PK11SlotInfo *slot, -+ PRBool is_retrying, -+ const char *password) ++static gboolean ++sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes) +{ -+ if (is_retrying) { -+ return NULL; -+ } ++ size_t bytes_left; ++ size_t total_bytes_read; ++ ssize_t bytes_read; + -+ return password != NULL? PL_strdup (password): NULL; -+} ++ bytes_left = (size_t) num_bytes; ++ total_bytes_read = 0; + -+gboolean -+gdm_smartcard_unlock (GdmSmartcard *card, -+ const char *password) -+{ -+ SECStatus status; ++ do { ++ bytes_read = read (fd, bytes + total_bytes_read, bytes_left); ++ g_assert (bytes_read <= (ssize_t) bytes_left); + -+ PK11_SetPasswordFunc ((PK11PasswordFunc) gdm_smartcard_password_handler); ++ if (bytes_read <= 0) { ++ if ((bytes_read < 0) && (errno == EINTR || errno == EAGAIN)) { ++ continue; ++ } + -+ /* we pass PR_TRUE to load certificates -+ */ -+ status = PK11_Authenticate (card->priv->slot, PR_TRUE, (gpointer) password); ++ bytes_left = 0; ++ } else { ++ bytes_left -= bytes_read; ++ total_bytes_read += bytes_read; ++ } ++ } while (bytes_left > 0); + -+ if (status != SECSuccess) { -+ g_debug ("could not unlock card - %d", status); ++ if (total_bytes_read < (size_t) num_bytes) { + return FALSE; + } ++ + return TRUE; +} + -+static PK11SlotInfo * -+gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, -+ const char *card_name) ++static gboolean ++sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes) +{ -+ int i; ++ size_t bytes_left; ++ size_t total_bytes_written; ++ ssize_t bytes_written; + -+ for (i = 0; i < card->priv->module->slotCount; i++) { -+ const char *slot_card_name; ++ bytes_left = (size_t) num_bytes; ++ total_bytes_written = 0; + -+ slot_card_name = PK11_GetTokenName (card->priv->module->slots[i]); ++ do { ++ bytes_written = write (fd, bytes + total_bytes_written, bytes_left); ++ g_assert (bytes_written <= (ssize_t) bytes_left); + -+ if ((slot_card_name != NULL) && -+ (strcmp (slot_card_name, card_name) == 0)) { -+ return card->priv->module->slots[i]; ++ if (bytes_written <= 0) { ++ if ((bytes_written < 0) && (errno == EINTR || errno == EAGAIN)) { ++ continue; ++ } ++ ++ bytes_left = 0; ++ } else { ++ bytes_left -= bytes_written; ++ total_bytes_written += bytes_written; + } ++ } while (bytes_left > 0); ++ ++ if (total_bytes_written < (size_t) num_bytes) { ++ return FALSE; + } + -+ return NULL; ++ return TRUE; +} + -+static PK11SlotInfo * -+gdm_smartcard_find_slot_from_id (GdmSmartcard *card, -+ int slot_id) ++static GdmSmartcard * ++sc_read_smartcard (gint fd, ++ SECMODModule *module) +{ -+ int i; ++ GdmSmartcard *card; ++ char *card_name; ++ gsize card_name_size; + -+ for (i = 0; i < card->priv->module->slotCount; i++) { -+ if (PK11_GetSlotID (card->priv->module->slots[i]) == slot_id) { -+ return card->priv->module->slots[i]; -+ } ++ card_name_size = 0; ++ if (!sc_read_bytes (fd, &card_name_size, sizeof (card_name_size))) { ++ return NULL; + } + -+ return NULL; ++ card_name = g_slice_alloc0 (card_name_size); ++ if (!sc_read_bytes (fd, card_name, card_name_size)) { ++ g_slice_free1 (card_name_size, card_name); ++ return NULL; ++ } ++ card = _gdm_smartcard_new_from_name (module, card_name); ++ g_slice_free1 (card_name_size, card_name); ++ ++ return card; +} -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard.h b/gui/simple-greeter/plugins/smartcard/gdm-smartcard.h -new file mode 100644 -index 0000000..20303bd ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard.h -@@ -0,0 +1,94 @@ -+/* securitycard.h - api for reading and writing data to a security card -+ * -+ * Copyright (C) 2006 Ray Strode -+ * -+ * 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, 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 -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * 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. -+ */ -+#ifndef GDM_SMARTCARD_H -+#define GDM_SMARTCARD_H + -+#include -+#include ++static gboolean ++sc_write_smartcard (gint fd, ++ GdmSmartcard *card) ++{ ++ gsize card_name_size; ++ char *card_name; + -+#include ++ card_name = gdm_smartcard_get_name (card); ++ card_name_size = strlen (card_name) + 1; + -+G_BEGIN_DECLS -+#define GDM_TYPE_SMARTCARD (gdm_smartcard_get_type ()) -+#define GDM_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SMARTCARD, GdmSmartcard)) -+#define GDM_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SMARTCARD, GdmSmartcardClass)) -+#define GDM_IS_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SMARTCARD)) -+#define GDM_IS_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SMARTCARD)) -+#define GDM_SMARTCARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SMARTCARD, GdmSmartcardClass)) -+#define GDM_SMARTCARD_ERROR (gdm_smartcard_error_quark ()) -+typedef struct _GdmSmartcardClass GdmSmartcardClass; -+typedef struct _GdmSmartcard GdmSmartcard; -+typedef struct _GdmSmartcardPrivate GdmSmartcardPrivate; -+typedef enum _GdmSmartcardError GdmSmartcardError; -+typedef enum _GdmSmartcardState GdmSmartcardState; ++ if (!sc_write_bytes (fd, &card_name_size, sizeof (card_name_size))) { ++ g_free (card_name); ++ return FALSE; ++ } + -+typedef struct _GdmSmartcardRequest GdmSmartcardRequest; ++ if (!sc_write_bytes (fd, card_name, card_name_size)) { ++ g_free (card_name); ++ return FALSE; ++ } ++ g_free (card_name); + -+struct _GdmSmartcard { -+ GObject parent; ++ return TRUE; ++} + -+ /*< private > */ -+ GdmSmartcardPrivate *priv; -+}; ++static gboolean ++gdm_smartcard_manager_worker_emit_smartcard_removed (GdmSmartcardManagerWorker *worker, ++ GdmSmartcard *card, ++ GError **error) ++{ ++ g_debug ("card '%s' removed!", gdm_smartcard_get_name (card)); + -+struct _GdmSmartcardClass { -+ GObjectClass parent_class; ++ if (!sc_write_bytes (worker->write_fd, "R", 1)) { ++ goto error_out; ++ } + -+ void (* inserted) (GdmSmartcard *card); -+ void (* removed) (GdmSmartcard *card); -+}; ++ if (!sc_write_smartcard (worker->write_fd, card)) { ++ goto error_out; ++ } + -+enum _GdmSmartcardError { -+ GDM_SMARTCARD_ERROR_GENERIC = 0, -+}; ++ return TRUE; + -+enum _GdmSmartcardState { -+ GDM_SMARTCARD_STATE_INSERTED = 0, -+ GDM_SMARTCARD_STATE_REMOVED, -+}; ++error_out: ++ g_set_error (error, GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, ++ "%s", g_strerror (errno)); ++ return FALSE; ++} + -+GType gdm_smartcard_get_type (void) G_GNUC_CONST; -+GQuark gdm_smartcard_error_quark (void) G_GNUC_CONST; ++static gboolean ++gdm_smartcard_manager_worker_emit_smartcard_inserted (GdmSmartcardManagerWorker *worker, ++ GdmSmartcard *card, ++ GError **error) ++{ ++ GError *write_error; + -+CK_SLOT_ID gdm_smartcard_get_slot_id (GdmSmartcard *card); -+gint gdm_smartcard_get_slot_series (GdmSmartcard *card); -+GdmSmartcardState gdm_smartcard_get_state (GdmSmartcard *card); ++ write_error = NULL; ++ g_debug ("card '%s' inserted!", gdm_smartcard_get_name (card)); ++ if (!sc_write_bytes (worker->write_fd, "I", 1)) { ++ goto error_out; ++ } + -+char *gdm_smartcard_get_name (GdmSmartcard *card); -+gboolean gdm_smartcard_is_login_card (GdmSmartcard *card); ++ if (!sc_write_smartcard (worker->write_fd, card)) { ++ goto error_out; ++ } + -+gboolean gdm_smartcard_unlock (GdmSmartcard *card, -+ const char *password); ++ return TRUE; + -+/* don't under any circumstances call these functions */ -+#ifdef GDM_SMARTCARD_ENABLE_INTERNAL_API ++error_out: ++ g_set_error (error, GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, ++ "%s", g_strerror (errno)); ++ return FALSE; ++} + -+GdmSmartcard *_gdm_smartcard_new (SECMODModule *module, -+ CK_SLOT_ID slot_id, -+ gint slot_series); -+GdmSmartcard *_gdm_smartcard_new_from_name (SECMODModule *module, -+ const char *name); ++static gboolean ++gdm_smartcard_manager_worker_watch_for_and_process_event (GdmSmartcardManagerWorker *worker, ++ GError **error) ++{ ++ PK11SlotInfo *slot; ++ CK_SLOT_ID slot_id, *key; ++ gint slot_series, card_slot_series; ++ GdmSmartcard *card; ++ GError *processing_error; + -+void _gdm_smartcard_set_state (GdmSmartcard *card, -+ GdmSmartcardState state); -+#endif ++ g_debug ("waiting for card event"); + -+G_END_DECLS -+#endif /* GDM_SMARTCARD_H */ --- -1.6.1 - - -From 6015de6362cb3c62313ec62445dc422cf26af219 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 19 Feb 2009 15:27:11 -0500 -Subject: [PATCH 39/65] Don't hard code locations of plugin data files - -They were full path names on my local system -before for quick testing. This commit cleans -it up to pull the location from the autogoo. ---- - configure.ac | 9 +++++++++ - gui/simple-greeter/plugins/fingerprint/Makefile.am | 14 ++++++++++++-- - .../plugins/fingerprint/gdm-fingerprint | 10 ++++++++++ - .../fingerprint/gdm-fingerprint-extension.c | 4 ++-- - gui/simple-greeter/plugins/password/Makefile.am | 13 +++++++++++-- - gui/simple-greeter/plugins/password/gdm-password | 13 +++++++++++++ - .../plugins/password/gdm-password-extension.c | 4 ++-- - gui/simple-greeter/plugins/smartcard/Makefile.am | 13 +++++++++++-- - gui/simple-greeter/plugins/smartcard/gdm-smartcard | 11 +++++++++++ - .../plugins/smartcard/gdm-smartcard-extension.c | 4 ++-- - 10 files changed, 83 insertions(+), 12 deletions(-) - create mode 100644 gui/simple-greeter/plugins/fingerprint/gdm-fingerprint - create mode 100644 gui/simple-greeter/plugins/password/gdm-password - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard - -diff --git a/configure.ac b/configure.ac -index 8e99509..1b109d5 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -222,6 +222,15 @@ AC_ARG_WITH(dmconfdir, - AC_SUBST(dmconfdir) - - dnl --------------------------------------------------------------------------- -+dnl - Configuration file stuff -+dnl --------------------------------------------------------------------------- -+AC_ARG_WITH(extensionsdatadir, -+ AS_HELP_STRING([--with-extensions-datadir], -+ [directory where extensions store data, default=DATADIR/gdm/simple-greeter/extensions]), -+ extensionsdatadir=${withval}, extensionsdatadir=${datadir}/gdm/simple-greeter/extensions) -+AC_SUBST(extensionsdatadir) ++ /* FIXME: we return FALSE quite a bit in this function without cleaning up ++ * resources. By returning FALSE we're going to ultimately exit anyway, but ++ * we should still be tidier about things. ++ */ + -+dnl --------------------------------------------------------------------------- - dnl - Configure arguments - dnl --------------------------------------------------------------------------- - -diff --git a/gui/simple-greeter/plugins/fingerprint/Makefile.am b/gui/simple-greeter/plugins/fingerprint/Makefile.am -index 6f2d727..6a5620f 100644 ---- a/gui/simple-greeter/plugins/fingerprint/Makefile.am -+++ b/gui/simple-greeter/plugins/fingerprint/Makefile.am -@@ -1,12 +1,18 @@ - NULL = - -+extensiondir = $(extensionsdatadir)/fingerprint -+extension_DATA = page.ui ++ slot = SECMOD_WaitForAnyTokenEvent (worker->module, 0, PR_SecondsToInterval (1)); ++ processing_error = NULL; + -+pamservicename = gdm-fingerprint ++ if (slot == NULL) { ++ int error_code; + - AM_CPPFLAGS = \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ - -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ - -DDMCONFDIR=\""$(dmconfdir)"\" \ - -DGDMCONFDIR=\"$(gdmconfdir)\" \ -- -DDATADIR=\""$(datadir)"\" \ -+ -DPLUGINDATADIR=\""$(extensiondir)"\" \ -+ -DPAMSERVICENAME=\""$(pamservicename)"\" \ - -DSYSCONFDIR=\""$(sysconfdir)"\" \ - -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ - -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ -@@ -18,6 +24,7 @@ AM_CPPFLAGS = \ - $(POLKIT_GNOME_CFLAGS) \ - $(NULL) - ++ error_code = PORT_GetError (); ++ if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT)) { ++ g_debug ("spurrious event occurred"); ++ return TRUE; ++ } + - plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) - plugin_LTLIBRARIES = fingerprint.la - -@@ -33,7 +40,10 @@ fingerprint_la_SOURCES = \ - gdm-fingerprint-extension.c \ - plugin.c - --EXTRA_DIST = gdm-fingerprint -+pamdir = $(PAM_PREFIX)/pam.d -+pam_DATA = $(pamservicename) ++ /* FIXME: is there a function to convert from a PORT error ++ * code to a translated string? ++ */ ++ g_set_error (error, GDM_SMARTCARD_MANAGER_ERROR, ++ GDM_SMARTCARD_MANAGER_ERROR_WITH_NSS, ++ _("encountered unexpected error while " ++ "waiting for smartcard events")); ++ return FALSE; ++ } + -+EXTRA_DIST = $(extension_DATA) $(pam_DATA) - - MAINTAINERCLEANFILES = \ - *~ \ -diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint -new file mode 100644 -index 0000000..e8316b0 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint -@@ -0,0 +1,10 @@ -+#%PAM-1.0 -+auth required pam_fprintd.so -+account required pam_nologin.so -+account include system-auth -+password include system-auth -+session required pam_loginuid.so -+session optional pam_console.so -+session optional pam_keyinit.so force revoke -+session required pam_namespace.so -+session include system-auth -diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -index 2a4027c..7f5eb1c 100644 ---- a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -+++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -@@ -118,7 +118,7 @@ gdm_fingerprint_extension_set_ready (GdmConversation *conversation) - char * - gdm_fingerprint_extension_get_service_name (GdmConversation *conversation) - { -- return g_strdup ("fingerprint-auth"); -+ return g_strdup (PAMSERVICENAME); - } - - GtkWidget * -@@ -245,7 +245,7 @@ create_page (GdmFingerprintExtension *extension) - - error = NULL; - gtk_builder_add_from_file (builder, -- "/usr/share/gdm/simple-greeter/extensions/fingerprint/page.ui", -+ PLUGINDATADIR "/page.ui", - &error); - - if (error != NULL) { -diff --git a/gui/simple-greeter/plugins/password/Makefile.am b/gui/simple-greeter/plugins/password/Makefile.am -index 18b9801..e832c4d 100644 ---- a/gui/simple-greeter/plugins/password/Makefile.am -+++ b/gui/simple-greeter/plugins/password/Makefile.am -@@ -1,12 +1,18 @@ - NULL = - -+extensiondir = $(extensionsdatadir)/password -+extension_DATA = page.ui ++ /* the slot id and series together uniquely identify a card. ++ * You can never have two cards with the same slot id at the ++ * same time, however (I think), so we can key off of it. ++ */ ++ slot_id = PK11_GetSlotID (slot); ++ slot_series = PK11_GetSlotSeries (slot); + -+pamservicename = gdm-password ++ /* First check to see if there is a card that we're currently ++ * tracking in the slot. ++ */ ++ key = g_new (CK_SLOT_ID, 1); ++ *key = slot_id; ++ card = g_hash_table_lookup (worker->smartcards, key); + - AM_CPPFLAGS = \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ - -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ - -DDMCONFDIR=\""$(dmconfdir)"\" \ - -DGDMCONFDIR=\"$(gdmconfdir)\" \ -- -DDATADIR=\""$(datadir)"\" \ -+ -DPLUGINDATADIR=\""$(extensiondir)"\" \ -+ -DPAMSERVICENAME=\""$(pamservicename)"\" \ - -DSYSCONFDIR=\""$(sysconfdir)"\" \ - -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ - -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ -@@ -33,7 +39,10 @@ password_la_SOURCES = \ - gdm-password-extension.c \ - plugin.c - --EXTRA_DIST = gdm-password -+pamdir = $(PAM_PREFIX)/pam.d -+pam_DATA = $(pamservicename) ++ if (card != NULL) { ++ card_slot_series = gdm_smartcard_get_slot_series (card); ++ } else { ++ card_slot_series = -1; ++ } + -+EXTRA_DIST = $(extension_DATA) $(pam_DATA) - - MAINTAINERCLEANFILES = \ - *~ \ -diff --git a/gui/simple-greeter/plugins/password/gdm-password b/gui/simple-greeter/plugins/password/gdm-password -new file mode 100644 -index 0000000..d17f7b1 ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/gdm-password -@@ -0,0 +1,13 @@ -+#%PAM-1.0 -+auth required pam_env.so -+auth substack system-auth -+auth optional pam_gnome_keyring.so -+account required pam_nologin.so -+account include system-auth -+password include system-auth -+session required pam_loginuid.so -+session optional pam_console.so -+session optional pam_keyinit.so force revoke -+session required pam_namespace.so -+session optional pam_gnome_keyring.so auto_start -+session include system-auth -diff --git a/gui/simple-greeter/plugins/password/gdm-password-extension.c b/gui/simple-greeter/plugins/password/gdm-password-extension.c -index 80c9ea7..fae73be 100644 ---- a/gui/simple-greeter/plugins/password/gdm-password-extension.c -+++ b/gui/simple-greeter/plugins/password/gdm-password-extension.c -@@ -118,7 +118,7 @@ gdm_password_extension_set_ready (GdmConversation *conversation) - char * - gdm_password_extension_get_service_name (GdmConversation *conversation) - { -- return g_strdup ("gdm"); -+ return g_strdup (PAMSERVICENAME); - } - - GtkWidget * -@@ -251,7 +251,7 @@ create_page (GdmPasswordExtension *extension) - - error = NULL; - gtk_builder_add_from_file (builder, -- "/usr/share/gdm/simple-greeter/extensions/password/page.ui", -+ PLUGINDATADIR "/page.ui", - &error); - - if (error != NULL) { -diff --git a/gui/simple-greeter/plugins/smartcard/Makefile.am b/gui/simple-greeter/plugins/smartcard/Makefile.am -index 2dfe226..4897416 100644 ---- a/gui/simple-greeter/plugins/smartcard/Makefile.am -+++ b/gui/simple-greeter/plugins/smartcard/Makefile.am -@@ -1,12 +1,18 @@ - NULL = - -+extensiondir = $(extensionsdatadir)/smartcard -+extension_DATA = page.ui ++ if (PK11_IsPresent (slot)) { ++ /* Now, check to see if their is a new card in the slot. ++ * If there was a different card in the slot now than ++ * there was before, then we need to emit a removed signal ++ * for the old card (we don't want unpaired insertion events). ++ */ ++ if ((card != NULL) && ++ card_slot_series != slot_series) { ++ if (!gdm_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { ++ g_propagate_error (error, processing_error); ++ return FALSE; ++ } ++ } + -+pamservicename = gdm-smartcard ++ card = _gdm_smartcard_new (worker->module, ++ slot_id, slot_series); + - AM_CPPFLAGS = \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ - -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ - -DDMCONFDIR=\""$(dmconfdir)"\" \ - -DGDMCONFDIR=\"$(gdmconfdir)\" \ -- -DDATADIR=\""$(datadir)"\" \ -+ -DPLUGINDATADIR=\""$(extensiondir)"\" \ -+ -DPAMSERVICENAME=\""$(pamservicename)"\" \ - -DSYSCONFDIR=\""$(sysconfdir)"\" \ - -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ - -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ -@@ -55,7 +61,10 @@ gdm_smartcard_worker_SOURCES = \ - gdm-smartcard-worker.c \ - $(NULL) - --EXTRA_DIST = gdm-smartcard -+pamdir = $(PAM_PREFIX)/pam.d -+pam_DATA = $(pamservicename) ++ g_hash_table_replace (worker->smartcards, ++ key, card); ++ key = NULL; + -+EXTRA_DIST = $(extension_DATA) $(pam_DATA) - - MAINTAINERCLEANFILES = \ - *~ \ -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard b/gui/simple-greeter/plugins/smartcard/gdm-smartcard -new file mode 100644 -index 0000000..a0d7492 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard -@@ -0,0 +1,11 @@ -+#%PAM-1.0 -+auth required pam_env.so -+auth required pam_pkcs11.so wait_for_card -+account required pam_nologin.so -+account include system-auth -+password include system-auth -+session required pam_loginuid.so -+session optional pam_console.so -+session optional pam_keyinit.so force revoke -+session required pam_namespace.so -+session include system-auth -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -index efa0978..0ffea2c 100644 ---- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -131,7 +131,7 @@ gdm_smartcard_extension_set_ready (GdmConversation *conversation) - char * - gdm_smartcard_extension_get_service_name (GdmConversation *conversation) - { -- return g_strdup ("smartcard-auth"); -+ return g_strdup (PAMSERVICENAME); - } - - GtkWidget * -@@ -258,7 +258,7 @@ create_page (GdmSmartcardExtension *extension) - - error = NULL; - gtk_builder_add_from_file (builder, -- "/usr/share/gdm/simple-greeter/extensions/smartcard/page.ui", -+ PLUGINDATADIR "/page.ui", - &error); - - if (error != NULL) { --- -1.6.1 - - -From 1565a925432d212a8b11eeae00d384c2f023a49c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Feb 2009 13:52:19 -0500 -Subject: [PATCH 40/65] Add a comment marking protected api in chooser - -The chooser widget has methods that only its -subclasses are supposed to call. We should -mark them as such. ---- - gui/simple-greeter/gdm-chooser-widget.h | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-chooser-widget.h b/gui/simple-greeter/gdm-chooser-widget.h -index b73d1bb..216ea85 100644 ---- a/gui/simple-greeter/gdm-chooser-widget.h -+++ b/gui/simple-greeter/gdm-chooser-widget.h -@@ -136,6 +136,8 @@ int gdm_chooser_widget_get_number_of_items (GdmChooserWidget - void gdm_chooser_widget_activate_if_one_item (GdmChooserWidget *widget); - void gdm_chooser_widget_propagate_pending_key_events (GdmChooserWidget *widget); - -+/* Protected -+ */ - void gdm_chooser_widget_loaded (GdmChooserWidget *widget); - - G_END_DECLS --- -1.6.1 - - -From 88e738b1aaa7785addea9fc4f8baba140e988e1c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Feb 2009 14:05:20 -0500 -Subject: [PATCH 41/65] Add new api to ask when chooser widget is done loading items - ---- - gui/simple-greeter/gdm-chooser-widget.c | 9 +++++++++ - gui/simple-greeter/gdm-chooser-widget.h | 2 ++ - 2 files changed, 11 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c -index f0298c6..e5ddf78 100644 ---- a/gui/simple-greeter/gdm-chooser-widget.c -+++ b/gui/simple-greeter/gdm-chooser-widget.c -@@ -93,6 +93,7 @@ struct GdmChooserWidgetPrivate - guint32 should_hide_inactive_items : 1; - guint32 emit_activated_after_resize_animation : 1; - guint32 was_fully_grown : 1; -+ guint32 is_loaded : 1; - - GdmChooserWidgetPosition separator_position; - GdmChooserWidgetState state; -@@ -2485,8 +2486,16 @@ gdm_chooser_widget_propagate_pending_key_events (GdmChooserWidget *widget) - gdm_scrollable_widget_replay_queued_key_events (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget)); - } - -+gboolean -+gdm_chooser_widget_is_loaded (GdmChooserWidget *widget) -+{ -+ return widget->priv->is_loaded; -+} ++ if (!gdm_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) { ++ g_propagate_error (error, processing_error); ++ return FALSE; ++ } ++ } else { ++ /* if we aren't tracking the card, just discard the event. ++ * We don't want unpaired remove events. Note on startup ++ * NSS will generate an "insertion" event if a card is ++ * already inserted in the slot. ++ */ ++ if ((card != NULL)) { ++ /* FIXME: i'm not sure about this code. Maybe we ++ * shouldn't do this at all, or maybe we should do it ++ * n times (where n = slot_series - card_slot_series + 1) ++ * ++ * Right now, i'm just doing it once. ++ */ ++ if ((slot_series - card_slot_series) > 1) { + - void - gdm_chooser_widget_loaded (GdmChooserWidget *widget) - { -+ widget->priv->is_loaded = TRUE; ++ if (!gdm_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { ++ g_propagate_error (error, processing_error); ++ return FALSE; ++ } ++ g_hash_table_remove (worker->smartcards, key); + - g_signal_emit (widget, signals[LOADED], 0); - } -diff --git a/gui/simple-greeter/gdm-chooser-widget.h b/gui/simple-greeter/gdm-chooser-widget.h -index 216ea85..38f889b 100644 ---- a/gui/simple-greeter/gdm-chooser-widget.h -+++ b/gui/simple-greeter/gdm-chooser-widget.h -@@ -136,6 +136,8 @@ int gdm_chooser_widget_get_number_of_items (GdmChooserWidget - void gdm_chooser_widget_activate_if_one_item (GdmChooserWidget *widget); - void gdm_chooser_widget_propagate_pending_key_events (GdmChooserWidget *widget); - -+gboolean gdm_chooser_widget_is_loaded (GdmChooserWidget *widget); ++ card = _gdm_smartcard_new (worker->module, ++ slot_id, slot_series); ++ g_hash_table_replace (worker->smartcards, ++ key, card); ++ key = NULL; ++ if (!gdm_smartcard_manager_worker_emit_smartcard_inserted (worker, card, &processing_error)) { ++ g_propagate_error (error, processing_error); ++ return FALSE; ++ } ++ } + - /* Protected - */ - void gdm_chooser_widget_loaded (GdmChooserWidget *widget); --- -1.6.1 - - -From 0bf2cd04e08ad29371eed89cd03425cced4506f3 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Feb 2009 14:31:27 -0500 -Subject: [PATCH 42/65] Tell tasks they're ready only after user list loads - -This way they won't try to access the list prematurely. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 10 +++++++++- - 1 files changed, 9 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 5f37d0c..30989ad 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -843,7 +843,15 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - (gpointer) service_name); - - if (task != NULL) { -- gdm_conversation_set_ready (GDM_CONVERSATION (task)); -+ if (gdm_chooser_widget_is_loaded (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser))) { -+ gdm_conversation_set_ready (GDM_CONVERSATION (task)); -+ } else { ++ if (!gdm_smartcard_manager_worker_emit_smartcard_removed (worker, card, &processing_error)) { ++ g_propagate_error (error, processing_error); ++ return FALSE; ++ } + -+ g_signal_connect_swapped (login_window->priv->user_chooser, -+ "loaded", -+ G_CALLBACK (gdm_conversation_set_ready), -+ GDM_CONVERSATION (task)); ++ g_hash_table_remove (worker->smartcards, key); ++ card = NULL; ++ } else { ++ g_debug ("got spurious remove event"); + } - g_object_unref (task); - } - --- -1.6.1 - - -From b16790919e0d368d0119d9f5ada238e6ae8e59ab Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Feb 2009 14:32:47 -0500 -Subject: [PATCH 43/65] Start smartcard listener only after getting the go ahead - -The greeter will tell us when it's ready for us. We -don't want to listen for events until that point. ---- - .../plugins/smartcard/gdm-smartcard-extension.c | 162 ++++++++++---------- - 1 files changed, 84 insertions(+), 78 deletions(-) - -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -index 0ffea2c..40ecd08 100644 ---- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -70,6 +70,84 @@ G_DEFINE_TYPE_WITH_CODE (GdmSmartcardExtension, - G_IMPLEMENT_INTERFACE (GDM_TYPE_CONVERSATION, - gdm_conversation_iface_init)); - -+static gboolean -+on_smartcard_event (GIOChannel *io_channel, -+ GIOCondition condition, -+ gpointer data) ++ } ++ ++ g_free (key); ++ PK11_FreeSlot (slot); ++ ++ return TRUE; ++} ++ ++static void ++gdm_smartcard_manager_worker_run (GdmSmartcardManagerWorker *worker) +{ -+ GdmSmartcardExtension *extension; -+ -+ extension = GDM_SMARTCARD_EXTENSION (data); ++ GError *error; + -+ if (condition & G_IO_IN) { -+ char buffer[1024]; -+ ssize_t num_bytes; + -+ num_bytes = read (g_io_channel_unix_get_fd (io_channel), -+ buffer, sizeof (buffer)); ++ error = NULL; + -+ if (num_bytes < 0 && errno != EINTR) -+ return FALSE; ++ while (gdm_smartcard_manager_worker_watch_for_and_process_event (worker, &error)); + -+ if (num_bytes != 1) { -+ g_debug ("buffer: %s\n", buffer); -+ return TRUE; -+ } ++ if (error != NULL) { ++ g_debug ("could not process card event - %s", error->message); ++ g_error_free (error); ++ } + -+ if (buffer[0] == 'I') { -+ extension->priv->number_of_tokens++; -+ } else { -+ extension->priv->number_of_tokens--; -+ } ++ gdm_smartcard_manager_worker_free (worker); ++} + -+ if (extension->priv->number_of_tokens == 1) { -+ gdm_conversation_choose_user (GDM_CONVERSATION (extension), -+ GDM_CONVERSATION_OTHER_USER); -+ } else if (extension->priv->number_of_tokens == 0) { -+ gdm_conversation_cancel (GDM_CONVERSATION (extension)); -+ } ++static gboolean ++gdm_smartcard_manager_create_worker (GdmSmartcardManager *manager, ++ gint *worker_fd, ++ GThread **worker_thread) ++{ ++ GdmSmartcardManagerWorker *worker; ++ gint write_fd, read_fd; + -+ return TRUE; ++ write_fd = -1; ++ read_fd = -1; ++ if (!gdm_open_pipe (&write_fd, &read_fd)) { ++ return FALSE; + } + -+ if (condition & G_IO_HUP) { ++ worker = gdm_smartcard_manager_worker_new (write_fd); ++ worker->module = manager->priv->module; ++ ++ *worker_thread = g_thread_create ((GThreadFunc) ++ gdm_smartcard_manager_worker_run, ++ worker, TRUE, NULL); ++ ++ if (*worker_thread == NULL) { ++ gdm_smartcard_manager_worker_free (worker); + return FALSE; + } + ++ if (worker_fd) { ++ *worker_fd = read_fd; ++ } ++ + return TRUE; +} + -+static void -+watch_for_smartcards (GdmSmartcardExtension *extension) ++#ifdef GDM_SMARTCARD_MANAGER_ENABLE_TEST ++#include ++ ++static GMainLoop *event_loop; ++static gboolean should_exit_on_next_remove = FALSE; ++ ++static gboolean ++on_timeout (GdmSmartcardManager *manager) +{ + GError *error; -+ GIOChannel *io_channel; -+ char *args[] = { GDM_SMARTCARD_WORKER_COMMAND, NULL }; -+ GPid pid; -+ int stdout_fd; -+ -+ error = NULL; ++ g_print ("Re-enabling manager.\n"); + -+ if (!g_spawn_async_with_pipes (NULL, args, NULL, 0, -+ NULL, NULL, &pid, NULL, -+ &stdout_fd, NULL, &error)) { -+ g_debug ("could not start smart card manager: %s", error->message); ++ if (!gdm_smartcard_manager_start (manager, &error)) { ++ g_warning ("could not start smartcard manager - %s", ++ error->message); + g_error_free (error); -+ return; ++ return 1; + } -+ fcntl (stdout_fd, F_SETFD, FD_CLOEXEC); ++ g_print ("Please re-insert smartcard\n"); + -+ io_channel = g_io_channel_unix_new (stdout_fd); -+ g_io_channel_set_flags (io_channel, G_IO_FLAG_NONBLOCK, NULL); -+ g_io_channel_set_encoding (io_channel, NULL, NULL); -+ g_io_channel_set_buffered (io_channel, FALSE); -+ g_io_add_watch (io_channel, G_IO_IN, on_smartcard_event, extension); -+ g_io_channel_set_close_on_unref (io_channel, TRUE); -+ g_io_channel_unref (io_channel); ++ should_exit_on_next_remove = TRUE; + -+ extension->priv->worker_pid = pid; ++ return FALSE; +} + - static void - gdm_smartcard_extension_set_message (GdmConversation *conversation, - const char *message) -@@ -125,7 +203,13 @@ gdm_smartcard_extension_reset (GdmConversation *conversation) - static void - gdm_smartcard_extension_set_ready (GdmConversation *conversation) - { -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); - gdm_task_set_enabled (GDM_TASK (conversation), TRUE); ++static void ++on_device_inserted (GdmSmartcardManager *manager, ++ GdmSmartcard *card) ++{ ++ g_print ("smartcard inserted!\n"); ++ g_print ("Please remove it.\n"); ++} + -+ if (extension->priv->worker_pid <= 0) -+ { -+ watch_for_smartcards (extension); -+ } - } - - char * -@@ -297,83 +381,6 @@ create_actions (GdmSmartcardExtension *extension) - - extension->priv->actions = gtk_action_group_new ("gdm-smartcard-extension"); - } --static gboolean --on_smartcard_event (GIOChannel *io_channel, -- GIOCondition condition, -- gpointer data) --{ -- GdmSmartcardExtension *extension; -- -- extension = GDM_SMARTCARD_EXTENSION (data); -- -- if (condition & G_IO_IN) { -- char buffer[1024]; -- ssize_t num_bytes; -- -- num_bytes = read (g_io_channel_unix_get_fd (io_channel), -- buffer, sizeof (buffer)); -- -- if (num_bytes < 0 && errno != EINTR) -- return FALSE; -- -- if (num_bytes != 1) { -- g_debug ("buffer: %s\n", buffer); -- return TRUE; -- } -- -- if (buffer[0] == 'I') { -- extension->priv->number_of_tokens++; -- } else { -- extension->priv->number_of_tokens--; -- } -- -- if (extension->priv->number_of_tokens == 1) { -- gdm_conversation_choose_user (GDM_CONVERSATION (extension), -- GDM_CONVERSATION_OTHER_USER); -- } else if (extension->priv->number_of_tokens == 0) { -- gdm_conversation_cancel (GDM_CONVERSATION (extension)); -- } -- -- return TRUE; -- } -- -- if (condition & G_IO_HUP) { -- return FALSE; -- } -- -- return TRUE; --} -- --static void --watch_for_smartcards (GdmSmartcardExtension *extension) --{ -- GError *error; -- GIOChannel *io_channel; -- char *args[] = { GDM_SMARTCARD_WORKER_COMMAND, NULL }; -- GPid pid; -- int stdout_fd; -- -- error = NULL; -- -- if (!g_spawn_async_with_pipes (NULL, args, NULL, 0, -- NULL, NULL, &pid, NULL, -- &stdout_fd, NULL, &error)) { -- g_debug ("could not start smart card manager: %s", error->message); -- g_error_free (error); -- return; -- } -- fcntl (stdout_fd, F_SETFD, FD_CLOEXEC); -- -- io_channel = g_io_channel_unix_new (stdout_fd); -- g_io_channel_set_flags (io_channel, G_IO_FLAG_NONBLOCK, NULL); -- g_io_channel_set_encoding (io_channel, NULL, NULL); -- g_io_channel_set_buffered (io_channel, FALSE); -- g_io_add_watch (io_channel, G_IO_IN, on_smartcard_event, extension); -- g_io_channel_set_close_on_unref (io_channel, TRUE); -- g_io_channel_unref (io_channel); -- -- extension->priv->worker_pid = pid; --} - - static void - gdm_smartcard_extension_init (GdmSmartcardExtension *extension) -@@ -383,7 +390,6 @@ gdm_smartcard_extension_init (GdmSmartcardExtension *extension) - GdmSmartcardExtensionPrivate); - - extension->priv->icon = g_themed_icon_new ("apple-green"); -- watch_for_smartcards (extension); - create_page (extension); - create_actions (extension); - gdm_smartcard_extension_reset (GDM_CONVERSATION (extension)); --- -1.6.1 - - -From 29bdaeeb5571914b2bff56c8ec39594712055f9c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Feb 2009 14:35:44 -0500 -Subject: [PATCH 44/65] Add a sanity check against buggy plugins - -We don't let them select items in the user list -before the user list is loaded. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 9 +++++++++ - 1 files changed, 9 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 30989ad..7739a7c 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -2268,6 +2268,15 @@ on_conversation_chose_user (GdmGreeterLoginWindow *login_window, - const char *username, - GdmConversation *conversation) - { -+ if (!gdm_chooser_widget_is_loaded (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser))) { -+ char *name; ++static void ++on_device_removed (GdmSmartcardManager *manager, ++ GdmSmartcard *card) ++{ ++ g_print ("smartcard removed!\n"); + -+ name = gdm_task_get_name (GDM_TASK (conversation)); -+ g_warning ("Task %s is trying to choose user before list is loaded", name); -+ g_free (name); -+ return; ++ if (should_exit_on_next_remove) { ++ g_main_loop_quit (event_loop); ++ } else { ++ g_print ("disabling manager for 2 seconds\n"); ++ gdm_smartcard_manager_stop (manager); ++ g_timeout_add (2000, (GSourceFunc) on_timeout, manager); + } ++} + - if (gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), - GDM_TASK (conversation))) { - gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), --- -1.6.1 - - -From ec0b4c65adb8fcf9c4f2b3a52fec039afde0fbaf Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 23 Feb 2009 13:27:29 -0500 -Subject: [PATCH 45/65] Fix smartcard plugin to accept a PIN code. - ---- - .../plugins/smartcard/gdm-smartcard-extension.c | 24 ++++++++++++++++++++ - 1 files changed, 24 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -index 40ecd08..621d1ab 100644 ---- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -43,6 +43,7 @@ struct _GdmSmartcardExtensionPrivate - GIcon *icon; - GtkWidget *page; - GtkActionGroup *actions; -+ GtkAction *login_action; - - GtkWidget *message_label; - GtkWidget *prompt_label; -@@ -167,6 +168,7 @@ gdm_smartcard_extension_ask_question (GdmConversation *conversation, - gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); - gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); - gtk_widget_show (extension->priv->prompt_entry); -+ gtk_action_set_visible (extension->priv->login_action, TRUE); - gtk_widget_grab_focus (extension->priv->prompt_entry); - extension->priv->answer_pending = TRUE; - } -@@ -182,6 +184,7 @@ gdm_smartcard_extension_ask_secret (GdmConversation *conversation, - gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); - gtk_widget_show (extension->priv->prompt_entry); - gtk_widget_grab_focus (extension->priv->prompt_entry); -+ gtk_action_set_visible (extension->priv->login_action, TRUE); - extension->priv->answer_pending = TRUE; - } - -@@ -195,6 +198,7 @@ gdm_smartcard_extension_reset (GdmConversation *conversation) - gtk_widget_hide (extension->priv->prompt_entry); - gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); - gtk_entry_set_visibility (GTK_ENTRY (extension->priv->prompt_entry), TRUE); -+ gtk_action_set_visible (extension->priv->login_action, FALSE); - extension->priv->answer_pending = FALSE; - - gdm_task_set_enabled (GDM_TASK (conversation), FALSE); -@@ -251,6 +255,7 @@ gdm_smartcard_extension_request_answer (GdmConversation *conversation) - gtk_widget_hide (extension->priv->prompt_entry); - gtk_label_set_text (GTK_LABEL (extension->priv->prompt_label), ""); - gtk_entry_set_text (GTK_ENTRY (extension->priv->prompt_entry), ""); -+ gtk_action_set_visible (extension->priv->login_action, FALSE); - } - - gboolean -@@ -375,11 +380,30 @@ create_page (GdmSmartcardExtension *extension) - } - - static void -+on_activate_log_in (GdmSmartcardExtension *extension) ++int ++main (int argc, ++ char *argv[]) +{ -+ gdm_smartcard_extension_request_answer (GDM_CONVERSATION (extension)); -+} ++ GdmSmartcardManager *manager; ++ GError *error; + -+static void - create_actions (GdmSmartcardExtension *extension) - { - GtkAction *action; - - extension->priv->actions = gtk_action_group_new ("gdm-smartcard-extension"); ++ g_log_set_always_fatal (G_LOG_LEVEL_ERROR ++ | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); + -+ action = gtk_action_new (GDM_CONVERSATION_DEFAULT_ACTION, -+ _("Log In"), -+ _("Log into the currently selected sesson"), -+ NULL); -+ g_signal_connect_swapped (action, "activate", -+ G_CALLBACK (on_activate_log_in), extension); -+ g_object_set (G_OBJECT (action), "icon-name", "go-home", NULL); -+ gtk_action_group_add_action (extension->priv->actions, -+ action); ++ g_type_init (); + -+ gtk_action_set_visible (action, FALSE); -+ extension->priv->login_action = action; - } - - static void --- -1.6.1 - - -From ecdb7ca6d5a3942352617b1cfea4a89ae06d1ae3 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 23 Feb 2009 17:57:06 -0500 -Subject: [PATCH 46/65] Add a new "choosable" property to show tasks in user list - -Useful for Smartcard and some future "Guest" account plugin ---- - gui/simple-greeter/gdm-greeter-login-window.c | 13 ++++++++++--- - gui/simple-greeter/libgdmsimplegreeter/gdm-task.c | 6 ++++++ - gui/simple-greeter/libgdmsimplegreeter/gdm-task.h | 2 ++ - .../fingerprint/gdm-fingerprint-extension.c | 7 +++++++ - .../plugins/password/gdm-password-extension.c | 7 +++++++ - .../plugins/smartcard/gdm-smartcard-extension.c | 7 +++++++ - 6 files changed, 39 insertions(+), 3 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 7739a7c..9f10cb3 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -2436,9 +2436,6 @@ gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, - g_debug ("GdmGreeterLoginWindow: new extension '%s - %s' added", - name, description); - -- g_free (name); -- g_free (description); -- - if (gdm_task_list_get_number_of_tasks (GDM_TASK_LIST (login_window->priv->conversation_list)) == 0) { - gtk_widget_hide (login_window->priv->conversation_list); - } else { -@@ -2449,6 +2446,16 @@ gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, - GDM_TASK (extension)); - - service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (extension)); ++ g_message ("creating instance of 'smartcard manager' object..."); ++ manager = gdm_smartcard_manager_new (NULL); ++ g_message ("'smartcard manager' object created successfully"); + -+ if (gdm_task_is_choosable (GDM_TASK (extension))) { -+ gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser), -+ service_name, NULL, name, description, ~0, -+ FALSE, TRUE); ++ g_signal_connect (manager, "smartcard-inserted", ++ G_CALLBACK (on_device_inserted), NULL); ++ ++ g_signal_connect (manager, "smartcard-removed", ++ G_CALLBACK (on_device_removed), NULL); ++ ++ g_message ("starting listener..."); ++ ++ error = NULL; ++ if (!gdm_smartcard_manager_start (manager, &error)) { ++ g_warning ("could not start smartcard manager - %s", ++ error->message); ++ g_error_free (error); ++ return 1; + } + -+ g_free (name); -+ g_free (description); ++ event_loop = g_main_loop_new (NULL, FALSE); ++ g_main_loop_run (event_loop); ++ g_main_loop_unref (event_loop); ++ event_loop = NULL; ++ ++ g_message ("destroying previously created 'smartcard manager' object..."); ++ g_object_unref (manager); ++ manager = NULL; ++ g_message ("'smartcard manager' object destroyed successfully"); ++ ++ return 0; ++} ++#endif +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.h +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.h 2009-03-03 17:45:05.742019456 -0500 +@@ -0,0 +1,86 @@ ++/* gdm-smartcard-manager.h - object for monitoring smartcard insertion and ++ * removal events ++ * ++ * Copyright (C) 2006, 2009 Red Hat, Inc. ++ * ++ * 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, 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 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written by: Ray Strode ++ */ ++#ifndef GDM_SMARTCARD_MANAGER_H ++#define GDM_SMARTCARD_MANAGER_H ++ ++#define GDM_SMARTCARD_ENABLE_INTERNAL_API ++#include "gdm-smartcard.h" + - g_debug ("GdmGreeterLoginWindow: starting conversation with '%s'", service_name); - g_signal_emit (login_window, signals[START_CONVERSATION], 0, service_name); - g_free (service_name); -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c -index f72fa78..05fd75c 100644 ---- a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c -@@ -88,6 +88,12 @@ gdm_task_is_enabled (GdmTask *task) - return !g_object_get_data (G_OBJECT (task), "gdm-task-is-disabled"); - } - -+gboolean -+gdm_task_is_choosable (GdmTask *task) -+{ -+ return GDM_TASK_GET_IFACE (task)->is_choosable (task); -+} ++#include ++#include + - static void - gdm_task_class_init (gpointer g_iface) - { -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h -index 9894e65..c75bf29 100644 ---- a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h -@@ -44,6 +44,7 @@ struct _GdmTaskIface - GIcon * (* get_icon) (GdmTask *task); - char * (* get_description) (GdmTask *task); - char * (* get_name) (GdmTask *task); -+ gboolean (* is_choosable) (GdmTask *task); - /* signals */ - void (* enabled) (GdmTask *task); - void (* disabled) (GdmTask *task); -@@ -57,6 +58,7 @@ char *gdm_task_get_name (GdmTask *task); - void gdm_task_set_enabled (GdmTask *task, - gboolean should_enable); - gboolean gdm_task_is_enabled (GdmTask *task); -+gboolean gdm_task_is_choosable (GdmTask *task); - G_END_DECLS - - #endif /* __GDM_TASK_H */ -diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -index 7f5eb1c..7c74ecf 100644 ---- a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -+++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -@@ -188,12 +188,19 @@ gdm_fingerprint_extension_get_description (GdmTask *task) - return g_strdup (_("Log into session with fingerprint")); - } - -+gboolean -+gdm_fingerprint_extension_is_choosable (GdmTask *task) -+{ -+ return FALSE; -+} ++G_BEGIN_DECLS ++#define GDM_TYPE_SMARTCARD_MANAGER (gdm_smartcard_manager_get_type ()) ++#define GDM_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SMARTCARD_MANAGER, GdmSmartcardManager)) ++#define GDM_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SMARTCARD_MANAGER, GdmSmartcardManagerClass)) ++#define GDM_IS_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SMARTCARD_MANAGER)) ++#define GDM_IS_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SMARTCARD_MANAGER)) ++#define GDM_SMARTCARD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SMARTCARD_MANAGER, GdmSmartcardManagerClass)) ++#define GDM_SMARTCARD_MANAGER_ERROR (gdm_smartcard_manager_error_quark ()) ++typedef struct _GdmSmartcardManager GdmSmartcardManager; ++typedef struct _GdmSmartcardManagerClass GdmSmartcardManagerClass; ++typedef struct _GdmSmartcardManagerPrivate GdmSmartcardManagerPrivate; ++typedef enum _GdmSmartcardManagerError GdmSmartcardManagerError; + - static void - gdm_task_iface_init (GdmTaskIface *iface) - { - iface->get_icon = gdm_fingerprint_extension_get_icon; - iface->get_description = gdm_fingerprint_extension_get_description; - iface->get_name = gdm_fingerprint_extension_get_name; -+ iface->is_choosable = gdm_fingerprint_extension_is_choosable; - } - - static void -diff --git a/gui/simple-greeter/plugins/password/gdm-password-extension.c b/gui/simple-greeter/plugins/password/gdm-password-extension.c -index fae73be..e6c608a 100644 ---- a/gui/simple-greeter/plugins/password/gdm-password-extension.c -+++ b/gui/simple-greeter/plugins/password/gdm-password-extension.c -@@ -188,12 +188,19 @@ gdm_password_extension_get_description (GdmTask *task) - return g_strdup (_("Log into session with username and password")); - } - -+gboolean -+gdm_password_extension_is_choosable (GdmTask *task) -+{ -+ return FALSE; -+} ++struct _GdmSmartcardManager { ++ GObject parent; + - static void - gdm_task_iface_init (GdmTaskIface *iface) - { - iface->get_icon = gdm_password_extension_get_icon; - iface->get_description = gdm_password_extension_get_description; - iface->get_name = gdm_password_extension_get_name; -+ iface->is_choosable = gdm_password_extension_is_choosable; - } - - static void -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -index 621d1ab..f09b4e4 100644 ---- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -290,12 +290,19 @@ gdm_smartcard_extension_get_description (GdmTask *task) - return g_strdup (_("Log into session with smartcard")); - } - -+gboolean -+gdm_smartcard_extension_is_choosable (GdmTask *task) -+{ -+ return TRUE; -+} ++ /*< private > */ ++ GdmSmartcardManagerPrivate *priv; ++}; + - static void - gdm_task_iface_init (GdmTaskIface *iface) - { - iface->get_icon = gdm_smartcard_extension_get_icon; - iface->get_description = gdm_smartcard_extension_get_description; - iface->get_name = gdm_smartcard_extension_get_name; -+ iface->is_choosable = gdm_smartcard_extension_is_choosable; - } - - static void --- -1.6.1 - - -From e25c0b355484745edf2f21f823bd78eb27570e0d Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 24 Feb 2009 15:12:35 -0500 -Subject: [PATCH 47/65] Separate handling of non-users in user list from users - -Now get_chosen_user returns NULL if the activated item -wasn't a user. We also separate the handling of on item -activation in two functions depending on the item type. - -This will be useful for adding custom handling for plugin -added items. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 47 ++++++++++++-------- - gui/simple-greeter/gdm-user-chooser-widget.c | 19 ++++++++- - .../fingerprint/gdm-fingerprint-extension.c | 2 - - 3 files changed, 47 insertions(+), 21 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 9f10cb3..f46ec78 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -1596,29 +1596,46 @@ begin_task_verification_for_selected_user (GdmTaskList *task_list, - } - - static void --on_user_chosen (GdmUserChooserWidget *user_chooser, -- GdmGreeterLoginWindow *login_window) -+on_user_chosen (GdmGreeterLoginWindow *login_window, -+ const char *user_name) - { -- char *user_name; -+ g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); ++struct _GdmSmartcardManagerClass { ++ GObjectClass parent_class; + -+ g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED], -+ 0, user_name); ++ /* Signals */ ++ void (*smartcard_inserted) (GdmSmartcardManager *manager, ++ GdmSmartcard *token); ++ void (*smartcard_removed) (GdmSmartcardManager *manager, ++ GdmSmartcard *token); ++ void (*error) (GdmSmartcardManager *manager, ++ GError *error); ++}; + -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ begin_task_verification_for_selected_user, -+ login_window); ++enum _GdmSmartcardManagerError { ++ GDM_SMARTCARD_MANAGER_ERROR_GENERIC = 0, ++ GDM_SMARTCARD_MANAGER_ERROR_WITH_NSS, ++ GDM_SMARTCARD_MANAGER_ERROR_LOADING_DRIVER, ++ GDM_SMARTCARD_MANAGER_ERROR_WATCHING_FOR_EVENTS, ++ GDM_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS ++}; + -+ switch_mode (login_window, MODE_AUTHENTICATION); -+} ++GType gdm_smartcard_manager_get_type (void) G_GNUC_CONST; ++GQuark gdm_smartcard_manager_error_quark (void) G_GNUC_CONST; + -+static void -+on_user_chooser_activated (GdmUserChooserWidget *user_chooser, -+ GdmGreeterLoginWindow *login_window) -+{ -+ char *item_id; - - user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser)); - g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); - -- if (user_name == NULL) { -+ if (user_name != NULL) { -+ on_user_chosen (login_window, user_name); -+ g_free (user_name); - return; - } - -- g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED], -- 0, user_name); -+ item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (user_chooser)); - -- if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) { -+ if (strcmp (item_id, GDM_USER_CHOOSER_USER_OTHER) == 0) { - gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), - (GdmTaskListForeachFunc) - begin_task_verification, - login_window); -- } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_GUEST) == 0) { -- /* FIXME: handle guest account stuff */ -- } else if (strcmp (user_name, GDM_USER_CHOOSER_USER_AUTO) == 0) { -+ g_free (item_id); -+ } else if (strcmp (item_id, GDM_USER_CHOOSER_USER_AUTO) == 0) { - g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, - login_window->priv->timed_login_username); - -@@ -1628,16 +1645,10 @@ on_user_chosen (GdmUserChooserWidget *user_chooser, - /* just wait for the user to select language and stuff */ - set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); - set_message (login_window, _("Select language and click Log In")); -- } else { -- gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- begin_task_verification_for_selected_user, -- login_window); -+ g_free (item_id); - } - - switch_mode (login_window, MODE_AUTHENTICATION); -- -- g_free (user_name); - } - - static void -@@ -1926,7 +1937,7 @@ load_theme (GdmGreeterLoginWindow *login_window) - login_window); - g_signal_connect (login_window->priv->user_chooser, - "activated", -- G_CALLBACK (on_user_chosen), -+ G_CALLBACK (on_user_chooser_activated), - login_window); - g_signal_connect (login_window->priv->user_chooser, - "deactivated", -diff --git a/gui/simple-greeter/gdm-user-chooser-widget.c b/gui/simple-greeter/gdm-user-chooser-widget.c -index 08420b8..e569b7b 100644 ---- a/gui/simple-greeter/gdm-user-chooser-widget.c -+++ b/gui/simple-greeter/gdm-user-chooser-widget.c -@@ -233,9 +233,26 @@ gdm_user_chooser_widget_set_show_user_auto (GdmUserChooserWidget *widget, - char * - gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget) - { -+ char *active_item_id; -+ gboolean isnt_user; ++GdmSmartcardManager *gdm_smartcard_manager_new (const char *module); + - g_return_val_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget), NULL); -+ active_item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget)); ++gboolean gdm_smartcard_manager_start (GdmSmartcardManager *manager, ++ GError **error); + -+ if (active_item_id == NULL) { -+ return NULL; -+ } ++void gdm_smartcard_manager_stop (GdmSmartcardManager *manager); + -+ gdm_chooser_widget_lookup_item (GDM_CHOOSER_WIDGET (widget), active_item_id, -+ NULL, NULL, NULL, NULL, NULL, -+ &isnt_user); ++char *gdm_smartcard_manager_get_module_path (GdmSmartcardManager *manager); ++gboolean gdm_smartcard_manager_login_token_is_inserted (GdmSmartcardManager *manager); + -+ if (isnt_user) { -+ g_free (active_item_id); -+ return NULL; -+ } - -- return gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget)); -+ return active_item_id; - } - - void -diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -index 7c74ecf..63f6ef3 100644 ---- a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -+++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -@@ -287,8 +287,6 @@ create_page (GdmFingerprintExtension *extension) - static void - create_actions (GdmFingerprintExtension *extension) - { -- GtkAction *action; -- - extension->priv->actions = gtk_action_group_new ("gdm-fingerprint-extension"); - } - --- -1.6.1 - - -From bd66c8fb770fff47761521509e78f7a320a96957 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 24 Feb 2009 16:54:34 -0500 -Subject: [PATCH 48/65] Fix compile warning - ---- - daemon/gdm-greeter-server.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c -index 5bf1f8a..ecb2ad6 100644 ---- a/daemon/gdm-greeter-server.c -+++ b/daemon/gdm-greeter-server.c -@@ -304,6 +304,7 @@ gdm_greeter_server_conversation_stopped (GdmGreeterServer *greeter_server, - const char *service_name) - { - send_dbus_string_signal (greeter_server, "ConversationStopped", service_name); -+ return TRUE; - } - - void --- -1.6.1 - - -From 06d075066911d897c2577628ec1049519e608796 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 25 Feb 2009 10:56:43 -0500 -Subject: [PATCH 49/65] Add some casts to fix compile warnings - ---- - gui/simple-greeter/gdm-user-chooser-widget.c | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/gui/simple-greeter/gdm-user-chooser-widget.c b/gui/simple-greeter/gdm-user-chooser-widget.c -index e569b7b..f8d5109 100644 ---- a/gui/simple-greeter/gdm-user-chooser-widget.c -+++ b/gui/simple-greeter/gdm-user-chooser-widget.c -@@ -357,7 +357,7 @@ add_user (GdmUserChooserWidget *widget, - return; - } - -- size = get_icon_height_for_widget (widget); -+ size = get_icon_height_for_widget (GTK_WIDGET (widget)); - pixbuf = gdm_user_render_icon (user, size); - if (pixbuf == NULL && widget->priv->stock_person_pixbuf != NULL) { - pixbuf = g_object_ref (widget->priv->stock_person_pixbuf); -@@ -597,7 +597,7 @@ get_stock_person_pixbuf (GdmUserChooserWidget *widget) - GdkPixbuf *pixbuf; - int size; - -- size = get_icon_height_for_widget (widget); -+ size = get_icon_height_for_widget (GTK_WIDGET (widget)); - - pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme, - DEFAULT_USER_ICON, -@@ -614,7 +614,7 @@ get_logged_in_pixbuf (GdmUserChooserWidget *widget) - GdkPixbuf *pixbuf; - int size; - -- size = get_icon_height_for_widget (widget); -+ size = get_icon_height_for_widget (GTK_WIDGET (widget)); - - pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme, - "emblem-default", --- -1.6.1 - - -From 36cbbb0bcda778c0da65980a38193d77de65057f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 27 Feb 2009 15:34:04 -0500 -Subject: [PATCH 50/65] Add newline on debug messages in sc helper - ---- - .../plugins/smartcard/gdm-smartcard-worker.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c -index 7fe4cf4..75e4f33 100644 ---- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c -@@ -124,7 +124,7 @@ on_debug_message (const char *log_domain, - const char *message, - gpointer user_data) - { -- g_printerr ("*** DEBUG: %s", message); -+ g_printerr ("*** DEBUG: %s\n", message); - } - - int --- -1.6.1 - - -From 86ab5470d491c686d1ad50acea58f3504bf3f981 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 27 Feb 2009 15:43:00 -0500 -Subject: [PATCH 51/65] Make password auth strictly password based - ---- - gui/simple-greeter/plugins/password/gdm-password | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/plugins/password/gdm-password b/gui/simple-greeter/plugins/password/gdm-password -index d17f7b1..5d4fb3a 100644 ---- a/gui/simple-greeter/plugins/password/gdm-password -+++ b/gui/simple-greeter/plugins/password/gdm-password -@@ -1,6 +1,6 @@ - #%PAM-1.0 - auth required pam_env.so --auth substack system-auth -+auth required pam_unix.so - auth optional pam_gnome_keyring.so - account required pam_nologin.so - account include system-auth --- -1.6.1 - - -From 58199fdcb04deddb0438558326e86954fe81c056 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 27 Feb 2009 15:44:13 -0500 -Subject: [PATCH 52/65] Initiate smart card auth when clicking on it in list - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 21 ++++++++++++++++++++ - .../plugins/smartcard/gdm-smartcard-extension.c | 2 +- - 2 files changed, 22 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index f46ec78..fcb5267 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -807,6 +807,7 @@ reset_dialog (GdmGreeterLoginWindow *login_window) - set_message (login_window, ""); - switch_mode (login_window, MODE_SELECTION); - -+ gtk_widget_set_sensitive (login_window->priv->conversation_list, TRUE); - set_sensitive (login_window, TRUE); - set_ready (login_window); - set_focus (GDM_GREETER_LOGIN_WINDOW (login_window)); -@@ -1616,6 +1617,7 @@ static void - on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - GdmGreeterLoginWindow *login_window) - { -+ char *user_name; - char *item_id; - - user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser)); -@@ -1646,6 +1648,25 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); - set_message (login_window, _("Select language and click Log In")); - g_free (item_id); -+ } else { -+ GdmTask *task; ++G_END_DECLS ++#endif /* GDM_SMARTCARD_MANAGER_H */ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard 2009-03-03 17:45:05.755021895 -0500 +@@ -0,0 +1,11 @@ ++#%PAM-1.0 ++auth required pam_env.so ++auth required pam_pkcs11.so wait_for_card ++account required pam_nologin.so ++account include system-auth ++password include system-auth ++session required pam_loginuid.so ++session optional pam_console.so ++session optional pam_keyinit.so force revoke ++session required pam_namespace.so ++session include system-auth +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c 2009-03-03 17:45:05.785021051 -0500 +@@ -0,0 +1,167 @@ ++#include "config.h" + -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) item_id); ++#include ++#include ++#include ++#include + -+ if (task == NULL) { -+ return; -+ } ++#include + -+ /* FIXME: we should probably give the plugin more say for -+ * what happens here. -+ */ -+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, item_id); -+ g_free (item_id); ++#include "gdm-smartcard-manager.h" ++#include "gdm-smartcard.h" + -+ gtk_widget_set_sensitive (login_window->priv->conversation_list, FALSE); - } - - switch_mode (login_window, MODE_AUTHENTICATION); -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -index f09b4e4..8e87db6 100644 ---- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -103,7 +103,7 @@ on_smartcard_event (GIOChannel *io_channel, - - if (extension->priv->number_of_tokens == 1) { - gdm_conversation_choose_user (GDM_CONVERSATION (extension), -- GDM_CONVERSATION_OTHER_USER); -+ PAMSERVICENAME); - } else if (extension->priv->number_of_tokens == 0) { - gdm_conversation_cancel (GDM_CONVERSATION (extension)); - } --- -1.6.1 - - -From a0142a0ae53b5931ba219d5c47c2a547967522dc Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 09:37:26 -0500 -Subject: [PATCH 53/65] Add some debug spew - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 9 ++++++++- - 1 files changed, 8 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index fcb5267..b0c3ae1 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -1621,23 +1621,26 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - char *item_id; - - user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser)); -- g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); - - if (user_name != NULL) { -+ g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); - on_user_chosen (login_window, user_name); - g_free (user_name); - return; - } - - item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (user_chooser)); -+ g_debug ("GdmGreeterLoginWindow: item chosen '%s'", item_id); - - if (strcmp (item_id, GDM_USER_CHOOSER_USER_OTHER) == 0) { -+ g_debug ("GdmGreeterLoginWindow: Starting all auth conversations"); - gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), - (GdmTaskListForeachFunc) - begin_task_verification, - login_window); - g_free (item_id); - } else if (strcmp (item_id, GDM_USER_CHOOSER_USER_AUTO) == 0) { -+ g_debug ("GdmGreeterLoginWindow: Starting auto login"); - g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, - login_window->priv->timed_login_username); - -@@ -1657,8 +1660,11 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - (gpointer) item_id); - - if (task == NULL) { -+ g_debug ("GdmGreeterLoginWindow: %s has no task associated with it", item_id); -+ g_free (item_id); - return; - } -+ g_debug ("GdmGreeterLoginWindow: Beginning auth conversation for item %s", item_id); - - /* FIXME: we should probably give the plugin more say for - * what happens here. -@@ -1669,6 +1675,7 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - gtk_widget_set_sensitive (login_window->priv->conversation_list, FALSE); - } - -+ g_debug ("GdmGreeterLoginWindow: Switching to shrunken authentication mode"); - switch_mode (login_window, MODE_AUTHENTICATION); - } - --- -1.6.1 - - -From 99a6c0de0e439b29cb4e2f19ecd9a0b059d83906 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 10:07:03 -0500 -Subject: [PATCH 54/65] Work around g_warning - ---- - gui/simple-greeter/gdm-chooser-widget.c | 31 ++++++++++++++++++++++++------- - 1 files changed, 24 insertions(+), 7 deletions(-) - -diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c -index e5ddf78..a7dbba5 100644 ---- a/gui/simple-greeter/gdm-chooser-widget.c -+++ b/gui/simple-greeter/gdm-chooser-widget.c -@@ -2133,13 +2133,30 @@ gdm_chooser_widget_lookup_item (GdmChooserWidget *widget, - } - g_free (active_item_id); - -- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -- CHOOSER_IMAGE_COLUMN, image, -- CHOOSER_NAME_COLUMN, name, -- CHOOSER_PRIORITY_COLUMN, priority, -- CHOOSER_ITEM_IS_IN_USE_COLUMN, is_in_use, -- CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate, -- -1); -+ if (image != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_IMAGE_COLUMN, image, -1); -+ } ++#ifndef GDM_SMARTCARDS_CONF ++#define GDM_SMARTCARDS_CONF GDMCONFDIR "/smartcards.conf" ++#endif + -+ if (name != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_NAME_COLUMN, name, -1); -+ } ++#ifndef GDM_SMARTCARDS_GROUP ++#define GDM_SMARTCARDS_GROUP "Smartcards" ++#endif + -+ if (priority != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_PRIORITY_COLUMN, priority, -1); -+ } ++#ifndef GDM_SMARTCARDS_KEY_ENABLED ++#define GDM_SMARTCARDS_KEY_ENABLED "Enabled" ++#endif + -+ if (is_in_use != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_ITEM_IS_IN_USE_COLUMN, is_in_use, -1); -+ } ++#ifndef GDM_SMARTCARDS_KEY_DRIVER ++#define GDM_SMARTCARDS_KEY_DRIVER "Driver" ++#endif + -+ if (is_separate != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate, -1); -+ } - - return TRUE; - } --- -1.6.1 - - -From 80c19c24a14976ad2b574ea7c504ddf359bacb0e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 11:09:27 -0500 -Subject: [PATCH 55/65] add debug spew - ---- - gui/simple-greeter/gdm-user-chooser-widget.c | 6 +++++- - 1 files changed, 5 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/gdm-user-chooser-widget.c b/gui/simple-greeter/gdm-user-chooser-widget.c -index f8d5109..bc83f39 100644 ---- a/gui/simple-greeter/gdm-user-chooser-widget.c -+++ b/gui/simple-greeter/gdm-user-chooser-widget.c -@@ -237,9 +237,10 @@ gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget) - gboolean isnt_user; - - g_return_val_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget), NULL); -- active_item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget)); - -+ active_item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget)); - if (active_item_id == NULL) { -+ g_debug ("GdmUserChooserWidget: no active item in list"); - return NULL; - } - -@@ -248,10 +249,13 @@ gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget) - &isnt_user); - - if (isnt_user) { -+ g_debug ("GdmUserChooserWidget: active item '%s' isn't a user", active_item_id); - g_free (active_item_id); - return NULL; - } - -+ g_debug ("GdmUserChooserWidget: active item '%s' is a user", active_item_id); ++static GMainLoop *event_loop; ++static GdmSmartcardManager *manager; ++static int signal_pipe_fds[2] = { -1, -1 }; + - return active_item_id; - } - --- -1.6.1 - - -From 46ce0e98d3e9c27bad63c15374e54eafe7b87151 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 11:10:28 -0500 -Subject: [PATCH 56/65] Only show task list if user is selected - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 49 ++++++++++++++++--------- - gui/simple-greeter/gdm-task-list.c | 11 +++++- - 2 files changed, 41 insertions(+), 19 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index b0c3ae1..a81cd09 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -105,7 +105,8 @@ - - enum { - MODE_SELECTION = 0, -- MODE_AUTHENTICATION -+ MODE_SINGLE_AUTHENTICATION, -+ MODE_MULTIPLE_AUTHENTICATION, - }; - - enum { -@@ -586,7 +587,8 @@ sensitize_power_buttons_timeout (GdmGreeterLoginWindow *login_window) - sensitize_widget (login_window, "suspend-button", TRUE); - sensitize_widget (login_window, "disconnect-button", TRUE); - break; -- case MODE_AUTHENTICATION: -+ case MODE_SINGLE_AUTHENTICATION: -+ case MODE_MULTIPLE_AUTHENTICATION: - break; - default: - g_assert_not_reached (); -@@ -614,6 +616,7 @@ switch_mode (GdmGreeterLoginWindow *login_window, - GtkWidget *box; - gboolean show_restart_buttons; - gboolean show_suspend_button; -+ int number_of_tasks; - - show_restart_buttons = get_show_restart_buttons (login_window); - show_suspend_button = can_suspend (login_window); -@@ -644,6 +647,8 @@ switch_mode (GdmGreeterLoginWindow *login_window, - ! login_window->priv->display_is_local); - - show_widget (login_window, "auth-page-box", FALSE); -+ show_widget (login_window, "conversation-list", FALSE); -+ gtk_widget_set_sensitive (login_window->priv->conversation_list, TRUE); - - add_sensitize_power_buttons_timeout (login_window); - sensitize_widget (login_window, "shutdown-button", FALSE); -@@ -653,7 +658,8 @@ switch_mode (GdmGreeterLoginWindow *login_window, - - default_name = NULL; - break; -- case MODE_AUTHENTICATION: -+ case MODE_SINGLE_AUTHENTICATION: -+ case MODE_MULTIPLE_AUTHENTICATION: - gtk_widget_set_size_request (GTK_WIDGET (login_window), - GTK_WIDGET (login_window)->allocation.width, - -1); -@@ -663,6 +669,18 @@ switch_mode (GdmGreeterLoginWindow *login_window, - show_widget (login_window, "suspend-button", FALSE); - show_widget (login_window, "disconnect-button", FALSE); - show_widget (login_window, "auth-page-box", TRUE); ++static void ++on_smartcard_event (const char *event_string) ++{ ++ g_debug ("smartcard event '%s' happened", event_string); ++ g_print ("%s", event_string); ++ fflush (stdout); ++} + -+ number_of_tasks = gdm_task_list_get_number_of_tasks (GDM_TASK_LIST (login_window->priv->conversation_list)); -+ show_widget (login_window, "conversation-list", number_of_tasks > 1); ++static void ++watch_for_smartcards (void) ++{ ++ GError *error; ++ char *driver; ++ GKeyFile *cfg; + -+ if (number == MODE_SINGLE_AUTHENTICATION) { -+ g_debug ("GdmGreeterLoginWindow: Single authentication, 1 task"); -+ gtk_widget_set_sensitive (login_window->priv->conversation_list, FALSE); -+ } else { -+ g_debug ("GdmGreeterLoginWindow: Multiple authentication, %d tasks", number_of_tasks); -+ gtk_widget_set_sensitive (login_window->priv->conversation_list, TRUE); ++ cfg = g_key_file_new (); ++ ++ error = NULL; ++ driver = NULL; ++ if (g_key_file_load_from_file (cfg, GDM_SMARTCARDS_CONF, G_KEY_FILE_NONE, &error)) { ++ if (!g_key_file_get_boolean (cfg, GDM_SMARTCARDS_GROUP, GDM_SMARTCARDS_KEY_ENABLED, &error)) { ++ g_debug ("smartcard support is not enabled"); ++ goto out; + } + - default_name = "log-in-button"; - break; - default: -@@ -1610,7 +1628,7 @@ on_user_chosen (GdmGreeterLoginWindow *login_window, - begin_task_verification_for_selected_user, - login_window); - -- switch_mode (login_window, MODE_AUTHENTICATION); -+ switch_mode (login_window, MODE_MULTIPLE_AUTHENTICATION); - } - - static void -@@ -1639,6 +1657,8 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - begin_task_verification, - login_window); - g_free (item_id); -+ -+ switch_mode (login_window, MODE_MULTIPLE_AUTHENTICATION); - } else if (strcmp (item_id, GDM_USER_CHOOSER_USER_AUTO) == 0) { - g_debug ("GdmGreeterLoginWindow: Starting auto login"); - g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, -@@ -1651,6 +1671,8 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); - set_message (login_window, _("Select language and click Log In")); - g_free (item_id); -+ -+ switch_mode (login_window, MODE_SINGLE_AUTHENTICATION); - } else { - GdmTask *task; - -@@ -1665,18 +1687,17 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - return; - } - g_debug ("GdmGreeterLoginWindow: Beginning auth conversation for item %s", item_id); -- - /* FIXME: we should probably give the plugin more say for - * what happens here. - */ - g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, item_id); - g_free (item_id); - -- gtk_widget_set_sensitive (login_window->priv->conversation_list, FALSE); -- } -+ switch_mode (login_window, MODE_SINGLE_AUTHENTICATION); -+ gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), task); - -- g_debug ("GdmGreeterLoginWindow: Switching to shrunken authentication mode"); -- switch_mode (login_window, MODE_AUTHENTICATION); -+ g_object_unref (task); ++ driver = g_key_file_get_string (cfg, GDM_SMARTCARDS_GROUP, GDM_SMARTCARDS_KEY_DRIVER, NULL); ++ g_debug ("smartcards driver is set to '%s'", ++ driver == NULL || driver[0] == '\0'? "" : driver); + } - } - - static void -@@ -1984,7 +2005,6 @@ load_theme (GdmGreeterLoginWindow *login_window) - "deactivated", - G_CALLBACK (on_task_deactivated), - login_window); -- gtk_widget_show (login_window->priv->conversation_list); - - login_window->priv->auth_banner_label = glade_xml_get_widget (login_window->priv->xml, "auth-banner-label"); - /*make_label_small_italic (login_window->priv->auth_banner_label);*/ -@@ -2023,7 +2043,8 @@ gdm_greeter_login_window_key_press_event (GtkWidget *widget, - login_window = GDM_GREETER_LOGIN_WINDOW (widget); - - if (event->keyval == GDK_Escape) { -- if (login_window->priv->dialog_mode == MODE_AUTHENTICATION) { -+ if (login_window->priv->dialog_mode == MODE_SINGLE_AUTHENTICATION || -+ login_window->priv->dialog_mode == MODE_MULTIPLE_AUTHENTICATION) { - do_cancel (GDM_GREETER_LOGIN_WINDOW (widget)); - } - } -@@ -2475,12 +2496,6 @@ gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, - g_debug ("GdmGreeterLoginWindow: new extension '%s - %s' added", - name, description); - -- if (gdm_task_list_get_number_of_tasks (GDM_TASK_LIST (login_window->priv->conversation_list)) == 0) { -- gtk_widget_hide (login_window->priv->conversation_list); -- } else { -- gtk_widget_show (login_window->priv->conversation_list); -- } -- - gdm_task_list_add_task (GDM_TASK_LIST (login_window->priv->conversation_list), - GDM_TASK (extension)); - -diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c -index 25831a6..162b784 100644 ---- a/gui/simple-greeter/gdm-task-list.c -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -302,17 +302,24 @@ gdm_task_list_set_active_task (GdmTaskList *widget, - GdmTask *task) - { - GtkWidget *button; -+ gboolean was_sensitive; -+ gboolean was_activated; + -+ was_sensitive = GTK_WIDGET_SENSITIVE (widget); -+ gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE); - - button = GTK_WIDGET (g_object_get_data (G_OBJECT (task), - "gdm-task-list-button")); - -+ was_activated = FALSE; - if (GTK_WIDGET_IS_SENSITIVE (button)) { - if (gtk_widget_activate (button)) { -- return TRUE; -+ was_activated = TRUE; - } - } - -- return FALSE; -+ gtk_widget_set_sensitive (GTK_WIDGET (widget), was_sensitive); -+ return was_activated; - } - - int --- -1.6.1 - - -From 69e56ff36056bb0a58e5af91c2ab3c9c79110f6b Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 13:30:03 -0500 -Subject: [PATCH 57/65] Add debug statement - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index a81cd09..45babd0 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -889,6 +889,8 @@ gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_wind - - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - -+ g_debug ("GdmGreeterLoginWindow: conversation '%s' has stopped", service_name); ++ g_debug ("watching for smartcard insertion and removal events"); ++ manager = gdm_smartcard_manager_new (driver); ++ g_free (driver); ++ ++ g_signal_connect_swapped (manager, ++ "smartcard-inserted", ++ G_CALLBACK (on_smartcard_event), ++ "I"); ++ ++ g_signal_connect_swapped (manager, ++ "smartcard-removed", ++ G_CALLBACK (on_smartcard_event), ++ "R"); ++ ++ error = NULL; ++ if (!gdm_smartcard_manager_start (manager, &error)) { ++ g_object_unref (manager); ++ manager = NULL; ++ ++ if (error != NULL) { ++ g_debug ("%s", error->message); ++ g_error_free (error); ++ } else { ++ g_debug ("could not start smartcard manager"); ++ ++ } ++ goto out; ++ } ++out: ++ g_key_file_free (cfg); ++} ++ ++static void ++stop_watching_for_smartcards (void) ++{ ++ if (manager != NULL) { ++ gdm_smartcard_manager_stop (manager); ++ g_object_unref (manager); ++ manager = NULL; ++ } ++} + - task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), - (GdmTaskListForeachFunc) - task_has_service_name, --- -1.6.1 - - -From 09ef23cbc8b1303164f921365b197c5aac53697f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 13:31:31 -0500 -Subject: [PATCH 58/65] Plug leak - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 45babd0..6bd2707 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -905,11 +905,11 @@ gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_wind - */ - task = gdm_task_list_get_active_task (GDM_TASK_LIST (login_window->priv->conversation_list)); - -- if (gdm_task_is_enabled (task)) { -- g_object_unref (task); -- } else { -+ if (!gdm_task_is_enabled (task)) { -+ g_debug ("GdmGreeterLoginWindow: No conversations left, starting over"); - restart_conversations (login_window); - } -+ g_object_unref (task); - - return TRUE; - } --- -1.6.1 - - -From ac8977339e6684150b268128ed311937f5d4207f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 13:53:34 -0500 -Subject: [PATCH 59/65] Pull verification functions out into their own subroutines - -This makes the function smaller and easier to read ---- - gui/simple-greeter/gdm-greeter-login-window.c | 107 +++++++++++++++--------- - 1 files changed, 67 insertions(+), 40 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 6bd2707..48e94ec 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -1592,6 +1592,17 @@ begin_task_verification (GdmTaskList *task_list, - return FALSE; - } - +static void -+begin_verification (GdmGreeterLoginWindow *login_window) ++on_term_signal (int signal_number) +{ -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ begin_task_verification, -+ login_window); -+ -+ switch_mode (login_window, MODE_MULTIPLE_AUTHENTICATION); ++ close (signal_pipe_fds[1]); ++ signal_pipe_fds[1] = -1; +} + - static gboolean - begin_task_verification_for_selected_user (GdmTaskList *task_list, - GdmTask *task, -@@ -1617,6 +1628,15 @@ begin_task_verification_for_selected_user (GdmTaskList *task_list, - } - - static void -+begin_verification_for_selected_user (GdmGreeterLoginWindow *login_window) ++static gboolean ++after_term_signal (GIOChannel *io_channel, ++ GIOCondition condition, ++ gpointer data) +{ -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ begin_task_verification_for_selected_user, -+ login_window); ++ g_main_loop_quit (event_loop); ++ return FALSE; +} + +static void - on_user_chosen (GdmGreeterLoginWindow *login_window, - const char *user_name) - { -@@ -1625,15 +1645,55 @@ on_user_chosen (GdmGreeterLoginWindow *login_window, - g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED], - 0, user_name); - -- gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- begin_task_verification_for_selected_user, -- login_window); -+ begin_verification_for_selected_user (login_window); - - switch_mode (login_window, MODE_MULTIPLE_AUTHENTICATION); - } - - static void -+begin_auto_login (GdmGreeterLoginWindow *login_window) ++on_debug_message (const char *log_domain, ++ GLogLevelFlags log_level, ++ const char *message, ++ gpointer user_data) +{ -+ g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, -+ login_window->priv->timed_login_username); ++ g_printerr ("*** DEBUG: %s\n", message); ++} + -+ login_window->priv->timed_login_enabled = TRUE; -+ restart_timed_login_timeout (login_window); ++int ++main (int argc, ++ char **argv) ++{ ++ GIOChannel *io_channel; + -+ /* just wait for the user to select language and stuff */ -+ set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); -+ set_message (login_window, _("Select language and click Log In")); ++ setlocale (LC_ALL, ""); + -+ switch_mode (login_window, MODE_SINGLE_AUTHENTICATION); -+} ++ g_type_init (); + -+static void -+begin_single_service_verification (GdmGreeterLoginWindow *login_window, -+ const char *service_name) -+{ -+ GdmTask *task; ++ g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, on_debug_message, NULL); + -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) service_name); ++ event_loop = g_main_loop_new (NULL, FALSE); + -+ if (task == NULL) { -+ g_debug ("GdmGreeterLoginWindow: %s has no task associated with it", service_name); -+ return; -+ } -+ g_debug ("GdmGreeterLoginWindow: Beginning auth conversation for item %s", service_name); -+ /* FIXME: we should probably give the plugin more say for -+ * what happens here. -+ */ -+ g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, service_name); ++ watch_for_smartcards (); + -+ switch_mode (login_window, MODE_SINGLE_AUTHENTICATION); -+ gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), task); ++ signal (SIGTERM, on_term_signal); ++ signal (SIGPIPE, on_term_signal); ++ if (pipe (signal_pipe_fds) != 0) { ++ return 1; ++ } ++ fcntl (signal_pipe_fds[0], F_SETFD, FD_CLOEXEC); ++ fcntl (signal_pipe_fds[1], F_SETFD, FD_CLOEXEC); + -+ g_object_unref (task); -+} ++ io_channel = g_io_channel_unix_new (signal_pipe_fds[0]); ++ g_io_channel_set_flags (io_channel, G_IO_FLAG_NONBLOCK, NULL); ++ g_io_channel_set_encoding (io_channel, NULL, NULL); ++ g_io_channel_set_buffered (io_channel, FALSE); ++ g_io_add_watch (io_channel, G_IO_HUP, after_term_signal, NULL); ++ g_io_channel_set_close_on_unref (io_channel, TRUE); ++ g_io_channel_unref (io_channel); + -+static void - on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - GdmGreeterLoginWindow *login_window) - { -@@ -1654,51 +1714,18 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - - if (strcmp (item_id, GDM_USER_CHOOSER_USER_OTHER) == 0) { - g_debug ("GdmGreeterLoginWindow: Starting all auth conversations"); -- gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- begin_task_verification, -- login_window); - g_free (item_id); - -- switch_mode (login_window, MODE_MULTIPLE_AUTHENTICATION); -+ begin_verification (login_window); - } else if (strcmp (item_id, GDM_USER_CHOOSER_USER_AUTO) == 0) { - g_debug ("GdmGreeterLoginWindow: Starting auto login"); -- g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, -- login_window->priv->timed_login_username); -- -- login_window->priv->timed_login_enabled = TRUE; -- restart_timed_login_timeout (login_window); -- -- /* just wait for the user to select language and stuff */ -- set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); -- set_message (login_window, _("Select language and click Log In")); - g_free (item_id); - -- switch_mode (login_window, MODE_SINGLE_AUTHENTICATION); -+ begin_auto_login (login_window); - } else { -- GdmTask *task; - -- task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- task_has_service_name, -- (gpointer) item_id); -- -- if (task == NULL) { -- g_debug ("GdmGreeterLoginWindow: %s has no task associated with it", item_id); -- g_free (item_id); -- return; -- } -- g_debug ("GdmGreeterLoginWindow: Beginning auth conversation for item %s", item_id); -- /* FIXME: we should probably give the plugin more say for -- * what happens here. -- */ -- g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, item_id); -+ begin_single_service_verification (login_window, item_id); - g_free (item_id); -- -- switch_mode (login_window, MODE_SINGLE_AUTHENTICATION); -- gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), task); -- -- g_object_unref (task); - } - } - --- -1.6.1 - - -From 5f6a57bff48ab174313966b05546a7b65dce6a69 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 13:57:34 -0500 -Subject: [PATCH 60/65] Add new function find_task_with_service_name - -It hides a bunch of icky foreach calls. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 50 +++++++++++-------------- - 1 files changed, 22 insertions(+), 28 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 48e94ec..9a2f415 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -776,6 +776,20 @@ task_has_service_name (GdmTaskList *task_list, - return has_service_name; - } - -+GdmTask * -+find_task_with_service_name (GdmGreeterLoginWindow *login_window, -+ const char *service_name) -+{ -+ GdmTask *task; ++ g_main_loop_run (event_loop); + -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) service_name); ++ stop_watching_for_smartcards (); + -+ return task; ++ return 0; +} +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/Makefile.am +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/Makefile.am 2009-03-03 17:45:05.754016464 -0500 +@@ -0,0 +1,71 @@ ++NULL = + - static gboolean - reset_task (GdmTaskList *task_list, - GdmTask *task, -@@ -856,10 +870,7 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - -- task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- task_has_service_name, -- (gpointer) service_name); -+ task = find_task_with_service_name (login_window, service_name); - - if (task != NULL) { - if (gdm_chooser_widget_is_loaded (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser))) { -@@ -891,10 +902,7 @@ gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_wind - - g_debug ("GdmGreeterLoginWindow: conversation '%s' has stopped", service_name); - -- task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- task_has_service_name, -- (gpointer) service_name); -+ task = find_task_with_service_name (login_window, service_name); - - if (task != NULL) { - gdm_conversation_reset (GDM_CONVERSATION (task)); -@@ -962,10 +970,7 @@ gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window, - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - g_debug ("GdmGreeterLoginWindow: info: %s", text); - -- task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- task_has_service_name, -- (gpointer) service_name); -+ task = find_task_with_service_name (login_window, service_name); - - if (task != NULL) { - gdm_conversation_set_message (GDM_CONVERSATION (task), -@@ -986,10 +991,7 @@ gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - g_debug ("GdmGreeterLoginWindow: problem: %s", text); - -- task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- task_has_service_name, -- (gpointer) service_name); -+ task = find_task_with_service_name (login_window, service_name); - - if (task != NULL) { - gdm_conversation_set_message (GDM_CONVERSATION (task), -@@ -1091,10 +1093,8 @@ gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, - - g_debug ("GdmGreeterLoginWindow: info query: %s", text); - -- task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- task_has_service_name, -- (gpointer) service_name); ++extensiondir = $(extensionsdatadir)/smartcard ++extension_DATA = page.ui + -+ task = find_task_with_service_name (login_window, service_name); - - if (task != NULL) { - gdm_conversation_ask_question (GDM_CONVERSATION (task), -@@ -1122,10 +1122,7 @@ gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, - - g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - -- task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- task_has_service_name, -- (gpointer) service_name); -+ task = find_task_with_service_name (login_window, service_name); - - if (task != NULL) { - gdm_conversation_ask_secret (GDM_CONVERSATION (task), -@@ -1672,10 +1669,7 @@ begin_single_service_verification (GdmGreeterLoginWindow *login_window, - { - GdmTask *task; - -- task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -- (GdmTaskListForeachFunc) -- task_has_service_name, -- (gpointer) service_name); -+ task = find_task_with_service_name (login_window, service_name); - - if (task == NULL) { - g_debug ("GdmGreeterLoginWindow: %s has no task associated with it", service_name); --- -1.6.1 - - -From 6472307e358cee4f47236ad0c38757ab10c892e3 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 15:23:51 -0500 -Subject: [PATCH 61/65] Drop the different auth modes in favor of calling reset manually - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 57 +++++++++++++++---------- - 1 files changed, 35 insertions(+), 22 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 9a2f415..83f4057 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -105,8 +105,7 @@ - - enum { - MODE_SELECTION = 0, -- MODE_SINGLE_AUTHENTICATION, -- MODE_MULTIPLE_AUTHENTICATION, -+ MODE_AUTHENTICATION - }; - - enum { -@@ -587,8 +586,7 @@ sensitize_power_buttons_timeout (GdmGreeterLoginWindow *login_window) - sensitize_widget (login_window, "suspend-button", TRUE); - sensitize_widget (login_window, "disconnect-button", TRUE); - break; -- case MODE_SINGLE_AUTHENTICATION: -- case MODE_MULTIPLE_AUTHENTICATION: -+ case MODE_AUTHENTICATION: - break; - default: - g_assert_not_reached (); -@@ -648,7 +646,6 @@ switch_mode (GdmGreeterLoginWindow *login_window, - - show_widget (login_window, "auth-page-box", FALSE); - show_widget (login_window, "conversation-list", FALSE); -- gtk_widget_set_sensitive (login_window->priv->conversation_list, TRUE); - - add_sensitize_power_buttons_timeout (login_window); - sensitize_widget (login_window, "shutdown-button", FALSE); -@@ -658,8 +655,7 @@ switch_mode (GdmGreeterLoginWindow *login_window, - - default_name = NULL; - break; -- case MODE_SINGLE_AUTHENTICATION: -- case MODE_MULTIPLE_AUTHENTICATION: -+ case MODE_AUTHENTICATION: - gtk_widget_set_size_request (GTK_WIDGET (login_window), - GTK_WIDGET (login_window)->allocation.width, - -1); -@@ -673,14 +669,6 @@ switch_mode (GdmGreeterLoginWindow *login_window, - number_of_tasks = gdm_task_list_get_number_of_tasks (GDM_TASK_LIST (login_window->priv->conversation_list)); - show_widget (login_window, "conversation-list", number_of_tasks > 1); - -- if (number == MODE_SINGLE_AUTHENTICATION) { -- g_debug ("GdmGreeterLoginWindow: Single authentication, 1 task"); -- gtk_widget_set_sensitive (login_window->priv->conversation_list, FALSE); -- } else { -- g_debug ("GdmGreeterLoginWindow: Multiple authentication, %d tasks", number_of_tasks); -- gtk_widget_set_sensitive (login_window->priv->conversation_list, TRUE); -- } -- - default_name = "log-in-button"; - break; - default: -@@ -1597,7 +1585,7 @@ begin_verification (GdmGreeterLoginWindow *login_window) - begin_task_verification, - login_window); - -- switch_mode (login_window, MODE_MULTIPLE_AUTHENTICATION); -+ switch_mode (login_window, MODE_AUTHENTICATION); - } - - static gboolean -@@ -1644,7 +1632,7 @@ on_user_chosen (GdmGreeterLoginWindow *login_window, - - begin_verification_for_selected_user (login_window); - -- switch_mode (login_window, MODE_MULTIPLE_AUTHENTICATION); -+ switch_mode (login_window, MODE_AUTHENTICATION); - } - - static void -@@ -1660,7 +1648,30 @@ begin_auto_login (GdmGreeterLoginWindow *login_window) - set_log_in_button_mode (login_window, LOGIN_BUTTON_TIMED_LOGIN); - set_message (login_window, _("Select language and click Log In")); - -- switch_mode (login_window, MODE_SINGLE_AUTHENTICATION); -+ switch_mode (login_window, MODE_AUTHENTICATION); -+} ++pamservicename = gdm-smartcard + -+static gboolean -+reset_task_if_not_given (GdmTaskList *task_list, -+ GdmTask *task, -+ GdmTask *given_task) -+{ -+ if (task == given_task) { -+ return FALSE; -+ } ++AM_CPPFLAGS = \ ++ -I$(top_srcdir)/common \ ++ -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ ++ -I$(top_srcdir)/gui/simple-greeter/libgdmsimplegreeter \ ++ -DDMCONFDIR=\""$(dmconfdir)"\" \ ++ -DGDMCONFDIR=\"$(gdmconfdir)\" \ ++ -DPLUGINDATADIR=\""$(extensiondir)"\" \ ++ -DPAMSERVICENAME=\""$(pamservicename)"\" \ ++ -DSYSCONFDIR=\""$(sysconfdir)"\" \ ++ -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ ++ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ ++ -DLIBEXECDIR=\""$(libexecdir)"\" \ ++ -DLIBDIR=\""$(libdir)"\" \ ++ -DSBINDIR=\""$(sbindir)"\" \ ++ $(DISABLE_DEPRECATED_CFLAGS) \ ++ $(GTK_CFLAGS) \ ++ $(SIMPLE_GREETER_CFLAGS) \ ++ $(POLKIT_GNOME_CFLAGS) \ ++ $(NULL) + -+ gdm_conversation_reset (GDM_CONVERSATION (task)); -+ return FALSE; -+} ++plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) ++plugin_LTLIBRARIES = smartcard.la + -+static void -+reset_every_task_but_given_task (GdmGreeterLoginWindow *login_window, -+ GdmTask *task) -+{ -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ reset_task_if_not_given, -+ task); - } - - static void -@@ -1675,15 +1686,18 @@ begin_single_service_verification (GdmGreeterLoginWindow *login_window, - g_debug ("GdmGreeterLoginWindow: %s has no task associated with it", service_name); - return; - } -- g_debug ("GdmGreeterLoginWindow: Beginning auth conversation for item %s", service_name); -+ g_debug ("GdmGreeterLoginWindow: Beginning %s auth conversation", service_name); ++smartcard_la_CFLAGS = \ ++ $(SIMPLE_GREETER_CFLAGS) \ ++ $(NULL) + - /* FIXME: we should probably give the plugin more say for - * what happens here. - */ - g_signal_emit (login_window, signals[BEGIN_VERIFICATION], 0, service_name); - -- switch_mode (login_window, MODE_SINGLE_AUTHENTICATION); -+ switch_mode (login_window, MODE_AUTHENTICATION); - gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), task); - -+ reset_every_task_but_given_task (login_window, task); ++libexec_PROGRAMS = \ ++ gdm-smartcard-worker \ ++ $(NULL) + - g_object_unref (task); - } - -@@ -2066,8 +2080,7 @@ gdm_greeter_login_window_key_press_event (GtkWidget *widget, - login_window = GDM_GREETER_LOGIN_WINDOW (widget); - - if (event->keyval == GDK_Escape) { -- if (login_window->priv->dialog_mode == MODE_SINGLE_AUTHENTICATION || -- login_window->priv->dialog_mode == MODE_MULTIPLE_AUTHENTICATION) { -+ if (login_window->priv->dialog_mode == MODE_AUTHENTICATION) { - do_cancel (GDM_GREETER_LOGIN_WINDOW (widget)); - } - } --- -1.6.1 - - -From 4f14d44c0c3106bc45b2d1e72300944467fd7465 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 15:50:47 -0500 -Subject: [PATCH 62/65] Disconnect task "loaded" handler when loaded - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 26 +++++++++++++++++++++--- - 1 files changed, 22 insertions(+), 4 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 83f4057..d7f3cf3 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -850,6 +850,27 @@ do_cancel (GdmGreeterLoginWindow *login_window) - restart_conversations (login_window); - } - -+static void -+on_can_set_task_ready (GtkWidget *user_chooser, -+ GdmTask *task) -+{ -+ g_signal_handlers_disconnect_by_func (user_chooser, -+ on_can_set_task_ready, -+ task); -+ gdm_conversation_set_ready (GDM_CONVERSATION (task)); -+ g_object_unref (task); -+} + -+static void -+set_task_ready_when_loaded (GdmGreeterLoginWindow *login_window, -+ GdmTask *task) -+{ -+ g_signal_connect (login_window->priv->user_chooser, -+ "loaded", -+ G_CALLBACK (on_can_set_task_ready), -+ g_object_ref (task)); -+} ++smartcard_la_LDFLAGS = -module -avoid-version -export-dynamic ++smartcard_la_LIBADD = ../../../../common/libgdmcommon.la \ ++ ../../libgdmsimplegreeter/libgdmsimplegreeter.la ++smartcard_la_SOURCES = \ ++ gdm-smartcard-extension.h \ ++ gdm-smartcard-extension.c \ ++ plugin.c + - gboolean - gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - const char *service_name) -@@ -865,10 +886,7 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - gdm_conversation_set_ready (GDM_CONVERSATION (task)); - } else { - -- g_signal_connect_swapped (login_window->priv->user_chooser, -- "loaded", -- G_CALLBACK (gdm_conversation_set_ready), -- GDM_CONVERSATION (task)); -+ set_task_ready_when_loaded (login_window, task); - } - g_object_unref (task); - } --- -1.6.1 - - -From 2a877374cd32423b29de0d4ba42f449026446ea9 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 17:09:16 -0500 -Subject: [PATCH 63/65] Notify plugins if their user choose requests fail - -This allows the smart card plugin to cancel pending -conversations when a card gets inserted. - -This isn't perfect. We really want to only cancel -the conversations if they're for a user other -than the user the smartcard is for. ---- - common/gdm-marshal.list | 1 + - gui/simple-greeter/gdm-greeter-login-window.c | 12 ++++++++- - gui/simple-greeter/libgdmsimplegreeter/Makefile.am | 2 + - .../libgdmsimplegreeter/gdm-conversation.c | 19 +++++++++++----- - .../libgdmsimplegreeter/gdm-conversation.h | 6 ++-- - .../plugins/smartcard/gdm-smartcard-extension.c | 23 +++++++++++++++---- - 6 files changed, 47 insertions(+), 16 deletions(-) - -diff --git a/common/gdm-marshal.list b/common/gdm-marshal.list -index d5455e1..d8a9e72 100644 ---- a/common/gdm-marshal.list -+++ b/common/gdm-marshal.list -@@ -5,3 +5,4 @@ VOID:STRING,STRING - VOID:UINT,UINT - VOID:STRING,INT - VOID:DOUBLE -+BOOLEAN:STRING -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index d7f3cf3..9797e67 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -2377,7 +2377,7 @@ on_conversation_cancel (GdmGreeterLoginWindow *login_window, - do_cancel (login_window); - } - --static void -+static gboolean - on_conversation_chose_user (GdmGreeterLoginWindow *login_window, - const char *username, - GdmConversation *conversation) -@@ -2388,7 +2388,13 @@ on_conversation_chose_user (GdmGreeterLoginWindow *login_window, - name = gdm_task_get_name (GDM_TASK (conversation)); - g_warning ("Task %s is trying to choose user before list is loaded", name); - g_free (name); -- return; -+ return FALSE; -+ } ++gdm_smartcard_worker_LDADD = ../../../../common/libgdmcommon.la \ ++ $(DAEMON_LIBS) \ ++ $(GTHREAD_LIBS) \ ++ $(NSS_LIBS) \ ++ $(NULL) ++gdm_smartcard_worker_CFLAGS = $(DAEMON_CFLAGS) \ ++ $(NSS_CFLAGS) \ ++ $(NULL) ++gdm_smartcard_worker_SOURCES = \ ++ gdm-smartcard.h \ ++ gdm-smartcard.c \ ++ gdm-smartcard-manager.h \ ++ gdm-smartcard-manager.c \ ++ gdm-smartcard-worker.c \ ++ $(NULL) + -+ /* If we're already authenticating then we can't pick a user -+ */ -+ if (login_window->priv->dialog_mode == MODE_AUTHENTICATION) { -+ return FALSE; - } - - if (gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), -@@ -2396,6 +2402,8 @@ on_conversation_chose_user (GdmGreeterLoginWindow *login_window, - gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), - username); - } ++pamdir = $(PAM_PREFIX)/pam.d ++pam_DATA = $(pamservicename) + -+ return TRUE; - } - - void -diff --git a/gui/simple-greeter/libgdmsimplegreeter/Makefile.am b/gui/simple-greeter/libgdmsimplegreeter/Makefile.am -index 1ef5725..0d7a0bd 100644 ---- a/gui/simple-greeter/libgdmsimplegreeter/Makefile.am -+++ b/gui/simple-greeter/libgdmsimplegreeter/Makefile.am -@@ -3,6 +3,7 @@ NULL = - AM_CPPFLAGS = \ - -I. \ - -I.. \ -+ -I$(top_srcdir)/common \ - -DBINDIR=\"$(bindir)\" \ - -DDATADIR=\"$(datadir)\" \ - -DLIBDIR=\"$(libdir)\" \ -@@ -28,6 +29,7 @@ libgdmsimplegreeter_la_SOURCES = \ - - libgdmsimplegreeter_la_LIBADD = \ - $(GTK_LIBS) \ -+ $(top_builddir)/common/libgdmcommon.la \ - $(NULL) - - libgdmsimplegreeter_la_LDFLAGS = \ -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c -index cef435c..ee763ef 100644 ---- a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c -@@ -25,9 +25,9 @@ - #include - - #include "gdm-conversation.h" -+#include "gdm-marshal.h" - #include "gdm-task.h" - -- - enum { - ANSWER, - USER_CHOSEN, -@@ -76,12 +76,12 @@ gdm_conversation_class_init (gpointer g_iface) - signals [USER_CHOSEN] = - g_signal_new ("user-chosen", - iface_type, -- G_SIGNAL_RUN_FIRST, -+ G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GdmConversationIface, user_chosen), - NULL, - NULL, -- g_cclosure_marshal_VOID__STRING, -- G_TYPE_NONE, -+ gdm_marshal_BOOLEAN__STRING, -+ G_TYPE_BOOLEAN, - 1, G_TYPE_STRING); - signals [CANCEL] = - g_signal_new ("cancel", -@@ -171,9 +171,16 @@ gdm_conversation_cancel (GdmConversation *conversation) - { - g_signal_emit (conversation, signals [CANCEL], 0); - } --void ++EXTRA_DIST = $(extension_DATA) $(pam_DATA) + -+gboolean - gdm_conversation_choose_user (GdmConversation *conversation, - const char *username) - { -- g_signal_emit (conversation, signals [USER_CHOSEN], 0, username); -+ gboolean was_chosen; ++MAINTAINERCLEANFILES = \ ++ *~ \ ++ Makefile.in +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/page.ui +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/page.ui 2009-03-03 17:45:05.727017538 -0500 +@@ -0,0 +1,56 @@ ++ ++ ++ ++ ++ True ++ vertical ++ ++ ++ True ++ ++ ++ True ++ ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ ++ ++ 1 ++ ++ ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ ++ ++ True ++ ++ ++ 0 ++ ++ ++ ++ ++ True ++ True ++ 1 ++ ++ ++ ++ +diff -up /dev/null gdm-2.25.2/gui/simple-greeter/plugins/smartcard/plugin.c +--- /dev/null 2009-03-03 12:39:28.547009636 -0500 ++++ gdm-2.25.2/gui/simple-greeter/plugins/smartcard/plugin.c 2009-03-03 17:45:05.728011655 -0500 +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2009 Red Hat, Inc. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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. ++ * ++ * Written By: Ray Strode ++ * ++ */ + -+ was_chosen = FALSE; ++#include "gdm-smartcard-extension.h" + -+ g_signal_emit (conversation, signals [USER_CHOSEN], 0, username, &was_chosen); ++#include ++#include + -+ return was_chosen; - } -diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h -index fb4bf49..b37b21e 100644 ---- a/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h -+++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h -@@ -61,7 +61,7 @@ struct _GdmConversationIface - /* signals */ - char * (* answer) (GdmConversation *conversation); - void (* cancel) (GdmConversation *conversation); -- void (* user_chosen) (GdmConversation *conversation); -+ gboolean (* user_chosen) (GdmConversation *conversation); - }; - - GType gdm_conversation_get_type (void) G_GNUC_CONST; -@@ -85,8 +85,8 @@ gboolean gdm_conversation_focus (GdmConversation *conversation); - void gdm_conversation_answer (GdmConversation *conversation, - const char *answer); - void gdm_conversation_cancel (GdmConversation *conversation); --void gdm_conversation_choose_user (GdmConversation *conversation, -- const char *username); -+gboolean gdm_conversation_choose_user (GdmConversation *conversation, -+ const char *username); - - G_END_DECLS - -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -index 8e87db6..5a2c380 100644 ---- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -53,6 +53,7 @@ struct _GdmSmartcardExtensionPrivate - int number_of_tokens; - - guint answer_pending : 1; -+ guint select_when_ready : 1; - }; - - static void gdm_smartcard_extension_finalize (GObject *object); -@@ -102,8 +103,14 @@ on_smartcard_event (GIOChannel *io_channel, - } - - if (extension->priv->number_of_tokens == 1) { -- gdm_conversation_choose_user (GDM_CONVERSATION (extension), -- PAMSERVICENAME); -+ if (!gdm_conversation_choose_user (GDM_CONVERSATION (extension), -+ PAMSERVICENAME)) { -+ g_debug ("could not choose smart card user, cancelling..."); -+ gdm_conversation_cancel (GDM_CONVERSATION (extension)); -+ extension->priv->select_when_ready = TRUE; -+ } else { -+ g_debug ("chose smart card user!"); -+ } - } else if (extension->priv->number_of_tokens == 0) { - gdm_conversation_cancel (GDM_CONVERSATION (extension)); - } -@@ -210,10 +217,16 @@ gdm_smartcard_extension_set_ready (GdmConversation *conversation) - GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); - gdm_task_set_enabled (GDM_TASK (conversation), TRUE); - -- if (extension->priv->worker_pid <= 0) -- { -+ if (extension->priv->worker_pid <= 0) { - watch_for_smartcards (extension); -- } -+ } ++GdmGreeterExtension * ++gdm_greeter_plugin_get_extension (void) ++{ ++ static GObject *extension; + -+ if (extension->priv->select_when_ready) { -+ if (gdm_conversation_choose_user (GDM_CONVERSATION (extension), -+ PAMSERVICENAME)) { -+ extension->priv->select_when_ready = FALSE; -+ } ++ if (extension != NULL) { ++ g_object_ref (extension); ++ } else { ++ extension = g_object_new (GDM_TYPE_SMARTCARD_EXTENSION, NULL); ++ g_object_add_weak_pointer (extension, (gpointer *) &extension); + } - } - - char * --- -1.6.1 - - -From cdb57fbb1366ca4fe7314850d223cd0a79240fd9 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 3 Mar 2009 13:33:09 -0500 -Subject: [PATCH 64/65] Don't build fingerprint and smartcard plugins - -I'm staging a degenerate single stack case -for rawhide. ---- - gui/simple-greeter/plugins/Makefile.am | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/plugins/Makefile.am b/gui/simple-greeter/plugins/Makefile.am -index 3dd336f..c0390db 100644 ---- a/gui/simple-greeter/plugins/Makefile.am -+++ b/gui/simple-greeter/plugins/Makefile.am -@@ -1 +1 @@ --SUBDIRS = password fingerprint smartcard -+SUBDIRS = password --- -1.6.1 - - -From 48c2237ff7efe68e116363ce51e0a4cdc42a5c78 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 3 Mar 2009 17:15:10 -0500 -Subject: [PATCH 65/65] Use "gdm" instead of "gdm-password" - -This is so we hook into system configured auth policy ---- - gui/simple-greeter/plugins/password/Makefile.am | 9 ++------- - 1 files changed, 2 insertions(+), 7 deletions(-) - -diff --git a/gui/simple-greeter/plugins/password/Makefile.am b/gui/simple-greeter/plugins/password/Makefile.am -index e832c4d..097b18e 100644 ---- a/gui/simple-greeter/plugins/password/Makefile.am -+++ b/gui/simple-greeter/plugins/password/Makefile.am -@@ -3,8 +3,6 @@ NULL = - extensiondir = $(extensionsdatadir)/password - extension_DATA = page.ui - --pamservicename = gdm-password -- - AM_CPPFLAGS = \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/gui/simple-greeter/libnotificationarea \ -@@ -12,7 +10,7 @@ AM_CPPFLAGS = \ - -DDMCONFDIR=\""$(dmconfdir)"\" \ - -DGDMCONFDIR=\"$(gdmconfdir)\" \ - -DPLUGINDATADIR=\""$(extensiondir)"\" \ -- -DPAMSERVICENAME=\""$(pamservicename)"\" \ -+ -DPAMSERVICENAME=\""gdm"\" \ - -DSYSCONFDIR=\""$(sysconfdir)"\" \ - -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \ - -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ -@@ -39,10 +37,7 @@ password_la_SOURCES = \ - gdm-password-extension.c \ - plugin.c - --pamdir = $(PAM_PREFIX)/pam.d --pam_DATA = $(pamservicename) -- --EXTRA_DIST = $(extension_DATA) $(pam_DATA) -+EXTRA_DIST = $(extension_DATA) - - MAINTAINERCLEANFILES = \ - *~ \ --- -1.6.1 - ++ ++ return GDM_GREETER_EXTENSION (extension); ++}