diff --git a/0001-Don-t-show-lock-screen-option-if-locked-down.patch b/0001-Don-t-show-lock-screen-option-if-locked-down.patch new file mode 100644 index 0000000..e3b6d65 --- /dev/null +++ b/0001-Don-t-show-lock-screen-option-if-locked-down.patch @@ -0,0 +1,88 @@ +diff -up gdm-2.28.1/gui/user-switch-applet/applet.c.dont-show-lock-screen-if-locked-down gdm-2.28.1/gui/user-switch-applet/applet.c +--- gdm-2.28.1/gui/user-switch-applet/applet.c.dont-show-lock-screen-if-locked-down 2009-10-19 18:12:45.000000000 -0400 ++++ gdm-2.28.1/gui/user-switch-applet/applet.c 2009-10-31 19:57:21.700544070 -0400 +@@ -44,7 +44,9 @@ + #include "gdm-entry-menu-item.h" + + #define LOCKDOWN_DIR "/desktop/gnome/lockdown" +-#define LOCKDOWN_KEY LOCKDOWN_DIR "/disable_user_switching" ++#define LOCKDOWN_USER_SWITCHING_KEY LOCKDOWN_DIR "/disable_user_switching" ++#define LOCKDOWN_LOCK_SCREEN_KEY LOCKDOWN_DIR "/disable_lock_screen" ++#define LOCKDOWN_COMMAND_LINE_KEY LOCKDOWN_DIR "/disable_command_line" + + typedef enum { + GSM_PRESENCE_STATUS_AVAILABLE = 0, +@@ -1163,7 +1165,11 @@ create_sub_menu (GdmAppletData *adata) + G_CALLBACK (menuitem_style_set_cb), adata); + g_signal_connect (adata->lock_screen_item, "activate", + G_CALLBACK (on_lock_screen_activate), adata); +- gtk_widget_show (adata->lock_screen_item); ++ if (gconf_client_get_bool (adata->client, LOCKDOWN_LOCK_SCREEN_KEY, NULL)) { ++ gtk_widget_hide (adata->lock_screen_item); ++ } else { ++ gtk_widget_show (adata->lock_screen_item); ++ } + + adata->login_screen_item = gtk_image_menu_item_new_with_label (_("Switch User")); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (adata->login_screen_item), +@@ -1174,7 +1180,7 @@ create_sub_menu (GdmAppletData *adata) + G_CALLBACK (menuitem_style_set_cb), adata); + g_signal_connect (adata->login_screen_item, "activate", + G_CALLBACK (on_login_screen_activate), adata); +- /* Only show switch user if there are other users */ ++ update_switch_user (adata); + + adata->quit_session_item = gtk_image_menu_item_new_with_label (_("Quit...")); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (adata->quit_session_item), +@@ -1229,11 +1235,17 @@ client_notify_lockdown_func (GConfClient + return; + } + +- if (strcmp (key, LOCKDOWN_KEY) == 0) { ++ if (strcmp (key, LOCKDOWN_USER_SWITCHING_KEY) == 0) { + if (gconf_value_get_bool (value)) { +- set_menu_visibility (adata, FALSE); ++ gtk_widget_hide (adata->login_screen_item); + } else { +- set_menu_visibility (adata, TRUE); ++ gtk_widget_show (adata->login_screen_item); ++ } ++ } else if (strcmp (key, LOCKDOWN_LOCK_SCREEN_KEY) == 0) { ++ if (gconf_value_get_bool (value)) { ++ gtk_widget_hide (adata->lock_screen_item); ++ } else { ++ gtk_widget_show (adata->lock_screen_item); + } + } + } +@@ -1430,7 +1442,7 @@ fill_applet (PanelApplet *applet) + + /* Hide the admin context menu items if locked down or no cmd-line */ + if (gconf_client_get_bool (adata->client, +- "/desktop/gnome/lockdown/inhibit_command_line", ++ LOCKDOWN_COMMAND_LINE_KEY, + NULL) || + panel_applet_get_locked_down (applet)) { + bonobo_ui_component_set_prop (popup_component, +@@ -1502,14 +1514,19 @@ fill_applet (PanelApplet *applet) + adata->manager = gdm_user_manager_ref_default (); + setup_current_user (adata); + ++ gconf_client_add_dir (adata->client, ++ LOCKDOWN_DIR, ++ GCONF_CLIENT_PRELOAD_ONELEVEL, ++ NULL); ++ + adata->client_notify_lockdown_id = gconf_client_notify_add (adata->client, +- LOCKDOWN_KEY, ++ LOCKDOWN_DIR, + (GConfClientNotifyFunc)client_notify_lockdown_func, + adata, + NULL, + NULL); + +- if (gconf_client_get_bool (adata->client, LOCKDOWN_KEY, NULL)) { ++ if (gconf_client_get_bool (adata->client, LOCKDOWN_USER_SWITCHING_KEY, NULL)) { + set_menu_visibility (adata, FALSE); + } else { + set_menu_visibility (adata, TRUE); diff --git a/0001-Fix-gdm_slave_get_timed_login_details.patch b/0001-Fix-gdm_slave_get_timed_login_details.patch deleted file mode 100644 index 42e17cb..0000000 --- a/0001-Fix-gdm_slave_get_timed_login_details.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 9fd603874caa65791cd74aa88daf61f9f196d5c3 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 25 Sep 2009 15:07:54 -0400 -Subject: [PATCH] Fix gdm_slave_get_timed_login_details - -Before it would fail if a NULL username was passed in, -breaking autologin on the multi-stack branch. ---- - daemon/gdm-slave.c | 10 ++++++++++ - 1 files changed, 10 insertions(+), 0 deletions(-) - -diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c -index 7bc98c5..94a32ee 100644 ---- a/daemon/gdm-slave.c -+++ b/daemon/gdm-slave.c -@@ -881,6 +881,16 @@ gdm_slave_get_timed_login_details (GdmSlave *slave, - if (usernamep != NULL) { - *usernamep = gdm_slave_parse_enriched_login (slave, - username, slave->priv->display_name); -+ } else { -+ g_free (username); -+ -+ if (enabledp != NULL) { -+ *enabledp = enabled; -+ } -+ if (delayp != NULL) { -+ *delayp = delay; -+ } -+ return TRUE; - } - g_free (username); - --- -1.6.4.2 - diff --git a/fix-clock.patch b/fix-clock.patch new file mode 100644 index 0000000..62d0661 --- /dev/null +++ b/fix-clock.patch @@ -0,0 +1,168 @@ +From 87248d5c3e0a90c3b0748c7be05a9e6eac231737 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 21 Oct 2009 10:57:59 -0400 +Subject: [PATCH] Move date to tooltip in panel clock + +It's a bit long at the moment. Dropping the +date makes the screen look a little cleaner, and putting +the date in the tooltip makes it still available for those +people who want to see it. +--- + gui/simple-greeter/gdm-clock-widget.c | 97 +++++++++++++++++++++++---------- + 1 files changed, 67 insertions(+), 30 deletions(-) + +diff --git a/gui/simple-greeter/gdm-clock-widget.c b/gui/simple-greeter/gdm-clock-widget.c +index a3816d2..9008e6d 100644 +--- a/gui/simple-greeter/gdm-clock-widget.c ++++ b/gui/simple-greeter/gdm-clock-widget.c +@@ -44,8 +44,10 @@ struct GdmClockWidgetPrivate + { + GtkWidget *label; + char *time_format; ++ char *tooltip_format; + guint update_clock_id; + guint should_show_seconds : 1; ++ guint should_show_date : 1; + }; + + static void gdm_clock_widget_class_init (GdmClockWidgetClass *klass); +@@ -55,38 +57,59 @@ static gboolean update_timeout_cb (GdmClockWidget *clock); + + G_DEFINE_TYPE (GdmClockWidget, gdm_clock_widget, GTK_TYPE_ALIGNMENT) + +-static char * +-get_time_format (GdmClockWidget *clock) ++static void ++update_time_format (GdmClockWidget *clock) + { +- const char *time_format; +- const char *date_format; + char *clock_format; +- char *result; +- +- time_format = clock->priv->should_show_seconds ? _("%l:%M:%S %p") : _("%l:%M %p"); +- /* translators: replace %e with %d if, when the day of the +- * month as a decimal number is a single digit, it +- * should begin with a 0 in your locale (e.g. "May +- * 01" instead of "May 1"). +- */ +- date_format = _("%a %b %e"); +- /* translators: reverse the order of these arguments +- * if the time should come before the +- * date on a clock in your locale. +- */ +- clock_format = g_strdup_printf (_("%1$s, %2$s"), +- date_format, +- time_format); +- +- result = g_locale_from_utf8 (clock_format, -1, NULL, NULL, NULL); +- g_free (clock_format); +- +- return result; ++ char *tooltip_format; ++ ++ if (clock->priv->should_show_date && clock->priv->should_show_seconds) { ++ /* translators: This is the time format to use when both ++ * the date and time with seconds are being shown together. ++ */ ++ clock_format = _("%a %b %e, %l:%M:%S %p"); ++ tooltip_format = NULL; ++ } else if (clock->priv->should_show_date && !clock->priv->should_show_seconds) { ++ /* translators: This is the time format to use when both ++ * the date and time without seconds are being shown together. ++ */ ++ clock_format = _("%a %b %e, %l:%M %p"); ++ ++ tooltip_format = NULL; ++ } else if (!clock->priv->should_show_date && clock->priv->should_show_seconds) { ++ /* translators: This is the time format to use when there is ++ * no date, just weekday and time with seconds. ++ */ ++ clock_format = _("%a %l:%M:%S %p"); ++ ++ /* translators: This is the time format to use for the date ++ */ ++ tooltip_format = _("%x"); ++ } else { ++ /* translators: This is the time format to use when there is ++ * no date, just weekday and time without seconds. ++ */ ++ clock_format = _("%a %l:%M %p"); ++ ++ tooltip_format = _("%x"); ++ } ++ ++ g_free (clock->priv->time_format); ++ clock->priv->time_format = g_locale_from_utf8 (clock_format, -1, NULL, NULL, NULL); ++ ++ g_free (clock->priv->tooltip_format); ++ ++ if (tooltip_format != NULL) { ++ clock->priv->tooltip_format = g_locale_from_utf8 (tooltip_format, -1, NULL, NULL, NULL); ++ } else { ++ clock->priv->tooltip_format = NULL; ++ } + } + + static void + update_clock (GtkLabel *label, +- const char *format) ++ const char *clock_format, ++ const char *tooltip_format) + { + time_t t; + struct tm *tm; +@@ -99,13 +122,25 @@ update_clock (GtkLabel *label, + g_warning ("Unable to get broken down local time"); + return; + } +- if (strftime (buf, sizeof (buf), format, tm) == 0) { +- g_warning ("Couldn't format time: %s", format); ++ if (strftime (buf, sizeof (buf), clock_format, tm) == 0) { ++ g_warning ("Couldn't format time: %s", clock_format); + strcpy (buf, "???"); + } + utf8 = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL); + gtk_label_set_text (label, utf8); + g_free (utf8); ++ ++ if (tooltip_format != NULL) { ++ if (strftime (buf, sizeof (buf), tooltip_format, tm) == 0) { ++ g_warning ("Couldn't format tooltip date: %s", tooltip_format); ++ strcpy (buf, "???"); ++ } ++ utf8 = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL); ++ gtk_widget_set_tooltip_text (GTK_WIDGET (label), utf8); ++ g_free (utf8); ++ } else { ++ gtk_widget_set_has_tooltip (GTK_WIDGET (label), FALSE); ++ } + } + + static void +@@ -142,7 +177,8 @@ update_timeout_cb (GdmClockWidget *clock) + + if (clock->priv->label != NULL) { + update_clock (GTK_LABEL (clock->priv->label), +- clock->priv->time_format); ++ clock->priv->time_format, ++ clock->priv->tooltip_format); + } + + set_clock_timeout (clock, new_time); +@@ -214,10 +250,11 @@ gdm_clock_widget_init (GdmClockWidget *widget) + gtk_container_add (GTK_CONTAINER (widget), box); + + widget->priv->label = gtk_label_new (""); ++ + gtk_widget_show (widget->priv->label); + gtk_box_pack_start (GTK_BOX (box), widget->priv->label, FALSE, FALSE, 0); + +- widget->priv->time_format = get_time_format (widget); ++ update_time_format (widget); + update_timeout_cb (widget); + } + +-- +1.6.5.rc2 + diff --git a/fix-computer-info.patch b/fix-computer-info.patch new file mode 100644 index 0000000..e497980 --- /dev/null +++ b/fix-computer-info.patch @@ -0,0 +1,104 @@ +From 18bf08d14ed77db00a17e74c5ce04c812ef251af Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 26 Oct 2009 10:45:49 -0400 +Subject: [PATCH 1/2] Use gethostname instead of g_get_host_name in greeter + +The latter is unreliable when the hostname changes at runtime. +--- + gui/simple-greeter/gdm-greeter-login-window.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 9a29a2e..9d75b8c 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -996,7 +996,11 @@ create_computer_info (GdmGreeterLoginWindow *login_window) + + label = glade_xml_get_widget (login_window->priv->xml, "computer-info-name-label"); + if (label != NULL) { +- gtk_label_set_text (GTK_LABEL (label), g_get_host_name ()); ++ char localhost[HOST_NAME_MAX + 1] = "";• ++ ++ if (gethostname (localhost, HOST_NAME_MAX) == 0) {• ++ gtk_label_set_text (GTK_LABEL (label), localhost); ++ } + } + + label = glade_xml_get_widget (login_window->priv->xml, "computer-info-version-label"); +-- +1.6.5.1 + + +From 03e01936f5c11580a1485c492355eb0a468ea0f6 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 26 Oct 2009 10:53:25 -0400 +Subject: [PATCH 2/2] Don't bother showing hostname if it's not unique + +The advantage of showing hostname by default is it is a +unique identifier for people who have multiple machines. + +If it only says "localhost" or "localhost.localdomain" +that advantage is mitigated, and it's probably better to +show OS release. +--- + gui/simple-greeter/gdm-greeter-login-window.c | 27 +++++++++++++++++++----- + 1 files changed, 21 insertions(+), 6 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 9d75b8c..8de74df 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -887,10 +887,8 @@ on_user_unchosen (GdmUserChooserWidget *user_chooser, + do_cancel (login_window); + } + +-static gboolean +-on_computer_info_label_button_press (GtkWidget *widget, +- GdkEventButton *event, +- GdmGreeterLoginWindow *login_window) ++static void ++rotate_computer_info (GdmGreeterLoginWindow *login_window) + { + GtkWidget *notebook; + int current_page; +@@ -907,6 +905,14 @@ on_computer_info_label_button_press (GtkWidget *widget, + gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0); + } + ++} ++ ++static gboolean ++on_computer_info_label_button_press (GtkWidget *widget, ++ GdkEventButton *event, ++ GdmGreeterLoginWindow *login_window) ++{ ++ rotate_computer_info (login_window); + return FALSE; + } + +@@ -996,11 +1002,20 @@ create_computer_info (GdmGreeterLoginWindow *login_window) + + label = glade_xml_get_widget (login_window->priv->xml, "computer-info-name-label"); + if (label != NULL) { +- char localhost[HOST_NAME_MAX + 1] = "";• ++ char localhost[HOST_NAME_MAX + 1] = ""; + +- if (gethostname (localhost, HOST_NAME_MAX) == 0) {• ++ if (gethostname (localhost, HOST_NAME_MAX) == 0) { + gtk_label_set_text (GTK_LABEL (label), localhost); + } ++ ++ /* If this isn't actually unique identifier for the computer, then ++ * don't bother showing it by default. ++ */ ++ if (strcmp (localhost, "localhost") == 0 || ++ strcmp (localhost, "localhost.localdomain") == 0) { ++ ++ rotate_computer_info (login_window); ++ } + } + + label = glade_xml_get_widget (login_window->priv->xml, "computer-info-version-label"); +-- +1.6.5.1 + diff --git a/fix-na-tray.patch b/fix-na-tray.patch new file mode 100644 index 0000000..059afbb --- /dev/null +++ b/fix-na-tray.patch @@ -0,0 +1,1586 @@ +From f304eec1bf7dd80e255092b3cdaade10827fd320 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 22 Oct 2009 22:02:51 -0400 +Subject: [PATCH 1/4] Update na-tray to latest upstream code + +It's a copy and paste from the panel. +--- + gui/simple-greeter/libnotificationarea/Makefile.am | 2 + + gui/simple-greeter/libnotificationarea/fixedtip.c | 1 + + .../libnotificationarea/na-tray-child.c | 430 ++++++++++++++++++++ + .../libnotificationarea/na-tray-child.h | 68 +++ + .../libnotificationarea/na-tray-manager.c | 264 +++++-------- + .../libnotificationarea/na-tray-manager.h | 15 +- + gui/simple-greeter/libnotificationarea/na-tray.c | 76 +++- + gui/simple-greeter/libnotificationarea/na-tray.h | 3 +- + gui/simple-greeter/libnotificationarea/testtray.c | 2 +- + 9 files changed, 674 insertions(+), 187 deletions(-) + create mode 100644 gui/simple-greeter/libnotificationarea/na-tray-child.c + create mode 100644 gui/simple-greeter/libnotificationarea/na-tray-child.h + +diff --git a/gui/simple-greeter/libnotificationarea/Makefile.am b/gui/simple-greeter/libnotificationarea/Makefile.am +index e3a6a1f..4009aaf 100644 +--- a/gui/simple-greeter/libnotificationarea/Makefile.am ++++ b/gui/simple-greeter/libnotificationarea/Makefile.am +@@ -29,6 +29,8 @@ libnotificationarea_la_SOURCES = \ + obox.h \ + na-tray.c \ + na-tray.h \ ++ na-tray-child.c \ ++ na-tray-child.h \ + na-tray-manager.c \ + na-tray-manager.h \ + na-marshal.c \ +diff --git a/gui/simple-greeter/libnotificationarea/fixedtip.c b/gui/simple-greeter/libnotificationarea/fixedtip.c +index cc90e26..53ac923 100644 +--- a/gui/simple-greeter/libnotificationarea/fixedtip.c ++++ b/gui/simple-greeter/libnotificationarea/fixedtip.c +@@ -81,6 +81,7 @@ na_fixed_tip_class_init (NaFixedTipClass *class) + g_type_class_add_private (class, sizeof (NaFixedTipPrivate)); + } + ++/* Did you already see this code? Yes, it's gtk_tooltips_ force_window() ;-) */ + static void + na_fixed_tip_init (NaFixedTip *fixedtip) + { +diff --git a/gui/simple-greeter/libnotificationarea/na-tray-child.c b/gui/simple-greeter/libnotificationarea/na-tray-child.c +new file mode 100644 +index 0000000..c7e3f61 +--- /dev/null ++++ b/gui/simple-greeter/libnotificationarea/na-tray-child.c +@@ -0,0 +1,430 @@ ++/* na-tray-child.c ++ * Copyright (C) 2002 Anders Carlsson ++ * Copyright (C) 2003-2006 Vincent Untz ++ * Copyright (C) 2008 Red Hat, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ */ ++ ++#include ++#include ++ ++#include "na-tray-child.h" ++ ++#include ++#include ++#include ++#include ++ ++G_DEFINE_TYPE (NaTrayChild, na_tray_child, GTK_TYPE_SOCKET) ++ ++static void ++na_tray_child_finalize (GObject *object) ++{ ++ G_OBJECT_CLASS (na_tray_child_parent_class)->finalize (object); ++} ++ ++static void ++na_tray_child_realize (GtkWidget *widget) ++{ ++ NaTrayChild *child = NA_TRAY_CHILD (widget); ++ GdkVisual *visual = gtk_widget_get_visual (widget); ++ ++ GTK_WIDGET_CLASS (na_tray_child_parent_class)->realize (widget); ++ ++ if (child->has_alpha) ++ { ++ /* We have real transparency with an ARGB visual and the Composite ++ * extension. */ ++ ++ /* Set a transparent background */ ++ GdkColor transparent = { 0, 0, 0, 0 }; /* only pixel=0 matters */ ++ gdk_window_set_background (widget->window, &transparent); ++ gdk_window_set_composited (widget->window, TRUE); ++ ++ child->parent_relative_bg = FALSE; ++ } ++ else if (visual == gdk_drawable_get_visual (GDK_DRAWABLE (gdk_window_get_parent (widget->window)))) ++ { ++ /* Otherwise, if the visual matches the visual of the parent window, we ++ * can use a parent-relative background and fake transparency. */ ++ gdk_window_set_back_pixmap (widget->window, NULL, TRUE); ++ ++ child->parent_relative_bg = TRUE; ++ } ++ else ++ { ++ /* Nothing to do; the icon will sit on top of an ugly gray box */ ++ child->parent_relative_bg = FALSE; ++ } ++ ++ gdk_window_set_composited (widget->window, child->composited); ++ ++ gtk_widget_set_app_paintable (GTK_WIDGET (child), ++ child->parent_relative_bg || child->has_alpha); ++ ++ /* Double-buffering will interfere with the parent-relative-background fake ++ * transparency, since the double-buffer code doesn't know how to fill in the ++ * background of the double-buffer correctly. ++ */ ++ gtk_widget_set_double_buffered (GTK_WIDGET (child), ++ child->parent_relative_bg); ++} ++ ++static void ++na_tray_child_style_set (GtkWidget *widget, ++ GtkStyle *previous_style) ++{ ++ /* The default handler resets the background according to the new style. ++ * We either use a transparent background or a parent-relative background ++ * and ignore the style background. So, just don't chain up. ++ */ ++} ++ ++#if 0 ++/* This is adapted from code that was commented out in na-tray-manager.c; the ++ * code in na-tray-manager.c wouldn't have worked reliably, this will. So maybe ++ * it can be reenabled. On other hand, things seem to be working fine without ++ * it. ++ * ++ * If reenabling, you need to hook it up in na_tray_child_class_init(). ++ */ ++static void ++na_tray_child_size_request (GtkWidget *widget, ++ GtkRequisition *request) ++{ ++ GTK_WIDGET_CLASS (na_tray_child_parent_class)->size_request (widget, request); ++ ++ /* ++ * Make sure the icons have a meaningful size .. ++ */ ++ if ((request->width < 16) || (request->height < 16)) ++ { ++ gint nw = MAX (24, request->width); ++ gint nh = MAX (24, request->height); ++ g_warning ("Tray icon has requested a size of (%ix%i), resizing to (%ix%i)", ++ req.width, req.height, nw, nh); ++ request->width = nw; ++ request->height = nh; ++ } ++} ++#endif ++ ++static void ++na_tray_child_size_allocate (GtkWidget *widget, ++ GtkAllocation *allocation) ++{ ++ NaTrayChild *child = NA_TRAY_CHILD (widget); ++ ++ gboolean moved = allocation->x != widget->allocation.x || ++ allocation->y != widget->allocation.y; ++ gboolean resized = allocation->width != widget->allocation.width || ++ allocation->height != widget->allocation.height; ++ ++ /* When we are allocating the widget while mapped we need special handling ++ * for both real and fake transparency. ++ * ++ * Real transparency: we need to invalidate and trigger a redraw of the old ++ * and new areas. (GDK really should handle this for us, but doesn't as of ++ * GTK+-2.14) ++ * ++ * Fake transparency: if the widget moved, we need to force the contents to ++ * be redrawn with the new offset for the parent-relative background. ++ */ ++ if ((moved || resized) && GTK_WIDGET_MAPPED (widget)) ++ { ++ if (na_tray_child_has_alpha (child)) ++ gdk_window_invalidate_rect (gdk_window_get_parent (widget->window), ++ &widget->allocation, FALSE); ++ } ++ ++ GTK_WIDGET_CLASS (na_tray_child_parent_class)->size_allocate (widget, ++ allocation); ++ ++ if ((moved || resized) && GTK_WIDGET_MAPPED (widget)) ++ { ++ if (na_tray_child_has_alpha (NA_TRAY_CHILD (widget))) ++ gdk_window_invalidate_rect (gdk_window_get_parent (widget->window), ++ &widget->allocation, FALSE); ++ else if (moved && child->parent_relative_bg) ++ na_tray_child_force_redraw (child); ++ } ++} ++ ++/* The plug window should completely occupy the area of the child, so we won't ++ * get an expose event. But in case we do (the plug unmaps itself, say), this ++ * expose handler draws with real or fake transparency. ++ */ ++static gboolean ++na_tray_child_expose_event (GtkWidget *widget, ++ GdkEventExpose *event) ++{ ++ NaTrayChild *child = NA_TRAY_CHILD (widget); ++ ++ if (na_tray_child_has_alpha (child)) ++ { ++ /* Clear to transparent */ ++ cairo_t *cr = gdk_cairo_create (widget->window); ++ cairo_set_source_rgba (cr, 0, 0, 0, 0); ++ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); ++ gdk_cairo_region (cr, event->region); ++ cairo_fill (cr); ++ cairo_destroy (cr); ++ } ++ else if (child->parent_relative_bg) ++ { ++ /* Clear to parent-relative pixmap */ ++ gdk_window_clear_area (widget->window, ++ event->area.x, event->area.y, ++ event->area.width, event->area.height); ++ } ++ ++ return FALSE; ++} ++ ++static void ++na_tray_child_init (NaTrayChild *child) ++{ ++} ++ ++static void ++na_tray_child_class_init (NaTrayChildClass *klass) ++{ ++ GObjectClass *gobject_class; ++ GtkWidgetClass *widget_class; ++ ++ gobject_class = (GObjectClass *)klass; ++ widget_class = (GtkWidgetClass *)klass; ++ ++ gobject_class->finalize = na_tray_child_finalize; ++ widget_class->style_set = na_tray_child_style_set; ++ widget_class->realize = na_tray_child_realize; ++ widget_class->size_allocate = na_tray_child_size_allocate; ++ widget_class->expose_event = na_tray_child_expose_event; ++} ++ ++GtkWidget * ++na_tray_child_new (GdkScreen *screen, ++ Window icon_window) ++{ ++ XWindowAttributes window_attributes; ++ Display *xdisplay; ++ NaTrayChild *child; ++ GdkVisual *visual; ++ gboolean visual_has_alpha; ++ GdkColormap *colormap; ++ gboolean new_colormap; ++ int result; ++ ++ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); ++ g_return_val_if_fail (icon_window != None, NULL); ++ ++ xdisplay = GDK_SCREEN_XDISPLAY (screen); ++ ++ /* We need to determine the visual of the window we are embedding and create ++ * the socket in the same visual. ++ */ ++ ++ gdk_error_trap_push (); ++ result = XGetWindowAttributes (xdisplay, icon_window, ++ &window_attributes); ++ gdk_error_trap_pop (); ++ ++ if (!result) /* Window already gone */ ++ return NULL; ++ ++ visual = gdk_x11_screen_lookup_visual (screen, ++ window_attributes.visual->visualid); ++ if (!visual) /* Icon window is on another screen? */ ++ return NULL; ++ ++ new_colormap = FALSE; ++ ++ if (visual == gdk_screen_get_rgb_visual (screen)) ++ colormap = gdk_screen_get_rgb_colormap (screen); ++ else if (visual == gdk_screen_get_rgba_visual (screen)) ++ colormap = gdk_screen_get_rgba_colormap (screen); ++ else if (visual == gdk_screen_get_system_visual (screen)) ++ colormap = gdk_screen_get_system_colormap (screen); ++ else ++ { ++ colormap = gdk_colormap_new (visual, FALSE); ++ new_colormap = TRUE; ++ } ++ ++ child = g_object_new (NA_TYPE_TRAY_CHILD, NULL); ++ child->icon_window = icon_window; ++ ++ gtk_widget_set_colormap (GTK_WIDGET (child), colormap); ++ ++ /* We have alpha if the visual has something other than red, green, ++ * and blue */ ++ visual_has_alpha = visual->red_prec + visual->blue_prec + visual->green_prec < visual->depth; ++ child->has_alpha = (visual_has_alpha && ++ gdk_display_supports_composite (gdk_screen_get_display (screen))); ++ ++ child->composited = child->has_alpha; ++ ++ if (new_colormap) ++ g_object_unref (colormap); ++ ++ return GTK_WIDGET (child); ++} ++ ++char * ++na_tray_child_get_title (NaTrayChild *child) ++{ ++ char *retval = NULL; ++ GdkDisplay *display; ++ Atom utf8_string, atom, type; ++ int result; ++ int format; ++ gulong nitems; ++ gulong bytes_after; ++ gchar *val; ++ ++ g_return_val_if_fail (NA_IS_TRAY_CHILD (child), NULL); ++ ++ display = gtk_widget_get_display (GTK_WIDGET (child)); ++ ++ utf8_string = gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"); ++ atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"); ++ ++ gdk_error_trap_push (); ++ ++ result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), ++ child->icon_window, ++ atom, ++ 0, G_MAXLONG, ++ False, utf8_string, ++ &type, &format, &nitems, ++ &bytes_after, (guchar **)&val); ++ ++ if (gdk_error_trap_pop () || result != Success) ++ return NULL; ++ ++ if (type != utf8_string || ++ format != 8 || ++ nitems == 0) ++ { ++ if (val) ++ XFree (val); ++ return NULL; ++ } ++ ++ if (!g_utf8_validate (val, nitems, NULL)) ++ { ++ XFree (val); ++ return NULL; ++ } ++ ++ retval = g_strndup (val, nitems); ++ ++ XFree (val); ++ ++ return retval; ++} ++ ++/** ++ * na_tray_child_has_alpha; ++ * @child: a #NaTrayChild ++ * ++ * Checks if the child has an ARGB visual and real alpha transparence. ++ * (as opposed to faked alpha transparency with an parent-relative ++ * background) ++ * ++ * Return value: %TRUE if the child has an alpha transparency ++ */ ++gboolean ++na_tray_child_has_alpha (NaTrayChild *child) ++{ ++ g_return_val_if_fail (NA_IS_TRAY_CHILD (child), FALSE); ++ ++ return child->has_alpha; ++} ++ ++/** ++ * na_tray_child_set_composited; ++ * @child: a #NaTrayChild ++ * @composited: %TRUE if the child's window should be redirected ++ * ++ * Sets whether the #GdkWindow of the child should be set redirected ++ * using gdk_window_set_composited(). By default this is based off of ++ * na_tray_child_has_alpha(), but it may be useful to override it in ++ * certain circumstances; for example, if the #NaTrayChild is added ++ * to a parent window and that parent window is composited against the ++ * background. ++ */ ++void ++na_tray_child_set_composited (NaTrayChild *child, ++ gboolean composited) ++{ ++ g_return_if_fail (NA_IS_TRAY_CHILD (child)); ++ ++ if (child->composited == composited) ++ return; ++ ++ child->composited = composited; ++ if (GTK_WIDGET_REALIZED (child)) ++ gdk_window_set_composited (GTK_WIDGET (child)->window, composited); ++} ++ ++/* If we are faking transparency with a window-relative background, force a ++ * redraw of the icon. This should be called if the background changes or if ++ * the child is shifted with respect to the background. ++ */ ++void ++na_tray_child_force_redraw (NaTrayChild *child) ++{ ++ GtkWidget *widget = GTK_WIDGET (child); ++ ++ if (GTK_WIDGET_MAPPED (child) && child->parent_relative_bg) ++ { ++#if 1 ++ /* Sending an ExposeEvent might cause redraw problems if the ++ * icon is expecting the server to clear-to-background before ++ * the redraw. It should be ok for GtkStatusIcon or EggTrayIcon. ++ */ ++ Display *xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)); ++ XEvent xev; ++ ++ xev.xexpose.type = Expose; ++ xev.xexpose.window = GDK_WINDOW_XWINDOW (GTK_SOCKET (child)->plug_window); ++ xev.xexpose.x = 0; ++ xev.xexpose.y = 0; ++ xev.xexpose.width = widget->allocation.width; ++ xev.xexpose.height = widget->allocation.height; ++ xev.xexpose.count = 0; ++ ++ gdk_error_trap_push (); ++ XSendEvent (GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)), ++ xev.xexpose.window, ++ False, ExposureMask, ++ &xev); ++ /* We have to sync to reliably catch errors from the XSendEvent(), ++ * since that is asynchronous. ++ */ ++ XSync (xdisplay, False); ++ gdk_error_trap_pop (); ++#else ++ /* Hiding and showing is the safe way to do it, but can result in more ++ * flickering. ++ */ ++ gdk_window_hide (widget->window); ++ gdk_window_show (widget->window); ++#endif ++ } ++} +diff --git a/gui/simple-greeter/libnotificationarea/na-tray-child.h b/gui/simple-greeter/libnotificationarea/na-tray-child.h +new file mode 100644 +index 0000000..c174abe +--- /dev/null ++++ b/gui/simple-greeter/libnotificationarea/na-tray-child.h +@@ -0,0 +1,68 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* na-tray-child.h ++ * Copyright (C) 2002 Anders Carlsson ++ * Copyright (C) 2003-2006 Vincent Untz ++ * Copyright (C) 2008 Red Hat, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ */ ++ ++#ifndef __NA_TRAY_CHILD_H__ ++#define __NA_TRAY_CHILD_H__ ++ ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#define NA_TYPE_TRAY_CHILD (na_tray_child_get_type ()) ++#define NA_TRAY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_TRAY_CHILD, NaTrayChild)) ++#define NA_TRAY_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_TRAY_CHILD, NaTrayChildClass)) ++#define NA_IS_TRAY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_TRAY_CHILD)) ++#define NA_IS_TRAY_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_TRAY_CHILD)) ++#define NA_TRAY_CHILD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_TRAY_CHILD, NaTrayChildClass)) ++ ++typedef struct _NaTrayChild NaTrayChild; ++typedef struct _NaTrayChildClass NaTrayChildClass; ++typedef struct _NaTrayChildChild NaTrayChildChild; ++ ++struct _NaTrayChild ++{ ++ GtkSocket parent_instance; ++ Window icon_window; ++ guint has_alpha : 1; ++ guint composited : 1; ++ guint parent_relative_bg : 1; ++}; ++ ++struct _NaTrayChildClass ++{ ++ GtkSocketClass parent_class; ++}; ++ ++GType na_tray_child_get_type (void); ++ ++GtkWidget *na_tray_child_new (GdkScreen *screen, ++ Window icon_window); ++char *na_tray_child_get_title (NaTrayChild *child); ++gboolean na_tray_child_has_alpha (NaTrayChild *child); ++void na_tray_child_set_composited (NaTrayChild *child, ++ gboolean composited); ++void na_tray_child_force_redraw (NaTrayChild *child); ++ ++G_END_DECLS ++ ++#endif /* __NA_TRAY_CHILD_H__ */ +diff --git a/gui/simple-greeter/libnotificationarea/na-tray-manager.c b/gui/simple-greeter/libnotificationarea/na-tray-manager.c +index 4842a91..1bf54f1 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray-manager.c ++++ b/gui/simple-greeter/libnotificationarea/na-tray-manager.c +@@ -252,120 +252,61 @@ static gboolean + na_tray_manager_plug_removed (GtkSocket *socket, + NaTrayManager *manager) + { +- Window *window; ++ NaTrayChild *child = NA_TRAY_CHILD (socket); + +- window = g_object_get_data (G_OBJECT (socket), "na-tray-child-window"); +- +- g_hash_table_remove (manager->socket_table, GINT_TO_POINTER (*window)); +- g_object_set_data (G_OBJECT (socket), "na-tray-child-window", +- NULL); +- +- g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, socket); ++ g_hash_table_remove (manager->socket_table, ++ GINT_TO_POINTER (child->icon_window)); ++ g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child); + + /* This destroys the socket. */ + return FALSE; + } + + static void +-na_tray_manager_make_socket_transparent (GtkWidget *widget, +- gpointer user_data) ++na_tray_manager_handle_dock_request (NaTrayManager *manager, ++ XClientMessageEvent *xevent) + { +- if (GTK_WIDGET_NO_WINDOW (widget)) +- return; ++ Window icon_window = xevent->data.l[2]; ++ GtkWidget *child; + +- gdk_window_set_back_pixmap (widget->window, NULL, TRUE); +-} +- +-static gboolean +-na_tray_manager_socket_exposed (GtkWidget *widget, +- GdkEventExpose *event, +- gpointer user_data) +-{ +- gdk_window_clear_area (widget->window, +- event->area.x, event->area.y, +- event->area.width, event->area.height); +- return FALSE; +-} ++ if (g_hash_table_lookup (manager->socket_table, ++ GINT_TO_POINTER (icon_window))) ++ { ++ /* We already got this notification earlier, ignore this one */ ++ return; ++ } + +-static void +-na_tray_manager_socket_style_set (GtkWidget *widget, +- GtkStyle *previous_style, +- gpointer user_data) +-{ +- if (widget->window == NULL) ++ child = na_tray_child_new (manager->screen, icon_window); ++ if (child == NULL) /* already gone or other error */ + return; + +- na_tray_manager_make_socket_transparent (widget, user_data); +-} ++ g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0, ++ child); + +-static void +-na_tray_manager_handle_dock_request (NaTrayManager *manager, +- XClientMessageEvent *xevent) +-{ +- GtkWidget *socket; +- Window *window; +- GtkRequisition req; ++ /* If the child wasn't attached, then destroy it */ + +- if (g_hash_table_lookup (manager->socket_table, GINT_TO_POINTER (xevent->data.l[2]))) ++ if (!GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (child)))) + { +- /* We already got this notification earlier, ignore this one */ ++ gtk_widget_destroy (child); + return; + } +- +- socket = gtk_socket_new (); +- +- gtk_widget_set_app_paintable (socket, TRUE); +- //FIXME: need to find a theme where this (and expose event) is needed +- gtk_widget_set_double_buffered (socket, FALSE); +- g_signal_connect (socket, "realize", +- G_CALLBACK (na_tray_manager_make_socket_transparent), NULL); +- g_signal_connect (socket, "expose_event", +- G_CALLBACK (na_tray_manager_socket_exposed), NULL); +- g_signal_connect_after (socket, "style_set", +- G_CALLBACK (na_tray_manager_socket_style_set), NULL); +- +- /* We need to set the child window here +- * so that the client can call _get functions +- * in the signal handler +- */ +- window = g_new (Window, 1); +- *window = xevent->data.l[2]; +- +- g_object_set_data_full (G_OBJECT (socket), +- "na-tray-child-window", +- window, g_free); +- g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0, +- socket); + +- /* Add the socket only if it's been attached */ +- if (GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket)))) ++ g_signal_connect (child, "plug_removed", ++ G_CALLBACK (na_tray_manager_plug_removed), manager); ++ ++ gtk_socket_add_id (GTK_SOCKET (child), icon_window); ++ ++ if (!GTK_SOCKET (child)->plug_window) + { +- g_signal_connect (socket, "plug_removed", +- G_CALLBACK (na_tray_manager_plug_removed), manager); +- +- gtk_socket_add_id (GTK_SOCKET (socket), *window); +- +- g_hash_table_insert (manager->socket_table, GINT_TO_POINTER (*window), socket); +- +- /* +- * Make sure the icons have a meaningfull size ... +- */ +- req.width = req.height = 1; +- gtk_widget_size_request (socket, &req); +- /* +- if ((req.width < 16) || (req.height < 16)) +- { +- gint nw = MAX (24, req.width); +- gint nh = MAX (24, req.height); +- g_warning (_("tray icon has requested a size of (%i x %i), resizing to (%i x %i)"), +- req.width, req.height, nw, nh); +- gtk_widget_set_size_request(icon, nw, nh); +- } +- */ +- gtk_widget_show(socket); ++ /* Embedding failed, we won't get a plug-removed signal */ ++ g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child); ++ gtk_widget_destroy (child); ++ return; + } +- else +- gtk_widget_destroy (socket); ++ ++ g_hash_table_insert (manager->socket_table, ++ GINT_TO_POINTER (icon_window), child); ++ gtk_widget_show (child); + } + + static void +@@ -445,13 +386,13 @@ na_tray_manager_handle_begin_message (NaTrayManager *manager, + /* Check if the same message is already in the queue and remove it if so */ + for (p = manager->messages; p; p = p->next) + { +- PendingMessage *message = p->data; ++ PendingMessage *pmsg = p->data; + +- if (xevent->window == message->window && +- xevent->data.l[4] == message->id) ++ if (xevent->window == pmsg->window && ++ xevent->data.l[4] == pmsg->id) + { + /* Hmm, we found it, now remove it */ +- pending_message_free (message); ++ pending_message_free (pmsg); + manager->messages = g_list_remove_link (manager->messages, p); + g_list_free_1 (p); + break; +@@ -660,6 +601,58 @@ na_tray_manager_set_orientation_property (NaTrayManager *manager) + #endif + } + ++static void ++na_tray_manager_set_visual_property (NaTrayManager *manager) ++{ ++#ifdef GDK_WINDOWING_X11 ++ GdkDisplay *display; ++ Visual *xvisual; ++ Atom visual_atom; ++ gulong data[1]; ++ ++ if (!manager->invisible || !manager->invisible->window) ++ return; ++ ++ /* The visual property is a hint to the tray icons as to what visual they ++ * should use for their windows. If the X server has RGBA colormaps, then ++ * we tell the tray icons to use a RGBA colormap and we'll composite the ++ * icon onto its parents with real transparency. Otherwise, we just tell ++ * the icon to use our colormap, and we'll do some hacks with parent ++ * relative backgrounds to simulate transparency. ++ */ ++ ++ display = gtk_widget_get_display (manager->invisible); ++ visual_atom = gdk_x11_get_xatom_by_name_for_display (display, ++ "_NET_SYSTEM_TRAY_VISUAL"); ++ ++ if (gdk_screen_get_rgba_visual (manager->screen) != NULL && ++ gdk_display_supports_composite (display)) ++ { ++ xvisual = GDK_VISUAL_XVISUAL (gdk_screen_get_rgba_visual (manager->screen)); ++ } ++ else ++ { ++ /* We actually want the visual of the tray where the icons will ++ * be embedded. In almost all cases, this will be the same as the visual ++ * of the screen. ++ */ ++ GdkColormap *colormap; ++ ++ colormap = gdk_screen_get_default_colormap (manager->screen); ++ xvisual = GDK_VISUAL_XVISUAL (gdk_colormap_get_visual (colormap)); ++ } ++ ++ data[0] = XVisualIDFromVisual (xvisual); ++ ++ XChangeProperty (GDK_DISPLAY_XDISPLAY (display), ++ GDK_WINDOW_XWINDOW (manager->invisible->window), ++ visual_atom, ++ XA_VISUALID, 32, ++ PropModeReplace, ++ (guchar *) &data, 1); ++#endif ++} ++ + #ifdef GDK_WINDOWING_X11 + + static gboolean +@@ -682,6 +675,9 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager, + if (na_tray_manager_check_running_screen_x11 (screen)) + return FALSE; + #endif ++ ++ manager->screen = screen; ++ + display = gdk_screen_get_display (screen); + xscreen = GDK_SCREEN_XSCREEN (screen); + +@@ -696,7 +692,11 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager, + manager->selection_atom = gdk_atom_intern (selection_atom_name, FALSE); + g_free (selection_atom_name); + ++ manager->invisible = invisible; ++ g_object_ref (G_OBJECT (manager->invisible)); ++ + na_tray_manager_set_orientation_property (manager); ++ na_tray_manager_set_visual_property (manager); + + timestamp = gdk_x11_get_server_time (invisible->window); + +@@ -728,9 +728,6 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager, + RootWindowOfScreen (xscreen), + False, StructureNotifyMask, (XEvent *)&xev); + +- manager->invisible = invisible; +- g_object_ref (G_OBJECT (manager->invisible)); +- + opcode_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_OPCODE", FALSE); + manager->opcode_atom = gdk_x11_atom_to_xatom_for_display (display, + opcode_atom); +@@ -761,6 +758,10 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager, + else + { + gtk_widget_destroy (invisible); ++ g_object_unref (invisible); ++ manager->invisible = NULL; ++ ++ manager->screen = NULL; + + return FALSE; + } +@@ -819,67 +820,6 @@ na_tray_manager_check_running (GdkScreen *screen) + #endif + } + +-char * +-na_tray_manager_get_child_title (NaTrayManager *manager, +- NaTrayManagerChild *child) +-{ +- char *retval = NULL; +-#ifdef GDK_WINDOWING_X11 +- GdkDisplay *display; +- Window *child_window; +- Atom utf8_string, atom, type; +- int result; +- int format; +- gulong nitems; +- gulong bytes_after; +- gchar *val; +- +- g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), NULL); +- g_return_val_if_fail (GTK_IS_SOCKET (child), NULL); +- +- display = gdk_screen_get_display (manager->screen); +- +- child_window = g_object_get_data (G_OBJECT (child), +- "na-tray-child-window"); +- +- utf8_string = gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"); +- atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"); +- +- gdk_error_trap_push (); +- +- result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), +- *child_window, +- atom, +- 0, G_MAXLONG, +- False, utf8_string, +- &type, &format, &nitems, +- &bytes_after, (guchar **)&val); +- +- if (gdk_error_trap_pop () || result != Success) +- return NULL; +- +- if (type != utf8_string || +- format != 8 || +- nitems == 0) +- { +- if (val) +- XFree (val); +- return NULL; +- } +- +- if (!g_utf8_validate (val, nitems, NULL)) +- { +- XFree (val); +- return NULL; +- } +- +- retval = g_strndup (val, nitems); +- +- XFree (val); +-#endif +- return retval; +-} +- + void + na_tray_manager_set_orientation (NaTrayManager *manager, + GtkOrientation orientation) +diff --git a/gui/simple-greeter/libnotificationarea/na-tray-manager.h b/gui/simple-greeter/libnotificationarea/na-tray-manager.h +index a1781a7..f325453 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray-manager.h ++++ b/gui/simple-greeter/libnotificationarea/na-tray-manager.h +@@ -24,10 +24,12 @@ + #ifndef __NA_TRAY_MANAGER_H__ + #define __NA_TRAY_MANAGER_H__ + +-#include + #ifdef GDK_WINDOWING_X11 + #include + #endif ++#include ++ ++#include "na-tray-child.h" + + G_BEGIN_DECLS + +@@ -40,7 +42,6 @@ G_BEGIN_DECLS + + typedef struct _NaTrayManager NaTrayManager; + typedef struct _NaTrayManagerClass NaTrayManagerClass; +-typedef struct _NaTrayManagerChild NaTrayManagerChild; + + struct _NaTrayManager + { +@@ -64,18 +65,18 @@ struct _NaTrayManagerClass + GObjectClass parent_class; + + void (* tray_icon_added) (NaTrayManager *manager, +- NaTrayManagerChild *child); ++ NaTrayChild *child); + void (* tray_icon_removed) (NaTrayManager *manager, +- NaTrayManagerChild *child); ++ NaTrayChild *child); + + void (* message_sent) (NaTrayManager *manager, +- NaTrayManagerChild *child, ++ NaTrayChild *child, + const gchar *message, + glong id, + glong timeout); + + void (* message_cancelled) (NaTrayManager *manager, +- NaTrayManagerChild *child, ++ NaTrayChild *child, + glong id); + + void (* lost_selection) (NaTrayManager *manager); +@@ -87,8 +88,6 @@ gboolean na_tray_manager_check_running (GdkScreen *screen); + NaTrayManager *na_tray_manager_new (void); + gboolean na_tray_manager_manage_screen (NaTrayManager *manager, + GdkScreen *screen); +-char *na_tray_manager_get_child_title (NaTrayManager *manager, +- NaTrayManagerChild *child); + void na_tray_manager_set_orientation (NaTrayManager *manager, + GtkOrientation orientation); + GtkOrientation na_tray_manager_get_orientation (NaTrayManager *manager); +diff --git a/gui/simple-greeter/libnotificationarea/na-tray.c b/gui/simple-greeter/libnotificationarea/na-tray.c +index 7192717..051a811 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray.c ++++ b/gui/simple-greeter/libnotificationarea/na-tray.c +@@ -12,7 +12,7 @@ + * 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 +@@ -26,7 +26,6 @@ + + #include "na-tray-manager.h" + #include "fixedtip.h" +-#include "obox.h" + + #include "na-tray.h" + +@@ -83,6 +82,27 @@ static TraysScreen *trays_screens = NULL; + + static void icon_tip_show_next (IconTip *icontip); + ++/* NaBox, an instantiable GtkBox */ ++ ++typedef GtkBox NaBox; ++typedef GtkBoxClass NaBoxClass; ++ ++static GType na_box_get_type (void); ++ ++G_DEFINE_TYPE (NaBox, na_box, GTK_TYPE_BOX) ++ ++static void ++na_box_init (NaBox *box) ++{ ++} ++ ++static void ++na_box_class_init (NaBoxClass *klass) ++{ ++} ++ ++/* NaTray */ ++ + G_DEFINE_TYPE (NaTray, na_tray, GTK_TYPE_BIN) + + static NaTray * +@@ -115,7 +135,6 @@ tray_added (NaTrayManager *manager, + gtk_box_pack_end (GTK_BOX (priv->box), icon, FALSE, FALSE, 0); + + gtk_widget_show (icon); +- na_tray_force_redraw (tray); + } + + static void +@@ -131,8 +150,6 @@ tray_removed (NaTrayManager *manager, + + g_assert (tray->priv->trays_screen == trays_screen); + +- na_tray_force_redraw (tray); +- + g_hash_table_remove (trays_screen->icon_table, icon); + /* this will also destroy the tip associated to this icon */ + g_hash_table_remove (trays_screen->tip_table, icon); +@@ -247,8 +264,9 @@ icon_tip_show_next (IconTip *icontip) + icontip->id = buffer->id; + + if (buffer->timeout > 0) +- icontip->source_id = g_timeout_add (buffer->timeout * 1000, +- icon_tip_show_next_timeout, icontip); ++ icontip->source_id = g_timeout_add_seconds (buffer->timeout, ++ icon_tip_show_next_timeout, ++ icontip); + + icon_tip_buffer_free (buffer, NULL); + } +@@ -375,7 +393,7 @@ update_size_and_orientation (NaTray *tray) + { + NaTrayPrivate *priv = tray->priv; + +- na_obox_set_orientation (NA_OBOX (priv->box), priv->orientation); ++ gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), priv->orientation); + + /* This only happens when setting the property during object construction */ + if (!priv->trays_screen) +@@ -399,8 +417,38 @@ update_size_and_orientation (NaTray *tray) + gtk_widget_set_size_request (priv->box, -1, MIN_BOX_SIZE); + break; + } ++} + +- na_tray_force_redraw (tray); ++/* Children with alpha channels have been set to be composited by calling ++ * gdk_window_set_composited(). We need to paint these children ourselves. ++ */ ++static void ++na_tray_expose_icon (GtkWidget *widget, ++ gpointer data) ++{ ++ cairo_t *cr = data; ++ ++ if (na_tray_child_has_alpha (NA_TRAY_CHILD (widget))) ++ { ++ gdk_cairo_set_source_pixmap (cr, widget->window, ++ widget->allocation.x, ++ widget->allocation.y); ++ cairo_paint (cr); ++ } ++} ++ ++static void ++na_tray_expose_box (GtkWidget *box, ++ GdkEventExpose *event) ++{ ++ cairo_t *cr = gdk_cairo_create (box->window); ++ ++ gdk_cairo_region (cr, event->region); ++ cairo_clip (cr); ++ ++ gtk_container_foreach (GTK_CONTAINER (box), na_tray_expose_icon, cr); ++ ++ cairo_destroy (cr); + } + + static void +@@ -417,7 +465,9 @@ na_tray_init (NaTray *tray) + gtk_container_add (GTK_CONTAINER (tray), priv->frame); + gtk_widget_show (priv->frame); + +- priv->box = na_obox_new (); ++ priv->box = g_object_new (na_box_get_type (), NULL); ++ g_signal_connect (priv->box, "expose-event", ++ G_CALLBACK (na_tray_expose_box), tray); + gtk_box_set_spacing (GTK_BOX (priv->box), ICON_SPACING); + gtk_container_add (GTK_CONTAINER (priv->frame), priv->box); + gtk_widget_show (priv->box); +@@ -658,9 +708,9 @@ idle_redraw_cb (NaTray *tray) + { + NaTrayPrivate *priv = tray->priv; + ++ gtk_container_foreach (GTK_CONTAINER (priv->box), (GtkCallback)na_tray_child_force_redraw, tray); ++ + priv->idle_redraw_id = 0; +- gtk_widget_hide (priv->box); +- gtk_widget_show (priv->box); + + return FALSE; + } +@@ -671,8 +721,6 @@ na_tray_force_redraw (NaTray *tray) + NaTrayPrivate *priv = tray->priv; + + /* Force the icons to redraw their backgrounds. +- * gtk_widget_queue_draw() doesn't work across process boundaries, +- * so we do this instead. + */ + if (priv->idle_redraw_id == 0) + priv->idle_redraw_id = g_idle_add ((GSourceFunc) idle_redraw_cb, tray); +diff --git a/gui/simple-greeter/libnotificationarea/na-tray.h b/gui/simple-greeter/libnotificationarea/na-tray.h +index f67062b..57baddd 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray.h ++++ b/gui/simple-greeter/libnotificationarea/na-tray.h +@@ -24,10 +24,10 @@ + #ifndef __NA_TRAY_H__ + #define __NA_TRAY_H__ + +-#include + #ifdef GDK_WINDOWING_X11 + #include + #endif ++#include + + G_BEGIN_DECLS + +@@ -41,7 +41,6 @@ G_BEGIN_DECLS + typedef struct _NaTray NaTray; + typedef struct _NaTrayPrivate NaTrayPrivate; + typedef struct _NaTrayClass NaTrayClass; +-typedef struct _NaTrayChild NaTrayChild; + + struct _NaTray + { +diff --git a/gui/simple-greeter/libnotificationarea/testtray.c b/gui/simple-greeter/libnotificationarea/testtray.c +index 42d3732..c0300b6 100644 +--- a/gui/simple-greeter/libnotificationarea/testtray.c ++++ b/gui/simple-greeter/libnotificationarea/testtray.c +@@ -66,7 +66,7 @@ static void + tray_added_cb (GtkContainer *box, GtkWidget *icon, TrayData *data) + { + g_print ("[Screen %u tray %p] Child %p added to tray: \"%s\"\n", +- data->screen_num, data->tray, icon, "XXX");//na_tray_manager_get_child_title (manager, icon)); ++ data->screen_num, data->tray, icon, "XXX");//na_tray_child_get_title (icon)); + + update_child_count (data); + } +-- +1.6.5.rc2 + + +From b2bd208cd0057e25b0aac380d519376b243537e0 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 22 Oct 2009 22:07:52 -0400 +Subject: [PATCH 2/4] Add ordering patch to na-tray + +This makes sure system utilities come up in the right order. +--- + .../libnotificationarea/na-tray-child.c | 81 ++++++++++++++++++ + .../libnotificationarea/na-tray-child.h | 5 +- + gui/simple-greeter/libnotificationarea/na-tray.c | 89 +++++++++++++++++++- + 3 files changed, 172 insertions(+), 3 deletions(-) + +diff --git a/gui/simple-greeter/libnotificationarea/na-tray-child.c b/gui/simple-greeter/libnotificationarea/na-tray-child.c +index c7e3f61..98769bd 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray-child.c ++++ b/gui/simple-greeter/libnotificationarea/na-tray-child.c +@@ -428,3 +428,84 @@ na_tray_child_force_redraw (NaTrayChild *child) + #endif + } + } ++ ++ ++/* from libwnck xutils.c */ ++static char * ++latin1_to_utf8 (const char *latin1) ++{ ++ GString *str; ++ const char *p; ++ ++ str = g_string_new (NULL); ++ ++ p = latin1; ++ while (*p) ++ { ++ g_string_append_unichar (str, (gunichar) *p); ++ ++p; ++ } ++ ++ return g_string_free (str, FALSE); ++} ++ ++/* derived from libwnck xutils.c */ ++static void ++_get_wmclass (Display *xdisplay, ++ Window xwindow, ++ char **res_class, ++ char **res_name) ++{ ++ XClassHint ch; ++ char *retval; ++ ++ gdk_error_trap_push (); ++ ++ ch.res_name = NULL; ++ ch.res_class = NULL; ++ ++ XGetClassHint (xdisplay, xwindow, &ch); ++ ++ gdk_error_trap_pop (); ++ ++ retval = NULL; ++ ++ if (res_class) ++ *res_class = NULL; ++ ++ if (res_name) ++ *res_name = NULL; ++ ++ if (ch.res_name) ++ { ++ if (res_name) ++ *res_name = latin1_to_utf8 (ch.res_name); ++ ++ XFree (ch.res_name); ++ } ++ ++ if (ch.res_class) ++ { ++ if (res_class) ++ *res_class = latin1_to_utf8 (ch.res_class); ++ ++ XFree (ch.res_class); ++ } ++} ++ ++void ++na_tray_child_get_wm_class (NaTrayChild *child, ++ char **res_name, ++ char **res_class) ++{ ++ GdkDisplay *display; ++ ++ g_return_if_fail (NA_IS_TRAY_CHILD (child)); ++ ++ display = gtk_widget_get_display (GTK_WIDGET (child)); ++ ++ _get_wmclass (GDK_DISPLAY_XDISPLAY (display), ++ child->icon_window, ++ res_class, ++ res_name); ++} +diff --git a/gui/simple-greeter/libnotificationarea/na-tray-child.h b/gui/simple-greeter/libnotificationarea/na-tray-child.h +index c174abe..ff036a7 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray-child.h ++++ b/gui/simple-greeter/libnotificationarea/na-tray-child.h +@@ -61,7 +61,10 @@ char *na_tray_child_get_title (NaTrayChild *child); + gboolean na_tray_child_has_alpha (NaTrayChild *child); + void na_tray_child_set_composited (NaTrayChild *child, + gboolean composited); +-void na_tray_child_force_redraw (NaTrayChild *child); ++void na_tray_child_force_redraw (NaTrayChild *child); ++void na_tray_child_get_wm_class (NaTrayChild *child, ++ char **res_name, ++ char **res_class); + + G_END_DECLS + +diff --git a/gui/simple-greeter/libnotificationarea/na-tray.c b/gui/simple-greeter/libnotificationarea/na-tray.c +index 051a811..3bd1258 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray.c ++++ b/gui/simple-greeter/libnotificationarea/na-tray.c +@@ -114,6 +114,51 @@ get_tray (TraysScreen *trays_screen) + return trays_screen->all_trays->data; + } + ++const char *roles[] = { ++ "keyboard", ++ "volume", ++ "bluetooth", ++ "network", ++ "battery", ++ NULL ++}; ++ ++const char *wmclass_roles[] = { ++ "Bluetooth-applet", "bluetooth", ++ "Gnome-volume-control-applet", "volume", ++ "Nm-applet", "network", ++ "Gnome-power-manager", "battery", ++ NULL, ++}; ++ ++static const char * ++find_role (const char *wmclass) ++{ ++ int i; ++ ++ for (i = 0; wmclass_roles[i]; i += 2) ++ { ++ if (strcmp (wmclass, wmclass_roles[i]) == 0) ++ return wmclass_roles[i + 1]; ++ } ++ ++ return NULL; ++} ++ ++static int ++find_role_pos (const char *role) ++{ ++ int i; ++ ++ for (i = 0; roles[i]; i++) ++ { ++ if (strcmp (role, roles[i]) == 0) ++ break; ++ } ++ ++ return i + 1; ++} ++ + static void + tray_added (NaTrayManager *manager, + GtkWidget *icon, +@@ -121,6 +166,11 @@ tray_added (NaTrayManager *manager, + { + NaTray *tray; + NaTrayPrivate *priv; ++ GList *l, *children; ++ int position; ++ char *class_a; ++ const char *role; ++ int role_position; + + tray = get_tray (trays_screen); + if (tray == NULL) +@@ -129,10 +179,45 @@ tray_added (NaTrayManager *manager, + priv = tray->priv; + + g_assert (priv->trays_screen == trays_screen); +- ++ + g_hash_table_insert (trays_screen->icon_table, icon, tray); + +- gtk_box_pack_end (GTK_BOX (priv->box), icon, FALSE, FALSE, 0); ++ position = 0; ++ ++ class_a = NULL; ++ na_tray_child_get_wm_class (NA_TRAY_CHILD (icon), NULL, &class_a); ++ if (!class_a) ++ goto insert; ++ ++ role = find_role (class_a); ++ g_free (class_a); ++ if (!role) ++ goto insert; ++ ++ role_position = find_role_pos (role); ++ g_object_set_data (G_OBJECT (icon), "role-position", GINT_TO_POINTER (role_position)); ++ ++ children = gtk_container_get_children (GTK_CONTAINER (priv->box)); ++ for (l = g_list_last (children); l; l = l->prev) ++ { ++ GtkWidget *child = l->data; ++ gint rp; ++ ++ rp = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), "role-position")); ++ if (rp == 0 || rp < role_position) ++ { ++ position = g_list_index (children, child) + 1; ++ break; ++ } ++ } ++ g_list_free (children); ++ ++ if (position < 0) ++ position = 0; ++ ++insert: ++ gtk_box_pack_start (GTK_BOX (priv->box), icon, FALSE, FALSE, 0); ++ gtk_box_reorder_child (GTK_BOX (priv->box), icon, position); + + gtk_widget_show (icon); + } +-- +1.6.5.rc2 + + +From ab7c74cca138c404338ebaf3ee3c1e3f6e92f083 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 22 Oct 2009 22:08:18 -0400 +Subject: [PATCH 3/4] Add the ability to have padding between icons in tray + +--- + .../libnotificationarea/na-tray-manager.c | 41 ++++++++++++++++++++ + .../libnotificationarea/na-tray-manager.h | 3 + + gui/simple-greeter/libnotificationarea/na-tray.c | 12 ++++++ + gui/simple-greeter/libnotificationarea/na-tray.h | 2 + + 4 files changed, 58 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/libnotificationarea/na-tray-manager.c b/gui/simple-greeter/libnotificationarea/na-tray-manager.c +index 1bf54f1..d49c646 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray-manager.c ++++ b/gui/simple-greeter/libnotificationarea/na-tray-manager.c +@@ -653,6 +653,32 @@ na_tray_manager_set_visual_property (NaTrayManager *manager) + #endif + } + ++static void ++na_tray_manager_set_padding_property (NaTrayManager *manager) ++{ ++#ifdef GDK_WINDOWING_X11 ++ GdkDisplay *display; ++ Atom orientation_atom; ++ gulong data[1]; ++ ++ if (!manager->invisible || !manager->invisible->window) ++ return; ++ ++ display = gtk_widget_get_display (manager->invisible); ++ orientation_atom = gdk_x11_get_xatom_by_name_for_display (display, ++ "_NET_SYSTEM_TRAY_PADDING"); ++ ++ data[0] = manager->padding; ++ ++ XChangeProperty (GDK_DISPLAY_XDISPLAY (display), ++ GDK_WINDOW_XWINDOW (manager->invisible->window), ++ orientation_atom, ++ XA_CARDINAL, 32, ++ PropModeReplace, ++ (guchar *) &data, 1); ++#endif ++} ++ + #ifdef GDK_WINDOWING_X11 + + static gboolean +@@ -697,6 +723,7 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager, + + na_tray_manager_set_orientation_property (manager); + na_tray_manager_set_visual_property (manager); ++ na_tray_manager_set_padding_property (manager); + + timestamp = gdk_x11_get_server_time (invisible->window); + +@@ -836,6 +863,20 @@ na_tray_manager_set_orientation (NaTrayManager *manager, + } + } + ++void ++na_tray_manager_set_padding (NaTrayManager *manager, ++ gint padding) ++{ ++ g_return_if_fail (NA_IS_TRAY_MANAGER (manager)); ++ ++ if (manager->padding != padding) ++ { ++ manager->padding = padding; ++ ++ na_tray_manager_set_padding_property (manager); ++ } ++} ++ + GtkOrientation + na_tray_manager_get_orientation (NaTrayManager *manager) + { +diff --git a/gui/simple-greeter/libnotificationarea/na-tray-manager.h b/gui/simple-greeter/libnotificationarea/na-tray-manager.h +index f325453..e93882e 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray-manager.h ++++ b/gui/simple-greeter/libnotificationarea/na-tray-manager.h +@@ -55,6 +55,7 @@ struct _NaTrayManager + GtkWidget *invisible; + GdkScreen *screen; + GtkOrientation orientation; ++ gint padding; + + GList *messages; + GHashTable *socket_table; +@@ -91,6 +92,8 @@ gboolean na_tray_manager_manage_screen (NaTrayManager *manager, + void na_tray_manager_set_orientation (NaTrayManager *manager, + GtkOrientation orientation); + GtkOrientation na_tray_manager_get_orientation (NaTrayManager *manager); ++void na_tray_manager_set_padding (NaTrayManager *manager, ++ gint padding); + + G_END_DECLS + +diff --git a/gui/simple-greeter/libnotificationarea/na-tray.c b/gui/simple-greeter/libnotificationarea/na-tray.c +index 3bd1258..40845c1 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray.c ++++ b/gui/simple-greeter/libnotificationarea/na-tray.c +@@ -599,6 +599,8 @@ na_tray_constructor (GType type, + { + trays_screens [screen_number].tray_manager = tray_manager; + ++ na_tray_manager_set_padding (tray_manager, 0); ++ + g_signal_connect (tray_manager, "tray_icon_added", + G_CALLBACK (tray_added), + &trays_screens [screen_number]); +@@ -801,6 +803,16 @@ idle_redraw_cb (NaTray *tray) + } + + void ++na_tray_set_padding (NaTray *tray, ++ gint padding) ++{ ++ NaTrayPrivate *priv = tray->priv; ++ ++ if (get_tray (priv->trays_screen) == tray) ++ na_tray_manager_set_padding (priv->trays_screen->tray_manager, padding); ++} ++ ++void + na_tray_force_redraw (NaTray *tray) + { + NaTrayPrivate *priv = tray->priv; +diff --git a/gui/simple-greeter/libnotificationarea/na-tray.h b/gui/simple-greeter/libnotificationarea/na-tray.h +index 57baddd..1ead20f 100644 +--- a/gui/simple-greeter/libnotificationarea/na-tray.h ++++ b/gui/simple-greeter/libnotificationarea/na-tray.h +@@ -60,6 +60,8 @@ NaTray *na_tray_new_for_screen (GdkScreen *screen, + void na_tray_set_orientation (NaTray *tray, + GtkOrientation orientation); + GtkOrientation na_tray_get_orientation (NaTray *tray); ++void na_tray_set_padding (NaTray *tray, ++ gint padding); + void na_tray_force_redraw (NaTray *tray); + + G_END_DECLS +-- +1.6.5.rc2 + + +From 050879701489074492a35b0427f0ac7cf21ebf82 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 22 Oct 2009 22:13:58 -0400 +Subject: [PATCH 4/4] Read padding from notification area applet and use it. + +--- + gui/simple-greeter/gdm-greeter-panel.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-panel.c b/gui/simple-greeter/gdm-greeter-panel.c +index 03c4122..43b91d5 100644 +--- a/gui/simple-greeter/gdm-greeter-panel.c ++++ b/gui/simple-greeter/gdm-greeter-panel.c +@@ -65,6 +65,7 @@ + #define GPM_DBUS_INTERFACE "org.freedesktop.PowerManagement" + + #define KEY_DISABLE_RESTART_BUTTONS "/apps/gdm/simple-greeter/disable_restart_buttons" ++#define KEY_NOTIFICATION_AREA_PADDING "/apps/notification_area_applet/prefs/padding" + + #define GDM_GREETER_PANEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_PANEL, GdmGreeterPanelPrivate)) + +@@ -824,6 +825,7 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) + { + NaTray *tray; + GtkWidget *spacer; ++ int padding; + + gdm_profile_start (NULL); + +@@ -955,6 +957,9 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) + + tray = na_tray_new_for_screen (gtk_window_get_screen (GTK_WINDOW (panel)), + GTK_ORIENTATION_HORIZONTAL); ++ ++ padding = gconf_client_get_int (panel->priv->client, KEY_NOTIFICATION_AREA_PADDING, NULL); ++ na_tray_set_padding (tray, padding); + gtk_box_pack_end (GTK_BOX (panel->priv->hbox), GTK_WIDGET (tray), FALSE, FALSE, 6); + gtk_widget_show (GTK_WIDGET (tray)); + gdm_greeter_panel_hide_user_options (panel); +-- +1.6.5.rc2 + diff --git a/fix-run-dir-permissions.patch b/fix-run-dir-permissions.patch new file mode 100644 index 0000000..7475236 --- /dev/null +++ b/fix-run-dir-permissions.patch @@ -0,0 +1,370 @@ +From 5475c0a823cf94f817821105b40760d902d9ace5 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 27 Oct 2009 10:40:55 -0400 +Subject: [PATCH 1/4] Make screenshot dir a configure argument + +This provides a little more flexibility to distributors, +but more importantly makes it less hard coded in gdm-screenshot.c +--- + configure.ac | 17 +++++++++++++++++ + data/Makefile.am | 8 ++++++++ + utils/Makefile.am | 1 + + utils/gdm-screenshot.c | 5 +---- + 4 files changed, 27 insertions(+), 4 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 4fe4430..0dd2658 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1237,6 +1237,23 @@ fi + AC_SUBST(GDM_XAUTH_DIR) + + dnl --------------------------------------------------------------------------- ++dnl - Directory for greeter screenshot ++dnl --------------------------------------------------------------------------- ++ ++AC_ARG_WITH(screenshot-dir, ++ AS_HELP_STRING([--with-screenshot-dir=], ++ [directory to store greeter screenshot])) ++ ++if ! test -z "$with_screenshot_dir"; then ++ GDM_SCREENSHOT_DIR=$with_screenshot_dir ++else ++ GDM_SCREENSHOT_DIR=${localstatedir}/run/gdm ++fi ++ ++AC_SUBST(GDM_SCREENSHOT_DIR) ++ ++ ++dnl --------------------------------------------------------------------------- + dnl - Finish + dnl --------------------------------------------------------------------------- + +diff --git a/data/Makefile.am b/data/Makefile.am +index 73fa106..608194d 100644 +--- a/data/Makefile.am ++++ b/data/Makefile.am +@@ -13,6 +13,7 @@ predir = $(gdmconfdir)/PreSession + postlogindir = $(gdmconfdir)/PostLogin + workingdir = $(GDM_WORKING_DIR) + xauthdir = $(GDM_XAUTH_DIR) ++screenshotdir = $(GDM_SCREENSHOT_DIR) + cachedir = $(localstatedir)/cache/gdm + + Xsession: $(srcdir)/Xsession.in +@@ -123,6 +124,7 @@ uninstall-hook: + -rf \ + $(DESTDIR)$(workingdir)/.gconf.mandatory \ + $(DESTDIR)$(xauthdir) ++ $(DESTDIR)$(screenshotdir) + + install-data-hook: gdm.conf-custom Xsession Init PostSession PreSession gconf.path + if test '!' -d $(DESTDIR)$(gdmconfdir); then \ +@@ -204,6 +206,12 @@ install-data-hook: gdm.conf-custom Xsession Init PostSession PreSession gconf.pa + chown root:gdm $(DESTDIR)$(xauthdir) || : ; \ + fi + ++ if test '!' -d $(DESTDIR)$(screenshotdir); then \ ++ $(mkinstalldirs) $(DESTDIR)$(screenshotdir); \ ++ chmod 0755 $(DESTDIR)$(screenshotdir); \ ++ chown gdm:gdm $(DESTDIR)$(screenshotdir) || : ; \ ++ fi ++ + if test '!' -d $(DESTDIR)$(workingdir); then \ + $(mkinstalldirs) $(DESTDIR)$(workingdir); \ + chmod 1770 $(DESTDIR)$(workingdir); \ +diff --git a/utils/Makefile.am b/utils/Makefile.am +index 0b6ea04..f1ff331 100644 +--- a/utils/Makefile.am ++++ b/utils/Makefile.am +@@ -4,6 +4,7 @@ AM_CPPFLAGS = \ + -I. \ + -I.. \ + -DLOCALSTATEDIR=\""$(localstatedir)"\" \ ++ -DGDM_SCREENSHOT_DIR=\""$(GDM_SCREENSHOT_DIR)"\"\ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ + $(UTILS_CFLAGS) \ + $(CANBERRA_GTK_CFLAGS) \ +diff --git a/utils/gdm-screenshot.c b/utils/gdm-screenshot.c +index f66de46..12102f2 100644 +--- a/utils/gdm-screenshot.c ++++ b/utils/gdm-screenshot.c +@@ -163,11 +163,8 @@ screenshot_save (GdkPixbuf *pixbuf) + char *filename; + gboolean res; + GError *error; +- const char *save_dir; + +- save_dir = LOCALSTATEDIR "/run/gdm"; +- +- filename = g_build_filename (save_dir, ++ filename = g_build_filename (GDM_SCREENSHOT_DIR, + "GDM-Screenshot.png", + NULL); + +-- +1.6.5.1 + + +From 1fe51c8f69dc93033d2035c27389377090f21b78 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 27 Oct 2009 11:25:19 -0400 +Subject: [PATCH 2/4] Create screenshot dir at runtime if not available + +We want the screenshot dir to be owned by the GDM user, +so the greeter can write screenshots to it. +--- + daemon/Makefile.am | 1 + + daemon/gdm-greeter-session.c | 1 + + daemon/gdm-welcome-session.c | 32 ++++++++++++++++++++++++++++++++ + 3 files changed, 34 insertions(+), 0 deletions(-) + +diff --git a/daemon/Makefile.am b/daemon/Makefile.am +index a122a15..ab10dc5 100644 +--- a/daemon/Makefile.am ++++ b/daemon/Makefile.am +@@ -15,6 +15,7 @@ AM_CPPFLAGS = \ + -DSBINDIR=\"$(sbindir)\" \ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ + -DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \ ++ -DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \ + -DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \ + -DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \ + $(DISABLE_DEPRECATED_CFLAGS) \ +diff --git a/daemon/gdm-greeter-session.c b/daemon/gdm-greeter-session.c +index aae1928..994acbc 100644 +--- a/daemon/gdm-greeter-session.c ++++ b/daemon/gdm-greeter-session.c +@@ -156,6 +156,7 @@ gdm_greeter_session_new (const char *display_name, + "x11-display-device", display_device, + "x11-display-hostname", display_hostname, + "x11-display-is-local", display_is_local, ++ "runtime-dir", GDM_SCREENSHOT_DIR, + NULL); + + return GDM_GREETER_SESSION (object); +diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c +index b58e855..f340660 100644 +--- a/daemon/gdm-welcome-session.c ++++ b/daemon/gdm-welcome-session.c +@@ -63,6 +63,7 @@ struct GdmWelcomeSessionPrivate + + char *user_name; + char *group_name; ++ char *runtime_dir; + + char *x11_display_name; + char *x11_display_device; +@@ -91,6 +92,7 @@ enum { + PROP_X11_DISPLAY_IS_LOCAL, + PROP_USER_NAME, + PROP_GROUP_NAME, ++ PROP_RUNTIME_DIR, + PROP_SERVER_ADDRESS, + PROP_COMMAND, + PROP_SERVER_DBUS_PATH, +@@ -408,6 +410,7 @@ rotate_logs (const char *path, + typedef struct { + const char *user_name; + const char *group_name; ++ const char *runtime_dir; + const char *log_file; + } SpawnChildData; + +@@ -435,6 +438,10 @@ spawn_child_setup (SpawnChildData *data) + _exit (1); + } + ++ g_debug ("GdmWelcomeSession: Setting up run time dir %s", data->runtime_dir); ++ g_mkdir (data->runtime_dir, 0755); ++ chown (data->runtime_dir, pwent->pw_uid, pwent->pw_gid); ++ + g_debug ("GdmWelcomeSession: Changing (uid:gid) for child process to (%d:%d)", + pwent->pw_uid, + grent->gr_gid); +@@ -552,6 +559,7 @@ static gboolean + spawn_command_line_async_as_user (const char *command_line, + const char *user_name, + const char *group_name, ++ const char *runtime_dir, + const char *log_file, + char **env, + GPid *child_pid, +@@ -575,6 +583,7 @@ spawn_command_line_async_as_user (const char *command_line, + + data.user_name = user_name; + data.group_name = group_name; ++ data.runtime_dir = runtime_dir; + data.log_file = log_file; + + local_error = NULL; +@@ -756,6 +765,7 @@ gdm_welcome_session_spawn (GdmWelcomeSession *welcome_session) + ret = spawn_command_line_async_as_user (welcome_session->priv->command, + welcome_session->priv->user_name, + welcome_session->priv->group_name, ++ welcome_session->priv->runtime_dir, + log_path, + (char **)env->pdata, + &welcome_session->priv->pid, +@@ -928,6 +938,14 @@ _gdm_welcome_session_set_group_name (GdmWelcomeSession *welcome_session, + } + + static void ++_gdm_welcome_session_set_runtime_dir (GdmWelcomeSession *welcome_session, ++ const char *dir) ++{ ++ g_free (welcome_session->priv->runtime_dir); ++ welcome_session->priv->runtime_dir = g_strdup (dir); ++} ++ ++static void + _gdm_welcome_session_set_server_dbus_path (GdmWelcomeSession *welcome_session, + const char *name) + { +@@ -998,6 +1016,9 @@ gdm_welcome_session_set_property (GObject *object, + case PROP_GROUP_NAME: + _gdm_welcome_session_set_group_name (self, g_value_get_string (value)); + break; ++ case PROP_RUNTIME_DIR: ++ _gdm_welcome_session_set_runtime_dir (self, g_value_get_string (value)); ++ break; + case PROP_SERVER_ADDRESS: + gdm_welcome_session_set_server_address (self, g_value_get_string (value)); + break; +@@ -1054,6 +1075,9 @@ gdm_welcome_session_get_property (GObject *object, + case PROP_GROUP_NAME: + g_value_set_string (value, self->priv->group_name); + break; ++ case PROP_RUNTIME_DIR: ++ g_value_set_string (value, self->priv->runtime_dir); ++ break; + case PROP_SERVER_ADDRESS: + g_value_set_string (value, self->priv->server_address); + break; +@@ -1154,6 +1178,13 @@ gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass) + GDM_GROUPNAME, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, ++ PROP_RUNTIME_DIR, ++ g_param_spec_string ("runtime-dir", ++ "runtime dir", ++ "runtime dir", ++ NULL, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); ++ g_object_class_install_property (object_class, + PROP_SERVER_ADDRESS, + g_param_spec_string ("server-address", + "server address", +@@ -1267,6 +1298,7 @@ gdm_welcome_session_finalize (GObject *object) + g_free (welcome_session->priv->command); + g_free (welcome_session->priv->user_name); + g_free (welcome_session->priv->group_name); ++ g_free (welcome_session->priv->runtime_dir); + g_free (welcome_session->priv->x11_display_name); + g_free (welcome_session->priv->x11_display_device); + g_free (welcome_session->priv->x11_display_hostname); +-- +1.6.5.1 + + +From 81870b019c929694ea392359b0a66b0a500c7d5c Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 27 Oct 2009 11:43:15 -0400 +Subject: [PATCH 3/4] Move default screenshot dir to it's own subdirectory + +--- + configure.ac | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 0dd2658..93917e2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1247,7 +1247,7 @@ AC_ARG_WITH(screenshot-dir, + if ! test -z "$with_screenshot_dir"; then + GDM_SCREENSHOT_DIR=$with_screenshot_dir + else +- GDM_SCREENSHOT_DIR=${localstatedir}/run/gdm ++ GDM_SCREENSHOT_DIR=${localstatedir}/run/gdm/greeter + fi + + AC_SUBST(GDM_SCREENSHOT_DIR) +-- +1.6.5.1 + + +From c96697431529ed87dbdbb987ed92ac2286b247b7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 27 Oct 2009 10:35:37 -0400 +Subject: [PATCH 4/4] Lock down /var/run/gdm + +We don't need it so open now that screenshots are written to their +own directory, and having it open has implications for quota abuse. +--- + daemon/gdm-display-access-file.c | 14 +++++++------- + data/Makefile.am | 2 +- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/daemon/gdm-display-access-file.c b/daemon/gdm-display-access-file.c +index a3d3e2f..1b52f15 100644 +--- a/daemon/gdm-display-access-file.c ++++ b/daemon/gdm-display-access-file.c +@@ -268,10 +268,10 @@ _create_xauth_file_for_user (const char *username, + fp = NULL; + fd = -1; + +- /* Create directory if not exist, then set permission 01775 and ownership root:gdm */ ++ /* Create directory if not exist, then set permission 0711 and ownership root:gdm */ + if (g_file_test (GDM_XAUTH_DIR, G_FILE_TEST_IS_DIR) == FALSE) { + g_unlink (GDM_XAUTH_DIR); +- if (g_mkdir (GDM_XAUTH_DIR, S_ISVTX | S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) { ++ if (g_mkdir (GDM_XAUTH_DIR, 0711) != 0) { + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), +@@ -279,15 +279,15 @@ _create_xauth_file_for_user (const char *username, + goto out; + } + +- g_chmod (GDM_XAUTH_DIR, S_ISVTX | S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); ++ g_chmod (GDM_XAUTH_DIR, 0711); + _get_uid_and_gid_for_user (GDM_USERNAME, &uid, &gid); + if (chown (GDM_XAUTH_DIR, 0, gid) != 0) { + g_warning ("Unable to change owner of '%s'", + GDM_XAUTH_DIR); + } + } else { +- /* if it does exist make sure it has correct mode 01775 */ +- g_chmod (GDM_XAUTH_DIR, S_ISVTX | S_IRWXU |S_IRWXG | S_IROTH | S_IXOTH); ++ /* if it does exist make sure it has correct mode 0711 */ ++ g_chmod (GDM_XAUTH_DIR, 0711); + + /* and clean up any stale auth subdirs */ + clean_up_stale_auth_subdirs (); +@@ -368,8 +368,8 @@ _create_xauth_file_for_user (const char *username, + } + + /* now open up permissions on per-session directory */ +- g_debug ("GdmDisplayAccessFile: chmoding %s to 1777", dir_name); +- g_chmod (dir_name, S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO); ++ g_debug ("GdmDisplayAccessFile: chmoding %s to 0711", dir_name); ++ g_chmod (dir_name, 0711); + + errno = 0; + fp = fdopen (fd, "w"); +diff --git a/data/Makefile.am b/data/Makefile.am +index 608194d..dfbd096 100644 +--- a/data/Makefile.am ++++ b/data/Makefile.am +@@ -202,7 +202,7 @@ install-data-hook: gdm.conf-custom Xsession Init PostSession PreSession gconf.pa + + if test '!' -d $(DESTDIR)$(xauthdir); then \ + $(mkinstalldirs) $(DESTDIR)$(xauthdir); \ +- chmod 1777 $(DESTDIR)$(xauthdir); \ ++ chmod 0711 $(DESTDIR)$(xauthdir); \ + chown root:gdm $(DESTDIR)$(xauthdir) || : ; \ + fi + +-- +1.6.5.1 + diff --git a/fix-timer.patch b/fix-timer.patch new file mode 100644 index 0000000..6029d02 --- /dev/null +++ b/fix-timer.patch @@ -0,0 +1,66 @@ +From 88d4e5d79ca5ded0f9e88af67044d53342ff0897 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 22 Oct 2009 17:39:27 -0400 +Subject: [PATCH 1/2] Force cell renderer to be a specific height + +Before it was growing and shrinking all the time causing, +flicker. +--- + gui/simple-greeter/gdm-cell-renderer-timer.c | 12 ++---------- + 1 files changed, 2 insertions(+), 10 deletions(-) + +diff --git a/gui/simple-greeter/gdm-cell-renderer-timer.c b/gui/simple-greeter/gdm-cell-renderer-timer.c +index 7918b48..9453d7e 100644 +--- a/gui/simple-greeter/gdm-cell-renderer-timer.c ++++ b/gui/simple-greeter/gdm-cell-renderer-timer.c +@@ -108,19 +108,11 @@ gdm_cell_renderer_timer_get_size (GtkCellRenderer *cell, + } + + if (width != NULL) { +- if (cell->width >= 0) { +- *width = cell->width; +- } else { +- *width = renderer->priv->value <= G_MINDOUBLE? 0 : 64; +- } ++ *width = cell->xpad * 2 + 24; + } + + if (height != NULL) { +- if (cell->height >= 0) { +- *height = cell->height; +- } else { +- *height = renderer->priv->value <= G_MINDOUBLE? 0 : 64; +- } ++ *height = cell->ypad * 2 + 24; + } + } + +-- +1.6.5.rc2 + + +From a87b05fac2c2de7cff80a183e397f33416bfc893 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 22 Oct 2009 17:45:13 -0400 +Subject: [PATCH 2/2] Drop set_operator (SOURCE) in cell renderer + +I'm not sure why I was doing it, when it looks +find using OVER, so I'm going to take it out. +--- + gui/simple-greeter/gdm-cell-renderer-timer.c | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/gdm-cell-renderer-timer.c b/gui/simple-greeter/gdm-cell-renderer-timer.c +index 9453d7e..0fb404c 100644 +--- a/gui/simple-greeter/gdm-cell-renderer-timer.c ++++ b/gui/simple-greeter/gdm-cell-renderer-timer.c +@@ -164,7 +164,6 @@ draw_timer (GdmCellRendererTimer *renderer, + cairo_arc (context, 0, 0, radius + 1, 0, 2 * G_PI); + cairo_fill (context); + +- cairo_set_operator (context, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgb (context, + bg->red / 65535.0, + bg->green / 65535.0, +-- +1.6.5.rc2 diff --git a/gdm-2.27.4-multistack.patch b/gdm-2.27.4-multistack.patch deleted file mode 100644 index f84ca1b..0000000 --- a/gdm-2.27.4-multistack.patch +++ /dev/null @@ -1,18187 +0,0 @@ -From a1ab1c57fa91751f067ff10465f01034bc5c1953 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Feb 2009 13:52:19 -0500 -Subject: [PATCH 01/38] 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 578e613..7e3e59c 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.3.3 - - -From 4e9cef5860311e3b39d2076f4dc9de5f69dfa51f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 17:44:37 -0500 -Subject: [PATCH 02/38] 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 2e01d33..cecce83 100644 ---- a/daemon/gdm-greeter-server.c -+++ b/daemon/gdm-greeter-server.c -@@ -752,7 +752,6 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -- " \n" - " \n" - " \n" - " \n" --- -1.6.3.3 - - -From ca75999e3ce75549554efb758c9210e2997cc9f6 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 10:07:03 -0500 -Subject: [PATCH 03/38] Make lookup_item not warn when passing NULL for args - -gtk_tree_model_get doesn't like NULL, and we allow -NULL for optional return values. - -We now check each argument for NULL and call -gtk_tree_model_get individually N times (one for -each argument) instead of just once. ---- - 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 b3f2a0d..4e76439 100644 ---- a/gui/simple-greeter/gdm-chooser-widget.c -+++ b/gui/simple-greeter/gdm-chooser-widget.c -@@ -2157,13 +2157,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); -+ } -+ -+ if (name != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_NAME_COLUMN, name, -1); -+ } -+ -+ if (priority != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_PRIORITY_COLUMN, priority, -1); -+ } -+ -+ 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; - } --- -1.6.3.3 - - -From 835922303f2b08036727aca11adf256f2209ac0c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 15:35:00 -0500 -Subject: [PATCH 04/38] 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 e1ea8a0..e4c8e05 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1538,13 +1538,6 @@ gdm_session_direct_init (GdmSessionDirect *session) - } - - static void --worker_stopped (GdmSessionWorkerJob *job, -- GdmSessionDirect *session) --{ -- g_debug ("GdmSessionDirect: Worker job stopped"); --} -- --static void - worker_started (GdmSessionWorkerJob *job, - GdmSessionDirect *session) - { -@@ -1587,10 +1580,6 @@ start_worker (GdmSessionDirect *session) - 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, - "started", - G_CALLBACK (worker_started), - session); -@@ -1612,9 +1601,6 @@ static void - stop_worker (GdmSessionDirect *session) - { - g_signal_handlers_disconnect_by_func (session->priv->job, -- G_CALLBACK (worker_stopped), -- session); -- g_signal_handlers_disconnect_by_func (session->priv->job, - G_CALLBACK (worker_started), - session); - g_signal_handlers_disconnect_by_func (session->priv->job, -diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c -index 6723464..633d6e2 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 -@@ -390,16 +389,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 d42eb37..5ad1c92 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.3.3 - - -From 910f5f152f3cb71a8084f44374514d9cb45eca5f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 11:00:08 -0500 -Subject: [PATCH 05/38] 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 | 327 ++++++++++++++++++++++++--------------- - daemon/gdm-session-private.h | 3 +- - daemon/gdm-session-relay.c | 29 +++-- - daemon/gdm-session-worker-job.c | 7 + - daemon/gdm-session-worker-job.h | 2 + - daemon/gdm-session.c | 20 ++- - daemon/gdm-session.h | 9 +- - daemon/gdm-simple-slave.c | 3 - - daemon/test-session.c | 13 +- - 11 files changed, 296 insertions(+), 177 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, - } - - static void --on_session_opened (GdmSession *session, -- GdmFactorySlave *slave) -+on_session_conversation_started (GdmSession *session, -+ GdmFactorySlave *slave, -+ const char *service_name) - { -- g_debug ("GdmFactorySlave: session opened"); -+ g_debug ("GdmFactorySlave: session conversation started"); - - gdm_greeter_server_ready (slave->priv->greeter_server); - } -@@ -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 -@@ -694,8 +695,8 @@ gdm_factory_slave_start (GdmSlave *slave) - - 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, - } - - static void --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); - } - - static void --on_session_opened (GdmSession *session, -- GdmProductSlave *slave) -+on_session_conversation_started (GdmSession *session, -+ const char *service_name, -+ GdmProductSlave *slave) - { -- g_debug ("GdmProductSlave: session opened"); -+ g_debug ("GdmProductSlave: session conversation started"); - -- relay_session_opened (slave); -+ relay_session_conversation_started (slave, service_name); - } - - static void -@@ -784,10 +786,27 @@ on_relay_user_selected (GdmProductSlave *slave, - } - - static void --on_relay_open (GdmProductSlave *slave, -- DBusMessage *message) -+on_relay_start_conversation (GdmProductSlave *slave, -+ DBusMessage *message) - { -- 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); - } - - static void -@@ -832,8 +851,8 @@ create_new_session (GdmProductSlave *slave) - g_free (display_device); - - 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 e4c8e05..d22a764 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -61,6 +61,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; -+ - struct _GdmSessionDirectPrivate - { - /* per open scope */ -@@ -73,13 +83,11 @@ struct _GdmSessionDirectPrivate - char *selected_user; - char *user_x11_authority_file; - -- DBusMessage *message_pending_reply; -- DBusConnection *worker_connection; -+ GdmSessionConversation *conversation; - -- GdmSessionWorkerJob *job; -- GPid session_pid; - guint32 is_authenticated : 1; - guint32 is_running : 1; -+ GPid session_pid; - - /* object lifetime scope */ - char *id; -@@ -116,39 +124,39 @@ G_DEFINE_TYPE_WITH_CODE (GdmSessionDirect, - gdm_session_iface_init)) - - static gboolean --send_dbus_message (DBusConnection *connection, -- DBusMessage *message) -+send_dbus_message (GdmSessionConversation *conversation, -+ DBusMessage *message) - { - 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; - } - - 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, -@@ -157,7 +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); - -- if (! send_dbus_message (session->priv->worker_connection, message)) { -+ if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", name); - } - -@@ -165,18 +173,18 @@ send_dbus_string_signal (GdmSessionDirect *session, - } - - 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); - } - -@@ -188,22 +196,32 @@ on_authentication_failed (GdmSession *session, - 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 = 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_session_started (GdmSession *session) - { - 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); -+ } - } - - static void -@@ -211,11 +229,16 @@ on_session_start_failed (GdmSession *session, - 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 = 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); -+ } - } - - static void -@@ -223,6 +246,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, -@@ -733,25 +757,26 @@ gdm_session_direct_handle_username_changed (GdmSessionDirect *session, - } - - static void --cancel_pending_query (GdmSessionDirect *session) -+cancel_pending_query (GdmSessionConversation *conversation) - { - DBusMessage *reply; - -- 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"); -- 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); -- session->priv->message_pending_reply = NULL; -+ dbus_message_unref (conversation->message_pending_reply); -+ conversation->message_pending_reply = NULL; - } - - static void -@@ -760,27 +785,29 @@ answer_pending_query (GdmSessionDirect *session, - { - DBusMessage *reply; - 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); - -- 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); -- session->priv->message_pending_reply = NULL; -+ dbus_message_unref (conversation->message_pending_reply); -+ conversation->message_pending_reply = NULL; - } - - static void --set_pending_query (GdmSessionDirect *session, -- DBusMessage *message) -+set_pending_query (GdmSessionConversation *conversation, -+ DBusMessage *message) - { -- g_assert (session->priv->message_pending_reply == NULL); -+ g_assert (conversation->message_pending_reply == NULL); - -- session->priv->message_pending_reply = dbus_message_ref (message); -+ conversation->message_pending_reply = dbus_message_ref (message); - } - - static DBusHandlerResult -@@ -798,7 +825,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), text); -@@ -821,7 +848,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), text); -@@ -863,7 +890,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 (connection, reply, NULL); -@@ -1429,16 +1456,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 - }; - -- 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); - -@@ -1455,8 +1484,9 @@ handle_connection (DBusServer *server, - &vtable, - session); - -- 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); - } - } - -@@ -1526,8 +1556,6 @@ gdm_session_direct_init (GdmSessionDirect *session) - G_CALLBACK (on_session_exited), - NULL); - -- session->priv->session_pid = -1; -- - session->priv->environment = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, -@@ -1539,7 +1567,7 @@ gdm_session_direct_init (GdmSessionDirect *session) - - static void - worker_started (GdmSessionWorkerJob *job, -- GdmSessionDirect *session) -+ GdmSessionConversation *conversation) - { - g_debug ("GdmSessionDirect: Worker job started"); - } -@@ -1547,91 +1575,111 @@ worker_started (GdmSessionWorkerJob *job, - static void - worker_exited (GdmSessionWorkerJob *job, - int code, -- GdmSessionDirect *session) -+ GdmSessionConversation *conversation) - { - g_debug ("GdmSessionDirect: Worker job exited: %d", code); - -- if (!session->priv->is_authenticated) { -- _gdm_session_authentication_failed (GDM_SESSION (session), NULL); -- } else if (session->priv->is_running) { -- _gdm_session_session_exited (GDM_SESSION (session), code); -+ if (!conversation->session->priv->is_authenticated) { -+ _gdm_session_authentication_failed (GDM_SESSION (conversation->session), NULL); -+ } else if (conversation->session->priv->is_running) { -+ _gdm_session_session_exited (GDM_SESSION (conversation->session), code); - } - } - - static void - worker_died (GdmSessionWorkerJob *job, - int signum, -- GdmSessionDirect *session) -+ GdmSessionConversation *conversation) - { - g_debug ("GdmSessionDirect: Worker job died: %d", signum); - -- if (!session->priv->is_authenticated) { -- _gdm_session_authentication_failed (GDM_SESSION (session), NULL); -- } else if (session->priv->is_running) { -- _gdm_session_session_died (GDM_SESSION (session), signum); -+ if (!conversation->session->priv->is_authenticated) { -+ _gdm_session_authentication_failed (GDM_SESSION (conversation->session), NULL); -+ } else if (conversation->session->priv->is_running) { -+ _gdm_session_session_died (GDM_SESSION (conversation->session), signum); - } - } - --static gboolean --start_worker (GdmSessionDirect *session) -+static GdmSessionConversation * -+start_conversation (GdmSessionDirect *session, -+ const char *service_name) - { -- 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, - "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; -+ conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job); -+ -+ return conversation; - } - - static void --stop_worker (GdmSessionDirect *session) -+stop_conversation (GdmSessionConversation *conversation) - { -- 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); - - cancel_pending_query (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_remove_filter (conversation->worker_connection, on_message, session); -+ -+ dbus_connection_close (conversation->worker_connection); -+ conversation->worker_connection = NULL; - } - -- 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); - } - - static void --gdm_session_direct_open (GdmSession *session) -+gdm_session_direct_start_conversation (GdmSession *session, -+ 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); - } - - static void -@@ -1644,6 +1692,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); - -@@ -1681,7 +1730,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 = session->priv->conversation; -+ if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "Setup"); - } - -@@ -1699,6 +1749,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); - -@@ -1742,7 +1793,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, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForUser"); - } - -@@ -1756,7 +1808,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); -@@ -1770,7 +1823,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); -@@ -1783,22 +1837,28 @@ static void - gdm_session_direct_authenticate (GdmSession *session) - { - 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)); -+ 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"); - } - - static void - gdm_session_direct_authorize (GdmSession *session) - { - 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)); -+ 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"); -+ conversation = impl->priv->conversation; -+ send_dbus_void_signal (conversation, "Authorize"); - } - - static void -@@ -1806,16 +1866,19 @@ gdm_session_direct_accredit (GdmSession *session, - 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)); -+ g_return_if_fail (impl->priv->conversation != NULL); -+ g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - -+ 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 (); -@@ -1829,6 +1892,7 @@ send_environment_variable (const char *key, - { - DBusMessage *message; - DBusMessageIter iter; -+ GdmSessionConversation *conversation; - - message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, - GDM_SESSION_DBUS_INTERFACE, -@@ -1838,7 +1902,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); - -- if (! send_dbus_message (session->priv->worker_connection, message)) { -+ conversation = session->priv->conversation; -+ if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable"); - } - -@@ -1971,6 +2036,7 @@ static void - gdm_session_direct_start_session (GdmSession *session) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - char *command; - char *program; - -@@ -1984,7 +2050,8 @@ gdm_session_direct_start_session (GdmSession *session) - setup_session_environment (impl); - send_environment (impl); - -- send_dbus_string_signal (impl, "StartProgram", program); -+ conversation = impl->priv->conversation; -+ send_dbus_string_signal (conversation, "StartProgram", program); - g_free (program); - } - -@@ -1997,16 +2064,12 @@ gdm_session_direct_close (GdmSession *session) - - 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); - } - - g_free (impl->priv->selected_user); -@@ -2035,7 +2098,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; - } -@@ -2055,10 +2117,19 @@ 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); - -- cancel_pending_query (impl); -+ 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); -+ } - } - - char * -@@ -2074,6 +2145,7 @@ gdm_session_direct_select_session (GdmSession *session, - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - - g_free (impl->priv->selected_session); - -@@ -2083,7 +2155,8 @@ gdm_session_direct_select_session (GdmSession *session, - impl->priv->selected_session = g_strdup (text); - } - -- send_dbus_string_signal (impl, "SetSessionName", -+ conversation = impl->priv->conversation; -+ send_dbus_string_signal (conversation, "SetSessionName", - get_session_name (impl)); - } - -@@ -2092,6 +2165,7 @@ gdm_session_direct_select_language (GdmSession *session, - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - - g_free (impl->priv->selected_language); - -@@ -2101,7 +2175,8 @@ gdm_session_direct_select_language (GdmSession *session, - impl->priv->selected_language = g_strdup (text); - } - -- send_dbus_string_signal (impl, "SetLanguageName", -+ conversation = impl->priv->conversation; -+ send_dbus_string_signal (conversation, "SetLanguageName", - get_language_name (impl)); - } - -@@ -2110,6 +2185,7 @@ gdm_session_direct_select_layout (GdmSession *session, - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - - g_free (impl->priv->selected_layout); - -@@ -2119,7 +2195,8 @@ gdm_session_direct_select_layout (GdmSession *session, - impl->priv->selected_layout = g_strdup (text); - } - -- send_dbus_string_signal (impl, "SetLayoutName", -+ conversation = impl->priv->conversation; -+ send_dbus_string_signal (conversation, "SetLayoutName", - get_layout_name (impl)); - } - -@@ -2379,7 +2456,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 - - /* 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, - } - - 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 -@@ -664,22 +665,28 @@ handle_session_stopped (GdmSessionRelay *session_relay, - } - - 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); -+ } - -- g_debug ("GdmSessionRelay: Opened"); -+ g_debug ("GdmSessionRelay: Conversation Started"); - - reply = dbus_message_new_method_return (message); - 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); - - 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); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -@@ -749,7 +756,8 @@ do_introspect (DBusConnection *connection, - /* interface */ - xml = g_string_append (xml, - " \n" -- " \n" -+ " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -810,7 +818,8 @@ do_introspect (DBusConnection *connection, - " \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-worker-job.c b/daemon/gdm-session-worker-job.c -index 633d6e2..9c020fa 100644 ---- a/daemon/gdm-session-worker-job.c -+++ b/daemon/gdm-session-worker-job.c -@@ -296,6 +296,13 @@ gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job) - return TRUE; - } - -+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) -diff --git a/daemon/gdm-session-worker-job.h b/daemon/gdm-session-worker-job.h -index 5ad1c92..d24f025 100644 ---- a/daemon/gdm-session-worker-job.h -+++ b/daemon/gdm-session-worker-job.h -@@ -60,6 +60,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); - -+GPid gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job); -+ - G_END_DECLS - - #endif /* __GDM_SESSION_WORKER_JOB_H */ -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 8b161bb..12e514e 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -174,7 +174,6 @@ reset_session (GdmSimpleSlave *slave) - { - destroy_session (slave); - create_new_session (slave); -- gdm_session_open (GDM_SESSION (slave->priv->session)); - } - - static gboolean -@@ -822,8 +821,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.3.3 - - -From f4596a6df988f88afe2d9d06ffeaf978eb519931 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 4 Feb 2009 10:55:03 -0500 -Subject: [PATCH 06/38] Rename session worker to the service it's managing - -This way when we're running multiple PAM conversations at once -it will be obvious which worker is managing which conversation. ---- - 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 d22a764..86bd59d 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1605,6 +1605,7 @@ start_conversation (GdmSessionDirect *session, - const char *service_name) - { - GdmSessionConversation *conversation; -+ char *job_name; - - conversation = g_new0 (GdmSessionConversation, 1); - conversation->session = session; -@@ -1625,12 +1626,16 @@ start_conversation (GdmSessionDirect *session, - G_CALLBACK (worker_died), - conversation); - -- 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); - - conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job); - -diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c -index 9c020fa..0327d77 100644 ---- a/daemon/gdm-session-worker-job.c -+++ b/daemon/gdm-session-worker-job.c -@@ -149,6 +149,37 @@ copy_environment_to_hash (GHashTable *hash) - } - - 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; -@@ -171,31 +202,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, -@@ -204,6 +235,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); - -@@ -220,7 +254,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; -@@ -233,13 +266,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) { - -@@ -287,6 +321,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 d24f025..4833f23 100644 ---- a/daemon/gdm-session-worker-job.h -+++ b/daemon/gdm-session-worker-job.h -@@ -57,7 +57,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.3.3 - - -From bae5bb00c77b693ab31d58aba416ec4a103f8501 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 13:01:48 -0500 -Subject: [PATCH 07/38] 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 | 32 ++++++++++++++---- - gui/simple-greeter/gdm-greeter-client.c | 18 ++++++---- - gui/simple-greeter/gdm-greeter-client.h | 4 ++- - gui/simple-greeter/gdm-greeter-session.c | 4 ++ - 7 files changed, 99 insertions(+), 20 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 cecce83..ffca7ec 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" -@@ -759,6 +795,7 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -1121,6 +1158,16 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) - "group name", - GDM_GROUPNAME, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); -+ signals [START_CONVERSATION] = -+ g_signal_new ("start-conversation", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmGreeterServerClass, start_conversation), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); - 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; - -+ 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_for_user)(GdmGreeterServer *greeter_server, -@@ -85,7 +87,8 @@ gboolean gdm_greeter_server_info (GdmGreeterServer * - gboolean gdm_greeter_server_problem (GdmGreeterServer *greeter_server, - 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); - 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 12e514e..8863fd4 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -484,17 +484,19 @@ on_session_secret_info_query (GdmSession *session, - } - - 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; - 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"); - } -@@ -510,8 +512,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); - } - -@@ -603,8 +607,8 @@ create_new_session (GdmSimpleSlave *slave) - 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, - "setup-complete", -@@ -735,6 +739,16 @@ on_greeter_session_died (GdmGreeterSession *greeter, - } - - 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); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), -+ service_name); -+} -+ -+static void - on_greeter_begin_verification (GdmGreeterServer *greeter_server, - GdmSimpleSlave *slave) - { -@@ -909,6 +923,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); - } - - static void -@@ -400,6 +396,14 @@ send_dbus_void_method (DBusConnection *connection, - } - - 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) - { -@@ -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); - - 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); -diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c -index fe2de48..ec99c12 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -85,6 +85,7 @@ on_problem (GdmGreeterClient *client, - - static void - on_ready (GdmGreeterClient *client, -+ const char *service_name, - GdmGreeterSession *session) - { - g_debug ("GdmGreeterSession: Ready"); -@@ -264,6 +265,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 -@@ -426,6 +428,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.3.3 - - -From d3004477cb4424526f6ae2132d0554501cd9ffc5 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 16 Jan 2009 15:18:31 -0500 -Subject: [PATCH 08/38] 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 | 132 ++++++++++++++++++++++++++++++++++--------- - 1 files changed, 106 insertions(+), 26 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 86bd59d..9af8252 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -84,6 +84,7 @@ struct _GdmSessionDirectPrivate - char *user_x11_authority_file; - - GdmSessionConversation *conversation; -+ GHashTable *conversations; - - guint32 is_authenticated : 1; - guint32 is_running : 1; -@@ -1450,6 +1451,42 @@ allow_user_function (DBusConnection *connection, - return FALSE; - } - -+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 GdmSessionConversation * -+find_conversation_by_pid (GdmSessionDirect *session, -+ GPid pid) -+{ -+ 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, -@@ -1457,10 +1494,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; -+ } -+ - if (conversation->worker_connection == NULL) { - DBusObjectPathVTable vtable = { &session_unregister_handler, - &session_message_handler, -@@ -1533,6 +1582,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, -@@ -1556,6 +1616,11 @@ gdm_session_direct_init (GdmSessionDirect *session) - G_CALLBACK (on_session_exited), - NULL); - -+ 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, -@@ -1659,8 +1724,6 @@ stop_conversation (GdmSessionConversation *conversation) - G_CALLBACK (worker_died), - conversation); - -- cancel_pending_query (session); -- - if (conversation->worker_connection != NULL) { - dbus_connection_remove_filter (conversation->worker_connection, on_message, session); - -@@ -1669,9 +1732,9 @@ stop_conversation (GdmSessionConversation *conversation) - } - - gdm_session_worker_job_stop (conversation->job); -+ - g_object_unref (conversation->job); -- g_free (conversation->service_name); -- g_free (conversation); -+ conversation->job = NULL; - } - - static void -@@ -1679,12 +1742,20 @@ gdm_session_direct_start_conversation (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"); - -- 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; -+ } - } - - static void -@@ -1735,8 +1806,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"); - } - -@@ -1798,8 +1869,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"); - } - -@@ -1813,8 +1884,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); -@@ -1828,8 +1897,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); - - gdm_session_direct_select_user (session, username); -@@ -2061,6 +2128,28 @@ gdm_session_direct_start_session (GdmSession *session) - } - - 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); -@@ -2077,6 +2166,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; - -@@ -2121,20 +2212,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.3.3 - - -From c26960e1b2b5f9dbd2afb68c60b68e972c85b2eb Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 4 Mar 2009 22:09:21 -0500 -Subject: [PATCH 09/38] start autologin conversation when creating session if necessary - -Without this autologin breaks, since when it comes time to -autologin, there's no worker to do it. ---- - daemon/gdm-simple-slave.c | 10 ++++++++++ - 1 files changed, 10 insertions(+), 0 deletions(-) - -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index 8863fd4..4db7440 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -1036,8 +1036,18 @@ idle_connect_to_display (GdmSimpleSlave *slave) - if (! enabled || delay > 0) { - start_greeter (slave); - create_new_session (slave); -+ -+ if (enabled) { -+ g_debug ("GdmSimpleSlave: Starting timed login conversation"); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), -+ "gdm-autologin"); -+ } - } else { - reset_session (slave); -+ -+ g_debug ("GdmSimpleSlave: Starting automatic login conversation"); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), -+ "gdm-autologin"); - } - } else { - if (slave->priv->connection_attempts >= MAX_CONNECT_ATTEMPTS) { --- -1.6.3.3 - - -From 4cab3c989f849f27ed4b225d50e40c89a25eadd1 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 22 Jan 2009 08:52:01 -0500 -Subject: [PATCH 10/38] Propagate service name to more layers - -This is more prep work to get multiple concurrent -PAM stacks going. ---- - daemon/gdm-factory-slave.c | 63 +++-- - daemon/gdm-greeter-server.c | 120 ++++++-- - daemon/gdm-greeter-server.h | 17 +- - daemon/gdm-product-slave.c | 233 +++++++++++++--- - daemon/gdm-session-direct.c | 465 ++++++++++++++++++------------ - daemon/gdm-session-private.h | 22 ++- - daemon/gdm-session-relay.c | 122 +++++++-- - daemon/gdm-session-worker.c | 27 ++ - daemon/gdm-session.c | 151 ++++++----- - daemon/gdm-session.h | 44 +++- - daemon/gdm-simple-slave.c | 70 ++++-- - daemon/test-session.c | 22 +- - gui/simple-greeter/gdm-greeter-client.c | 188 ++++++++++--- - gui/simple-greeter/gdm-greeter-client.h | 16 +- - gui/simple-greeter/gdm-greeter-session.c | 11 +- - 15 files changed, 1126 insertions(+), 445 deletions(-) - -diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c -index d1bb5dd..826612e 100644 ---- a/daemon/gdm-factory-slave.c -+++ b/daemon/gdm-factory-slave.c -@@ -144,45 +144,49 @@ on_greeter_session_died (GdmGreeterSession *greeter, - - 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_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, - - 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 - 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")); - - queue_greeter_reset (slave); - } -@@ -224,23 +230,26 @@ on_session_reset_failed (GdmSession *session, - - static void - on_session_authenticated (GdmSession *session, -+ const char *service_name, - GdmFactorySlave *slave) - { -- gdm_session_authorize (session); -+ gdm_session_authorize (session, service_name); - } - - 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); - } - - 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; - -- gdm_session_accredit (session, flag); -+ gdm_session_accredit (session, service_name, flag); - } - - static void - on_session_authorization_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmFactorySlave *slave) - { -- 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 - on_session_accredited (GdmSession *session, -+ const char *service_name, - GdmFactorySlave *slave) - { - g_debug ("GdmFactorySlave: session user verified"); - -- gdm_session_start_session (session); -+ gdm_session_start_session (session, service_name); - - gdm_greeter_server_reset (slave->priv->greeter_server); - } - - static void - on_session_accreditation_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmFactorySlave *slave) - { - 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); - } -@@ -368,37 +380,48 @@ 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) -+{ -+ g_debug ("GdmFactorySlave: start conversation"); - -- gdm_session_start_conversation (GDM_SESSION (slave->priv->session), "gdm"); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), service_name); - } - - static void - on_greeter_begin_verification (GdmGreeterServer *greeter_server, -+ const char *service_name, - GdmFactorySlave *slave) - { - g_debug ("GdmFactorySlave: begin verification"); - gdm_session_setup (GDM_SESSION (slave->priv->session), -- "gdm"); -+ service_name); - } - - static void - on_greeter_begin_verification_for_user (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *username, - GdmFactorySlave *slave) - { - g_debug ("GdmFactorySlave: begin verification for user"); - gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), -- "gdm", -+ service_name, - username); - } - - static void - on_greeter_answer (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text, - GdmFactorySlave *slave) - { - 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 void -@@ -495,6 +518,10 @@ run_greeter (GdmFactorySlave *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-verification", - G_CALLBACK (on_greeter_begin_verification), - slave); -diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c -index ffca7ec..dae34c5 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, - } - - 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) - { -- send_dbus_string_signal (greeter_server, "InfoQuery", text); -+ send_dbus_string_string_signal (greeter_server, "InfoQuery", service_name, text); - - return TRUE; - } - - gboolean - gdm_greeter_server_secret_info_query (GdmGreeterServer *greeter_server, -+ 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; - } - - gboolean - gdm_greeter_server_info (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text) - { -- send_dbus_string_signal (greeter_server, "Info", text); -+ send_dbus_string_string_signal (greeter_server, "Info", service_name, text); - return TRUE; - } - - gboolean - gdm_greeter_server_problem (GdmGreeterServer *greeter_server, -+ 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; - } - -@@ -291,9 +336,10 @@ gdm_greeter_server_request_timed_login (GdmGreeterServer *greeter_server, - } - - 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); - } - - /* 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; -+ -+ 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: BeginVerification"); - -@@ -365,7 +421,7 @@ handle_begin_verification (GdmGreeterServer *greeter_server, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION], 0); -+ g_signal_emit (greeter_server, signals [BEGIN_VERIFICATION], 0, service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -379,7 +435,6 @@ handle_begin_auto_login (GdmGreeterServer *greeter_server, - DBusError error; - const char *text; - -- - 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; - - 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_debug ("GreeterServer: BeginVerificationForUser for '%s'", text); - -@@ -420,7 +478,7 @@ handle_begin_verification_for_user (GdmGreeterServer *greeter_server, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- 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 DBUS_HANDLER_RESULT_HANDLED; - } -@@ -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); - } -+ dbus_error_free (&error); - - g_debug ("GreeterServer: AnswerQuery"); - -@@ -447,7 +508,7 @@ handle_answer_query (GdmGreeterServer *greeter_server, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- 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; - } -@@ -644,9 +705,11 @@ handle_start_session_when_ready (GdmGreeterServer *greeter_server, - 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); -@@ -660,9 +723,9 @@ handle_start_session_when_ready (GdmGreeterServer *greeter_server, - 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_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" -@@ -800,6 +871,7 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -+ " \n" - " \n" - " \n"); - -@@ -1175,9 +1247,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), -@@ -1196,10 +1268,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), -@@ -1207,10 +1279,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), -@@ -1304,9 +1376,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); - - signals [START_SESSION_LATER] = - g_signal_new ("start-session-later", -@@ -1315,9 +1387,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); - } - - 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; - -@@ -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); - -- - 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); - - G_END_DECLS - -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 - - DBusGProxy *product_display_proxy; - DBusGConnection *connection; -+ -+ char *start_session_service_name; - }; - - enum { -@@ -93,6 +95,68 @@ static void gdm_product_slave_finalize (GObject *object); - G_DEFINE_TYPE (GdmProductSlave, gdm_product_slave, GDM_TYPE_SLAVE) - - 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); - -- gdm_session_start_session (GDM_SESSION (slave->priv->session)); -+ gdm_session_start_session (GDM_SESSION (slave->priv->session), -+ slave->priv->start_session_service_name); - - return TRUE; - } -@@ -508,96 +573,112 @@ on_session_reset_failed (GdmSession *session, - - static void - on_session_authenticated (GdmSession *session, -+ const char *service_name, - GdmProductSlave *slave) - { -- send_dbus_void_method (slave->priv->session_relay_connection, -- "Authenticated"); -+ send_dbus_string_method (slave->priv->session_relay_connection, -+ "Authenticated", service_name); - } - - 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); - } - - 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); - } - - 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); - } - - static void - on_session_accredited (GdmSession *session, -+ const char *service_name, - GdmProductSlave *slave) - { -- send_dbus_void_method (slave->priv->session_relay_connection, -- "Accredited"); -+ send_dbus_string_method (slave->priv->session_relay_connection, -+ "Accredited", service_name); - } - - static void - on_session_accreditation_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmProductSlave *slave) - { -- 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); - } - - 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); - } - - 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 - on_session_info_query (GdmSession *session, -+ const char *service_name, - const char *text, - GdmProductSlave *slave) - { -- 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); - } - - 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); - } - - 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; - -- 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); - } - - static void - on_relay_authorize (GdmProductSlave *slave, - DBusMessage *message) - { -- g_debug ("GdmProductSlave: Relay Authorize"); -+ DBusError error; -+ char *service_name; -+ dbus_bool_t res; - -- 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); - } - - static void - on_relay_establish_credentials (GdmProductSlave *slave, - DBusMessage *message) - { -- g_debug ("GdmProductSlave: Relay EstablishCredentials"); -+ DBusError error; -+ char *service_name; -+ dbus_bool_t res; - -- 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); - } - - static void - on_relay_refresh_credentials (GdmProductSlave *slave, - DBusMessage *message) - { -- g_debug ("GdmProductSlave: Relay RefreshCredentials"); -+ DBusError error; -+ char *service_name; -+ dbus_bool_t res; - -- 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); - } - - static void -@@ -696,16 +833,18 @@ on_relay_answer_query (GdmProductSlave *slave, - { - DBusError error; - const char *text; -+ 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_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); -+ } - } - - static void -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 9af8252..dbd85a7 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -83,9 +83,10 @@ struct _GdmSessionDirectPrivate - char *selected_user; - char *user_x11_authority_file; - -- GdmSessionConversation *conversation; - GHashTable *conversations; - -+ GList *pending_connections; -+ - guint32 is_authenticated : 1; - guint32 is_running : 1; - GPid session_pid; -@@ -192,14 +193,30 @@ send_dbus_void_signal (GdmSessionConversation *conversation, - dbus_message_unref (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; - -- 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, -@@ -210,12 +227,13 @@ on_authentication_failed (GdmSession *session, - } - - static void --on_session_started (GdmSession *session) -+on_session_started (GdmSession *session, -+ const char *service_name) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; - -- 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, -@@ -227,12 +245,13 @@ on_session_started (GdmSession *session) - - static void - on_session_start_failed (GdmSession *session, -+ const char *service_name, - const char *message) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); - GdmSessionConversation *conversation; - -- 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, -@@ -257,7 +276,7 @@ on_session_exited (GdmSession *session, - - static DBusHandlerResult - gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -265,17 +284,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; -@@ -290,12 +309,12 @@ gdm_session_direct_handle_setup_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 'setup-failed' signal"); - -- _gdm_session_setup_failed (GDM_SESSION (session), text); -+ _gdm_session_setup_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -303,7 +322,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; -@@ -311,7 +330,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)); -@@ -321,7 +340,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) - { - DBusMessage *reply; -@@ -336,7 +355,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"); -@@ -348,7 +367,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; -@@ -356,18 +375,18 @@ gdm_session_direct_handle_authenticated (GdmSessionDirect *session, - g_debug ("GdmSessionDirect: Emitting 'authenticated' 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); - - session->priv->is_authenticated = TRUE; -- _gdm_session_authenticated (GDM_SESSION (session)); -+ _gdm_session_authenticated (GDM_SESSION (session), conversation->service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -382,20 +401,20 @@ gdm_session_direct_handle_authentication_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 'authentication-failed' signal"); - - session->priv->is_authenticated = FALSE; -- _gdm_session_authentication_failed (GDM_SESSION (session), text); -+ _gdm_session_authentication_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_authorized (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -403,17 +422,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); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_authorization_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -428,19 +447,19 @@ gdm_session_direct_handle_authorization_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 'authorization-failed' signal"); - -- _gdm_session_authorization_failed (GDM_SESSION (session), text); -+ _gdm_session_authorization_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_accredited (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -448,17 +467,17 @@ gdm_session_direct_handle_accredited (GdmSessionDirect *session, - 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 DBusHandlerResult - gdm_session_direct_handle_accreditation_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -473,12 +492,12 @@ gdm_session_direct_handle_accreditation_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 'accreditation-failed' signal"); - -- _gdm_session_accreditation_failed (GDM_SESSION (session), text); -+ _gdm_session_accreditation_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -726,7 +745,7 @@ gdm_session_direct_select_user (GdmSession *session, - - static DBusHandlerResult - gdm_session_direct_handle_username_changed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -741,7 +760,7 @@ gdm_session_direct_handle_username_changed (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: changing username from '%s' to '%s'", -@@ -771,7 +790,7 @@ cancel_pending_query (GdmSessionConversation *conversation) - reply = dbus_message_new_error (conversation->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 (GdmSessionConversation *conversation) - - 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 (GdmSessionConversation *conversation, - - 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 (conversation, 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 (conversation, 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; - } - - static DBusHandlerResult - gdm_session_direct_handle_info (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -874,18 +894,18 @@ gdm_session_direct_handle_info (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 'info' signal"); -- _gdm_session_info (GDM_SESSION (session), text); -+ _gdm_session_info (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_cancel_pending_query (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 (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); - - return DBUS_HANDLER_RESULT_HANDLED; -@@ -902,7 +922,7 @@ gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, - - static DBusHandlerResult - gdm_session_direct_handle_problem (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, - } - - 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 (! get_session_command_for_name (session_name, NULL)) { -@@ -1156,54 +1176,57 @@ session_worker_message (DBusConnection *connection, - DBusMessage *message, - void *user_data) - { -- GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); -+ GdmSessionConversation *conversation = user_data; -+ GdmSessionDirect *session; -+ -+ session = conversation->session; - - if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "InfoQuery")) { -- return gdm_session_direct_handle_info_query (session, connection, message); -+ return gdm_session_direct_handle_info_query (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SecretInfoQuery")) { -- return gdm_session_direct_handle_secret_info_query (session, connection, message); -+ return gdm_session_direct_handle_secret_info_query (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Info")) { -- return gdm_session_direct_handle_info (session, connection, message); -+ return gdm_session_direct_handle_info (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Problem")) { -- return gdm_session_direct_handle_problem (session, connection, message); -+ return gdm_session_direct_handle_problem (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "CancelPendingQuery")) { -- return gdm_session_direct_handle_cancel_pending_query (session, connection, message); -+ return gdm_session_direct_handle_cancel_pending_query (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupComplete")) { -- return gdm_session_direct_handle_setup_complete (session, connection, message); -+ return gdm_session_direct_handle_setup_complete (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupFailed")) { -- return gdm_session_direct_handle_setup_failed (session, connection, message); -+ return gdm_session_direct_handle_setup_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetComplete")) { -- return gdm_session_direct_handle_reset_complete (session, connection, message); -+ return gdm_session_direct_handle_reset_complete (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetFailed")) { -- return gdm_session_direct_handle_reset_failed (session, connection, message); -+ return gdm_session_direct_handle_reset_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authenticated")) { -- return gdm_session_direct_handle_authenticated (session, connection, message); -+ return gdm_session_direct_handle_authenticated (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthenticationFailed")) { -- return gdm_session_direct_handle_authentication_failed (session, connection, message); -+ return gdm_session_direct_handle_authentication_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authorized")) { -- return gdm_session_direct_handle_authorized (session, connection, message); -+ return gdm_session_direct_handle_authorized (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthorizationFailed")) { -- return gdm_session_direct_handle_authorization_failed (session, connection, message); -+ return gdm_session_direct_handle_authorization_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Accredited")) { -- return gdm_session_direct_handle_accredited (session, connection, message); -+ return gdm_session_direct_handle_accredited (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AccreditationFailed")) { -- return gdm_session_direct_handle_accreditation_failed (session, connection, message); -+ return gdm_session_direct_handle_accreditation_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) { -- return gdm_session_direct_handle_username_changed (session, connection, message); -+ return gdm_session_direct_handle_username_changed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) { -- return gdm_session_direct_handle_session_started (session, connection, message); -+ return gdm_session_direct_handle_session_started (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartFailed")) { -- return gdm_session_direct_handle_start_failed (session, connection, message); -+ return gdm_session_direct_handle_start_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionExited")) { -- return gdm_session_direct_handle_session_exited (session, connection, message); -+ return gdm_session_direct_handle_session_exited (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionDied")) { -- return gdm_session_direct_handle_session_died (session, connection, message); -+ return gdm_session_direct_handle_session_died (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLanguageNameRead")) { -- return gdm_session_direct_handle_saved_language_name_read (session, connection, message); -+ return gdm_session_direct_handle_saved_language_name_read (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLayoutNameRead")) { -- return gdm_session_direct_handle_saved_layout_name_read (session, connection, message); -+ return gdm_session_direct_handle_saved_layout_name_read (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedSessionNameRead")) { -- return gdm_session_direct_handle_saved_session_name_read (session, connection, message); -+ return gdm_session_direct_handle_saved_session_name_read (session, conversation, message); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -@@ -1437,6 +1460,27 @@ session_unregister_handler (DBusConnection *connection, - g_debug ("session_unregister_handler"); - } - -+static GdmSessionConversation * -+find_conversation_by_pid (GdmSessionDirect *session, -+ GPid pid) -+{ -+ 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 dbus_bool_t - allow_user_function (DBusConnection *connection, - unsigned long uid, -@@ -1451,40 +1495,83 @@ allow_user_function (DBusConnection *connection, - return FALSE; - } - --static GdmSessionConversation * --find_conversation_by_name (GdmSessionDirect *session, -- const char *service_name) -+static gboolean -+register_worker (GdmSessionDirect *session, -+ DBusConnection *connection) - { - 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); -+ -+ if (connection_node == NULL) { -+ g_debug ("GdmSessionDirect: Ignoring connection that we aren't tracking"); -+ return FALSE; -+ } -+ -+ session->priv->pending_connections = -+ g_list_delete_link (session->priv->pending_connections, -+ connection_node); -+ -+ if (!dbus_connection_get_unix_process_id (connection, &pid)) { -+ g_warning ("GdmSessionDirect: Unable to read pid on new worker connection"); -+ dbus_connection_unref (connection); -+ return FALSE; -+ } -+ -+ conversation = find_conversation_by_pid (session, (GPid) pid); - - if (conversation == NULL) { -- g_warning ("Tried to look up non-existant conversation"); -+ 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); -+ -+ dbus_connection_register_object_path (connection, -+ GDM_SESSION_DBUS_PATH, -+ &vtable, -+ conversation); -+ -+ g_debug ("GdmSessionDirect: Emitting conversation-started signal"); -+ _gdm_session_conversation_started (GDM_SESSION (session), -+ conversation->service_name); -+ -+ 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 -@@ -1493,50 +1580,23 @@ handle_connection (DBusServer *server, - 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) { -- DBusObjectPathVTable vtable = { &session_unregister_handler, -- &session_message_handler, -- NULL, NULL, NULL, NULL -- }; -- -- conversation->worker_connection = new_connection; -- dbus_connection_ref (new_connection); -- dbus_connection_setup_with_g_main (new_connection, NULL); -- -- g_debug ("GdmSessionDirect: worker connection is %p", new_connection); -- dbus_connection_set_exit_on_disconnect (new_connection, FALSE); -- -- dbus_connection_set_unix_user_function (new_connection, -- allow_user_function, -- session, -- NULL); -- -- dbus_connection_register_object_path (new_connection, -- GDM_SESSION_DBUS_PATH, -- &vtable, -- 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). -+ */ -+ session->priv->pending_connections = -+ g_list_prepend (session->priv->pending_connections, -+ dbus_connection_ref (new_connection)); -+ dbus_connection_setup_with_g_main (new_connection, NULL); -+ dbus_connection_set_exit_on_disconnect (new_connection, FALSE); - -- 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, -+ NULL); -+ dbus_connection_add_filter (new_connection, on_message, session, NULL); - } - - static gboolean -@@ -1752,10 +1812,6 @@ gdm_session_direct_start_conversation (GdmSession *session, - - g_hash_table_insert (impl->priv->conversations, - g_strdup (service_name), conversation); -- -- if (impl->priv->conversation != NULL) { -- impl->priv->conversation = conversation; -- } - } - - static void -@@ -1906,45 +1962,50 @@ gdm_session_direct_setup_for_user (GdmSession *session, - } - - 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 (impl->priv->conversation != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - -- 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"); -+ } - } - - 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 (impl->priv->conversation != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - -- 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"); -+ } - } - - 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 (impl->priv->conversation != NULL); -- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); - -- conversation = impl->priv->conversation; -+ conversation = find_conversation_by_name (impl, service_name); -+ if (conversation == NULL) { -+ return; -+ } -+ - switch (cred_flag) { - case GDM_SESSION_CRED_ESTABLISH: - send_dbus_void_signal (conversation, "EstablishCredentials"); -@@ -1958,13 +2019,12 @@ gdm_session_direct_accredit (GdmSession *session, - } - - 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; -- GdmSessionConversation *conversation; - - message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, - GDM_SESSION_DBUS_INTERFACE, -@@ -1974,7 +2034,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); - -- conversation = session->priv->conversation; - if (! send_dbus_message (conversation, message)) { - g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable"); - } -@@ -1983,12 +2042,13 @@ send_environment_variable (const char *key, - } - - 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 * -@@ -2105,7 +2165,8 @@ setup_session_environment (GdmSessionDirect *session) - } - - 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; -@@ -2119,10 +2180,11 @@ gdm_session_direct_start_session (GdmSession *session) - 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); - -- conversation = impl->priv->conversation; - send_dbus_string_signal (conversation, "StartProgram", program); - g_free (program); - } -@@ -2168,6 +2230,11 @@ gdm_session_direct_close (GdmSession *session) - - 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; - -@@ -2200,13 +2267,14 @@ gdm_session_direct_close (GdmSession *session) - - 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 -@@ -2230,7 +2298,8 @@ gdm_session_direct_select_session (GdmSession *session, - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- GdmSessionConversation *conversation; -+ GHashTableIter iter; -+ gpointer key, value; - - g_free (impl->priv->selected_session); - -@@ -2240,9 +2309,15 @@ gdm_session_direct_select_session (GdmSession *session, - impl->priv->selected_session = g_strdup (text); - } - -- conversation = impl->priv->conversation; -- send_dbus_string_signal (conversation, "SetSessionName", -- get_session_name (impl)); -+ g_hash_table_iter_init (&iter, impl->priv->conversations); -+ while (g_hash_table_iter_next (&iter, &key, &value)) { -+ GdmSessionConversation *conversation; -+ -+ conversation = (GdmSessionConversation *) value; -+ -+ send_dbus_string_signal (conversation, "SetSessionName", -+ get_session_name (impl)); -+ } - } - - static void -@@ -2250,7 +2325,8 @@ gdm_session_direct_select_language (GdmSession *session, - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- GdmSessionConversation *conversation; -+ GHashTableIter iter; -+ gpointer key, value; - - g_free (impl->priv->selected_language); - -@@ -2260,9 +2336,15 @@ gdm_session_direct_select_language (GdmSession *session, - impl->priv->selected_language = g_strdup (text); - } - -- conversation = impl->priv->conversation; -- send_dbus_string_signal (conversation, "SetLanguageName", -- get_language_name (impl)); -+ g_hash_table_iter_init (&iter, impl->priv->conversations); -+ while (g_hash_table_iter_next (&iter, &key, &value)) { -+ GdmSessionConversation *conversation; -+ -+ conversation = (GdmSessionConversation *) value; -+ -+ send_dbus_string_signal (conversation, "SetLanguageName", -+ get_language_name (impl)); -+ } - } - - static void -@@ -2270,7 +2352,8 @@ gdm_session_direct_select_layout (GdmSession *session, - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -- GdmSessionConversation *conversation; -+ GHashTableIter iter; -+ gpointer key, value; - - g_free (impl->priv->selected_layout); - -@@ -2280,9 +2363,15 @@ gdm_session_direct_select_layout (GdmSession *session, - impl->priv->selected_layout = g_strdup (text); - } - -- conversation = impl->priv->conversation; -- send_dbus_string_signal (conversation, "SetLayoutName", -- get_layout_name (impl)); -+ g_hash_table_iter_init (&iter, impl->priv->conversations); -+ while (g_hash_table_iter_next (&iter, &key, &value)) { -+ GdmSessionConversation *conversation; -+ -+ conversation = (GdmSessionConversation *) value; -+ -+ send_dbus_string_signal (conversation, "SetLayoutName", -+ get_layout_name (impl)); -+ } - } - - 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); - 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 - - /* call and response stuff */ - void _gdm_session_info_query (GdmSession *session, -+ const char *service_name, - const char *text); - void _gdm_session_secret_info_query (GdmSession *session, -+ const char *service_name, - const char *text); - void _gdm_session_info (GdmSession *session, -+ const char *service_name, - const char *text); - void _gdm_session_problem (GdmSession *session, -+ const char *service_name, - const char *text); - - G_END_DECLS -diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c -index 35b4738..6e15f75 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, - } - - static void --gdm_session_relay_authenticate (GdmSession *session) -+gdm_session_relay_authenticate (GdmSession *session, -+ const char *service_name) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -- send_dbus_void_signal (impl, "Authenticate"); -+ send_dbus_string_signal (impl, "Authenticate", service_name); - } - - static void --gdm_session_relay_authorize (GdmSession *session) -+gdm_session_relay_authorize (GdmSession *session, -+ const char *service_name) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -- send_dbus_void_signal (impl, "Authorize"); -+ send_dbus_string_signal (impl, "Authorize", service_name); - } - - static void - gdm_session_relay_accredit (GdmSession *session, -+ const char *service_name, - int cred_flag) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); - - switch (cred_flag) { - case GDM_SESSION_CRED_ESTABLISH: -- send_dbus_void_signal (impl, "EstablishCredentials"); -+ send_dbus_string_signal (impl, "EstablishCredentials", service_name); - break; - case GDM_SESSION_CRED_REFRESH: -- send_dbus_void_signal (impl, "RefreshCredentials"); -+ send_dbus_string_signal (impl, "RefreshCredentials", service_name); - break; - default: - g_assert_not_reached (); -@@ -245,10 +248,11 @@ gdm_session_relay_accredit (GdmSession *session, - - static void - gdm_session_relay_answer_query (GdmSession *session, -+ const char *service_name, - const char *text) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -- send_dbus_string_signal (impl, "AnswerQuery", text); -+ send_dbus_string_string_signal (impl, "AnswerQuery", service_name, text); - } - - static void -@@ -292,11 +296,12 @@ gdm_session_relay_cancel (GdmSession *session) - } - - 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 -@@ -334,10 +339,12 @@ handle_info_query (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -- const char *text; -+ char *service_name; -+ char *text; - - 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); -@@ -349,7 +356,7 @@ handle_info_query (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_info_query (GDM_SESSION (session_relay), text); -+ _gdm_session_info_query (GDM_SESSION (session_relay), service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -361,12 +368,14 @@ handle_secret_info_query (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -- const char *text; -+ char *service_name; -+ char *text; - - text = 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); -@@ -378,7 +387,7 @@ handle_secret_info_query (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_secret_info_query (GDM_SESSION (session_relay), text); -+ _gdm_session_secret_info_query (GDM_SESSION (session_relay), service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -390,12 +399,14 @@ handle_info (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -- const char *text; -+ char *service_name; -+ char *text; - - text = 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); -@@ -407,7 +418,7 @@ handle_info (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_info (GDM_SESSION (session_relay), text); -+ _gdm_session_info (GDM_SESSION (session_relay), service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -419,12 +430,14 @@ handle_problem (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -- const char *text; -+ char *service_name; -+ char *text; - - text = 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); -@@ -436,7 +449,7 @@ handle_problem (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_problem (GDM_SESSION (session_relay), text); -+ _gdm_session_problem (GDM_SESSION (session_relay), service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -448,8 +461,15 @@ handle_setup_complete (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: SetupComplete"); - -@@ -457,7 +477,7 @@ handle_setup_complete (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_setup_complete (GDM_SESSION (session_relay)); -+ _gdm_session_setup_complete (GDM_SESSION (session_relay), service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -469,8 +489,15 @@ handle_setup_failed (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: SetupFailed"); - -@@ -478,7 +505,7 @@ handle_setup_failed (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_setup_failed (GDM_SESSION (session_relay), NULL); -+ _gdm_session_setup_failed (GDM_SESSION (session_relay), service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -491,8 +518,15 @@ handle_authenticated (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: Authenticated"); - -@@ -500,7 +534,7 @@ handle_authenticated (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authenticated (GDM_SESSION (session_relay)); -+ _gdm_session_authenticated (GDM_SESSION (session_relay), service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -512,8 +546,15 @@ handle_authentication_failed (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: AuthenticationFailed"); - -@@ -521,7 +562,7 @@ handle_authentication_failed (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authentication_failed (GDM_SESSION (session_relay), NULL); -+ _gdm_session_authentication_failed (GDM_SESSION (session_relay), service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -533,8 +574,15 @@ handle_authorized (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: Authorized"); - -@@ -542,7 +590,7 @@ handle_authorized (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authorized (GDM_SESSION (session_relay)); -+ _gdm_session_authorized (GDM_SESSION (session_relay), service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -554,8 +602,15 @@ handle_authorization_failed (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: AuthorizationFailed"); - -@@ -563,7 +618,7 @@ handle_authorization_failed (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authorization_failed (GDM_SESSION (session_relay), NULL); -+ _gdm_session_authorization_failed (GDM_SESSION (session_relay), service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -575,8 +630,15 @@ handle_accredited (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: Accredited"); - -@@ -584,7 +646,7 @@ handle_accredited (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_accredited (GDM_SESSION (session_relay)); -+ _gdm_session_accredited (GDM_SESSION (session_relay), service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -596,8 +658,15 @@ handle_accreditation_failed (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: AccreditationFailed"); - -@@ -605,7 +674,7 @@ handle_accreditation_failed (GdmSessionRelay *session_relay, - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_accreditation_failed (GDM_SESSION (session_relay), NULL); -+ _gdm_session_accreditation_failed (GDM_SESSION (session_relay), service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -617,6 +686,7 @@ handle_session_started (GdmSessionRelay *session_relay, - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - int pid; - - dbus_error_init (&error); -@@ -624,6 +694,7 @@ handle_session_started (GdmSessionRelay *session_relay, - pid = 0; - if (! dbus_message_get_args (message, - &error, -+ DBUS_TYPE_STRING, &service_name, - DBUS_TYPE_INT32, &pid, - DBUS_TYPE_INVALID)) { - g_warning ("ERROR: %s", error.message); -@@ -636,6 +707,7 @@ handle_session_started (GdmSessionRelay *session_relay, - dbus_message_unref (reply); - - _gdm_session_session_started (GDM_SESSION (session_relay), -+ service_name, - pid); - - return DBUS_HANDLER_RESULT_HANDLED; -diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c -index c1331df..ccfb3ec 100644 ---- a/daemon/gdm-session-worker.c -+++ b/daemon/gdm-session-worker.c -@@ -2606,6 +2606,28 @@ worker_dbus_filter_function (DBusConnection *connection, - return DBUS_HANDLER_RESULT_HANDLED; - } - -+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, -@@ -2632,6 +2654,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); - -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 - -+#include "gdm-marshal.h" - #include "gdm-session.h" - #include "gdm-session-private.h" - -@@ -114,37 +115,41 @@ gdm_session_setup_for_user (GdmSession *session, - } - - void --gdm_session_authenticate (GdmSession *session) -+gdm_session_authenticate (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); - -- GDM_SESSION_GET_IFACE (session)->authenticate (session); -+ GDM_SESSION_GET_IFACE (session)->authenticate (session, service_name); - } - - 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_GET_IFACE (session)->authorize (session); -+ GDM_SESSION_GET_IFACE (session)->authorize (session, service_name); - } - - void - gdm_session_accredit (GdmSession *session, -+ const char *service_name, - int flag) - { - 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); - } - - void - gdm_session_answer_query (GdmSession *session, -+ const char *service_name, - const char *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); - } - - void -@@ -192,11 +197,12 @@ gdm_session_cancel (GdmSession *session) - } - - 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)); - -- GDM_SESSION_GET_IFACE (session)->start_session (session); -+ GDM_SESSION_GET_IFACE (session)->start_session (session, service_name); - } - - static void -@@ -213,7 +219,7 @@ gdm_session_class_init (gpointer g_iface) - NULL, - g_cclosure_marshal_VOID__STRING, - 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, -- 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, -@@ -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 [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 --_gdm_session_setup_complete (GdmSession *session) -+_gdm_session_setup_complete (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); - -- g_signal_emit (session, signals [SETUP_COMPLETE], 0); -+ g_signal_emit (session, signals [SETUP_COMPLETE], 0, service_name); - } - - void - _gdm_session_setup_failed (GdmSession *session, -+ const char *service_name, - const char *text) - { - g_return_if_fail (GDM_IS_SESSION (session)); -- g_signal_emit (session, signals [SETUP_FAILED], 0, text); -+ g_signal_emit (session, signals [SETUP_FAILED], 0, service_name, text); - } - - void -@@ -497,99 +506,111 @@ _gdm_session_reset_failed (GdmSession *session, - } - - void --_gdm_session_authenticated (GdmSession *session) -+_gdm_session_authenticated (GdmSession *session, -+ const char *service_name) - { - 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 4db7440..9421a64 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -71,6 +71,8 @@ struct GdmSimpleSlavePrivate - guint greeter_reset_id; - guint start_session_id; - -+ char *start_session_service_name; -+ - int ping_interval; - - GPid server_pid; -@@ -101,6 +103,7 @@ static void start_greeter (GdmSimpleSlave *slave); - - static void - on_session_started (GdmSession *session, -+ const char *service_name, - int pid, - GdmSimpleSlave *slave) - { -@@ -204,19 +207,22 @@ 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); - } - - static void - on_session_setup_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmSimpleSlave *slave) - { - if (slave->priv->greeter_server != NULL) { - gdm_greeter_server_problem (slave->priv->greeter_server, -- message != NULL ? message: _("Unable to initialize login system")); -+ service_name, -+ message != NULL ? message: _("Unable to initialize login system")); - } - - destroy_session (slave); -@@ -240,18 +246,21 @@ on_session_reset_failed (GdmSession *session, - - static void - on_session_authenticated (GdmSession *session, -+ const char *service_name, - GdmSimpleSlave *slave) - { -- gdm_session_authorize (session); -+ gdm_session_authorize (session, service_name); - } - - static void - on_session_authentication_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmSimpleSlave *slave) - { - if (slave->priv->greeter_server != NULL) { - gdm_greeter_server_problem (slave->priv->greeter_server, -+ service_name, - message != NULL ? message : _("Unable to authenticate user")); - } - destroy_session (slave); -@@ -259,7 +268,8 @@ on_session_authentication_failed (GdmSession *session, - } - - static void --gdm_simple_slave_accredit_when_ready (GdmSimpleSlave *slave) -+gdm_simple_slave_accredit_when_ready (GdmSimpleSlave *slave, -+ const char *service_name) - { - if (slave->priv->start_session_when_ready) { - char *ssid; -@@ -280,7 +290,7 @@ gdm_simple_slave_accredit_when_ready (GdmSimpleSlave *slave) - g_free (ssid); - g_free (username); - -- gdm_session_accredit (GDM_SESSION (slave->priv->session), cred_flag); -+ gdm_session_accredit (GDM_SESSION (slave->priv->session), service_name, cred_flag); - } else { - slave->priv->waiting_to_start_session = TRUE; - } -@@ -288,25 +298,28 @@ gdm_simple_slave_accredit_when_ready (GdmSimpleSlave *slave) - - static void - on_session_authorized (GdmSession *session, -+ const char *service_name, - GdmSimpleSlave *slave) - { - if (slave->priv->greeter_server != NULL) { -- gdm_greeter_server_user_authorized (slave->priv->greeter_server); -- gdm_simple_slave_accredit_when_ready (slave); -+ gdm_greeter_server_user_authorized (slave->priv->greeter_server, service_name); -+ gdm_simple_slave_accredit_when_ready (slave, service_name); - } else { - slave->priv->start_session_when_ready = TRUE; -- gdm_simple_slave_accredit_when_ready (slave); -+ gdm_simple_slave_accredit_when_ready (slave, service_name); - } - } - - static void - on_session_authorization_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmSimpleSlave *slave) - { - if (slave->priv->greeter_server != NULL) { - gdm_greeter_server_problem (slave->priv->greeter_server, -- message != NULL ? message : _("Unable to authorize user")); -+ service_name, -+ message != NULL ? message : _("Unable to authorize user")); - } - - destroy_session (slave); -@@ -386,31 +399,38 @@ start_session_timeout (GdmSimpleSlave *slave) - - g_free (auth_file); - -- gdm_session_start_session (GDM_SESSION (slave->priv->session)); -+ gdm_session_start_session (GDM_SESSION (slave->priv->session), -+ slave->priv->start_session_service_name); - out: - slave->priv->start_session_id = 0; -+ g_free (slave->priv->start_session_service_name); -+ slave->priv->start_session_service_name = NULL; - return FALSE; - } - - static void --queue_start_session (GdmSimpleSlave *slave) -+queue_start_session (GdmSimpleSlave *slave, -+ const char *service_name) - { - if (slave->priv->start_session_id > 0) { - return; - } - - slave->priv->start_session_id = g_idle_add ((GSourceFunc)start_session_timeout, slave); -+ slave->priv->start_session_service_name = g_strdup (service_name); - } - - static void - on_session_accredited (GdmSession *session, -+ const char *service_name, - GdmSimpleSlave *slave) - { -- queue_start_session (slave); -+ queue_start_session (slave, service_name); - } - - static void - on_session_accreditation_failed (GdmSession *session, -+ const char *service_name, - const char *message, - GdmSimpleSlave *slave) - { -@@ -431,6 +451,7 @@ on_session_accreditation_failed (GdmSession *session, - problem = _("Unable to establish credentials"); - } - gdm_greeter_server_problem (slave->priv->greeter_server, -+ service_name, - problem); - } - } -@@ -446,41 +467,45 @@ on_session_accreditation_failed (GdmSession *session, - - static void - on_session_info (GdmSession *session, -+ const char *service_name, - const char *text, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: Info: %s", text); - if (slave->priv->greeter_server != NULL) { -- gdm_greeter_server_info (slave->priv->greeter_server, 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, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: 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, - GdmSimpleSlave *slave) - { - - g_debug ("GdmSimpleSlave: 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, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: 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 -@@ -750,11 +775,12 @@ on_greeter_start_conversation (GdmGreeterServer *greeter_server, - - static void - on_greeter_begin_verification (GdmGreeterServer *greeter_server, -+ const char *service_name, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: begin verification"); - gdm_session_setup (GDM_SESSION (slave->priv->session), -- "gdm"); -+ service_name); - } - - static void -@@ -770,21 +796,23 @@ on_greeter_begin_auto_login (GdmGreeterServer *greeter_server, - - static void - on_greeter_begin_verification_for_user (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *username, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: begin verification"); - gdm_session_setup_for_user (GDM_SESSION (slave->priv->session), -- "gdm", -+ service_name, - username); - } - - static void - on_greeter_answer (GdmGreeterServer *greeter_server, -+ const char *service_name, - const char *text, - GdmSimpleSlave *slave) - { -- gdm_session_answer_query (GDM_SESSION (slave->priv->session), text); -+ gdm_session_answer_query (GDM_SESSION (slave->priv->session), service_name, text); - } - - static void -@@ -847,18 +875,20 @@ on_greeter_connected (GdmGreeterServer *greeter_server, - - static void - on_start_session_when_ready (GdmGreeterServer *session, -+ const char *service_name, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: Will start session when ready"); - slave->priv->start_session_when_ready = TRUE; - - if (slave->priv->waiting_to_start_session) { -- gdm_simple_slave_accredit_when_ready (slave); -+ gdm_simple_slave_accredit_when_ready (slave, service_name); - } - } - - static void - on_start_session_later (GdmGreeterServer *session, -+ const char *service_name, - GdmSimpleSlave *slave) - { - g_debug ("GdmSimpleSlave: Will start session when ready and told"); -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, - - static void - on_session_setup_complete (GdmSession *session, -+ const char *service_name, - gpointer data) - { - g_debug ("Session setup complete"); -- gdm_session_authenticate (session); -+ gdm_session_authenticate (session, service_name); - } - - static void -@@ -79,10 +80,11 @@ on_session_reset_failed (GdmSession *session, - - static void - on_session_authenticated (GdmSession *session, -+ const char *service_name, - gpointer data) - { - g_debug ("Session authenticated"); -- gdm_session_authorize (session); -+ gdm_session_authorize (session, service_name); - } - - static void -@@ -97,14 +99,16 @@ on_session_authentication_failed (GdmSession *session, - - static void - on_session_authorized (GdmSession *session, -+ const char *service_name, - gpointer data) - { - g_debug ("Session authorized"); -- gdm_session_accredit (session, GDM_SESSION_CRED_ESTABLISH); -+ gdm_session_accredit (session, service_name, GDM_SESSION_CRED_ESTABLISH); - } - - static void - on_session_authorization_failed (GdmSession *session, -+ const char *service_name, - const char *message, - gpointer data) - { -@@ -115,6 +119,7 @@ on_session_authorization_failed (GdmSession *session, - - static void - on_session_accredited (GdmSession *session, -+ const char *service_name, - gpointer data) - { - char *username; -@@ -125,12 +130,13 @@ on_session_accredited (GdmSession *session, - username ? username : "", username ? " " : ""); - g_free (username); - -- gdm_session_start_session (session); -+ gdm_session_start_session (session, service_name); - - } - - static void - on_session_accreditation_failed (GdmSession *session, -+ const char *service_name, - const char *message, - gpointer data) - { -@@ -165,6 +171,7 @@ on_session_died (GdmSession *session, - - static void - on_info_query (GdmSession *session, -+ const char *service_name, - const char *query_text) - { - char answer[1024]; -@@ -178,12 +185,13 @@ on_info_query (GdmSession *session, - gdm_session_close (session); - g_main_loop_quit (loop); - } else { -- gdm_session_answer_query (session, answer); -+ gdm_session_answer_query (session, service_name, answer); - } - } - - static void - on_info (GdmSession *session, -+ const char *service_name, - const char *info) - { - g_print ("\n** NOTE: %s\n", info); -@@ -191,6 +199,7 @@ on_info (GdmSession *session, - - static void - on_problem (GdmSession *session, -+ const char *service_name, - const char *problem) - { - g_print ("\n** WARNING: %s\n", problem); -@@ -198,6 +207,7 @@ on_problem (GdmSession *session, - - static void - on_secret_info_query (GdmSession *session, -+ const char *service_name, - const char *query_text) - { - char answer[1024]; -@@ -222,7 +232,7 @@ on_secret_info_query (GdmSession *session, - - g_print ("\n"); - -- gdm_session_answer_query (session, answer); -+ gdm_session_answer_query (session, service_name, answer); - } - - static void -diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c -index 1e2c55d..0bd27a9 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, - } - - 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 - on_user_authorized (GdmGreeterClient *client, - DBusMessage *message) - { -- g_signal_emit (client, -- gdm_greeter_client_signals[USER_AUTHORIZED], -- 0); -+ emit_string_signal_for_message (client, "UserAuthorized", message, USER_AUTHORIZED); - } - - static void - on_info_query (GdmGreeterClient *client, - DBusMessage *message) - { -- emit_string_signal_for_message (client, "InfoQuery", message, INFO_QUERY); -+ emit_string_and_string_signal_for_message (client, "InfoQuery", message, INFO_QUERY); - } - - static void - on_secret_info_query (GdmGreeterClient *client, - DBusMessage *message) - { -- emit_string_signal_for_message (client, "SecretInfoQuery", message, SECRET_INFO_QUERY); -+ emit_string_and_string_signal_for_message (client, "SecretInfoQuery", message, SECRET_INFO_QUERY); - } - - static void - on_info (GdmGreeterClient *client, - DBusMessage *message) - { -- emit_string_signal_for_message (client, "Info", message, INFO); -+ emit_string_and_string_signal_for_message (client, "Info", message, INFO); - } - - static void - on_problem (GdmGreeterClient *client, - DBusMessage *message) - { -- emit_string_signal_for_message (client, "Problem", message, PROBLEM); -+ emit_string_and_string_signal_for_message (client, "Problem", message, PROBLEM); - } - - static void -@@ -307,14 +336,22 @@ send_dbus_string_method (DBusConnection *connection, - } - - static gboolean --send_dbus_bool_method (DBusConnection *connection, -- const char *method, -- gboolean payload) -+send_dbus_string_and_bool_method (DBusConnection *connection, -+ const char *method, -+ const char *string_payload, -+ gboolean bool_payload) - { - DBusError error; - DBusMessage *message; - DBusMessage *reply; - DBusMessageIter iter; -+ const char *str; -+ -+ if (string_payload != NULL) { -+ str = string_payload; -+ } else { -+ str = ""; -+ } - - g_debug ("GdmGreeterClient: Calling %s", method); - message = dbus_message_new_method_call (NULL, -@@ -328,8 +365,77 @@ send_dbus_bool_method (DBusConnection *connection, - - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_append_basic (&iter, -+ DBUS_TYPE_STRING, -+ &str); -+ -+ dbus_message_iter_append_basic (&iter, - DBUS_TYPE_BOOLEAN, -- &payload); -+ &bool_payload); -+ -+ 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_and_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 ("GdmGreeterClient: Calling %s", method); -+ message = dbus_message_new_method_call (NULL, -+ GREETER_SERVER_DBUS_PATH, -+ GREETER_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, -@@ -412,37 +518,44 @@ gdm_greeter_client_call_begin_auto_login (GdmGreeterClient *client, - } - - void --gdm_greeter_client_call_begin_verification (GdmGreeterClient *client) -+gdm_greeter_client_call_begin_verification (GdmGreeterClient *client, -+ const char *service_name) - { -- send_dbus_void_method (client->priv->connection, -- "BeginVerification"); -+ send_dbus_string_method (client->priv->connection, -+ "BeginVerification", service_name); - } - - void - gdm_greeter_client_call_begin_verification_for_user (GdmGreeterClient *client, -+ const char *service_name, - const char *username) - { -- send_dbus_string_method (client->priv->connection, -- "BeginVerificationForUser", -- username); -+ send_dbus_string_and_string_method (client->priv->connection, -+ "BeginVerificationForUser", -+ service_name, -+ username); - } - - void - gdm_greeter_client_call_answer_query (GdmGreeterClient *client, -+ const char *service_name, - const char *text) - { -- send_dbus_string_method (client->priv->connection, -- "AnswerQuery", -- text); -+ send_dbus_string_and_string_method (client->priv->connection, -+ "AnswerQuery", -+ service_name, -+ text); - } - - void - gdm_greeter_client_call_start_session_when_ready (GdmGreeterClient *client, -+ const char *service_name, - gboolean should_start_session) - { -- send_dbus_bool_method (client->priv->connection, -- "StartSessionWhenReady", -- should_start_session); -+ send_dbus_string_and_bool_method (client->priv->connection, -+ "StartSessionWhenReady", -+ service_name, -+ should_start_session); - } - - void -@@ -835,10 +948,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) - G_STRUCT_OFFSET (GdmGreeterClientClass, 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); - - gdm_greeter_client_signals[SECRET_INFO_QUERY] = - g_signal_new ("secret-info-query", -@@ -847,10 +960,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) - G_STRUCT_OFFSET (GdmGreeterClientClass, 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); - - gdm_greeter_client_signals[INFO] = - g_signal_new ("info", -@@ -859,10 +972,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) - G_STRUCT_OFFSET (GdmGreeterClientClass, 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); - - gdm_greeter_client_signals[PROBLEM] = - g_signal_new ("problem", -@@ -871,10 +984,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) - G_STRUCT_OFFSET (GdmGreeterClientClass, 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); - - gdm_greeter_client_signals[READY] = - g_signal_new ("ready", -@@ -956,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 -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 - GObjectClass parent_class; - - void (* info_query) (GdmGreeterClient *client, -+ const char *service_name, - const char *query_text); - - void (* secret_info_query) (GdmGreeterClient *client, -+ const char *service_name, - const char *query_text); - - void (* info) (GdmGreeterClient *client, -+ const char *service_name, - const char *info); - - void (* problem) (GdmGreeterClient *client, -+ const char *service_name, - const char *problem); -- void (* ready) (GdmGreeterClient *client); -+ void (* ready) (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 - void (* timed_login_requested) (GdmGreeterClient *client, - const char *username, - int delay); -- void (* user_authorized) (GdmGreeterClient *client); -+ void (* user_authorized) (GdmGreeterClient *client, -+ const char *service_name); - } 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); - void gdm_greeter_client_call_begin_auto_login (GdmGreeterClient *client, - const char *username); --void gdm_greeter_client_call_begin_verification (GdmGreeterClient *client); -+void gdm_greeter_client_call_begin_verification (GdmGreeterClient *client, -+ const char *service_name); - void gdm_greeter_client_call_begin_verification_for_user (GdmGreeterClient *client, -+ const char *service_name, - 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 - void gdm_greeter_client_call_select_session (GdmGreeterClient *client, - const char *text); - void gdm_greeter_client_call_answer_query (GdmGreeterClient *client, -+ const char *service_name, - const char *text); - - void gdm_greeter_client_call_start_session_when_ready (GdmGreeterClient *client, -+ const char *service_name, - gboolean should_start_session); - - -diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c -index ec99c12..7873679 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -65,6 +65,7 @@ static gpointer session_object = NULL; - - static void - on_info (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { -@@ -75,6 +76,7 @@ on_info (GdmGreeterClient *client, - - static void - on_problem (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { -@@ -173,6 +175,7 @@ on_user_authorized (GdmGreeterClient *client, - - static void - on_info_query (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { -@@ -183,6 +186,7 @@ on_info_query (GdmGreeterClient *client, - - static void - on_secret_info_query (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { -@@ -204,7 +208,8 @@ static void - on_begin_verification (GdmGreeterLoginWindow *login_window, - GdmGreeterSession *session) - { -- gdm_greeter_client_call_begin_verification (session->priv->client); -+ gdm_greeter_client_call_begin_verification (session->priv->client, -+ "gdm"); - } - - static void -@@ -213,6 +218,7 @@ on_begin_verification_for_user (GdmGreeterLoginWindow *login_window, - GdmGreeterSession *session) - { - gdm_greeter_client_call_begin_verification_for_user (session->priv->client, -+ "gdm", - username); - } - -@@ -222,6 +228,7 @@ on_query_answer (GdmGreeterLoginWindow *login_window, - GdmGreeterSession *session) - { - gdm_greeter_client_call_answer_query (session->priv->client, -+ "gdm", - text); - } - -@@ -279,7 +286,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 int --- -1.6.3.3 - - -From 2d43cb675898b5c2c2d124050ccdb4b43502f036 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sat, 7 Feb 2009 11:36:40 -0500 -Subject: [PATCH 11/38] 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 | 14 ++++++++++++++ - 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, 114 insertions(+), 8 deletions(-) - -diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c -index dae34c5..ecb2ad6 100644 ---- a/daemon/gdm-greeter-server.c -+++ b/daemon/gdm-greeter-server.c -@@ -299,6 +299,14 @@ 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); -+ return TRUE; -+} -+ - void - gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server, - const char *username) -@@ -797,6 +805,9 @@ do_introspect (DBusConnection *connection, - " \n" - " \n" - " \n" -+ " \n" -+ " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -868,6 +879,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 dbd85a7..d648390 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -1704,11 +1704,17 @@ worker_exited (GdmSessionWorkerJob *job, - { - g_debug ("GdmSessionDirect: Worker job exited: %d", code); - -+ g_object_ref (conversation); - if (!conversation->session->priv->is_authenticated) { - _gdm_session_authentication_failed (GDM_SESSION (conversation->session), NULL); - } 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 -@@ -1718,11 +1724,17 @@ worker_died (GdmSessionWorkerJob *job, - { - g_debug ("GdmSessionDirect: Worker job died: %d", signum); - -+ g_object_ref (conversation); - if (!conversation->session->priv->is_authenticated) { - _gdm_session_authentication_failed (GDM_SESSION (conversation->session), NULL); - } else if (conversation->session->priv->is_running) { - _gdm_session_session_died (GDM_SESSION (conversation->session), signum); - } -+ -+ g_debug ("GdmSessionDirect: Emitting conversation-stopped signal"); -+ _gdm_session_conversation_stopped (GDM_SESSION (conversation->session), -+ conversation->service_name); -+ g_object_unref (conversation); - } - - static GdmSessionConversation * -@@ -1795,6 +1807,10 @@ stop_conversation (GdmSessionConversation *conversation) - - 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 -@@ -1815,6 +1831,25 @@ gdm_session_direct_start_conversation (GdmSession *session, - } - - 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 - send_setup (GdmSessionDirect *session, - const char *service_name) - { -@@ -2631,6 +2666,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) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ -+ GDM_SESSION_GET_IFACE (session)->stop_conversation (session, service_name); -+} -+ -+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) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ g_signal_emit (session, signals [CONVERSATION_STOPPED], 0, service_name); -+} -+ -+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 9421a64..6eadf62 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -225,8 +225,7 @@ on_session_setup_failed (GdmSession *session, - message != NULL ? message: _("Unable to initialize login system")); - } - -- destroy_session (slave); -- queue_greeter_reset (slave); -+ gdm_session_stop_conversation (session, service_name); - } - - static void -@@ -263,8 +262,8 @@ on_session_authentication_failed (GdmSession *session, - service_name, - message != NULL ? message : _("Unable to authenticate user")); - } -- destroy_session (slave); -- queue_greeter_reset (slave); -+ -+ gdm_session_stop_conversation (session, service_name); - } - - static void -@@ -322,8 +321,7 @@ on_session_authorization_failed (GdmSession *session, - message != NULL ? message : _("Unable to authorize user")); - } - -- destroy_session (slave); -- queue_greeter_reset (slave); -+ gdm_session_stop_conversation (session, service_name); - } - - static gboolean -@@ -460,9 +458,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 -@@ -548,6 +545,23 @@ on_session_conversation_started (GdmSession *session, - } - - 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) -@@ -636,6 +650,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.3.3 - - -From a6469d77a955e7ca174d2c763a3b261831618612 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 9 Mar 2009 15:41:12 -0400 -Subject: [PATCH 12/38] Don't tear down greeter until pam_open_session finishes - -Some PAM modules ask questions at that late stage of the game, -and so we need a greeter to forward the questions on to the -user. ---- - daemon/gdm-factory-slave.c | 37 ++++++++++++++++++++-- - daemon/gdm-product-slave.c | 30 +++++++++++++++++- - daemon/gdm-session-direct.c | 70 ++++++++++++++++++++++++++++++++++++++++++ - daemon/gdm-session-private.h | 5 +++ - daemon/gdm-session-relay.c | 68 ++++++++++++++++++++++++++++++++++++++++ - daemon/gdm-session-worker.c | 14 +++++++- - daemon/gdm-session.c | 50 ++++++++++++++++++++++++++++++ - daemon/gdm-session.h | 9 +++++ - daemon/gdm-simple-slave.c | 33 +++++++++++++++++++- - 9 files changed, 309 insertions(+), 7 deletions(-) - -diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c -index 826612e..ef6d236 100644 ---- a/daemon/gdm-factory-slave.c -+++ b/daemon/gdm-factory-slave.c -@@ -278,9 +278,7 @@ on_session_accredited (GdmSession *session, - { - g_debug ("GdmFactorySlave: session user verified"); - -- gdm_session_start_session (session, service_name); -- -- gdm_greeter_server_reset (slave->priv->greeter_server); -+ gdm_session_open_session (session, service_name); - } - - static void -@@ -298,6 +296,31 @@ on_session_accreditation_failed (GdmSession *session, - } - - static void -+on_session_opened (GdmSession *session, -+ const char *service_name, -+ GdmFactorySlave *slave) -+{ -+ g_debug ("GdmFactorySlave: session opened"); -+ -+ gdm_session_start_session (session, service_name); -+ -+ gdm_greeter_server_reset (slave->priv->greeter_server); -+} -+ -+static void -+on_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *message, -+ GdmFactorySlave *slave) -+{ -+ g_debug ("GdmFactorySlave: could not open session: %s", message); -+ -+ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to open session")); -+ -+ queue_greeter_reset (slave); -+} -+ -+static void - on_session_session_started (GdmSession *session, - GdmFactorySlave *slave) - { -@@ -767,6 +790,14 @@ gdm_factory_slave_start (GdmSlave *slave) - G_CALLBACK (on_session_accreditation_failed), - slave); - g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, -+ "session-opened", -+ G_CALLBACK (on_session_opened), -+ slave); -+ g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, -+ "session-open-failed", -+ G_CALLBACK (on_session_open_failed), -+ slave); -+ g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, - "info", - G_CALLBACK (on_session_info), - slave); -diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c -index dd2e1bc..93d83a1 100644 ---- a/daemon/gdm-product-slave.c -+++ b/daemon/gdm-product-slave.c -@@ -635,6 +635,27 @@ on_session_accreditation_failed (GdmSession *session, - } - - static void -+on_session_opened (GdmSession *session, -+ const char *service_name, -+ GdmProductSlave *slave) -+{ -+ send_dbus_string_method (slave->priv->session_relay_connection, -+ "SessionOpened", service_name); -+} -+ -+static void -+on_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *message, -+ GdmProductSlave *slave) -+{ -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "SessionOpenFailed", -+ service_name, -+ message); -+} -+ -+static void - on_session_info (GdmSession *session, - const char *service_name, - const char *text, -@@ -1051,7 +1072,14 @@ create_new_session (GdmProductSlave *slave) - "accreditation-failed", - G_CALLBACK (on_session_accreditation_failed), - slave); -- -+ g_signal_connect (slave->priv->session, -+ "session-opened", -+ G_CALLBACK (on_session_opened), -+ slave); -+ g_signal_connect (slave->priv->session, -+ "session-open-failed", -+ G_CALLBACK (on_session_open_failed), -+ slave); - g_signal_connect (slave->priv->session, - "info", - G_CALLBACK (on_session_info), -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index d648390..c189f98 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -947,6 +947,58 @@ gdm_session_direct_handle_problem (GdmSessionDirect *session, - } - - static DBusHandlerResult -+gdm_session_direct_handle_session_opened (GdmSessionDirect *session, -+ GdmSessionConversation *conversation, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ -+ g_debug ("GdmSessionDirect: Handling SessionOpened"); -+ -+ dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ -+ g_debug ("GdmSessionDirect: Emitting 'session-opened' signal"); -+ -+ _gdm_session_session_opened (GDM_SESSION (session), conversation->service_name); -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+static DBusHandlerResult -+gdm_session_direct_handle_open_failed (GdmSessionDirect *session, -+ GdmSessionConversation *conversation, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ const char *text; -+ -+ dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &text, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ g_debug ("GdmSessionDirect: Emitting 'session-open-failed' signal"); -+ _gdm_session_session_open_failed (GDM_SESSION (session), conversation->service_name, text); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+static DBusHandlerResult - gdm_session_direct_handle_session_started (GdmSessionDirect *session, - GdmSessionConversation *conversation, - DBusMessage *message) -@@ -1213,6 +1265,10 @@ session_worker_message (DBusConnection *connection, - return gdm_session_direct_handle_accreditation_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) { - return gdm_session_direct_handle_username_changed (session, conversation, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionOpened")) { -+ return gdm_session_direct_handle_session_opened (session, conversation, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "OpenFailed")) { -+ return gdm_session_direct_handle_open_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) { - return gdm_session_direct_handle_session_started (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartFailed")) { -@@ -2200,6 +2256,19 @@ setup_session_environment (GdmSessionDirect *session) - } - - static void -+gdm_session_direct_open_session (GdmSession *session, -+ const char *service_name) -+{ -+ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; -+ -+ g_return_if_fail (session != NULL); -+ -+ conversation = find_conversation_by_name (impl, service_name); -+ send_dbus_void_signal (conversation, "OpenSession"); -+} -+ -+static void - gdm_session_direct_start_session (GdmSession *session, - const char *service_name) - { -@@ -2672,6 +2741,7 @@ gdm_session_iface_init (GdmSessionIface *iface) - iface->authenticate = gdm_session_direct_authenticate; - iface->authorize = gdm_session_direct_authorize; - iface->accredit = gdm_session_direct_accredit; -+ iface->open_session = gdm_session_direct_open_session; - iface->close = gdm_session_direct_close; - - iface->cancel = gdm_session_direct_cancel; -diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h -index 860c09c..36781dd 100644 ---- a/daemon/gdm-session-private.h -+++ b/daemon/gdm-session-private.h -@@ -54,6 +54,11 @@ void _gdm_session_accredited (GdmSession *sessio - void _gdm_session_accreditation_failed (GdmSession *session, - const char *service_name, - const char *text); -+void _gdm_session_session_opened (GdmSession *session, -+ const char *service_name); -+void _gdm_session_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *message); - void _gdm_session_session_started (GdmSession *session, - const char *service_name, - int pid); -diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c -index 6e15f75..3bf8ed7 100644 ---- a/daemon/gdm-session-relay.c -+++ b/daemon/gdm-session-relay.c -@@ -247,6 +247,14 @@ gdm_session_relay_accredit (GdmSession *session, - } - - static void -+gdm_session_relay_open_session (GdmSession *session, -+ const char *service_name) -+{ -+ GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -+ send_dbus_string_signal (impl, "OpenSession", service_name); -+} -+ -+static void - gdm_session_relay_answer_query (GdmSession *session, - const char *service_name, - const char *text) -@@ -678,6 +686,61 @@ handle_accreditation_failed (GdmSessionRelay *session_relay, - - return DBUS_HANDLER_RESULT_HANDLED; - } -+static DBusHandlerResult -+handle_session_opened (GdmSessionRelay *session_relay, -+ DBusConnection *connection, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ char *service_name; -+ -+ dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); -+ -+ g_debug ("GdmSessionRelay: Session Opened"); -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ _gdm_session_session_opened (GDM_SESSION (session_relay), service_name); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+static DBusHandlerResult -+handle_session_open_failed (GdmSessionRelay *session_relay, -+ DBusConnection *connection, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ char *service_name; -+ -+ dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); -+ -+ g_debug ("GdmSessionRelay: Session Open Failed"); -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ _gdm_session_session_open_failed (GDM_SESSION (session_relay), service_name, NULL); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} - - static DBusHandlerResult - handle_session_started (GdmSessionRelay *session_relay, -@@ -794,6 +857,10 @@ session_handle_child_message (DBusConnection *connection, - return handle_accredited (session_relay, connection, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "AccreditationFailed")) { - return handle_accreditation_failed (session_relay, connection, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionOpened")) { -+ return handle_session_opened (session_relay, connection, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionOpenFailed")) { -+ return handle_session_open_failed (session_relay, connection, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStarted")) { - return handle_session_started (session_relay, connection, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStopped")) { -@@ -1193,6 +1260,7 @@ gdm_session_iface_init (GdmSessionIface *iface) - iface->authenticate = gdm_session_relay_authenticate; - iface->authorize = gdm_session_relay_authorize; - iface->accredit = gdm_session_relay_accredit; -+ iface->open_session = gdm_session_relay_open_session; - iface->close = gdm_session_relay_close; - - iface->cancel = gdm_session_relay_cancel; -diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c -index ccfb3ec..194de7d 100644 ---- a/daemon/gdm-session-worker.c -+++ b/daemon/gdm-session-worker.c -@@ -2197,13 +2197,13 @@ do_open_session (GdmSessionWorker *worker) - res = gdm_session_worker_open_user_session (worker, &error); - if (! res) { - send_dbus_string_method (worker->priv->connection, -- "StartFailed", -+ "OpenFailed", - error->message); - g_error_free (error); - return; - } - -- queue_state_change (worker); -+ send_dbus_void_method (worker->priv->connection, "SessionOpened"); - } - - static void -@@ -2478,6 +2478,14 @@ on_establish_credentials (GdmSessionWorker *worker, - } - - static void -+on_open_session (GdmSessionWorker *worker, -+ DBusMessage *message) -+{ -+ /* FIXME: return error if not in ACCREDITED state */ -+ queue_state_change (worker); -+} -+ -+static void - on_reauthenticate (GdmSessionWorker *worker, - DBusMessage *message) - { -@@ -2549,6 +2557,8 @@ worker_dbus_handle_message (DBusConnection *connection, - on_authorize (worker, message); - } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "EstablishCredentials")) { - on_establish_credentials (worker, message); -+ } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "OpenSession")) { -+ on_open_session (worker, message); - } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "StartProgram")) { - on_start_program (worker, message); - } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "Reauthenticate")) { -diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c -index 9ee34af..8858071 100644 ---- a/daemon/gdm-session.c -+++ b/daemon/gdm-session.c -@@ -46,6 +46,8 @@ enum { - PROBLEM, - INFO_QUERY, - SECRET_INFO_QUERY, -+ SESSION_OPENED, -+ SESSION_OPEN_FAILED, - SESSION_STARTED, - SESSION_START_FAILED, - SESSION_EXITED, -@@ -207,6 +209,15 @@ gdm_session_cancel (GdmSession *session) - } - - void -+gdm_session_open_session (GdmSession *session, -+ const char *service_name) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ -+ GDM_SESSION_GET_IFACE (session)->open_session (session, service_name); -+} -+ -+void - gdm_session_start_session (GdmSession *session, - const char *service_name) - { -@@ -391,6 +402,28 @@ gdm_session_class_init (gpointer g_iface) - G_TYPE_NONE, - 2, - G_TYPE_STRING, G_TYPE_STRING); -+ signals [SESSION_OPENED] = -+ g_signal_new ("session-opened", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmSessionIface, session_opened), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, -+ G_TYPE_STRING); -+ signals [SESSION_OPEN_FAILED] = -+ g_signal_new ("session-open-failed", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmSessionIface, session_open_failed), -+ NULL, -+ NULL, -+ gdm_marshal_VOID__STRING_STRING, -+ G_TYPE_NONE, -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); - signals [SESSION_STARTED] = - g_signal_new ("session-started", - iface_type, -@@ -616,6 +649,23 @@ _gdm_session_problem (GdmSession *session, - } - - void -+_gdm_session_session_opened (GdmSession *session, -+ const char *service_name) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ g_signal_emit (session, signals [SESSION_OPENED], 0, service_name); -+} -+ -+void -+_gdm_session_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *text) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ g_signal_emit (session, signals [SESSION_OPEN_FAILED], 0, service_name, text); -+} -+ -+void - _gdm_session_session_started (GdmSession *session, - const char *service_name, - int pid) -diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h -index c45a770..22c2ccb 100644 ---- a/daemon/gdm-session.h -+++ b/daemon/gdm-session.h -@@ -62,6 +62,8 @@ struct _GdmSessionIface - void (* accredit) (GdmSession *session, - const char *service_name, - int cred_flag); -+ void (* open_session) (GdmSession *session, -+ const char *service_name); - void (* answer_query) (GdmSession *session, - const char *service_name, - const char *text); -@@ -115,6 +117,11 @@ struct _GdmSessionIface - void (* problem) (GdmSession *session, - const char *service_name, - const char *problem); -+ void (* session_opened) (GdmSession *session, -+ const char *service_name); -+ void (* session_open_failed) (GdmSession *session, -+ const char *service_name, -+ const char *message); - void (* session_started) (GdmSession *session, - const char *service_name, - int pid); -@@ -160,6 +167,8 @@ void gdm_session_authorize (GdmSession *session, - void gdm_session_accredit (GdmSession *session, - const char *service_name, - int cred_flag); -+void gdm_session_open_session (GdmSession *session, -+ const char *service_name); - void gdm_session_start_session (GdmSession *session, - const char *service_name); - void gdm_session_close (GdmSession *session); -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index 6eadf62..4c68974 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -423,7 +423,7 @@ on_session_accredited (GdmSession *session, - const char *service_name, - GdmSimpleSlave *slave) - { -- queue_start_session (slave, service_name); -+ gdm_session_open_session (session, service_name); - } - - static void -@@ -463,6 +463,29 @@ on_session_accreditation_failed (GdmSession *session, - } - - static void -+on_session_opened (GdmSession *session, -+ const char *service_name, -+ GdmSimpleSlave *slave) -+{ -+ queue_start_session (slave, service_name); -+} -+ -+static void -+on_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *message, -+ GdmSimpleSlave *slave) -+{ -+ if (slave->priv->greeter_server != NULL) { -+ gdm_greeter_server_problem (slave->priv->greeter_server, -+ service_name, -+ _("Unable to open session")); -+ } -+ -+ gdm_session_stop_conversation (session, service_name); -+} -+ -+static void - on_session_info (GdmSession *session, - const char *service_name, - const char *text, -@@ -694,6 +717,14 @@ create_new_session (GdmSimpleSlave *slave) - G_CALLBACK (on_session_accreditation_failed), - slave); - g_signal_connect (slave->priv->session, -+ "session-opened", -+ G_CALLBACK (on_session_opened), -+ slave); -+ g_signal_connect (slave->priv->session, -+ "session-open-failed", -+ G_CALLBACK (on_session_open_failed), -+ slave); -+ g_signal_connect (slave->priv->session, - "info", - G_CALLBACK (on_session_info), - slave); --- -1.6.3.3 - - -From 7d088d42327ecdcacd646b3f1865fd7ea3128a0d Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 30 Jan 2009 23:57:31 -0500 -Subject: [PATCH 13/38] 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 | 91 +++++++++-- - 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 | 198 +++++++++++++++++++++ - gui/simple-greeter/gdm-task-list.h | 64 +++++++ - 7 files changed, 409 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 b36aa28..22536b4 100644 ---- a/gui/simple-greeter/Makefile.am -+++ b/gui/simple-greeter/Makefile.am -@@ -82,6 +82,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) - - test_greeter_login_window_LDADD = \ -@@ -312,6 +314,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) - - 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 c7ea5d6..6dad52f 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -56,12 +56,16 @@ - #include - #include - -+#include "gdm-marshal.h" -+ - #include "gdm-settings-client.h" - #include "gdm-settings-keys.h" - #include "gdm-profile.h" - -+#include "gdm-greeter-client.h" - #include "gdm-greeter-login-window.h" - #include "gdm-user-chooser-widget.h" -+#include "gdm-task-list.h" - - #ifdef HAVE_PAM - #include -@@ -109,6 +113,7 @@ struct GdmGreeterLoginWindowPrivate - { - GladeXML *xml; - GtkWidget *user_chooser; -+ GtkWidget *conversation_list; - GtkWidget *auth_banner_label; - guint display_is_local : 1; - guint is_interactive : 1; -@@ -138,6 +143,7 @@ enum { - }; - - enum { -+ START_CONVERSATION, - BEGIN_AUTO_LOGIN, - BEGIN_VERIFICATION, - BEGIN_VERIFICATION_FOR_USER, -@@ -398,7 +404,7 @@ on_login_button_clicked_answer_query (GtkButton *button, - 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); -+ g_signal_emit (login_window, signals[QUERY_ANSWER], 0, "gdm", text); - } - - static void -@@ -787,26 +793,32 @@ gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window) - - 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); - - 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 (GDM_TASK_LIST (login_window->priv->conversation_list))) == 0) { -+ set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); -+ } - - 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); - - 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 (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); - - return TRUE; -@@ -882,6 +894,7 @@ gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_ - - gboolean - gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text) - { - GtkWidget *entry; -@@ -889,6 +902,10 @@ 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 (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"); -@@ -911,6 +928,7 @@ gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, - - gboolean - gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - const char *text) - { - GtkWidget *entry; -@@ -1170,7 +1188,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) { -@@ -1184,7 +1205,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; -+ -+ 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); - } - - switch_mode (login_window, MODE_AUTHENTICATION); -@@ -1328,6 +1352,21 @@ create_computer_info (GdmGreeterLoginWindow *login_window) - #define INVISIBLE_CHAR_BULLET 0x2022 - #define INVISIBLE_CHAR_NONE 0 - -+static void -+on_task_activated (GdmGreeterLoginWindow *login_window, -+ const char *name) -+{ -+ g_debug ("GdmGreeterLoginWindow: starting conversation with '%s'", name); -+ g_signal_emit (login_window, signals[START_CONVERSATION], 0, name); -+} -+ -+static void -+on_task_deactivated (GdmGreeterLoginWindow *login_window, -+ const char *name) -+{ -+ g_debug ("GdmGreeterLoginWindow: conversation '%s' now in background", name); -+} -+ - static GtkWidget * - custom_widget_constructor (GladeXML *xml, - char *func_name, -@@ -1350,6 +1389,8 @@ custom_widget_constructor (GladeXML *xml, - - 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); -@@ -1428,6 +1469,25 @@ load_theme (GdmGreeterLoginWindow *login_window) - - gtk_widget_show (login_window->priv->user_chooser); - -+ login_window->priv->conversation_list = glade_xml_get_widget (login_window->priv->xml, -+ "conversation-list"); -+ g_signal_connect_swapped (GDM_TASK_LIST (login_window->priv->conversation_list), -+ "activated", -+ G_CALLBACK (on_task_activated), -+ login_window); -+ g_signal_connect_swapped (GDM_TASK_LIST (login_window->priv->conversation_list), -+ "deactivated", -+ G_CALLBACK (on_task_deactivated), -+ 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);*/ - -@@ -1609,6 +1669,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", -+ G_TYPE_FROM_CLASS (object_class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, start_conversation), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, 1, G_TYPE_STRING); - signals [BEGIN_AUTO_LOGIN] = - g_signal_new ("begin-auto-login", - G_TYPE_FROM_CLASS (object_class), -@@ -1625,9 +1694,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) - G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, begin_verification), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); - signals [BEGIN_VERIFICATION_FOR_USER] = - g_signal_new ("begin-verification-for-user", - G_TYPE_FROM_CLASS (object_class), -@@ -1635,9 +1704,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) - G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, 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_TYPE_FROM_CLASS (object_class), -@@ -1645,9 +1714,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) - G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, 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 [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 d972c82..26d81d5 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 -@@ -778,10 +805,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 7873679..18d5ef7 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -71,7 +71,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 -@@ -82,7 +82,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 -@@ -181,7 +181,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 -@@ -192,10 +192,18 @@ on_secret_info_query (GdmGreeterClient *client, - { - 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 -+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) -@@ -206,29 +214,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); - } - -@@ -379,7 +390,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..e0fd3d4 ---- /dev/null -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -0,0 +1,198 @@ -+/* -+ * 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 -+ -+#include "gdm-task-list.h" -+ -+#define GDM_TASK_LIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_TASK_LIST, GdmTaskListPrivate)) -+ -+typedef struct -+{ -+ GtkWidget *radio_button; -+ char *name; -+} GdmTask; -+ -+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 *radio_button) -+{ -+ GdmTask *task; -+ -+ task = g_object_get_data (G_OBJECT (radio_button), "gdm-task"); -+ -+ 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); -+ } -+} -+ -+void -+gdm_task_list_add_task (GdmTaskList *task_list, -+ const char *name, -+ const char *icon_name) -+{ -+ GdmTask *task; -+ GtkWidget *image; -+ -+ task = g_new0 (GdmTask, 1); -+ -+ 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)); -+ } -+ -+ 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 (task_list->priv->box), task->radio_button); -+ task_list->priv->tasks = g_list_append (task_list->priv->tasks, task); -+} -+ -+static void -+gdm_task_list_class_init (GdmTaskListClass *klass) -+{ -+ 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); -+ -+ 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); -+ -+ g_type_class_add_private (klass, sizeof (GdmTaskListPrivate)); -+} -+ -+static void -+gdm_task_list_init (GdmTaskList *widget) -+{ -+ 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); -+ -+ widget->priv->box = gtk_hbox_new (FALSE, 2); -+ gtk_widget_show (widget->priv->box); -+ gtk_container_add (GTK_CONTAINER (widget), -+ widget->priv->box); -+} -+ -+static void -+gdm_task_list_finalize (GObject *object) -+{ -+ GdmTaskList *widget; -+ -+ g_return_if_fail (object != NULL); -+ g_return_if_fail (GDM_IS_TASK_LIST (object)); -+ -+ widget = GDM_TASK_LIST (object); -+ -+ g_list_foreach (widget->priv->tasks, (GFunc) g_free, NULL); -+ g_list_free (widget->priv->tasks); -+ -+ G_OBJECT_CLASS (gdm_task_list_parent_class)->finalize (object); -+} -+ -+GtkWidget * -+gdm_task_list_new (void) -+{ -+ GObject *object; -+ -+ object = g_object_new (GDM_TYPE_TASK_LIST, NULL); -+ -+ return GTK_WIDGET (object); -+} -+ -+const char * -+gdm_task_list_get_active_task (GdmTaskList *widget) -+{ -+ GList *node; -+ -+ for (node = widget->priv->tasks; node != NULL; node = node->next) { -+ GdmTask *task; -+ -+ task = node->data; -+ -+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (task->radio_button)) ) { -+ return task->name; -+ } -+ } -+ -+ return NULL; -+} -diff --git a/gui/simple-greeter/gdm-task-list.h b/gui/simple-greeter/gdm-task-list.h -new file mode 100644 -index 0000000..ade21b6 ---- /dev/null -+++ b/gui/simple-greeter/gdm-task-list.h -@@ -0,0 +1,64 @@ -+/* -+ * 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 -+ -+#include -+#include -+ -+G_BEGIN_DECLS -+ -+#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)) -+ -+typedef struct GdmTaskListPrivate GdmTaskListPrivate; -+ -+typedef struct -+{ -+ GtkAlignment parent; -+ GdmTaskListPrivate *priv; -+} GdmTaskList; -+ -+typedef struct -+{ -+ GtkAlignmentClass parent_class; -+ -+ void (* deactivated) (GdmTaskList *widget, -+ const char *name); -+ void (* activated) (GdmTaskList *widget, -+ const char *name); -+} GdmTaskListClass; -+ -+ -+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 -+ -+#endif /* __GDM_TASK_LIST_H */ --- -1.6.3.3 - - -From 287eeb864410a8504023fb39ef2312abdcdc788e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Mar 2009 11:19:40 -0500 -Subject: [PATCH 14/38] Create session settings object when first starting worker - -This is because one PAM module may complete before setup -gets called on another, and when one completes *all* PAM -modules get told about language, session, and layouts -set by the user. ---- - daemon/gdm-session-worker.c | 3 +-- - 1 files changed, 1 insertions(+), 2 deletions(-) - -diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c -index 194de7d..1b1f14b 100644 ---- a/daemon/gdm-session-worker.c -+++ b/daemon/gdm-session-worker.c -@@ -2060,8 +2060,6 @@ do_setup (GdmSessionWorker *worker) - GError *error; - gboolean res; - -- worker->priv->user_settings = gdm_session_settings_new (); -- - g_signal_connect_swapped (worker->priv->user_settings, - "notify::language-name", - G_CALLBACK (on_saved_language_name_read), -@@ -2710,6 +2708,7 @@ gdm_session_worker_init (GdmSessionWorker *worker) - g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); -+ worker->priv->user_settings = gdm_session_settings_new (); - } - - static void --- -1.6.3.3 - - -From 5d580cde9e73d3e6cd41d37ca1983883dc5db4ed Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 5 Feb 2009 15:20:25 -0500 -Subject: [PATCH 15/38] 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 4c68974..337718b 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -818,6 +818,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); - } -@@ -828,6 +831,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); - } -@@ -838,6 +844,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); -@@ -850,6 +859,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); -@@ -861,6 +873,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); - } - -@@ -869,6 +884,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); - } - -@@ -877,6 +895,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); - } - -@@ -885,6 +906,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); - } - -@@ -901,7 +925,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 -@@ -911,6 +939,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, -@@ -928,6 +959,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) { -@@ -941,6 +975,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.3.3 - - -From 21ebc4975e94c73c3a49d61e9655070c09e50926 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 16:23:48 -0500 -Subject: [PATCH 16/38] 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 | 45 ++ - gui/simple-greeter/Makefile.am | 15 + - gui/simple-greeter/gdm-greeter-client.c | 21 + - gui/simple-greeter/gdm-greeter-client.h | 2 + - gui/simple-greeter/gdm-greeter-login-window.c | 674 ++++++++++++++++---- - gui/simple-greeter/gdm-greeter-login-window.glade | 144 +---- - gui/simple-greeter/gdm-greeter-login-window.h | 21 +- - gui/simple-greeter/gdm-greeter-plugin.c | 255 ++++++++ - gui/simple-greeter/gdm-greeter-plugin.h | 61 ++ - gui/simple-greeter/gdm-greeter-session.c | 91 +++- - gui/simple-greeter/gdm-plugin-manager.c | 478 ++++++++++++++ - gui/simple-greeter/gdm-plugin-manager.h | 66 ++ - gui/simple-greeter/gdm-task-list.c | 216 +++++-- - gui/simple-greeter/gdm-task-list.h | 36 +- - 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 | 53 ++ - .../plugins/password/gdm-password-extension.c | 316 +++++++++ - .../plugins/password/gdm-password-extension.h | 56 ++ - .../plugins/password/gdm-password.pam | 19 + - gui/simple-greeter/plugins/password/page.ui | 56 ++ - gui/simple-greeter/plugins/password/plugin.c | 40 ++ - 29 files changed, 2987 insertions(+), 297 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/gdm-password.pam - 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 e2e34ef..4278d7c 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) -@@ -174,6 +190,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 --------------------------------------------------------------------------- - -@@ -1204,6 +1229,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 --------------------------------------------------------------------------- - -@@ -1330,6 +1371,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/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am -index 22536b4..a247aad 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) \ -@@ -84,10 +88,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) \ -@@ -138,6 +147,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) \ -@@ -308,10 +318,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 \ -@@ -322,6 +336,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-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) -+{ -+ emit_string_signal_for_message (client, "ConversationStopped", message, CONVERSATION_STOPPED); -+} -+ -+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); -+ - 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 6dad52f..07cb4e3 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" -@@ -115,6 +118,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; - guint user_chooser_loaded : 1; -@@ -168,6 +172,8 @@ static void on_user_unchosen (GdmUserChooserWidget *user_chooser, - static void switch_mode (GdmGreeterLoginWindow *login_window, - int number); - static void update_banner_message (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) - -@@ -193,9 +199,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); - -@@ -205,27 +208,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 -@@ -391,30 +410,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; -+ -+ 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; -+ } -+ } - -- _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 - on_login_button_clicked_start_other (GtkButton *button, -@@ -433,6 +498,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); -@@ -445,6 +511,12 @@ 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_START_OTHER: -@@ -452,11 +524,18 @@ set_log_in_button_mode (GdmGreeterLoginWindow *login_window, - gtk_widget_show (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: -@@ -598,7 +677,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); -@@ -614,6 +693,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: -@@ -693,25 +773,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); -@@ -735,16 +830,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"); -- -- delete_entry_text (entry); -+ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ reset_task, -+ login_window); - -- 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); -@@ -768,11 +859,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)); -@@ -782,12 +884,63 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window) - } - - gboolean --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: 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); -+ -+ if (task != NULL) { -+ gdm_conversation_reset (GDM_CONVERSATION (task)); -+ 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; - } - -@@ -796,12 +949,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; -@@ -812,13 +973,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; -@@ -856,11 +1026,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 " -@@ -870,8 +1050,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 -@@ -897,26 +1077,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)); -@@ -931,20 +1109,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)); -@@ -955,13 +1136,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 -@@ -1171,6 +1355,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) -@@ -1188,10 +1412,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) { -@@ -1205,10 +1429,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); -@@ -1354,17 +1578,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 * -@@ -1401,7 +1673,6 @@ custom_widget_constructor (GladeXML *xml, - static void - load_theme (GdmGreeterLoginWindow *login_window) - { -- GtkWidget *entry; - GtkWidget *button; - GtkWidget *box; - GtkWidget *image; -@@ -1481,15 +1752,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); -@@ -1505,14 +1770,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"); -@@ -1754,9 +2011,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, -@@ -1809,6 +2066,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 26d81d5..aaa8170 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,56 +671,12 @@ - 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 -@@ -744,46 +685,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..c312a47 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,10 @@ 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_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); -@@ -88,7 +97,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..02814a2 ---- /dev/null -+++ b/gui/simple-greeter/gdm-greeter-plugin.c -@@ -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 -+ */ -+ -+#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_warning ("plugin %s couldn't be opened: %s", -+ plugin->priv->filename, -+ g_module_error ()); -+ 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 18d5ef7..2e1f021 100644 ---- a/gui/simple-greeter/gdm-greeter-session.c -+++ b/gui/simple-greeter/gdm-greeter-session.c -@@ -39,6 +39,8 @@ - #include "gdm-greeter-login-window.h" - #include "gdm-user-chooser-widget.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)) -@@ -46,9 +48,11 @@ - struct GdmGreeterSessionPrivate - { - GdmGreeterClient *client; -+ GdmPluginManager *plugin_manager; - - GtkWidget *login_window; - GtkWidget *panel; -+ - }; - - enum { -@@ -92,7 +96,19 @@ 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 -+on_conversation_stopped (GdmGreeterClient *client, -+ const char *service_name, -+ GdmGreeterSession *session) -+{ -+ g_debug ("GdmGreeterSession: Conversation '%s' stopped", service_name); -+ -+ gdm_greeter_login_window_conversation_stopped (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), -+ service_name); - } - - static void -@@ -167,10 +183,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 -@@ -283,7 +300,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 -@@ -295,9 +311,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 int -@@ -449,8 +466,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; -@@ -560,6 +575,64 @@ gdm_greeter_session_event_handler (GdkEvent *event, - } - - 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); -@@ -588,6 +661,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); -@@ -622,6 +699,8 @@ gdm_greeter_session_init (GdmGreeterSession *session) - gdk_event_handler_set ((GdkEventFunc) gdm_greeter_session_event_handler, - session, NULL); - -+ -+ 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); -+} -+ -+static void -+gdm_plugin_manager_cancel_pending_operations (GdmPluginManager *manager) -+{ -+ 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; -+ } -+} -+ -+static void -+gdm_plugin_manager_class_init (GdmPluginManagerClass *klass) -+{ -+ 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)); -+} -+ -+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); -+} -+ -+static void -+on_plugin_load_failed (GdmPluginManager *manager, -+ GdmGreeterPlugin *plugin) -+{ -+ 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); -+} -+ -+static void -+on_plugin_unloaded (GdmPluginManager *manager, -+ GdmGreeterPlugin *plugin) -+{ -+ const char *filename; -+ -+ filename = gdm_greeter_plugin_get_filename (plugin); -+ g_hash_table_remove (manager->priv->plugins, filename); -+} -+ -+static void -+load_plugin (GdmPluginManager *manager, -+ const char *filename) -+{ -+ 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; -+ } -+ 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) -+{ -+ GdmPluginManager *manager; -+ GFileEnumerator *enumerator; -+ GError *error; -+ GdmPluginManagerOperation *operation; -+ -+ manager = open_operation->manager; -+ gdm_plugin_manager_untrack_operation (manager, open_operation); -+ -+ error = NULL; -+ enumerator = g_file_enumerate_children_finish (plugin_dir_file, -+ result, &error); -+ -+ if (enumerator == 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 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; -+ } -+ -+ operation = start_operation (manager); -+ -+ g_file_enumerator_next_files_async (enumerator, G_MAXINT, -+ G_PRIORITY_DEFAULT, -+ operation->cancellable, -+ (GAsyncReadyCallback) -+ on_plugin_info_read, -+ operation); -+ -+ gdm_plugin_manager_track_operation (manager, operation); -+} -+ -+static void -+load_plugins_in_dir (GdmPluginManager *manager, -+ const char *plugin_dir) -+{ -+ GFile *plugin_dir_file; -+ GdmPluginManagerOperation *operation; -+ -+ g_debug ("GdmPluginManager: loading plugins in dir '%s'", plugin_dir); -+ -+ 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 -+on_plugin_dir_changed (GFileMonitor *monitor, -+ GFile *file, -+ GFile *other_file, -+ GFileMonitorEvent event_type, -+ GdmPluginManagerOperation *operation) -+{ -+} -+ -+static void -+watch_plugin_dir (GdmPluginManager *manager, -+ const char *plugin_dir) -+{ -+ -+ GdmPluginManagerOperation *operation; -+ GFile *file; -+ GError *error; -+ -+ 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); -+} -+ -+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_plugin_manager_finalize (GObject *object) -+{ -+ GdmPluginManager *manager; -+ -+ manager = GDM_PLUGIN_MANAGER (object); -+ -+ g_hash_table_destroy (manager->priv->plugins); -+ g_file_monitor_cancel (manager->priv->plugin_dir_monitor); -+ -+ gdm_plugin_manager_cancel_pending_operations (manager); -+ -+ G_OBJECT_CLASS (gdm_plugin_manager_parent_class)->finalize (object); -+} -+ -+GdmPluginManager * -+gdm_plugin_manager_ref_default (void) -+{ -+ 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); -+} -+ -+GdmGreeterPlugin * -+gdm_plugin_manager_get_plugin (GdmPluginManager *manager, -+ const char *name) -+{ -+ return g_hash_table_lookup (manager->priv->plugins, name); -+} -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 @@ -+/* -+ * 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_PLUGIN_MANAGER_H -+#define __GDM_PLUGIN_MANAGER_H -+ -+#include -+ -+#include "gdm-greeter-plugin.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)) -+ -+typedef struct GdmPluginManagerPrivate GdmPluginManagerPrivate; -+ -+typedef struct -+{ -+ GObject parent; -+ GdmPluginManagerPrivate *priv; -+} GdmPluginManager; -+ -+typedef struct -+{ -+ 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); -+ -+GdmGreeterPlugin *gdm_plugin_manager_get_plugin (GdmPluginManager *plugin, -+ const char *name); -+ -+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..25831a6 100644 ---- a/gui/simple-greeter/gdm-task-list.c -+++ b/gui/simple-greeter/gdm-task-list.c -@@ -37,12 +37,6 @@ - - #define GDM_TASK_LIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_TASK_LIST, GdmTaskListPrivate)) - --typedef struct --{ -- GtkWidget *radio_button; -- char *name; --} GdmTask; -- - struct GdmTaskListPrivate - { - GtkWidget *box; -@@ -59,54 +53,161 @@ 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); -+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 *radio_button) -+ GtkRadioButton *button) - { - GdmTask *task; - -- task = g_object_get_data (G_OBJECT (radio_button), "gdm-task"); -+ task = g_object_get_data (G_OBJECT (button), "gdm-task"); - -- 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; -+ 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, -- const char *name, -- const char *icon_name) -+ GdmTask *task) - { -- GdmTask *task; - GtkWidget *image; -+ GtkWidget *button; -+ GIcon *icon; -+ char *description; - -- 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); - -- 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); - -- 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 -@@ -122,9 +223,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 +233,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) - { - 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); - -- 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 +277,46 @@ gdm_task_list_new (void) - return GTK_WIDGET (object); - } - --const char * -+gboolean -+gdm_task_list_task_is_active (GdmTaskList *task_list, -+ GdmTask *task) -+{ -+ GtkWidget *button; -+ -+ button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); -+ -+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); -+} -+ -+GdmTask * - gdm_task_list_get_active_task (GdmTaskList *widget) - { -- GList *node; -+ return gdm_task_list_foreach_task (widget, -+ (GdmTaskListForeachFunc) -+ gdm_task_list_task_is_active, -+ NULL); -+} - -- for (node = widget->priv->tasks; node != NULL; node = node->next) { -- GdmTask *task; -+gboolean -+gdm_task_list_set_active_task (GdmTaskList *widget, -+ GdmTask *task) -+{ -+ GtkWidget *button; - -- task = node->data; -+ button = GTK_WIDGET (g_object_get_data (G_OBJECT (task), -+ "gdm-task-list-button")); - -- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (task->radio_button)) ) { -- return task->name; -+ if (GTK_WIDGET_IS_SENSITIVE (button)) { -+ if (gtk_widget_activate (button)) { -+ return TRUE; - } - } - -- return NULL; -+ return FALSE; -+} -+ -+int -+gdm_task_list_get_number_of_tasks (GdmTaskList *widget) -+{ -+ 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..8bc0c0e 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" -+ - G_BEGIN_DECLS - - #define GDM_TYPE_TASK_LIST (gdm_task_list_get_type ()) -@@ -34,31 +37,44 @@ 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); -+ -+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); -+ - --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); -+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); - --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 = -+ -+AM_CPPFLAGS = \ -+ -I. \ -+ -I.. \ -+ -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) \ -+ $(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 --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 @@ -+/* -+ * 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 "gdm-conversation.h" -+#include "gdm-task.h" -+ -+ -+enum { -+ ANSWER, -+ LAST_SIGNAL -+}; -+ -+static guint signals [LAST_SIGNAL] = { 0, }; -+ -+static void gdm_conversation_class_init (gpointer g_iface); -+ -+GType -+gdm_conversation_get_type (void) -+{ -+ static GType type = 0; -+ -+ 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_conversation_class_init (gpointer g_iface) -+{ -+ 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); -+} -+ -+void -+gdm_conversation_set_message (GdmConversation *conversation, -+ const char *message) -+{ -+ GDM_CONVERSATION_GET_IFACE (conversation)->set_message (conversation, message); -+} -+ -+void -+gdm_conversation_ask_question (GdmConversation *conversation, -+ const char *message) -+{ -+ GDM_CONVERSATION_GET_IFACE (conversation)->ask_question (conversation, message); -+} -+ -+void -+gdm_conversation_ask_secret (GdmConversation *conversation, -+ const char *message) -+{ -+ GDM_CONVERSATION_GET_IFACE (conversation)->ask_secret (conversation, message); -+} -+ -+void -+gdm_conversation_reset (GdmConversation *conversation) -+{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->reset (conversation); -+} -+ -+void -+gdm_conversation_set_ready (GdmConversation *conversation) -+{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->set_ready (conversation); -+} -+ -+char * -+gdm_conversation_get_service_name (GdmConversation *conversation) -+{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->get_service_name (conversation); -+} -+ -+GtkWidget * -+gdm_conversation_get_page (GdmConversation *conversation) -+{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->get_page (conversation); -+} -+ -+GtkActionGroup * -+gdm_conversation_get_actions (GdmConversation *conversation) -+{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->get_actions (conversation); -+} -+ -+gboolean -+gdm_conversation_focus (GdmConversation *conversation) -+{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->focus (conversation); -+} -+ -+void -+gdm_conversation_request_answer (GdmConversation *conversation) -+{ -+ return GDM_CONVERSATION_GET_IFACE (conversation)->request_answer (conversation); -+} -+ -+/* protected -+ */ -+void -+gdm_conversation_answer (GdmConversation *conversation, -+ const char *answer) -+{ -+ g_signal_emit (conversation, signals [ANSWER], 0, answer); -+} -+ -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 -+ */ -+ -+ -+#ifndef __GDM_CONVERSATION_H -+#define __GDM_CONVERSATION_H -+ -+#include -+#include -+ -+G_BEGIN_DECLS -+ -+#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)) -+ -+#define GDM_CONVERSATION_DEFAULT_ACTION "default-action" -+ -+typedef struct _GdmConversation GdmConversation; -+typedef struct _GdmConversationIface GdmConversationIface; -+ -+struct _GdmConversationIface -+{ -+ GTypeInterface base_iface; -+ -+ /* 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); -+ -+ /* signals */ -+ char * (* answer) (GdmConversation *conversation); -+}; -+ -+GType gdm_conversation_get_type (void) G_GNUC_CONST; -+ -+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); -+ -+G_END_DECLS -+ -+#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 -+ * -+ */ -+ -+#include -+#include -+ -+#include "gdm-greeter-extension.h" -+ -+enum { -+ LOADED, -+ LOAD_FAILED, -+ LAST_SIGNAL -+}; -+ -+static guint signals [LAST_SIGNAL] = { 0, }; -+ -+static void gdm_greeter_extension_class_init (gpointer g_iface); -+ -+GType -+gdm_greeter_extension_get_type (void) -+{ -+ 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); -+ -+ g_type_interface_add_prerequisite (greeter_extension_type, G_TYPE_OBJECT); -+ } -+ -+ return greeter_extension_type; -+} -+ -+static void -+gdm_greeter_extension_class_init (gpointer g_iface) -+{ -+ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); -+ -+ 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); -+ -+ 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); -+} -+ -+void -+gdm_greeter_extension_loaded (GdmGreeterExtension *extension) -+{ -+ g_signal_emit (extension, signals [LOADED], 0); -+} -+ -+void -+gdm_greeter_extension_load_failed (GdmGreeterExtension *extension, -+ GError *error) -+{ -+ g_signal_emit (extension, signals [LOAD_FAILED], 0, error); -+} -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 @@ -+/* -+ * 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 -+ */ -+ -+#ifndef __GDM_GREETER_EXTENSION_H -+#define __GDM_GREETER_EXTENSION_H -+ -+#include -+ -+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)) -+ -+typedef struct _GdmGreeterExtension GdmGreeterExtension; -+typedef struct _GdmGreeterExtensionIface GdmGreeterExtensionIface; -+ -+struct _GdmGreeterExtensionIface -+{ -+ GTypeInterface base_iface; -+ -+ void (* loaded) (GdmGreeterExtension *extension); -+ void (* load_failed) (GdmGreeterExtension *extension, -+ GError *error); -+}; -+ -+GType gdm_greeter_extension_get_type (void) G_GNUC_CONST; -+ -+void gdm_greeter_extension_loaded (GdmGreeterExtension *extension); -+void gdm_greeter_extension_load_failed (GdmGreeterExtension *extension, -+ GError *error); -+ -+typedef GdmGreeterExtension * (* GdmGreeterPluginGetExtensionFunc) (void); -+ -+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 @@ -+/* -+ * 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 "gdm-task.h" -+ -+enum { -+ ENABLED, -+ DISABLED, -+ LAST_SIGNAL -+}; -+ -+static guint signals [LAST_SIGNAL] = { 0, }; -+static void gdm_task_class_init (gpointer g_iface); -+ -+GType -+gdm_task_get_type (void) -+{ -+ static GType task_type = 0; -+ -+ if (!task_type) { -+ task_type = g_type_register_static_simple (G_TYPE_INTERFACE, -+ "GdmTask", -+ sizeof (GdmTaskIface), -+ (GClassInitFunc) gdm_task_class_init, -+ 0, NULL, 0); -+ -+ g_type_interface_add_prerequisite (task_type, G_TYPE_OBJECT); -+ } -+ -+ return task_type; -+} -+ -+GIcon * -+gdm_task_get_icon (GdmTask *task) -+{ -+ return GDM_TASK_GET_IFACE (task)->get_icon (task); -+} -+ -+char * -+gdm_task_get_description (GdmTask *task) -+{ -+ return GDM_TASK_GET_IFACE (task)->get_description (task); -+} -+ -+char * -+gdm_task_get_name (GdmTask *task) -+{ -+ return GDM_TASK_GET_IFACE (task)->get_name (task); -+} -+ -+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 (should_enable) { -+ g_signal_emit (G_OBJECT (task), signals [ENABLED], 0); -+ } else { -+ g_signal_emit (G_OBJECT (task), signals [DISABLED], 0); -+ } -+} -+ -+gboolean -+gdm_task_is_enabled (GdmTask *task) -+{ -+ return !g_object_get_data (G_OBJECT (task), "gdm-task-is-disabled"); -+} -+ -+static void -+gdm_task_class_init (gpointer g_iface) -+{ -+ 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 -+ -+#include -+#include -+ -+G_BEGIN_DECLS -+ -+#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 _GdmTask GdmTask; -+typedef struct _GdmTaskIface GdmTaskIface; -+ -+struct _GdmTaskIface -+{ -+ GTypeInterface base_iface; -+ -+ /* 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); -+}; -+ -+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); -+G_END_DECLS -+ -+#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@ -+ -+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..764904d ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/Makefile.am -@@ -0,0 +1,53 @@ -+NULL = -+PAM_SERVICE_NAME = gdm-password -+ -+extensiondir = $(extensionsdatadir)/password -+extension_DATA = page.ui -+ -+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=\""$(PAM_SERVICE_NAME)"\" \ -+ -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) -+ -+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 -+ -+$(PAM_SERVICE_NAME): $(PAM_SERVICE_NAME).pam -+ cp $(PAM_SERVICE_NAME).pam $(PAM_SERVICE_NAME) -+ -+pamdir = $(PAM_PREFIX)/pam.d -+pam_DATA = $(PAM_SERVICE_NAME) -+ -+EXTRA_DIST = $(extension_DATA) $(PAM_SERVICE_NAME).pam -+CLEANFILES = $(PAM_SERVICE_NAME) -+ -+MAINTAINERCLEANFILES = \ -+ *~ \ -+ $(PAM_SERVICE_NAME) \ -+ 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..fae73be ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/gdm-password-extension.c -@@ -0,0 +1,316 @@ -+/* -+ * 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 "gdm-password-extension.h" -+#include "gdm-conversation.h" -+#include "gdm-task.h" -+ -+#include -+#include -+#include -+ -+struct _GdmPasswordExtensionPrivate -+{ -+ GIcon *icon; -+ GtkWidget *page; -+ GtkActionGroup *actions; -+ -+ GtkWidget *message_label; -+ GtkWidget *prompt_label; -+ GtkWidget *prompt_entry; -+ -+ guint answer_pending : 1; -+}; -+ -+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 (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)); -+ -+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); -+} -+ -+static void -+gdm_password_extension_ask_question (GdmConversation *conversation, -+ const char *message) -+{ -+ 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; -+} -+ -+static void -+gdm_password_extension_ask_secret (GdmConversation *conversation, -+ const char *message) -+{ -+ 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; -+} -+ -+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), ""); -+ -+ 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; -+ -+ 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); -+} -+ -+char * -+gdm_password_extension_get_service_name (GdmConversation *conversation) -+{ -+ return g_strdup (PAMSERVICENAME); -+} -+ -+GtkWidget * -+gdm_password_extension_get_page (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ return extension->priv->page; -+} -+ -+GtkActionGroup * -+gdm_password_extension_get_actions (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ return g_object_ref (extension->priv->actions); -+} -+ -+void -+gdm_password_extension_request_answer (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ const char *text; -+ -+ 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_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_password_extension_focus (GdmConversation *conversation) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (conversation); -+ if (!extension->priv->answer_pending) { -+ gdm_conversation_answer (conversation, NULL); -+ return FALSE; -+ } -+ -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ return TRUE; -+} -+ -+GIcon * -+gdm_password_extension_get_icon (GdmTask *task) -+{ -+ GdmPasswordExtension *extension = GDM_PASSWORD_EXTENSION (task); -+ return g_object_ref (extension->priv->icon); -+} -+ -+char * -+gdm_password_extension_get_name (GdmTask *task) -+{ -+ return g_strdup (_("Password Authentication")); -+} -+ -+char * -+gdm_password_extension_get_description (GdmTask *task) -+{ -+ return g_strdup (_("Log into session with username and password")); -+} -+ -+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; -+} -+ -+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 -+gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) -+{ -+} -+ -+static void -+gdm_password_extension_class_init (GdmPasswordExtensionClass *extension_class) -+{ -+ 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)); -+} -+ -+static void -+gdm_password_extension_finalize (GObject *object) -+{ -+} -+ -+static void -+on_activate_log_in (GdmPasswordExtension *extension) -+{ -+ gdm_password_extension_request_answer (GDM_CONVERSATION (extension)); -+} -+ -+static void -+create_page (GdmPasswordExtension *extension) -+{ -+ GtkBuilder *builder; -+ GObject *object; -+ GError *error; -+ -+ builder = gtk_builder_new (); -+ -+ error = NULL; -+ gtk_builder_add_from_file (builder, -+ PLUGINDATADIR "/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); -+} -+ -+static void -+create_actions (GdmPasswordExtension *extension) -+{ -+ 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); -+} -+ -+static void -+gdm_password_extension_init (GdmPasswordExtension *extension) -+{ -+ 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)); -+} -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)) -+ -+typedef struct _GdmPasswordExtensionPrivate GdmPasswordExtensionPrivate; -+ -+typedef struct -+{ -+ GObject parent; -+ GdmPasswordExtensionPrivate *priv; -+} GdmPasswordExtension; -+ -+typedef struct -+{ -+ GObjectClass parent_class; -+} GdmPasswordExtensionClass; -+ -+GType gdm_password_extension_get_type (void); -+ -+GdmPasswordExtension *gdm_password_extension_new (void); -+ -+G_END_DECLS -+ -+#endif /* GDM_PASSWORD_EXTENSION_H */ -diff --git a/gui/simple-greeter/plugins/password/gdm-password.pam b/gui/simple-greeter/plugins/password/gdm-password.pam -new file mode 100644 -index 0000000..bac431d ---- /dev/null -+++ b/gui/simple-greeter/plugins/password/gdm-password.pam -@@ -0,0 +1,19 @@ -+# Sample PAM file for doing password authentication. -+# Distros should replace this with what makes sense for them. -+auth required pam_env.so -+auth sufficient pam_unix.so nullok try_first_pass -+auth requisite pam_succeed_if.so uid >= 500 quiet -+auth required pam_deny.so -+ -+account required pam_unix.so -+account sufficient pam_localuser.so -+account sufficient pam_succeed_if.so uid < 500 quiet -+account required pam_permit.so -+ -+password requisite pam_cracklib.so try_first_pass retry=3 type= -+password sufficient pam_unix.so nullok try_first_pass use_authtok -+password required pam_deny.so -+ -+session optional pam_keyinit.so revoke -+session required pam_limits.so -+session required pam_unix.so -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 @@ -+/* -+ * 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-password-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_PASSWORD_EXTENSION, NULL); -+ g_object_add_weak_pointer (extension, (gpointer *) &extension); -+ } -+ -+ return GDM_GREETER_EXTENSION (extension); -+} --- -1.6.3.3 - - -From f65b1f138fa4f8e3e9ee5add0c83a64b6fb281d4 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sat, 7 Feb 2009 21:17:49 -0500 -Subject: [PATCH 17/38] 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 07cb4e3..7f01748 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -849,15 +849,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) -+{ -+ /* need to wait for response from backend */ -+ set_message (login_window, _("Cancelling...")); -+ restart_conversations (login_window); -+} -+ - gboolean - gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - const char *service_name) -@@ -903,6 +909,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)); -+ -+ 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.3.3 - - -From b235677b51bd727e60520208bfd3f9d75f9c6033 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 18 Feb 2009 12:32:39 -0500 -Subject: [PATCH 18/38] Add a way for plugins to pick users from list - -The smartcard plugin is going to want to -start its conversation as soon as the card -gets plugged in. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 36 ++++++++++++++++++++ - .../libgdmsimplegreeter/gdm-conversation.c | 32 +++++++++++++++++ - .../libgdmsimplegreeter/gdm-conversation.h | 6 +++ - 3 files changed, 74 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 7f01748..9fdf50e 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -2101,6 +2101,34 @@ on_conversation_answer (GdmGreeterLoginWindow *login_window, - set_ready (login_window); - } - -+static void -+on_conversation_cancel (GdmGreeterLoginWindow *login_window, -+ GdmConversation *conversation) -+{ -+ do_cancel (login_window); -+} -+ -+static void -+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; -+ -+ 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 (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); -+ } -+} -+ - void - gdm_greeter_login_window_remove_extension (GdmGreeterLoginWindow *login_window, - GdmGreeterExtension *extension) -@@ -2238,6 +2266,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); -+} -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.3.3 - - -From bd3ea14146897f47a7b4fcb7f698e47ad9185c31 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Feb 2009 14:05:20 -0500 -Subject: [PATCH 19/38] 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 4e76439..da41f77 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; -@@ -2527,8 +2528,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; -+} -+ - void - gdm_chooser_widget_loaded (GdmChooserWidget *widget) - { -+ widget->priv->is_loaded = TRUE; -+ - 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 7e3e59c..6a07843 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); -+ - /* Protected - */ - void gdm_chooser_widget_loaded (GdmChooserWidget *widget); --- -1.6.3.3 - - -From 958f7acdca959afa04aa0ce05be6ffe9b531bd0e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Feb 2009 14:31:27 -0500 -Subject: [PATCH 20/38] 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 | 28 ++++++++++++++++++++++++- - 1 files changed, 27 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 9fdf50e..6ef3d00 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -864,6 +864,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)); -+} -+ - gboolean - gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, - const char *service_name) -@@ -878,7 +899,12 @@ 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 { -+ -+ set_task_ready_when_loaded (login_window, task); -+ } - g_object_unref (task); - } - --- -1.6.3.3 - - -From 4f8000921ea2c762d460629f93c88e8384923cbc Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 6 Feb 2009 16:25:47 -0500 -Subject: [PATCH 21/38] Add fingerprint plugin - -This commit adds a plugin to initiate a conversation for -fingerprint scans. ---- - configure.ac | 4 + - gui/simple-greeter/plugins/Makefile.am | 2 +- - gui/simple-greeter/plugins/fingerprint/Makefile.am | 56 ++++ - .../fingerprint/gdm-fingerprint-extension.c | 299 ++++++++++++++++++++ - .../fingerprint/gdm-fingerprint-extension.h | 56 ++++ - .../plugins/fingerprint/gdm-fingerprint.pam | 17 ++ - .../plugins/fingerprint/icons/16x16/Makefile.am | 5 + - .../plugins/fingerprint/icons/48x48/Makefile.am | 5 + - .../plugins/fingerprint/icons/Makefile.am | 1 + - gui/simple-greeter/plugins/fingerprint/page.ui | 56 ++++ - gui/simple-greeter/plugins/fingerprint/plugin.c | 40 +++ - 11 files changed, 540 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/gdm-fingerprint.pam - create mode 100644 gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am - create mode 100644 gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am - create mode 100644 gui/simple-greeter/plugins/fingerprint/icons/Makefile.am - 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 4278d7c..33bb81f 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1375,6 +1375,10 @@ 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/fingerprint/icons/Makefile -+gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile -+gui/simple-greeter/plugins/fingerprint/icons/48x48/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..25fb6e8 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/Makefile.am -@@ -0,0 +1,56 @@ -+SUBDIRS = icons -+ -+NULL = -+PAM_SERVICE_NAME = gdm-fingerprint -+ -+extensiondir = $(extensionsdatadir)/fingerprint -+extension_DATA = page.ui -+ -+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=\""$(PAM_SERVICE_NAME)"\" \ -+ -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 = fingerprint.la -+ -+fingerprint_la_CFLAGS = \ -+ $(SIMPLE_GREETER_CFLAGS) \ -+ $(NULL) -+ -+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 -+ -+$(PAM_SERVICE_NAME): $(PAM_SERVICE_NAME).pam -+ cp $(PAM_SERVICE_NAME).pam $(PAM_SERVICE_NAME) -+ -+pamdir = $(PAM_PREFIX)/pam.d -+pam_DATA = $(PAM_SERVICE_NAME) -+ -+EXTRA_DIST = $(extension_DATA) $(PAM_SERVICE_NAME).pam -+CLEANFILES = $(PAM_SERVICE_NAME) -+ -+MAINTAINERCLEANFILES = \ -+ *~ \ -+ $(PAM_SERVICE_NAME) \ -+ 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..b20dd65 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c -@@ -0,0 +1,299 @@ -+/* -+ * 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 "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); -+ -+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 (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)); -+ -+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) -+{ -+ 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 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), ""); -+ -+ 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; -+ -+ gdm_task_set_enabled (GDM_TASK (conversation), FALSE); -+} -+ -+static void -+gdm_fingerprint_extension_set_ready (GdmConversation *conversation) -+{ -+ gdm_task_set_enabled (GDM_TASK (conversation), TRUE); -+} -+ -+char * -+gdm_fingerprint_extension_get_service_name (GdmConversation *conversation) -+{ -+ return g_strdup (PAMSERVICENAME); -+} -+ -+GtkWidget * -+gdm_fingerprint_extension_get_page (GdmConversation *conversation) -+{ -+ 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_fingerprint_extension_request_answer (GdmConversation *conversation) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ const char *text; -+ -+ 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) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ -+ if (!extension->priv->answer_pending) { -+ return FALSE; -+ } -+ -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ return TRUE; -+} -+ -+GIcon * -+gdm_fingerprint_extension_get_icon (GdmTask *task) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (task); -+ return g_object_ref (extension->priv->icon); -+} -+ -+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")); -+} -+ -+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; -+} -+ -+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; -+} -+ -+static void -+gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) -+{ -+} -+ -+static void -+gdm_fingerprint_extension_class_init (GdmFingerprintExtensionClass *extension_class) -+{ -+ GObjectClass *object_class; -+ -+ object_class = G_OBJECT_CLASS (extension_class); -+ -+ object_class->finalize = gdm_fingerprint_extension_finalize; -+ -+ g_type_class_add_private (extension_class, -+ sizeof (GdmFingerprintExtensionPrivate)); -+} -+ -+static void -+gdm_fingerprint_extension_finalize (GObject *object) -+{ -+} -+ -+static void -+create_page (GdmFingerprintExtension *extension) -+{ -+ GtkBuilder *builder; -+ GObject *object; -+ GError *error; -+ -+ builder = gtk_builder_new (); -+ -+ error = NULL; -+ gtk_builder_add_from_file (builder, -+ PLUGINDATADIR "/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); -+} -+ -+static void -+create_actions (GdmFingerprintExtension *extension) -+{ -+ GtkAction *action; -+ -+ extension->priv->actions = gtk_action_group_new ("gdm-fingerprint-extension"); -+} -+ -+static void -+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 ("gdm-fingerprint"); -+ create_page (extension); -+ create_actions (extension); -+ gdm_fingerprint_extension_reset (GDM_CONVERSATION (extension)); -+} -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 @@ -+/* -+ * 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 -+{ -+ GObjectClass parent_class; -+} GdmFingerprintExtensionClass; -+ -+GType gdm_fingerprint_extension_get_type (void); -+ -+GdmFingerprintExtension *gdm_fingerprint_extension_new (void); -+ -+G_END_DECLS -+ -+#endif /* GDM_FINGERPRINT_EXTENSION_H */ -diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint.pam b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint.pam -new file mode 100644 -index 0000000..1a1c777 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint.pam -@@ -0,0 +1,17 @@ -+# Sample PAM file for doing fingerprint authentication. -+# Distros should replace this with what makes sense for them. -+auth required pam_env.so -+auth required pam_fprintd.so -+auth sufficient pam_succeed_if.so uid >= 500 quiet -+auth required pam_deny.so -+ -+account required pam_unix.so -+account sufficient pam_localuser.so -+account sufficient pam_succeed_if.so uid < 500 quiet -+account required pam_permit.so -+ -+password required pam_deny.so -+ -+session optional pam_keyinit.so revoke -+session required pam_limits.so -+session required pam_unix.so -diff --git a/gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am b/gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am -new file mode 100644 -index 0000000..f42e317 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am -@@ -0,0 +1,5 @@ -+iconsdir = $(datadir)/icons/hicolor/16x16/apps -+ -+icons_DATA = gdm-fingerprint.png -+ -+EXTRA_DIST = $(icons_DATA) -diff --git a/gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am b/gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am -new file mode 100644 -index 0000000..f4ab2a0 ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am -@@ -0,0 +1,5 @@ -+iconsdir = $(datadir)/icons/hicolor/48x48/apps -+ -+icons_DATA = gdm-fingerprint.png -+ -+EXTRA_DIST = $(icons_DATA) -diff --git a/gui/simple-greeter/plugins/fingerprint/icons/Makefile.am b/gui/simple-greeter/plugins/fingerprint/icons/Makefile.am -new file mode 100644 -index 0000000..c20f10d ---- /dev/null -+++ b/gui/simple-greeter/plugins/fingerprint/icons/Makefile.am -@@ -0,0 +1 @@ -+SUBDIRS = 16x16 48x48 -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 @@ -+/* -+ * 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); -+} --- -1.6.3.3 - - -From d47888f0c98007a00e93c178370d1d1eafcc56ae Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 11 Feb 2009 08:47:52 -0500 -Subject: [PATCH 22/38] Add start of a smartcard plugin - -It contains a copy and paste of an old RHEL patch -I did a few years ago. ---- - configure.ac | 11 + - gui/simple-greeter/plugins/Makefile.am | 2 +- - gui/simple-greeter/plugins/smartcard/Makefile.am | 77 ++ - .../plugins/smartcard/gdm-smartcard-extension.c | 420 ++++++ - .../plugins/smartcard/gdm-smartcard-extension.h | 56 + - .../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 ++ - .../plugins/smartcard/gdm-smartcard.pam | 18 + - .../plugins/smartcard/icons/16x16/Makefile.am | 5 + - .../smartcard/icons/16x16/gdm-smartcard.png | Bin 0 -> 871 bytes - .../plugins/smartcard/icons/48x48/Makefile.am | 5 + - .../smartcard/icons/48x48/gdm-smartcard.png | Bin 0 -> 4202 bytes - .../plugins/smartcard/icons/Makefile.am | 1 + - gui/simple-greeter/plugins/smartcard/page.ui | 56 + - gui/simple-greeter/plugins/smartcard/plugin.c | 40 + - 18 files changed, 2989 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/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 - create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam - create mode 100644 gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am - create mode 100644 gui/simple-greeter/plugins/smartcard/icons/16x16/gdm-smartcard.png - create mode 100644 gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am - create mode 100644 gui/simple-greeter/plugins/smartcard/icons/48x48/gdm-smartcard.png - create mode 100644 gui/simple-greeter/plugins/smartcard/icons/Makefile.am - 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 33bb81f..6e46508 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -66,6 +66,7 @@ GNOME_PANEL_REQUIRED_VERSION=2.0.0 - LIBXKLAVIER_REQUIRED_VERSION=4.0 - #FONTCONFIG_REQUIRED_VERSION=2.6.0 - FONTCONFIG_REQUIRED_VERSION=2.5.0 -+NSS_REQUIRED_VERSION=3.11.1 - - EXTRA_COMPILE_WARNINGS(yes) - -@@ -88,6 +89,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 -@@ -1379,6 +1386,10 @@ gui/simple-greeter/plugins/fingerprint/Makefile - gui/simple-greeter/plugins/fingerprint/icons/Makefile - gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile - gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile -+gui/simple-greeter/plugins/smartcard/Makefile -+gui/simple-greeter/plugins/smartcard/icons/Makefile -+gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile -+gui/simple-greeter/plugins/smartcard/icons/48x48/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..1ccebda ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/Makefile.am -@@ -0,0 +1,77 @@ -+SUBDIRS = icons -+ -+NULL = -+PAM_SERVICE_NAME = gdm-smartcard -+ -+extensiondir = $(extensionsdatadir)/smartcard -+extension_DATA = page.ui -+ -+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=\""$(pam_DATA)"\" \ -+ -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) -+ -+plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) -+plugin_LTLIBRARIES = smartcard.la -+ -+smartcard_la_CFLAGS = \ -+ $(SIMPLE_GREETER_CFLAGS) \ -+ $(NULL) -+ -+libexec_PROGRAMS = \ -+ gdm-smartcard-worker \ -+ $(NULL) -+ -+ -+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 -+ -+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) -+ -+$(PAM_SERVICE_NAME): $(PAM_SERVICE_NAME).pam -+ cp $(PAM_SERVICE_NAME).pam $(PAM_SERVICE_NAME) -+ -+pamdir = $(PAM_PREFIX)/pam.d -+pam_DATA = $(PAM_SERVICE_NAME) -+ -+EXTRA_DIST = $(extension_DATA) $(PAM_SERVICE_NAME).pam -+CLEANFILES = $(PAM_SERVICE_NAME) -+ -+MAINTAINERCLEANFILES = \ -+ *~ \ -+ $(PAM_SERVICE_NAME) \ -+ 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..632ee2d ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -@@ -0,0 +1,420 @@ -+/* -+ * 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 "gdm-smartcard-extension.h" -+#include "gdm-conversation.h" -+#include "gdm-task.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#ifndef GDM_SMARTCARD_WORKER_COMMAND -+#define GDM_SMARTCARD_WORKER_COMMAND LIBEXECDIR "/gdm-smartcard-worker" -+#endif -+ -+struct _GdmSmartcardExtensionPrivate -+{ -+ GIcon *icon; -+ GtkWidget *page; -+ GtkActionGroup *actions; -+ GtkAction *login_action; -+ -+ GtkWidget *message_label; -+ GtkWidget *prompt_label; -+ GtkWidget *prompt_entry; -+ -+ GPid worker_pid; -+ int number_of_tokens; -+ -+ guint answer_pending : 1; -+}; -+ -+static void gdm_smartcard_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_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 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_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); -+} -+ -+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; -+} -+ -+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), ""); -+ -+ 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); -+} -+ -+static void -+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) -+ { -+ watch_for_smartcards (extension); -+ } -+} -+ -+char * -+gdm_smartcard_extension_get_service_name (GdmConversation *conversation) -+{ -+ return g_strdup (PAMSERVICENAME); -+} -+ -+GtkWidget * -+gdm_smartcard_extension_get_page (GdmConversation *conversation) -+{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); -+ return extension->priv->page; -+} -+ -+GtkActionGroup * -+gdm_smartcard_extension_get_actions (GdmConversation *conversation) -+{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); -+ -+ return g_object_ref (extension->priv->actions); -+} -+ -+void -+gdm_smartcard_extension_request_answer (GdmConversation *conversation) -+{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); -+ const char *text; -+ -+ 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), ""); -+ gtk_action_set_visible (extension->priv->login_action, FALSE); -+} -+ -+gboolean -+gdm_smartcard_extension_focus (GdmConversation *conversation) -+{ -+ GdmSmartcardExtension *extension = GDM_SMARTCARD_EXTENSION (conversation); -+ -+ if (!extension->priv->answer_pending) { -+ return FALSE; -+ } -+ -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ return TRUE; -+} -+ -+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) -+{ -+ return g_strdup (_("Smartcard Authentication")); -+} -+ -+char * -+gdm_smartcard_extension_get_description (GdmTask *task) -+{ -+ return g_strdup (_("Log into session with smartcard")); -+} -+ -+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; -+} -+ -+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; -+} -+ -+static void -+gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) -+{ -+} -+ -+static void -+gdm_smartcard_extension_class_init (GdmSmartcardExtensionClass *extension_class) -+{ -+ GObjectClass *object_class; -+ -+ object_class = G_OBJECT_CLASS (extension_class); -+ -+ object_class->finalize = gdm_smartcard_extension_finalize; -+ -+ g_type_class_add_private (extension_class, -+ sizeof (GdmSmartcardExtensionPrivate)); -+} -+ -+static void -+gdm_smartcard_extension_finalize (GObject *object) -+{ -+} -+ -+static void -+create_page (GdmSmartcardExtension *extension) -+{ -+ GtkBuilder *builder; -+ GObject *object; -+ GError *error; -+ -+ builder = gtk_builder_new (); -+ -+ error = NULL; -+ gtk_builder_add_from_file (builder, -+ PLUGINDATADIR "/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); -+} -+ -+static void -+on_activate_log_in (GdmSmartcardExtension *extension) -+{ -+ gdm_smartcard_extension_request_answer (GDM_CONVERSATION (extension)); -+} -+ -+static void -+create_actions (GdmSmartcardExtension *extension) -+{ -+ GtkAction *action; -+ -+ extension->priv->actions = gtk_action_group_new ("gdm-smartcard-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); -+ -+ gtk_action_set_visible (action, FALSE); -+ extension->priv->login_action = action; -+} -+ -+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 ("gdm-smartcard"); -+ 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/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 -+ * -+ * 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" -+ -+#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 -+ -+#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; -+ SECMODModule *module; -+ char *module_path; -+ -+ GSource *smartcard_event_source; -+ GPid smartcard_event_watcher_pid; -+ GHashTable *smartcards; -+ -+ GThread *worker_thread; -+ -+ guint poll_timeout_id; -+ -+ guint32 is_unstoppable : 1; -+ guint32 nss_is_loaded : 1; -+}; -+ -+struct _GdmSmartcardManagerWorker { -+ SECMODModule *module; -+ GHashTable *smartcards; -+ gint write_fd; -+ -+ guint32 nss_is_loaded : 1; -+}; -+ -+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); -+ -+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); -+ -+enum { -+ PROP_0 = 0, -+ PROP_MODULE_PATH, -+ NUMBER_OF_PROPERTIES -+}; -+ -+enum { -+ SMARTCARD_INSERTED = 0, -+ SMARTCARD_REMOVED, -+ ERROR, -+ NUMBER_OF_SIGNALS -+}; -+ -+static guint gdm_smartcard_manager_signals[NUMBER_OF_SIGNALS]; -+ -+G_DEFINE_TYPE (GdmSmartcardManager, -+ gdm_smartcard_manager, -+ G_TYPE_OBJECT); -+ -+static void -+gdm_smartcard_manager_class_init (GdmSmartcardManagerClass *manager_class) -+{ -+ GObjectClass *gobject_class; -+ -+ gobject_class = G_OBJECT_CLASS (manager_class); -+ -+ gobject_class->finalize = gdm_smartcard_manager_finalize; -+ -+ 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 -+gdm_smartcard_manager_class_install_properties (GdmSmartcardManagerClass *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; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+static void -+gdm_smartcard_manager_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ 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; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+char * -+gdm_smartcard_manager_get_module_path (GdmSmartcardManager *manager) -+{ -+ return manager->priv->module_path; -+} -+ -+static void -+gdm_smartcard_manager_set_module_path (GdmSmartcardManager *manager, -+ const char *module_path) -+{ -+ if ((manager->priv->module_path == NULL) && (module_path == NULL)) { -+ return; -+ } -+ -+ 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"); -+ } -+} -+ -+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"); -+} -+ -+static void -+gdm_smartcard_manager_card_inserted_handler (GdmSmartcardManager *manager, -+ GdmSmartcard *card) -+{ -+ g_debug ("informing smartcard of its insertion"); -+ -+ _gdm_smartcard_set_state (card, GDM_SMARTCARD_STATE_INSERTED); -+ g_debug ("done"); -+ -+} -+ -+static void -+gdm_smartcard_manager_class_install_signals (GdmSmartcardManagerClass *manager_class) -+{ -+ GObjectClass *object_class; -+ -+ object_class = G_OBJECT_CLASS (manager_class); -+ -+ 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; -+ -+ 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; -+ -+ 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; -+} -+ -+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); -+ -+ return *slot_id_1 == *slot_id_2; -+} -+ -+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); -+} -+ -+static void -+gdm_smartcard_manager_init (GdmSmartcardManager *manager) -+{ -+ g_debug ("initializing smartcard manager"); -+ -+ 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; -+ -+ manager->priv->smartcards = -+ g_hash_table_new_full (g_str_hash, -+ g_str_equal, -+ (GDestroyNotify) g_free, -+ (GDestroyNotify) g_object_unref); -+ -+ if (!g_thread_supported()) { -+ g_thread_init (NULL); -+ } -+ -+} -+ -+static void -+gdm_smartcard_manager_finalize (GObject *object) -+{ -+ GdmSmartcardManager *manager; -+ GObjectClass *gobject_class; -+ -+ manager = GDM_SMARTCARD_MANAGER (object); -+ gobject_class = -+ G_OBJECT_CLASS (gdm_smartcard_manager_parent_class); -+ -+ gdm_smartcard_manager_stop_now (manager); -+ -+ g_hash_table_destroy (manager->priv->smartcards); -+ manager->priv->smartcards = NULL; -+ -+ gobject_class->finalize (object); -+} -+ -+GQuark -+gdm_smartcard_manager_error_quark (void) -+{ -+ static GQuark error_quark = 0; -+ -+ if (error_quark == 0) { -+ error_quark = g_quark_from_static_string ("gdm-smartcard-manager-error-quark"); -+ } -+ -+ return error_quark; -+} -+ -+GdmSmartcardManager * -+gdm_smartcard_manager_new (const char *module_path) -+{ -+ GdmSmartcardManager *instance; -+ -+ instance = GDM_SMARTCARD_MANAGER (g_object_new (GDM_TYPE_SMARTCARD_MANAGER, -+ "module-path", module_path, -+ NULL)); -+ -+ return instance; -+} -+ -+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; -+} -+ -+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; -+} -+ -+static void -+gdm_smartcard_manager_emit_smartcard_removed (GdmSmartcardManager *manager, -+ GdmSmartcard *card) -+{ -+ GdmSmartcardManagerState old_state; -+ -+ 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; -+} -+ -+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; -+ -+ card = NULL; -+ should_stop = (condition & G_IO_HUP) || (condition & G_IO_ERR); -+ -+ 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"); -+ } -+ -+ if (!(condition & G_IO_IN)) { -+ goto out; -+ } -+ -+ 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; -+ } -+ -+ card = sc_read_smartcard (fd, manager->priv->module); -+ -+ if (card == NULL) { -+ should_stop = TRUE; -+ goto out; -+ } -+ -+ 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; -+ } -+ -+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")); -+ -+ gdm_smartcard_manager_emit_error (manager, error); -+ g_error_free (error); -+ gdm_smartcard_manager_stop_now (manager); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static void -+gdm_smartcard_manager_event_processing_stopped_handler (GdmSmartcardManager *manager) -+{ -+ manager->priv->smartcard_event_source = NULL; -+ gdm_smartcard_manager_stop_now (manager); -+} -+ -+static gboolean -+gdm_open_pipe (gint *write_fd, -+ gint *read_fd) -+{ -+ gint pipe_fds[2] = { -1, -1 }; -+ -+ g_assert (write_fd != NULL); -+ g_assert (read_fd != NULL); -+ -+ if (pipe (pipe_fds) < 0) { -+ return FALSE; -+ } -+ -+ if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) { -+ close (pipe_fds[0]); -+ close (pipe_fds[1]); -+ return FALSE; -+ } -+ -+ if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) { -+ close (pipe_fds[0]); -+ close (pipe_fds[1]); -+ return FALSE; -+ } -+ -+ *read_fd = pipe_fds[0]; -+ *write_fd = pipe_fds[1]; -+ -+ return TRUE; -+} -+ -+static void -+gdm_smartcard_manager_stop_watching_for_events (GdmSmartcardManager *manager) -+{ -+ if (manager->priv->smartcard_event_source != NULL) { -+ g_source_destroy (manager->priv->smartcard_event_source); -+ manager->priv->smartcard_event_source = NULL; -+ } -+ -+ 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; -+ } -+} -+ -+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; -+ -+ g_debug ("attempting to load NSS database '%s'", -+ GDM_SMARTCARD_MANAGER_NSS_DB); -+ -+ status = NSS_Initialize (GDM_SMARTCARD_MANAGER_NSS_DB, -+ "", "", SECMOD_DB, flags); -+ -+ if (status != SECSuccess) { -+ gsize error_message_size; -+ char *error_message; -+ -+ error_message_size = PR_GetErrorTextLength (); -+ -+ 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; -+ } -+ -+ g_debug ("NSS database sucessfully loaded"); -+ return TRUE; -+ -+out: -+ g_debug ("NSS database couldn't be sucessfully loaded"); -+ return FALSE; -+} -+ -+static SECMODModule * -+load_driver (char *module_path, -+ GError **error) -+{ -+ SECMODModule *module; -+ char *module_spec; -+ gboolean module_explicitly_specified; -+ -+ g_debug ("attempting to load driver..."); -+ -+ 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); -+ -+ module = SECMOD_LoadUserModule (module_spec, -+ NULL /* parent */, -+ FALSE /* recurse */); -+ g_free (module_spec); -+ module_spec = NULL; -+ -+ } else { -+ SECMODModuleList *modules, *tmp; -+ -+ modules = SECMOD_GetDefaultModuleList (); -+ -+ for (tmp = modules; tmp != NULL; tmp = tmp->next) { -+ if (!SECMOD_HasRemovableSlots (tmp->module) || -+ !tmp->module->loaded) -+ continue; -+ -+ module = SECMOD_ReferenceModule (tmp->module); -+ 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); -+ -+ module = SECMOD_LoadUserModule (module_spec, -+ NULL /* parent */, -+ FALSE /* recurse */); -+ g_free (module_spec); -+ module_spec = NULL; -+ } -+ -+ } -+ -+ 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) { -+ -+ gsize error_message_size; -+ char *error_message; -+ -+ if (module != NULL && !module->loaded) { -+ g_debug ("module found but not loaded?!"); -+ SECMOD_DestroyModule (module); -+ module = NULL; -+ } -+ -+ error_message_size = PR_GetErrorTextLength (); -+ -+ 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; -+ } -+ -+ 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); -+ } -+ -+out: -+ return module; -+} -+ -+static void -+gdm_smartcard_manager_get_all_cards (GdmSmartcardManager *manager) -+{ -+ 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]); -+ -+ card = _gdm_smartcard_new (manager->priv->module, -+ slot_id, slot_series); -+ -+ card_name = gdm_smartcard_get_name (card); -+ -+ g_hash_table_replace (manager->priv->smartcards, -+ card_name, card); -+ } -+} -+ -+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 (manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STARTED) { -+ g_debug ("smartcard manager already started"); -+ return TRUE; -+ } -+ -+ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STARTING; -+ -+ worker_fd = -1; -+ worker_pid = 0; -+ -+ 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; -+ -+ 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; -+ } -+ -+ if (!gdm_smartcard_manager_create_worker (manager, &worker_fd, &manager->priv->worker_thread)) { -+ -+ 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)); -+ -+ goto out; -+ } -+ -+ 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); -+ g_io_channel_unref (io_channel); -+ io_channel = NULL; -+ -+ manager->priv->smartcard_event_source = source; -+ -+ 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); -+ -+ /* populate the hash with cards that are already inserted -+ */ -+ gdm_smartcard_manager_get_all_cards (manager); -+ -+ 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 gboolean -+gdm_smartcard_manager_stop_now (GdmSmartcardManager *manager) -+{ -+ 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); -+ -+ if (manager->priv->module != NULL) { -+ SECMOD_DestroyModule (manager->priv->module); -+ manager->priv->module = NULL; -+ } -+ -+ if (manager->priv->nss_is_loaded) { -+ NSS_Shutdown (); -+ manager->priv->nss_is_loaded = FALSE; -+ } -+ -+ g_debug ("smartcard manager stopped"); -+ -+ return FALSE; -+} -+ -+static void -+gdm_smartcard_manager_queue_stop (GdmSmartcardManager *manager) -+{ -+ -+ manager->priv->state = GDM_SMARTCARD_MANAGER_STATE_STOPPING; -+ -+ g_idle_add ((GSourceFunc) gdm_smartcard_manager_stop_now, manager); -+} -+ -+void -+gdm_smartcard_manager_stop (GdmSmartcardManager *manager) -+{ -+ if (manager->priv->state == GDM_SMARTCARD_MANAGER_STATE_STOPPED) { -+ return; -+ } -+ -+ if (manager->priv->is_unstoppable) { -+ gdm_smartcard_manager_queue_stop (manager); -+ return; -+ } -+ -+ gdm_smartcard_manager_stop_now (manager); -+} -+ -+static void -+gdm_smartcard_manager_check_for_login_card (CK_SLOT_ID slot_id, -+ GdmSmartcard *card, -+ gboolean *is_inserted) -+{ -+ g_assert (is_inserted != NULL); -+ -+ if (gdm_smartcard_is_login_card (card)) { -+ *is_inserted = TRUE; -+ } -+ -+} -+ -+gboolean -+gdm_smartcard_manager_login_card_is_inserted (GdmSmartcardManager *manager) -+ -+{ -+ gboolean is_inserted; -+ -+ is_inserted = FALSE; -+ g_hash_table_foreach (manager->priv->smartcards, -+ (GHFunc) -+ gdm_smartcard_manager_check_for_login_card, -+ &is_inserted); -+ return is_inserted; -+} -+ -+static GdmSmartcardManagerWorker * -+gdm_smartcard_manager_worker_new (gint write_fd) -+{ -+ GdmSmartcardManagerWorker *worker; -+ -+ worker = g_slice_new0 (GdmSmartcardManagerWorker); -+ worker->write_fd = write_fd; -+ worker->module = NULL; -+ -+ 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; -+} -+ -+static void -+gdm_smartcard_manager_worker_free (GdmSmartcardManagerWorker *worker) -+{ -+ if (worker->smartcards != NULL) { -+ g_hash_table_destroy (worker->smartcards); -+ worker->smartcards = NULL; -+ } -+ -+ g_slice_free (GdmSmartcardManagerWorker, worker); -+} -+ -+static gboolean -+sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes) -+{ -+ 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); -+ -+ if (bytes_read <= 0) { -+ if ((bytes_read < 0) && (errno == EINTR || errno == EAGAIN)) { -+ continue; -+ } -+ -+ bytes_left = 0; -+ } else { -+ bytes_left -= bytes_read; -+ total_bytes_read += bytes_read; -+ } -+ } while (bytes_left > 0); -+ -+ if (total_bytes_read < (size_t) num_bytes) { -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static gboolean -+sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes) -+{ -+ 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); -+ -+ 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 TRUE; -+} -+ -+static GdmSmartcard * -+sc_read_smartcard (gint fd, -+ SECMODModule *module) -+{ -+ 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); -+ -+ return card; -+} -+ -+static gboolean -+sc_write_smartcard (gint fd, -+ GdmSmartcard *card) -+{ -+ gsize card_name_size; -+ char *card_name; -+ -+ card_name = gdm_smartcard_get_name (card); -+ card_name_size = strlen (card_name) + 1; -+ -+ if (!sc_write_bytes (fd, &card_name_size, sizeof (card_name_size))) { -+ g_free (card_name); -+ return FALSE; -+ } -+ -+ if (!sc_write_bytes (fd, card_name, card_name_size)) { -+ g_free (card_name); -+ return FALSE; -+ } -+ g_free (card_name); -+ -+ return TRUE; -+} -+ -+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)); -+ -+ if (!sc_write_bytes (worker->write_fd, "R", 1)) { -+ goto error_out; -+ } -+ -+ if (!sc_write_smartcard (worker->write_fd, card)) { -+ goto error_out; -+ } -+ -+ return TRUE; -+ -+error_out: -+ g_set_error (error, GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, -+ "%s", g_strerror (errno)); -+ return FALSE; -+} -+ -+static gboolean -+gdm_smartcard_manager_worker_emit_smartcard_inserted (GdmSmartcardManagerWorker *worker, -+ GdmSmartcard *card, -+ GError **error) -+{ -+ GError *write_error; -+ -+ 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; -+ } -+ -+ if (!sc_write_smartcard (worker->write_fd, card)) { -+ goto error_out; -+ } -+ -+ return TRUE; -+ -+error_out: -+ g_set_error (error, GDM_SMARTCARD_MANAGER_ERROR, -+ GDM_SMARTCARD_MANAGER_ERROR_REPORTING_EVENTS, -+ "%s", g_strerror (errno)); -+ return FALSE; -+} -+ -+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; -+ -+ g_debug ("waiting for card event"); -+ -+ /* 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. -+ */ -+ -+ slot = SECMOD_WaitForAnyTokenEvent (worker->module, 0, PR_SecondsToInterval (1)); -+ processing_error = NULL; -+ -+ if (slot == NULL) { -+ int error_code; -+ -+ error_code = PORT_GetError (); -+ if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT)) { -+ g_debug ("spurrious event occurred"); -+ return TRUE; -+ } -+ -+ /* 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; -+ } -+ -+ /* 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); -+ -+ /* 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); -+ -+ if (card != NULL) { -+ card_slot_series = gdm_smartcard_get_slot_series (card); -+ } else { -+ card_slot_series = -1; -+ } -+ -+ 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; -+ } -+ } -+ -+ 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; -+ } -+ } 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) { -+ -+ 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); -+ -+ 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; -+ } -+ } -+ -+ 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); -+ card = NULL; -+ } else { -+ g_debug ("got spurious remove event"); -+ } -+ } -+ -+ g_free (key); -+ PK11_FreeSlot (slot); -+ -+ return TRUE; -+} -+ -+static void -+gdm_smartcard_manager_worker_run (GdmSmartcardManagerWorker *worker) -+{ -+ GError *error; -+ -+ -+ error = NULL; -+ -+ while (gdm_smartcard_manager_worker_watch_for_and_process_event (worker, &error)); -+ -+ if (error != NULL) { -+ g_debug ("could not process card event - %s", error->message); -+ g_error_free (error); -+ } -+ -+ gdm_smartcard_manager_worker_free (worker); -+} -+ -+static gboolean -+gdm_smartcard_manager_create_worker (GdmSmartcardManager *manager, -+ gint *worker_fd, -+ GThread **worker_thread) -+{ -+ GdmSmartcardManagerWorker *worker; -+ gint write_fd, read_fd; -+ -+ write_fd = -1; -+ read_fd = -1; -+ if (!gdm_open_pipe (&write_fd, &read_fd)) { -+ return FALSE; -+ } -+ -+ 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; -+} -+ -+#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; -+ g_print ("Re-enabling manager.\n"); -+ -+ 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"); -+ -+ should_exit_on_next_remove = TRUE; -+ -+ return FALSE; -+} -+ -+static void -+on_device_inserted (GdmSmartcardManager *manager, -+ GdmSmartcard *card) -+{ -+ g_print ("smartcard inserted!\n"); -+ g_print ("Please remove it.\n"); -+} -+ -+static void -+on_device_removed (GdmSmartcardManager *manager, -+ GdmSmartcard *card) -+{ -+ g_print ("smartcard removed!\n"); -+ -+ 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); -+ } -+} -+ -+int -+main (int argc, -+ char *argv[]) -+{ -+ 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); -+ -+ 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; -+ } -+ -+ 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; -+ -+ /* Signals */ -+ void (*smartcard_inserted) (GdmSmartcardManager *manager, -+ GdmSmartcard *token); -+ void (*smartcard_removed) (GdmSmartcardManager *manager, -+ GdmSmartcard *token); -+ void (*error) (GdmSmartcardManager *manager, -+ GError *error); -+}; -+ -+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 -+}; -+ -+GType gdm_smartcard_manager_get_type (void) G_GNUC_CONST; -+GQuark gdm_smartcard_manager_error_quark (void) G_GNUC_CONST; -+ -+GdmSmartcardManager *gdm_smartcard_manager_new (const char *module); -+ -+gboolean gdm_smartcard_manager_start (GdmSmartcardManager *manager, -+ GError **error); -+ -+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); -+ -+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..75e4f33 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c -@@ -0,0 +1,167 @@ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "gdm-smartcard-manager.h" -+#include "gdm-smartcard.h" -+ -+#ifndef GDM_SMARTCARDS_CONF -+#define GDM_SMARTCARDS_CONF GDMCONFDIR "/smartcards.conf" -+#endif -+ -+#ifndef GDM_SMARTCARDS_GROUP -+#define GDM_SMARTCARDS_GROUP "Smartcards" -+#endif -+ -+#ifndef GDM_SMARTCARDS_KEY_ENABLED -+#define GDM_SMARTCARDS_KEY_ENABLED "Enabled" -+#endif -+ -+#ifndef GDM_SMARTCARDS_KEY_DRIVER -+#define GDM_SMARTCARDS_KEY_DRIVER "Driver" -+#endif -+ -+static GMainLoop *event_loop; -+static GdmSmartcardManager *manager; -+static int signal_pipe_fds[2] = { -1, -1 }; -+ -+static void -+on_smartcard_event (const char *event_string) -+{ -+ g_debug ("smartcard event '%s' happened", event_string); -+ g_print ("%s", event_string); -+ fflush (stdout); -+} -+ -+static void -+watch_for_smartcards (void) -+{ -+ GError *error; -+ char *driver; -+ GKeyFile *cfg; -+ -+ 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; -+ } -+ -+ 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); -+ } -+ -+ 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; -+ } -+} -+ -+static void -+on_term_signal (int signal_number) -+{ -+ close (signal_pipe_fds[1]); -+ signal_pipe_fds[1] = -1; -+} -+ -+static gboolean -+after_term_signal (GIOChannel *io_channel, -+ GIOCondition condition, -+ gpointer data) -+{ -+ g_main_loop_quit (event_loop); -+ return FALSE; -+} -+ -+static void -+on_debug_message (const char *log_domain, -+ GLogLevelFlags log_level, -+ const char *message, -+ gpointer user_data) -+{ -+ g_printerr ("*** DEBUG: %s\n", message); -+} -+ -+int -+main (int argc, -+ char **argv) -+{ -+ GIOChannel *io_channel; -+ -+ setlocale (LC_ALL, ""); -+ -+ g_type_init (); -+ -+ g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, on_debug_message, NULL); -+ -+ event_loop = g_main_loop_new (NULL, FALSE); -+ -+ watch_for_smartcards (); -+ -+ 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); -+ -+ 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); -+ -+ g_main_loop_run (event_loop); -+ -+ stop_watching_for_smartcards (); -+ -+ 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" -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct _GdmSmartcardPrivate { -+ SECMODModule *module; -+ GdmSmartcardState state; -+ -+ CK_SLOT_ID slot_id; -+ int slot_series; -+ -+ PK11SlotInfo *slot; -+ char *name; -+ -+ CERTCertificate *signing_certificate; -+ CERTCertificate *encryption_certificate; -+}; -+ -+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); -+ -+static PK11SlotInfo *gdm_smartcard_find_slot_from_id (GdmSmartcard *card, -+ int slot_id); -+ -+static PK11SlotInfo *gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, -+ const char *card_name); -+static gboolean gdm_smartcard_fetch_certificates (GdmSmartcard *card); -+ -+#ifndef GDM_SMARTCARD_DEFAULT_SLOT_ID -+#define GDM_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1) -+#endif -+ -+#ifndef GDM_SMARTCARD_DEFAULT_SLOT_SERIES -+#define GDM_SMARTCARD_DEFAULT_SLOT_SERIES -1 -+#endif -+ -+enum { -+ PROP_0 = 0, -+ PROP_NAME, -+ PROP_SLOT_ID, -+ PROP_SLOT_SERIES, -+ PROP_MODULE, -+ NUMBER_OF_PROPERTIES -+}; -+ -+enum { -+ INSERTED, -+ REMOVED, -+ NUMBER_OF_SIGNALS -+}; -+ -+static guint gdm_smartcard_signals[NUMBER_OF_SIGNALS]; -+ -+G_DEFINE_TYPE (GdmSmartcard, gdm_smartcard, G_TYPE_OBJECT); -+ -+static void -+gdm_smartcard_class_init (GdmSmartcardClass *card_class) -+{ -+ GObjectClass *gobject_class; -+ -+ gobject_class = G_OBJECT_CLASS (card_class); -+ -+ gobject_class->finalize = gdm_smartcard_finalize; -+ -+ gdm_smartcard_class_install_signals (card_class); -+ gdm_smartcard_class_install_properties (card_class); -+ -+ g_type_class_add_private (card_class, -+ sizeof (GdmSmartcardPrivate)); -+} -+ -+static void -+gdm_smartcard_class_install_signals (GdmSmartcardClass *card_class) -+{ -+ GObjectClass *object_class; -+ -+ object_class = G_OBJECT_CLASS (card_class); -+ -+ 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); -+ -+ 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_class_install_properties (GdmSmartcardClass *card_class) -+{ -+ 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; -+ -+ 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); -+ -+ 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); -+ -+ 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); -+ -+ 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_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ GdmSmartcard *card = GDM_SMARTCARD (object); -+ -+ switch (prop_id) { -+ case PROP_NAME: -+ gdm_smartcard_set_name (card, g_value_get_string (value)); -+ break; -+ -+ case PROP_SLOT_ID: -+ gdm_smartcard_set_slot_id (card, -+ g_value_get_ulong (value)); -+ break; -+ -+ case PROP_SLOT_SERIES: -+ gdm_smartcard_set_slot_series (card, -+ g_value_get_int (value)); -+ break; -+ -+ case PROP_MODULE: -+ gdm_smartcard_set_module (card, -+ (SECMODModule *) -+ g_value_get_pointer (value)); -+ break; -+ -+ 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; -+} -+ -+GdmSmartcardState -+gdm_smartcard_get_state (GdmSmartcard *card) -+{ -+ return card->priv->state; -+} -+ -+char * -+gdm_smartcard_get_name (GdmSmartcard *card) -+{ -+ return g_strdup (card->priv->name); -+} -+ -+gboolean -+gdm_smartcard_is_login_card (GdmSmartcard *card) -+{ -+ const char *login_card_name; -+ login_card_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME"); -+ -+ if ((login_card_name == NULL) || (card->priv->name == NULL)) { -+ return FALSE; -+ } -+ -+ if (strcmp (card->priv->name, login_card_name) == 0) { -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+static void -+gdm_smartcard_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ GdmSmartcard *card = GDM_SMARTCARD (object); -+ -+ switch (prop_id) { -+ case PROP_NAME: -+ g_value_take_string (value, -+ gdm_smartcard_get_name (card)); -+ break; -+ -+ case PROP_SLOT_ID: -+ g_value_set_ulong (value, -+ (gulong) gdm_smartcard_get_slot_id (card)); -+ break; -+ -+ case PROP_SLOT_SERIES: -+ g_value_set_int (value, -+ gdm_smartcard_get_slot_series (card)); -+ break; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ } -+} -+ -+static void -+gdm_smartcard_set_name (GdmSmartcard *card, -+ const char *name) -+{ -+ if (name == NULL) { -+ return; -+ } -+ -+ if ((card->priv->name == NULL) || -+ (strcmp (card->priv->name, name) != 0)) { -+ g_free (card->priv->name); -+ card->priv->name = g_strdup (name); -+ -+ if (card->priv->slot == NULL) { -+ card->priv->slot = gdm_smartcard_find_slot_from_card_name (card, -+ card->priv->name); -+ -+ if (card->priv->slot != NULL) { -+ int slot_id, slot_series; -+ -+ slot_id = PK11_GetSlotID (card->priv->slot); -+ if (slot_id != card->priv->slot_id) { -+ gdm_smartcard_set_slot_id (card, slot_id); -+ } -+ -+ slot_series = PK11_GetSlotSeries (card->priv->slot); -+ if (slot_series != card->priv->slot_series) { -+ gdm_smartcard_set_slot_series (card, slot_series); -+ } -+ -+ _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_set_slot_id (GdmSmartcard *card, -+ int slot_id) -+{ -+ if (card->priv->slot_id != slot_id) { -+ card->priv->slot_id = slot_id; -+ -+ if (card->priv->slot == NULL) { -+ card->priv->slot = gdm_smartcard_find_slot_from_id (card, -+ card->priv->slot_id); -+ -+ if (card->priv->slot != NULL) { -+ const char *card_name; -+ -+ 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); -+ } -+ -+ _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), "slot-id"); -+ } -+} -+ -+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"); -+ } -+} -+ -+static void -+gdm_smartcard_set_module (GdmSmartcard *card, -+ SECMODModule *module) -+{ -+ gboolean should_notify; -+ -+ if (card->priv->module != module) { -+ should_notify = TRUE; -+ } else { -+ should_notify = FALSE; -+ } -+ -+ if (card->priv->module != NULL) { -+ SECMOD_DestroyModule (card->priv->module); -+ card->priv->module = NULL; -+ } -+ -+ if (module != NULL) { -+ card->priv->module = SECMOD_ReferenceModule (module); -+ } -+ -+ if (should_notify) { -+ g_object_notify (G_OBJECT (card), "module"); -+ } -+} -+ -+int -+gdm_smartcard_get_slot_series (GdmSmartcard *card) -+{ -+ return card->priv->slot_series; -+} -+ -+static void -+gdm_smartcard_init (GdmSmartcard *card) -+{ -+ -+ g_debug ("initializing smartcard "); -+ -+ card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card, -+ GDM_TYPE_SMARTCARD, -+ GdmSmartcardPrivate); -+ -+ if (card->priv->slot != NULL) { -+ card->priv->name = g_strdup (PK11_GetTokenName (card->priv->slot)); -+ } -+} -+ -+static void gdm_smartcard_finalize (GObject *object) -+{ -+ GdmSmartcard *card; -+ GObjectClass *gobject_class; -+ -+ card = GDM_SMARTCARD (object); -+ -+ g_free (card->priv->name); -+ -+ gdm_smartcard_set_module (card, NULL); -+ -+ gobject_class = G_OBJECT_CLASS (gdm_smartcard_parent_class); -+ -+ gobject_class->finalize (object); -+} -+ -+GQuark gdm_smartcard_error_quark (void) -+{ -+ static GQuark error_quark = 0; -+ -+ if (error_quark == 0) { -+ error_quark = g_quark_from_static_string ("gdm-smartcard-error-quark"); -+ } -+ -+ return error_quark; -+} -+ -+GdmSmartcard * -+_gdm_smartcard_new (SECMODModule *module, -+ CK_SLOT_ID slot_id, -+ int slot_series) -+{ -+ GdmSmartcard *card; -+ -+ 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); -+ -+ card = GDM_SMARTCARD (g_object_new (GDM_TYPE_SMARTCARD, -+ "module", module, -+ "slot-id", (gulong) slot_id, -+ "slot-series", slot_series, -+ NULL)); -+ return card; -+} -+ -+GdmSmartcard * -+_gdm_smartcard_new_from_name (SECMODModule *module, -+ const char *name) -+{ -+ GdmSmartcard *card; -+ -+ g_return_val_if_fail (module != NULL, NULL); -+ g_return_val_if_fail (name != NULL, NULL); -+ -+ 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 (); -+ } -+ } -+} -+ -+/* 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; -+ } -+ -+ return password != NULL? PL_strdup (password): NULL; -+} -+ -+gboolean -+gdm_smartcard_unlock (GdmSmartcard *card, -+ const char *password) -+{ -+ SECStatus status; -+ -+ PK11_SetPasswordFunc ((PK11PasswordFunc) gdm_smartcard_password_handler); -+ -+ /* we pass PR_TRUE to load certificates -+ */ -+ status = PK11_Authenticate (card->priv->slot, PR_TRUE, (gpointer) password); -+ -+ if (status != SECSuccess) { -+ g_debug ("could not unlock card - %d", status); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+static PK11SlotInfo * -+gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, -+ const char *card_name) -+{ -+ int i; -+ -+ for (i = 0; i < card->priv->module->slotCount; i++) { -+ const char *slot_card_name; -+ -+ slot_card_name = PK11_GetTokenName (card->priv->module->slots[i]); -+ -+ if ((slot_card_name != NULL) && -+ (strcmp (slot_card_name, card_name) == 0)) { -+ return card->priv->module->slots[i]; -+ } -+ } -+ -+ return NULL; -+} -+ -+static PK11SlotInfo * -+gdm_smartcard_find_slot_from_id (GdmSmartcard *card, -+ int slot_id) -+{ -+ int i; -+ -+ 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]; -+ } -+ } -+ -+ return NULL; -+} -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 -+ -+#include -+ -+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; -+ -+typedef struct _GdmSmartcardRequest GdmSmartcardRequest; -+ -+struct _GdmSmartcard { -+ GObject parent; -+ -+ /*< private > */ -+ GdmSmartcardPrivate *priv; -+}; -+ -+struct _GdmSmartcardClass { -+ GObjectClass parent_class; -+ -+ void (* inserted) (GdmSmartcard *card); -+ void (* removed) (GdmSmartcard *card); -+}; -+ -+enum _GdmSmartcardError { -+ GDM_SMARTCARD_ERROR_GENERIC = 0, -+}; -+ -+enum _GdmSmartcardState { -+ GDM_SMARTCARD_STATE_INSERTED = 0, -+ GDM_SMARTCARD_STATE_REMOVED, -+}; -+ -+GType gdm_smartcard_get_type (void) G_GNUC_CONST; -+GQuark gdm_smartcard_error_quark (void) G_GNUC_CONST; -+ -+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); -+ -+char *gdm_smartcard_get_name (GdmSmartcard *card); -+gboolean gdm_smartcard_is_login_card (GdmSmartcard *card); -+ -+gboolean gdm_smartcard_unlock (GdmSmartcard *card, -+ const char *password); -+ -+/* don't under any circumstances call these functions */ -+#ifdef GDM_SMARTCARD_ENABLE_INTERNAL_API -+ -+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); -+ -+void _gdm_smartcard_set_state (GdmSmartcard *card, -+ GdmSmartcardState state); -+#endif -+ -+G_END_DECLS -+#endif /* GDM_SMARTCARD_H */ -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam b/gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam -new file mode 100644 -index 0000000..3c803f7 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam -@@ -0,0 +1,18 @@ -+# Sample PAM file for doing smartcard authentication. -+# Distros should replace this with what makes sense for them. -+auth required pam_env.so -+auth [success=done ignore=ignore default=die] pam_pkcs11.so wait_for_card -+auth requisite pam_succeed_if.so uid >= 500 quiet -+auth required pam_deny.so -+ -+account required pam_unix.so -+account sufficient pam_localuser.so -+account sufficient pam_succeed_if.so uid < 500 quiet -+account required pam_permit.so -+ -+password optional pam_pkcs11.so -+password requisite pam_cracklib.so try_first_pass retry=3 type= -+ -+session optional pam_keyinit.so revoke -+session required pam_limits.so -+session required pam_unix.so -diff --git a/gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am b/gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am -new file mode 100644 -index 0000000..661d687 ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am -@@ -0,0 +1,5 @@ -+iconsdir = $(datadir)/icons/hicolor/16x16/apps -+ -+icons_DATA = gdm-smartcard.png -+ -+EXTRA_DIST = $(icons_DATA) -diff --git a/gui/simple-greeter/plugins/smartcard/icons/16x16/gdm-smartcard.png b/gui/simple-greeter/plugins/smartcard/icons/16x16/gdm-smartcard.png -new file mode 100644 -index 0000000000000000000000000000000000000000..0112af1b8d891ad312f9fcc3bf6074df3e003359 -GIT binary patch -literal 871 -zcmV-t1DO1YP)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iXJ- -z6cQQvze?o*000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0008QNkl25h)mRS()F5IML|LeofZ5$Phq#SvEXn3)x9QHz&V1jD*OHUa=lnh|yoWc& -zo1+2m0}628RN4)kP9zfJhGEoz$TZEX{|)Htgf`%?ZQIABl!txa-_X&~;rI9Vo88^r -z1;L|^!4>6dV71>-}NC2_0X(TUE+qIrDYmT)AaSb -zqQSwzu&1X-?Cbi7rG`eaTxYT75y*%ZE6&r0<4pW|3Ey2K2m+~;x&Y(=rCFBMd{LP< -ze!f%2@g%ktXZzbJvY9kitjV=&V+;=uGc+_rtyZH_sW3S?$@KK}cfeU)DJ6Ufjwku* -z#Jf~p{6)1o%ag||*tX5+=qR~dj#8<_+}s>O2(sBM#bWVH7>3^p-}m(}(unH3ls_kY}+QE&oeeQMlzYCTCI{!r;|XJ05A-lFao6%Gcz-k%VnBP$+`1i -z^JL;6j^og}#l)>&;?s|J5k(Q5do}@lp##MA7)pgK{$tR(^AIgbgR>VO(YA9dDYL-` -zsh`;Y%6?x&ziM4udm5K2(B3uPvQ%dL5Nt5QX;$Nu&Y|(&dU|=Ac -znwoM8g@R?8=8}~1uJ8MIfoDQ+^ZMlj@4UAwMAl}h&MMZb@Tk<}`x}kRnq^tHG);3I -x$GHPM0G_Y=$2Q;_pbrQE4|oMk0zdM9c?}H%H!P_~w{rjh002ovPDHLkV1ieHj1>R? - -literal 0 -HcmV?d00001 - -diff --git a/gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am b/gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am -new file mode 100644 -index 0000000..e79d85b ---- /dev/null -+++ b/gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am -@@ -0,0 +1,5 @@ -+iconsdir = $(datadir)/icons/hicolor/48x48/apps -+ -+icons_DATA = gdm-smartcard.png -+ -+EXTRA_DIST = $(icons_DATA) -diff --git a/gui/simple-greeter/plugins/smartcard/icons/48x48/gdm-smartcard.png b/gui/simple-greeter/plugins/smartcard/icons/48x48/gdm-smartcard.png -new file mode 100644 -index 0000000000000000000000000000000000000000..35d5578d9ec83ae6b17aa7230c1b4df34e13e2cc -GIT binary patch -literal 4202 -zcmV-w5S8zVP)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iXJ- -z6calzC#000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000lgNkl2aFf(X>ozT5 -zC$5aZk)aA|*R=Bt;5o9kwWGLxmKt<-N{vG7>41KQobz$)Btw?d%RxnyB)`A*IJ8UFsQn_yUTz( -zIywx~G;av_`rnpip|uYDs!S+YWQjXH9?w0l>%LQKZTS6uy>sVI(cRrmPfriG+;WTI -z@p#@6@Iu;UXgp0zq>6^HuiPI91TYLkD5ZWW0{DTQz#hx8?o~?Nrj#^8Cli339gNwym|C9-PB*HI@kv?`fqW>?@BILKy#D -z4S0a;tuC6Y+ySqg!7UTBYZx?>Q|Av62(oD=`2?xClT$$(W&^%g! -zTIQ6mo}a-m1X^pf7EI3NXk4{4pHeFHiwMvG>@`jEE+8hQ^c#kuJ3Bk+>FE)%Sd1Mz -zc8Fjw_@?GCIhSXAHcNDspBGO};7E<_NQ5YWEH$6Uz?B-Qba9Tt=f>65#Ugb-f=#OBSLRV)@WcJJQJ&Ye3&I2?Xcz^>Gsxim*Q?-KBt3|v`2Duq&D7y_j< -z0x%8GT2LLZXlt%!eN&J%4OM6j-+g(6iP&p8JBMy -zy3F*%&q)02ENiPXEG{l``t)fA1_rW9sr5kOEj1ve^tZRS)6mec0`UBz&A;|tBkxE8 -zJ`-DNTvuTTQMPBVWuO4R$D}nHpshK?+Qt9@f2Dh6vsn^}1XEK}BoYa1+on2P$8&%6 -zXIvfZ$23jq>+2Chkjv#zN>u?Pz<%H{Erluyw#>N;L8e(*Gv`DLkM=6Eh@8_O-?!oKzic_afJqug{j#UWY -zI1WMx{9Y4}DUeEFnSyt9HPNv?jFgh;>FJ6cc3rnJpQx!J5{ZgwtW?Zo48;_*12 -z``qW)zI{6nKKLN5t*wlWjnUuVPdc4OO3Cu*tCS+0PNS5ftE-FQ;bCK9V&ZR$v@chf -zkjFCFxTc!(L-W*!{dBgi;_~Io^!N9#0K96|Dx%RSjg5^&qfr8ZKzY%*xj8OgyvW4F -z1XEK}>x86!T9_QS-bIi`plFQ}rcswhZN^6ajlEuYEVzC(e_wU~V -z+zY(8LIVqFhs)QJ0IY2cAcP>F&!d#0zP_GlG)g2Ap|P=%QWSPwm+9$g;_-OdoE*og -z01*m>XliQW%9Sf@-MW=syLK@>JxwZ=VrXcH^XJdAdi838!626|T_TxG(%9I@=FOYS -zb7V3ZJRT2`NQ6Wp@!QJRH14t>!X0sePaDb|+Dtta4 -zufP5}>(;HKy}g}yJWeK)K}yM*HET#D5_gq-z%nx;u(VMPRx)Uz}P+MC|E|(*h%P~DYjo0fXolcX@W|^3n;K?VS -z=PjT#i5aQW?mE5b2T$nTAnL5%hH+mw(UYawHN7CMG7BoSbBK -zcDC#XmSxf2-d=ux&mFsn4_)CepZOr~-DB`-zg6b=QkMFm4`zAa9rIv#i`l6cfsfvw -z_z8tV<+xB{xngSqhOH8x3L#k27{o9{kzJNdD3i&Q!A?v}Fh4)Pf>N8BnrLorrmd~5 -zBC`MZ%vp~A^A0vdhpDPHkW!Sv=ks~A)_B7YQoHF6K%;R$=YcHQS6;()T|6F7S%CJ< -zbqo!K7#mys4zSHC0Te=DI}%+K&@JZcGcz+BJb17yxe$W-`uZ~9Xf#@3GS_Qtdshpd -zwL$D_<2Z{M=10zx+0coUlJW6zgb*Yyo<{4fMa?VFE?|@Y=}Y|0muHAXA{a&?n~etY -z9P4|4p56OfCnvLCu!Imf*L4eElX(zJ0YnHvFc_q*t*y-E(P;FBEOY(uGv_CfN@Iyd -zG=jRG)y$q8NID7Ow6H`@eTVF+6OPB|KYcpCU3TtbPMgo#YKK*`%esqSRvqNln -zpqi@2ChmQx6*WK2XMblkk3SRtJqyT}R35DhAP@)vj$3fzKp?=LJ$v31aC~^4{x=eA -zXj#R{fia%>`ybP`HcWiDU}lTM)ujQ{++^d8y6n0%1+77R?~CGDRgIki0dHM>MW1&~E51#8(B?Z)b2G@9BjiR-q4GA` -z1ub=fK}=Ct*j6}6g`JexNsUf|*Y6{37kt7}N;%nV79j+wjLp=14y`qgT5{rlI`BH5 -z{mKvd{1e@L^!^UAIhUc)1+HFO;Fhh8oWDGcl$uX|^j7xn*+4^G6}2^f9{+F`vDn{L -z20p7A?c0LsjY3r&qTw=za|xYyakFs#oWrS~*yucTzr#yQorzb0vK2C~srG4v)|3pQ -zM5AR5h>{xR(mC-vFAnngC%W-i2J7yu1oZVkzl;0s*uX+6PhHsmU!P$`9z1I?gdc^x -zt`9mkTYUR_S^n|gGW_BFK_3555VOj_sxol18q=#;KFm@|=@P?K`7AcIgt;&@%krwE -zWg5KNKgNqM4*{_6W4G~}_ipC-e}A2u*41JfVg>lwWR9!jDW>ML#nMs{q)Z@$4sA?5`wY$vF6CHez{E%@3`>BkDOHUut+h_2QsozaHc|NQ$fdzg?~8Hx=udg_ -z(OcQlR#*Q2Q;*%gl=Cmz42>tbG(5-E@f1>O6q; -zX-_O5v;07EtbcS_^-VG|xmachDJ7OAFfh5jGlJ`CydHyHoz3{XW -z{(dz$IAT2ho_d-#6|#4&hB1V1g$WsgB6x$QI*YsCwN&|#S%sTbNE@USNTtgHIC@#} -zG8FJ)ngXp0H6j3yX`s=3WJoXpKFL!MA(BVttUA6Kx!+>2od~AOws2nU#N~T`3Nv9y~ -zm^h|M`!<7cBlMoN0Zv;$_WFsm)?B!7f!^L;`uh5GZ*Q+kCX;57$_9&od$ratYprK~ -z&O-86fXE$>&V1^7U-zHPRK--Qpu^f!9}X+|e<~ -z6MvoI@K5qN;7er_x_I#-M~@z*udk0IM~=vunHdwn -+ -+ -+ -+ 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.3.3 - - -From 6a736eae4072d7779f333fd4114481317a864523 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 23 Feb 2009 17:57:06 -0500 -Subject: [PATCH 23/38] 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 6ef3d00..c0283f2 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -2307,9 +2307,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 { -@@ -2320,6 +2317,16 @@ gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, - GDM_TASK (extension)); - - service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (extension)); -+ -+ 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_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); -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); -+} -+ - 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 b20dd65..7aa99e7 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; -+} -+ - 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; -+} -+ - 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 632ee2d..ed19e62 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; -+} -+ - 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.3.3 - - -From 9f7550eaf2a02a0b7f48e81f4e2ced1aed13337f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 24 Feb 2009 15:12:35 -0500 -Subject: [PATCH 24/38] 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 | 53 +++++++++++++------- - gui/simple-greeter/gdm-user-chooser-widget.c | 23 ++++++++- - .../fingerprint/gdm-fingerprint-extension.c | 2 - - 3 files changed, 56 insertions(+), 22 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index c0283f2..e5c5e24 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -1438,29 +1438,49 @@ 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); -+ -+ 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); -+ -+ switch_mode (login_window, MODE_AUTHENTICATION); -+} -+ -+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) { -+ g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); -+ 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)); -+ g_debug ("GdmGreeterLoginWindow: item chosen '%s'", item_id); - -- if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) { -+ 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); -- } 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_debug ("GdmGreeterLoginWindow: Starting auto login"); - g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, - login_window->priv->timed_login_username); - -@@ -1470,16 +1490,11 @@ 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); - } - -+ g_debug ("GdmGreeterLoginWindow: Switching to shrunken authentication mode"); - switch_mode (login_window, MODE_AUTHENTICATION); -- -- g_free (user_name); - } - - static void -@@ -1768,7 +1783,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 4410a02..a615ee5 100644 ---- a/gui/simple-greeter/gdm-user-chooser-widget.c -+++ b/gui/simple-greeter/gdm-user-chooser-widget.c -@@ -267,9 +267,30 @@ 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; -+ - 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; -+ } -+ -+ gdm_chooser_widget_lookup_item (GDM_CHOOSER_WIDGET (widget), active_item_id, -+ NULL, NULL, NULL, NULL, NULL, -+ &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); -+ -+ 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 7aa99e7..316ef46 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.3.3 - - -From a1598f4fb8fdd16314c3172a3fed7550bc9027ff Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 27 Feb 2009 15:44:13 -0500 -Subject: [PATCH 25/38] Initiate smart card auth when clicking on it in list - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 24 ++++++++++++++++++++ - .../plugins/smartcard/gdm-smartcard-extension.c | 2 +- - 2 files changed, 25 insertions(+), 1 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index e5c5e24..6712cf8 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -838,6 +838,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)); -@@ -1458,6 +1459,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)); -@@ -1491,6 +1493,28 @@ 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; -+ -+ 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); -+ g_free (item_id); -+ -+ gtk_widget_set_sensitive (login_window->priv->conversation_list, FALSE); - } - - g_debug ("GdmGreeterLoginWindow: Switching to shrunken authentication mode"); -diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c -index ed19e62..d3641ba 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.3.3 - - -From 5abe595674643baf0e7c811bf39adbd717910c3f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 11:10:28 -0500 -Subject: [PATCH 26/38] Only show task list if user is selected - ---- - gui/simple-greeter/gdm-greeter-login-window.c | 52 +++++++++++++++++-------- - gui/simple-greeter/gdm-task-list.c | 11 ++++- - 2 files changed, 44 insertions(+), 19 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index 6712cf8..c7c579b 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -102,7 +102,8 @@ - - enum { - MODE_SELECTION = 0, -- MODE_AUTHENTICATION -+ MODE_SINGLE_AUTHENTICATION, -+ MODE_MULTIPLE_AUTHENTICATION, - }; - - enum { -@@ -621,7 +622,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 (); -@@ -649,6 +651,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); -@@ -678,6 +681,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); -@@ -687,13 +692,29 @@ 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); - show_widget (login_window, "cancel-button", TRUE); - show_widget (login_window, "shutdown-button", FALSE); - 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); -+ -+ 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: -@@ -1452,7 +1473,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 -@@ -1481,6 +1502,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, -@@ -1493,6 +1516,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; - -@@ -1507,18 +1532,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); -+ } - } - - static void -@@ -1831,7 +1855,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);*/ -@@ -1870,7 +1893,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)); - } - } -@@ -2346,12 +2370,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.3.3 - - -From 071d53902b55c4ac74553040703009d25ab770f0 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 13:53:34 -0500 -Subject: [PATCH 27/38] 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 | 110 ++++++++++++++++--------- - 1 files changed, 70 insertions(+), 40 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index c7c579b..6c625ba 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -1435,6 +1435,17 @@ begin_task_verification (GdmTaskList *task_list, - return FALSE; - } - -+static void -+begin_verification (GdmGreeterLoginWindow *login_window) -+{ -+ 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); -+} -+ - static gboolean - begin_task_verification_for_selected_user (GdmTaskList *task_list, - GdmTask *task, -@@ -1460,6 +1471,15 @@ begin_task_verification_for_selected_user (GdmTaskList *task_list, - } - - 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) - { -@@ -1468,15 +1488,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) -+{ -+ 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_SINGLE_AUTHENTICATION); -+} -+ -+static void -+begin_single_service_verification (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); -+ -+ 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); -+ -+ 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); -+} -+ -+static void - on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - GdmGreeterLoginWindow *login_window) - { -@@ -1495,53 +1555,23 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, - item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (user_chooser)); - g_debug ("GdmGreeterLoginWindow: item chosen '%s'", item_id); - -+ g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED], -+ 0, 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); - -- 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.3.3 - - -From ed50184115bb835c89bc0492e2a74c9cc6095b0b Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 13:57:34 -0500 -Subject: [PATCH 28/38] 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 6c625ba..b04549f 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -810,6 +810,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; -+ -+ 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, -@@ -915,10 +929,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))) { -@@ -947,10 +958,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)); -@@ -1018,10 +1026,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), -@@ -1042,10 +1047,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), -@@ -1147,10 +1149,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); -+ -+ task = find_task_with_service_name (login_window, service_name); - - if (task != NULL) { - gdm_conversation_ask_question (GDM_CONVERSATION (task), -@@ -1178,10 +1178,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), -@@ -1515,10 +1512,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.3.3 - - -From a80bfcb439d7cdd9ae1c719c5197f993c4062995 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 15:23:51 -0500 -Subject: [PATCH 29/38] 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 b04549f..4256e1f 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -102,8 +102,7 @@ - - enum { - MODE_SELECTION = 0, -- MODE_SINGLE_AUTHENTICATION, -- MODE_MULTIPLE_AUTHENTICATION, -+ MODE_AUTHENTICATION - }; - - enum { -@@ -622,8 +621,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 (); -@@ -682,7 +680,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); -@@ -692,8 +689,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); -@@ -707,14 +703,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: -@@ -1440,7 +1428,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 -@@ -1487,7 +1475,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 -@@ -1503,7 +1491,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); -+} -+ -+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 -@@ -1518,15 +1529,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); -+ - /* 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); -+ - g_object_unref (task); - } - -@@ -1917,8 +1931,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.3.3 - - -From 60c4b08b34f72bfa19509f17785ce570426f5cde Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 2 Mar 2009 17:09:16 -0500 -Subject: [PATCH 30/38] 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 4256e1f..add0393 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -2234,7 +2234,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) -@@ -2245,7 +2245,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; -+ } -+ -+ /* 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), -@@ -2253,6 +2259,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); - } -+ -+ 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 -+ -+gboolean - gdm_conversation_choose_user (GdmConversation *conversation, - const char *username) - { -- g_signal_emit (conversation, signals [USER_CHOSEN], 0, username); -+ gboolean was_chosen; -+ -+ was_chosen = FALSE; -+ -+ g_signal_emit (conversation, signals [USER_CHOSEN], 0, username, &was_chosen); -+ -+ 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 d3641ba..73e0f84 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); -- } -+ } -+ -+ if (extension->priv->select_when_ready) { -+ if (gdm_conversation_choose_user (GDM_CONVERSATION (extension), -+ PAMSERVICENAME)) { -+ extension->priv->select_when_ready = FALSE; -+ } -+ } - } - - char * --- -1.6.3.3 - - -From be8d9a5363300545f7ea51682ff6e1c17e3fdf26 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 13 Apr 2009 14:19:50 -0400 -Subject: [PATCH 31/38] reset all conversations if password conversation fails - -This is a temporary hack until we store plugin policy in -gconf. ---- - gui/simple-greeter/gdm-greeter-login-window.c | 10 ++++++++++ - 1 files changed, 10 insertions(+), 0 deletions(-) - -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index add0393..9613695 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -946,6 +946,16 @@ gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_wind - - g_debug ("GdmGreeterLoginWindow: conversation '%s' has stopped", service_name); - -+ /* If the password conversation failed, then start over -+ * -+ * FIXME: we need to get this policy out of the source code -+ */ -+ if (strcmp (service_name, "gdm-password") == 0) { -+ g_debug ("GdmGreeterLoginWindow: main conversation failed, starting over"); -+ restart_conversations (login_window); -+ return TRUE; -+ } -+ - task = find_task_with_service_name (login_window, service_name); - - if (task != NULL) { --- -1.6.3.3 - - -From 10530c87e295f3ba83e16e75763217818480f224 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 21 Apr 2009 10:25:18 -0400 -Subject: [PATCH 32/38] When one PAM conversation wins, stop the others - -This doesn't work yet, it's still in progress code. ---- - daemon/gdm-session-direct.c | 64 ++++++++++++++++++++++++++++++------------- - daemon/gdm-simple-slave.c | 2 +- - 2 files changed, 46 insertions(+), 20 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index c189f98..e63e453 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -2269,6 +2269,40 @@ gdm_session_direct_open_session (GdmSession *session, - } - - static void -+stop_all_other_conversations (GdmSessionDirect *session, -+ GdmSessionConversation *conversation_to_keep) -+{ -+ GHashTableIter iter; -+ gpointer key, value; -+ -+ if (session->priv->conversations == NULL) { -+ return; -+ } -+ -+ if (conversation_to_keep == NULL) { -+ g_debug ("GdmSessionDirect: Stopping all conversations"); -+ } else { -+ g_debug ("GdmSessionDirect: Stopping all conversations " -+ "except for %s", conversation_to_keep->service_name); -+ } -+ -+ 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 == conversation_to_keep) { -+ continue; -+ } -+ -+ stop_conversation (conversation); -+ } -+ -+ g_hash_table_remove_all (session->priv->conversations); -+} -+ -+static void - gdm_session_direct_start_session (GdmSession *session, - const char *service_name) - { -@@ -2280,12 +2314,20 @@ gdm_session_direct_start_session (GdmSession *session, - g_return_if_fail (session != NULL); - g_return_if_fail (impl->priv->is_running == FALSE); - -+ conversation = find_conversation_by_name (impl, service_name); -+ -+ if (conversation == NULL) { -+ g_warning ("GdmSessionDirect: Tried to start session of " -+ "nonexistent conversation %s", service_name); -+ return; -+ } -+ -+ stop_all_other_conversations (impl, conversation); -+ - command = get_session_command (impl); - 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, conversation); - -@@ -2296,23 +2338,7 @@ gdm_session_direct_start_session (GdmSession *session, - 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); -+ stop_all_other_conversations (session, NULL); - } - - static void -diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c -index 337718b..63ea82c 100644 ---- a/daemon/gdm-simple-slave.c -+++ b/daemon/gdm-simple-slave.c -@@ -575,7 +575,7 @@ on_session_conversation_stopped (GdmSession *session, - gboolean res; - g_debug ("GdmSimpleSlave: conversation stopped"); - -- if (slave->priv->greeter_server != NULL) { -+ if (slave->priv->greeter != NULL) { - res = gdm_greeter_server_conversation_stopped (slave->priv->greeter_server, - service_name); - if (! res) { --- -1.6.3.3 - - -From ba40486a7e8a7be80b16a89d8a0f7fd264ddfe21 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 21 Apr 2009 15:30:28 -0400 -Subject: [PATCH 33/38] When one PAM conv. wins, actually stop the others - -We weren't properly keeping the winning conversation -around in the previous commit ---- - daemon/gdm-session-direct.c | 13 ++++++++++--- - 1 files changed, 10 insertions(+), 3 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index e63e453..2899ea2 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -2293,13 +2293,20 @@ stop_all_other_conversations (GdmSessionDirect *session, - conversation = (GdmSessionConversation *) value; - - if (conversation == conversation_to_keep) { -- continue; -+ g_hash_table_iter_steal (&iter); -+ g_free (key); -+ } else { -+ stop_conversation (conversation); - } -- -- stop_conversation (conversation); - } - - g_hash_table_remove_all (session->priv->conversations); -+ -+ if (conversation_to_keep != NULL) { -+ g_hash_table_insert (session->priv->conversations, -+ g_strdup (conversation_to_keep->service_name), -+ conversation_to_keep); -+ } - } - - static void --- -1.6.3.3 - - -From c4ebe26db9c963d587694d0197e145e086ec43ca Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 13 May 2009 13:43:33 -0400 -Subject: [PATCH 34/38] Don't send auth-failed when worker dies - -Authentication hasn't failed, it just got aborted before it -could. This prevents a crash that happens when switching -runlevels while the login screen is up. ---- - daemon/gdm-session-direct.c | 10 ++-------- - 1 files changed, 2 insertions(+), 8 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 2899ea2..689e4cf 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -87,7 +87,6 @@ struct _GdmSessionDirectPrivate - - GList *pending_connections; - -- guint32 is_authenticated : 1; - guint32 is_running : 1; - GPid session_pid; - -@@ -1761,9 +1760,7 @@ worker_exited (GdmSessionWorkerJob *job, - g_debug ("GdmSessionDirect: Worker job exited: %d", code); - - g_object_ref (conversation); -- if (!conversation->session->priv->is_authenticated) { -- _gdm_session_authentication_failed (GDM_SESSION (conversation->session), NULL); -- } else if (conversation->session->priv->is_running) { -+ if (conversation->session->priv->is_running) { - _gdm_session_session_exited (GDM_SESSION (conversation->session), code); - } - -@@ -1781,9 +1778,7 @@ worker_died (GdmSessionWorkerJob *job, - g_debug ("GdmSessionDirect: Worker job died: %d", signum); - - g_object_ref (conversation); -- if (!conversation->session->priv->is_authenticated) { -- _gdm_session_authentication_failed (GDM_SESSION (conversation->session), NULL); -- } else if (conversation->session->priv->is_running) { -+ if (conversation->session->priv->is_running) { - _gdm_session_session_died (GDM_SESSION (conversation->session), signum); - } - -@@ -2398,7 +2393,6 @@ gdm_session_direct_close (GdmSession *session) - - g_hash_table_remove_all (impl->priv->environment); - -- impl->priv->is_authenticated = FALSE; - impl->priv->is_running = FALSE; - } - --- -1.6.3.3 - - -From 68384fcc0d1dfb5b451d4be8136959a037c6c2a6 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 16 Jun 2009 08:49:05 -0400 -Subject: [PATCH 35/38] Drop bogus conversation = NULL line - -cancel_pending_query would set conversation to NULL -immediately before trying to use the conversation. - -I probably introduced this bug when converting the -code over to work in terms of multiple conversation -objects instead of one conversation per session. - -Spotted by Michael Young: - -https://bugzilla.redhat.com/show_bug.cgi?id=499489#c9 ---- - daemon/gdm-session-direct.c | 1 - - 1 files changed, 0 insertions(+), 1 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 689e4cf..7528ae6 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -789,7 +789,6 @@ cancel_pending_query (GdmSessionConversation *conversation) - 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); - --- -1.6.3.3 - - -From 0daaf4814f9f78be4e85bef7f181426c06c5349c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 20 Jul 2009 11:06:59 -0400 -Subject: [PATCH 36/38] Drop is_authenticated flag in session - -It's not used anymore, so no reason to set it. ---- - daemon/gdm-session-direct.c | 2 -- - 1 files changed, 0 insertions(+), 2 deletions(-) - -diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c -index 7528ae6..4b08da3 100644 ---- a/daemon/gdm-session-direct.c -+++ b/daemon/gdm-session-direct.c -@@ -377,7 +377,6 @@ gdm_session_direct_handle_authenticated (GdmSessionDirect *session, - dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - -- session->priv->is_authenticated = TRUE; - _gdm_session_authenticated (GDM_SESSION (session), conversation->service_name); - - return DBUS_HANDLER_RESULT_HANDLED; -@@ -405,7 +404,6 @@ gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session, - - g_debug ("GdmSessionDirect: Emitting 'authentication-failed' signal"); - -- session->priv->is_authenticated = FALSE; - _gdm_session_authentication_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; --- -1.6.3.3 - - -From 790263cf9b8cab0bf3dc39c29e814d8c9034d802 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 20 Jul 2009 12:56:08 -0400 -Subject: [PATCH 37/38] Only start session if in SESSION_OPEN state no accredited state - -The state machine check wasn't quite right in light of the new -SESSION_OPEN state ---- - daemon/gdm-session-worker.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c -index 1b1f14b..4ebde84 100644 ---- a/daemon/gdm-session-worker.c -+++ b/daemon/gdm-session-worker.c -@@ -2317,7 +2317,7 @@ on_start_program (GdmSessionWorker *worker, - const char *text; - dbus_bool_t res; - -- if (worker->priv->state != GDM_SESSION_WORKER_STATE_ACCREDITED) { -+ if (worker->priv->state != GDM_SESSION_WORKER_STATE_SESSION_OPENED) { - g_debug ("GdmSessionWorker: ignoring spurious start program while in state %s", get_state_name (worker->priv->state)); - return; - } --- -1.6.3.3 - - -From 49d62227bd6eb4a802b89feb937e347be38dc116 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 24 Jul 2009 14:41:48 -0400 -Subject: [PATCH 38/38] KILL pam stack instead of TERM pam stack - -Some PAM modules are really slow to shut down. -We need to handle them being slow to shut down better, -(by not blocking login on them shutting down etc), but -in the mean time force them to die immediately. - -This is a temporary hack. ---- - 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 0327d77..d99b8a5 100644 ---- a/daemon/gdm-session-worker-job.c -+++ b/daemon/gdm-session-worker-job.c -@@ -320,7 +320,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); -+ res = gdm_signal_pid (session_worker_job->priv->pid, SIGKILL); - - if (res < 0) { - g_warning ("Unable to kill session worker process"); --- -1.6.3.3 - diff --git a/gdm-2.28.0-use-devicekit-power.patch b/gdm-2.28.0-use-devicekit-power.patch deleted file mode 100644 index dfd869b..0000000 --- a/gdm-2.28.0-use-devicekit-power.patch +++ /dev/null @@ -1,186 +0,0 @@ -From aa132a553b871a19a8d23fe8e9d93f736f2a4faf Mon Sep 17 00:00:00 2001 -From: Richard Hughes -Date: Mon, 28 Sep 2009 09:14:33 +0100 -Subject: [PATCH] Convert gdm from using gnome-power-manager to DeviceKit-power - ---- - configure.ac | 7 ++ - gui/simple-greeter/Makefile.am | 4 + - gui/simple-greeter/gdm-greeter-login-window.c | 84 ++++++------------------- - 3 files changed, 31 insertions(+), 64 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 756890a..2cae1cf 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -51,6 +51,7 @@ LIBXKLAVIER_REQUIRED_VERSION=4.0 - LIBCANBERRA_GTK_REQUIRED_VERSION=0.4 - #FONTCONFIG_REQUIRED_VERSION=2.6.0 - FONTCONFIG_REQUIRED_VERSION=2.5.0 -+DEVKIT_POWER_REQUIRED_VERSION=008 - - EXTRA_COMPILE_WARNINGS(yes) - -@@ -103,6 +104,12 @@ PKG_CHECK_MODULES(GCONF, - AC_SUBST(GCONF_CFLAGS) - AC_SUBST(GCONF_LIBS) - -+PKG_CHECK_MODULES(DEVKIT_POWER, -+ devkit-power-gobject >= $DEVKIT_POWER_REQUIRED_VERSION -+) -+AC_SUBST(DEVKIT_POWER_CFLAGS) -+AC_SUBST(DEVKIT_POWER_LIBS) -+ - PKG_CHECK_MODULES(SIMPLE_GREETER, - dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION - gtk+-2.0 >= $GTK_REQUIRED_VERSION -diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am -index 8c9ae46..4c06bc3 100644 ---- a/gui/simple-greeter/Makefile.am -+++ b/gui/simple-greeter/Makefile.am -@@ -18,6 +18,8 @@ AM_CPPFLAGS = \ - -DSBINDIR=\""$(sbindir)"\" \ - -DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \ - -DAT_SPI_REGISTRYD_DIR="\"$(AT_SPI_REGISTRYD_DIR)\"" \ -+ $(DEVKIT_POWER_CFLAGS) \ -+ -DI_KNOW_THE_DEVICEKIT_POWER_API_IS_SUBJECT_TO_CHANGE \ - $(DISABLE_DEPRECATED_CFLAGS) \ - $(GTK_CFLAGS) \ - $(SIMPLE_GREETER_CFLAGS) \ -@@ -90,6 +92,7 @@ test_greeter_login_window_LDADD = \ - libgdmuser.la \ - $(COMMON_LIBS) \ - $(SIMPLE_GREETER_LIBS) \ -+ $(DEVKIT_POWER_LIBS) \ - $(RBAC_LIBS) \ - $(NULL) - -@@ -324,6 +327,7 @@ gdm_simple_greeter_LDADD = \ - $(SIMPLE_GREETER_LIBS) \ - $(RBAC_LIBS) \ - $(LIBXKLAVIER_LIBS) \ -+ $(DEVKIT_POWER_LIBS) \ - $(NULL) - - gladedir = $(pkgdatadir) -diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c -index c7ea5d6..7d4ef83 100644 ---- a/gui/simple-greeter/gdm-greeter-login-window.c -+++ b/gui/simple-greeter/gdm-greeter-login-window.c -@@ -56,6 +56,8 @@ - #include - #include - -+#include -+ - #include "gdm-settings-client.h" - #include "gdm-settings-keys.h" - #include "gdm-profile.h" -@@ -79,10 +81,6 @@ - #define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat" - #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" - --#define GPM_DBUS_NAME "org.freedesktop.PowerManagement" --#define GPM_DBUS_PATH "/org/freedesktop/PowerManagement" --#define GPM_DBUS_INTERFACE "org.freedesktop.PowerManagement" -- - #define GLADE_XML_FILE "gdm-greeter-login-window.glade" - - #define KEY_GREETER_DIR "/apps/gdm/simple-greeter" -@@ -480,40 +478,15 @@ adjust_other_login_visibility(GdmGreeterLoginWindow *login_window) - static gboolean - can_suspend (GdmGreeterLoginWindow *login_window) - { -- DBusGConnection *connection; -- DBusGProxy *proxy; -- GError *error; -- gboolean ret; -- gboolean res; -- -- error = NULL; -- connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); -- if (error != NULL) { -- g_warning ("Couldn't connect to power manager: %s", error->message); -- g_error_free (error); -- return FALSE; -- } -- proxy = dbus_g_proxy_new_for_name (connection, -- GPM_DBUS_NAME, -- GPM_DBUS_PATH, -- GPM_DBUS_INTERFACE); -- ret = FALSE; -- -- res = dbus_g_proxy_call (proxy, "CanSuspend", -- &error, -- G_TYPE_INVALID, -- G_TYPE_BOOLEAN, -- &ret, -- G_TYPE_INVALID); -- if (! res) { -- if (error != NULL) { -- g_warning ("Could not ask power manager if user can suspend: %s", -- error->message); -- g_error_free (error); -- } -- ret = FALSE; -- } -+ gboolean ret; -+ DkpClient *dkp_client; - -+ /* use DeviceKit-power to get data */ -+ dkp_client = dkp_client_new (); -+ g_object_get (dkp_client, -+ "can-suspend", &ret, -+ NULL); -+ g_object_unref (dkp_client); - return ret; - } - -@@ -655,36 +628,19 @@ do_disconnect (GdmGreeterLoginWindow *login_window) - static void - do_suspend (GdmGreeterLoginWindow *login_window) - { -- GError *error; -- DBusGConnection *connection; -- DBusGProxy *proxy; -+ gboolean ret; -+ DkpClient *dkp_client; -+ GError *error = NULL; - -- g_debug ("GdmGreeterLoginWindow: Suspend button clicked"); -- -- error = NULL; -- connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); -- if (error != NULL) { -+ /* use DeviceKit-power to get data */ -+ dkp_client = dkp_client_new (); -+ ret = dkp_client_suspend (dkp_client, &error); -+ if (!ret) { - g_warning ("Couldn't suspend: %s", error->message); - g_error_free (error); - return; - } -- proxy = dbus_g_proxy_new_for_name (connection, -- GPM_DBUS_NAME, -- GPM_DBUS_PATH, -- GPM_DBUS_INTERFACE); -- error = NULL; -- dbus_g_proxy_call (proxy, -- "Suspend", -- &error, -- G_TYPE_INVALID, -- G_TYPE_INVALID); -- if (error != NULL) { -- g_warning ("Couldn't suspend: %s", error->message); -- g_error_free (error); -- return; -- } -- -- g_object_unref (proxy); -+ g_object_unref (dkp_client); - } - - static void --- -1.6.4.4 - diff --git a/gdm-2.28.1-move-shutdown-functions.patch b/gdm-2.28.1-move-shutdown-functions.patch new file mode 100644 index 0000000..9610908 --- /dev/null +++ b/gdm-2.28.1-move-shutdown-functions.patch @@ -0,0 +1,1326 @@ +commit 7b3be6884096a2d21af3c6c26090641c16988b15 +Merge: f0a0955 4c20614 +Author: Ray Strode +Date: Tue Oct 20 17:56:09 2009 -0400 + + Move Shutdown functions to panel instead of login window + + Robert Ancell gives a good rationale for the move: + "In GDM 2.28/master on startup the user is presented with a window + containing: + - A list of users to log in as with the first user selected + - Two buttons, restart and shutdown, below the user list + + Since the first user is selected, users who are unfamiliar/not paying + close attention sometimes click on the shutdown button as this is placed + where the default action (in this case login) is conventionally placed + (the lower right hand corner of the window). The penalty of making this + mistake is for the computer to shut down immediately with no chance of + aborting this mistake. + + An additional mistake users can make is to miss clicking on their user + and then click on the shutdown button (as this button is replaced with + the login button after selecting a user). + + Recommended behaviour: + + Move the shutdown actions (shutdown, sleep, hibernate, restart) to a + menu on the GDM panel. + + The shutdown buttons do not need to be prominently located as: + - They are used less frequently than the login buttons (normal operation + is to shutdown from within your session). + - Most hardware has a dedicated power button that performs the same + action + - It is better to have them in a location where they are less likely to + be accidentally activated" + + (see https://bugs.gnome.org/596151) + +From e53b45310bc0b83ab14fdfde1cac6e6ea22d82b7 Mon Sep 17 00:00:00 2001 +From: Robert Ancell +Date: Thu, 24 Sep 2009 15:51:10 +1000 +Subject: [PATCH 1/3] Move shutdown buttons to menu in panel (Bug #596151) + +--- + gui/simple-greeter/Makefile.am | 2 +- + gui/simple-greeter/gdm-greeter-login-window.c | 294 --------------------- + gui/simple-greeter/gdm-greeter-login-window.glade | 194 -------------- + gui/simple-greeter/gdm-greeter-panel.c | 263 ++++++++++++++++++- + gui/simple-greeter/gdm-greeter-panel.h | 3 +- + gui/simple-greeter/gdm-greeter-session.c | 4 +- + gui/simple-greeter/test-greeter-panel.c | 2 +- + 7 files changed, 267 insertions(+), 495 deletions(-) + +diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am +index 4c06bc3..519e652 100644 +--- a/gui/simple-greeter/Makefile.am ++++ b/gui/simple-greeter/Makefile.am +@@ -92,7 +92,6 @@ test_greeter_login_window_LDADD = \ + libgdmuser.la \ + $(COMMON_LIBS) \ + $(SIMPLE_GREETER_LIBS) \ +- $(DEVKIT_POWER_LIBS) \ + $(RBAC_LIBS) \ + $(NULL) + +@@ -144,6 +143,7 @@ test_greeter_panel_LDADD = \ + $(GTK_LIBS) \ + $(GCONF_LIBS) \ + $(LIBXKLAVIER_LIBS) \ ++ $(DEVKIT_POWER_LIBS) \ + $(NULL) + + test_remote_login_window_SOURCES = \ +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 10a5132..9a29a2e 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -34,11 +34,6 @@ + #include + #include + +-#ifdef ENABLE_RBAC_SHUTDOWN +-#include +-#include +-#endif +- + #include + #include + #include +@@ -56,10 +51,6 @@ + #include + #include + +-#ifdef HAVE_DEVICEKIT_POWER +-#include +-#endif +- + #include "gdm-settings-client.h" + #include "gdm-settings-keys.h" + #include "gdm-profile.h" +@@ -90,7 +81,6 @@ + #define KEY_BANNER_MESSAGE_TEXT KEY_GREETER_DIR "/banner_message_text" + #define KEY_BANNER_MESSAGE_TEXT_NOCHOOSER KEY_GREETER_DIR "/banner_message_text_nochooser" + #define KEY_LOGO KEY_GREETER_DIR "/logo_icon_name" +-#define KEY_DISABLE_RESTART_BUTTONS KEY_GREETER_DIR "/disable_restart_buttons" + #define GDM_GREETER_LOGIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_LOGIN_WINDOW, GdmGreeterLoginWindowPrivate)) + + enum { +@@ -125,8 +115,6 @@ struct GdmGreeterLoginWindowPrivate + char *timed_login_username; + guint timed_login_timeout_id; + +- guint sensitize_power_buttons_timeout_id; +- + guint login_button_handler_id; + guint start_session_handler_id; + }; +@@ -353,37 +341,6 @@ sensitize_widget (GdmGreeterLoginWindow *login_window, + } + } + +-static gboolean +-get_show_restart_buttons (GdmGreeterLoginWindow *login_window) +-{ +- gboolean show; +- GError *error; +- +- error = NULL; +- show = ! gconf_client_get_bool (login_window->priv->client, KEY_DISABLE_RESTART_BUTTONS, &error); +- if (error != NULL) { +- g_debug ("GdmGreeterLoginWindow: unable to get disable-restart-buttons configuration: %s", error->message); +- g_error_free (error); +- } +- +-#ifdef ENABLE_RBAC_SHUTDOWN +- { +- char *username; +- +- username = g_get_user_name (); +- if (username == NULL || !chkauthattr (RBAC_SHUTDOWN_KEY, username)) { +- show = FALSE; +- g_debug ("GdmGreeterLoginWindow: Not showing stop/restart buttons for user %s due to RBAC key %s", +- username, RBAC_SHUTDOWN_KEY); +- } else { +- g_debug ("GdmGreeterLoginWindow: Showing stop/restart buttons for user %s due to RBAC key %s", +- username, RBAC_SHUTDOWN_KEY); +- } +- } +-#endif +- return show; +-} +- + static void + on_login_button_clicked_answer_query (GtkButton *button, + GdmGreeterLoginWindow *login_window) +@@ -477,61 +434,6 @@ adjust_other_login_visibility(GdmGreeterLoginWindow *login_window) + } + } + +-#ifdef HAVE_DEVICEKIT_POWER +-static gboolean +-can_suspend (GdmGreeterLoginWindow *login_window) +-{ +- gboolean ret; +- DkpClient *dkp_client; +- +- /* use DeviceKit-power to get data */ +- dkp_client = dkp_client_new (); +- g_object_get (dkp_client, +- "can-suspend", &ret, +- NULL); +- g_object_unref (dkp_client); +- return ret; +-} +-#endif +- +-static void +-remove_sensitize_power_buttons_timeout (GdmGreeterLoginWindow *login_window) +-{ +- if (login_window->priv->sensitize_power_buttons_timeout_id > 0) { +- g_source_remove (login_window->priv->sensitize_power_buttons_timeout_id); +- login_window->priv->sensitize_power_buttons_timeout_id = 0; +- } +-} +- +-static gboolean +-sensitize_power_buttons_timeout (GdmGreeterLoginWindow *login_window) +-{ +- switch (login_window->priv->dialog_mode) { +- case MODE_SELECTION: +- sensitize_widget (login_window, "shutdown-button", TRUE); +- sensitize_widget (login_window, "restart-button", TRUE); +- sensitize_widget (login_window, "suspend-button", TRUE); +- sensitize_widget (login_window, "disconnect-button", TRUE); +- break; +- case MODE_AUTHENTICATION: +- break; +- default: +- g_assert_not_reached (); +- } +- +- login_window->priv->sensitize_power_buttons_timeout_id = 0; +- return FALSE; +-} +- +-static void +-add_sensitize_power_buttons_timeout (GdmGreeterLoginWindow *login_window) +-{ +- remove_sensitize_power_buttons_timeout (login_window); +- login_window->priv->sensitize_power_buttons_timeout_id = g_timeout_add_seconds (1, +- (GSourceFunc)sensitize_power_buttons_timeout, +- login_window); +-} +- + static void + switch_mode (GdmGreeterLoginWindow *login_window, + int number) +@@ -539,16 +441,6 @@ switch_mode (GdmGreeterLoginWindow *login_window, + const char *default_name; + GtkWidget *user_chooser; + GtkWidget *box; +- gboolean show_restart_buttons; +- gboolean show_suspend_button; +- +- show_restart_buttons = get_show_restart_buttons (login_window); +- +-#ifdef HAVE_DEVICEKIT_POWER +- show_suspend_button = can_suspend (login_window); +-#else +- show_suspend_button = FALSE; +-#endif + + /* we want to run this even if we're supposed to + be in the mode already so that we reset everything +@@ -557,38 +449,20 @@ switch_mode (GdmGreeterLoginWindow *login_window, + + default_name = NULL; + +- remove_sensitize_power_buttons_timeout (login_window); +- + switch (number) { + case MODE_SELECTION: + set_log_in_button_mode (login_window, LOGIN_BUTTON_HIDDEN); + + show_widget (login_window, "cancel-button", FALSE); + +- show_widget (login_window, "shutdown-button", +- login_window->priv->display_is_local && show_restart_buttons); +- show_widget (login_window, "restart-button", +- login_window->priv->display_is_local && show_restart_buttons); +- show_widget (login_window, "suspend-button", +- login_window->priv->display_is_local && show_restart_buttons && show_suspend_button); +- show_widget (login_window, "disconnect-button", +- ! login_window->priv->display_is_local); +- + show_widget (login_window, "auth-input-box", FALSE); + +- add_sensitize_power_buttons_timeout (login_window); +- sensitize_widget (login_window, "shutdown-button", FALSE); +- sensitize_widget (login_window, "restart-button", FALSE); +- sensitize_widget (login_window, "suspend-button", FALSE); + sensitize_widget (login_window, "disconnect-button", FALSE); + + default_name = NULL; + break; + case MODE_AUTHENTICATION: + show_widget (login_window, "cancel-button", TRUE); +- show_widget (login_window, "shutdown-button", FALSE); +- show_widget (login_window, "restart-button", FALSE); +- show_widget (login_window, "suspend-button", FALSE); + show_widget (login_window, "disconnect-button", FALSE); + default_name = "log-in-button"; + break; +@@ -629,32 +503,6 @@ switch_mode (GdmGreeterLoginWindow *login_window, + } + + static void +-do_disconnect (GdmGreeterLoginWindow *login_window) +-{ +- gtk_main_quit (); +-} +- +-#ifdef HAVE_DEVICEKIT_POWER +-static void +-do_suspend (GdmGreeterLoginWindow *login_window) +-{ +- gboolean ret; +- DkpClient *dkp_client; +- GError *error = NULL; +- +- /* use DeviceKit-power to get data */ +- dkp_client = dkp_client_new (); +- ret = dkp_client_suspend (dkp_client, &error); +- if (!ret) { +- g_warning ("Couldn't suspend: %s", error->message); +- g_error_free (error); +- return; +- } +- g_object_unref (dkp_client); +-} +-#endif +- +-static void + delete_entry_text (GtkWidget *entry) + { + const char *typed_text; +@@ -968,16 +816,6 @@ gdm_greeter_login_window_get_property (GObject *object, + } + + static void +-suspend_button_clicked (GtkButton *button, +- GdmGreeterLoginWindow *login_window) +-{ +-#ifdef HAVE_DEVICEKIT_POWER +- do_suspend (login_window); +-#endif +-} +- +- +-static void + cancel_button_clicked (GtkButton *button, + GdmGreeterLoginWindow *login_window) + { +@@ -985,125 +823,6 @@ cancel_button_clicked (GtkButton *button, + } + + static void +-disconnect_button_clicked (GtkButton *button, +- GdmGreeterLoginWindow *login_window) +-{ +- do_disconnect (login_window); +-} +- +-static gboolean +-try_system_stop (DBusGConnection *connection, +- GError **error) +-{ +- DBusGProxy *proxy; +- gboolean res; +- +- g_debug ("GdmGreeterLoginWindow: trying to stop system"); +- +- proxy = dbus_g_proxy_new_for_name (connection, +- CK_NAME, +- CK_MANAGER_PATH, +- CK_MANAGER_INTERFACE); +- res = dbus_g_proxy_call_with_timeout (proxy, +- "Stop", +- INT_MAX, +- error, +- /* parameters: */ +- G_TYPE_INVALID, +- /* return values: */ +- G_TYPE_INVALID); +- return res; +-} +- +-static gboolean +-try_system_restart (DBusGConnection *connection, +- GError **error) +-{ +- DBusGProxy *proxy; +- gboolean res; +- +- g_debug ("GdmGreeterLoginWindow: trying to restart system"); +- +- proxy = dbus_g_proxy_new_for_name (connection, +- CK_NAME, +- CK_MANAGER_PATH, +- CK_MANAGER_INTERFACE); +- res = dbus_g_proxy_call_with_timeout (proxy, +- "Restart", +- INT_MAX, +- error, +- /* parameters: */ +- G_TYPE_INVALID, +- /* return values: */ +- G_TYPE_INVALID); +- return res; +-} +- +-static void +-do_system_restart (GdmGreeterLoginWindow *login_window) +-{ +- gboolean res; +- GError *error; +- DBusGConnection *connection; +- +- error = NULL; +- connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); +- if (connection == NULL) { +- g_warning ("Unable to get system bus connection: %s", error->message); +- g_error_free (error); +- return; +- } +- +- res = try_system_restart (connection, &error); +- if (!res) { +- g_debug ("GdmGreeterLoginWindow: unable to restart system: %s: %s", +- dbus_g_error_get_name (error), +- error->message); +- g_error_free (error); +- } +-} +- +-static void +-do_system_stop (GdmGreeterLoginWindow *login_window) +-{ +- gboolean res; +- GError *error; +- DBusGConnection *connection; +- +- error = NULL; +- connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); +- if (connection == NULL) { +- g_warning ("Unable to get system bus connection: %s", error->message); +- g_error_free (error); +- return; +- } +- +- res = try_system_stop (connection, &error); +- if (!res) { +- g_debug ("GdmGreeterLoginWindow: unable to stop system: %s: %s", +- dbus_g_error_get_name (error), +- error->message); +- g_error_free (error); +- } +-} +- +-static void +-restart_button_clicked (GtkButton *button, +- GdmGreeterLoginWindow *login_window) +-{ +- g_debug ("GdmGreeterLoginWindow: restart button clicked"); +- do_system_restart (login_window); +-} +- +-static void +-shutdown_button_clicked (GtkButton *button, +- GdmGreeterLoginWindow *login_window) +-{ +- g_debug ("GdmGreeterLoginWindow: stop button clicked"); +- do_system_stop (login_window); +-} +- +-static void + on_user_chooser_visibility_changed (GdmGreeterLoginWindow *login_window) + { + update_banner_message (login_window); +@@ -1400,20 +1119,9 @@ load_theme (GdmGreeterLoginWindow *login_window) + 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);*/ + +- button = glade_xml_get_widget (login_window->priv->xml, "suspend-button"); +- g_signal_connect (button, "clicked", G_CALLBACK (suspend_button_clicked), login_window); +- + button = glade_xml_get_widget (login_window->priv->xml, "cancel-button"); + g_signal_connect (button, "clicked", G_CALLBACK (cancel_button_clicked), login_window); + +- button = glade_xml_get_widget (login_window->priv->xml, "disconnect-button"); +- g_signal_connect (button, "clicked", G_CALLBACK (disconnect_button_clicked), login_window); +- +- button = glade_xml_get_widget (login_window->priv->xml, "restart-button"); +- g_signal_connect (button, "clicked", G_CALLBACK (restart_button_clicked), 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))) { +@@ -1780,8 +1488,6 @@ gdm_greeter_login_window_finalize (GObject *object) + g_object_unref (login_window->priv->client); + } + +- remove_sensitize_power_buttons_timeout (login_window); +- + G_OBJECT_CLASS (gdm_greeter_login_window_parent_class)->finalize (object); + } + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.glade b/gui/simple-greeter/gdm-greeter-login-window.glade +index d972c82..7c6e94b 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.glade ++++ b/gui/simple-greeter/gdm-greeter-login-window.glade +@@ -337,200 +337,6 @@ + 6 + + +- +- True +- True +- gtk-disconnect +- True +- GTK_RELIEF_NORMAL +- True +- +- +- +- +- +- True +- True +- True +- True +- GTK_RELIEF_NORMAL +- True +- +- +- +- True +- False +- 0 +- +- +- +- True +- media-playback-pause +- 16 +- 0.5 +- 0.5 +- 0 +- 0 +- +- +- 0 +- True +- True +- +- +- +- +- +- True +- Suspend +- False +- False +- GTK_JUSTIFY_LEFT +- False +- False +- 0 +- 0.5 +- 0 +- 0 +- PANGO_ELLIPSIZE_NONE +- -1 +- False +- 0 +- +- +- 0 +- True +- True +- +- +- +- +- +- +- +- +- +- True +- True +- True +- True +- GTK_RELIEF_NORMAL +- True +- +- +- +- True +- False +- 0 +- +- +- +- True +- view-refresh +- 16 +- 0.5 +- 0.5 +- 0 +- 0 +- +- +- 0 +- True +- True +- +- +- +- +- +- True +- Restart +- False +- False +- GTK_JUSTIFY_LEFT +- False +- False +- 0 +- 0.5 +- 0 +- 0 +- PANGO_ELLIPSIZE_NONE +- -1 +- False +- 0 +- +- +- 0 +- True +- True +- +- +- +- +- +- +- +- +- +- True +- True +- True +- True +- GTK_RELIEF_NORMAL +- True +- +- +- +- True +- False +- 0 +- +- +- +- True +- system-shutdown +- 16 +- 0.5 +- 0.5 +- 0 +- 0 +- +- +- 0 +- True +- True +- +- +- +- +- +- True +- Shut Down +- False +- False +- GTK_JUSTIFY_LEFT +- False +- False +- 0.5 +- 0.5 +- 0 +- 0 +- PANGO_ELLIPSIZE_NONE +- -1 +- False +- 0 +- +- +- 0 +- True +- True +- +- +- +- +- +- +- +- + + True + True +diff --git a/gui/simple-greeter/gdm-greeter-panel.c b/gui/simple-greeter/gdm-greeter-panel.c +index dbdef29..dd0cb32 100644 +--- a/gui/simple-greeter/gdm-greeter-panel.c ++++ b/gui/simple-greeter/gdm-greeter-panel.c +@@ -27,12 +27,22 @@ + #include + #include + ++#ifdef ENABLE_RBAC_SHUTDOWN ++#include ++#include ++#endif ++ + #include + #include + #include + #include + + #include ++#include ++ ++#ifdef HAVE_DEVICEKIT_POWER ++#include ++#endif + + #include "gdm-languages.h" + #include "gdm-layouts.h" +@@ -46,6 +56,16 @@ + + #include "na-tray.h" + ++#define CK_NAME "org.freedesktop.ConsoleKit" ++#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager" ++#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager" ++ ++#define GPM_DBUS_NAME "org.freedesktop.PowerManagement" ++#define GPM_DBUS_PATH "/org/freedesktop/PowerManagement" ++#define GPM_DBUS_INTERFACE "org.freedesktop.PowerManagement" ++ ++#define KEY_DISABLE_RESTART_BUTTONS "/apps/gdm/simple-greeter/disable_restart_buttons" ++ + #define GDM_GREETER_PANEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_PANEL, GdmGreeterPanelPrivate)) + + struct GdmGreeterPanelPrivate +@@ -66,11 +86,15 @@ struct GdmGreeterPanelPrivate + + char *default_session_name; + char *default_language_name; ++ ++ GConfClient *client; ++ guint display_is_local : 1; + }; + + enum { + PROP_0, +- PROP_MONITOR ++ PROP_MONITOR, ++ PROP_DISPLAY_IS_LOCAL + }; + + enum { +@@ -107,6 +131,13 @@ gdm_greeter_panel_set_monitor (GdmGreeterPanel *panel, + } + + static void ++_gdm_greeter_panel_set_display_is_local (GdmGreeterPanel *panel, ++ gboolean is) ++{ ++ panel->priv->display_is_local = is; ++} ++ ++static void + gdm_greeter_panel_set_property (GObject *object, + guint prop_id, + const GValue *value, +@@ -120,6 +151,9 @@ gdm_greeter_panel_set_property (GObject *object, + case PROP_MONITOR: + gdm_greeter_panel_set_monitor (self, g_value_get_int (value)); + break; ++ case PROP_DISPLAY_IS_LOCAL: ++ _gdm_greeter_panel_set_display_is_local (self, g_value_get_boolean (value)); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -140,6 +174,9 @@ gdm_greeter_panel_get_property (GObject *object, + case PROP_MONITOR: + g_value_set_int (value, self->priv->monitor); + break; ++ case PROP_DISPLAY_IS_LOCAL: ++ g_value_set_boolean (value, self->priv->display_is_local); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -477,6 +514,13 @@ gdm_greeter_panel_class_init (GdmGreeterPanelClass *klass) + G_MAXINT, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); ++ g_object_class_install_property (object_class, ++ PROP_DISPLAY_IS_LOCAL, ++ g_param_spec_boolean ("display-is-local", ++ "display is local", ++ "display is local", ++ FALSE, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (klass, sizeof (GdmGreeterPanelPrivate)); + } +@@ -563,11 +607,185 @@ on_animation_tick (GdmGreeterPanel *panel, + gtk_widget_queue_resize (GTK_WIDGET (panel)); + } + ++static gboolean ++try_system_stop (DBusGConnection *connection, ++ GError **error) ++{ ++ DBusGProxy *proxy; ++ gboolean res; ++ ++ g_debug ("GdmGreeterPanel: trying to stop system"); ++ ++ proxy = dbus_g_proxy_new_for_name (connection, ++ CK_NAME, ++ CK_MANAGER_PATH, ++ CK_MANAGER_INTERFACE); ++ res = dbus_g_proxy_call_with_timeout (proxy, ++ "Stop", ++ INT_MAX, ++ error, ++ /* parameters: */ ++ G_TYPE_INVALID, ++ /* return values: */ ++ G_TYPE_INVALID); ++ return res; ++} ++ ++static gboolean ++try_system_restart (DBusGConnection *connection, ++ GError **error) ++{ ++ DBusGProxy *proxy; ++ gboolean res; ++ ++ g_debug ("GdmGreeterPanel: trying to restart system"); ++ ++ proxy = dbus_g_proxy_new_for_name (connection, ++ CK_NAME, ++ CK_MANAGER_PATH, ++ CK_MANAGER_INTERFACE); ++ res = dbus_g_proxy_call_with_timeout (proxy, ++ "Restart", ++ INT_MAX, ++ error, ++ /* parameters: */ ++ G_TYPE_INVALID, ++ /* return values: */ ++ G_TYPE_INVALID); ++ return res; ++} ++ ++static gboolean ++can_suspend (void) ++{ ++ gboolean ret = FALSE; ++ ++#ifdef HAVE_DEVICEKIT_POWER ++ DkpClient *dkp_client; ++ ++ /* use DeviceKit-power to get data */ ++ dkp_client = dkp_client_new (); ++ g_object_get (dkp_client, ++ "can-suspend", &ret, ++ NULL); ++ g_object_unref (dkp_client); ++#endif ++ ++ return ret; ++} ++ ++static void ++do_system_suspend (void) ++{ ++#ifdef HAVE_DEVICEKIT_POWER ++ gboolean ret; ++ DkpClient *dkp_client; ++ GError *error = NULL; ++ ++ /* use DeviceKit-power to get data */ ++ dkp_client = dkp_client_new (); ++ ret = dkp_client_suspend (dkp_client, &error); ++ if (!ret) { ++ g_warning ("Couldn't suspend: %s", error->message); ++ g_error_free (error); ++ return; ++ } ++ g_object_unref (dkp_client); ++#endif ++} ++ ++static void ++do_system_restart (void) ++{ ++ gboolean res; ++ GError *error; ++ DBusGConnection *connection; ++ ++ error = NULL; ++ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); ++ if (connection == NULL) { ++ g_warning ("Unable to get system bus connection: %s", error->message); ++ g_error_free (error); ++ return; ++ } ++ ++ res = try_system_restart (connection, &error); ++ if (!res) { ++ g_debug ("GdmGreeterPanel: unable to restart system: %s: %s", ++ dbus_g_error_get_name (error), ++ error->message); ++ g_error_free (error); ++ } ++} ++ ++static void ++do_system_stop (void) ++{ ++ gboolean res; ++ GError *error; ++ DBusGConnection *connection; ++ ++ error = NULL; ++ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); ++ if (connection == NULL) { ++ g_warning ("Unable to get system bus connection: %s", error->message); ++ g_error_free (error); ++ return; ++ } ++ ++ res = try_system_stop (connection, &error); ++ if (!res) { ++ g_debug ("GdmGreeterPanel: unable to stop system: %s: %s", ++ dbus_g_error_get_name (error), ++ error->message); ++ g_error_free (error); ++ } ++} ++ ++static void ++do_disconnect (void) ++{ ++ gtk_main_quit (); ++} ++ ++static gboolean ++get_show_restart_buttons (GdmGreeterPanel *panel) ++{ ++ gboolean show; ++ GError *error; ++ ++ error = NULL; ++ show = ! gconf_client_get_bool (panel->priv->client, KEY_DISABLE_RESTART_BUTTONS, &error); ++ if (error != NULL) { ++ g_debug ("GdmGreeterPanel: unable to get disable-restart-buttons configuration: %s", error->message); ++ g_error_free (error); ++ } ++ ++#ifdef ENABLE_RBAC_SHUTDOWN ++ { ++ char *username; ++ ++ username = g_get_user_name (); ++ if (username == NULL || !chkauthattr (RBAC_SHUTDOWN_KEY, username)) { ++ show = FALSE; ++ g_debug ("GdmGreeterPanel: Not showing stop/restart buttons for user %s due to RBAC key %s", ++ username, RBAC_SHUTDOWN_KEY); ++ } else { ++ g_debug ("GdmGreeterPanel: Showing stop/restart buttons for user %s due to RBAC key %s", ++ username, RBAC_SHUTDOWN_KEY); ++ } ++ } ++#endif ++ return show; ++} ++ + static void + gdm_greeter_panel_init (GdmGreeterPanel *panel) + { + NaTray *tray; + GtkWidget *spacer; ++ GtkWidget *shutdown_menu; ++ GtkWidget *menu, *menu_item; + + gdm_profile_start (NULL); + +@@ -603,6 +821,8 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) + spacer = gtk_label_new (""); + gtk_box_pack_start (GTK_BOX (panel->priv->option_hbox), spacer, TRUE, TRUE, 6); + gtk_widget_show (spacer); ++ ++ panel->priv->client = gconf_client_get_default (); + + gdm_profile_start ("creating option widget"); + panel->priv->language_option_widget = gdm_language_option_widget_new (); +@@ -642,6 +862,42 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) + gtk_widget_show (panel->priv->hostname_label); + } + ++ if (panel->priv->display_is_local || get_show_restart_buttons (panel)) { ++ shutdown_menu = gtk_menu_bar_new (); ++ ++ menu_item = gtk_image_menu_item_new (); ++ menu = gtk_menu_new (); ++ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu); ++ gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menu_item), TRUE); ++ gtk_menu_item_set_label (GTK_MENU_ITEM (menu_item), ""); ++ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), ++ gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_BUTTON)); ++ gtk_menu_shell_append (GTK_MENU_SHELL (shutdown_menu), menu_item); ++ ++ if (panel->priv->display_is_local) { ++ menu_item = gtk_menu_item_new_with_label ("Disconnect"); ++ g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_disconnect), NULL); ++ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); ++ } else { ++ if (can_suspend ()) { ++ menu_item = gtk_menu_item_new_with_label ("Suspend"); ++ g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_suspend), NULL); ++ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); ++ } ++ ++ menu_item = gtk_menu_item_new_with_label ("Restart"); ++ g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_restart), NULL); ++ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); ++ ++ menu_item = gtk_menu_item_new_with_label ("Shut Down"); ++ g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_stop), NULL); ++ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); ++ } ++ ++ gtk_box_pack_end (GTK_BOX (panel->priv->hbox), GTK_WIDGET (shutdown_menu), FALSE, FALSE, 0); ++ gtk_widget_show_all (GTK_WIDGET (shutdown_menu)); ++ } ++ + panel->priv->clock = gdm_clock_widget_new (); + gtk_box_pack_end (GTK_BOX (panel->priv->hbox), + GTK_WIDGET (panel->priv->clock), FALSE, FALSE, 6); +@@ -651,7 +907,6 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) + GTK_ORIENTATION_HORIZONTAL); + gtk_box_pack_end (GTK_BOX (panel->priv->hbox), GTK_WIDGET (tray), FALSE, FALSE, 6); + gtk_widget_show (GTK_WIDGET (tray)); +- + gdm_greeter_panel_hide_user_options (panel); + + panel->priv->progress = 0.0; +@@ -684,13 +939,15 @@ gdm_greeter_panel_finalize (GObject *object) + + GtkWidget * + gdm_greeter_panel_new (GdkScreen *screen, +- int monitor) ++ int monitor, ++ gboolean is_local) + { + GObject *object; + + object = g_object_new (GDM_TYPE_GREETER_PANEL, + "screen", screen, + "monitor", monitor, ++ "display-is-local", is_local, + NULL); + + return GTK_WIDGET (object); +diff --git a/gui/simple-greeter/gdm-greeter-panel.h b/gui/simple-greeter/gdm-greeter-panel.h +index 1e637f5..625c80d 100644 +--- a/gui/simple-greeter/gdm-greeter-panel.h ++++ b/gui/simple-greeter/gdm-greeter-panel.h +@@ -60,7 +60,8 @@ typedef struct + GType gdm_greeter_panel_get_type (void); + + GtkWidget * gdm_greeter_panel_new (GdkScreen *screen, +- int monitor); ++ int monitor, ++ gboolean is_local); + + void gdm_greeter_panel_show_user_options (GdmGreeterPanel *panel); + void gdm_greeter_panel_hide_user_options (GdmGreeterPanel *panel); +diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c +index 167b693..e7d206a 100644 +--- a/gui/simple-greeter/gdm-greeter-session.c ++++ b/gui/simple-greeter/gdm-greeter-session.c +@@ -332,13 +332,15 @@ toggle_panel (GdmGreeterSession *session, + GdkScreen *screen; + int monitor; + int x, y; ++ gboolean is_local; + + display = gdk_display_get_default (); + gdk_display_get_pointer (display, &screen, &x, &y, NULL); + + monitor = get_tallest_monitor_at_point (screen, x, y); + +- session->priv->panel = gdm_greeter_panel_new (screen, monitor); ++ is_local = gdm_greeter_client_get_display_is_local (session->priv->client); ++ session->priv->panel = gdm_greeter_panel_new (screen, monitor, is_local); + + g_signal_connect_swapped (session->priv->panel, + "language-selected", +diff --git a/gui/simple-greeter/test-greeter-panel.c b/gui/simple-greeter/test-greeter-panel.c +index 80ef0a9..86adae3 100644 +--- a/gui/simple-greeter/test-greeter-panel.c ++++ b/gui/simple-greeter/test-greeter-panel.c +@@ -53,7 +53,7 @@ main (int argc, char *argv[]) + gdk_display_get_pointer (display, &screen, &x, &y, NULL); + monitor = gdk_screen_get_monitor_at_point (screen, x, y); + +- panel = gdm_greeter_panel_new (screen, monitor); ++ panel = gdm_greeter_panel_new (screen, monitor, TRUE); + gdm_greeter_panel_show_user_options (GDM_GREETER_PANEL (panel)); + + gtk_widget_show (panel); +-- +1.6.5.rc2 + + +From 4ee17e4732cbdc4c91e93da732de6849c4f95a86 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 20 Oct 2009 17:06:58 -0400 +Subject: [PATCH 2/3] Use button instead of menu bar + +The menu bar isn't a great fit for the panel +--- + gui/simple-greeter/gdm-greeter-panel.c | 81 +++++++++++++++++++++++++------- + 1 files changed, 64 insertions(+), 17 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-panel.c b/gui/simple-greeter/gdm-greeter-panel.c +index dd0cb32..d5dd820 100644 +--- a/gui/simple-greeter/gdm-greeter-panel.c ++++ b/gui/simple-greeter/gdm-greeter-panel.c +@@ -77,6 +77,8 @@ struct GdmGreeterPanelPrivate + GtkWidget *option_hbox; + GtkWidget *hostname_label; + GtkWidget *clock; ++ GtkWidget *shutdown_button; ++ GtkWidget *shutdown_menu; + GtkWidget *language_option_widget; + GtkWidget *layout_option_widget; + GtkWidget *session_option_widget; +@@ -780,12 +782,48 @@ get_show_restart_buttons (GdmGreeterPanel *panel) + } + + static void ++position_shutdown_menu (GtkMenu *menu, ++ int *x, ++ int *y, ++ gboolean *push_in, ++ GdmGreeterPanel *panel) ++{ ++ GtkRequisition menu_requisition; ++ ++ *push_in = TRUE; ++ ++ *x = panel->priv->shutdown_button->allocation.x; ++ gtk_window_get_position (GTK_WINDOW (panel), NULL, y); ++ ++ gtk_widget_size_request (GTK_WIDGET (menu), &menu_requisition); ++ ++ *y -= menu_requisition.height; ++} ++ ++static void ++on_shutdown_button_toggled (GdmGreeterPanel *panel) ++{ ++ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (panel->priv->shutdown_button))) { ++ gtk_menu_popup (GTK_MENU (panel->priv->shutdown_menu), NULL, NULL, ++ (GtkMenuPositionFunc) position_shutdown_menu, ++ panel, 0, 0); ++ } else { ++ gtk_menu_popdown (GTK_MENU (panel->priv->shutdown_menu)); ++ } ++} ++ ++static void ++on_shutdown_menu_deactivate (GdmGreeterPanel *panel) ++{ ++ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (panel->priv->shutdown_button), ++ FALSE); ++} ++ ++static void + gdm_greeter_panel_init (GdmGreeterPanel *panel) + { + NaTray *tray; + GtkWidget *spacer; +- GtkWidget *shutdown_menu; +- GtkWidget *menu, *menu_item; + + gdm_profile_start (NULL); + +@@ -863,39 +901,48 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) + } + + if (panel->priv->display_is_local || get_show_restart_buttons (panel)) { +- shutdown_menu = gtk_menu_bar_new (); ++ GtkWidget *menu_item; ++ GtkWidget *image; ++ ++ panel->priv->shutdown_button = gtk_toggle_button_new (); ++ gtk_button_set_relief (GTK_BUTTON (panel->priv->shutdown_button), ++ GTK_RELIEF_NONE); ++ ++ panel->priv->shutdown_menu = gtk_menu_new (); ++ gtk_menu_attach_to_widget (GTK_MENU (panel->priv->shutdown_menu), ++ panel->priv->shutdown_button, NULL); ++ g_signal_connect_swapped (panel->priv->shutdown_button, "toggled", ++ G_CALLBACK (on_shutdown_button_toggled), panel); ++ g_signal_connect_swapped (panel->priv->shutdown_menu, "deactivate", ++ G_CALLBACK (on_shutdown_menu_deactivate), panel); + +- menu_item = gtk_image_menu_item_new (); +- menu = gtk_menu_new (); +- gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu); +- gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menu_item), TRUE); +- gtk_menu_item_set_label (GTK_MENU_ITEM (menu_item), ""); +- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), +- gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_BUTTON)); +- gtk_menu_shell_append (GTK_MENU_SHELL (shutdown_menu), menu_item); ++ image = gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_BUTTON); ++ gtk_widget_show (image); ++ gtk_container_add (GTK_CONTAINER (panel->priv->shutdown_button), image); + + if (panel->priv->display_is_local) { + menu_item = gtk_menu_item_new_with_label ("Disconnect"); + g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_disconnect), NULL); +- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); ++ gtk_menu_shell_append (GTK_MENU_SHELL (panel->priv->shutdown_menu), menu_item); + } else { + if (can_suspend ()) { + menu_item = gtk_menu_item_new_with_label ("Suspend"); + g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_suspend), NULL); +- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); ++ gtk_menu_shell_append (GTK_MENU_SHELL (panel->priv->shutdown_menu), menu_item); + } + + menu_item = gtk_menu_item_new_with_label ("Restart"); + g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_restart), NULL); +- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); ++ gtk_menu_shell_append (GTK_MENU_SHELL (panel->priv->shutdown_menu), menu_item); + + menu_item = gtk_menu_item_new_with_label ("Shut Down"); + g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_stop), NULL); +- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); ++ gtk_menu_shell_append (GTK_MENU_SHELL (panel->priv->shutdown_menu), menu_item); + } + +- gtk_box_pack_end (GTK_BOX (panel->priv->hbox), GTK_WIDGET (shutdown_menu), FALSE, FALSE, 0); +- gtk_widget_show_all (GTK_WIDGET (shutdown_menu)); ++ gtk_box_pack_end (GTK_BOX (panel->priv->hbox), GTK_WIDGET (panel->priv->shutdown_button), FALSE, FALSE, 0); ++ gtk_widget_show_all (panel->priv->shutdown_menu); ++ gtk_widget_show_all (GTK_WIDGET (panel->priv->shutdown_button)); + } + + panel->priv->clock = gdm_clock_widget_new (); +-- +1.6.5.rc2 + + +From 4c206142ddb22315d9beb42eae9d868f449bdf11 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 20 Oct 2009 17:23:15 -0400 +Subject: [PATCH 3/3] Mark Shutdown, Restart, and Suspend for translation + +--- + gui/simple-greeter/gdm-greeter-panel.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-panel.c b/gui/simple-greeter/gdm-greeter-panel.c +index d5dd820..016f636 100644 +--- a/gui/simple-greeter/gdm-greeter-panel.c ++++ b/gui/simple-greeter/gdm-greeter-panel.c +@@ -926,16 +926,16 @@ gdm_greeter_panel_init (GdmGreeterPanel *panel) + gtk_menu_shell_append (GTK_MENU_SHELL (panel->priv->shutdown_menu), menu_item); + } else { + if (can_suspend ()) { +- menu_item = gtk_menu_item_new_with_label ("Suspend"); ++ menu_item = gtk_menu_item_new_with_label (_("Suspend")); + g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_suspend), NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (panel->priv->shutdown_menu), menu_item); + } + +- menu_item = gtk_menu_item_new_with_label ("Restart"); ++ menu_item = gtk_menu_item_new_with_label (_("Restart")); + g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_restart), NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (panel->priv->shutdown_menu), menu_item); + +- menu_item = gtk_menu_item_new_with_label ("Shut Down"); ++ menu_item = gtk_menu_item_new_with_label (_("Shut Down")); + g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (do_system_stop), NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (panel->priv->shutdown_menu), menu_item); + } +-- +1.6.5.rc2 + +From 7fbb5c0dec8aa42b1d8985c6f62be02c035175da Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 26 Oct 2009 15:00:43 -0400 +Subject: [PATCH] Position shutdown menu better in multi-monitor displays + +--- + gui/simple-greeter/gdm-greeter-panel.c | 13 ++++++++++++- + 1 files changed, 12 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-panel.c b/gui/simple-greeter/gdm-greeter-panel.c +index 43b91d5..caade7a 100644 +--- a/gui/simple-greeter/gdm-greeter-panel.c ++++ b/gui/simple-greeter/gdm-greeter-panel.c +@@ -790,10 +790,21 @@ position_shutdown_menu (GtkMenu *menu, + GdmGreeterPanel *panel) + { + GtkRequisition menu_requisition; ++ GdkScreen *screen; ++ int monitor; + + *push_in = TRUE; + +- *x = panel->priv->shutdown_button->allocation.x; ++ screen = gtk_widget_get_screen (GTK_WIDGET (panel)); ++ monitor = gdk_screen_get_monitor_at_window (screen, GTK_WIDGET (panel)->window); ++ gtk_menu_set_monitor (menu, monitor); ++ ++ gtk_widget_translate_coordinates (GTK_WIDGET (panel->priv->shutdown_button), ++ GTK_WIDGET (panel), ++ panel->priv->shutdown_button->allocation.x, ++ panel->priv->shutdown_button->allocation.y, ++ x, y); ++ + gtk_window_get_position (GTK_WINDOW (panel), NULL, y); + + gtk_widget_size_request (GTK_WIDGET (menu), &menu_requisition); +-- +1.6.5.1 + diff --git a/gdm-bubble-location.patch b/gdm-bubble-location.patch new file mode 100644 index 0000000..f8ddfad --- /dev/null +++ b/gdm-bubble-location.patch @@ -0,0 +1,15 @@ +diff -up gdm-2.28.0/data/session-setup.entries.bubble-location gdm-2.28.0/data/session-setup.entries +--- gdm-2.28.0/data/session-setup.entries.bubble-location 2009-10-09 09:38:01.315620045 -0400 ++++ gdm-2.28.0/data/session-setup.entries 2009-10-09 09:39:11.354874396 -0400 +@@ -755,5 +755,11 @@ + /bin/true + + ++ ++ /apps/notification-daemon/popup_location ++ ++ bottom_right ++ ++ + + diff --git a/gdm-multistack.patch b/gdm-multistack.patch index 4f97fef..c5409f4 100644 --- a/gdm-multistack.patch +++ b/gdm-multistack.patch @@ -1,120 +1,2385 @@ -diff -up gdm-2.28.0/common/gdm-marshal.list.multistack gdm-2.28.0/common/gdm-marshal.list ---- gdm-2.28.0/common/gdm-marshal.list.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/common/gdm-marshal.list 2009-09-23 18:46:06.861400723 -0400 -@@ -5,3 +5,4 @@ VOID:STRING,STRING - VOID:UINT,UINT - VOID:STRING,INT - VOID:DOUBLE -+BOOLEAN:STRING -diff -up gdm-2.28.0/configure.ac.multistack gdm-2.28.0/configure.ac ---- gdm-2.28.0/configure.ac.multistack 2009-09-23 18:46:06.497641172 -0400 -+++ gdm-2.28.0/configure.ac 2009-09-23 18:46:06.800400573 -0400 -@@ -18,6 +18,22 @@ AC_PROG_CXX - AM_PROG_CC_C_O - AC_PROG_LIBTOOL() + +From dfa6b8d5ed60552f435c34c47bc45089fa3eef48 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Feb 2009 13:52:19 -0500 +Subject: [PATCH 07/81] 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 578e613..7e3e59c 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); -+## 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 ++/* Protected ++ */ + void gdm_chooser_widget_loaded (GdmChooserWidget *widget); - AC_SUBST(VERSION) -@@ -51,6 +67,7 @@ LIBXKLAVIER_REQUIRED_VERSION=4.0 - LIBCANBERRA_GTK_REQUIRED_VERSION=0.4 - #FONTCONFIG_REQUIRED_VERSION=2.6.0 - FONTCONFIG_REQUIRED_VERSION=2.5.0 -+NSS_REQUIRED_VERSION=3.11.1 + G_END_DECLS +-- +1.6.5.1 + + +From 7b4e38d04e246d7dc4c446ed2a3c69fcc67257cb Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 6 Feb 2009 17:44:37 -0500 +Subject: [PATCH 08/81] 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 2e01d33..cecce83 100644 +--- a/daemon/gdm-greeter-server.c ++++ b/daemon/gdm-greeter-server.c +@@ -752,7 +752,6 @@ do_introspect (DBusConnection *connection, + " \n" + " \n" + " \n" +- " \n" + " \n" + " \n" + " \n" +-- +1.6.5.1 + + +From 8d5ddd913f13581df1662730745c1d906772185e Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 2 Mar 2009 10:07:03 -0500 +Subject: [PATCH 09/81] Make lookup_item not warn when passing NULL for args + +gtk_tree_model_get doesn't like NULL, and we allow +NULL for optional return values. + +We now check each argument for NULL and call +gtk_tree_model_get individually N times (one for +each argument) instead of just once. +--- + 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 2875456..cbd5072 100644 +--- a/gui/simple-greeter/gdm-chooser-widget.c ++++ b/gui/simple-greeter/gdm-chooser-widget.c +@@ -2171,13 +2171,30 @@ gdm_chooser_widget_lookup_item (GdmChooserWidget *widget, + } + g_free (active_item_id); - EXTRA_COMPILE_WARNINGS(yes) - -@@ -75,6 +92,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) +- 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); ++ } + - PKG_CHECK_MODULES(XLIB, x11 xau, , - [AC_PATH_XTRA - if test "x$no_x" = xyes; then -@@ -183,6 +206,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) ++ if (name != NULL) { ++ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, ++ CHOOSER_NAME_COLUMN, name, -1); ++ } + -+dnl --------------------------------------------------------------------------- - dnl - Configure arguments - dnl --------------------------------------------------------------------------- - -@@ -1242,6 +1274,22 @@ AC_SUBST(GDM_SPOOL_DIR) - - - dnl --------------------------------------------------------------------------- -+dnl - Directory for simple greeter plugins -+dnl --------------------------------------------------------------------------- ++ if (priority != NULL) { ++ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, ++ CHOOSER_PRIORITY_COLUMN, priority, -1); ++ } + -+AC_ARG_WITH(simple-greeter-plugins-dir, -+ AS_HELP_STRING([--with-simple-greeter-plugins-dir=], -+ [simple greeter plugins directory])) ++ 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 ! 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 --------------------------------------------------------------------------- ++ if (is_separate != NULL) { ++ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, ++ CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate, -1); ++ } -@@ -1368,6 +1416,18 @@ 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/fingerprint/icons/Makefile -+gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile -+gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile -+gui/simple-greeter/plugins/smartcard/Makefile -+gui/simple-greeter/plugins/smartcard/icons/Makefile -+gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile -+gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile - gui/simple-chooser/Makefile - gui/user-switch-applet/Makefile - utils/Makefile -diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm-factory-slave.c ---- gdm-2.28.0/daemon/gdm-factory-slave.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-factory-slave.c 2009-09-23 18:46:06.673650996 -0400 -@@ -144,63 +144,71 @@ on_greeter_session_died (GdmGreeterSessi + return TRUE; + } +-- +1.6.5.1 + + +From 57a0d19b8b1e5e7a2132b15ea2c536207b61f80f Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 6 Feb 2009 15:35:00 -0500 +Subject: [PATCH 10/81] 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 47a5778..b6abae4 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -1539,13 +1539,6 @@ gdm_session_direct_init (GdmSessionDirect *session) + } + + static void +-worker_stopped (GdmSessionWorkerJob *job, +- GdmSessionDirect *session) +-{ +- g_debug ("GdmSessionDirect: Worker job stopped"); +-} +- +-static void + worker_started (GdmSessionWorkerJob *job, + GdmSessionDirect *session) + { +@@ -1588,10 +1581,6 @@ start_worker (GdmSessionDirect *session) + 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, + "started", + G_CALLBACK (worker_started), + session); +@@ -1613,9 +1602,6 @@ static void + stop_worker (GdmSessionDirect *session) + { + g_signal_handlers_disconnect_by_func (session->priv->job, +- G_CALLBACK (worker_stopped), +- session); +- g_signal_handlers_disconnect_by_func (session->priv->job, + G_CALLBACK (worker_started), + session); + g_signal_handlers_disconnect_by_func (session->priv->job, +diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c +index 6723464..633d6e2 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 +@@ -390,16 +389,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 d42eb37..5ad1c92 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.5.1 + + + +From 98b3621d59550909f9d837e94d3cb15d20730f30 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 13 May 2009 13:43:33 -0400 +Subject: [PATCH 12/81] Don't send auth-failed when worker dies + +Authentication hasn't failed, it just got aborted before it +could. This prevents a crash that happens when switching +runlevels while the login screen is up. +--- + daemon/gdm-session-direct.c | 12 ++---------- + 1 files changed, 2 insertions(+), 10 deletions(-) + +diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c +index b6abae4..8eadf4d 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -78,7 +78,6 @@ struct _GdmSessionDirectPrivate + + GdmSessionWorkerJob *job; + GPid session_pid; +- guint32 is_authenticated : 1; + guint32 is_running : 1; + + /* object lifetime scope */ +@@ -335,7 +334,6 @@ gdm_session_direct_handle_authenticated (GdmSessionDirect *session, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- session->priv->is_authenticated = TRUE; + _gdm_session_authenticated (GDM_SESSION (session)); + + return DBUS_HANDLER_RESULT_HANDLED; +@@ -363,7 +361,6 @@ gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session, + + g_debug ("GdmSessionDirect: Emitting 'authentication-failed' signal"); + +- session->priv->is_authenticated = FALSE; + _gdm_session_authentication_failed (GDM_SESSION (session), text); + + return DBUS_HANDLER_RESULT_HANDLED; +@@ -1552,9 +1549,7 @@ worker_exited (GdmSessionWorkerJob *job, + { + g_debug ("GdmSessionDirect: Worker job exited: %d", code); + +- if (!session->priv->is_authenticated) { +- _gdm_session_authentication_failed (GDM_SESSION (session), NULL); +- } else if (session->priv->is_running) { ++ if (session->priv->is_running) { + _gdm_session_session_exited (GDM_SESSION (session), code); + } + } +@@ -1566,9 +1561,7 @@ worker_died (GdmSessionWorkerJob *job, + { + g_debug ("GdmSessionDirect: Worker job died: %d", signum); + +- if (!session->priv->is_authenticated) { +- _gdm_session_authentication_failed (GDM_SESSION (session), NULL); +- } else if (session->priv->is_running) { ++ if (session->priv->is_running) { + _gdm_session_session_died (GDM_SESSION (session), signum); + } + } +@@ -2037,7 +2030,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; + } + +-- +1.6.5.1 + + + +From c3d7aa8a30e643ee6068220abd3209b6bbdc6c1a Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 23 Oct 2009 17:40:36 -0400 +Subject: [PATCH 20/81] Don't set has_other_user to FALSE in ctor + +It's initialized to FALSE anyway, and we were +setting it too late. +--- + gui/simple-greeter/gdm-user-chooser-widget.c | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/gdm-user-chooser-widget.c b/gui/simple-greeter/gdm-user-chooser-widget.c +index 167e324..77e06a7 100644 +--- a/gui/simple-greeter/gdm-user-chooser-widget.c ++++ b/gui/simple-greeter/gdm-user-chooser-widget.c +@@ -549,7 +549,6 @@ gdm_user_chooser_widget_constructor (GType type, + n_construct_properties, + construct_properties)); + +- widget->priv->has_user_other = FALSE; + widget->priv->show_normal_users = !is_user_list_disabled (widget); + + widget->priv->load_idle_id = g_idle_add ((GSourceFunc)load_users, widget); +-- +1.6.5.1 + + + +From 92a560913b1c587b79e5ebe63f90dfbea234a7d1 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 16 Jan 2009 11:00:08 -0500 +Subject: [PATCH 33/81] 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 | 322 ++++++++++++++++++++++++--------------- + daemon/gdm-session-private.h | 3 +- + daemon/gdm-session-relay.c | 29 +++-- + daemon/gdm-session-worker-job.c | 7 + + daemon/gdm-session-worker-job.h | 2 + + daemon/gdm-session.c | 20 ++- + daemon/gdm-session.h | 9 +- + daemon/gdm-simple-slave.c | 3 - + daemon/test-session.c | 13 +- + 11 files changed, 293 insertions(+), 175 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, + } + + static void +-on_session_opened (GdmSession *session, +- GdmFactorySlave *slave) ++on_session_conversation_started (GdmSession *session, ++ GdmFactorySlave *slave, ++ const char *service_name) + { +- g_debug ("GdmFactorySlave: session opened"); ++ g_debug ("GdmFactorySlave: session conversation started"); + + gdm_greeter_server_ready (slave->priv->greeter_server); + } +@@ -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 +@@ -694,8 +695,8 @@ gdm_factory_slave_start (GdmSlave *slave) + + 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, + } + + static void +-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); + } + + static void +-on_session_opened (GdmSession *session, +- GdmProductSlave *slave) ++on_session_conversation_started (GdmSession *session, ++ const char *service_name, ++ GdmProductSlave *slave) + { +- g_debug ("GdmProductSlave: session opened"); ++ g_debug ("GdmProductSlave: session conversation started"); + +- relay_session_opened (slave); ++ relay_session_conversation_started (slave, service_name); + } + + static void +@@ -784,10 +786,27 @@ on_relay_user_selected (GdmProductSlave *slave, + } + + static void +-on_relay_open (GdmProductSlave *slave, +- DBusMessage *message) ++on_relay_start_conversation (GdmProductSlave *slave, ++ DBusMessage *message) + { +- 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); + } + + static void +@@ -832,8 +851,8 @@ create_new_session (GdmProductSlave *slave) + g_free (display_device); + + 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 8eadf4d..fa257a0 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -61,6 +61,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; ++ + struct _GdmSessionDirectPrivate + { + /* per open scope */ +@@ -73,8 +83,7 @@ struct _GdmSessionDirectPrivate + char *selected_user; + char *user_x11_authority_file; + +- DBusMessage *message_pending_reply; +- DBusConnection *worker_connection; ++ GdmSessionConversation *conversation; + + GdmSessionWorkerJob *job; + GPid session_pid; +@@ -115,39 +124,39 @@ G_DEFINE_TYPE_WITH_CODE (GdmSessionDirect, + gdm_session_iface_init)) + + static gboolean +-send_dbus_message (DBusConnection *connection, +- DBusMessage *message) ++send_dbus_message (GdmSessionConversation *conversation, ++ DBusMessage *message) + { + 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; + } + + 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, +@@ -156,7 +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); + +- if (! send_dbus_message (session->priv->worker_connection, message)) { ++ if (! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", + name ? name : "(null)"); + } +@@ -165,18 +174,18 @@ send_dbus_string_signal (GdmSessionDirect *session, + } + + 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); + } + +@@ -188,22 +197,32 @@ on_authentication_failed (GdmSession *session, + 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 = 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_session_started (GdmSession *session) + { + 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); ++ } + } + + static void +@@ -211,11 +230,16 @@ on_session_start_failed (GdmSession *session, + 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 = 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); ++ } + } + + static void +@@ -223,6 +247,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, +@@ -731,54 +756,52 @@ gdm_session_direct_handle_username_changed (GdmSessionDirect *session, + } + + static void +-cancel_pending_query (GdmSessionDirect *session) ++cancel_pending_query (GdmSessionConversation *conversation) + { + DBusMessage *reply; + +- 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"); +- 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); + + 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 +-answer_pending_query (GdmSessionDirect *session, +- const char *answer) ++answer_pending_query (GdmSessionConversation *conversation, ++ const char *answer) + { + DBusMessage *reply; + DBusMessageIter iter; + +- g_assert (session->priv->message_pending_reply != NULL); +- +- 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); + +- 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 +-set_pending_query (GdmSessionDirect *session, +- DBusMessage *message) ++set_pending_query (GdmSessionConversation *conversation, ++ DBusMessage *message) + { +- g_assert (session->priv->message_pending_reply == NULL); ++ g_assert (conversation->message_pending_reply == NULL); + +- session->priv->message_pending_reply = dbus_message_ref (message); ++ conversation->message_pending_reply = dbus_message_ref (message); + } + + static DBusHandlerResult +@@ -788,6 +811,9 @@ gdm_session_direct_handle_info_query (GdmSessionDirect *session, + { + DBusError error; + const char *text; ++ GdmSessionConversation *conversation; ++ ++ conversation = session->priv->conversation; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, +@@ -796,7 +822,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), text); +@@ -811,6 +837,9 @@ gdm_session_direct_handle_secret_info_query (GdmSessionDirect *session, + { + DBusError error; + const char *text; ++ GdmSessionConversation *conversation; ++ ++ conversation = session->priv->conversation; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, +@@ -819,7 +848,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), text); +@@ -859,9 +888,13 @@ gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, + DBusMessage *message) + { + DBusMessage *reply; ++ GdmSessionConversation *conversation; + + g_debug ("GdmSessionDirect: worker cancelling pending query"); +- cancel_pending_query (session); ++ ++ conversation = session->priv->conversation; ++ ++ cancel_pending_query (conversation); + + reply = dbus_message_new_method_return (message); + dbus_connection_send (connection, reply, NULL); +@@ -1427,16 +1460,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 + }; + +- 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); + +@@ -1453,8 +1488,9 @@ handle_connection (DBusServer *server, + &vtable, + session); + +- 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); + } + } + +@@ -1524,8 +1560,6 @@ gdm_session_direct_init (GdmSessionDirect *session) + G_CALLBACK (on_session_exited), + NULL); + +- session->priv->session_pid = -1; +- + session->priv->environment = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, +@@ -1537,7 +1571,7 @@ gdm_session_direct_init (GdmSessionDirect *session) + + static void + worker_started (GdmSessionWorkerJob *job, +- GdmSessionDirect *session) ++ GdmSessionConversation *conversation) + { + g_debug ("GdmSessionDirect: Worker job started"); + } +@@ -1545,87 +1579,105 @@ worker_started (GdmSessionWorkerJob *job, + static void + worker_exited (GdmSessionWorkerJob *job, + int code, +- GdmSessionDirect *session) ++ GdmSessionConversation *conversation) + { + g_debug ("GdmSessionDirect: Worker job exited: %d", code); + +- if (session->priv->is_running) { +- _gdm_session_session_exited (GDM_SESSION (session), code); ++ if (conversation->session->priv->is_running) { ++ _gdm_session_session_exited (GDM_SESSION (conversation->session), code); + } + } + + static void + worker_died (GdmSessionWorkerJob *job, + int signum, +- GdmSessionDirect *session) ++ GdmSessionConversation *conversation) + { + g_debug ("GdmSessionDirect: Worker job died: %d", signum); + +- if (session->priv->is_running) { +- _gdm_session_session_died (GDM_SESSION (session), signum); ++ if (conversation->session->priv->is_running) { ++ _gdm_session_session_died (GDM_SESSION (conversation->session), signum); + } + } + +-static gboolean +-start_worker (GdmSessionDirect *session) ++static GdmSessionConversation * ++start_conversation (GdmSessionDirect *session, ++ const char *service_name) + { +- 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, + "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; ++ conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job); ++ ++ return conversation; + } + + static void +-stop_worker (GdmSessionDirect *session) ++stop_conversation (GdmSessionConversation *conversation) + { +- 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); + +- cancel_pending_query (session); ++ cancel_pending_query (conversation); + +- 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; + } + +- 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); + } + + static void +-gdm_session_direct_open (GdmSession *session) ++gdm_session_direct_start_conversation (GdmSession *session, ++ 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); + } + + static void +@@ -1638,6 +1690,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); + +@@ -1675,7 +1728,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 = session->priv->conversation; ++ if (! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", "Setup"); + } + +@@ -1693,6 +1747,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); + +@@ -1736,7 +1791,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, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForUser"); + } + +@@ -1750,7 +1806,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); +@@ -1764,7 +1821,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); +@@ -1777,22 +1835,28 @@ static void + gdm_session_direct_authenticate (GdmSession *session) + { + 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)); ++ 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"); + } + + static void + gdm_session_direct_authorize (GdmSession *session) + { + 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)); ++ 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"); ++ conversation = impl->priv->conversation; ++ send_dbus_void_signal (conversation, "Authorize"); + } + + static void +@@ -1800,16 +1864,19 @@ gdm_session_direct_accredit (GdmSession *session, + 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)); ++ g_return_if_fail (impl->priv->conversation != NULL); ++ g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); + ++ 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 (); +@@ -1823,6 +1890,7 @@ send_environment_variable (const char *key, + { + DBusMessage *message; + DBusMessageIter iter; ++ GdmSessionConversation *conversation; + + message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, + GDM_SESSION_DBUS_INTERFACE, +@@ -1832,7 +1900,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); + +- if (! send_dbus_message (session->priv->worker_connection, message)) { ++ conversation = session->priv->conversation; ++ if (! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable"); + } + +@@ -1965,6 +2034,7 @@ static void + gdm_session_direct_start_session (GdmSession *session) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + char *command; + char *program; + +@@ -1978,7 +2048,8 @@ gdm_session_direct_start_session (GdmSession *session) + setup_session_environment (impl); + send_environment (impl); + +- send_dbus_string_signal (impl, "StartProgram", program); ++ conversation = impl->priv->conversation; ++ send_dbus_string_signal (conversation, "StartProgram", program); + g_free (program); + } + +@@ -1991,16 +2062,12 @@ gdm_session_direct_close (GdmSession *session) + + 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); + } + + g_free (impl->priv->selected_user); +@@ -2038,10 +2105,13 @@ gdm_session_direct_answer_query (GdmSession *session, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + + g_return_if_fail (session != NULL); + +- answer_pending_query (impl, text); ++ conversation = impl->priv->conversation; ++ ++ answer_pending_query (conversation, text); + } + + static void +@@ -2051,7 +2121,7 @@ gdm_session_direct_cancel (GdmSession *session) + + g_return_if_fail (session != NULL); + +- cancel_pending_query (impl); ++ cancel_pending_query (impl->priv->conversation); + } + + char * +@@ -2067,6 +2137,7 @@ gdm_session_direct_select_session (GdmSession *session, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + + g_free (impl->priv->selected_session); + +@@ -2076,7 +2147,8 @@ gdm_session_direct_select_session (GdmSession *session, + impl->priv->selected_session = g_strdup (text); + } + +- send_dbus_string_signal (impl, "SetSessionName", ++ conversation = impl->priv->conversation; ++ send_dbus_string_signal (conversation, "SetSessionName", + get_session_name (impl)); + } + +@@ -2085,6 +2157,7 @@ gdm_session_direct_select_language (GdmSession *session, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + + g_free (impl->priv->selected_language); + +@@ -2094,7 +2167,8 @@ gdm_session_direct_select_language (GdmSession *session, + impl->priv->selected_language = g_strdup (text); + } + +- send_dbus_string_signal (impl, "SetLanguageName", ++ conversation = impl->priv->conversation; ++ send_dbus_string_signal (conversation, "SetLanguageName", + get_language_name (impl)); + } + +@@ -2103,6 +2177,7 @@ gdm_session_direct_select_layout (GdmSession *session, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; + + g_free (impl->priv->selected_layout); + +@@ -2112,7 +2187,8 @@ gdm_session_direct_select_layout (GdmSession *session, + impl->priv->selected_layout = g_strdup (text); + } + +- send_dbus_string_signal (impl, "SetLayoutName", ++ conversation = impl->priv->conversation; ++ send_dbus_string_signal (conversation, "SetLayoutName", + get_layout_name (impl)); + } + +@@ -2372,7 +2448,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 + + /* 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, + } + + 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 +@@ -664,22 +665,28 @@ handle_session_stopped (GdmSessionRelay *session_relay, + } + + 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); ++ } + +- g_debug ("GdmSessionRelay: Opened"); ++ g_debug ("GdmSessionRelay: Conversation Started"); + + reply = dbus_message_new_method_return (message); + 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); + + 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); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +@@ -749,7 +756,8 @@ do_introspect (DBusConnection *connection, + /* interface */ + xml = g_string_append (xml, + " \n" +- " \n" ++ " \n" ++ " \n" + " \n" + " \n" + " \n" +@@ -810,7 +818,8 @@ do_introspect (DBusConnection *connection, + " \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-worker-job.c b/daemon/gdm-session-worker-job.c +index 633d6e2..9c020fa 100644 +--- a/daemon/gdm-session-worker-job.c ++++ b/daemon/gdm-session-worker-job.c +@@ -296,6 +296,13 @@ gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job) + return TRUE; + } + ++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) +diff --git a/daemon/gdm-session-worker-job.h b/daemon/gdm-session-worker-job.h +index 5ad1c92..d24f025 100644 +--- a/daemon/gdm-session-worker-job.h ++++ b/daemon/gdm-session-worker-job.h +@@ -60,6 +60,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); + ++GPid gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job); ++ + G_END_DECLS + + #endif /* __GDM_SESSION_WORKER_JOB_H */ +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 8b161bb..12e514e 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -174,7 +174,6 @@ reset_session (GdmSimpleSlave *slave) + { + destroy_session (slave); + create_new_session (slave); +- gdm_session_open (GDM_SESSION (slave->priv->session)); + } + + static gboolean +@@ -822,8 +821,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.5.1 + + +From 8516e66b11d4e009ff7913d7996a407efbeb4eb5 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 4 Feb 2009 10:55:03 -0500 +Subject: [PATCH 34/81] Rename session worker to the service it's managing + +This way when we're running multiple PAM conversations at once +it will be obvious which worker is managing which conversation. +--- + 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 fa257a0..51ecf39 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -1605,6 +1605,7 @@ start_conversation (GdmSessionDirect *session, + const char *service_name) + { + GdmSessionConversation *conversation; ++ char *job_name; + + conversation = g_new0 (GdmSessionConversation, 1); + conversation->session = session; +@@ -1625,12 +1626,16 @@ start_conversation (GdmSessionDirect *session, + G_CALLBACK (worker_died), + conversation); + +- 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); + + conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job); + +diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c +index 9c020fa..0327d77 100644 +--- a/daemon/gdm-session-worker-job.c ++++ b/daemon/gdm-session-worker-job.c +@@ -149,6 +149,37 @@ copy_environment_to_hash (GHashTable *hash) + } + + 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; +@@ -171,31 +202,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, +@@ -204,6 +235,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); + +@@ -220,7 +254,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; +@@ -233,13 +266,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) { + +@@ -287,6 +321,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 d24f025..4833f23 100644 +--- a/daemon/gdm-session-worker-job.h ++++ b/daemon/gdm-session-worker-job.h +@@ -57,7 +57,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.5.1 + + +From b3c168d5cff70b47b1cc87acd6941bcf78a1e1fd Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 16 Jan 2009 13:01:48 -0500 +Subject: [PATCH 35/81] 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 | 32 ++++++++++++++---- + gui/simple-greeter/gdm-greeter-client.c | 18 ++++++---- + gui/simple-greeter/gdm-greeter-client.h | 4 ++- + gui/simple-greeter/gdm-greeter-session.c | 4 ++ + 7 files changed, 99 insertions(+), 20 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 cecce83..ffca7ec 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" +@@ -759,6 +795,7 @@ do_introspect (DBusConnection *connection, + " \n" + " \n" + " \n" ++ " \n" + " \n" + " \n" + " \n" +@@ -1121,6 +1158,16 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) + "group name", + GDM_GROUPNAME, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); ++ signals [START_CONVERSATION] = ++ g_signal_new ("start-conversation", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmGreeterServerClass, start_conversation), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, ++ 1, G_TYPE_STRING); + 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; + ++ 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_for_user)(GdmGreeterServer *greeter_server, +@@ -85,7 +87,8 @@ gboolean gdm_greeter_server_info (GdmGreeterServer * + gboolean gdm_greeter_server_problem (GdmGreeterServer *greeter_server, + 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); + 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 12e514e..8863fd4 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -484,17 +484,19 @@ on_session_secret_info_query (GdmSession *session, + } + + 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; + 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"); + } +@@ -510,8 +512,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); + } + +@@ -603,8 +607,8 @@ create_new_session (GdmSimpleSlave *slave) + 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, + "setup-complete", +@@ -735,6 +739,16 @@ on_greeter_session_died (GdmGreeterSession *greeter, + } + + 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); ++ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), ++ service_name); ++} ++ ++static void + on_greeter_begin_verification (GdmGreeterServer *greeter_server, + GdmSimpleSlave *slave) + { +@@ -909,6 +923,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); + } + + static void +@@ -400,6 +396,14 @@ send_dbus_void_method (DBusConnection *connection, + } + + 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) + { +@@ -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); + + 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); +diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c +index e7d206a..cd0cbdf 100644 +--- a/gui/simple-greeter/gdm-greeter-session.c ++++ b/gui/simple-greeter/gdm-greeter-session.c +@@ -85,6 +85,7 @@ on_problem (GdmGreeterClient *client, + + static void + on_ready (GdmGreeterClient *client, ++ const char *service_name, + GdmGreeterSession *session) + { + g_debug ("GdmGreeterSession: Ready"); +@@ -270,6 +271,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 +@@ -439,6 +441,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.5.1 + + +From 0fe56d49e631bafe55a4540cc73b761fd2751185 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 16 Jan 2009 15:18:31 -0500 +Subject: [PATCH 36/81] 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 | 123 +++++++++++++++++++++++++++++++++++++------ + 1 files changed, 106 insertions(+), 17 deletions(-) + +diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c +index 51ecf39..b86475c 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -84,6 +84,7 @@ struct _GdmSessionDirectPrivate + char *user_x11_authority_file; + + GdmSessionConversation *conversation; ++ GHashTable *conversations; + + GdmSessionWorkerJob *job; + GPid session_pid; +@@ -1454,6 +1455,42 @@ allow_user_function (DBusConnection *connection, + return FALSE; + } + ++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 GdmSessionConversation * ++find_conversation_by_pid (GdmSessionDirect *session, ++ GPid pid) ++{ ++ 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, +@@ -1461,10 +1498,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; ++ } ++ + if (conversation->worker_connection == NULL) { + DBusObjectPathVTable vtable = { &session_unregister_handler, + &session_message_handler, +@@ -1537,6 +1586,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, +@@ -1560,6 +1620,11 @@ gdm_session_direct_init (GdmSessionDirect *session) + G_CALLBACK (on_session_exited), + NULL); + ++ 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, +@@ -1659,17 +1724,15 @@ stop_conversation (GdmSessionConversation *conversation) + G_CALLBACK (worker_died), + conversation); + +- cancel_pending_query (conversation); +- + if (conversation->worker_connection != NULL) { + dbus_connection_close (conversation->worker_connection); + conversation->worker_connection = NULL; + } + + gdm_session_worker_job_stop (conversation->job); ++ + g_object_unref (conversation->job); +- g_free (conversation->service_name); +- g_free (conversation); ++ conversation->job = NULL; + } + + static void +@@ -1677,12 +1740,20 @@ gdm_session_direct_start_conversation (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"); + +- 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; ++ } + } + + static void +@@ -1733,8 +1804,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"); + } + +@@ -1796,8 +1867,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"); + } + +@@ -1811,8 +1882,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); +@@ -1826,8 +1895,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); + + gdm_session_direct_select_user (session, username); +@@ -2059,6 +2126,28 @@ gdm_session_direct_start_session (GdmSession *session) + } + + 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); +@@ -2075,6 +2164,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; + +@@ -2122,11 +2213,9 @@ gdm_session_direct_answer_query (GdmSession *session, + static void + gdm_session_direct_cancel (GdmSession *session) + { +- GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +- + g_return_if_fail (session != NULL); + +- cancel_pending_query (impl->priv->conversation); ++ stop_all_conversations (GDM_SESSION_DIRECT (session)); + } + + char * +-- +1.6.5.1 + + +From eed69f233f58a00167729eb0e9f32734d4e9202f Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 4 Mar 2009 22:09:21 -0500 +Subject: [PATCH 37/81] start autologin conversation when creating session if necessary + +Without this autologin breaks, since when it comes time to +autologin, there's no worker to do it. +--- + daemon/gdm-simple-slave.c | 10 ++++++++++ + 1 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index 8863fd4..4db7440 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -1036,8 +1036,18 @@ idle_connect_to_display (GdmSimpleSlave *slave) + if (! enabled || delay > 0) { + start_greeter (slave); + create_new_session (slave); ++ ++ if (enabled) { ++ g_debug ("GdmSimpleSlave: Starting timed login conversation"); ++ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), ++ "gdm-autologin"); ++ } + } else { + reset_session (slave); ++ ++ g_debug ("GdmSimpleSlave: Starting automatic login conversation"); ++ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), ++ "gdm-autologin"); + } + } else { + if (slave->priv->connection_attempts >= MAX_CONNECT_ATTEMPTS) { +-- +1.6.5.1 + + +From 71332bb2610827f1ad16ffcef257e5e980a47f41 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 22 Jan 2009 08:52:01 -0500 +Subject: [PATCH 38/81] Propagate service name to more layers + +This is more prep work to get multiple concurrent +PAM stacks going. +--- + daemon/gdm-factory-slave.c | 63 +++-- + daemon/gdm-greeter-server.c | 120 ++++++-- + daemon/gdm-greeter-server.h | 17 +- + daemon/gdm-product-slave.c | 233 ++++++++++++--- + daemon/gdm-session-direct.c | 472 +++++++++++++++++------------- + daemon/gdm-session-private.h | 22 ++- + daemon/gdm-session-relay.c | 122 ++++++-- + daemon/gdm-session-worker.c | 27 ++ + daemon/gdm-session.c | 151 ++++++---- + daemon/gdm-session.h | 44 +++- + daemon/gdm-simple-slave.c | 70 ++++-- + daemon/test-session.c | 22 +- + gui/simple-greeter/gdm-greeter-client.c | 188 ++++++++++--- + gui/simple-greeter/gdm-greeter-client.h | 16 +- + gui/simple-greeter/gdm-greeter-session.c | 11 +- + 15 files changed, 1125 insertions(+), 453 deletions(-) + +diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c +index d1bb5dd..826612e 100644 +--- a/daemon/gdm-factory-slave.c ++++ b/daemon/gdm-factory-slave.c +@@ -144,45 +144,49 @@ on_greeter_session_died (GdmGreeterSession *greeter, static void on_session_info (GdmSession *session, @@ -162,19 +2427,15 @@ diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm- } static void --on_session_opened (GdmSession *session, -- GdmFactorySlave *slave) -+on_session_conversation_started (GdmSession *session, + 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"); + g_debug ("GdmFactorySlave: session conversation started"); -- gdm_greeter_server_ready (slave->priv->greeter_server); -+ gdm_greeter_server_ready (slave->priv->greeter_server, -+ service_name); - } +@@ -192,17 +196,19 @@ on_session_conversation_started (GdmSession *session, static void on_session_setup_complete (GdmSession *session, @@ -196,7 +2457,7 @@ diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm- queue_greeter_reset (slave); } -@@ -222,23 +230,26 @@ on_session_reset_failed (GdmSession +@@ -224,23 +230,26 @@ on_session_reset_failed (GdmSession *session, static void on_session_authenticated (GdmSession *session, @@ -225,7 +2486,7 @@ diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm- GdmFactorySlave *slave) { int flag; -@@ -246,39 +257,65 @@ on_session_authorized (GdmSession * +@@ -248,39 +257,42 @@ on_session_authorized (GdmSession *session, /* FIXME: check for migration? */ flag = GDM_SESSION_CRED_ESTABLISH; @@ -253,9 +2514,9 @@ diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm- g_debug ("GdmFactorySlave: session user verified"); - gdm_session_start_session (session); -- -- gdm_greeter_server_reset (slave->priv->greeter_server); -+ gdm_session_open_session (session, service_name); ++ gdm_session_start_session (session, service_name); + + gdm_greeter_server_reset (slave->priv->greeter_server); } static void @@ -269,35 +2530,10 @@ diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm- - 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); -+} -+ -+static void -+on_session_opened (GdmSession *session, -+ const char *service_name, -+ GdmFactorySlave *slave) -+{ -+ g_debug ("GdmFactorySlave: session opened"); -+ -+ gdm_session_start_session (session, service_name); -+ -+ gdm_greeter_server_reset (slave->priv->greeter_server); -+} -+ -+static void -+on_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *message, -+ GdmFactorySlave *slave) -+{ -+ g_debug ("GdmFactorySlave: could not open session: %s", message); -+ -+ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to open session")); queue_greeter_reset (slave); } -@@ -366,37 +403,48 @@ on_session_relay_connected (GdmSessionRe +@@ -368,37 +380,48 @@ on_session_relay_connected (GdmSessionRelay *session, GdmFactorySlave *slave) { g_debug ("GdmFactorySlave: Relay Connected"); @@ -310,7 +2546,7 @@ diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm- +{ + g_debug ("GdmFactorySlave: start conversation"); -- gdm_session_open (GDM_SESSION (slave->priv->session)); +- gdm_session_start_conversation (GDM_SESSION (slave->priv->session), "gdm"); + gdm_session_start_conversation (GDM_SESSION (slave->priv->session), service_name); } @@ -350,7 +2586,7 @@ diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm- } static void -@@ -493,6 +541,10 @@ run_greeter (GdmFactorySlave *slave) +@@ -495,6 +518,10 @@ run_greeter (GdmFactorySlave *slave) slave->priv->greeter_server = gdm_greeter_server_new (display_id); g_signal_connect (slave->priv->greeter_server, @@ -361,35 +2597,10 @@ diff -up gdm-2.28.0/daemon/gdm-factory-slave.c.multistack gdm-2.28.0/daemon/gdm- "begin-verification", G_CALLBACK (on_greeter_begin_verification), slave); -@@ -694,8 +746,8 @@ gdm_factory_slave_start (GdmSlave *slave - - 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", -@@ -738,6 +790,14 @@ gdm_factory_slave_start (GdmSlave *slave - G_CALLBACK (on_session_accreditation_failed), - slave); - g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, -+ "session-opened", -+ G_CALLBACK (on_session_opened), -+ slave); -+ g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, -+ "session-open-failed", -+ G_CALLBACK (on_session_open_failed), -+ slave); -+ g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, - "info", - G_CALLBACK (on_session_info), - slave); -diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm-greeter-server.c ---- gdm-2.28.0/daemon/gdm-greeter-server.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-greeter-server.c 2009-09-23 18:46:06.658640357 -0400 +diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c +index ffca7ec..dae34c5 100644 +--- a/daemon/gdm-greeter-server.c ++++ b/daemon/gdm-greeter-server.c @@ -43,6 +43,7 @@ #include #include @@ -398,15 +2609,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm #include "gdm-greeter-server.h" #define GDM_GREETER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/GreeterServer" -@@ -69,6 +70,7 @@ enum { - }; - - enum { -+ START_CONVERSATION, - BEGIN_AUTO_LOGIN, - BEGIN_VERIFICATION, - BEGIN_VERIFICATION_FOR_USER, -@@ -155,6 +157,46 @@ send_dbus_string_and_int_signal (GdmGree +@@ -156,6 +157,46 @@ send_dbus_string_and_int_signal (GdmGreeterServer *greeter_server, } static void @@ -453,7 +2656,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm send_dbus_string_signal (GdmGreeterServer *greeter_server, const char *name, const char *text) -@@ -207,34 +249,38 @@ send_dbus_void_signal (GdmGreeterServer +@@ -208,34 +249,38 @@ send_dbus_void_signal (GdmGreeterServer *greeter_server, gboolean gdm_greeter_server_info_query (GdmGreeterServer *greeter_server, @@ -496,28 +2699,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm return TRUE; } -@@ -246,9 +292,18 @@ gdm_greeter_server_reset (GdmGreeterServ - } - - 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; -+} -+ -+gboolean -+gdm_greeter_server_conversation_stopped (GdmGreeterServer *greeter_server, -+ const char *service_name) -+{ -+ send_dbus_string_signal (greeter_server, "ConversationStopped", service_name); - return TRUE; - } - -@@ -289,9 +344,10 @@ gdm_greeter_server_request_timed_login ( +@@ -291,9 +336,10 @@ gdm_greeter_server_request_timed_login (GdmGreeterServer *greeter_server, } void @@ -530,40 +2712,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm } /* Note: Use abstract sockets like dbus does by default on Linux. Abstract -@@ -323,11 +379,49 @@ 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, +@@ -358,6 +404,16 @@ handle_begin_verification (GdmGreeterServer *greeter_server, DBusMessage *message) { DBusMessage *reply; @@ -580,7 +2729,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm g_debug ("GreeterServer: BeginVerification"); -@@ -335,7 +429,7 @@ handle_begin_verification (GdmGreeterSer +@@ -365,7 +421,7 @@ handle_begin_verification (GdmGreeterServer *greeter_server, dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -589,7 +2738,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm return DBUS_HANDLER_RESULT_HANDLED; } -@@ -349,7 +443,6 @@ handle_begin_auto_login (GdmGreeterServe +@@ -379,7 +435,6 @@ handle_begin_auto_login (GdmGreeterServer *greeter_server, DBusError error; const char *text; @@ -597,7 +2746,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm 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 +@@ -406,13 +461,16 @@ handle_begin_verification_for_user (GdmGreeterServer *greeter_server, DBusMessage *reply; DBusError error; const char *text; @@ -614,7 +2763,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm g_debug ("GreeterServer: BeginVerificationForUser for '%s'", text); -@@ -390,7 +486,7 @@ handle_begin_verification_for_user (GdmG +@@ -420,7 +478,7 @@ handle_begin_verification_for_user (GdmGreeterServer *greeter_server, dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -623,7 +2772,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm return DBUS_HANDLER_RESULT_HANDLED; } -@@ -403,13 +499,16 @@ handle_answer_query (GdmGreeterServer *g +@@ -433,13 +491,16 @@ handle_answer_query (GdmGreeterServer *greeter_server, DBusMessage *reply; DBusError error; const char *text; @@ -640,7 +2789,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm g_debug ("GreeterServer: AnswerQuery"); -@@ -417,7 +516,7 @@ handle_answer_query (GdmGreeterServer *g +@@ -447,7 +508,7 @@ handle_answer_query (GdmGreeterServer *greeter_server, dbus_connection_send (connection, reply, NULL); dbus_message_unref (reply); @@ -649,7 +2798,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm return DBUS_HANDLER_RESULT_HANDLED; } -@@ -614,9 +713,11 @@ handle_start_session_when_ready (GdmGree +@@ -644,9 +705,11 @@ handle_start_session_when_ready (GdmGreeterServer *greeter_server, DBusMessage *reply; DBusError error; gboolean should_start_session; @@ -661,7 +2810,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm 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 +@@ -660,9 +723,9 @@ handle_start_session_when_ready (GdmGreeterServer *greeter_server, dbus_message_unref (reply); if (should_start_session) { @@ -673,30 +2822,12 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm } 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" +@@ -735,13 +798,16 @@ do_introspect (DBusConnection *connection, + " \n" + " \n" " \n" + " \n" -+ " \n" + " \n" " \n" " \n" " \n" @@ -708,7 +2839,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm " \n" " \n" " \n" -@@ -728,18 +841,23 @@ do_introspect (DBusConnection *connectio +@@ -764,18 +830,23 @@ do_introspect (DBusConnection *connection, " \n" " \n" " \n" @@ -732,23 +2863,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm " \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" +@@ -800,6 +871,7 @@ do_introspect (DBusConnection *connection, " \n" " \n" " \n" @@ -756,24 +2871,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm " \n" " \n"); -@@ -1122,6 +1244,16 @@ gdm_greeter_server_class_init (GdmGreete - "group name", - GDM_GROUPNAME, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); -+ signals [START_CONVERSATION] = -+ g_signal_new ("start-conversation", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmGreeterServerClass, start_conversation), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, -+ 1, G_TYPE_STRING); - signals [BEGIN_VERIFICATION] = - g_signal_new ("begin-verification", - G_OBJECT_CLASS_TYPE (object_class), -@@ -1129,9 +1261,9 @@ gdm_greeter_server_class_init (GdmGreete +@@ -1175,9 +1247,9 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) G_STRUCT_OFFSET (GdmGreeterServerClass, begin_verification), NULL, NULL, @@ -785,7 +2883,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm 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 +@@ -1196,10 +1268,10 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) G_STRUCT_OFFSET (GdmGreeterServerClass, begin_verification_for_user), NULL, NULL, @@ -799,7 +2897,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm signals [QUERY_ANSWER] = g_signal_new ("query-answer", G_OBJECT_CLASS_TYPE (object_class), -@@ -1161,10 +1293,10 @@ gdm_greeter_server_class_init (GdmGreete +@@ -1207,10 +1279,10 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) G_STRUCT_OFFSET (GdmGreeterServerClass, query_answer), NULL, NULL, @@ -813,7 +2911,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm signals [SESSION_SELECTED] = g_signal_new ("session-selected", G_OBJECT_CLASS_TYPE (object_class), -@@ -1258,9 +1390,9 @@ gdm_greeter_server_class_init (GdmGreete +@@ -1304,9 +1376,9 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) G_STRUCT_OFFSET (GdmGreeterServerClass, start_session_when_ready), NULL, NULL, @@ -825,7 +2923,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm signals [START_SESSION_LATER] = g_signal_new ("start-session-later", -@@ -1269,9 +1401,9 @@ gdm_greeter_server_class_init (GdmGreete +@@ -1315,9 +1387,9 @@ gdm_greeter_server_class_init (GdmGreeterServerClass *klass) G_STRUCT_OFFSET (GdmGreeterServerClass, start_session_later), NULL, NULL, @@ -837,15 +2935,13 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.c.multistack gdm-2.28.0/daemon/gdm } static void -diff -up gdm-2.28.0/daemon/gdm-greeter-server.h.multistack gdm-2.28.0/daemon/gdm-greeter-server.h ---- gdm-2.28.0/daemon/gdm-greeter-server.h.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-greeter-server.h 2009-09-23 18:46:06.659640973 -0400 -@@ -45,11 +45,16 @@ typedef struct - { - GObjectClass parent_class; - -+ void (* start_conversation) (GdmGreeterServer *greeter_server, -+ const char *service_name); +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, @@ -858,7 +2954,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.h.multistack gdm-2.28.0/daemon/gdm const char *text); void (* session_selected) (GdmGreeterServer *greeter_server, const char *name); -@@ -64,7 +69,8 @@ typedef struct +@@ -66,7 +69,8 @@ typedef struct void (* cancelled) (GdmGreeterServer *greeter_server); void (* connected) (GdmGreeterServer *greeter_server); void (* disconnected) (GdmGreeterServer *greeter_server); @@ -868,7 +2964,7 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.h.multistack gdm-2.28.0/daemon/gdm void (* start_session_later) (GdmGreeterServer *greeter_server); } GdmGreeterServerClass; -@@ -75,17 +81,23 @@ gboolean gdm_greeter_server_s +@@ -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); @@ -886,15 +2982,8 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.h.multistack gdm-2.28.0/daemon/gdm + 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, -@@ -98,8 +110,8 @@ void gdm_greeter_server_d + 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); @@ -905,9 +2994,10 @@ diff -up gdm-2.28.0/daemon/gdm-greeter-server.h.multistack gdm-2.28.0/daemon/gdm G_END_DECLS -diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm-product-slave.c ---- gdm-2.28.0/daemon/gdm-product-slave.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-product-slave.c 2009-09-23 18:46:06.676640203 -0400 +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 DBusGProxy *product_display_proxy; @@ -917,7 +3007,7 @@ diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm- }; enum { -@@ -93,6 +95,68 @@ static void gdm_product_slave_finali +@@ -93,6 +95,68 @@ static void gdm_product_slave_finalize (GObject *object); G_DEFINE_TYPE (GdmProductSlave, gdm_product_slave, GDM_TYPE_SLAVE) static gboolean @@ -986,36 +3076,7 @@ diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm- send_dbus_string_method (DBusConnection *connection, const char *method, const char *payload) -@@ -246,19 +310,21 @@ relay_session_started (GdmProductSlave * - } - - static void --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); - } - - static void --on_session_opened (GdmSession *session, -- GdmProductSlave *slave) -+on_session_conversation_started (GdmSession *session, -+ const char *service_name, -+ GdmProductSlave *slave) - { -- g_debug ("GdmProductSlave: session opened"); -+ g_debug ("GdmProductSlave: session conversation started"); - -- relay_session_opened (slave); -+ relay_session_conversation_started (slave, service_name); - } - - static void -@@ -354,7 +420,8 @@ setup_session (GdmProductSlave *slave) +@@ -356,7 +420,8 @@ setup_session (GdmProductSlave *slave) g_free (display_device); g_free (auth_file); @@ -1025,7 +3086,7 @@ diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm- return TRUE; } -@@ -506,96 +573,133 @@ on_session_reset_failed (GdmSession +@@ -508,96 +573,112 @@ on_session_reset_failed (GdmSession *session, static void on_session_authenticated (GdmSession *session, @@ -1096,31 +3157,11 @@ diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm- const char *message, GdmProductSlave *slave) { -+ send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "AccreditationFailed", -+ service_name, -+ message); -+} -+ -+static void -+on_session_opened (GdmSession *session, -+ const char *service_name, -+ GdmProductSlave *slave) -+{ - send_dbus_string_method (slave->priv->session_relay_connection, +- send_dbus_string_method (slave->priv->session_relay_connection, - "AccreditationFailed", - message); -+ "SessionOpened", service_name); -+} -+ -+static void -+on_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *message, -+ GdmProductSlave *slave) -+{ + send_dbus_string_string_method (slave->priv->session_relay_connection, -+ "SessionOpenFailed", ++ "AccreditationFailed", + service_name, + message); } @@ -1185,7 +3226,7 @@ diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm- } static void -@@ -656,36 +760,92 @@ static void +@@ -658,36 +739,92 @@ static void on_relay_authenticate (GdmProductSlave *slave, DBusMessage *message) { @@ -1286,7 +3327,7 @@ diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm- } static void -@@ -694,16 +854,18 @@ on_relay_answer_query (GdmProductSlave * +@@ -696,16 +833,18 @@ on_relay_answer_query (GdmProductSlave *slave, { DBusError error; const char *text; @@ -1306,37 +3347,7 @@ diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm- } else { g_warning ("Unable to get arguments: %s", error.message); dbus_error_free (&error); -@@ -784,17 +946,52 @@ on_relay_user_selected (GdmProductSlave - } - - static void --on_relay_open (GdmProductSlave *slave, -- DBusMessage *message) -+on_relay_start_conversation (GdmProductSlave *slave, -+ DBusMessage *message) - { -- 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); - } - - static void +@@ -813,7 +952,25 @@ static void on_relay_start_session (GdmProductSlave *slave, DBusMessage *message) { @@ -1363,48 +3374,1618 @@ diff -up gdm-2.28.0/daemon/gdm-product-slave.c.multistack gdm-2.28.0/daemon/gdm- } static void -@@ -832,8 +1029,8 @@ create_new_session (GdmProductSlave *sla - g_free (display_device); +diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c +index b86475c..1c151fd 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -83,10 +83,10 @@ struct _GdmSessionDirectPrivate + char *selected_user; + char *user_x11_authority_file; - 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", -@@ -875,7 +1072,14 @@ create_new_session (GdmProductSlave *sla - "accreditation-failed", - G_CALLBACK (on_session_accreditation_failed), - slave); +- GdmSessionConversation *conversation; + GHashTable *conversations; + +- GdmSessionWorkerJob *job; ++ GList *pending_connections; ++ + GPid session_pid; + guint32 is_running : 1; + +@@ -193,14 +193,30 @@ send_dbus_void_signal (GdmSessionConversation *conversation, + dbus_message_unref (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; + +- 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 +227,13 @@ on_authentication_failed (GdmSession *session, + } + + static void +-on_session_started (GdmSession *session) ++on_session_started (GdmSession *session, ++ const char *service_name) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); + GdmSessionConversation *conversation; + +- 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 +245,13 @@ on_session_started (GdmSession *session) + + static void + on_session_start_failed (GdmSession *session, ++ const char *service_name, + const char *message) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); + GdmSessionConversation *conversation; + +- 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 +276,7 @@ on_session_exited (GdmSession *session, + + static DBusHandlerResult + gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -266,17 +284,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 +309,12 @@ gdm_session_direct_handle_setup_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 'setup-failed' signal"); + +- _gdm_session_setup_failed (GDM_SESSION (session), text); ++ _gdm_session_setup_failed (GDM_SESSION (session), conversation->service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -304,7 +322,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 +330,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 +340,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) + { + DBusMessage *reply; +@@ -337,7 +355,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 +367,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 +375,17 @@ gdm_session_direct_handle_authenticated (GdmSessionDirect *session, + g_debug ("GdmSessionDirect: Emitting 'authenticated' 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_authenticated (GDM_SESSION (session)); ++ _gdm_session_authenticated (GDM_SESSION (session), conversation->service_name); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + static DBusHandlerResult + gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -382,19 +400,19 @@ gdm_session_direct_handle_authentication_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 'authentication-failed' signal"); + +- _gdm_session_authentication_failed (GDM_SESSION (session), text); ++ _gdm_session_authentication_failed (GDM_SESSION (session), conversation->service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + static DBusHandlerResult + gdm_session_direct_handle_authorized (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -402,17 +420,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); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + static DBusHandlerResult + gdm_session_direct_handle_authorization_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -427,19 +445,19 @@ gdm_session_direct_handle_authorization_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 'authorization-failed' signal"); + +- _gdm_session_authorization_failed (GDM_SESSION (session), text); ++ _gdm_session_authorization_failed (GDM_SESSION (session), conversation->service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + static DBusHandlerResult + gdm_session_direct_handle_accredited (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -447,17 +465,17 @@ gdm_session_direct_handle_accredited (GdmSessionDirect *session, + 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 DBusHandlerResult + gdm_session_direct_handle_accreditation_failed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -472,12 +490,12 @@ gdm_session_direct_handle_accreditation_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 'accreditation-failed' signal"); + +- _gdm_session_accreditation_failed (GDM_SESSION (session), text); ++ _gdm_session_accreditation_failed (GDM_SESSION (session), conversation->service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -725,7 +743,7 @@ gdm_session_direct_select_user (GdmSession *session, + + static DBusHandlerResult + gdm_session_direct_handle_username_changed (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -740,7 +758,7 @@ gdm_session_direct_handle_username_changed (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: changing username from '%s' to '%s'", +@@ -807,14 +825,11 @@ set_pending_query (GdmSessionConversation *conversation, + + static DBusHandlerResult + gdm_session_direct_handle_info_query (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusError error; + const char *text; +- GdmSessionConversation *conversation; - -+ g_signal_connect (slave->priv->session, -+ "session-opened", -+ G_CALLBACK (on_session_opened), -+ slave); -+ g_signal_connect (slave->priv->session, -+ "session-open-failed", -+ G_CALLBACK (on_session_open_failed), -+ slave); - g_signal_connect (slave->priv->session, - "info", - G_CALLBACK (on_session_info), -@@ -991,8 +1195,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.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-session.c ---- gdm-2.28.0/daemon/gdm-session.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-session.c 2009-09-23 18:46:06.690641636 -0400 -@@ -24,11 +24,13 @@ +- conversation = session->priv->conversation; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, +@@ -826,21 +841,18 @@ gdm_session_direct_handle_info_query (GdmSessionDirect *session, + set_pending_query (conversation, 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; + const char *text; +- GdmSessionConversation *conversation; +- +- conversation = session->priv->conversation; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, +@@ -852,14 +864,14 @@ gdm_session_direct_handle_secret_info_query (GdmSessionDirect *session, + set_pending_query (conversation, 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; + } + + static DBusHandlerResult + gdm_session_direct_handle_info (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -874,31 +886,28 @@ gdm_session_direct_handle_info (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 'info' signal"); +- _gdm_session_info (GDM_SESSION (session), text); ++ _gdm_session_info (GDM_SESSION (session), conversation->service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + static DBusHandlerResult + gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +- GdmSessionConversation *conversation; + + g_debug ("GdmSessionDirect: worker cancelling pending query"); + +- conversation = session->priv->conversation; +- + 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); + + return DBUS_HANDLER_RESULT_HANDLED; +@@ -906,7 +915,7 @@ gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, + + static DBusHandlerResult + gdm_session_direct_handle_problem (GdmSessionDirect *session, +- DBusConnection *connection, ++ GdmSessionConversation *conversation, + DBusMessage *message) + { + DBusMessage *reply; +@@ -921,18 +930,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; +@@ -951,7 +960,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'", +@@ -960,14 +969,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; +@@ -982,18 +991,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; +@@ -1008,7 +1017,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'", +@@ -1022,7 +1031,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; +@@ -1037,7 +1046,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'", +@@ -1051,7 +1060,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; +@@ -1066,7 +1075,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, +@@ -1084,7 +1093,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; +@@ -1099,7 +1108,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, +@@ -1117,7 +1126,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; +@@ -1132,7 +1141,7 @@ gdm_session_direct_handle_saved_session_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 (! get_session_command_for_name (session_name, NULL)) { +@@ -1160,54 +1169,57 @@ session_worker_message (DBusConnection *connection, + DBusMessage *message, + void *user_data) + { +- GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); ++ GdmSessionConversation *conversation = user_data; ++ GdmSessionDirect *session; ++ ++ session = conversation->session; + + if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "InfoQuery")) { +- return gdm_session_direct_handle_info_query (session, connection, message); ++ return gdm_session_direct_handle_info_query (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SecretInfoQuery")) { +- return gdm_session_direct_handle_secret_info_query (session, connection, message); ++ return gdm_session_direct_handle_secret_info_query (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Info")) { +- return gdm_session_direct_handle_info (session, connection, message); ++ return gdm_session_direct_handle_info (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Problem")) { +- return gdm_session_direct_handle_problem (session, connection, message); ++ return gdm_session_direct_handle_problem (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "CancelPendingQuery")) { +- return gdm_session_direct_handle_cancel_pending_query (session, connection, message); ++ return gdm_session_direct_handle_cancel_pending_query (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupComplete")) { +- return gdm_session_direct_handle_setup_complete (session, connection, message); ++ return gdm_session_direct_handle_setup_complete (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupFailed")) { +- return gdm_session_direct_handle_setup_failed (session, connection, message); ++ return gdm_session_direct_handle_setup_failed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetComplete")) { +- return gdm_session_direct_handle_reset_complete (session, connection, message); ++ return gdm_session_direct_handle_reset_complete (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetFailed")) { +- return gdm_session_direct_handle_reset_failed (session, connection, message); ++ return gdm_session_direct_handle_reset_failed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authenticated")) { +- return gdm_session_direct_handle_authenticated (session, connection, message); ++ return gdm_session_direct_handle_authenticated (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthenticationFailed")) { +- return gdm_session_direct_handle_authentication_failed (session, connection, message); ++ return gdm_session_direct_handle_authentication_failed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authorized")) { +- return gdm_session_direct_handle_authorized (session, connection, message); ++ return gdm_session_direct_handle_authorized (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthorizationFailed")) { +- return gdm_session_direct_handle_authorization_failed (session, connection, message); ++ return gdm_session_direct_handle_authorization_failed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Accredited")) { +- return gdm_session_direct_handle_accredited (session, connection, message); ++ return gdm_session_direct_handle_accredited (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AccreditationFailed")) { +- return gdm_session_direct_handle_accreditation_failed (session, connection, message); ++ return gdm_session_direct_handle_accreditation_failed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) { +- return gdm_session_direct_handle_username_changed (session, connection, message); ++ return gdm_session_direct_handle_username_changed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) { +- return gdm_session_direct_handle_session_started (session, connection, message); ++ return gdm_session_direct_handle_session_started (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartFailed")) { +- return gdm_session_direct_handle_start_failed (session, connection, message); ++ return gdm_session_direct_handle_start_failed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionExited")) { +- return gdm_session_direct_handle_session_exited (session, connection, message); ++ return gdm_session_direct_handle_session_exited (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionDied")) { +- return gdm_session_direct_handle_session_died (session, connection, message); ++ return gdm_session_direct_handle_session_died (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLanguageNameRead")) { +- return gdm_session_direct_handle_saved_language_name_read (session, connection, message); ++ return gdm_session_direct_handle_saved_language_name_read (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLayoutNameRead")) { +- return gdm_session_direct_handle_saved_layout_name_read (session, connection, message); ++ return gdm_session_direct_handle_saved_layout_name_read (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedSessionNameRead")) { +- return gdm_session_direct_handle_saved_session_name_read (session, connection, message); ++ return gdm_session_direct_handle_saved_session_name_read (session, conversation, message); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +@@ -1441,6 +1453,27 @@ session_unregister_handler (DBusConnection *connection, + g_debug ("session_unregister_handler"); + } + ++static GdmSessionConversation * ++find_conversation_by_pid (GdmSessionDirect *session, ++ GPid pid) ++{ ++ 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 dbus_bool_t + allow_user_function (DBusConnection *connection, + unsigned long uid, +@@ -1455,40 +1488,83 @@ allow_user_function (DBusConnection *connection, + return FALSE; + } + +-static GdmSessionConversation * +-find_conversation_by_name (GdmSessionDirect *session, +- const char *service_name) ++static gboolean ++register_worker (GdmSessionDirect *session, ++ DBusConnection *connection) + { + 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); ++ ++ if (connection_node == NULL) { ++ g_debug ("GdmSessionDirect: Ignoring connection that we aren't tracking"); ++ return FALSE; ++ } ++ ++ session->priv->pending_connections = ++ g_list_delete_link (session->priv->pending_connections, ++ connection_node); ++ ++ if (!dbus_connection_get_unix_process_id (connection, &pid)) { ++ g_warning ("GdmSessionDirect: Unable to read pid on new worker connection"); ++ dbus_connection_unref (connection); ++ return FALSE; ++ } ++ ++ conversation = find_conversation_by_pid (session, (GPid) pid); + + if (conversation == NULL) { +- g_warning ("Tried to look up non-existant conversation"); ++ 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); ++ ++ dbus_connection_register_object_path (connection, ++ GDM_SESSION_DBUS_PATH, ++ &vtable, ++ conversation); ++ ++ g_debug ("GdmSessionDirect: Emitting conversation-started signal"); ++ _gdm_session_conversation_started (GDM_SESSION (session), ++ conversation->service_name); ++ ++ 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 +@@ -1497,50 +1573,23 @@ handle_connection (DBusServer *server, + 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) { +- DBusObjectPathVTable vtable = { &session_unregister_handler, +- &session_message_handler, +- NULL, NULL, NULL, NULL +- }; +- +- conversation->worker_connection = new_connection; +- dbus_connection_ref (new_connection); +- dbus_connection_setup_with_g_main (new_connection, NULL); +- +- g_debug ("GdmSessionDirect: worker connection is %p", new_connection); +- dbus_connection_set_exit_on_disconnect (new_connection, FALSE); +- +- dbus_connection_set_unix_user_function (new_connection, +- allow_user_function, +- session, +- NULL); +- +- dbus_connection_register_object_path (new_connection, +- GDM_SESSION_DBUS_PATH, +- &vtable, +- 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). ++ */ ++ session->priv->pending_connections = ++ g_list_prepend (session->priv->pending_connections, ++ dbus_connection_ref (new_connection)); ++ dbus_connection_setup_with_g_main (new_connection, NULL); ++ dbus_connection_set_exit_on_disconnect (new_connection, FALSE); + +- 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, ++ NULL); ++ dbus_connection_add_filter (new_connection, on_message, session, NULL); + } + + static gboolean +@@ -1725,6 +1774,8 @@ stop_conversation (GdmSessionConversation *conversation) + 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; + } +@@ -1750,10 +1801,6 @@ gdm_session_direct_start_conversation (GdmSession *session, + + g_hash_table_insert (impl->priv->conversations, + g_strdup (service_name), conversation); +- +- if (impl->priv->conversation != NULL) { +- impl->priv->conversation = conversation; +- } + } + + static void +@@ -1904,45 +1951,50 @@ gdm_session_direct_setup_for_user (GdmSession *session, + } + + 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 (impl->priv->conversation != NULL); +- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); + +- 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"); ++ } + } + + 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 (impl->priv->conversation != NULL); +- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); + +- 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"); ++ } + } + + 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 (impl->priv->conversation != NULL); +- g_return_if_fail (dbus_connection_get_is_connected (impl->priv->conversation->worker_connection)); + +- conversation = impl->priv->conversation; ++ conversation = find_conversation_by_name (impl, service_name); ++ if (conversation == NULL) { ++ return; ++ } ++ + switch (cred_flag) { + case GDM_SESSION_CRED_ESTABLISH: + send_dbus_void_signal (conversation, "EstablishCredentials"); +@@ -1956,13 +2008,12 @@ gdm_session_direct_accredit (GdmSession *session, + } + + 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; +- GdmSessionConversation *conversation; + + message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH, + GDM_SESSION_DBUS_INTERFACE, +@@ -1972,7 +2023,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); + +- conversation = session->priv->conversation; + if (! send_dbus_message (conversation, message)) { + g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable"); + } +@@ -1981,12 +2031,13 @@ send_environment_variable (const char *key, + } + + 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 * +@@ -2103,7 +2154,8 @@ setup_session_environment (GdmSessionDirect *session) + } + + 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; +@@ -2117,10 +2169,11 @@ gdm_session_direct_start_session (GdmSession *session) + 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); + +- conversation = impl->priv->conversation; + send_dbus_string_signal (conversation, "StartProgram", program); + g_free (program); + } +@@ -2166,6 +2219,11 @@ gdm_session_direct_close (GdmSession *session) + + 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; + +@@ -2198,6 +2256,7 @@ gdm_session_direct_close (GdmSession *session) + + static void + gdm_session_direct_answer_query (GdmSession *session, ++ const char *service_name, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +@@ -2205,7 +2264,7 @@ gdm_session_direct_answer_query (GdmSession *session, + + g_return_if_fail (session != NULL); + +- conversation = impl->priv->conversation; ++ conversation = find_conversation_by_name (impl, service_name); + + answer_pending_query (conversation, text); + } +@@ -2231,7 +2290,8 @@ gdm_session_direct_select_session (GdmSession *session, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +- GdmSessionConversation *conversation; ++ GHashTableIter iter; ++ gpointer key, value; + + g_free (impl->priv->selected_session); + +@@ -2241,9 +2301,15 @@ gdm_session_direct_select_session (GdmSession *session, + impl->priv->selected_session = g_strdup (text); + } + +- conversation = impl->priv->conversation; +- send_dbus_string_signal (conversation, "SetSessionName", +- get_session_name (impl)); ++ g_hash_table_iter_init (&iter, impl->priv->conversations); ++ while (g_hash_table_iter_next (&iter, &key, &value)) { ++ GdmSessionConversation *conversation; ++ ++ conversation = (GdmSessionConversation *) value; ++ ++ send_dbus_string_signal (conversation, "SetSessionName", ++ get_session_name (impl)); ++ } + } + + static void +@@ -2251,7 +2317,8 @@ gdm_session_direct_select_language (GdmSession *session, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +- GdmSessionConversation *conversation; ++ GHashTableIter iter; ++ gpointer key, value; + + g_free (impl->priv->selected_language); + +@@ -2261,9 +2328,15 @@ gdm_session_direct_select_language (GdmSession *session, + impl->priv->selected_language = g_strdup (text); + } + +- conversation = impl->priv->conversation; +- send_dbus_string_signal (conversation, "SetLanguageName", +- get_language_name (impl)); ++ g_hash_table_iter_init (&iter, impl->priv->conversations); ++ while (g_hash_table_iter_next (&iter, &key, &value)) { ++ GdmSessionConversation *conversation; ++ ++ conversation = (GdmSessionConversation *) value; ++ ++ send_dbus_string_signal (conversation, "SetLanguageName", ++ get_language_name (impl)); ++ } + } + + static void +@@ -2271,7 +2344,8 @@ gdm_session_direct_select_layout (GdmSession *session, + const char *text) + { + GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); +- GdmSessionConversation *conversation; ++ GHashTableIter iter; ++ gpointer key, value; + + g_free (impl->priv->selected_layout); + +@@ -2281,9 +2355,15 @@ gdm_session_direct_select_layout (GdmSession *session, + impl->priv->selected_layout = g_strdup (text); + } + +- conversation = impl->priv->conversation; +- send_dbus_string_signal (conversation, "SetLayoutName", +- get_layout_name (impl)); ++ g_hash_table_iter_init (&iter, impl->priv->conversations); ++ while (g_hash_table_iter_next (&iter, &key, &value)) { ++ GdmSessionConversation *conversation; ++ ++ conversation = (GdmSessionConversation *) value; ++ ++ send_dbus_string_signal (conversation, "SetLayoutName", ++ get_layout_name (impl)); ++ } + } + + 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); + 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 + + /* call and response stuff */ + void _gdm_session_info_query (GdmSession *session, ++ const char *service_name, + const char *text); + void _gdm_session_secret_info_query (GdmSession *session, ++ const char *service_name, + const char *text); + void _gdm_session_info (GdmSession *session, ++ const char *service_name, + const char *text); + void _gdm_session_problem (GdmSession *session, ++ const char *service_name, + const char *text); + + G_END_DECLS +diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c +index 35b4738..6e15f75 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, + } + + static void +-gdm_session_relay_authenticate (GdmSession *session) ++gdm_session_relay_authenticate (GdmSession *session, ++ const char *service_name) + { + GdmSessionRelay *impl = GDM_SESSION_RELAY (session); +- send_dbus_void_signal (impl, "Authenticate"); ++ send_dbus_string_signal (impl, "Authenticate", service_name); + } + + static void +-gdm_session_relay_authorize (GdmSession *session) ++gdm_session_relay_authorize (GdmSession *session, ++ const char *service_name) + { + GdmSessionRelay *impl = GDM_SESSION_RELAY (session); +- send_dbus_void_signal (impl, "Authorize"); ++ send_dbus_string_signal (impl, "Authorize", service_name); + } + + static void + gdm_session_relay_accredit (GdmSession *session, ++ const char *service_name, + int cred_flag) + { + GdmSessionRelay *impl = GDM_SESSION_RELAY (session); + + switch (cred_flag) { + case GDM_SESSION_CRED_ESTABLISH: +- send_dbus_void_signal (impl, "EstablishCredentials"); ++ send_dbus_string_signal (impl, "EstablishCredentials", service_name); + break; + case GDM_SESSION_CRED_REFRESH: +- send_dbus_void_signal (impl, "RefreshCredentials"); ++ send_dbus_string_signal (impl, "RefreshCredentials", service_name); + break; + default: + g_assert_not_reached (); +@@ -245,10 +248,11 @@ gdm_session_relay_accredit (GdmSession *session, + + static void + gdm_session_relay_answer_query (GdmSession *session, ++ const char *service_name, + const char *text) + { + GdmSessionRelay *impl = GDM_SESSION_RELAY (session); +- send_dbus_string_signal (impl, "AnswerQuery", text); ++ send_dbus_string_string_signal (impl, "AnswerQuery", service_name, text); + } + + static void +@@ -292,11 +296,12 @@ gdm_session_relay_cancel (GdmSession *session) + } + + 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 +@@ -334,10 +339,12 @@ handle_info_query (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; +- const char *text; ++ char *service_name; ++ char *text; + + 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); +@@ -349,7 +356,7 @@ handle_info_query (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_info_query (GDM_SESSION (session_relay), text); ++ _gdm_session_info_query (GDM_SESSION (session_relay), service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -361,12 +368,14 @@ handle_secret_info_query (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; +- const char *text; ++ char *service_name; ++ char *text; + + text = 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); +@@ -378,7 +387,7 @@ handle_secret_info_query (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_secret_info_query (GDM_SESSION (session_relay), text); ++ _gdm_session_secret_info_query (GDM_SESSION (session_relay), service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -390,12 +399,14 @@ handle_info (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; +- const char *text; ++ char *service_name; ++ char *text; + + text = 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); +@@ -407,7 +418,7 @@ handle_info (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_info (GDM_SESSION (session_relay), text); ++ _gdm_session_info (GDM_SESSION (session_relay), service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -419,12 +430,14 @@ handle_problem (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; +- const char *text; ++ char *service_name; ++ char *text; + + text = 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); +@@ -436,7 +449,7 @@ handle_problem (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_problem (GDM_SESSION (session_relay), text); ++ _gdm_session_problem (GDM_SESSION (session_relay), service_name, text); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -448,8 +461,15 @@ handle_setup_complete (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + + dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); + + g_debug ("GdmSessionRelay: SetupComplete"); + +@@ -457,7 +477,7 @@ handle_setup_complete (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_setup_complete (GDM_SESSION (session_relay)); ++ _gdm_session_setup_complete (GDM_SESSION (session_relay), service_name); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -469,8 +489,15 @@ handle_setup_failed (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + + dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); + + g_debug ("GdmSessionRelay: SetupFailed"); + +@@ -478,7 +505,7 @@ handle_setup_failed (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_setup_failed (GDM_SESSION (session_relay), NULL); ++ _gdm_session_setup_failed (GDM_SESSION (session_relay), service_name, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -491,8 +518,15 @@ handle_authenticated (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + + dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); + + g_debug ("GdmSessionRelay: Authenticated"); + +@@ -500,7 +534,7 @@ handle_authenticated (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_authenticated (GDM_SESSION (session_relay)); ++ _gdm_session_authenticated (GDM_SESSION (session_relay), service_name); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -512,8 +546,15 @@ handle_authentication_failed (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + + dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); + + g_debug ("GdmSessionRelay: AuthenticationFailed"); + +@@ -521,7 +562,7 @@ handle_authentication_failed (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_authentication_failed (GDM_SESSION (session_relay), NULL); ++ _gdm_session_authentication_failed (GDM_SESSION (session_relay), service_name, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -533,8 +574,15 @@ handle_authorized (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + + dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); + + g_debug ("GdmSessionRelay: Authorized"); + +@@ -542,7 +590,7 @@ handle_authorized (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_authorized (GDM_SESSION (session_relay)); ++ _gdm_session_authorized (GDM_SESSION (session_relay), service_name); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -554,8 +602,15 @@ handle_authorization_failed (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + + dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); + + g_debug ("GdmSessionRelay: AuthorizationFailed"); + +@@ -563,7 +618,7 @@ handle_authorization_failed (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_authorization_failed (GDM_SESSION (session_relay), NULL); ++ _gdm_session_authorization_failed (GDM_SESSION (session_relay), service_name, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -575,8 +630,15 @@ handle_accredited (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + + dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); + + g_debug ("GdmSessionRelay: Accredited"); + +@@ -584,7 +646,7 @@ handle_accredited (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_accredited (GDM_SESSION (session_relay)); ++ _gdm_session_accredited (GDM_SESSION (session_relay), service_name); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -596,8 +658,15 @@ handle_accreditation_failed (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + + dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); + + g_debug ("GdmSessionRelay: AccreditationFailed"); + +@@ -605,7 +674,7 @@ handle_accreditation_failed (GdmSessionRelay *session_relay, + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + +- _gdm_session_accreditation_failed (GDM_SESSION (session_relay), NULL); ++ _gdm_session_accreditation_failed (GDM_SESSION (session_relay), service_name, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; + } +@@ -617,6 +686,7 @@ handle_session_started (GdmSessionRelay *session_relay, + { + DBusMessage *reply; + DBusError error; ++ char *service_name; + int pid; + + dbus_error_init (&error); +@@ -624,6 +694,7 @@ handle_session_started (GdmSessionRelay *session_relay, + pid = 0; + if (! dbus_message_get_args (message, + &error, ++ DBUS_TYPE_STRING, &service_name, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID)) { + g_warning ("ERROR: %s", error.message); +@@ -636,6 +707,7 @@ handle_session_started (GdmSessionRelay *session_relay, + dbus_message_unref (reply); + + _gdm_session_session_started (GDM_SESSION (session_relay), ++ service_name, + pid); + + return DBUS_HANDLER_RESULT_HANDLED; +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index 47a5c08..bcd4f93 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -2851,6 +2851,28 @@ worker_dbus_filter_function (DBusConnection *connection, + return DBUS_HANDLER_RESULT_HANDLED; + } + ++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, +@@ -2877,6 +2899,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); + +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 @@ -1412,47 +4993,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio #include "gdm-session.h" #include "gdm-session-private.h" - enum { -- OPENED = 0, -+ CONVERSATION_STARTED = 0, -+ CONVERSATION_STOPPED, - SETUP_COMPLETE, - SETUP_FAILED, - RESET_COMPLETE, -@@ -44,6 +46,8 @@ enum { - PROBLEM, - INFO_QUERY, - SECRET_INFO_QUERY, -+ SESSION_OPENED, -+ SESSION_OPEN_FAILED, - SESSION_STARTED, - SESSION_START_FAILED, - SESSION_EXITED, -@@ -78,11 +82,21 @@ 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 -+gdm_session_stop_conversation (GdmSession *session, -+ const char *service_name) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ -+ GDM_SESSION_GET_IFACE (session)->stop_conversation (session, service_name); - } - - void -@@ -113,37 +127,41 @@ gdm_session_setup_for_user (GdmSession * +@@ -114,37 +115,41 @@ gdm_session_setup_for_user (GdmSession *session, } void @@ -1500,20 +5041,11 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio } void -@@ -191,11 +209,21 @@ gdm_session_cancel (GdmSession *session) +@@ -192,11 +197,12 @@ gdm_session_cancel (GdmSession *session) } void -gdm_session_start_session (GdmSession *session) -+gdm_session_open_session (GdmSession *session, -+ const char *service_name) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ -+ GDM_SESSION_GET_IFACE (session)->open_session (session, service_name); -+} -+ -+void +gdm_session_start_session (GdmSession *session, + const char *service_name) { @@ -1524,39 +5056,16 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio } static void -@@ -203,16 +231,26 @@ 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), +@@ -213,7 +219,7 @@ gdm_session_class_init (gpointer g_iface) NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, + 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 +258,10 @@ gdm_session_class_init (gpointer g_iface +@@ -221,9 +227,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, setup_complete), NULL, NULL, @@ -1569,7 +5078,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [SETUP_FAILED] = g_signal_new ("setup-failed", iface_type, -@@ -230,10 +269,10 @@ gdm_session_class_init (gpointer g_iface +@@ -231,10 +238,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, setup_failed), NULL, NULL, @@ -1583,7 +5092,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [RESET_COMPLETE] = g_signal_new ("reset-complete", iface_type, -@@ -262,9 +301,9 @@ gdm_session_class_init (gpointer g_iface +@@ -263,9 +270,9 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, authenticated), NULL, NULL, @@ -1595,7 +5104,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [AUTHENTICATION_FAILED] = g_signal_new ("authentication-failed", iface_type, -@@ -272,10 +311,10 @@ gdm_session_class_init (gpointer g_iface +@@ -273,10 +280,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, authentication_failed), NULL, NULL, @@ -1609,7 +5118,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [AUTHORIZED] = g_signal_new ("authorized", iface_type, -@@ -283,9 +322,9 @@ gdm_session_class_init (gpointer g_iface +@@ -284,9 +291,9 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, authorized), NULL, NULL, @@ -1621,7 +5130,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [AUTHORIZATION_FAILED] = g_signal_new ("authorization-failed", iface_type, -@@ -293,10 +332,10 @@ gdm_session_class_init (gpointer g_iface +@@ -294,10 +301,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, authorization_failed), NULL, NULL, @@ -1635,7 +5144,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [ACCREDITED] = g_signal_new ("accredited", iface_type, -@@ -304,9 +343,9 @@ gdm_session_class_init (gpointer g_iface +@@ -305,9 +312,9 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, accredited), NULL, NULL, @@ -1647,7 +5156,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [ACCREDITATION_FAILED] = g_signal_new ("accreditation-failed", iface_type, -@@ -314,10 +353,10 @@ gdm_session_class_init (gpointer g_iface +@@ -315,10 +322,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, accreditation_failed), NULL, NULL, @@ -1661,7 +5170,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [INFO_QUERY] = g_signal_new ("info-query", -@@ -326,10 +365,10 @@ gdm_session_class_init (gpointer g_iface +@@ -327,10 +334,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, info_query), NULL, NULL, @@ -1675,7 +5184,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [SECRET_INFO_QUERY] = g_signal_new ("secret-info-query", iface_type, -@@ -337,10 +376,10 @@ gdm_session_class_init (gpointer g_iface +@@ -338,10 +345,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, secret_info_query), NULL, NULL, @@ -1689,7 +5198,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [INFO] = g_signal_new ("info", iface_type, -@@ -348,10 +387,10 @@ gdm_session_class_init (gpointer g_iface +@@ -349,10 +356,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, info), NULL, NULL, @@ -1703,40 +5212,21 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [PROBLEM] = g_signal_new ("problem", iface_type, -@@ -359,10 +398,32 @@ gdm_session_class_init (gpointer g_iface +@@ -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, -+ 2, -+ G_TYPE_STRING, G_TYPE_STRING); -+ signals [SESSION_OPENED] = -+ g_signal_new ("session-opened", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmSessionIface, session_opened), -+ NULL, -+ NULL, - g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, - 1, - G_TYPE_STRING); -+ signals [SESSION_OPEN_FAILED] = -+ g_signal_new ("session-open-failed", -+ iface_type, -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmSessionIface, session_open_failed), -+ NULL, -+ NULL, -+ gdm_marshal_VOID__STRING_STRING, -+ G_TYPE_NONE, +- 1, +- G_TYPE_STRING); + 2, + G_TYPE_STRING, G_TYPE_STRING); signals [SESSION_STARTED] = g_signal_new ("session-started", iface_type, -@@ -370,10 +431,10 @@ gdm_session_class_init (gpointer g_iface +@@ -371,10 +378,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, session_started), NULL, NULL, @@ -1750,7 +5240,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [SESSION_START_FAILED] = g_signal_new ("session-start-failed", iface_type, -@@ -381,10 +442,10 @@ gdm_session_class_init (gpointer g_iface +@@ -382,10 +389,10 @@ gdm_session_class_init (gpointer g_iface) G_STRUCT_OFFSET (GdmSessionIface, session_start_failed), NULL, NULL, @@ -1764,7 +5254,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio signals [SESSION_EXITED] = g_signal_new ("session-exited", iface_type, -@@ -464,19 +525,21 @@ gdm_session_class_init (gpointer g_iface +@@ -465,19 +472,21 @@ gdm_session_class_init (gpointer g_iface) } void @@ -1789,7 +5279,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio } void -@@ -496,99 +559,128 @@ _gdm_session_reset_failed (GdmSession +@@ -497,99 +506,111 @@ _gdm_session_reset_failed (GdmSession *session, } void @@ -1893,23 +5383,6 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio 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_opened (GdmSession *session, -+ const char *service_name) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ g_signal_emit (session, signals [SESSION_OPENED], 0, service_name); -+} -+ -+void -+_gdm_session_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *text) -+{ -+ g_return_if_fail (GDM_IS_SESSION (session)); -+ g_signal_emit (session, signals [SESSION_OPEN_FAILED], 0, service_name, text); } void @@ -1933,1781 +5406,11 @@ diff -up gdm-2.28.0/daemon/gdm-session.c.multistack gdm-2.28.0/daemon/gdm-sessio } void -@@ -608,10 +700,19 @@ _gdm_session_session_died (GdmSession - } - - 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 [CONVERSATION_STARTED], 0, service_name); -+} -+ -+void -+_gdm_session_conversation_stopped (GdmSession *session, -+ const char *service_name) - { - g_return_if_fail (GDM_IS_SESSION (session)); -- g_signal_emit (session, signals [OPENED], 0); -+ g_signal_emit (session, signals [CONVERSATION_STOPPED], 0, service_name); - } - - void -diff -up gdm-2.28.0/daemon/gdm-session-direct.c.multistack gdm-2.28.0/daemon/gdm-session-direct.c ---- gdm-2.28.0/daemon/gdm-session-direct.c.multistack 2009-09-23 18:46:06.502641319 -0400 -+++ gdm-2.28.0/daemon/gdm-session-direct.c 2009-09-23 19:35:10.029394668 -0400 -@@ -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; -+ - struct _GdmSessionDirectPrivate - { - /* per open scope */ -@@ -75,13 +85,12 @@ struct _GdmSessionDirectPrivate - char *selected_user; - char *user_x11_authority_file; - -- DBusMessage *message_pending_reply; -- DBusConnection *worker_connection; -+ GHashTable *conversations; -+ -+ GList *pending_connections; - -- GdmSessionWorkerJob *job; -- GPid session_pid; -- guint32 is_authenticated : 1; - guint32 is_running : 1; -+ GPid session_pid; - - /* object lifetime scope */ - char *id; -@@ -118,39 +127,39 @@ G_DEFINE_TYPE_WITH_CODE (GdmSessionDirec - gdm_session_iface_init)) - - static gboolean --send_dbus_message (DBusConnection *connection, -- DBusMessage *message) -+send_dbus_message (GdmSessionConversation *conversation, -+ DBusMessage *message) - { - 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; - } - - static void --send_dbus_string_signal (GdmSessionDirect *session, -- const char *name, -+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 +168,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 ? name : "(null)"); - } -@@ -168,57 +177,90 @@ send_dbus_string_signal (GdmSessionDirec - } - - 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_message_unref (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); -- 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); -+ } - } - - 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); -+ } - } - - 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); -+ } - } - - static void -@@ -226,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, -@@ -235,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; -@@ -243,17 +286,17 @@ gdm_session_direct_handle_setup_complete - 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; -@@ -268,12 +311,12 @@ gdm_session_direct_handle_setup_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); - - g_debug ("GdmSessionDirect: Emitting 'setup-failed' signal"); - -- _gdm_session_setup_failed (GDM_SESSION (session), text); -+ _gdm_session_setup_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -281,7 +324,7 @@ gdm_session_direct_handle_setup_failed ( - - static DBusHandlerResult - gdm_session_direct_handle_reset_complete (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -289,7 +332,7 @@ gdm_session_direct_handle_reset_complete - 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)); -@@ -299,7 +342,7 @@ gdm_session_direct_handle_reset_complete - - static DBusHandlerResult - gdm_session_direct_handle_reset_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -314,7 +357,7 @@ gdm_session_direct_handle_reset_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); - - g_debug ("GdmSessionDirect: Emitting 'reset-failed' signal"); -@@ -326,7 +369,7 @@ gdm_session_direct_handle_reset_failed ( - - static DBusHandlerResult - gdm_session_direct_handle_authenticated (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -334,18 +377,17 @@ gdm_session_direct_handle_authenticated - g_debug ("GdmSessionDirect: Emitting 'authenticated' 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); - -- session->priv->is_authenticated = TRUE; -- _gdm_session_authenticated (GDM_SESSION (session)); -+ _gdm_session_authenticated (GDM_SESSION (session), conversation->service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -360,20 +402,19 @@ gdm_session_direct_handle_authentication - } - - 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 'authentication-failed' signal"); - -- session->priv->is_authenticated = FALSE; -- _gdm_session_authentication_failed (GDM_SESSION (session), text); -+ _gdm_session_authentication_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_authorized (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -381,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 DBusHandlerResult - gdm_session_direct_handle_authorization_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -406,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), text); -+ _gdm_session_authorization_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_accredited (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -426,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 DBusHandlerResult - gdm_session_direct_handle_accreditation_failed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -451,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), text); -+ _gdm_session_accreditation_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -756,7 +797,7 @@ gdm_session_direct_select_user (GdmSessi - - static DBusHandlerResult - gdm_session_direct_handle_username_changed (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -771,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'", -@@ -788,59 +829,62 @@ gdm_session_direct_handle_username_chang - } - - static void --cancel_pending_query (GdmSessionDirect *session) -+cancel_pending_query (GdmSessionConversation *conversation) - { - DBusMessage *reply; - -- 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"); -- 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); - - 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 - answer_pending_query (GdmSessionDirect *session, -+ const char *service_name, - const char *answer) - { - DBusMessage *reply; - 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); - -- dbus_connection_send (session->priv->worker_connection, reply, NULL); -+ conversation = find_conversation_by_name (session, service_name); -+ 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 --set_pending_query (GdmSessionDirect *session, -- DBusMessage *message) -+set_pending_query (GdmSessionConversation *conversation, -+ DBusMessage *message) - { -- g_assert (session->priv->message_pending_reply == NULL); -+ g_assert (conversation->message_pending_reply == NULL); - -- session->priv->message_pending_reply = dbus_message_ref (message); -+ conversation->message_pending_reply = dbus_message_ref (message); - } - - static DBusHandlerResult - gdm_session_direct_handle_info_query (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusError error; -@@ -853,17 +897,17 @@ gdm_session_direct_handle_info_query (Gd - 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), 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; -@@ -876,17 +920,17 @@ gdm_session_direct_handle_secret_info_qu - 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), text); -+ _gdm_session_secret_info_query (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_info (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -901,27 +945,27 @@ gdm_session_direct_handle_info (GdmSessi - } - - 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 'info' signal"); -- _gdm_session_info (GDM_SESSION (session), text); -+ _gdm_session_info (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - 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 (connection, reply, NULL); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); - dbus_message_unref (reply); - - return DBUS_HANDLER_RESULT_HANDLED; -@@ -929,7 +973,7 @@ gdm_session_direct_handle_cancel_pending - - static DBusHandlerResult - gdm_session_direct_handle_problem (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -944,18 +988,70 @@ gdm_session_direct_handle_problem (GdmSe - } - - 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_opened (GdmSessionDirect *session, -+ GdmSessionConversation *conversation, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ -+ g_debug ("GdmSessionDirect: Handling SessionOpened"); -+ -+ dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ -+ g_debug ("GdmSessionDirect: Emitting 'session-opened' signal"); -+ -+ _gdm_session_session_opened (GDM_SESSION (session), conversation->service_name); -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+static DBusHandlerResult -+gdm_session_direct_handle_open_failed (GdmSessionDirect *session, -+ GdmSessionConversation *conversation, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ const char *text; -+ -+ dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &text, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (conversation->worker_connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ g_debug ("GdmSessionDirect: Emitting 'session-open-failed' signal"); -+ _gdm_session_session_open_failed (GDM_SESSION (session), conversation->service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - static DBusHandlerResult - gdm_session_direct_handle_session_started (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -974,7 +1070,7 @@ gdm_session_direct_handle_session_starte - } - - 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'", -@@ -983,14 +1079,14 @@ gdm_session_direct_handle_session_starte - 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; -@@ -1005,18 +1101,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); - - 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; -@@ -1031,7 +1127,7 @@ gdm_session_direct_handle_session_exited - } - - 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'", -@@ -1045,7 +1141,7 @@ gdm_session_direct_handle_session_exited - - static DBusHandlerResult - gdm_session_direct_handle_session_died (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1060,7 +1156,7 @@ gdm_session_direct_handle_session_died ( - } - - 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'", -@@ -1074,7 +1170,7 @@ gdm_session_direct_handle_session_died ( - - static DBusHandlerResult - gdm_session_direct_handle_saved_language_name_read (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1089,7 +1185,7 @@ gdm_session_direct_handle_saved_language - } - - 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, -@@ -1107,7 +1203,7 @@ gdm_session_direct_handle_saved_language - - static DBusHandlerResult - gdm_session_direct_handle_saved_layout_name_read (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1122,7 +1218,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); - - if (strcmp (layout_name, -@@ -1140,7 +1236,7 @@ gdm_session_direct_handle_saved_layout_n - - static DBusHandlerResult - gdm_session_direct_handle_saved_session_name_read (GdmSessionDirect *session, -- DBusConnection *connection, -+ GdmSessionConversation *conversation, - DBusMessage *message) - { - DBusMessage *reply; -@@ -1155,7 +1251,7 @@ gdm_session_direct_handle_saved_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 (! get_session_command_for_name (session_name, NULL)) { -@@ -1183,54 +1279,61 @@ session_worker_message (DBusConnection * - DBusMessage *message, - void *user_data) - { -- GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); -+ GdmSessionConversation *conversation = user_data; -+ GdmSessionDirect *session; -+ -+ session = conversation->session; - - if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "InfoQuery")) { -- return gdm_session_direct_handle_info_query (session, connection, message); -+ return gdm_session_direct_handle_info_query (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SecretInfoQuery")) { -- return gdm_session_direct_handle_secret_info_query (session, connection, message); -+ return gdm_session_direct_handle_secret_info_query (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Info")) { -- return gdm_session_direct_handle_info (session, connection, message); -+ return gdm_session_direct_handle_info (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Problem")) { -- return gdm_session_direct_handle_problem (session, connection, message); -+ return gdm_session_direct_handle_problem (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "CancelPendingQuery")) { -- return gdm_session_direct_handle_cancel_pending_query (session, connection, message); -+ return gdm_session_direct_handle_cancel_pending_query (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupComplete")) { -- return gdm_session_direct_handle_setup_complete (session, connection, message); -+ return gdm_session_direct_handle_setup_complete (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupFailed")) { -- return gdm_session_direct_handle_setup_failed (session, connection, message); -+ return gdm_session_direct_handle_setup_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetComplete")) { -- return gdm_session_direct_handle_reset_complete (session, connection, message); -+ return gdm_session_direct_handle_reset_complete (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetFailed")) { -- return gdm_session_direct_handle_reset_failed (session, connection, message); -+ return gdm_session_direct_handle_reset_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authenticated")) { -- return gdm_session_direct_handle_authenticated (session, connection, message); -+ return gdm_session_direct_handle_authenticated (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthenticationFailed")) { -- return gdm_session_direct_handle_authentication_failed (session, connection, message); -+ return gdm_session_direct_handle_authentication_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authorized")) { -- return gdm_session_direct_handle_authorized (session, connection, message); -+ return gdm_session_direct_handle_authorized (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthorizationFailed")) { -- return gdm_session_direct_handle_authorization_failed (session, connection, message); -+ return gdm_session_direct_handle_authorization_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Accredited")) { -- return gdm_session_direct_handle_accredited (session, connection, message); -+ return gdm_session_direct_handle_accredited (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AccreditationFailed")) { -- return gdm_session_direct_handle_accreditation_failed (session, connection, message); -+ return gdm_session_direct_handle_accreditation_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) { -- return gdm_session_direct_handle_username_changed (session, connection, message); -+ return gdm_session_direct_handle_username_changed (session, conversation, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionOpened")) { -+ return gdm_session_direct_handle_session_opened (session, conversation, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "OpenFailed")) { -+ return gdm_session_direct_handle_open_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) { -- return gdm_session_direct_handle_session_started (session, connection, message); -+ return gdm_session_direct_handle_session_started (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartFailed")) { -- return gdm_session_direct_handle_start_failed (session, connection, message); -+ return gdm_session_direct_handle_start_failed (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionExited")) { -- return gdm_session_direct_handle_session_exited (session, connection, message); -+ return gdm_session_direct_handle_session_exited (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionDied")) { -- return gdm_session_direct_handle_session_died (session, connection, message); -+ return gdm_session_direct_handle_session_died (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLanguageNameRead")) { -- return gdm_session_direct_handle_saved_language_name_read (session, connection, message); -+ return gdm_session_direct_handle_saved_language_name_read (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLayoutNameRead")) { -- return gdm_session_direct_handle_saved_layout_name_read (session, connection, message); -+ return gdm_session_direct_handle_saved_layout_name_read (session, conversation, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedSessionNameRead")) { -- return gdm_session_direct_handle_saved_session_name_read (session, connection, message); -+ return gdm_session_direct_handle_saved_session_name_read (session, conversation, message); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -@@ -1464,6 +1567,27 @@ session_unregister_handler (DBusConnecti - g_debug ("session_unregister_handler"); - } - -+static GdmSessionConversation * -+find_conversation_by_pid (GdmSessionDirect *session, -+ GPid pid) -+{ -+ 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 dbus_bool_t - allow_user_function (DBusConnection *connection, - unsigned long uid, -@@ -1478,41 +1602,108 @@ allow_user_function (DBusConnection *con - return FALSE; - } - -+static gboolean -+register_worker (GdmSessionDirect *session, -+ DBusConnection *connection) -+{ -+ GdmSessionConversation *conversation; -+ DBusObjectPathVTable vtable = { &session_unregister_handler, -+ &session_message_handler, -+ NULL, NULL, NULL, NULL }; -+ GList *connection_node; -+ gulong pid; -+ -+ g_debug ("GdmSessionDirect: Authenticating new connection"); -+ -+ connection_node = g_list_find (session->priv->pending_connections, connection); -+ -+ if (connection_node == NULL) { -+ g_debug ("GdmSessionDirect: Ignoring connection that we aren't tracking"); -+ return FALSE; -+ } -+ -+ session->priv->pending_connections = -+ g_list_delete_link (session->priv->pending_connections, -+ connection_node); -+ -+ if (!dbus_connection_get_unix_process_id (connection, &pid)) { -+ g_warning ("GdmSessionDirect: Unable to read pid on new worker connection"); -+ dbus_connection_unref (connection); -+ return FALSE; -+ } -+ -+ conversation = find_conversation_by_pid (session, (GPid) pid); -+ -+ if (conversation == NULL) { -+ g_warning ("GdmSessionDirect: New worker connection is from unknown source"); -+ dbus_connection_unref (connection); -+ return FALSE; -+ } -+ -+ conversation->worker_connection = connection; -+ -+ g_debug ("GdmSessionDirect: worker connection is %p", connection); -+ -+ dbus_connection_register_object_path (connection, -+ GDM_SESSION_DBUS_PATH, -+ &vtable, -+ conversation); -+ -+ g_debug ("GdmSessionDirect: Emitting conversation-started signal"); -+ _gdm_session_conversation_started (GDM_SESSION (session), -+ conversation->service_name); -+ -+ g_debug ("GdmSessionDirect: Conversation started"); -+ -+ return TRUE; -+} -+ -+static DBusHandlerResult -+on_message (DBusConnection *connection, DBusMessage *message, void *user_data) -+{ -+ GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); -+ -+ g_debug ("GdmSessionDirect: got message"); -+ -+ if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Hello")) { -+ DBusMessage *reply; -+ -+ 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 DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -+} -+ - static void - handle_connection (DBusServer *server, - DBusConnection *new_connection, - void *user_data) - { - GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data); -- - g_debug ("GdmSessionDirect: Handing new connection"); - -- if (session->priv->worker_connection == NULL) { -- DBusObjectPathVTable vtable = { &session_unregister_handler, -- &session_message_handler, -- NULL, NULL, NULL, NULL -- }; -- -- session->priv->worker_connection = new_connection; -- dbus_connection_ref (new_connection); -- dbus_connection_setup_with_g_main (new_connection, NULL); -- -- g_debug ("GdmSessionDirect: worker connection is %p", new_connection); -- dbus_connection_set_exit_on_disconnect (new_connection, FALSE); -- -- dbus_connection_set_unix_user_function (new_connection, -- allow_user_function, -- session, -- NULL); -- -- dbus_connection_register_object_path (new_connection, -- 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). -+ */ -+ session->priv->pending_connections = -+ g_list_prepend (session->priv->pending_connections, -+ dbus_connection_ref (new_connection)); -+ dbus_connection_setup_with_g_main (new_connection, NULL); -+ dbus_connection_set_exit_on_disconnect (new_connection, FALSE); -+ -+ dbus_connection_set_unix_user_function (new_connection, -+ allow_user_function, -+ session, -+ NULL); -+ dbus_connection_add_filter (new_connection, on_message, session, NULL); - } - - static gboolean -@@ -1558,6 +1749,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, -@@ -1581,8 +1783,11 @@ gdm_session_direct_init (GdmSessionDirec - G_CALLBACK (on_session_exited), - NULL); - -- session->priv->session_pid = -1; -- -+ 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, -@@ -1593,15 +1798,8 @@ gdm_session_direct_init (GdmSessionDirec - } - - static void --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"); - } -@@ -1609,98 +1807,149 @@ worker_started (GdmSessionWorkerJob *job - static void - worker_exited (GdmSessionWorkerJob *job, - int code, -- GdmSessionDirect *session) -+ GdmSessionConversation *conversation) - { - g_debug ("GdmSessionDirect: Worker job exited: %d", code); - -- if (!session->priv->is_authenticated) { -- _gdm_session_authentication_failed (GDM_SESSION (session), NULL); -- } else if (session->priv->is_running) { -- _gdm_session_session_exited (GDM_SESSION (session), code); -+ g_object_ref (conversation); -+ 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 - worker_died (GdmSessionWorkerJob *job, - int signum, -- GdmSessionDirect *session) -+ GdmSessionConversation *conversation) - { - g_debug ("GdmSessionDirect: Worker job died: %d", signum); - -- if (!session->priv->is_authenticated) { -- _gdm_session_authentication_failed (GDM_SESSION (session), NULL); -- } else if (session->priv->is_running) { -- _gdm_session_session_died (GDM_SESSION (session), signum); -- } --} -- --static gboolean --start_worker (GdmSessionDirect *session) --{ -- gboolean res; -- -- 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_object_ref (conversation); -+ if (conversation->session->priv->is_running) { -+ _gdm_session_session_died (GDM_SESSION (conversation->session), signum); -+ } -+ -+ 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); -+ -+ 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); - -- res = gdm_session_worker_job_start (session->priv->job); -+ conversation->worker_pid = gdm_session_worker_job_get_pid (conversation->job); - -- return res; -+ return conversation; - } - - static void --stop_worker (GdmSessionDirect *session) -+stop_conversation (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); - -- cancel_pending_query (session); -+ if (conversation->worker_connection != NULL) { -+ dbus_connection_remove_filter (conversation->worker_connection, on_message, session); - -- 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; - } - -- 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 -+gdm_session_direct_start_conversation (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"); -+ -+ conversation = start_conversation (impl, service_name); -+ -+ g_hash_table_insert (impl->priv->conversations, -+ g_strdup (service_name), conversation); - } - - static void --gdm_session_direct_open (GdmSession *session) -+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: Opening session"); -+ g_debug ("GdmSessionDirect: stopping conversation"); -+ -+ conversation = find_conversation_by_name (impl, service_name); - -- start_worker (impl); -+ if (conversation != NULL) { -+ stop_conversation (conversation); -+ g_hash_table_remove (impl->priv->conversations, service_name); -+ } - } - - static void -@@ -1713,6 +1962,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); - -@@ -1750,7 +2000,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"); - } - -@@ -1768,6 +2019,7 @@ send_setup_for_user (GdmSessionDirect *s - const char *display_hostname; - const char *display_x11_authority_file; - const char *selected_user; -+ GdmSessionConversation *conversation; - - g_assert (service_name != NULL); - -@@ -1811,7 +2063,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); - -- 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"); - } - -@@ -1825,7 +2078,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)); - - send_setup (impl, service_name); - gdm_session_direct_defaults_changed (impl); -@@ -1839,7 +2091,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); -@@ -1849,42 +2100,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 (); -@@ -1892,9 +2157,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; -@@ -1907,7 +2172,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"); - } - -@@ -1915,12 +2180,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 * -@@ -2037,27 +2303,99 @@ setup_session_environment (GdmSessionDir - } - - static void --gdm_session_direct_start_session (GdmSession *session) -+gdm_session_direct_open_session (GdmSession *session, -+ const char *service_name) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; -+ -+ g_return_if_fail (session != NULL); -+ -+ conversation = find_conversation_by_name (impl, service_name); -+ send_dbus_void_signal (conversation, "OpenSession"); -+} -+ -+static void -+stop_all_other_conversations (GdmSessionDirect *session, -+ GdmSessionConversation *conversation_to_keep) -+{ -+ GHashTableIter iter; -+ gpointer key, value; -+ -+ if (session->priv->conversations == NULL) { -+ return; -+ } -+ -+ if (conversation_to_keep == NULL) { -+ g_debug ("GdmSessionDirect: Stopping all conversations"); -+ } else { -+ g_debug ("GdmSessionDirect: Stopping all conversations " -+ "except for %s", conversation_to_keep->service_name); -+ } -+ -+ 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 == conversation_to_keep) { -+ g_hash_table_iter_steal (&iter); -+ g_free (key); -+ } else { -+ stop_conversation (conversation); -+ } -+ } -+ -+ g_hash_table_remove_all (session->priv->conversations); -+ -+ if (conversation_to_keep != NULL) { -+ g_hash_table_insert (session->priv->conversations, -+ g_strdup (conversation_to_keep->service_name), -+ conversation_to_keep); -+ } -+} -+ -+static void -+gdm_session_direct_start_session (GdmSession *session, -+ const char *service_name) -+{ -+ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GdmSessionConversation *conversation; - char *command; - char *program; - - g_return_if_fail (session != NULL); - g_return_if_fail (impl->priv->is_running == FALSE); - -+ conversation = find_conversation_by_name (impl, service_name); -+ -+ if (conversation == NULL) { -+ g_warning ("GdmSessionDirect: Tried to start session of " -+ "nonexistent conversation %s", service_name); -+ return; -+ } -+ -+ stop_all_other_conversations (impl, conversation); -+ - command = get_session_command (impl); - program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command); - g_free (command); - - 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) -+{ -+ stop_all_other_conversations (session, NULL); -+} -+ -+static void - gdm_session_direct_close (GdmSession *session) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -@@ -2066,18 +2404,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; - -@@ -2104,30 +2445,27 @@ 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 - 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 * -@@ -2143,6 +2481,8 @@ gdm_session_direct_select_session (GdmSe - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GHashTableIter iter; -+ gpointer key, value; - - g_free (impl->priv->selected_session); - -@@ -2152,8 +2492,15 @@ gdm_session_direct_select_session (GdmSe - impl->priv->selected_session = g_strdup (text); - } - -- 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)) { -+ GdmSessionConversation *conversation; -+ -+ conversation = (GdmSessionConversation *) value; -+ -+ send_dbus_string_signal (conversation, "SetSessionName", -+ get_session_name (impl)); -+ } - } - - static void -@@ -2161,6 +2508,8 @@ gdm_session_direct_select_language (GdmS - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GHashTableIter iter; -+ gpointer key, value; - - g_free (impl->priv->selected_language); - -@@ -2170,8 +2519,15 @@ gdm_session_direct_select_language (GdmS - impl->priv->selected_language = g_strdup (text); - } - -- 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)) { -+ GdmSessionConversation *conversation; -+ -+ conversation = (GdmSessionConversation *) value; -+ -+ send_dbus_string_signal (conversation, "SetLanguageName", -+ get_language_name (impl)); -+ } - } - - static void -@@ -2179,6 +2535,8 @@ gdm_session_direct_select_layout (GdmSes - const char *text) - { - GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); -+ GHashTableIter iter; -+ gpointer key, value; - - g_free (impl->priv->selected_layout); - -@@ -2188,8 +2546,15 @@ gdm_session_direct_select_layout (GdmSes - impl->priv->selected_layout = g_strdup (text); - } - -- 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)) { -+ GdmSessionConversation *conversation; -+ -+ conversation = (GdmSessionConversation *) value; -+ -+ send_dbus_string_signal (conversation, "SetLayoutName", -+ get_layout_name (impl)); -+ } - } - - static void -@@ -2448,12 +2813,14 @@ 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; - iface->authorize = gdm_session_direct_authorize; - iface->accredit = gdm_session_direct_accredit; -+ iface->open_session = gdm_session_direct_open_session; - iface->close = gdm_session_direct_close; - - iface->cancel = gdm_session_direct_cancel; -diff -up gdm-2.28.0/daemon/gdm-session.h.multistack gdm-2.28.0/daemon/gdm-session.h ---- gdm-2.28.0/daemon/gdm-session.h.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-session.h 2009-09-23 18:46:06.691641204 -0400 -@@ -45,18 +45,27 @@ 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, +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); @@ -3720,14 +5423,12 @@ diff -up gdm-2.28.0/daemon/gdm-session.h.multistack gdm-2.28.0/daemon/gdm-sessio void (* accredit) (GdmSession *session, + const char *service_name, int cred_flag); -+ void (* open_session) (GdmSession *session, -+ const char *service_name); void (* answer_query) (GdmSession *session, + const char *service_name, const char *text); void (* select_language) (GdmSession *session, const char *text); -@@ -66,44 +75,67 @@ struct _GdmSessionIface +@@ -67,38 +71,53 @@ struct _GdmSessionIface const char *text); void (* select_user) (GdmSession *session, const char *text); @@ -3778,11 +5479,6 @@ diff -up gdm-2.28.0/daemon/gdm-session.h.multistack gdm-2.28.0/daemon/gdm-sessio void (* problem) (GdmSession *session, + const char *service_name, const char *problem); -+ void (* session_opened) (GdmSession *session, -+ const char *service_name); -+ void (* session_open_failed) (GdmSession *session, -+ const char *service_name, -+ const char *message); void (* session_started) (GdmSession *session, + const char *service_name, int pid); @@ -3791,28 +5487,7 @@ diff -up gdm-2.28.0/daemon/gdm-session.h.multistack gdm-2.28.0/daemon/gdm-sessio 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 +150,31 @@ 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, +@@ -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); @@ -3826,8 +5501,6 @@ diff -up gdm-2.28.0/daemon/gdm-session.h.multistack gdm-2.28.0/daemon/gdm-sessio + const char *service_name, int cred_flag); -void gdm_session_start_session (GdmSession *session); -+void gdm_session_open_session (GdmSession *session, -+ const char *service_name); +void gdm_session_start_session (GdmSession *session, + const char *service_name); void gdm_session_close (GdmSession *session); @@ -3837,939 +5510,10 @@ diff -up gdm-2.28.0/daemon/gdm-session.h.multistack gdm-2.28.0/daemon/gdm-sessio const char *text); void gdm_session_select_session (GdmSession *session, const char *session_name); -diff -up gdm-2.28.0/daemon/gdm-session-private.h.multistack gdm-2.28.0/daemon/gdm-session-private.h ---- gdm-2.28.0/daemon/gdm-session-private.h.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-session-private.h 2009-09-23 18:46:06.681641189 -0400 -@@ -27,25 +27,43 @@ - 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_opened (GdmSession *session, -+ const char *service_name); -+void _gdm_session_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *message); - void _gdm_session_session_started (GdmSession *session, -+ const char *service_name, - int pid); - 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); -@@ -66,12 +84,16 @@ void _gdm_session_selected_u - - /* call and response stuff */ - void _gdm_session_info_query (GdmSession *session, -+ const char *service_name, - const char *text); - void _gdm_session_secret_info_query (GdmSession *session, -+ const char *service_name, - const char *text); - void _gdm_session_info (GdmSession *session, -+ const char *service_name, - const char *text); - void _gdm_session_problem (GdmSession *session, -+ const char *service_name, - const char *text); - - G_END_DECLS -diff -up gdm-2.28.0/daemon/gdm-session-relay.c.multistack gdm-2.28.0/daemon/gdm-session-relay.c ---- gdm-2.28.0/daemon/gdm-session-relay.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-session-relay.c 2009-09-23 18:46:06.684641082 -0400 -@@ -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 --gdm_session_relay_authenticate (GdmSession *session) -+gdm_session_relay_authenticate (GdmSession *session, -+ const char *service_name) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -- send_dbus_void_signal (impl, "Authenticate"); -+ send_dbus_string_signal (impl, "Authenticate", service_name); - } - - static void --gdm_session_relay_authorize (GdmSession *session) -+gdm_session_relay_authorize (GdmSession *session, -+ const char *service_name) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -- send_dbus_void_signal (impl, "Authorize"); -+ send_dbus_string_signal (impl, "Authorize", service_name); - } - - static void - gdm_session_relay_accredit (GdmSession *session, -+ const char *service_name, - int cred_flag) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); - - switch (cred_flag) { - case GDM_SESSION_CRED_ESTABLISH: -- send_dbus_void_signal (impl, "EstablishCredentials"); -+ send_dbus_string_signal (impl, "EstablishCredentials", service_name); - break; - case GDM_SESSION_CRED_REFRESH: -- send_dbus_void_signal (impl, "RefreshCredentials"); -+ send_dbus_string_signal (impl, "RefreshCredentials", service_name); - break; - default: - g_assert_not_reached (); -@@ -243,11 +247,20 @@ gdm_session_relay_accredit (GdmSession * - } - - static void -+gdm_session_relay_open_session (GdmSession *session, -+ const char *service_name) -+{ -+ GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -+ send_dbus_string_signal (impl, "OpenSession", service_name); -+} -+ -+static void - gdm_session_relay_answer_query (GdmSession *session, -+ const char *service_name, - const char *text) - { - GdmSessionRelay *impl = GDM_SESSION_RELAY (session); -- send_dbus_string_signal (impl, "AnswerQuery", text); -+ send_dbus_string_string_signal (impl, "AnswerQuery", service_name, text); - } - - static void -@@ -291,11 +304,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 +347,12 @@ handle_info_query (GdmSessionRelay *sess - { - DBusMessage *reply; - DBusError error; -- const char *text; -+ char *service_name; -+ char *text; - - 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); -@@ -348,7 +364,7 @@ handle_info_query (GdmSessionRelay *sess - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_info_query (GDM_SESSION (session_relay), text); -+ _gdm_session_info_query (GDM_SESSION (session_relay), service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -360,12 +376,14 @@ handle_secret_info_query (GdmSessionRela - { - DBusMessage *reply; - DBusError error; -- const char *text; -+ char *service_name; -+ char *text; - - text = 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); -@@ -377,7 +395,7 @@ handle_secret_info_query (GdmSessionRela - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_secret_info_query (GDM_SESSION (session_relay), text); -+ _gdm_session_secret_info_query (GDM_SESSION (session_relay), service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -389,12 +407,14 @@ handle_info (GdmSessionRelay *session_re - { - DBusMessage *reply; - DBusError error; -- const char *text; -+ char *service_name; -+ char *text; - - text = 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); -@@ -406,7 +426,7 @@ handle_info (GdmSessionRelay *session_re - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_info (GDM_SESSION (session_relay), text); -+ _gdm_session_info (GDM_SESSION (session_relay), service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -418,12 +438,14 @@ handle_problem (GdmSessionRelay *session - { - DBusMessage *reply; - DBusError error; -- const char *text; -+ char *service_name; -+ char *text; - - text = 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); -@@ -435,7 +457,7 @@ handle_problem (GdmSessionRelay *session - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_problem (GDM_SESSION (session_relay), text); -+ _gdm_session_problem (GDM_SESSION (session_relay), service_name, text); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -447,8 +469,15 @@ handle_setup_complete (GdmSessionRelay * - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: SetupComplete"); - -@@ -456,7 +485,7 @@ handle_setup_complete (GdmSessionRelay * - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_setup_complete (GDM_SESSION (session_relay)); -+ _gdm_session_setup_complete (GDM_SESSION (session_relay), service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -468,8 +497,15 @@ handle_setup_failed (GdmSessionRelay *se - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: SetupFailed"); - -@@ -477,7 +513,7 @@ handle_setup_failed (GdmSessionRelay *se - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_setup_failed (GDM_SESSION (session_relay), NULL); -+ _gdm_session_setup_failed (GDM_SESSION (session_relay), service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -490,8 +526,15 @@ handle_authenticated (GdmSessionRelay *s - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: Authenticated"); - -@@ -499,7 +542,7 @@ handle_authenticated (GdmSessionRelay *s - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authenticated (GDM_SESSION (session_relay)); -+ _gdm_session_authenticated (GDM_SESSION (session_relay), service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -511,8 +554,15 @@ handle_authentication_failed (GdmSession - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: AuthenticationFailed"); - -@@ -520,7 +570,7 @@ handle_authentication_failed (GdmSession - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authentication_failed (GDM_SESSION (session_relay), NULL); -+ _gdm_session_authentication_failed (GDM_SESSION (session_relay), service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -532,8 +582,15 @@ handle_authorized (GdmSessionRelay *sess - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: Authorized"); - -@@ -541,7 +598,7 @@ handle_authorized (GdmSessionRelay *sess - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authorized (GDM_SESSION (session_relay)); -+ _gdm_session_authorized (GDM_SESSION (session_relay), service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -553,8 +610,15 @@ handle_authorization_failed (GdmSessionR - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: AuthorizationFailed"); - -@@ -562,7 +626,7 @@ handle_authorization_failed (GdmSessionR - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_authorization_failed (GDM_SESSION (session_relay), NULL); -+ _gdm_session_authorization_failed (GDM_SESSION (session_relay), service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -574,8 +638,15 @@ handle_accredited (GdmSessionRelay *sess - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: Accredited"); - -@@ -583,7 +654,7 @@ handle_accredited (GdmSessionRelay *sess - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_accredited (GDM_SESSION (session_relay)); -+ _gdm_session_accredited (GDM_SESSION (session_relay), service_name); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -595,8 +666,15 @@ handle_accreditation_failed (GdmSessionR - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - - dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); - - g_debug ("GdmSessionRelay: AccreditationFailed"); - -@@ -604,7 +682,62 @@ handle_accreditation_failed (GdmSessionR - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - -- _gdm_session_accreditation_failed (GDM_SESSION (session_relay), NULL); -+ _gdm_session_accreditation_failed (GDM_SESSION (session_relay), service_name, NULL); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+static DBusHandlerResult -+handle_session_opened (GdmSessionRelay *session_relay, -+ DBusConnection *connection, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ char *service_name; -+ -+ dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); -+ -+ g_debug ("GdmSessionRelay: Session Opened"); -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ _gdm_session_session_opened (GDM_SESSION (session_relay), service_name); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+static DBusHandlerResult -+handle_session_open_failed (GdmSessionRelay *session_relay, -+ DBusConnection *connection, -+ DBusMessage *message) -+{ -+ DBusMessage *reply; -+ DBusError error; -+ char *service_name; -+ -+ dbus_error_init (&error); -+ if (! dbus_message_get_args (message, &error, -+ DBUS_TYPE_STRING, &service_name, -+ DBUS_TYPE_INVALID)) { -+ g_warning ("ERROR: %s", error.message); -+ } -+ dbus_error_free (&error); -+ -+ g_debug ("GdmSessionRelay: Session Open Failed"); -+ -+ reply = dbus_message_new_method_return (message); -+ dbus_connection_send (connection, reply, NULL); -+ dbus_message_unref (reply); -+ -+ _gdm_session_session_open_failed (GDM_SESSION (session_relay), service_name, NULL); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -616,6 +749,7 @@ handle_session_started (GdmSessionRelay - { - DBusMessage *reply; - DBusError error; -+ char *service_name; - int pid; - - dbus_error_init (&error); -@@ -623,6 +757,7 @@ handle_session_started (GdmSessionRelay - pid = 0; - if (! dbus_message_get_args (message, - &error, -+ DBUS_TYPE_STRING, &service_name, - DBUS_TYPE_INT32, &pid, - DBUS_TYPE_INVALID)) { - g_warning ("ERROR: %s", error.message); -@@ -635,6 +770,7 @@ handle_session_started (GdmSessionRelay - dbus_message_unref (reply); - - _gdm_session_session_started (GDM_SESSION (session_relay), -+ service_name, - pid); - - return DBUS_HANDLER_RESULT_HANDLED; -@@ -664,22 +800,28 @@ handle_session_stopped (GdmSessionRelay - } - - 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); -+ } - -- g_debug ("GdmSessionRelay: Opened"); -+ g_debug ("GdmSessionRelay: Conversation Started"); - - reply = dbus_message_new_method_return (message); - 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); - - return DBUS_HANDLER_RESULT_HANDLED; - } -@@ -715,12 +857,16 @@ session_handle_child_message (DBusConnec - return handle_accredited (session_relay, connection, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "AccreditationFailed")) { - return handle_accreditation_failed (session_relay, connection, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionOpened")) { -+ return handle_session_opened (session_relay, connection, message); -+ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionOpenFailed")) { -+ return handle_session_open_failed (session_relay, connection, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStarted")) { - return handle_session_started (session_relay, connection, message); - } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStopped")) { - 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); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -@@ -749,7 +895,8 @@ do_introspect (DBusConnection *connectio - /* interface */ - xml = g_string_append (xml, - " \n" -- " \n" -+ " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -810,7 +957,8 @@ do_introspect (DBusConnection *connectio - " \n" - " \n" - -- " \n" -+ " \n" -+ " \n" - " \n" - " \n" - " \n" -@@ -1106,12 +1254,13 @@ 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; - iface->authorize = gdm_session_relay_authorize; - iface->accredit = gdm_session_relay_accredit; -+ iface->open_session = gdm_session_relay_open_session; - iface->close = gdm_session_relay_close; - - iface->cancel = gdm_session_relay_cancel; -diff -up gdm-2.28.0/daemon/gdm-session-worker.c.multistack gdm-2.28.0/daemon/gdm-session-worker.c ---- gdm-2.28.0/daemon/gdm-session-worker.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-session-worker.c 2009-09-23 18:46:06.895410636 -0400 -@@ -2302,8 +2302,6 @@ do_setup (GdmSessionWorker *worker) - GError *error; - gboolean res; - -- worker->priv->user_settings = gdm_session_settings_new (); -- - g_signal_connect_swapped (worker->priv->user_settings, - "notify::language-name", - G_CALLBACK (on_saved_language_name_read), -@@ -2439,13 +2437,13 @@ do_open_session (GdmSessionWorker *worke - res = gdm_session_worker_open_user_session (worker, &error); - if (! res) { - send_dbus_string_method (worker->priv->connection, -- "StartFailed", -+ "OpenFailed", - error->message); - g_error_free (error); - return; - } - -- queue_state_change (worker); -+ send_dbus_void_method (worker->priv->connection, "SessionOpened"); - } - - static void -@@ -2561,7 +2559,7 @@ on_start_program (GdmSessionWorker *work - const char *text; - dbus_bool_t res; - -- if (worker->priv->state != GDM_SESSION_WORKER_STATE_ACCREDITED) { -+ if (worker->priv->state != GDM_SESSION_WORKER_STATE_SESSION_OPENED) { - g_debug ("GdmSessionWorker: ignoring spurious start program while in state %s", get_state_name (worker->priv->state)); - return; - } -@@ -2720,6 +2718,14 @@ on_establish_credentials (GdmSessionWork - } - - static void -+on_open_session (GdmSessionWorker *worker, -+ DBusMessage *message) -+{ -+ /* FIXME: return error if not in ACCREDITED state */ -+ queue_state_change (worker); -+} -+ -+static void - on_reauthenticate (GdmSessionWorker *worker, - DBusMessage *message) - { -@@ -2791,6 +2797,8 @@ worker_dbus_handle_message (DBusConnecti - on_authorize (worker, message); - } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "EstablishCredentials")) { - on_establish_credentials (worker, message); -+ } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "OpenSession")) { -+ on_open_session (worker, message); - } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "StartProgram")) { - on_start_program (worker, message); - } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "Reauthenticate")) { -@@ -2848,6 +2856,28 @@ worker_dbus_filter_function (DBusConnect - return DBUS_HANDLER_RESULT_HANDLED; - } - -+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, -@@ -2874,6 +2904,11 @@ gdm_session_worker_constructor (GType - 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); - -@@ -2915,6 +2950,7 @@ gdm_session_worker_init (GdmSessionWorke - g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); -+ worker->priv->user_settings = gdm_session_settings_new (); - } - - static void -diff -up gdm-2.28.0/daemon/gdm-session-worker-job.c.multistack gdm-2.28.0/daemon/gdm-session-worker-job.c ---- gdm-2.28.0/daemon/gdm-session-worker-job.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-session-worker-job.c 2009-09-23 18:46:06.896400986 -0400 -@@ -68,7 +68,6 @@ enum { - - enum { - STARTED, -- STOPPED, - EXITED, - DIED, - LAST_SIGNAL -@@ -150,6 +149,37 @@ copy_environment_to_hash (GHashTable *ha - } - - 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; -@@ -172,31 +202,31 @@ get_job_environment (GdmSessionWorkerJob - } - - 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, -@@ -205,6 +235,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); - -@@ -221,7 +254,6 @@ gdm_session_worker_job_spawn (GdmSession - (GChildWatchFunc)session_worker_job_child_watch, - session_worker_job); - -- g_strfreev (argv); - out: - - return ret; -@@ -234,13 +266,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) - { - 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) { - -@@ -287,7 +320,8 @@ 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); -+ res = gdm_signal_pid (session_worker_job->priv->pid, SIGKILL); -+ - if (res < 0) { - g_warning ("Unable to kill session worker process"); - } else { -@@ -297,6 +331,13 @@ gdm_session_worker_job_stop (GdmSessionW - return TRUE; - } - -+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) -@@ -390,16 +431,6 @@ gdm_session_worker_job_class_init (GdmSe - 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 -up gdm-2.28.0/daemon/gdm-session-worker-job.h.multistack gdm-2.28.0/daemon/gdm-session-worker-job.h ---- gdm-2.28.0/daemon/gdm-session-worker-job.h.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/gdm-session-worker-job.h 2009-09-23 18:46:06.592642295 -0400 -@@ -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); - -@@ -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); - -+GPid gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job); -+ - G_END_DECLS - - #endif /* __GDM_SESSION_WORKER_JOB_H */ -diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-simple-slave.c ---- gdm-2.28.0/daemon/gdm-simple-slave.c.multistack 2009-09-23 18:46:06.484641543 -0400 -+++ gdm-2.28.0/daemon/gdm-simple-slave.c 2009-09-23 18:46:06.877395356 -0400 +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index 4db7440..9421a64 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c @@ -71,6 +71,8 @@ struct GdmSimpleSlavePrivate guint greeter_reset_id; guint start_session_id; @@ -4779,7 +5523,7 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s int ping_interval; GPid server_pid; -@@ -102,6 +104,7 @@ static void start_greeter (GdmSimpl +@@ -101,6 +103,7 @@ static void start_greeter (GdmSimpleSlave *slave); static void on_session_started (GdmSession *session, @@ -4787,15 +5531,7 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s int pid, GdmSimpleSlave *slave) { -@@ -175,7 +178,6 @@ reset_session (GdmSimpleSlave *slave) - { - destroy_session (slave); - create_new_session (slave); -- gdm_session_open (GDM_SESSION (slave->priv->session)); - } - - static gboolean -@@ -206,23 +208,25 @@ queue_greeter_reset (GdmSimpleSlave *sla +@@ -204,19 +207,22 @@ queue_greeter_reset (GdmSimpleSlave *slave) static void on_session_setup_complete (GdmSession *session, @@ -4819,13 +5555,8 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s + message != NULL ? message: _("Unable to initialize login system")); } -- destroy_session (slave); -- queue_greeter_reset (slave); -+ gdm_session_stop_conversation (session, service_name); - } - - static void -@@ -242,26 +246,30 @@ on_session_reset_failed (GdmSession + destroy_session (slave); +@@ -240,18 +246,21 @@ on_session_reset_failed (GdmSession *session, static void on_session_authenticated (GdmSession *session, @@ -4847,10 +5578,8 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s + service_name, message != NULL ? message : _("Unable to authenticate user")); } -- destroy_session (slave); -- queue_greeter_reset (slave); -+ -+ gdm_session_stop_conversation (session, service_name); + destroy_session (slave); +@@ -259,7 +268,8 @@ on_session_authentication_failed (GdmSession *session, } static void @@ -4860,7 +5589,7 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s { if (slave->priv->start_session_when_ready) { char *ssid; -@@ -282,7 +290,7 @@ gdm_simple_slave_accredit_when_ready (Gd +@@ -280,7 +290,7 @@ gdm_simple_slave_accredit_when_ready (GdmSimpleSlave *slave) g_free (ssid); g_free (username); @@ -4869,7 +5598,7 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s } else { slave->priv->waiting_to_start_session = TRUE; } -@@ -290,29 +298,31 @@ gdm_simple_slave_accredit_when_ready (Gd +@@ -288,25 +298,28 @@ gdm_simple_slave_accredit_when_ready (GdmSimpleSlave *slave) static void on_session_authorized (GdmSession *session, @@ -4901,13 +5630,8 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s + message != NULL ? message : _("Unable to authorize user")); } -- destroy_session (slave); -- queue_greeter_reset (slave); -+ gdm_session_stop_conversation (session, service_name); - } - - static gboolean -@@ -388,31 +398,38 @@ start_session_timeout (GdmSimpleSlave *s + destroy_session (slave); +@@ -386,31 +399,38 @@ start_session_timeout (GdmSimpleSlave *slave) g_free (auth_file); @@ -4940,7 +5664,7 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s GdmSimpleSlave *slave) { - queue_start_session (slave); -+ gdm_session_open_session (session, service_name); ++ queue_start_session (slave, service_name); } static void @@ -4949,7 +5673,7 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s const char *message, GdmSimpleSlave *slave) { -@@ -433,6 +450,7 @@ on_session_accreditation_failed (GdmSess +@@ -431,6 +451,7 @@ on_session_accreditation_failed (GdmSession *session, problem = _("Unable to establish credentials"); } gdm_greeter_server_problem (slave->priv->greeter_server, @@ -4957,38 +5681,7 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s problem); } } -@@ -441,62 +459,90 @@ 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_opened (GdmSession *session, -+ const char *service_name, -+ GdmSimpleSlave *slave) -+{ -+ queue_start_session (slave, service_name); -+} -+ -+static void -+on_session_open_failed (GdmSession *session, -+ const char *service_name, -+ const char *message, -+ GdmSimpleSlave *slave) -+{ -+ if (slave->priv->greeter_server != NULL) { -+ gdm_greeter_server_problem (slave->priv->greeter_server, -+ service_name, -+ _("Unable to open session")); -+ } -+ -+ gdm_session_stop_conversation (session, service_name); - } +@@ -446,41 +467,45 @@ on_session_accreditation_failed (GdmSession *session, static void on_session_info (GdmSession *session, @@ -5038,134 +5731,21 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s } 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; - 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"); - } -@@ -512,8 +558,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); - } - -@@ -521,6 +569,23 @@ on_session_opened (GdmSession *sessi - } +@@ -750,11 +775,12 @@ on_greeter_start_conversation (GdmGreeterServer *greeter_server, 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 != 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) -@@ -605,8 +670,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", -@@ -649,6 +718,14 @@ create_new_session (GdmSimpleSlave *slav - G_CALLBACK (on_session_accreditation_failed), - slave); - g_signal_connect (slave->priv->session, -+ "session-opened", -+ G_CALLBACK (on_session_opened), -+ slave); -+ g_signal_connect (slave->priv->session, -+ "session-open-failed", -+ G_CALLBACK (on_session_open_failed), -+ slave); -+ g_signal_connect (slave->priv->session, - "info", - G_CALLBACK (on_session_info), - slave); -@@ -737,12 +814,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 -@@ -751,6 +845,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); -@@ -758,21 +855,29 @@ on_greeter_begin_auto_login (GdmGreeterS +@@ -770,21 +796,23 @@ on_greeter_begin_auto_login (GdmGreeterServer *greeter_server, static void on_greeter_begin_verification_for_user (GdmGreeterServer *greeter_server, @@ -5174,9 +5754,6 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s 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, @@ -5190,68 +5767,11 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s 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 -@@ -780,6 +885,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); - } - -@@ -788,6 +896,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); - } - -@@ -796,6 +907,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); - } - -@@ -812,7 +926,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 -@@ -822,8 +940,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, -@@ -837,21 +956,29 @@ on_greeter_connected (GdmGreeterServer * +@@ -847,18 +875,20 @@ on_greeter_connected (GdmGreeterServer *greeter_server, static void on_start_session_when_ready (GdmGreeterServer *session, @@ -5259,9 +5779,6 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s 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) { @@ -5276,60 +5793,11 @@ diff -up gdm-2.28.0/daemon/gdm-simple-slave.c.multistack gdm-2.28.0/daemon/gdm-s 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; - } - -@@ -922,6 +1049,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); -@@ -1031,8 +1162,18 @@ idle_connect_to_display (GdmSimpleSlave - if (! enabled || delay > 0) { - start_greeter (slave); - create_new_session (slave); -+ -+ if (enabled) { -+ g_debug ("GdmSimpleSlave: Starting timed login conversation"); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), -+ "gdm-autologin"); -+ } - } else { - reset_session (slave); -+ -+ g_debug ("GdmSimpleSlave: Starting automatic login conversation"); -+ gdm_session_start_conversation (GDM_SESSION (slave->priv->session), -+ "gdm-autologin"); - } - } else { - if (slave->priv->connection_attempts >= MAX_CONNECT_ATTEMPTS) { -diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-session.c ---- gdm-2.28.0/daemon/test-session.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/daemon/test-session.c 2009-09-23 18:46:06.649640679 -0400 -@@ -33,20 +33,22 @@ - 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); - } +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, static void on_session_setup_complete (GdmSession *session, @@ -5342,7 +5810,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess } static void -@@ -78,10 +80,11 @@ on_session_reset_failed (GdmSession *ses +@@ -79,10 +80,11 @@ on_session_reset_failed (GdmSession *session, static void on_session_authenticated (GdmSession *session, @@ -5355,7 +5823,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess } static void -@@ -96,14 +99,16 @@ on_session_authentication_failed (GdmSes +@@ -97,14 +99,16 @@ on_session_authentication_failed (GdmSession *session, static void on_session_authorized (GdmSession *session, @@ -5373,7 +5841,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess const char *message, gpointer data) { -@@ -114,6 +119,7 @@ on_session_authorization_failed (GdmSess +@@ -115,6 +119,7 @@ on_session_authorization_failed (GdmSession *session, static void on_session_accredited (GdmSession *session, @@ -5381,7 +5849,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess gpointer data) { char *username; -@@ -124,12 +130,13 @@ on_session_accredited (GdmSession *sessi +@@ -125,12 +130,13 @@ on_session_accredited (GdmSession *session, username ? username : "", username ? " " : ""); g_free (username); @@ -5396,7 +5864,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess const char *message, gpointer data) { -@@ -164,6 +171,7 @@ on_session_died (GdmSession *session, +@@ -165,6 +171,7 @@ on_session_died (GdmSession *session, static void on_info_query (GdmSession *session, @@ -5404,7 +5872,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess const char *query_text) { char answer[1024]; -@@ -177,12 +185,13 @@ on_info_query (GdmSession *session, +@@ -178,12 +185,13 @@ on_info_query (GdmSession *session, gdm_session_close (session); g_main_loop_quit (loop); } else { @@ -5419,7 +5887,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess const char *info) { g_print ("\n** NOTE: %s\n", info); -@@ -190,6 +199,7 @@ on_info (GdmSession *session, +@@ -191,6 +199,7 @@ on_info (GdmSession *session, static void on_problem (GdmSession *session, @@ -5427,7 +5895,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess const char *problem) { g_print ("\n** WARNING: %s\n", problem); -@@ -197,6 +207,7 @@ on_problem (GdmSession *session, +@@ -198,6 +207,7 @@ on_problem (GdmSession *session, static void on_secret_info_query (GdmSession *session, @@ -5435,7 +5903,7 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess const char *query_text) { char answer[1024]; -@@ -221,7 +232,7 @@ on_secret_info_query (GdmSession *sessio +@@ -222,7 +232,7 @@ on_secret_info_query (GdmSession *session, g_print ("\n"); @@ -5444,113 +5912,11 @@ diff -up gdm-2.28.0/daemon/test-session.c.multistack gdm-2.28.0/daemon/test-sess } static void -@@ -256,11 +267,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", -diff -up gdm-2.28.0/gui/simple-greeter/gdm-chooser-widget.c.multistack gdm-2.28.0/gui/simple-greeter/gdm-chooser-widget.c ---- gdm-2.28.0/gui/simple-greeter/gdm-chooser-widget.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-chooser-widget.c 2009-09-23 18:46:06.773650311 -0400 -@@ -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; -@@ -2171,13 +2172,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); -+ } -+ -+ if (name != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_NAME_COLUMN, name, -1); -+ } -+ -+ if (priority != NULL) { -+ gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter, -+ CHOOSER_PRIORITY_COLUMN, priority, -1); -+ } -+ -+ 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; - } -@@ -2524,8 +2542,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.28.0/gui/simple-greeter/gdm-chooser-widget.h.multistack gdm-2.28.0/gui/simple-greeter/gdm-chooser-widget.h ---- gdm-2.28.0/gui/simple-greeter/gdm-chooser-widget.h.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-chooser-widget.h 2009-09-23 18:46:06.775655105 -0400 -@@ -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.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c ---- gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c 2009-09-23 18:46:06.721641040 -0400 -@@ -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 ( +diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c +index 1e2c55d..0bd27a9 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, } static void @@ -5588,7 +5954,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. emit_string_signal_for_message (GdmGreeterClient *client, const char *name, DBusMessage *message, -@@ -200,48 +232,49 @@ static void +@@ -200,37 +231,35 @@ static void on_user_authorized (GdmGreeterClient *client, DBusMessage *message) { @@ -5631,25 +5997,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. } static void - 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 +@@ -307,14 +336,22 @@ send_dbus_string_method (DBusConnection *connection, } static gboolean @@ -5675,7 +6023,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. g_debug ("GdmGreeterClient: Calling %s", method); message = dbus_message_new_method_call (NULL, -@@ -332,8 +373,77 @@ send_dbus_bool_method (DBusConnection *c +@@ -328,8 +365,77 @@ send_dbus_bool_method (DBusConnection *connection, dbus_message_iter_init_append (message, &iter); dbus_message_iter_append_basic (&iter, @@ -5754,22 +6102,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, -@@ -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 +@@ -412,37 +518,44 @@ gdm_greeter_client_call_begin_auto_login (GdmGreeterClient *client, } void @@ -5826,16 +6159,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. } void -@@ -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 +@@ -835,10 +948,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) G_STRUCT_OFFSET (GdmGreeterClientClass, info_query), NULL, NULL, @@ -5849,7 +6173,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. gdm_greeter_client_signals[SECRET_INFO_QUERY] = g_signal_new ("secret-info-query", -@@ -843,10 +970,10 @@ gdm_greeter_client_class_init (GdmGreete +@@ -847,10 +960,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) G_STRUCT_OFFSET (GdmGreeterClientClass, secret_info_query), NULL, NULL, @@ -5863,7 +6187,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. gdm_greeter_client_signals[INFO] = g_signal_new ("info", -@@ -855,10 +982,10 @@ gdm_greeter_client_class_init (GdmGreete +@@ -859,10 +972,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) G_STRUCT_OFFSET (GdmGreeterClientClass, info), NULL, NULL, @@ -5877,7 +6201,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. gdm_greeter_client_signals[PROBLEM] = g_signal_new ("problem", -@@ -867,10 +994,10 @@ gdm_greeter_client_class_init (GdmGreete +@@ -871,10 +984,10 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) G_STRUCT_OFFSET (GdmGreeterClientClass, problem), NULL, NULL, @@ -5891,30 +6215,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. gdm_greeter_client_signals[READY] = g_signal_new ("ready", -@@ -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 +@@ -956,8 +1069,9 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) G_STRUCT_OFFSET (GdmGreeterClientClass, user_authorized), NULL, NULL, @@ -5926,10 +6227,11 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.c.multistack gdm-2.28. } static void -diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.h.multistack gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.h ---- gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.h.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.h 2009-09-23 18:46:06.722645987 -0400 -@@ -45,17 +45,24 @@ typedef struct +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 GObjectClass parent_class; void (* info_query) (GdmGreeterClient *client, @@ -5949,13 +6251,11 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.h.multistack gdm-2.28. const char *problem); - 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 +76,8 @@ typedef struct +@@ -69,7 +74,8 @@ typedef struct void (* timed_login_requested) (GdmGreeterClient *client, const char *username, int delay); @@ -5965,20 +6265,8 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.h.multistack gdm-2.28. } GdmGreeterClientClass; #define GDM_GREETER_CLIENT_ERROR (gdm_greeter_client_error_quark ()) -@@ -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); +@@ -95,8 +101,10 @@ void gdm_greeter_client_call_start_conversation (GdmGreeter + 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); @@ -5989,7 +6277,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.h.multistack gdm-2.28. const char *username); void gdm_greeter_client_call_cancel (GdmGreeterClient *client); void gdm_greeter_client_call_disconnect (GdmGreeterClient *client); -@@ -109,9 +121,11 @@ void gdm_greeter_client_ca +@@ -111,9 +119,11 @@ void gdm_greeter_client_call_select_layout (GdmGreeter void gdm_greeter_client_call_select_session (GdmGreeterClient *client, const char *text); void gdm_greeter_client_call_answer_query (GdmGreeterClient *client, @@ -6001,9 +6289,2244 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-client.h.multistack gdm-2.28. gboolean should_start_session); -diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c ---- gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c 2009-09-23 18:46:06.871400249 -0400 +diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c +index cd0cbdf..e856dd4 100644 +--- a/gui/simple-greeter/gdm-greeter-session.c ++++ b/gui/simple-greeter/gdm-greeter-session.c +@@ -65,6 +65,7 @@ static gpointer session_object = NULL; + + static void + on_info (GdmGreeterClient *client, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) + { +@@ -75,6 +76,7 @@ on_info (GdmGreeterClient *client, + + static void + on_problem (GdmGreeterClient *client, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) + { +@@ -173,6 +175,7 @@ on_user_authorized (GdmGreeterClient *client, + + static void + on_info_query (GdmGreeterClient *client, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) + { +@@ -183,6 +186,7 @@ on_info_query (GdmGreeterClient *client, + + static void + on_secret_info_query (GdmGreeterClient *client, ++ const char *service_name, + const char *text, + GdmGreeterSession *session) + { +@@ -204,7 +208,8 @@ static void + on_begin_verification (GdmGreeterLoginWindow *login_window, + GdmGreeterSession *session) + { +- gdm_greeter_client_call_begin_verification (session->priv->client); ++ gdm_greeter_client_call_begin_verification (session->priv->client, ++ "gdm"); + } + + static void +@@ -213,6 +218,7 @@ on_begin_verification_for_user (GdmGreeterLoginWindow *login_window, + GdmGreeterSession *session) + { + gdm_greeter_client_call_begin_verification_for_user (session->priv->client, ++ "gdm", + username); + } + +@@ -222,6 +228,7 @@ on_query_answer (GdmGreeterLoginWindow *login_window, + GdmGreeterSession *session) + { + gdm_greeter_client_call_answer_query (session->priv->client, ++ "gdm", + text); + } + +@@ -285,7 +292,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 int +-- +1.6.5.1 + + +From bc4cdcc36df5af64065144c016abaa9513a54e54 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sat, 7 Feb 2009 11:36:40 -0500 +Subject: [PATCH 39/81] 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 | 14 ++++++++++++++ + 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, 114 insertions(+), 8 deletions(-) + +diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c +index dae34c5..ecb2ad6 100644 +--- a/daemon/gdm-greeter-server.c ++++ b/daemon/gdm-greeter-server.c +@@ -299,6 +299,14 @@ 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); ++ return TRUE; ++} ++ + void + gdm_greeter_server_selected_user_changed (GdmGreeterServer *greeter_server, + const char *username) +@@ -797,6 +805,9 @@ do_introspect (DBusConnection *connection, + " \n" + " \n" + " \n" ++ " \n" ++ " \n" ++ " \n" + " \n" + " \n" + " \n" +@@ -868,6 +879,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 1c151fd..dc8b4f6 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -1697,9 +1697,15 @@ worker_exited (GdmSessionWorkerJob *job, + { + g_debug ("GdmSessionDirect: Worker job exited: %d", code); + ++ g_object_ref (conversation->job); + 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->job); + } + + static void +@@ -1709,9 +1715,15 @@ worker_died (GdmSessionWorkerJob *job, + { + g_debug ("GdmSessionDirect: Worker job died: %d", signum); + ++ g_object_ref (conversation->job); + if (conversation->session->priv->is_running) { + _gdm_session_session_died (GDM_SESSION (conversation->session), signum); + } ++ ++ g_debug ("GdmSessionDirect: Emitting conversation-stopped signal"); ++ _gdm_session_conversation_stopped (GDM_SESSION (conversation->session), ++ conversation->service_name); ++ g_object_unref (conversation->job); + } + + static GdmSessionConversation * +@@ -1784,6 +1796,10 @@ stop_conversation (GdmSessionConversation *conversation) + + 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 +@@ -1804,6 +1820,25 @@ gdm_session_direct_start_conversation (GdmSession *session, + } + + 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 + send_setup (GdmSessionDirect *session, + const char *service_name) + { +@@ -2623,6 +2658,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) ++{ ++ g_return_if_fail (GDM_IS_SESSION (session)); ++ ++ GDM_SESSION_GET_IFACE (session)->stop_conversation (session, service_name); ++} ++ ++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) ++{ ++ g_return_if_fail (GDM_IS_SESSION (session)); ++ g_signal_emit (session, signals [CONVERSATION_STOPPED], 0, service_name); ++} ++ ++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 9421a64..6eadf62 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -225,8 +225,7 @@ on_session_setup_failed (GdmSession *session, + message != NULL ? message: _("Unable to initialize login system")); + } + +- destroy_session (slave); +- queue_greeter_reset (slave); ++ gdm_session_stop_conversation (session, service_name); + } + + static void +@@ -263,8 +262,8 @@ on_session_authentication_failed (GdmSession *session, + service_name, + message != NULL ? message : _("Unable to authenticate user")); + } +- destroy_session (slave); +- queue_greeter_reset (slave); ++ ++ gdm_session_stop_conversation (session, service_name); + } + + static void +@@ -322,8 +321,7 @@ on_session_authorization_failed (GdmSession *session, + message != NULL ? message : _("Unable to authorize user")); + } + +- destroy_session (slave); +- queue_greeter_reset (slave); ++ gdm_session_stop_conversation (session, service_name); + } + + static gboolean +@@ -460,9 +458,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 +@@ -548,6 +545,23 @@ on_session_conversation_started (GdmSession *session, + } + + 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) +@@ -636,6 +650,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.5.1 + + +From 2da86871bdfe2ff0b147db4077350b2ef2a0623f Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 26 Oct 2009 10:17:49 -0400 +Subject: [PATCH 40/81] init session pid to -1 + +--- + daemon/gdm-session-direct.c | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c +index dc8b4f6..e0b5f32 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -2285,7 +2285,6 @@ gdm_session_direct_close (GdmSession *session) + + g_hash_table_remove_all (impl->priv->environment); + +- impl->priv->session_pid = -1; + impl->priv->is_running = FALSE; + } + +-- +1.6.5.1 + + +From efc53714006058ce219d4dac748e63b18e72c684 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 9 Mar 2009 15:41:12 -0400 +Subject: [PATCH 41/81] Don't tear down greeter until pam_open_session finishes + +Some PAM modules ask questions at that late stage of the game, +and so we need a greeter to forward the questions on to the +user. +--- + daemon/gdm-factory-slave.c | 37 ++++++++++++++++++++-- + daemon/gdm-product-slave.c | 30 +++++++++++++++++- + daemon/gdm-session-direct.c | 70 ++++++++++++++++++++++++++++++++++++++++++ + daemon/gdm-session-private.h | 5 +++ + daemon/gdm-session-relay.c | 68 ++++++++++++++++++++++++++++++++++++++++ + daemon/gdm-session-worker.c | 16 ++++++++-- + daemon/gdm-session.c | 50 ++++++++++++++++++++++++++++++ + daemon/gdm-session.h | 9 +++++ + daemon/gdm-simple-slave.c | 33 +++++++++++++++++++- + 9 files changed, 310 insertions(+), 8 deletions(-) + +diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c +index 826612e..ef6d236 100644 +--- a/daemon/gdm-factory-slave.c ++++ b/daemon/gdm-factory-slave.c +@@ -278,9 +278,7 @@ on_session_accredited (GdmSession *session, + { + g_debug ("GdmFactorySlave: session user verified"); + +- gdm_session_start_session (session, service_name); +- +- gdm_greeter_server_reset (slave->priv->greeter_server); ++ gdm_session_open_session (session, service_name); + } + + static void +@@ -298,6 +296,31 @@ on_session_accreditation_failed (GdmSession *session, + } + + static void ++on_session_opened (GdmSession *session, ++ const char *service_name, ++ GdmFactorySlave *slave) ++{ ++ g_debug ("GdmFactorySlave: session opened"); ++ ++ gdm_session_start_session (session, service_name); ++ ++ gdm_greeter_server_reset (slave->priv->greeter_server); ++} ++ ++static void ++on_session_open_failed (GdmSession *session, ++ const char *service_name, ++ const char *message, ++ GdmFactorySlave *slave) ++{ ++ g_debug ("GdmFactorySlave: could not open session: %s", message); ++ ++ gdm_greeter_server_problem (slave->priv->greeter_server, service_name, _("Unable to open session")); ++ ++ queue_greeter_reset (slave); ++} ++ ++static void + on_session_session_started (GdmSession *session, + GdmFactorySlave *slave) + { +@@ -767,6 +790,14 @@ gdm_factory_slave_start (GdmSlave *slave) + G_CALLBACK (on_session_accreditation_failed), + slave); + g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, ++ "session-opened", ++ G_CALLBACK (on_session_opened), ++ slave); ++ g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, ++ "session-open-failed", ++ G_CALLBACK (on_session_open_failed), ++ slave); ++ g_signal_connect (GDM_FACTORY_SLAVE (slave)->priv->session, + "info", + G_CALLBACK (on_session_info), + slave); +diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c +index dd2e1bc..93d83a1 100644 +--- a/daemon/gdm-product-slave.c ++++ b/daemon/gdm-product-slave.c +@@ -635,6 +635,27 @@ on_session_accreditation_failed (GdmSession *session, + } + + static void ++on_session_opened (GdmSession *session, ++ const char *service_name, ++ GdmProductSlave *slave) ++{ ++ send_dbus_string_method (slave->priv->session_relay_connection, ++ "SessionOpened", service_name); ++} ++ ++static void ++on_session_open_failed (GdmSession *session, ++ const char *service_name, ++ const char *message, ++ GdmProductSlave *slave) ++{ ++ send_dbus_string_string_method (slave->priv->session_relay_connection, ++ "SessionOpenFailed", ++ service_name, ++ message); ++} ++ ++static void + on_session_info (GdmSession *session, + const char *service_name, + const char *text, +@@ -1051,7 +1072,14 @@ create_new_session (GdmProductSlave *slave) + "accreditation-failed", + G_CALLBACK (on_session_accreditation_failed), + slave); +- ++ g_signal_connect (slave->priv->session, ++ "session-opened", ++ G_CALLBACK (on_session_opened), ++ slave); ++ g_signal_connect (slave->priv->session, ++ "session-open-failed", ++ G_CALLBACK (on_session_open_failed), ++ slave); + g_signal_connect (slave->priv->session, + "info", + G_CALLBACK (on_session_info), +diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c +index e0b5f32..738267a 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -940,6 +940,58 @@ gdm_session_direct_handle_problem (GdmSessionDirect *session, + } + + static DBusHandlerResult ++gdm_session_direct_handle_session_opened (GdmSessionDirect *session, ++ GdmSessionConversation *conversation, ++ DBusMessage *message) ++{ ++ DBusMessage *reply; ++ DBusError error; ++ ++ g_debug ("GdmSessionDirect: Handling SessionOpened"); ++ ++ dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ ++ g_debug ("GdmSessionDirect: Emitting 'session-opened' signal"); ++ ++ _gdm_session_session_opened (GDM_SESSION (session), conversation->service_name); ++ ++ reply = dbus_message_new_method_return (message); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); ++ dbus_message_unref (reply); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ ++static DBusHandlerResult ++gdm_session_direct_handle_open_failed (GdmSessionDirect *session, ++ GdmSessionConversation *conversation, ++ DBusMessage *message) ++{ ++ DBusMessage *reply; ++ DBusError error; ++ const char *text; ++ ++ dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &text, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ ++ reply = dbus_message_new_method_return (message); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); ++ dbus_message_unref (reply); ++ ++ g_debug ("GdmSessionDirect: Emitting 'session-open-failed' signal"); ++ _gdm_session_session_open_failed (GDM_SESSION (session), conversation->service_name, text); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ ++static DBusHandlerResult + gdm_session_direct_handle_session_started (GdmSessionDirect *session, + GdmSessionConversation *conversation, + DBusMessage *message) +@@ -1206,6 +1258,10 @@ session_worker_message (DBusConnection *connection, + return gdm_session_direct_handle_accreditation_failed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) { + return gdm_session_direct_handle_username_changed (session, conversation, message); ++ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionOpened")) { ++ return gdm_session_direct_handle_session_opened (session, conversation, message); ++ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "OpenFailed")) { ++ return gdm_session_direct_handle_open_failed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) { + return gdm_session_direct_handle_session_started (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartFailed")) { +@@ -2189,6 +2245,19 @@ setup_session_environment (GdmSessionDirect *session) + } + + static void ++gdm_session_direct_open_session (GdmSession *session, ++ const char *service_name) ++{ ++ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session); ++ GdmSessionConversation *conversation; ++ ++ g_return_if_fail (session != NULL); ++ ++ conversation = find_conversation_by_name (impl, service_name); ++ send_dbus_void_signal (conversation, "OpenSession"); ++} ++ ++static void + gdm_session_direct_start_session (GdmSession *session, + const char *service_name) + { +@@ -2663,6 +2732,7 @@ gdm_session_iface_init (GdmSessionIface *iface) + iface->authenticate = gdm_session_direct_authenticate; + iface->authorize = gdm_session_direct_authorize; + iface->accredit = gdm_session_direct_accredit; ++ iface->open_session = gdm_session_direct_open_session; + iface->close = gdm_session_direct_close; + + iface->cancel = gdm_session_direct_cancel; +diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h +index 860c09c..36781dd 100644 +--- a/daemon/gdm-session-private.h ++++ b/daemon/gdm-session-private.h +@@ -54,6 +54,11 @@ void _gdm_session_accredited (GdmSession *sessio + void _gdm_session_accreditation_failed (GdmSession *session, + const char *service_name, + const char *text); ++void _gdm_session_session_opened (GdmSession *session, ++ const char *service_name); ++void _gdm_session_session_open_failed (GdmSession *session, ++ const char *service_name, ++ const char *message); + void _gdm_session_session_started (GdmSession *session, + const char *service_name, + int pid); +diff --git a/daemon/gdm-session-relay.c b/daemon/gdm-session-relay.c +index 6e15f75..3bf8ed7 100644 +--- a/daemon/gdm-session-relay.c ++++ b/daemon/gdm-session-relay.c +@@ -247,6 +247,14 @@ gdm_session_relay_accredit (GdmSession *session, + } + + static void ++gdm_session_relay_open_session (GdmSession *session, ++ const char *service_name) ++{ ++ GdmSessionRelay *impl = GDM_SESSION_RELAY (session); ++ send_dbus_string_signal (impl, "OpenSession", service_name); ++} ++ ++static void + gdm_session_relay_answer_query (GdmSession *session, + const char *service_name, + const char *text) +@@ -678,6 +686,61 @@ handle_accreditation_failed (GdmSessionRelay *session_relay, + + return DBUS_HANDLER_RESULT_HANDLED; + } ++static DBusHandlerResult ++handle_session_opened (GdmSessionRelay *session_relay, ++ DBusConnection *connection, ++ DBusMessage *message) ++{ ++ DBusMessage *reply; ++ DBusError error; ++ char *service_name; ++ ++ dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); ++ ++ g_debug ("GdmSessionRelay: Session Opened"); ++ ++ reply = dbus_message_new_method_return (message); ++ dbus_connection_send (connection, reply, NULL); ++ dbus_message_unref (reply); ++ ++ _gdm_session_session_opened (GDM_SESSION (session_relay), service_name); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ ++static DBusHandlerResult ++handle_session_open_failed (GdmSessionRelay *session_relay, ++ DBusConnection *connection, ++ DBusMessage *message) ++{ ++ DBusMessage *reply; ++ DBusError error; ++ char *service_name; ++ ++ dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); ++ ++ g_debug ("GdmSessionRelay: Session Open Failed"); ++ ++ reply = dbus_message_new_method_return (message); ++ dbus_connection_send (connection, reply, NULL); ++ dbus_message_unref (reply); ++ ++ _gdm_session_session_open_failed (GDM_SESSION (session_relay), service_name, NULL); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} + + static DBusHandlerResult + handle_session_started (GdmSessionRelay *session_relay, +@@ -794,6 +857,10 @@ session_handle_child_message (DBusConnection *connection, + return handle_accredited (session_relay, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "AccreditationFailed")) { + return handle_accreditation_failed (session_relay, connection, message); ++ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionOpened")) { ++ return handle_session_opened (session_relay, connection, message); ++ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionOpenFailed")) { ++ return handle_session_open_failed (session_relay, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStarted")) { + return handle_session_started (session_relay, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStopped")) { +@@ -1193,6 +1260,7 @@ gdm_session_iface_init (GdmSessionIface *iface) + iface->authenticate = gdm_session_relay_authenticate; + iface->authorize = gdm_session_relay_authorize; + iface->accredit = gdm_session_relay_accredit; ++ iface->open_session = gdm_session_relay_open_session; + iface->close = gdm_session_relay_close; + + iface->cancel = gdm_session_relay_cancel; +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index bcd4f93..867ce67 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -2442,13 +2442,13 @@ do_open_session (GdmSessionWorker *worker) + res = gdm_session_worker_open_user_session (worker, &error); + if (! res) { + send_dbus_string_method (worker->priv->connection, +- "StartFailed", ++ "OpenFailed", + error->message); + g_error_free (error); + return; + } + +- queue_state_change (worker); ++ send_dbus_void_method (worker->priv->connection, "SessionOpened"); + } + + static void +@@ -2564,7 +2564,7 @@ on_start_program (GdmSessionWorker *worker, + const char *text; + dbus_bool_t res; + +- if (worker->priv->state != GDM_SESSION_WORKER_STATE_ACCREDITED) { ++ if (worker->priv->state != GDM_SESSION_WORKER_STATE_SESSION_OPENED) { + g_debug ("GdmSessionWorker: ignoring spurious start program while in state %s", get_state_name (worker->priv->state)); + return; + } +@@ -2723,6 +2723,14 @@ on_establish_credentials (GdmSessionWorker *worker, + } + + static void ++on_open_session (GdmSessionWorker *worker, ++ DBusMessage *message) ++{ ++ /* FIXME: return error if not in ACCREDITED state */ ++ queue_state_change (worker); ++} ++ ++static void + on_reauthenticate (GdmSessionWorker *worker, + DBusMessage *message) + { +@@ -2794,6 +2802,8 @@ worker_dbus_handle_message (DBusConnection *connection, + on_authorize (worker, message); + } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "EstablishCredentials")) { + on_establish_credentials (worker, message); ++ } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "OpenSession")) { ++ on_open_session (worker, message); + } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "StartProgram")) { + on_start_program (worker, message); + } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "Reauthenticate")) { +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 9ee34af..8858071 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -46,6 +46,8 @@ enum { + PROBLEM, + INFO_QUERY, + SECRET_INFO_QUERY, ++ SESSION_OPENED, ++ SESSION_OPEN_FAILED, + SESSION_STARTED, + SESSION_START_FAILED, + SESSION_EXITED, +@@ -207,6 +209,15 @@ gdm_session_cancel (GdmSession *session) + } + + void ++gdm_session_open_session (GdmSession *session, ++ const char *service_name) ++{ ++ g_return_if_fail (GDM_IS_SESSION (session)); ++ ++ GDM_SESSION_GET_IFACE (session)->open_session (session, service_name); ++} ++ ++void + gdm_session_start_session (GdmSession *session, + const char *service_name) + { +@@ -391,6 +402,28 @@ gdm_session_class_init (gpointer g_iface) + G_TYPE_NONE, + 2, + G_TYPE_STRING, G_TYPE_STRING); ++ signals [SESSION_OPENED] = ++ g_signal_new ("session-opened", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmSessionIface, session_opened), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, ++ 1, ++ G_TYPE_STRING); ++ signals [SESSION_OPEN_FAILED] = ++ g_signal_new ("session-open-failed", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmSessionIface, session_open_failed), ++ NULL, ++ NULL, ++ gdm_marshal_VOID__STRING_STRING, ++ G_TYPE_NONE, ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [SESSION_STARTED] = + g_signal_new ("session-started", + iface_type, +@@ -616,6 +649,23 @@ _gdm_session_problem (GdmSession *session, + } + + void ++_gdm_session_session_opened (GdmSession *session, ++ const char *service_name) ++{ ++ g_return_if_fail (GDM_IS_SESSION (session)); ++ g_signal_emit (session, signals [SESSION_OPENED], 0, service_name); ++} ++ ++void ++_gdm_session_session_open_failed (GdmSession *session, ++ const char *service_name, ++ const char *text) ++{ ++ g_return_if_fail (GDM_IS_SESSION (session)); ++ g_signal_emit (session, signals [SESSION_OPEN_FAILED], 0, service_name, text); ++} ++ ++void + _gdm_session_session_started (GdmSession *session, + const char *service_name, + int pid) +diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h +index c45a770..22c2ccb 100644 +--- a/daemon/gdm-session.h ++++ b/daemon/gdm-session.h +@@ -62,6 +62,8 @@ struct _GdmSessionIface + void (* accredit) (GdmSession *session, + const char *service_name, + int cred_flag); ++ void (* open_session) (GdmSession *session, ++ const char *service_name); + void (* answer_query) (GdmSession *session, + const char *service_name, + const char *text); +@@ -115,6 +117,11 @@ struct _GdmSessionIface + void (* problem) (GdmSession *session, + const char *service_name, + const char *problem); ++ void (* session_opened) (GdmSession *session, ++ const char *service_name); ++ void (* session_open_failed) (GdmSession *session, ++ const char *service_name, ++ const char *message); + void (* session_started) (GdmSession *session, + const char *service_name, + int pid); +@@ -160,6 +167,8 @@ void gdm_session_authorize (GdmSession *session, + void gdm_session_accredit (GdmSession *session, + const char *service_name, + int cred_flag); ++void gdm_session_open_session (GdmSession *session, ++ const char *service_name); + void gdm_session_start_session (GdmSession *session, + const char *service_name); + void gdm_session_close (GdmSession *session); +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index 6eadf62..4c68974 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -423,7 +423,7 @@ on_session_accredited (GdmSession *session, + const char *service_name, + GdmSimpleSlave *slave) + { +- queue_start_session (slave, service_name); ++ gdm_session_open_session (session, service_name); + } + + static void +@@ -463,6 +463,29 @@ on_session_accreditation_failed (GdmSession *session, + } + + static void ++on_session_opened (GdmSession *session, ++ const char *service_name, ++ GdmSimpleSlave *slave) ++{ ++ queue_start_session (slave, service_name); ++} ++ ++static void ++on_session_open_failed (GdmSession *session, ++ const char *service_name, ++ const char *message, ++ GdmSimpleSlave *slave) ++{ ++ if (slave->priv->greeter_server != NULL) { ++ gdm_greeter_server_problem (slave->priv->greeter_server, ++ service_name, ++ _("Unable to open session")); ++ } ++ ++ gdm_session_stop_conversation (session, service_name); ++} ++ ++static void + on_session_info (GdmSession *session, + const char *service_name, + const char *text, +@@ -694,6 +717,14 @@ create_new_session (GdmSimpleSlave *slave) + G_CALLBACK (on_session_accreditation_failed), + slave); + g_signal_connect (slave->priv->session, ++ "session-opened", ++ G_CALLBACK (on_session_opened), ++ slave); ++ g_signal_connect (slave->priv->session, ++ "session-open-failed", ++ G_CALLBACK (on_session_open_failed), ++ slave); ++ g_signal_connect (slave->priv->session, + "info", + G_CALLBACK (on_session_info), + slave); +-- +1.6.5.1 + + +From a380ce9c46f25183c8bc2c36d3d7d923fb34d4f5 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 30 Jan 2009 23:57:31 -0500 +Subject: [PATCH 42/81] 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 | 91 +++++++++-- + 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 | 198 +++++++++++++++++++++ + gui/simple-greeter/gdm-task-list.h | 64 +++++++ + 7 files changed, 409 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 519e652..fc2d4b3 100644 +--- a/gui/simple-greeter/Makefile.am ++++ b/gui/simple-greeter/Makefile.am +@@ -85,6 +85,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) + + 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) + + 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 8de74df..9c847f0 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -51,12 +51,16 @@ + #include + #include + ++#include "gdm-marshal.h" ++ + #include "gdm-settings-client.h" + #include "gdm-settings-keys.h" + #include "gdm-profile.h" + ++#include "gdm-greeter-client.h" + #include "gdm-greeter-login-window.h" + #include "gdm-user-chooser-widget.h" ++#include "gdm-task-list.h" + + #ifdef HAVE_PAM + #include +@@ -99,6 +103,7 @@ struct GdmGreeterLoginWindowPrivate + { + GladeXML *xml; + GtkWidget *user_chooser; ++ GtkWidget *conversation_list; + GtkWidget *auth_banner_label; + guint display_is_local : 1; + guint is_interactive : 1; +@@ -126,6 +131,7 @@ enum { + }; + + enum { ++ START_CONVERSATION, + BEGIN_AUTO_LOGIN, + BEGIN_VERIFICATION, + BEGIN_VERIFICATION_FOR_USER, +@@ -355,7 +361,7 @@ on_login_button_clicked_answer_query (GtkButton *button, + 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); ++ g_signal_emit (login_window, signals[QUERY_ANSWER], 0, "gdm", text); + } + + static void +@@ -602,26 +608,32 @@ gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window) + + 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); + + 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 (GDM_TASK_LIST (login_window->priv->conversation_list))) == 0) { ++ set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text); ++ } + + 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); + + 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 (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); + + return TRUE; +@@ -697,6 +709,7 @@ gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_ + + gboolean + gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text) + { + GtkWidget *entry; +@@ -704,6 +717,10 @@ 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 (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"); +@@ -726,6 +743,7 @@ gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, + + gboolean + gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, ++ const char *service_name, + const char *text) + { + GtkWidget *entry; +@@ -858,7 +876,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) { +@@ -872,7 +893,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; ++ ++ 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); + } + + switch_mode (login_window, MODE_AUTHENTICATION); +@@ -1035,6 +1059,21 @@ create_computer_info (GdmGreeterLoginWindow *login_window) + #define INVISIBLE_CHAR_BULLET 0x2022 + #define INVISIBLE_CHAR_NONE 0 + ++static void ++on_task_activated (GdmGreeterLoginWindow *login_window, ++ const char *name) ++{ ++ g_debug ("GdmGreeterLoginWindow: starting conversation with '%s'", name); ++ g_signal_emit (login_window, signals[START_CONVERSATION], 0, name); ++} ++ ++static void ++on_task_deactivated (GdmGreeterLoginWindow *login_window, ++ const char *name) ++{ ++ g_debug ("GdmGreeterLoginWindow: conversation '%s' now in background", name); ++} ++ + static GtkWidget * + custom_widget_constructor (GladeXML *xml, + char *func_name, +@@ -1057,6 +1096,8 @@ custom_widget_constructor (GladeXML *xml, + + 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); +@@ -1135,6 +1176,25 @@ load_theme (GdmGreeterLoginWindow *login_window) + + gtk_widget_show (login_window->priv->user_chooser); + ++ login_window->priv->conversation_list = glade_xml_get_widget (login_window->priv->xml, ++ "conversation-list"); ++ g_signal_connect_swapped (GDM_TASK_LIST (login_window->priv->conversation_list), ++ "activated", ++ G_CALLBACK (on_task_activated), ++ login_window); ++ g_signal_connect_swapped (GDM_TASK_LIST (login_window->priv->conversation_list), ++ "deactivated", ++ G_CALLBACK (on_task_deactivated), ++ 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);*/ + +@@ -1305,6 +1365,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", ++ G_TYPE_FROM_CLASS (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, start_conversation), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, 1, G_TYPE_STRING); + signals [BEGIN_AUTO_LOGIN] = + g_signal_new ("begin-auto-login", + G_TYPE_FROM_CLASS (object_class), +@@ -1321,9 +1390,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) + G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, begin_verification), + NULL, + NULL, +- g_cclosure_marshal_VOID__VOID, ++ g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, +- 0); ++ 1, G_TYPE_STRING); + signals [BEGIN_VERIFICATION_FOR_USER] = + g_signal_new ("begin-verification-for-user", + G_TYPE_FROM_CLASS (object_class), +@@ -1331,9 +1400,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) + G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, 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_TYPE_FROM_CLASS (object_class), +@@ -1341,9 +1410,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) + G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, 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 [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 7c6e94b..e06c091 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.glade ++++ b/gui/simple-greeter/gdm-greeter-login-window.glade +@@ -460,11 +460,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 +@@ -584,10 +611,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 e856dd4..945e210 100644 +--- a/gui/simple-greeter/gdm-greeter-session.c ++++ b/gui/simple-greeter/gdm-greeter-session.c +@@ -71,7 +71,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 +@@ -82,7 +82,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 +@@ -181,7 +181,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 +@@ -192,10 +192,18 @@ on_secret_info_query (GdmGreeterClient *client, + { + 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 ++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) +@@ -206,29 +214,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); + } + +@@ -392,7 +403,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..e0fd3d4 +--- /dev/null ++++ b/gui/simple-greeter/gdm-task-list.c +@@ -0,0 +1,198 @@ ++/* ++ * 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 ++ ++#include "gdm-task-list.h" ++ ++#define GDM_TASK_LIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_TASK_LIST, GdmTaskListPrivate)) ++ ++typedef struct ++{ ++ GtkWidget *radio_button; ++ char *name; ++} GdmTask; ++ ++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 *radio_button) ++{ ++ GdmTask *task; ++ ++ task = g_object_get_data (G_OBJECT (radio_button), "gdm-task"); ++ ++ 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); ++ } ++} ++ ++void ++gdm_task_list_add_task (GdmTaskList *task_list, ++ const char *name, ++ const char *icon_name) ++{ ++ GdmTask *task; ++ GtkWidget *image; ++ ++ task = g_new0 (GdmTask, 1); ++ ++ 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)); ++ } ++ ++ 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 (task_list->priv->box), task->radio_button); ++ task_list->priv->tasks = g_list_append (task_list->priv->tasks, task); ++} ++ ++static void ++gdm_task_list_class_init (GdmTaskListClass *klass) ++{ ++ 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); ++ ++ 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); ++ ++ g_type_class_add_private (klass, sizeof (GdmTaskListPrivate)); ++} ++ ++static void ++gdm_task_list_init (GdmTaskList *widget) ++{ ++ 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); ++ ++ widget->priv->box = gtk_hbox_new (FALSE, 2); ++ gtk_widget_show (widget->priv->box); ++ gtk_container_add (GTK_CONTAINER (widget), ++ widget->priv->box); ++} ++ ++static void ++gdm_task_list_finalize (GObject *object) ++{ ++ GdmTaskList *widget; ++ ++ g_return_if_fail (object != NULL); ++ g_return_if_fail (GDM_IS_TASK_LIST (object)); ++ ++ widget = GDM_TASK_LIST (object); ++ ++ g_list_foreach (widget->priv->tasks, (GFunc) g_free, NULL); ++ g_list_free (widget->priv->tasks); ++ ++ G_OBJECT_CLASS (gdm_task_list_parent_class)->finalize (object); ++} ++ ++GtkWidget * ++gdm_task_list_new (void) ++{ ++ GObject *object; ++ ++ object = g_object_new (GDM_TYPE_TASK_LIST, NULL); ++ ++ return GTK_WIDGET (object); ++} ++ ++const char * ++gdm_task_list_get_active_task (GdmTaskList *widget) ++{ ++ GList *node; ++ ++ for (node = widget->priv->tasks; node != NULL; node = node->next) { ++ GdmTask *task; ++ ++ task = node->data; ++ ++ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (task->radio_button)) ) { ++ return task->name; ++ } ++ } ++ ++ return NULL; ++} +diff --git a/gui/simple-greeter/gdm-task-list.h b/gui/simple-greeter/gdm-task-list.h +new file mode 100644 +index 0000000..ade21b6 +--- /dev/null ++++ b/gui/simple-greeter/gdm-task-list.h +@@ -0,0 +1,64 @@ ++/* ++ * 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 ++ ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#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)) ++ ++typedef struct GdmTaskListPrivate GdmTaskListPrivate; ++ ++typedef struct ++{ ++ GtkAlignment parent; ++ GdmTaskListPrivate *priv; ++} GdmTaskList; ++ ++typedef struct ++{ ++ GtkAlignmentClass parent_class; ++ ++ void (* deactivated) (GdmTaskList *widget, ++ const char *name); ++ void (* activated) (GdmTaskList *widget, ++ const char *name); ++} GdmTaskListClass; ++ ++ ++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 ++ ++#endif /* __GDM_TASK_LIST_H */ +-- +1.6.5.1 + + +From 7b611192c2aa9ef30b19e622e9ca525a7c343dc1 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 6 Mar 2009 11:19:40 -0500 +Subject: [PATCH 43/81] Create session settings object when first starting worker + +This is because one PAM module may complete before setup +gets called on another, and when one completes *all* PAM +modules get told about language, session, and layouts +set by the user. +--- + daemon/gdm-session-worker.c | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index 867ce67..9a9f364 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -2305,8 +2305,6 @@ do_setup (GdmSessionWorker *worker) + GError *error; + gboolean res; + +- worker->priv->user_settings = gdm_session_settings_new (); +- + g_signal_connect_swapped (worker->priv->user_settings, + "notify::language-name", + G_CALLBACK (on_saved_language_name_read), +@@ -2955,6 +2953,7 @@ gdm_session_worker_init (GdmSessionWorker *worker) + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); ++ worker->priv->user_settings = gdm_session_settings_new (); + } + + static void +-- +1.6.5.1 + + +From f908d03d5515fac5c7700e49d20a3f69c159d8fe Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 5 Feb 2009 15:20:25 -0500 +Subject: [PATCH 44/81] 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 4c68974..337718b 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -818,6 +818,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); + } +@@ -828,6 +831,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); + } +@@ -838,6 +844,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); +@@ -850,6 +859,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); +@@ -861,6 +873,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); + } + +@@ -869,6 +884,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); + } + +@@ -877,6 +895,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); + } + +@@ -885,6 +906,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); + } + +@@ -901,7 +925,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 +@@ -911,6 +939,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, +@@ -928,6 +959,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) { +@@ -941,6 +975,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.5.1 + + +From 775a32d565721e926312f23138b82e924233a900 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 6 Feb 2009 16:23:48 -0500 +Subject: [PATCH 45/81] 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 | 45 ++ + gui/simple-greeter/Makefile.am | 15 + + gui/simple-greeter/gdm-greeter-client.c | 21 + + gui/simple-greeter/gdm-greeter-client.h | 2 + + gui/simple-greeter/gdm-greeter-login-window.c | 675 ++++++++++++++++---- + gui/simple-greeter/gdm-greeter-login-window.glade | 144 +---- + gui/simple-greeter/gdm-greeter-login-window.h | 21 +- + gui/simple-greeter/gdm-greeter-plugin.c | 255 ++++++++ + gui/simple-greeter/gdm-greeter-plugin.h | 61 ++ + gui/simple-greeter/gdm-greeter-session.c | 91 +++- + gui/simple-greeter/gdm-plugin-manager.c | 478 ++++++++++++++ + gui/simple-greeter/gdm-plugin-manager.h | 66 ++ + gui/simple-greeter/gdm-task-list.c | 216 +++++-- + gui/simple-greeter/gdm-task-list.h | 36 +- + 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 | 53 ++ + .../plugins/password/gdm-password-extension.c | 314 +++++++++ + .../plugins/password/gdm-password-extension.h | 56 ++ + .../plugins/password/gdm-password.pam | 19 + + gui/simple-greeter/plugins/password/page.ui | 56 ++ + gui/simple-greeter/plugins/password/plugin.c | 40 ++ + po/POTFILES.in | 1 + + 30 files changed, 2986 insertions(+), 298 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/gdm-password.pam + 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 4fe4430..aa8a620 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) +@@ -195,6 +211,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 --------------------------------------------------------------------------- + +@@ -1237,6 +1262,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 --------------------------------------------------------------------------- + +@@ -1363,6 +1404,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/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am +index fc2d4b3..5056956 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)"\" \ +@@ -20,6 +23,7 @@ AM_CPPFLAGS = \ + -DAT_SPI_REGISTRYD_DIR="\"$(AT_SPI_REGISTRYD_DIR)\"" \ + $(DEVKIT_POWER_CFLAGS) \ + -DI_KNOW_THE_DEVICEKIT_POWER_API_IS_SUBJECT_TO_CHANGE \ ++ -DGDM_SIMPLE_GREETER_PLUGINS_DIR="\"$(GDM_SIMPLE_GREETER_PLUGINS_DIR)\""\ + $(DISABLE_DEPRECATED_CFLAGS) \ + $(GTK_CFLAGS) \ + $(SIMPLE_GREETER_CFLAGS) \ +@@ -87,10 +91,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) \ +@@ -141,6 +150,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-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) ++{ ++ emit_string_signal_for_message (client, "ConversationStopped", message, CONVERSATION_STOPPED); ++} ++ ++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); ++ + 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 9c847f0..af8ff82 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 -*- * @@ -6023,42 +8546,15 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm */ #include "config.h" -@@ -56,12 +59,16 @@ - #include - #include - -+#include "gdm-marshal.h" -+ - #include "gdm-settings-client.h" - #include "gdm-settings-keys.h" - #include "gdm-profile.h" - -+#include "gdm-greeter-client.h" - #include "gdm-greeter-login-window.h" - #include "gdm-user-chooser-widget.h" -+#include "gdm-task-list.h" - - #ifdef HAVE_PAM - #include -@@ -109,7 +116,9 @@ struct GdmGreeterLoginWindowPrivate - { - GladeXML *xml; +@@ -105,6 +108,7 @@ struct GdmGreeterLoginWindowPrivate GtkWidget *user_chooser; -+ GtkWidget *conversation_list; + GtkWidget *conversation_list; GtkWidget *auth_banner_label; + GtkWidget *auth_page_box; guint display_is_local : 1; guint is_interactive : 1; guint user_chooser_loaded : 1; -@@ -138,6 +147,7 @@ enum { - }; - - enum { -+ START_CONVERSATION, - BEGIN_AUTO_LOGIN, - BEGIN_VERIFICATION, - BEGIN_VERIFICATION_FOR_USER, -@@ -162,6 +172,8 @@ static void on_user_unchosen +@@ -156,6 +160,8 @@ static void on_user_unchosen (GdmUserChooserWidget *user_chooser, static void switch_mode (GdmGreeterLoginWindow *login_window, int number); static void update_banner_message (GdmGreeterLoginWindow *login_window); @@ -6067,7 +8563,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm G_DEFINE_TYPE (GdmGreeterLoginWindow, gdm_greeter_login_window, GTK_TYPE_WINDOW) -@@ -187,9 +199,6 @@ set_sensitive (GdmGreeterLoginWindow *lo +@@ -181,9 +187,6 @@ set_sensitive (GdmGreeterLoginWindow *login_window, { GtkWidget *box; @@ -6077,7 +8573,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm box = glade_xml_get_widget (login_window->priv->xml, "buttonbox"); gtk_widget_set_sensitive (box, sensitive); -@@ -199,27 +208,43 @@ set_sensitive (GdmGreeterLoginWindow *lo +@@ -193,27 +196,43 @@ set_sensitive (GdmGreeterLoginWindow *login_window, static void set_focus (GdmGreeterLoginWindow *login_window) { @@ -6129,7 +8625,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm } static void -@@ -385,30 +410,76 @@ get_show_restart_buttons (GdmGreeterLogi +@@ -348,30 +367,76 @@ sensitize_widget (GdmGreeterLoginWindow *login_window, } static void @@ -6148,7 +8644,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm - 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); +- g_signal_emit (login_window, signals[QUERY_ANSWER], 0, "gdm", text); } static void @@ -6159,8 +8655,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm - 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) { @@ -6202,7 +8697,8 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + break; + } + } -+ + +- _gdm_greeter_login_window_set_interactive (login_window, TRUE); +} + +static void @@ -6220,7 +8716,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm } static void on_login_button_clicked_start_other (GtkButton *button, -@@ -427,6 +498,7 @@ set_log_in_button_mode (GdmGreeterLoginW +@@ -390,6 +455,7 @@ set_log_in_button_mode (GdmGreeterLoginWindow *login_window, int mode) { GtkWidget *button; @@ -6228,7 +8724,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm button = glade_xml_get_widget (login_window->priv->xml, "log-in-button"); gtk_widget_grab_default (button); -@@ -439,6 +511,12 @@ set_log_in_button_mode (GdmGreeterLoginW +@@ -402,6 +468,12 @@ set_log_in_button_mode (GdmGreeterLoginWindow *login_window, switch (mode) { case LOGIN_BUTTON_HIDDEN: @@ -6241,7 +8737,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm gtk_widget_hide (button); break; case LOGIN_BUTTON_START_OTHER: -@@ -446,11 +524,18 @@ set_log_in_button_mode (GdmGreeterLoginW +@@ -409,11 +481,18 @@ set_log_in_button_mode (GdmGreeterLoginWindow *login_window, gtk_widget_show (button); break; case LOGIN_BUTTON_ANSWER_QUERY: @@ -6262,46 +8758,26 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm gtk_widget_show (button); break; default: -@@ -564,6 +649,7 @@ switch_mode (GdmGreeterLoginWindow *logi - 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); -@@ -592,7 +678,8 @@ switch_mode (GdmGreeterLoginWindow *logi - show_widget (login_window, "disconnect-button", - ! login_window->priv->display_is_local); +@@ -460,8 +539,7 @@ switch_mode (GdmGreeterLoginWindow *login_window, + set_log_in_button_mode (login_window, LOGIN_BUTTON_HIDDEN); + show_widget (login_window, "cancel-button", FALSE); +- - 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); -@@ -603,11 +690,19 @@ switch_mode (GdmGreeterLoginWindow *logi - default_name = NULL; - break; + sensitize_widget (login_window, "disconnect-button", FALSE); + +@@ -470,6 +548,7 @@ switch_mode (GdmGreeterLoginWindow *login_window, case MODE_AUTHENTICATION: -+ gtk_widget_set_size_request (GTK_WIDGET (login_window), -+ GTK_WIDGET (login_window)->allocation.width, -+ -1); show_widget (login_window, "cancel-button", TRUE); - show_widget (login_window, "shutdown-button", FALSE); - 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); -+ -+ 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: -@@ -687,25 +782,54 @@ do_suspend (GdmGreeterLoginWindow *login - g_object_unref (proxy); +@@ -508,25 +587,40 @@ switch_mode (GdmGreeterLoginWindow *login_window, + } } -static void @@ -6310,37 +8786,23 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm +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); -+ -+ return has_service_name; -+} -+ -+GdmTask * -+find_task_with_service_name (GdmGreeterLoginWindow *login_window, -+ const char *service_name) - { -- const char *typed_text; -- char *null_text; -+ GdmTask *task; -+ -+ task = gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), -+ (GdmTaskListForeachFunc) -+ task_has_service_name, -+ (gpointer) 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 task; ++ has_service_name = strcmp (service_name, task_service_name) == 0; ++ g_free (task_service_name); ++ ++ return has_service_name; +} + +static gboolean @@ -6367,18 +8829,18 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm g_debug ("GdmGreeterLoginWindow: Resetting dialog"); set_busy (login_window); set_sensitive (login_window, FALSE); -@@ -729,18 +853,15 @@ reset_dialog (GdmGreeterLoginWindow *log +@@ -550,16 +644,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"); -- -- delete_entry_text (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, ""); - @@ -6387,53 +8849,10 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm - 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)); -@@ -752,21 +873,61 @@ reset_dialog (GdmGreeterLoginWindow *log +@@ -583,11 +673,22 @@ do_cancel (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) -+{ -+ /* 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_ready (GdmGreeterLoginWindow *login_window) +gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, @@ -6444,21 +8863,19 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE); - reset_dialog (login_window); -+ task = find_task_with_service_name (login_window, service_name); ++ 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) { -+ 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); -+ } ++ 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)); -@@ -776,37 +937,122 @@ gdm_greeter_login_window_ready (GdmGreet +@@ -597,12 +698,63 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window) } gboolean @@ -6472,33 +8889,16 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + g_debug ("GdmGreeterLoginWindow: conversation '%s' has stopped", service_name); + -+ /* If the password conversation failed, then start over -+ * -+ * FIXME: we need to get this policy out of the source code -+ */ -+ if (strcmp (service_name, "gdm-password") == 0) { -+ g_debug ("GdmGreeterLoginWindow: main conversation failed, starting over"); -+ restart_conversations (login_window); -+ return TRUE; -+ } -+ -+ task = find_task_with_service_name (login_window, service_name); ++ 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_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; +} + @@ -6540,9 +8940,8 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm return TRUE; } - gboolean - gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window, -+ const char *service_name, +@@ -611,12 +763,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); @@ -6551,21 +8950,22 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + 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 (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; - } - - gboolean - gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, -+ const char *service_name, +@@ -627,13 +787,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); @@ -6574,19 +8974,23 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + 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); -+ task = find_task_with_service_name (login_window, service_name); +- 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; -@@ -844,11 +1090,21 @@ gdm_greeter_login_window_request_timed_l +@@ -671,11 +840,21 @@ gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_windo } static void @@ -6610,7 +9014,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm } else { g_debug ("GdmGreeterLoginWindow: not starting session since " "user hasn't had an opportunity to pick language " -@@ -858,8 +1114,8 @@ gdm_greeter_login_window_start_session_w +@@ -685,8 +864,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", @@ -6621,11 +9025,8 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm /* FIXME: If the user wasn't asked any questions by pam but * pam still authorized them (passwd -d, or the questions got -@@ -882,24 +1138,25 @@ gdm_greeter_login_window_start_session_w - - gboolean - gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, -+ const char *service_name, +@@ -712,26 +891,24 @@ gdm_greeter_login_window_info_query (GdmGreeterLoginWindow *login_window, + const char *service_name, const char *text) { - GtkWidget *entry; @@ -6634,33 +9035,36 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm 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); -+ task = find_task_with_service_name (login_window, service_name); - -- show_widget (login_window, "auth-input-box", TRUE); + 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)); -@@ -911,22 +1168,23 @@ gdm_greeter_login_window_info_query (Gdm - - gboolean - gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, -+ const char *service_name, +@@ -746,20 +923,23 @@ gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, + const char *service_name, const char *text) { - GtkWidget *entry; @@ -6674,7 +9078,10 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm - 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); ++ 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); @@ -6689,7 +9096,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm 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)); -@@ -937,13 +1195,16 @@ gdm_greeter_login_window_secret_info_que +@@ -770,13 +950,16 @@ gdm_greeter_login_window_secret_info_query (GdmGreeterLoginWindow *login_window, } void @@ -6709,7 +9116,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm } static void -@@ -1153,43 +1414,183 @@ on_users_loaded (GdmUserChooserWidget * +@@ -859,6 +1042,46 @@ on_users_loaded (GdmUserChooserWidget *user_chooser, gdm_chooser_widget_activate_if_one_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser)); } @@ -6728,33 +9135,18 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + + return FALSE; +} -+ - static void --on_user_chosen (GdmUserChooserWidget *user_chooser, -- GdmGreeterLoginWindow *login_window) -+begin_verification (GdmGreeterLoginWindow *login_window) -+{ -+ 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 gboolean +begin_task_verification_for_selected_user (GdmTaskList *task_list, + GdmTask *task, + GdmGreeterLoginWindow *login_window) - { - char *user_name; ++{ ++ 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)); -- g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); - - if (user_name == NULL) { -- return; ++ ++ 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; + } + @@ -6762,166 +9154,54 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + 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], + static void + on_user_chosen (GdmUserChooserWidget *user_chooser, + GdmGreeterLoginWindow *login_window) +@@ -876,10 +1099,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); -- } 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); + if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) { +- const char *service_name; - -- login_window->priv->timed_login_enabled = TRUE; -- restart_timed_login_timeout (login_window); +- 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) { +@@ -893,10 +1116,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; - -- /* 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; +- 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); } -+ 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); -+ -+ g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED], -+ 0, 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); -+ } - } +@@ -1061,17 +1284,65 @@ create_computer_info (GdmGreeterLoginWindow *login_window) static void -@@ -1328,6 +1729,69 @@ create_computer_info (GdmGreeterLoginWin - #define INVISIBLE_CHAR_BULLET 0x2022 - #define INVISIBLE_CHAR_NONE 0 - -+static void -+on_task_activated (GdmGreeterLoginWindow *login_window, + 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; + @@ -6951,12 +9231,14 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + + gtk_widget_show (container); + set_log_in_button_mode (login_window, login_window->priv->dialog_mode); -+} -+ -+static void -+on_task_deactivated (GdmGreeterLoginWindow *login_window, + } + + 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; @@ -6979,21 +9261,10 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + gtk_action_group_set_visible (actions, FALSE); + g_object_unref (actions); + } -+} -+ + } + static GtkWidget * - custom_widget_constructor (GladeXML *xml, - char *func_name, -@@ -1350,6 +1814,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); -@@ -1360,7 +1826,6 @@ custom_widget_constructor (GladeXML +@@ -1108,7 +1379,6 @@ custom_widget_constructor (GladeXML *xml, static void load_theme (GdmGreeterLoginWindow *login_window) { @@ -7001,39 +9272,23 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm GtkWidget *button; GtkWidget *box; GtkWidget *image; -@@ -1414,7 +1879,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", -@@ -1428,8 +1893,20 @@ load_theme (GdmGreeterLoginWindow *login +@@ -1188,27 +1458,13 @@ load_theme (GdmGreeterLoginWindow *login_window) + login_window); + gtk_widget_show (login_window->priv->conversation_list); - gtk_widget_show (login_window->priv->user_chooser); - -+ login_window->priv->conversation_list = glade_xml_get_widget (login_window->priv->xml, -+ "conversation-list"); -+ g_signal_connect_swapped (GDM_TASK_LIST (login_window->priv->conversation_list), -+ "activated", -+ G_CALLBACK (on_task_activated), -+ login_window); -+ g_signal_connect_swapped (GDM_TASK_LIST (login_window->priv->conversation_list), -+ "deactivated", -+ G_CALLBACK (on_task_deactivated), -+ login_window); -+ +- 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); -@@ -1445,14 +1922,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); + button = glade_xml_get_widget (login_window->priv->xml, "cancel-button"); + g_signal_connect (button, "clicked", G_CALLBACK (cancel_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 */ @@ -7046,59 +9301,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm create_computer_info (login_window); box = glade_xml_get_widget (login_window->priv->xml, "computer-info-event-box"); -@@ -1609,6 +2078,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), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__STRING, -+ G_TYPE_NONE, 1, G_TYPE_STRING); - signals [BEGIN_AUTO_LOGIN] = - g_signal_new ("begin-auto-login", - G_TYPE_FROM_CLASS (object_class), -@@ -1625,9 +2103,9 @@ gdm_greeter_login_window_class_init (Gdm - G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, begin_verification), - NULL, - NULL, -- g_cclosure_marshal_VOID__VOID, -+ g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, -- 0); -+ 1, G_TYPE_STRING); - signals [BEGIN_VERIFICATION_FOR_USER] = - g_signal_new ("begin-verification-for-user", - G_TYPE_FROM_CLASS (object_class), -@@ -1635,9 +2113,9 @@ gdm_greeter_login_window_class_init (Gdm - G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, 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_TYPE_FROM_CLASS (object_class), -@@ -1645,9 +2123,9 @@ gdm_greeter_login_window_class_init (Gdm - G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, 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 [USER_SELECTED] = - g_signal_new ("user-selected", - G_TYPE_FROM_CLASS (object_class), -@@ -1685,9 +2163,9 @@ gdm_greeter_login_window_class_init (Gdm +@@ -1450,9 +1706,9 @@ gdm_greeter_login_window_class_init (GdmGreeterLoginWindowClass *klass) G_STRUCT_OFFSET (GdmGreeterLoginWindowClass, start_session), NULL, NULL, @@ -7110,7 +9313,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm g_object_class_install_property (object_class, PROP_DISPLAY_IS_LOCAL, -@@ -1740,6 +2218,232 @@ on_gconf_key_changed (GConfClient +@@ -1505,6 +1761,187 @@ on_gconf_key_changed (GConfClient *client, } } @@ -7133,42 +9336,6 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + set_ready (login_window); +} + -+static void -+on_conversation_cancel (GdmGreeterLoginWindow *login_window, -+ GdmConversation *conversation) -+{ -+ do_cancel (login_window); -+} -+ -+static gboolean -+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; -+ -+ 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; -+ } -+ -+ /* 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), -+ GDM_TASK (conversation))) { -+ gdm_user_chooser_widget_set_chosen_user_name (GDM_USER_CHOOSER_WIDGET (login_window->priv->user_chooser), -+ username); -+ } -+ -+ return TRUE; -+} -+ +void +gdm_greeter_login_window_remove_extension (GdmGreeterLoginWindow *login_window, + GdmGreeterExtension *extension) @@ -7306,14 +9473,6 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + "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)); @@ -7321,20 +9480,19 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm + 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)); -+ -+ 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_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); @@ -7343,10 +9501,11 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.c.multistack gdm static gboolean on_window_state_event (GtkWidget *widget, GdkEventWindowState *event, -diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade.multistack gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade ---- gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade 2009-09-23 18:46:06.730661253 -0400 -@@ -611,30 +611,29 @@ +diff --git a/gui/simple-greeter/gdm-greeter-login-window.glade b/gui/simple-greeter/gdm-greeter-login-window.glade +index e06c091..d221d78 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.glade ++++ b/gui/simple-greeter/gdm-greeter-login-window.glade +@@ -417,30 +417,29 @@ @@ -7399,15 +9558,31 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade.multistack True -@@ -654,42 +653,17 @@ - 10 +@@ -466,20 +465,6 @@ + 0 - -- -- True -- 0 -- 0 -- Tue, 18 Nov 2008 21:55:38 GMT + +- +- True +- 0 +- 0 +- Tue, 18 Nov 2008 21:55:38 GMT +- +- +- 0 +- True +- True +- +- +- +- + + True + 0 +@@ -492,56 +477,12 @@ + False + + - - - 0 @@ -7418,16 +9593,13 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade.multistack - - - -+ - True - False +- True +- False - 6 -+ 0 - - +- +- - -+ - True +- True - - False - False @@ -7442,14 +9614,13 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade.multistack - -1 - False - 0 -+ 0 -+ 0 -+ Fri, 30 Jan 2009 16:03:30 GMT - - - 0 -@@ -699,16 +673,10 @@ - +- +- +- 0 +- False +- False +- +- - @@ -7469,7 +9640,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade.multistack 0 -@@ -717,46 +685,21 @@ +@@ -550,46 +491,21 @@ @@ -7520,20 +9691,10 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.glade.multistack -@@ -778,10 +721,6 @@ - - - -- -- -- -- - - - -diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.h.multistack gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.h ---- gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.h.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.h 2009-09-23 18:46:06.731651392 -0400 +diff --git a/gui/simple-greeter/gdm-greeter-login-window.h b/gui/simple-greeter/gdm-greeter-login-window.h +index 559b26b..c312a47 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 @@ -7553,24 +9714,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.h.multistack gdm typedef struct GdmGreeterLoginWindowPrivate GdmGreeterLoginWindowPrivate; typedef struct -@@ -46,18 +51,24 @@ 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, +@@ -62,7 +67,8 @@ typedef struct const char *text); void (* cancelled) (GdmGreeterLoginWindow *login_window); void (* disconnected) (GdmGreeterLoginWindow *login_window); @@ -7580,7 +9724,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.h.multistack gdm } GdmGreeterLoginWindowClass; -@@ -66,20 +77,33 @@ GtkWidget * gdm_greeter_login_wi +@@ -71,7 +77,10 @@ GtkWidget * gdm_greeter_login_window_new (gboolean displa gboolean gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window); @@ -7590,18 +9734,9 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.h.multistack gdm +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 *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); - +@@ -88,7 +97,13 @@ gboolean gdm_greeter_login_window_problem (GdmGreeterLogin void gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, const char *username, int delay); @@ -7616,9 +9751,11 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-login-window.h.multistack gdm G_END_DECLS -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-greeter-plugin.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-greeter-plugin.c 2009-09-23 18:46:06.732650193 -0400 +diff --git a/gui/simple-greeter/gdm-greeter-plugin.c b/gui/simple-greeter/gdm-greeter-plugin.c +new file mode 100644 +index 0000000..02814a2 +--- /dev/null ++++ b/gui/simple-greeter/gdm-greeter-plugin.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. @@ -7875,9 +10012,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-greeter-plugin.c + gdm_greeter_plugin_unload (plugin); +} + -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-greeter-plugin.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-greeter-plugin.h 2009-09-23 18:46:06.734650587 -0400 +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. @@ -7940,9 +10079,10 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-greeter-plugin.h +G_END_DECLS + +#endif -diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c.multistack gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c ---- gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c 2009-09-23 18:46:06.735651133 -0400 +diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c +index 945e210..848ea1e 100644 +--- a/gui/simple-greeter/gdm-greeter-session.c ++++ b/gui/simple-greeter/gdm-greeter-session.c @@ -39,6 +39,8 @@ #include "gdm-greeter-login-window.h" #include "gdm-user-chooser-widget.h" @@ -7964,36 +10104,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c.multistack gdm-2.28 }; enum { -@@ -65,31 +69,46 @@ static gpointer session_object = NULL; - - static void - on_info (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) - { - 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 - 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) +@@ -92,7 +96,19 @@ on_ready (GdmGreeterClient *client, { g_debug ("GdmGreeterSession: Ready"); @@ -8014,7 +10125,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c.multistack gdm-2.28 } static void -@@ -164,33 +183,44 @@ on_timed_login_requested (GdmGreeterClie +@@ -167,10 +183,11 @@ on_timed_login_requested (GdmGreeterClient *client, static void on_user_authorized (GdmGreeterClient *client, @@ -8027,100 +10138,36 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c.multistack gdm-2.28 } static void - on_info_query (GdmGreeterClient *client, -+ const char *service_name, - const char *text, - GdmGreeterSession *session) +@@ -289,7 +306,6 @@ on_cancelled (GdmGreeterLoginWindow *login_window, { - 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); + 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 - 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 -+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) -@@ -201,26 +231,32 @@ on_begin_auto_login (GdmGreeterLoginWind - - static void - on_begin_verification (GdmGreeterLoginWindow *login_window, -+ const char *service_name, - GdmGreeterSession *session) - { -- gdm_greeter_client_call_begin_verification (session->priv->client); -+ gdm_greeter_client_call_begin_verification (session->priv->client, -+ 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, -+ 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, -+ service_name, - text); - } - -@@ -281,9 +317,10 @@ on_disconnected (GdmGreeterLoginWindow * +@@ -301,9 +317,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, TRUE); +- 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 int -@@ -381,7 +418,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); +@@ -462,8 +479,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"); - -+ 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), -@@ -546,6 +586,64 @@ gdm_greeter_session_event_handler (GdkEv + gdm_profile_end (NULL); + + return res; +@@ -573,6 +588,64 @@ gdm_greeter_session_event_handler (GdkEvent *event, } static void @@ -8185,7 +10232,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c.multistack gdm-2.28 gdm_greeter_session_init (GdmGreeterSession *session) { gdm_profile_start (NULL); -@@ -574,6 +672,10 @@ gdm_greeter_session_init (GdmGreeterSess +@@ -601,6 +674,10 @@ gdm_greeter_session_init (GdmGreeterSession *session) G_CALLBACK (on_ready), session); g_signal_connect (session->priv->client, @@ -8196,7 +10243,7 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c.multistack gdm-2.28 "reset", G_CALLBACK (on_reset), session); -@@ -608,6 +710,8 @@ gdm_greeter_session_init (GdmGreeterSess +@@ -635,6 +712,8 @@ gdm_greeter_session_init (GdmGreeterSession *session) gdk_event_handler_set ((GdkEventFunc) gdm_greeter_session_event_handler, session, NULL); @@ -8205,9 +10252,11 @@ diff -up gdm-2.28.0/gui/simple-greeter/gdm-greeter-session.c.multistack gdm-2.28 gdm_profile_end (NULL); } -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-plugin-manager.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-plugin-manager.c 2009-09-23 18:46:06.737661724 -0400 +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. @@ -8687,9 +10736,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-plugin-manager.c +{ + return g_hash_table_lookup (manager->priv->plugins, name); +} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-plugin-manager.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-plugin-manager.h 2009-09-23 18:46:06.739650664 -0400 +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 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. @@ -8757,80 +10808,48 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-plugin-manager.h +G_END_DECLS + +#endif /* __GDM_PLUGIN_MANAGER_H */ -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-task-list.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-task-list.c 2009-09-23 18:46:06.849405831 -0400 -@@ -0,0 +1,329 @@ -+/* -+ * 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 -+ -+#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); +diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c +index e0fd3d4..25831a6 100644 +--- a/gui/simple-greeter/gdm-task-list.c ++++ b/gui/simple-greeter/gdm-task-list.c +@@ -37,12 +37,6 @@ + + #define GDM_TASK_LIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_TASK_LIST, GdmTaskListPrivate)) + +-typedef struct +-{ +- GtkWidget *radio_button; +- char *name; +-} GdmTask; +- + struct GdmTaskListPrivate + { + GtkWidget *box; +@@ -59,54 +53,161 @@ 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); +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, + + G_DEFINE_TYPE (GdmTaskList, gdm_task_list, GTK_TYPE_ALIGNMENT); + + static void + on_task_toggled (GdmTaskList *widget, +- GtkRadioButton *radio_button) + GtkRadioButton *button) -+{ -+ GdmTask *task; -+ + { + GdmTask *task; + +- task = g_object_get_data (G_OBJECT (radio_button), "gdm-task"); + task = g_object_get_data (G_OBJECT (button), "gdm-task"); -+ + +- 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 { + } else { +- g_signal_emit (widget, signals[DEACTIVATED], 0, task->name); + g_signal_emit (widget, signals[DEACTIVATED], 0, task); + } +} @@ -8913,28 +10932,36 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-task-list.c + + if (was_active) { + activate_first_available_task (task_list); -+ } -+} -+ -+void -+gdm_task_list_add_task (GdmTaskList *task_list, + } + } + + void + gdm_task_list_add_task (GdmTaskList *task_list, +- const char *name, +- const char *icon_name) + GdmTask *task) -+{ -+ GtkWidget *image; + { +- GdmTask *task; + GtkWidget *image; + GtkWidget *button; + GIcon *icon; + char *description; -+ -+ if (task_list->priv->tasks == NULL) { + +- 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 { + } 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); @@ -8957,89 +10984,76 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-task-list.c + icon = gdm_task_get_icon (task); + image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_SMALL_TOOLBAR); + g_object_unref (icon); -+ -+ gtk_widget_show (image); + +- 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); -+ + +- 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); + 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 -+gdm_task_list_class_init (GdmTaskListClass *klass) -+{ -+ 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, + } + + static void +@@ -122,9 +223,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, + G_TYPE_NONE, +- 1, G_TYPE_STRING); + 1, G_TYPE_OBJECT); -+ -+ signals [DEACTIVATED] = g_signal_new ("deactivated", -+ G_TYPE_FROM_CLASS (object_class), -+ G_SIGNAL_RUN_FIRST, -+ G_STRUCT_OFFSET (GdmTaskListClass, deactivated), -+ NULL, -+ NULL, + + signals [DEACTIVATED] = g_signal_new ("deactivated", + G_TYPE_FROM_CLASS (object_class), +@@ -132,22 +233,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, + G_TYPE_NONE, +- 1, G_TYPE_STRING); + 1, G_TYPE_OBJECT); -+ -+ g_type_class_add_private (klass, sizeof (GdmTaskListPrivate)); + + g_type_class_add_private (klass, sizeof (GdmTaskListPrivate)); +-} +- +-static void +-gdm_task_list_init (GdmTaskList *widget) +} static void gdm_task_list_init (GdmTaskList *widget) -+{ -+ 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); -+ + { + 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); + +- 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); -+} -+ -+static void -+gdm_task_list_finalize (GObject *object) -+{ -+ GdmTaskList *widget; -+ -+ g_return_if_fail (object != NULL); -+ g_return_if_fail (GDM_IS_TASK_LIST (object)); -+ -+ widget = GDM_TASK_LIST (object); -+ -+ g_list_foreach (widget->priv->tasks, (GFunc) g_free, NULL); -+ g_list_free (widget->priv->tasks); -+ -+ G_OBJECT_CLASS (gdm_task_list_parent_class)->finalize (object); -+} -+ -+GtkWidget * -+gdm_task_list_new (void) -+{ -+ GObject *object; -+ -+ object = g_object_new (GDM_TYPE_TASK_LIST, NULL); -+ -+ return GTK_WIDGET (object); -+} -+ + gtk_widget_show (widget->priv->box); + gtk_container_add (GTK_CONTAINER (widget), + widget->priv->box); +@@ -179,20 +277,46 @@ gdm_task_list_new (void) + return GTK_WIDGET (object); + } + +-const char * +gboolean +gdm_task_list_task_is_active (GdmTaskList *task_list, + GdmTask *task) @@ -9052,113 +11066,96 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-task-list.c +} + +GdmTask * -+gdm_task_list_get_active_task (GdmTaskList *widget) -+{ + gdm_task_list_get_active_task (GdmTaskList *widget) + { +- GList *node; + return gdm_task_list_foreach_task (widget, + (GdmTaskListForeachFunc) + gdm_task_list_task_is_active, + NULL); +} -+ + +- for (node = widget->priv->tasks; node != NULL; node = node->next) { +- GdmTask *task; +gboolean +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); -+ + +- task = node->data; + button = GTK_WIDGET (g_object_get_data (G_OBJECT (task), + "gdm-task-list-button")); -+ -+ was_activated = FALSE; + +- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (task->radio_button)) ) { +- return task->name; + if (GTK_WIDGET_IS_SENSITIVE (button)) { + if (gtk_widget_activate (button)) { -+ was_activated = TRUE; -+ } -+ } -+ -+ gtk_widget_set_sensitive (GTK_WIDGET (widget), was_sensitive); -+ return was_activated; ++ return TRUE; + } + } + +- return NULL; ++ return FALSE; +} + +int +gdm_task_list_get_number_of_tasks (GdmTaskList *widget) +{ + return g_list_length (widget->priv->tasks); -+} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-task-list.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-task-list.h 2009-09-23 18:46:06.742650418 -0400 -@@ -0,0 +1,80 @@ -+/* -+ * 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 -+ -+#include + } +diff --git a/gui/simple-greeter/gdm-task-list.h b/gui/simple-greeter/gdm-task-list.h +index ade21b6..8bc0c0e 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 + +#include "gdm-task.h" + -+G_BEGIN_DECLS -+ -+#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)) -+ -+typedef struct GdmTaskListPrivate GdmTaskListPrivate; + G_BEGIN_DECLS + + #define GDM_TYPE_TASK_LIST (gdm_task_list_get_type ()) +@@ -34,31 +37,44 @@ 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); + +struct _GdmTaskList -+{ -+ GtkAlignment parent; -+ GdmTaskListPrivate *priv; + { + GtkAlignment parent; + GdmTaskListPrivate *priv; +-} GdmTaskList; +}; -+ -+typedef struct -+{ -+ GtkAlignmentClass parent_class; -+ -+ void (* deactivated) (GdmTaskList *widget, + + typedef struct + { + GtkAlignmentClass parent_class; + + void (* deactivated) (GdmTaskList *widget, +- const char *name); + GdmTask *task); -+ void (* activated) (GdmTaskList *widget, + void (* activated) (GdmTaskList *widget, +- const char *name); + GdmTask *task); -+} GdmTaskListClass; -+ + } GdmTaskListClass; + +GType gdm_task_list_get_type (void); +GtkWidget * gdm_task_list_new (void); + -+ + +-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); @@ -9169,50 +11166,73 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/gdm-task-list.h + 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 -up gdm-2.28.0/gui/simple-greeter/gdm-user-chooser-widget.c.multistack gdm-2.28.0/gui/simple-greeter/gdm-user-chooser-widget.c ---- gdm-2.28.0/gui/simple-greeter/gdm-user-chooser-widget.c.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/gdm-user-chooser-widget.c 2009-09-23 18:46:06.839395619 -0400 -@@ -267,9 +267,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; -+ - g_return_val_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget), NULL); + G_END_DECLS -- 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; -+ } + #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 = + -+ gdm_chooser_widget_lookup_item (GDM_CHOOSER_WIDGET (widget), active_item_id, -+ NULL, NULL, NULL, NULL, NULL, -+ &isnt_user); ++AM_CPPFLAGS = \ ++ -I. \ ++ -I.. \ ++ -DBINDIR=\"$(bindir)\" \ ++ -DDATADIR=\"$(datadir)\" \ ++ -DLIBDIR=\"$(libdir)\" \ ++ -DLIBEXECDIR=\"$(libexecdir)\" \ ++ -DLOGDIR=\"$(logdir)\" \ ++ -DPIXMAPDIR=\"$(pixmapdir)\" \ ++ -DSBINDIR=\"$(sbindir)\" \ ++ $(GTK_CFLAGS) \ ++ $(NULL) + -+ if (isnt_user) { -+ g_debug ("GdmUserChooserWidget: active item '%s' isn't a user", active_item_id); -+ g_free (active_item_id); -+ return NULL; -+ } ++lib_LTLIBRARIES = \ ++ libgdmsimplegreeter.la \ ++ $(NULL) + -+ g_debug ("GdmUserChooserWidget: active item '%s' is a user", active_item_id); ++libgdmsimplegreeter_la_SOURCES = \ ++ gdm-task.h \ ++ gdm-task.c \ ++ gdm-conversation.h \ ++ gdm-conversation.c \ ++ gdm-greeter-extension.h \ ++ gdm-greeter-extension.c \ ++ $(NULL) + -+ return active_item_id; - } - - void -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.c 2009-09-23 18:46:06.866396190 -0400 -@@ -0,0 +1,186 @@ ++libgdmsimplegreeter_la_LIBADD = \ ++ $(GTK_LIBS) \ ++ $(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 --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 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -9240,13 +11260,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-convers +#include + +#include "gdm-conversation.h" -+#include "gdm-marshal.h" +#include "gdm-task.h" + ++ +enum { + ANSWER, -+ USER_CHOSEN, -+ CANCEL, + LAST_SIGNAL +}; + @@ -9288,25 +11306,6 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-convers + 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); +} + +void @@ -9381,28 +11380,12 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-convers + g_signal_emit (conversation, signals [ANSWER], 0, answer); +} + -+void -+gdm_conversation_cancel (GdmConversation *conversation) -+{ -+ g_signal_emit (conversation, signals [CANCEL], 0); -+} -+ -+gboolean -+gdm_conversation_choose_user (GdmConversation *conversation, -+ const char *username) -+{ -+ gboolean was_chosen; -+ -+ was_chosen = FALSE; -+ -+ g_signal_emit (conversation, signals [USER_CHOSEN], 0, username, &was_chosen); -+ -+ return was_chosen; -+} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-conversation.h 2009-09-23 18:46:06.867400089 -0400 -@@ -0,0 +1,93 @@ +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. + * @@ -9439,7 +11422,6 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-convers +#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; @@ -9465,8 +11447,6 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-convers + + /* signals */ + char * (* answer) (GdmConversation *conversation); -+ void (* cancel) (GdmConversation *conversation); -+ gboolean (* user_chosen) (GdmConversation *conversation); +}; + +GType gdm_conversation_get_type (void) G_GNUC_CONST; @@ -9489,16 +11469,15 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-convers + */ +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.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.c 2009-09-23 18:46:06.748650972 -0400 +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. @@ -9593,9 +11572,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter +{ + g_signal_emit (extension, signals [LOAD_FAILED], 0, error); +} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter-extension.h 2009-09-23 18:46:06.749650540 -0400 +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 @@ +/* + * Copyright 2009 Red Hat, Inc. * @@ -9652,25 +11633,12 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-greeter + +G_END_DECLS +#endif /* __GDM_GREETER_EXTENSION_H */ -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc.in ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdmsimplegreeter.pc.in 2009-09-23 18:46:06.752658465 -0400 -@@ -0,0 +1,11 @@ -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+libdir=@libdir@ -+includedir=@includedir@ -+pluginsdir=@GDM_SIMPLE_GREETER_PLUGINS_DIR@ -+ -+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.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c 2009-09-23 18:46:06.829395324 -0400 -@@ -0,0 +1,123 @@ +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 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -9761,12 +11729,6 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c + 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); -+} -+ +static void +gdm_task_class_init (gpointer g_iface) +{ @@ -9794,10 +11756,12 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c + G_TYPE_NONE, + 0); +} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h 2009-09-23 18:46:06.830395102 -0400 -@@ -0,0 +1,64 @@ +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. + * @@ -9844,7 +11808,6 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h + 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); @@ -9858,562 +11821,43 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h +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 -up /dev/null gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/libgdmsimplegreeter/Makefile.am 2009-09-23 18:46:06.865392711 -0400 -@@ -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.28.0/gui/simple-greeter/Makefile.am.multistack gdm-2.28.0/gui/simple-greeter/Makefile.am ---- gdm-2.28.0/gui/simple-greeter/Makefile.am.multistack 2009-09-21 16:05:27.000000000 -0400 -+++ gdm-2.28.0/gui/simple-greeter/Makefile.am 2009-09-23 18:46:06.719650843 -0400 -@@ -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)"\" \ - -DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \ -+ -DGDM_SIMPLE_GREETER_PLUGINS_DIR="\"$(GDM_SIMPLE_GREETER_PLUGINS_DIR)\""\ - -DAT_SPI_REGISTRYD_DIR="\"$(AT_SPI_REGISTRYD_DIR)\"" \ - $(DISABLE_DEPRECATED_CFLAGS) \ - $(GTK_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) \ -@@ -137,6 +148,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) \ -@@ -307,18 +319,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.28.0/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c 2009-09-23 18:46:06.840395606 -0400 -@@ -0,0 +1,304 @@ -+/* -+ * 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 "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); -+ -+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 (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)); -+ -+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) -+{ -+ 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 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), ""); -+ -+ 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; -+ -+ gdm_task_set_enabled (GDM_TASK (conversation), FALSE); -+} -+ -+static void -+gdm_fingerprint_extension_set_ready (GdmConversation *conversation) -+{ -+ gdm_task_set_enabled (GDM_TASK (conversation), TRUE); -+} -+ -+char * -+gdm_fingerprint_extension_get_service_name (GdmConversation *conversation) -+{ -+ return g_strdup (PAMSERVICENAME); -+} -+ -+GtkWidget * -+gdm_fingerprint_extension_get_page (GdmConversation *conversation) -+{ -+ 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_fingerprint_extension_request_answer (GdmConversation *conversation) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ const char *text; -+ -+ 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) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); -+ -+ if (!extension->priv->answer_pending) { -+ return FALSE; -+ } -+ -+ gtk_widget_grab_focus (extension->priv->prompt_entry); -+ return TRUE; -+} -+ -+GIcon * -+gdm_fingerprint_extension_get_icon (GdmTask *task) -+{ -+ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (task); -+ return g_object_ref (extension->priv->icon); -+} -+ -+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")); -+} -+ -+gboolean -+gdm_fingerprint_extension_is_choosable (GdmTask *task) -+{ -+ return FALSE; -+} -+ -+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 -+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; -+} -+ -+static void -+gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) -+{ -+} -+ -+static void -+gdm_fingerprint_extension_class_init (GdmFingerprintExtensionClass *extension_class) -+{ -+ GObjectClass *object_class; -+ -+ object_class = G_OBJECT_CLASS (extension_class); -+ -+ object_class->finalize = gdm_fingerprint_extension_finalize; -+ -+ g_type_class_add_private (extension_class, -+ sizeof (GdmFingerprintExtensionPrivate)); -+} -+ -+static void -+gdm_fingerprint_extension_finalize (GObject *object) -+{ -+} -+ -+static void -+create_page (GdmFingerprintExtension *extension) -+{ -+ GtkBuilder *builder; -+ GObject *object; -+ GError *error; -+ -+ builder = gtk_builder_new (); -+ -+ error = NULL; -+ gtk_builder_add_from_file (builder, -+ PLUGINDATADIR "/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); -+} -+ -+static void -+create_actions (GdmFingerprintExtension *extension) -+{ -+ extension->priv->actions = gtk_action_group_new ("gdm-fingerprint-extension"); -+} -+ -+static void -+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 ("gdm-fingerprint"); -+ create_page (extension); -+ create_actions (extension); -+ gdm_fingerprint_extension_reset (GDM_CONVERSATION (extension)); -+} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.h 2009-09-23 18:46:06.789648576 -0400 -@@ -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 -+{ -+ GObjectClass parent_class; -+} GdmFingerprintExtensionClass; -+ -+GType gdm_fingerprint_extension_get_type (void); -+ -+GdmFingerprintExtension *gdm_fingerprint_extension_new (void); -+ -+G_END_DECLS -+ -+#endif /* GDM_FINGERPRINT_EXTENSION_H */ -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint.pam ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint.pam 2009-09-23 18:46:06.791416748 -0400 -@@ -0,0 +1,17 @@ -+# Sample PAM file for doing fingerprint authentication. -+# Distros should replace this with what makes sense for them. -+auth required pam_env.so -+auth required pam_fprintd.so -+auth sufficient pam_succeed_if.so uid >= 500 quiet -+auth required pam_deny.so -+ -+account required pam_unix.so -+account sufficient pam_localuser.so -+account sufficient pam_succeed_if.so uid < 500 quiet -+account required pam_permit.so -+ -+password required pam_deny.so -+ -+session optional pam_keyinit.so revoke -+session required pam_limits.so -+session required pam_unix.so -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am 2009-09-23 18:46:06.793390394 -0400 -@@ -0,0 +1,5 @@ -+iconsdir = $(datadir)/icons/hicolor/16x16/apps -+ -+icons_DATA = gdm-fingerprint.png -+ -+EXTRA_DIST = $(icons_DATA) -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am 2009-09-23 18:46:06.795405874 -0400 -@@ -0,0 +1,5 @@ -+iconsdir = $(datadir)/icons/hicolor/48x48/apps -+ -+icons_DATA = gdm-fingerprint.png -+ -+EXTRA_DIST = $(icons_DATA) -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/icons/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/icons/Makefile.am 2009-09-23 18:46:06.796402997 -0400 +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@ ++ ++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 = 16x16 48x48 -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/Makefile.am 2009-09-23 18:46:06.783657869 -0400 -@@ -0,0 +1,56 @@ -+SUBDIRS = icons -+ ++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..764904d +--- /dev/null ++++ b/gui/simple-greeter/plugins/password/Makefile.am +@@ -0,0 +1,53 @@ +NULL = -+PAM_SERVICE_NAME = gdm-fingerprint ++PAM_SERVICE_NAME = gdm-password + -+extensiondir = $(extensionsdatadir)/fingerprint ++extensiondir = $(extensionsdatadir)/password +extension_DATA = page.ui + +AM_CPPFLAGS = \ @@ -10435,20 +11879,19 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/Makefile.am + $(POLKIT_GNOME_CFLAGS) \ + $(NULL) + -+ +plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) -+plugin_LTLIBRARIES = fingerprint.la ++plugin_LTLIBRARIES = password.la + -+fingerprint_la_CFLAGS = \ ++password_la_CFLAGS = \ + $(SIMPLE_GREETER_CFLAGS) \ + $(NULL) + -+fingerprint_la_LDFLAGS = -module -avoid-version -export-dynamic -+fingerprint_la_LIBADD = ../../../../common/libgdmcommon.la \ ++password_la_LDFLAGS = -module -avoid-version -export-dynamic ++password_la_LIBADD = ../../../../common/libgdmcommon.la \ + ../../libgdmsimplegreeter/libgdmsimplegreeter.la -+fingerprint_la_SOURCES = \ -+ gdm-fingerprint-extension.h \ -+ gdm-fingerprint-extension.c \ ++password_la_SOURCES = \ ++ gdm-password-extension.h \ ++ gdm-password-extension.c \ + plugin.c + +$(PAM_SERVICE_NAME): $(PAM_SERVICE_NAME).pam @@ -10464,119 +11907,12 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/Makefile.am + *~ \ + $(PAM_SERVICE_NAME) \ + Makefile.in -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/page.ui ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/page.ui 2009-09-23 18:46:06.797402706 -0400 -@@ -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.28.0/gui/simple-greeter/plugins/fingerprint/plugin.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/fingerprint/plugin.c 2009-09-23 18:46:06.798411004 -0400 -@@ -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.28.0/gui/simple-greeter/plugins/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/Makefile.am 2009-09-23 18:46:06.801415786 -0400 -@@ -0,0 +1 @@ -+SUBDIRS = password fingerprint smartcard -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password-extension.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password-extension.c 2009-09-23 18:46:06.832406042 -0400 -@@ -0,0 +1,323 @@ +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..3acab3f +--- /dev/null ++++ b/gui/simple-greeter/plugins/password/gdm-password-extension.c +@@ -0,0 +1,314 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -10767,19 +12103,12 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password-e + return g_strdup (_("Log into session with username and password")); +} + -+gboolean -+gdm_password_extension_is_choosable (GdmTask *task) -+{ -+ return FALSE; -+} -+ +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 @@ -10877,9 +12206,7 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password-e + 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); ++ _("Log In"), NULL, 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); @@ -10900,9 +12227,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password-e + + gdm_password_extension_reset (GDM_CONVERSATION (extension)); +} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password-extension.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password-extension.h 2009-09-23 18:46:06.758650778 -0400 +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. @@ -10960,9 +12289,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password-e +G_END_DECLS + +#endif /* GDM_PASSWORD_EXTENSION_H */ -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password.pam ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password.pam 2009-09-23 18:46:06.759650276 -0400 +diff --git a/gui/simple-greeter/plugins/password/gdm-password.pam b/gui/simple-greeter/plugins/password/gdm-password.pam +new file mode 100644 +index 0000000..bac431d +--- /dev/null ++++ b/gui/simple-greeter/plugins/password/gdm-password.pam @@ -0,0 +1,19 @@ +# Sample PAM file for doing password authentication. +# Distros should replace this with what makes sense for them. @@ -10983,66 +12314,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/gdm-password.p +session optional pam_keyinit.so revoke +session required pam_limits.so +session required pam_unix.so -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/password/Makefile.am 2009-09-23 18:46:06.755661360 -0400 -@@ -0,0 +1,53 @@ -+NULL = -+PAM_SERVICE_NAME = gdm-password -+ -+extensiondir = $(extensionsdatadir)/password -+extension_DATA = page.ui -+ -+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=\""$(PAM_SERVICE_NAME)"\" \ -+ -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) -+ -+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 -+ -+$(PAM_SERVICE_NAME): $(PAM_SERVICE_NAME).pam -+ cp $(PAM_SERVICE_NAME).pam $(PAM_SERVICE_NAME) -+ -+pamdir = $(PAM_PREFIX)/pam.d -+pam_DATA = $(PAM_SERVICE_NAME) -+ -+EXTRA_DIST = $(extension_DATA) $(PAM_SERVICE_NAME).pam -+CLEANFILES = $(PAM_SERVICE_NAME) -+ -+MAINTAINERCLEANFILES = \ -+ *~ \ -+ $(PAM_SERVICE_NAME) \ -+ Makefile.in -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/page.ui ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/password/page.ui 2009-09-23 18:46:06.760651730 -0400 +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 @@ + + @@ -11100,9 +12376,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/page.ui + + + -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/plugin.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/password/plugin.c 2009-09-23 18:46:06.762655966 -0400 +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 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. @@ -11144,13 +12422,781 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/password/plugin.c + + return GDM_GREETER_EXTENSION (extension); +} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard.c 2009-09-23 18:46:06.814407453 -0400 -@@ -0,0 +1,558 @@ -+/* gdm-smartcard.c - smartcard object +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 9fb8a48..3963bd6 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -85,6 +85,7 @@ gui/simple-greeter/gdm-timer.c + gui/simple-greeter/gdm-user.c + gui/simple-greeter/gdm-user-chooser-widget.c + gui/simple-greeter/greeter-main.c ++gui/simple-greeter/plugins/password/gdm-password-extension.c + gui/user-switch-applet/applet.c + gui/user-switch-applet/gdm-entry-menu-item.c + gui/user-switch-applet/GNOME_FastUserSwitchApplet.server.in.in +-- +1.6.5.1 + + +From 58281be140f8065de49d6392c0db439840cf9c9b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sat, 7 Feb 2009 21:17:49 -0500 +Subject: [PATCH 46/81] 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 af8ff82..e27b905 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -663,15 +663,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) ++{ ++ /* need to wait for response from backend */ ++ set_message (login_window, _("Cancelling...")); ++ restart_conversations (login_window); ++} ++ + gboolean + gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, + const char *service_name) +@@ -717,6 +723,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)); ++ ++ 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.5.1 + + +From d2e1f986ae6c5c5b6e55df7f062031160ebb4dc6 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 18 Feb 2009 12:32:39 -0500 +Subject: [PATCH 47/81] Add a way for plugins to pick users from list + +The smartcard plugin is going to want to +start its conversation as soon as the card +gets plugged in. +--- + gui/simple-greeter/gdm-greeter-login-window.c | 36 ++++++++++++++++++++ + .../libgdmsimplegreeter/gdm-conversation.c | 32 +++++++++++++++++ + .../libgdmsimplegreeter/gdm-conversation.h | 6 +++ + 3 files changed, 74 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index e27b905..912a1e6 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -1796,6 +1796,34 @@ on_conversation_answer (GdmGreeterLoginWindow *login_window, + set_ready (login_window); + } + ++static void ++on_conversation_cancel (GdmGreeterLoginWindow *login_window, ++ GdmConversation *conversation) ++{ ++ do_cancel (login_window); ++} ++ ++static void ++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; ++ ++ 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 (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); ++ } ++} ++ + void + gdm_greeter_login_window_remove_extension (GdmGreeterLoginWindow *login_window, + GdmGreeterExtension *extension) +@@ -1933,6 +1961,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); ++} +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.5.1 + + +From bd213dd68b7002b38fcf739d013f9a17f9f8b3eb Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Feb 2009 14:05:20 -0500 +Subject: [PATCH 48/81] 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 cbd5072..ee5eeb0 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; +@@ -2541,8 +2542,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; ++} ++ + void + gdm_chooser_widget_loaded (GdmChooserWidget *widget) + { ++ widget->priv->is_loaded = TRUE; ++ + 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 7e3e59c..6a07843 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); ++ + /* Protected + */ + void gdm_chooser_widget_loaded (GdmChooserWidget *widget); +-- +1.6.5.1 + + +From aa3ae5b264ffa04c88f56be187a70e3845b2ef95 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Feb 2009 14:31:27 -0500 +Subject: [PATCH 49/81] 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 | 28 ++++++++++++++++++++++++- + 1 files changed, 27 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 912a1e6..4c14d40 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -678,6 +678,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)); ++} ++ + gboolean + gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window, + const char *service_name) +@@ -692,7 +713,12 @@ 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 { ++ ++ set_task_ready_when_loaded (login_window, task); ++ } + g_object_unref (task); + } + +-- +1.6.5.1 + + +From f7640b51fa287e75cde6170f0cd3b402f10e9db7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 6 Feb 2009 16:25:47 -0500 +Subject: [PATCH 50/81] Add fingerprint plugin + +This commit adds a plugin to initiate a conversation for +fingerprint scans. +--- + configure.ac | 4 + + gui/simple-greeter/plugins/Makefile.am | 2 +- + gui/simple-greeter/plugins/fingerprint/Makefile.am | 56 ++++ + .../fingerprint/gdm-fingerprint-extension.c | 299 ++++++++++++++++++++ + .../fingerprint/gdm-fingerprint-extension.h | 56 ++++ + .../plugins/fingerprint/gdm-fingerprint.pam | 17 ++ + .../plugins/fingerprint/icons/16x16/Makefile.am | 5 + + .../plugins/fingerprint/icons/48x48/Makefile.am | 5 + + .../plugins/fingerprint/icons/Makefile.am | 1 + + gui/simple-greeter/plugins/fingerprint/page.ui | 56 ++++ + gui/simple-greeter/plugins/fingerprint/plugin.c | 40 +++ + 11 files changed, 540 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/gdm-fingerprint.pam + create mode 100644 gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am + create mode 100644 gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am + create mode 100644 gui/simple-greeter/plugins/fingerprint/icons/Makefile.am + 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 aa8a620..c183a37 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1408,6 +1408,10 @@ 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/fingerprint/icons/Makefile ++gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile ++gui/simple-greeter/plugins/fingerprint/icons/48x48/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..25fb6e8 +--- /dev/null ++++ b/gui/simple-greeter/plugins/fingerprint/Makefile.am +@@ -0,0 +1,56 @@ ++SUBDIRS = icons ++ ++NULL = ++PAM_SERVICE_NAME = gdm-fingerprint ++ ++extensiondir = $(extensionsdatadir)/fingerprint ++extension_DATA = page.ui ++ ++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=\""$(PAM_SERVICE_NAME)"\" \ ++ -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 = fingerprint.la ++ ++fingerprint_la_CFLAGS = \ ++ $(SIMPLE_GREETER_CFLAGS) \ ++ $(NULL) ++ ++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 ++ ++$(PAM_SERVICE_NAME): $(PAM_SERVICE_NAME).pam ++ cp $(PAM_SERVICE_NAME).pam $(PAM_SERVICE_NAME) ++ ++pamdir = $(PAM_PREFIX)/pam.d ++pam_DATA = $(PAM_SERVICE_NAME) ++ ++EXTRA_DIST = $(extension_DATA) $(PAM_SERVICE_NAME).pam ++CLEANFILES = $(PAM_SERVICE_NAME) ++ ++MAINTAINERCLEANFILES = \ ++ *~ \ ++ $(PAM_SERVICE_NAME) \ ++ 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..b20dd65 +--- /dev/null ++++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c +@@ -0,0 +1,299 @@ ++/* ++ * Copyright (C) 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 ++ * 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 "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); ++ ++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 (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)); ++ ++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) ++{ ++ 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 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), ""); ++ ++ 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; ++ ++ gdm_task_set_enabled (GDM_TASK (conversation), FALSE); ++} ++ ++static void ++gdm_fingerprint_extension_set_ready (GdmConversation *conversation) ++{ ++ gdm_task_set_enabled (GDM_TASK (conversation), TRUE); ++} ++ ++char * ++gdm_fingerprint_extension_get_service_name (GdmConversation *conversation) ++{ ++ return g_strdup (PAMSERVICENAME); ++} ++ ++GtkWidget * ++gdm_fingerprint_extension_get_page (GdmConversation *conversation) ++{ ++ 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_fingerprint_extension_request_answer (GdmConversation *conversation) ++{ ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ const char *text; ++ ++ 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) ++{ ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (conversation); ++ ++ if (!extension->priv->answer_pending) { ++ return FALSE; ++ } ++ ++ gtk_widget_grab_focus (extension->priv->prompt_entry); ++ return TRUE; ++} ++ ++GIcon * ++gdm_fingerprint_extension_get_icon (GdmTask *task) ++{ ++ GdmFingerprintExtension *extension = GDM_FINGERPRINT_EXTENSION (task); ++ return g_object_ref (extension->priv->icon); ++} ++ ++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")); ++} ++ ++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; ++} ++ ++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; ++} ++ ++static void ++gdm_greeter_extension_iface_init (GdmGreeterExtensionIface *iface) ++{ ++} ++ ++static void ++gdm_fingerprint_extension_class_init (GdmFingerprintExtensionClass *extension_class) ++{ ++ GObjectClass *object_class; ++ ++ object_class = G_OBJECT_CLASS (extension_class); ++ ++ object_class->finalize = gdm_fingerprint_extension_finalize; ++ ++ g_type_class_add_private (extension_class, ++ sizeof (GdmFingerprintExtensionPrivate)); ++} ++ ++static void ++gdm_fingerprint_extension_finalize (GObject *object) ++{ ++} ++ ++static void ++create_page (GdmFingerprintExtension *extension) ++{ ++ GtkBuilder *builder; ++ GObject *object; ++ GError *error; ++ ++ builder = gtk_builder_new (); ++ ++ error = NULL; ++ gtk_builder_add_from_file (builder, ++ PLUGINDATADIR "/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); ++} ++ ++static void ++create_actions (GdmFingerprintExtension *extension) ++{ ++ GtkAction *action; ++ ++ extension->priv->actions = gtk_action_group_new ("gdm-fingerprint-extension"); ++} ++ ++static void ++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 ("gdm-fingerprint"); ++ create_page (extension); ++ create_actions (extension); ++ gdm_fingerprint_extension_reset (GDM_CONVERSATION (extension)); ++} +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 @@ ++/* ++ * 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 @@ -11166,550 +13212,386 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + * 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 GDM_SMARTCARD_ENABLE_INTERNAL_API -+#include "gdm-smartcard.h" + -+#include -+#include -+#include ++#ifndef __GDM_FINGERPRINT_EXTENSION_H ++#define __GDM_FINGERPRINT_EXTENSION_H + -+#include -+#include ++#include ++#include "gdm-greeter-extension.h" + -+#include -+#include -+#include -+#include -+#include -+#include ++G_BEGIN_DECLS + -+struct _GdmSmartcardPrivate { -+ SECMODModule *module; -+ GdmSmartcardState state; ++#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)) + -+ CK_SLOT_ID slot_id; -+ int slot_series; ++typedef struct _GdmFingerprintExtensionPrivate GdmFingerprintExtensionPrivate; + -+ PK11SlotInfo *slot; -+ char *name; -+ -+ CERTCertificate *signing_certificate; -+ CERTCertificate *encryption_certificate; -+}; -+ -+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); -+ -+static PK11SlotInfo *gdm_smartcard_find_slot_from_id (GdmSmartcard *card, -+ int slot_id); -+ -+static PK11SlotInfo *gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, -+ const char *card_name); -+static gboolean gdm_smartcard_fetch_certificates (GdmSmartcard *card); -+ -+#ifndef GDM_SMARTCARD_DEFAULT_SLOT_ID -+#define GDM_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1) -+#endif -+ -+#ifndef GDM_SMARTCARD_DEFAULT_SLOT_SERIES -+#define GDM_SMARTCARD_DEFAULT_SLOT_SERIES -1 -+#endif -+ -+enum { -+ PROP_0 = 0, -+ PROP_NAME, -+ PROP_SLOT_ID, -+ PROP_SLOT_SERIES, -+ PROP_MODULE, -+ NUMBER_OF_PROPERTIES -+}; -+ -+enum { -+ INSERTED, -+ REMOVED, -+ NUMBER_OF_SIGNALS -+}; -+ -+static guint gdm_smartcard_signals[NUMBER_OF_SIGNALS]; -+ -+G_DEFINE_TYPE (GdmSmartcard, gdm_smartcard, G_TYPE_OBJECT); -+ -+static void -+gdm_smartcard_class_init (GdmSmartcardClass *card_class) ++typedef struct +{ -+ GObjectClass *gobject_class; ++ GObject parent; ++ GdmFingerprintExtensionPrivate *priv; ++} GdmFingerprintExtension; + -+ gobject_class = G_OBJECT_CLASS (card_class); -+ -+ gobject_class->finalize = gdm_smartcard_finalize; -+ -+ gdm_smartcard_class_install_signals (card_class); -+ gdm_smartcard_class_install_properties (card_class); -+ -+ g_type_class_add_private (card_class, -+ sizeof (GdmSmartcardPrivate)); -+} -+ -+static void -+gdm_smartcard_class_install_signals (GdmSmartcardClass *card_class) ++typedef struct +{ -+ GObjectClass *object_class; ++ GObjectClass parent_class; ++} GdmFingerprintExtensionClass; + -+ object_class = G_OBJECT_CLASS (card_class); ++GType gdm_fingerprint_extension_get_type (void); + -+ 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); ++GdmFingerprintExtension *gdm_fingerprint_extension_new (void); + -+ 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_END_DECLS + -+static void -+gdm_smartcard_class_install_properties (GdmSmartcardClass *card_class) ++#endif /* GDM_FINGERPRINT_EXTENSION_H */ +diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint.pam b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint.pam +new file mode 100644 +index 0000000..1a1c777 +--- /dev/null ++++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint.pam +@@ -0,0 +1,17 @@ ++# Sample PAM file for doing fingerprint authentication. ++# Distros should replace this with what makes sense for them. ++auth required pam_env.so ++auth required pam_fprintd.so ++auth sufficient pam_succeed_if.so uid >= 500 quiet ++auth required pam_deny.so ++ ++account required pam_unix.so ++account sufficient pam_localuser.so ++account sufficient pam_succeed_if.so uid < 500 quiet ++account required pam_permit.so ++ ++password required pam_deny.so ++ ++session optional pam_keyinit.so revoke ++session required pam_limits.so ++session required pam_unix.so +diff --git a/gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am b/gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am +new file mode 100644 +index 0000000..f42e317 +--- /dev/null ++++ b/gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile.am +@@ -0,0 +1,5 @@ ++iconsdir = $(datadir)/icons/hicolor/16x16/apps ++ ++icons_DATA = gdm-fingerprint.png ++ ++EXTRA_DIST = $(icons_DATA) +diff --git a/gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am b/gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am +new file mode 100644 +index 0000000..f4ab2a0 +--- /dev/null ++++ b/gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile.am +@@ -0,0 +1,5 @@ ++iconsdir = $(datadir)/icons/hicolor/48x48/apps ++ ++icons_DATA = gdm-fingerprint.png ++ ++EXTRA_DIST = $(icons_DATA) +diff --git a/gui/simple-greeter/plugins/fingerprint/icons/Makefile.am b/gui/simple-greeter/plugins/fingerprint/icons/Makefile.am +new file mode 100644 +index 0000000..c20f10d +--- /dev/null ++++ b/gui/simple-greeter/plugins/fingerprint/icons/Makefile.am +@@ -0,0 +1 @@ ++SUBDIRS = 16x16 48x48 +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 @@ ++/* ++ * 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) +{ -+ GObjectClass *object_class; -+ GParamSpec *param_spec; ++ static GObject *extension; + -+ object_class = G_OBJECT_CLASS (card_class); -+ object_class->set_property = gdm_smartcard_set_property; -+ object_class->get_property = gdm_smartcard_get_property; -+ -+ 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); -+ -+ 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); -+ -+ 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); -+ -+ 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_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ GdmSmartcard *card = GDM_SMARTCARD (object); -+ -+ switch (prop_id) { -+ case PROP_NAME: -+ gdm_smartcard_set_name (card, g_value_get_string (value)); -+ break; -+ -+ case PROP_SLOT_ID: -+ gdm_smartcard_set_slot_id (card, -+ g_value_get_ulong (value)); -+ break; -+ -+ case PROP_SLOT_SERIES: -+ gdm_smartcard_set_slot_series (card, -+ g_value_get_int (value)); -+ break; -+ -+ case PROP_MODULE: -+ gdm_smartcard_set_module (card, -+ (SECMODModule *) -+ g_value_get_pointer (value)); -+ break; -+ -+ 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; -+} -+ -+GdmSmartcardState -+gdm_smartcard_get_state (GdmSmartcard *card) -+{ -+ return card->priv->state; -+} -+ -+char * -+gdm_smartcard_get_name (GdmSmartcard *card) -+{ -+ return g_strdup (card->priv->name); -+} -+ -+gboolean -+gdm_smartcard_is_login_card (GdmSmartcard *card) -+{ -+ const char *login_card_name; -+ login_card_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME"); -+ -+ if ((login_card_name == NULL) || (card->priv->name == NULL)) { -+ return FALSE; -+ } -+ -+ if (strcmp (card->priv->name, login_card_name) == 0) { -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+static void -+gdm_smartcard_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ GdmSmartcard *card = GDM_SMARTCARD (object); -+ -+ switch (prop_id) { -+ case PROP_NAME: -+ g_value_take_string (value, -+ gdm_smartcard_get_name (card)); -+ break; -+ -+ case PROP_SLOT_ID: -+ g_value_set_ulong (value, -+ (gulong) gdm_smartcard_get_slot_id (card)); -+ break; -+ -+ case PROP_SLOT_SERIES: -+ g_value_set_int (value, -+ gdm_smartcard_get_slot_series (card)); -+ break; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ } -+} -+ -+static void -+gdm_smartcard_set_name (GdmSmartcard *card, -+ const char *name) -+{ -+ if (name == NULL) { -+ return; -+ } -+ -+ if ((card->priv->name == NULL) || -+ (strcmp (card->priv->name, name) != 0)) { -+ g_free (card->priv->name); -+ card->priv->name = g_strdup (name); -+ -+ if (card->priv->slot == NULL) { -+ card->priv->slot = gdm_smartcard_find_slot_from_card_name (card, -+ card->priv->name); -+ -+ if (card->priv->slot != NULL) { -+ int slot_id, slot_series; -+ -+ slot_id = PK11_GetSlotID (card->priv->slot); -+ if (slot_id != card->priv->slot_id) { -+ gdm_smartcard_set_slot_id (card, slot_id); -+ } -+ -+ slot_series = PK11_GetSlotSeries (card->priv->slot); -+ if (slot_series != card->priv->slot_series) { -+ gdm_smartcard_set_slot_series (card, slot_series); -+ } -+ -+ _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_set_slot_id (GdmSmartcard *card, -+ int slot_id) -+{ -+ if (card->priv->slot_id != slot_id) { -+ card->priv->slot_id = slot_id; -+ -+ if (card->priv->slot == NULL) { -+ card->priv->slot = gdm_smartcard_find_slot_from_id (card, -+ card->priv->slot_id); -+ -+ if (card->priv->slot != NULL) { -+ const char *card_name; -+ -+ 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); -+ } -+ -+ _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), "slot-id"); -+ } -+} -+ -+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"); -+ } -+} -+ -+static void -+gdm_smartcard_set_module (GdmSmartcard *card, -+ SECMODModule *module) -+{ -+ gboolean should_notify; -+ -+ if (card->priv->module != module) { -+ should_notify = TRUE; ++ if (extension != NULL) { ++ g_object_ref (extension); + } else { -+ should_notify = FALSE; ++ extension = g_object_new (GDM_TYPE_FINGERPRINT_EXTENSION, NULL); ++ g_object_add_weak_pointer (extension, (gpointer *) &extension); + } + -+ if (card->priv->module != NULL) { -+ SECMOD_DestroyModule (card->priv->module); -+ card->priv->module = NULL; -+ } -+ -+ if (module != NULL) { -+ card->priv->module = SECMOD_ReferenceModule (module); -+ } -+ -+ if (should_notify) { -+ g_object_notify (G_OBJECT (card), "module"); -+ } ++ return GDM_GREETER_EXTENSION (extension); +} +-- +1.6.5.1 + + +From d727101394f9ce3c121c2ab7d7f37671f2c807aa Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 11 Feb 2009 08:47:52 -0500 +Subject: [PATCH 51/81] Add start of a smartcard plugin + +It contains a copy and paste of an old RHEL patch +I did a few years ago. +--- + configure.ac | 11 + + gui/simple-greeter/plugins/Makefile.am | 2 +- + gui/simple-greeter/plugins/smartcard/Makefile.am | 77 ++ + .../plugins/smartcard/gdm-smartcard-extension.c | 418 ++++++ + .../plugins/smartcard/gdm-smartcard-extension.h | 56 + + .../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 ++ + .../plugins/smartcard/gdm-smartcard.pam | 18 + + .../plugins/smartcard/icons/16x16/Makefile.am | 5 + + .../smartcard/icons/16x16/gdm-smartcard.png | Bin 0 -> 871 bytes + .../plugins/smartcard/icons/48x48/Makefile.am | 5 + + .../smartcard/icons/48x48/gdm-smartcard.png | Bin 0 -> 4202 bytes + .../plugins/smartcard/icons/Makefile.am | 1 + + gui/simple-greeter/plugins/smartcard/page.ui | 56 + + gui/simple-greeter/plugins/smartcard/plugin.c | 40 + + po/POTFILES.in | 1 + + 19 files changed, 2988 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/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 + create mode 100644 gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam + create mode 100644 gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am + create mode 100644 gui/simple-greeter/plugins/smartcard/icons/16x16/gdm-smartcard.png + create mode 100644 gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am + create mode 100644 gui/simple-greeter/plugins/smartcard/icons/48x48/gdm-smartcard.png + create mode 100644 gui/simple-greeter/plugins/smartcard/icons/Makefile.am + 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 c183a37..5a007a8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -68,6 +68,7 @@ LIBCANBERRA_GTK_REQUIRED_VERSION=0.4 + #FONTCONFIG_REQUIRED_VERSION=2.6.0 + FONTCONFIG_REQUIRED_VERSION=2.5.0 + DEVKIT_POWER_REQUIRED_VERSION=008 ++NSS_REQUIRED_VERSION=3.11.1 + + EXTRA_COMPILE_WARNINGS(yes) + +@@ -91,6 +92,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) + -+int -+gdm_smartcard_get_slot_series (GdmSmartcard *card) -+{ -+ return card->priv->slot_series; -+} + PKG_CHECK_MODULES(XLIB, x11 xau, , + [AC_PATH_XTRA + if test "x$no_x" = xyes; then +@@ -1412,6 +1419,10 @@ gui/simple-greeter/plugins/fingerprint/Makefile + gui/simple-greeter/plugins/fingerprint/icons/Makefile + gui/simple-greeter/plugins/fingerprint/icons/16x16/Makefile + gui/simple-greeter/plugins/fingerprint/icons/48x48/Makefile ++gui/simple-greeter/plugins/smartcard/Makefile ++gui/simple-greeter/plugins/smartcard/icons/Makefile ++gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile ++gui/simple-greeter/plugins/smartcard/icons/48x48/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..1ccebda +--- /dev/null ++++ b/gui/simple-greeter/plugins/smartcard/Makefile.am +@@ -0,0 +1,77 @@ ++SUBDIRS = icons + -+static void -+gdm_smartcard_init (GdmSmartcard *card) -+{ ++NULL = ++PAM_SERVICE_NAME = gdm-smartcard + -+ g_debug ("initializing smartcard "); ++extensiondir = $(extensionsdatadir)/smartcard ++extension_DATA = page.ui + -+ card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card, -+ GDM_TYPE_SMARTCARD, -+ GdmSmartcardPrivate); ++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=\""$(pam_DATA)"\" \ ++ -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) + -+ if (card->priv->slot != NULL) { -+ card->priv->name = g_strdup (PK11_GetTokenName (card->priv->slot)); -+ } -+} ++plugindir = $(GDM_SIMPLE_GREETER_PLUGINS_DIR) ++plugin_LTLIBRARIES = smartcard.la + -+static void gdm_smartcard_finalize (GObject *object) -+{ -+ GdmSmartcard *card; -+ GObjectClass *gobject_class; ++smartcard_la_CFLAGS = \ ++ $(SIMPLE_GREETER_CFLAGS) \ ++ $(NULL) + -+ card = GDM_SMARTCARD (object); ++libexec_PROGRAMS = \ ++ gdm-smartcard-worker \ ++ $(NULL) + -+ g_free (card->priv->name); + -+ gdm_smartcard_set_module (card, NULL); ++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 + -+ gobject_class = G_OBJECT_CLASS (gdm_smartcard_parent_class); ++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) + -+ gobject_class->finalize (object); -+} ++$(PAM_SERVICE_NAME): $(PAM_SERVICE_NAME).pam ++ cp $(PAM_SERVICE_NAME).pam $(PAM_SERVICE_NAME) + -+GQuark gdm_smartcard_error_quark (void) -+{ -+ static GQuark error_quark = 0; ++pamdir = $(PAM_PREFIX)/pam.d ++pam_DATA = $(PAM_SERVICE_NAME) + -+ if (error_quark == 0) { -+ error_quark = g_quark_from_static_string ("gdm-smartcard-error-quark"); -+ } ++EXTRA_DIST = $(extension_DATA) $(PAM_SERVICE_NAME).pam ++CLEANFILES = $(PAM_SERVICE_NAME) + -+ return error_quark; -+} -+ -+GdmSmartcard * -+_gdm_smartcard_new (SECMODModule *module, -+ CK_SLOT_ID slot_id, -+ int slot_series) -+{ -+ GdmSmartcard *card; -+ -+ 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); -+ -+ card = GDM_SMARTCARD (g_object_new (GDM_TYPE_SMARTCARD, -+ "module", module, -+ "slot-id", (gulong) slot_id, -+ "slot-series", slot_series, -+ NULL)); -+ return card; -+} -+ -+GdmSmartcard * -+_gdm_smartcard_new_from_name (SECMODModule *module, -+ const char *name) -+{ -+ GdmSmartcard *card; -+ -+ g_return_val_if_fail (module != NULL, NULL); -+ g_return_val_if_fail (name != NULL, NULL); -+ -+ 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 (); -+ } -+ } -+} -+ -+/* 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; -+ } -+ -+ return password != NULL? PL_strdup (password): NULL; -+} -+ -+gboolean -+gdm_smartcard_unlock (GdmSmartcard *card, -+ const char *password) -+{ -+ SECStatus status; -+ -+ PK11_SetPasswordFunc ((PK11PasswordFunc) gdm_smartcard_password_handler); -+ -+ /* we pass PR_TRUE to load certificates -+ */ -+ status = PK11_Authenticate (card->priv->slot, PR_TRUE, (gpointer) password); -+ -+ if (status != SECSuccess) { -+ g_debug ("could not unlock card - %d", status); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+static PK11SlotInfo * -+gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, -+ const char *card_name) -+{ -+ int i; -+ -+ for (i = 0; i < card->priv->module->slotCount; i++) { -+ const char *slot_card_name; -+ -+ slot_card_name = PK11_GetTokenName (card->priv->module->slots[i]); -+ -+ if ((slot_card_name != NULL) && -+ (strcmp (slot_card_name, card_name) == 0)) { -+ return card->priv->module->slots[i]; -+ } -+ } -+ -+ return NULL; -+} -+ -+static PK11SlotInfo * -+gdm_smartcard_find_slot_from_id (GdmSmartcard *card, -+ int slot_id) -+{ -+ int i; -+ -+ 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]; -+ } -+ } -+ -+ return NULL; -+} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c 2009-09-23 18:46:06.868400496 -0400 -@@ -0,0 +1,440 @@ ++MAINTAINERCLEANFILES = \ ++ *~ \ ++ $(PAM_SERVICE_NAME) \ ++ 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..6fa01fb +--- /dev/null ++++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c +@@ -0,0 +1,418 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * @@ -11765,7 +13647,6 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + int number_of_tokens; + + guint answer_pending : 1; -+ guint select_when_ready : 1; +}; + +static void gdm_smartcard_extension_finalize (GObject *object); @@ -11815,14 +13696,8 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + } + + 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!"); -+ } ++ 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)); + } @@ -11929,16 +13804,10 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + 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); -+ } -+ -+ if (extension->priv->select_when_ready) { -+ if (gdm_conversation_choose_user (GDM_CONVERSATION (extension), -+ PAMSERVICENAME)) { -+ extension->priv->select_when_ready = FALSE; -+ } -+ } ++ } +} + +char * @@ -12015,19 +13884,12 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + return g_strdup (_("Log into session with smartcard")); +} + -+gboolean -+gdm_smartcard_extension_is_choosable (GdmTask *task) -+{ -+ return TRUE; -+} -+ +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 @@ -12125,9 +13987,7 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + extension->priv->actions = gtk_action_group_new ("gdm-smartcard-extension"); + + action = gtk_action_new (GDM_CONVERSATION_DEFAULT_ACTION, -+ _("Log In"), -+ _("Log into the currently selected sesson"), -+ NULL); ++ _("Log In"), NULL, 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); @@ -12150,9 +14010,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + create_actions (extension); + gdm_smartcard_extension_reset (GDM_CONVERSATION (extension)); +} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.h 2009-09-23 18:46:06.806407203 -0400 +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. @@ -12210,107 +14072,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard +G_END_DECLS + +#endif /* GDM_SMARTCARD_EXTENSION_H */ -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard.h 2009-09-23 18:46:06.816405822 -0400 -@@ -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 -+ -+#include -+ -+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; -+ -+typedef struct _GdmSmartcardRequest GdmSmartcardRequest; -+ -+struct _GdmSmartcard { -+ GObject parent; -+ -+ /*< private > */ -+ GdmSmartcardPrivate *priv; -+}; -+ -+struct _GdmSmartcardClass { -+ GObjectClass parent_class; -+ -+ void (* inserted) (GdmSmartcard *card); -+ void (* removed) (GdmSmartcard *card); -+}; -+ -+enum _GdmSmartcardError { -+ GDM_SMARTCARD_ERROR_GENERIC = 0, -+}; -+ -+enum _GdmSmartcardState { -+ GDM_SMARTCARD_STATE_INSERTED = 0, -+ GDM_SMARTCARD_STATE_REMOVED, -+}; -+ -+GType gdm_smartcard_get_type (void) G_GNUC_CONST; -+GQuark gdm_smartcard_error_quark (void) G_GNUC_CONST; -+ -+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); -+ -+char *gdm_smartcard_get_name (GdmSmartcard *card); -+gboolean gdm_smartcard_is_login_card (GdmSmartcard *card); -+ -+gboolean gdm_smartcard_unlock (GdmSmartcard *card, -+ const char *password); -+ -+/* don't under any circumstances call these functions */ -+#ifdef GDM_SMARTCARD_ENABLE_INTERNAL_API -+ -+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); -+ -+void _gdm_smartcard_set_state (GdmSmartcard *card, -+ GdmSmartcardState state); -+#endif -+ -+G_END_DECLS -+#endif /* GDM_SMARTCARD_H */ -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.c 2009-09-23 18:46:06.809405560 -0400 +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 @@ -13706,9 +15472,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + return 0; +} +#endif -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.h ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-manager.h 2009-09-23 18:46:06.811390170 -0400 +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 @@ -13796,31 +15564,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + +G_END_DECLS +#endif /* GDM_SMARTCARD_MANAGER_H */ -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam 2009-09-23 18:46:06.817400851 -0400 -@@ -0,0 +1,18 @@ -+# Sample PAM file for doing smartcard authentication. -+# Distros should replace this with what makes sense for them. -+auth required pam_env.so -+auth [success=done ignore=ignore default=die] pam_pkcs11.so wait_for_card -+auth requisite pam_succeed_if.so uid >= 500 quiet -+auth required pam_deny.so -+ -+account required pam_unix.so -+account sufficient pam_localuser.so -+account sufficient pam_succeed_if.so uid < 500 quiet -+account required pam_permit.so -+ -+password optional pam_pkcs11.so -+password requisite pam_cracklib.so try_first_pass retry=3 type= -+ -+session optional pam_keyinit.so revoke -+session required pam_limits.so -+session required pam_unix.so -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c 2009-09-23 18:46:06.812410900 -0400 +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..75e4f33 +--- /dev/null ++++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-worker.c @@ -0,0 +1,167 @@ +#include "config.h" + @@ -13989,113 +15737,845 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/gdm-smartcard + + return 0; +} -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am 2009-09-23 18:46:06.819416331 -0400 +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" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct _GdmSmartcardPrivate { ++ SECMODModule *module; ++ GdmSmartcardState state; ++ ++ CK_SLOT_ID slot_id; ++ int slot_series; ++ ++ PK11SlotInfo *slot; ++ char *name; ++ ++ CERTCertificate *signing_certificate; ++ CERTCertificate *encryption_certificate; ++}; ++ ++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); ++ ++static PK11SlotInfo *gdm_smartcard_find_slot_from_id (GdmSmartcard *card, ++ int slot_id); ++ ++static PK11SlotInfo *gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, ++ const char *card_name); ++static gboolean gdm_smartcard_fetch_certificates (GdmSmartcard *card); ++ ++#ifndef GDM_SMARTCARD_DEFAULT_SLOT_ID ++#define GDM_SMARTCARD_DEFAULT_SLOT_ID ((gulong) -1) ++#endif ++ ++#ifndef GDM_SMARTCARD_DEFAULT_SLOT_SERIES ++#define GDM_SMARTCARD_DEFAULT_SLOT_SERIES -1 ++#endif ++ ++enum { ++ PROP_0 = 0, ++ PROP_NAME, ++ PROP_SLOT_ID, ++ PROP_SLOT_SERIES, ++ PROP_MODULE, ++ NUMBER_OF_PROPERTIES ++}; ++ ++enum { ++ INSERTED, ++ REMOVED, ++ NUMBER_OF_SIGNALS ++}; ++ ++static guint gdm_smartcard_signals[NUMBER_OF_SIGNALS]; ++ ++G_DEFINE_TYPE (GdmSmartcard, gdm_smartcard, G_TYPE_OBJECT); ++ ++static void ++gdm_smartcard_class_init (GdmSmartcardClass *card_class) ++{ ++ GObjectClass *gobject_class; ++ ++ gobject_class = G_OBJECT_CLASS (card_class); ++ ++ gobject_class->finalize = gdm_smartcard_finalize; ++ ++ gdm_smartcard_class_install_signals (card_class); ++ gdm_smartcard_class_install_properties (card_class); ++ ++ g_type_class_add_private (card_class, ++ sizeof (GdmSmartcardPrivate)); ++} ++ ++static void ++gdm_smartcard_class_install_signals (GdmSmartcardClass *card_class) ++{ ++ GObjectClass *object_class; ++ ++ object_class = G_OBJECT_CLASS (card_class); ++ ++ 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); ++ ++ 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_class_install_properties (GdmSmartcardClass *card_class) ++{ ++ 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; ++ ++ 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); ++ ++ 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); ++ ++ 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); ++ ++ 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_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ GdmSmartcard *card = GDM_SMARTCARD (object); ++ ++ switch (prop_id) { ++ case PROP_NAME: ++ gdm_smartcard_set_name (card, g_value_get_string (value)); ++ break; ++ ++ case PROP_SLOT_ID: ++ gdm_smartcard_set_slot_id (card, ++ g_value_get_ulong (value)); ++ break; ++ ++ case PROP_SLOT_SERIES: ++ gdm_smartcard_set_slot_series (card, ++ g_value_get_int (value)); ++ break; ++ ++ case PROP_MODULE: ++ gdm_smartcard_set_module (card, ++ (SECMODModule *) ++ g_value_get_pointer (value)); ++ break; ++ ++ 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; ++} ++ ++GdmSmartcardState ++gdm_smartcard_get_state (GdmSmartcard *card) ++{ ++ return card->priv->state; ++} ++ ++char * ++gdm_smartcard_get_name (GdmSmartcard *card) ++{ ++ return g_strdup (card->priv->name); ++} ++ ++gboolean ++gdm_smartcard_is_login_card (GdmSmartcard *card) ++{ ++ const char *login_card_name; ++ login_card_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME"); ++ ++ if ((login_card_name == NULL) || (card->priv->name == NULL)) { ++ return FALSE; ++ } ++ ++ if (strcmp (card->priv->name, login_card_name) == 0) { ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++static void ++gdm_smartcard_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ GdmSmartcard *card = GDM_SMARTCARD (object); ++ ++ switch (prop_id) { ++ case PROP_NAME: ++ g_value_take_string (value, ++ gdm_smartcard_get_name (card)); ++ break; ++ ++ case PROP_SLOT_ID: ++ g_value_set_ulong (value, ++ (gulong) gdm_smartcard_get_slot_id (card)); ++ break; ++ ++ case PROP_SLOT_SERIES: ++ g_value_set_int (value, ++ gdm_smartcard_get_slot_series (card)); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++gdm_smartcard_set_name (GdmSmartcard *card, ++ const char *name) ++{ ++ if (name == NULL) { ++ return; ++ } ++ ++ if ((card->priv->name == NULL) || ++ (strcmp (card->priv->name, name) != 0)) { ++ g_free (card->priv->name); ++ card->priv->name = g_strdup (name); ++ ++ if (card->priv->slot == NULL) { ++ card->priv->slot = gdm_smartcard_find_slot_from_card_name (card, ++ card->priv->name); ++ ++ if (card->priv->slot != NULL) { ++ int slot_id, slot_series; ++ ++ slot_id = PK11_GetSlotID (card->priv->slot); ++ if (slot_id != card->priv->slot_id) { ++ gdm_smartcard_set_slot_id (card, slot_id); ++ } ++ ++ slot_series = PK11_GetSlotSeries (card->priv->slot); ++ if (slot_series != card->priv->slot_series) { ++ gdm_smartcard_set_slot_series (card, slot_series); ++ } ++ ++ _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_set_slot_id (GdmSmartcard *card, ++ int slot_id) ++{ ++ if (card->priv->slot_id != slot_id) { ++ card->priv->slot_id = slot_id; ++ ++ if (card->priv->slot == NULL) { ++ card->priv->slot = gdm_smartcard_find_slot_from_id (card, ++ card->priv->slot_id); ++ ++ if (card->priv->slot != NULL) { ++ const char *card_name; ++ ++ 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); ++ } ++ ++ _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), "slot-id"); ++ } ++} ++ ++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"); ++ } ++} ++ ++static void ++gdm_smartcard_set_module (GdmSmartcard *card, ++ SECMODModule *module) ++{ ++ gboolean should_notify; ++ ++ if (card->priv->module != module) { ++ should_notify = TRUE; ++ } else { ++ should_notify = FALSE; ++ } ++ ++ if (card->priv->module != NULL) { ++ SECMOD_DestroyModule (card->priv->module); ++ card->priv->module = NULL; ++ } ++ ++ if (module != NULL) { ++ card->priv->module = SECMOD_ReferenceModule (module); ++ } ++ ++ if (should_notify) { ++ g_object_notify (G_OBJECT (card), "module"); ++ } ++} ++ ++int ++gdm_smartcard_get_slot_series (GdmSmartcard *card) ++{ ++ return card->priv->slot_series; ++} ++ ++static void ++gdm_smartcard_init (GdmSmartcard *card) ++{ ++ ++ g_debug ("initializing smartcard "); ++ ++ card->priv = G_TYPE_INSTANCE_GET_PRIVATE (card, ++ GDM_TYPE_SMARTCARD, ++ GdmSmartcardPrivate); ++ ++ if (card->priv->slot != NULL) { ++ card->priv->name = g_strdup (PK11_GetTokenName (card->priv->slot)); ++ } ++} ++ ++static void gdm_smartcard_finalize (GObject *object) ++{ ++ GdmSmartcard *card; ++ GObjectClass *gobject_class; ++ ++ card = GDM_SMARTCARD (object); ++ ++ g_free (card->priv->name); ++ ++ gdm_smartcard_set_module (card, NULL); ++ ++ gobject_class = G_OBJECT_CLASS (gdm_smartcard_parent_class); ++ ++ gobject_class->finalize (object); ++} ++ ++GQuark gdm_smartcard_error_quark (void) ++{ ++ static GQuark error_quark = 0; ++ ++ if (error_quark == 0) { ++ error_quark = g_quark_from_static_string ("gdm-smartcard-error-quark"); ++ } ++ ++ return error_quark; ++} ++ ++GdmSmartcard * ++_gdm_smartcard_new (SECMODModule *module, ++ CK_SLOT_ID slot_id, ++ int slot_series) ++{ ++ GdmSmartcard *card; ++ ++ 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); ++ ++ card = GDM_SMARTCARD (g_object_new (GDM_TYPE_SMARTCARD, ++ "module", module, ++ "slot-id", (gulong) slot_id, ++ "slot-series", slot_series, ++ NULL)); ++ return card; ++} ++ ++GdmSmartcard * ++_gdm_smartcard_new_from_name (SECMODModule *module, ++ const char *name) ++{ ++ GdmSmartcard *card; ++ ++ g_return_val_if_fail (module != NULL, NULL); ++ g_return_val_if_fail (name != NULL, NULL); ++ ++ 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 (); ++ } ++ } ++} ++ ++/* 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; ++ } ++ ++ return password != NULL? PL_strdup (password): NULL; ++} ++ ++gboolean ++gdm_smartcard_unlock (GdmSmartcard *card, ++ const char *password) ++{ ++ SECStatus status; ++ ++ PK11_SetPasswordFunc ((PK11PasswordFunc) gdm_smartcard_password_handler); ++ ++ /* we pass PR_TRUE to load certificates ++ */ ++ status = PK11_Authenticate (card->priv->slot, PR_TRUE, (gpointer) password); ++ ++ if (status != SECSuccess) { ++ g_debug ("could not unlock card - %d", status); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++static PK11SlotInfo * ++gdm_smartcard_find_slot_from_card_name (GdmSmartcard *card, ++ const char *card_name) ++{ ++ int i; ++ ++ for (i = 0; i < card->priv->module->slotCount; i++) { ++ const char *slot_card_name; ++ ++ slot_card_name = PK11_GetTokenName (card->priv->module->slots[i]); ++ ++ if ((slot_card_name != NULL) && ++ (strcmp (slot_card_name, card_name) == 0)) { ++ return card->priv->module->slots[i]; ++ } ++ } ++ ++ return NULL; ++} ++ ++static PK11SlotInfo * ++gdm_smartcard_find_slot_from_id (GdmSmartcard *card, ++ int slot_id) ++{ ++ int i; ++ ++ 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]; ++ } ++ } ++ ++ return NULL; ++} +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 ++ ++#include ++ ++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; ++ ++typedef struct _GdmSmartcardRequest GdmSmartcardRequest; ++ ++struct _GdmSmartcard { ++ GObject parent; ++ ++ /*< private > */ ++ GdmSmartcardPrivate *priv; ++}; ++ ++struct _GdmSmartcardClass { ++ GObjectClass parent_class; ++ ++ void (* inserted) (GdmSmartcard *card); ++ void (* removed) (GdmSmartcard *card); ++}; ++ ++enum _GdmSmartcardError { ++ GDM_SMARTCARD_ERROR_GENERIC = 0, ++}; ++ ++enum _GdmSmartcardState { ++ GDM_SMARTCARD_STATE_INSERTED = 0, ++ GDM_SMARTCARD_STATE_REMOVED, ++}; ++ ++GType gdm_smartcard_get_type (void) G_GNUC_CONST; ++GQuark gdm_smartcard_error_quark (void) G_GNUC_CONST; ++ ++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); ++ ++char *gdm_smartcard_get_name (GdmSmartcard *card); ++gboolean gdm_smartcard_is_login_card (GdmSmartcard *card); ++ ++gboolean gdm_smartcard_unlock (GdmSmartcard *card, ++ const char *password); ++ ++/* don't under any circumstances call these functions */ ++#ifdef GDM_SMARTCARD_ENABLE_INTERNAL_API ++ ++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); ++ ++void _gdm_smartcard_set_state (GdmSmartcard *card, ++ GdmSmartcardState state); ++#endif ++ ++G_END_DECLS ++#endif /* GDM_SMARTCARD_H */ +diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam b/gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam +new file mode 100644 +index 0000000..3c803f7 +--- /dev/null ++++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard.pam +@@ -0,0 +1,18 @@ ++# Sample PAM file for doing smartcard authentication. ++# Distros should replace this with what makes sense for them. ++auth required pam_env.so ++auth [success=done ignore=ignore default=die] pam_pkcs11.so wait_for_card ++auth requisite pam_succeed_if.so uid >= 500 quiet ++auth required pam_deny.so ++ ++account required pam_unix.so ++account sufficient pam_localuser.so ++account sufficient pam_succeed_if.so uid < 500 quiet ++account required pam_permit.so ++ ++password optional pam_pkcs11.so ++password requisite pam_cracklib.so try_first_pass retry=3 type= ++ ++session optional pam_keyinit.so revoke ++session required pam_limits.so ++session required pam_unix.so +diff --git a/gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am b/gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am +new file mode 100644 +index 0000000..661d687 +--- /dev/null ++++ b/gui/simple-greeter/plugins/smartcard/icons/16x16/Makefile.am @@ -0,0 +1,5 @@ +iconsdir = $(datadir)/icons/hicolor/16x16/apps + +icons_DATA = gdm-smartcard.png + +EXTRA_DIST = $(icons_DATA) -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am 2009-09-23 18:46:06.821400871 -0400 +diff --git a/gui/simple-greeter/plugins/smartcard/icons/16x16/gdm-smartcard.png b/gui/simple-greeter/plugins/smartcard/icons/16x16/gdm-smartcard.png +new file mode 100644 +index 0000000000000000000000000000000000000000..0112af1b8d891ad312f9fcc3bf6074df3e003359 +GIT binary patch +literal 871 +zcmV-t1DO1YP)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iXJ- +z6cQQvze?o*000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0008QNkl25h)mRS()F5IML|LeofZ5$Phq#SvEXn3)x9QHz&V1jD*OHUa=lnh|yoWc& +zo1+2m0}628RN4)kP9zfJhGEoz$TZEX{|)Htgf`%?ZQIABl!txa-_X&~;rI9Vo88^r +z1;L|^!4>6dV71>-}NC2_0X(TUE+qIrDYmT)AaSb +zqQSwzu&1X-?Cbi7rG`eaTxYT75y*%ZE6&r0<4pW|3Ey2K2m+~;x&Y(=rCFBMd{LP< +ze!f%2@g%ktXZzbJvY9kitjV=&V+;=uGc+_rtyZH_sW3S?$@KK}cfeU)DJ6Ufjwku* +z#Jf~p{6)1o%ag||*tX5+=qR~dj#8<_+}s>O2(sBM#bWVH7>3^p-}m(}(unH3ls_kY}+QE&oeeQMlzYCTCI{!r;|XJ05A-lFao6%Gcz-k%VnBP$+`1i +z^JL;6j^og}#l)>&;?s|J5k(Q5do}@lp##MA7)pgK{$tR(^AIgbgR>VO(YA9dDYL-` +zsh`;Y%6?x&ziM4udm5K2(B3uPvQ%dL5Nt5QX;$Nu&Y|(&dU|=Ac +znwoM8g@R?8=8}~1uJ8MIfoDQ+^ZMlj@4UAwMAl}h&MMZb@Tk<}`x}kRnq^tHG);3I +x$GHPM0G_Y=$2Q;_pbrQE4|oMk0zdM9c?}H%H!P_~w{rjh002ovPDHLkV1ieHj1>R? + +literal 0 +HcmV?d00001 + +diff --git a/gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am b/gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am +new file mode 100644 +index 0000000..e79d85b +--- /dev/null ++++ b/gui/simple-greeter/plugins/smartcard/icons/48x48/Makefile.am @@ -0,0 +1,5 @@ +iconsdir = $(datadir)/icons/hicolor/48x48/apps + +icons_DATA = gdm-smartcard.png + +EXTRA_DIST = $(icons_DATA) -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/icons/Makefile.am ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/icons/Makefile.am 2009-09-23 18:46:06.822408960 -0400 +diff --git a/gui/simple-greeter/plugins/smartcard/icons/48x48/gdm-smartcard.png b/gui/simple-greeter/plugins/smartcard/icons/48x48/gdm-smartcard.png +new file mode 100644 +index 0000000000000000000000000000000000000000..35d5578d9ec83ae6b17aa7230c1b4df34e13e2cc +GIT binary patch +literal 4202 +zcmV-w5S8zVP)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iXJ- +z6calzC#000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000lgNkl2aFf(X>ozT5 +zC$5aZk)aA|*R=Bt;5o9kwWGLxmKt<-N{vG7>41KQobz$)Btw?d%RxnyB)`A*IJ8UFsQn_yUTz( +zIywx~G;av_`rnpip|uYDs!S+YWQjXH9?w0l>%LQKZTS6uy>sVI(cRrmPfriG+;WTI +z@p#@6@Iu;UXgp0zq>6^HuiPI91TYLkD5ZWW0{DTQz#hx8?o~?Nrj#^8Cli339gNwym|C9-PB*HI@kv?`fqW>?@BILKy#D +z4S0a;tuC6Y+ySqg!7UTBYZx?>Q|Av62(oD=`2?xClT$$(W&^%g! +zTIQ6mo}a-m1X^pf7EI3NXk4{4pHeFHiwMvG>@`jEE+8hQ^c#kuJ3Bk+>FE)%Sd1Mz +zc8Fjw_@?GCIhSXAHcNDspBGO};7E<_NQ5YWEH$6Uz?B-Qba9Tt=f>65#Ugb-f=#OBSLRV)@WcJJQJ&Ye3&I2?Xcz^>Gsxim*Q?-KBt3|v`2Duq&D7y_j< +z0x%8GT2LLZXlt%!eN&J%4OM6j-+g(6iP&p8JBMy +zy3F*%&q)02ENiPXEG{l``t)fA1_rW9sr5kOEj1ve^tZRS)6mec0`UBz&A;|tBkxE8 +zJ`-DNTvuTTQMPBVWuO4R$D}nHpshK?+Qt9@f2Dh6vsn^}1XEK}BoYa1+on2P$8&%6 +zXIvfZ$23jq>+2Chkjv#zN>u?Pz<%H{Erluyw#>N;L8e(*Gv`DLkM=6Eh@8_O-?!oKzic_afJqug{j#UWY +zI1WMx{9Y4}DUeEFnSyt9HPNv?jFgh;>FJ6cc3rnJpQx!J5{ZgwtW?Zo48;_*12 +z``qW)zI{6nKKLN5t*wlWjnUuVPdc4OO3Cu*tCS+0PNS5ftE-FQ;bCK9V&ZR$v@chf +zkjFCFxTc!(L-W*!{dBgi;_~Io^!N9#0K96|Dx%RSjg5^&qfr8ZKzY%*xj8OgyvW4F +z1XEK}>x86!T9_QS-bIi`plFQ}rcswhZN^6ajlEuYEVzC(e_wU~V +z+zY(8LIVqFhs)QJ0IY2cAcP>F&!d#0zP_GlG)g2Ap|P=%QWSPwm+9$g;_-OdoE*og +z01*m>XliQW%9Sf@-MW=syLK@>JxwZ=VrXcH^XJdAdi838!626|T_TxG(%9I@=FOYS +zb7V3ZJRT2`NQ6Wp@!QJRH14t>!X0sePaDb|+Dtta4 +zufP5}>(;HKy}g}yJWeK)K}yM*HET#D5_gq-z%nx;u(VMPRx)Uz}P+MC|E|(*h%P~DYjo0fXolcX@W|^3n;K?VS +z=PjT#i5aQW?mE5b2T$nTAnL5%hH+mw(UYawHN7CMG7BoSbBK +zcDC#XmSxf2-d=ux&mFsn4_)CepZOr~-DB`-zg6b=QkMFm4`zAa9rIv#i`l6cfsfvw +z_z8tV<+xB{xngSqhOH8x3L#k27{o9{kzJNdD3i&Q!A?v}Fh4)Pf>N8BnrLorrmd~5 +zBC`MZ%vp~A^A0vdhpDPHkW!Sv=ks~A)_B7YQoHF6K%;R$=YcHQS6;()T|6F7S%CJ< +zbqo!K7#mys4zSHC0Te=DI}%+K&@JZcGcz+BJb17yxe$W-`uZ~9Xf#@3GS_Qtdshpd +zwL$D_<2Z{M=10zx+0coUlJW6zgb*Yyo<{4fMa?VFE?|@Y=}Y|0muHAXA{a&?n~etY +z9P4|4p56OfCnvLCu!Imf*L4eElX(zJ0YnHvFc_q*t*y-E(P;FBEOY(uGv_CfN@Iyd +zG=jRG)y$q8NID7Ow6H`@eTVF+6OPB|KYcpCU3TtbPMgo#YKK*`%esqSRvqNln +zpqi@2ChmQx6*WK2XMblkk3SRtJqyT}R35DhAP@)vj$3fzKp?=LJ$v31aC~^4{x=eA +zXj#R{fia%>`ybP`HcWiDU}lTM)ujQ{++^d8y6n0%1+77R?~CGDRgIki0dHM>MW1&~E51#8(B?Z)b2G@9BjiR-q4GA` +z1ub=fK}=Ct*j6}6g`JexNsUf|*Y6{37kt7}N;%nV79j+wjLp=14y`qgT5{rlI`BH5 +z{mKvd{1e@L^!^UAIhUc)1+HFO;Fhh8oWDGcl$uX|^j7xn*+4^G6}2^f9{+F`vDn{L +z20p7A?c0LsjY3r&qTw=za|xYyakFs#oWrS~*yucTzr#yQorzb0vK2C~srG4v)|3pQ +zM5AR5h>{xR(mC-vFAnngC%W-i2J7yu1oZVkzl;0s*uX+6PhHsmU!P$`9z1I?gdc^x +zt`9mkTYUR_S^n|gGW_BFK_3555VOj_sxol18q=#;KFm@|=@P?K`7AcIgt;&@%krwE +zWg5KNKgNqM4*{_6W4G~}_ipC-e}A2u*41JfVg>lwWR9!jDW>ML#nMs{q)Z@$4sA?5`wY$vF6CHez{E%@3`>BkDOHUut+h_2QsozaHc|NQ$fdzg?~8Hx=udg_ +z(OcQlR#*Q2Q;*%gl=Cmz42>tbG(5-E@f1>O6q; +zX-_O5v;07EtbcS_^-VG|xmachDJ7OAFfh5jGlJ`CydHyHoz3{XW +z{(dz$IAT2ho_d-#6|#4&hB1V1g$WsgB6x$QI*YsCwN&|#S%sTbNE@USNTtgHIC@#} +zG8FJ)ngXp0H6j3yX`s=3WJoXpKFL!MA(BVttUA6Kx!+>2od~AOws2nU#N~T`3Nv9y~ +zm^h|M`!<7cBlMoN0Zv;$_WFsm)?B!7f!^L;`uh5GZ*Q+kCX;57$_9&od$ratYprK~ +z&O-86fXE$>&V1^7U-zHPRK--Qpu^f!9}X+|e<~ +z6MvoI@K5qN;7er_x_I#-M~@z*udk0IM~=vunHdwn + @@ -14153,9 +16633,11 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/page.ui + + + -diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/plugin.c ---- /dev/null 2009-09-23 15:09:11.116404522 -0400 -+++ gdm-2.28.0/gui/simple-greeter/plugins/smartcard/plugin.c 2009-09-23 18:46:06.825390205 -0400 +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. @@ -14197,3 +16679,2465 @@ diff -up /dev/null gdm-2.28.0/gui/simple-greeter/plugins/smartcard/plugin.c + + return GDM_GREETER_EXTENSION (extension); +} +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 3963bd6..4d219fb 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -86,6 +86,7 @@ gui/simple-greeter/gdm-user.c + gui/simple-greeter/gdm-user-chooser-widget.c + gui/simple-greeter/greeter-main.c + gui/simple-greeter/plugins/password/gdm-password-extension.c ++gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c + gui/user-switch-applet/applet.c + gui/user-switch-applet/gdm-entry-menu-item.c + gui/user-switch-applet/GNOME_FastUserSwitchApplet.server.in.in +-- +1.6.5.1 + + +From abba21674b3db119288f89d3ccf4a84379f8fbc6 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 23 Feb 2009 17:57:06 -0500 +Subject: [PATCH 52/81] 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 4c14d40..e137e1b 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -2002,9 +2002,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 { +@@ -2015,6 +2012,16 @@ gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, + GDM_TASK (extension)); + + service_name = gdm_conversation_get_service_name (GDM_CONVERSATION (extension)); ++ ++ 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_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); +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); ++} ++ + 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 b20dd65..7aa99e7 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; ++} ++ + 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 3acab3f..4922c65 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; ++} ++ + 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 6fa01fb..25d5de4 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; ++} ++ + 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.5.1 + + +From 7ff0274b43e1d0dd6e0f1ec1ac60f628c546679b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 24 Feb 2009 15:12:35 -0500 +Subject: [PATCH 53/81] 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 | 53 +++++++++++++------- + gui/simple-greeter/gdm-user-chooser-widget.c | 23 ++++++++- + .../fingerprint/gdm-fingerprint-extension.c | 2 - + 3 files changed, 56 insertions(+), 22 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index e137e1b..3d11fa7 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -1125,29 +1125,49 @@ 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); ++ ++ 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); ++ ++ switch_mode (login_window, MODE_AUTHENTICATION); ++} ++ ++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) { ++ g_debug ("GdmGreeterLoginWindow: user chosen '%s'", user_name); ++ 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)); ++ g_debug ("GdmGreeterLoginWindow: item chosen '%s'", item_id); + +- if (strcmp (user_name, GDM_USER_CHOOSER_USER_OTHER) == 0) { ++ 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); +- } 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_debug ("GdmGreeterLoginWindow: Starting auto login"); + g_signal_emit (login_window, signals[BEGIN_AUTO_LOGIN], 0, + login_window->priv->timed_login_username); + +@@ -1157,16 +1177,11 @@ 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); + } + ++ g_debug ("GdmGreeterLoginWindow: Switching to shrunken authentication mode"); + switch_mode (login_window, MODE_AUTHENTICATION); +- +- g_free (user_name); + } + + static void +@@ -1474,7 +1489,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 77e06a7..bff71e5 100644 +--- a/gui/simple-greeter/gdm-user-chooser-widget.c ++++ b/gui/simple-greeter/gdm-user-chooser-widget.c +@@ -269,9 +269,30 @@ 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; ++ + 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; ++ } ++ ++ gdm_chooser_widget_lookup_item (GDM_CHOOSER_WIDGET (widget), active_item_id, ++ NULL, NULL, NULL, NULL, NULL, ++ &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); ++ ++ 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 7aa99e7..316ef46 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.5.1 + + +From 5471f0fc6d996cf8b8bccd5bfc87b00aee5d8539 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 27 Feb 2009 15:44:13 -0500 +Subject: [PATCH 54/81] Initiate smart card auth when clicking on it in list + +--- + gui/simple-greeter/gdm-greeter-login-window.c | 24 ++++++++++++++++++++ + .../plugins/smartcard/gdm-smartcard-extension.c | 2 +- + 2 files changed, 25 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 3d11fa7..080a766 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -652,6 +652,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)); +@@ -1145,6 +1146,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)); +@@ -1178,6 +1180,28 @@ 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; ++ ++ 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); ++ g_free (item_id); ++ ++ gtk_widget_set_sensitive (login_window->priv->conversation_list, FALSE); + } + + g_debug ("GdmGreeterLoginWindow: Switching to shrunken authentication mode"); +diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c +index 25d5de4..a9e41f4 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.5.1 + + +From 9b1dd8920d77ac6eb29019dbeb0f7cc4dfa7d9f5 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 2 Mar 2009 11:10:28 -0500 +Subject: [PATCH 55/81] Only show task list if user is selected + +--- + gui/simple-greeter/gdm-greeter-login-window.c | 32 ++++++++++++++---------- + gui/simple-greeter/gdm-task-list.c | 11 +++++++- + 2 files changed, 28 insertions(+), 15 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 080a766..b578ac1 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -526,6 +526,7 @@ switch_mode (GdmGreeterLoginWindow *login_window, + const char *default_name; + GtkWidget *user_chooser; + GtkWidget *box; ++ int number_of_tasks; + + /* we want to run this even if we're supposed to + be in the mode already so that we reset everything +@@ -540,15 +541,23 @@ switch_mode (GdmGreeterLoginWindow *login_window, + + show_widget (login_window, "cancel-button", FALSE); + show_widget (login_window, "auth-page-box", FALSE); ++ show_widget (login_window, "conversation-list", FALSE); + + sensitize_widget (login_window, "disconnect-button", FALSE); + + default_name = NULL; + break; + case MODE_AUTHENTICATION: ++ gtk_widget_set_size_request (GTK_WIDGET (login_window), ++ GTK_WIDGET (login_window)->allocation.width, ++ -1); + show_widget (login_window, "cancel-button", TRUE); + show_widget (login_window, "disconnect-button", FALSE); + show_widget (login_window, "auth-page-box", TRUE); ++ ++ 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: +@@ -1163,11 +1172,14 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, + + if (strcmp (item_id, GDM_USER_CHOOSER_USER_OTHER) == 0) { + g_debug ("GdmGreeterLoginWindow: Starting all auth conversations"); ++ g_free (item_id); ++ + 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_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, +@@ -1180,6 +1192,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_AUTHENTICATION); + } else { + GdmTask *task; + +@@ -1194,18 +1208,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_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); ++ } + } + + static void +@@ -1537,7 +1550,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);*/ +@@ -2041,12 +2053,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.5.1 + + +From 3902afbcf465b15c6638b759c2ffece24f0b3f82 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 2 Mar 2009 13:53:34 -0500 +Subject: [PATCH 56/81] 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 | 135 +++++++++++++++++------- + 1 files changed, 95 insertions(+), 40 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index b578ac1..4314955 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -1110,6 +1110,17 @@ begin_task_verification (GdmTaskList *task_list, + return FALSE; + } + ++static void ++begin_verification (GdmGreeterLoginWindow *login_window) ++{ ++ 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 gboolean + begin_task_verification_for_selected_user (GdmTaskList *task_list, + GdmTask *task, +@@ -1135,6 +1146,15 @@ begin_task_verification_for_selected_user (GdmTaskList *task_list, + } + + 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) + { +@@ -1143,12 +1163,78 @@ on_user_chosen (GdmGreeterLoginWindow *login_window, + g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED], + 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) +- begin_task_verification_for_selected_user, +- login_window); ++ reset_task_if_not_given, ++ task); ++} ++ ++static void ++begin_single_service_verification (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); ++ ++ 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); ++ ++ reset_every_task_but_given_task (login_window, task); ++ g_object_unref (task); + } + + static void +@@ -1170,54 +1256,23 @@ on_user_chooser_activated (GdmUserChooserWidget *user_chooser, + item_id = gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (user_chooser)); + g_debug ("GdmGreeterLoginWindow: item chosen '%s'", item_id); + ++ g_signal_emit (G_OBJECT (login_window), signals[USER_SELECTED], ++ 0, item_id); ++ + if (strcmp (item_id, GDM_USER_CHOOSER_USER_OTHER) == 0) { + g_debug ("GdmGreeterLoginWindow: Starting all auth conversations"); + g_free (item_id); + +- 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); ++ 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_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); ++ g_debug ("GdmGreeterLoginWindow: Starting single auth conversation"); ++ begin_single_service_verification (login_window, item_id); + g_free (item_id); +- +- switch_mode (login_window, MODE_AUTHENTICATION); +- gdm_task_list_set_active_task (GDM_TASK_LIST (login_window->priv->conversation_list), task); +- +- g_object_unref (task); + } + } + +-- +1.6.5.1 + + +From e32a388bf163a1ff59e0d1aa850b19043150f5e7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 2 Mar 2009 13:57:34 -0500 +Subject: [PATCH 57/81] 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 4314955..12bda46 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -612,6 +612,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; ++ ++ 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, +@@ -717,10 +731,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))) { +@@ -749,10 +760,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)); +@@ -820,10 +828,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), +@@ -844,10 +849,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), +@@ -949,10 +951,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); ++ ++ task = find_task_with_service_name (login_window, service_name); + + if (task != NULL) { + gdm_conversation_ask_question (GDM_CONVERSATION (task), +@@ -980,10 +980,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), +@@ -1213,10 +1210,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.5.1 + + +From 1d866e5714a270c9192c70cc0ad1c61537700b61 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 2 Mar 2009 17:09:16 -0500 +Subject: [PATCH 58/81] 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 12bda46..38ec8d0 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -1929,7 +1929,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) +@@ -1940,7 +1940,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; ++ } ++ ++ /* 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), +@@ -1948,6 +1954,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); + } ++ ++ 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 ++ ++gboolean + gdm_conversation_choose_user (GdmConversation *conversation, + const char *username) + { +- g_signal_emit (conversation, signals [USER_CHOSEN], 0, username); ++ gboolean was_chosen; ++ ++ was_chosen = FALSE; ++ ++ g_signal_emit (conversation, signals [USER_CHOSEN], 0, username, &was_chosen); ++ ++ 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 a9e41f4..274132e 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); +- } ++ } ++ ++ if (extension->priv->select_when_ready) { ++ if (gdm_conversation_choose_user (GDM_CONVERSATION (extension), ++ PAMSERVICENAME)) { ++ extension->priv->select_when_ready = FALSE; ++ } ++ } + } + + char * +-- +1.6.5.1 + + +From 96713ef041fb14215eb062f4023e40a8ed62359a Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 13 Apr 2009 14:19:50 -0400 +Subject: [PATCH 59/81] reset all conversations if password conversation fails + +This is a temporary hack until we store plugin policy in +gconf. +--- + gui/simple-greeter/gdm-greeter-login-window.c | 10 ++++++++++ + 1 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 38ec8d0..8a72e9d 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -760,6 +760,16 @@ gdm_greeter_login_window_conversation_stopped (GdmGreeterLoginWindow *login_wind + + g_debug ("GdmGreeterLoginWindow: conversation '%s' has stopped", service_name); + ++ /* If the password conversation failed, then start over ++ * ++ * FIXME: we need to get this policy out of the source code ++ */ ++ if (strcmp (service_name, "gdm-password") == 0) { ++ g_debug ("GdmGreeterLoginWindow: main conversation failed, starting over"); ++ restart_conversations (login_window); ++ return TRUE; ++ } ++ + task = find_task_with_service_name (login_window, service_name); + + if (task != NULL) { +-- +1.6.5.1 + + +From 3a5dd5f7ac6eabf35677969127db238bc57afb23 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 21 Apr 2009 10:25:18 -0400 +Subject: [PATCH 60/81] When one PAM conversation wins, stop the others + +This doesn't work yet, it's still in progress code. +--- + daemon/gdm-session-direct.c | 64 ++++++++++++++++++++++++++++++------------- + daemon/gdm-simple-slave.c | 2 +- + 2 files changed, 46 insertions(+), 20 deletions(-) + +diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c +index 738267a..52a67c4 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -2258,6 +2258,40 @@ gdm_session_direct_open_session (GdmSession *session, + } + + static void ++stop_all_other_conversations (GdmSessionDirect *session, ++ GdmSessionConversation *conversation_to_keep) ++{ ++ GHashTableIter iter; ++ gpointer key, value; ++ ++ if (session->priv->conversations == NULL) { ++ return; ++ } ++ ++ if (conversation_to_keep == NULL) { ++ g_debug ("GdmSessionDirect: Stopping all conversations"); ++ } else { ++ g_debug ("GdmSessionDirect: Stopping all conversations " ++ "except for %s", conversation_to_keep->service_name); ++ } ++ ++ 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 == conversation_to_keep) { ++ continue; ++ } ++ ++ stop_conversation (conversation); ++ } ++ ++ g_hash_table_remove_all (session->priv->conversations); ++} ++ ++static void + gdm_session_direct_start_session (GdmSession *session, + const char *service_name) + { +@@ -2269,12 +2303,20 @@ gdm_session_direct_start_session (GdmSession *session, + g_return_if_fail (session != NULL); + g_return_if_fail (impl->priv->is_running == FALSE); + ++ conversation = find_conversation_by_name (impl, service_name); ++ ++ if (conversation == NULL) { ++ g_warning ("GdmSessionDirect: Tried to start session of " ++ "nonexistent conversation %s", service_name); ++ return; ++ } ++ ++ stop_all_other_conversations (impl, conversation); ++ + command = get_session_command (impl); + 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, conversation); + +@@ -2285,23 +2327,7 @@ gdm_session_direct_start_session (GdmSession *session, + 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); ++ stop_all_other_conversations (session, NULL); + } + + static void +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index 337718b..63ea82c 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -575,7 +575,7 @@ on_session_conversation_stopped (GdmSession *session, + gboolean res; + g_debug ("GdmSimpleSlave: conversation stopped"); + +- if (slave->priv->greeter_server != NULL) { ++ if (slave->priv->greeter != NULL) { + res = gdm_greeter_server_conversation_stopped (slave->priv->greeter_server, + service_name); + if (! res) { +-- +1.6.5.1 + + +From 6a2b392cd5b36c13035ffdb70701057b15c92a70 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 21 Apr 2009 15:30:28 -0400 +Subject: [PATCH 61/81] When one PAM conv. wins, actually stop the others + +We weren't properly keeping the winning conversation +around in the previous commit +--- + daemon/gdm-session-direct.c | 13 ++++++++++--- + 1 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c +index 52a67c4..7cc5511 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -2282,13 +2282,20 @@ stop_all_other_conversations (GdmSessionDirect *session, + conversation = (GdmSessionConversation *) value; + + if (conversation == conversation_to_keep) { +- continue; ++ g_hash_table_iter_steal (&iter); ++ g_free (key); ++ } else { ++ stop_conversation (conversation); + } +- +- stop_conversation (conversation); + } + + g_hash_table_remove_all (session->priv->conversations); ++ ++ if (conversation_to_keep != NULL) { ++ g_hash_table_insert (session->priv->conversations, ++ g_strdup (conversation_to_keep->service_name), ++ conversation_to_keep); ++ } + } + + static void +-- +1.6.5.1 + + +From 142f6a9c969526561b7bccb05d14c16bb6543540 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 24 Jul 2009 14:41:48 -0400 +Subject: [PATCH 62/81] KILL pam stack instead of TERM pam stack + +Some PAM modules are really slow to shut down. +We need to handle them being slow to shut down better, +(by not blocking login on them shutting down etc), but +in the mean time force them to die immediately. + +This is a temporary hack. +--- + 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 0327d77..d99b8a5 100644 +--- a/daemon/gdm-session-worker-job.c ++++ b/daemon/gdm-session-worker-job.c +@@ -320,7 +320,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); ++ res = gdm_signal_pid (session_worker_job->priv->pid, SIGKILL); + + if (res < 0) { + g_warning ("Unable to kill session worker process"); +-- +1.6.5.1 + + +From 03166ed45888420651008bc7be7c0d51b4397f94 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 21 Oct 2009 16:08:52 -0400 +Subject: [PATCH 63/81] Don't show tasklist for autologin + +--- + gui/simple-greeter/gdm-greeter-login-window.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 8a72e9d..4991cb1 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -1189,6 +1189,11 @@ begin_auto_login (GdmGreeterLoginWindow *login_window) + set_message (login_window, _("Select language and click Log In")); + + switch_mode (login_window, MODE_AUTHENTICATION); ++ ++ show_widget (login_window, "conversation-list", FALSE); ++ gdm_task_list_foreach_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ (GdmTaskListForeachFunc) reset_task, ++ login_window); + } + + static gboolean +-- +1.6.5.1 + + +From f8561b2383c343f2afb962e9ac77b58eac909b82 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 23 Oct 2009 17:39:19 -0400 +Subject: [PATCH 64/81] Drop the other hiding stuff for now. + +It depends on buttons being available that we don't have +in the multi-stack branch. +--- + gui/simple-greeter/gdm-user-chooser-widget.c | 8 +------- + 1 files changed, 1 insertions(+), 7 deletions(-) + +diff --git a/gui/simple-greeter/gdm-user-chooser-widget.c b/gui/simple-greeter/gdm-user-chooser-widget.c +index bff71e5..4d3c445 100644 +--- a/gui/simple-greeter/gdm-user-chooser-widget.c ++++ b/gui/simple-greeter/gdm-user-chooser-widget.c +@@ -140,13 +140,7 @@ update_other_user_visibility (GdmUserChooserWidget *widget) + return; + } + +- number_of_users = gdm_chooser_widget_get_number_of_items (GDM_CHOOSER_WIDGET (widget)); +- +- /* we hide the Other user if it's the last one, and we show it +- * if there's another user */ +- if (number_of_users == 1 && widget->priv->has_user_other) { +- remove_user_other (widget); +- } if (number_of_users >= 1 && !widget->priv->has_user_other) { ++ if (!widget->priv->has_user_other) { + add_user_other (widget); + } + } +-- +1.6.5.1 + + +From a1835572951be24cdaa15496708d502ef90e29ff Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 11:13:10 -0400 +Subject: [PATCH 65/81] Prevent start session signal handler from getting called multiple times + +It was causing a double free. +--- + 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 4991cb1..4e147ea 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -908,8 +908,17 @@ on_ready_to_start_session (GdmGreeterLoginWindow *login_window, + GParamSpec *param_spec, + char *service_name) + { ++ if (!login_window->priv->is_interactive) { ++ return; ++ } ++ + gdm_greeter_login_window_start_session_when_ready (login_window, service_name); + g_free (service_name); ++ ++ if (login_window->priv->start_session_handler_id > 0) { ++ g_signal_handler_disconnect (login_window, login_window->priv->start_session_handler_id); ++ login_window->priv->start_session_handler_id = 0; ++ } + } + + static void +-- +1.6.5.1 + + +From 258e9beb0536e6bebe2e6fff805d37d2ae652b06 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 13:57:53 -0400 +Subject: [PATCH 66/81] Don't show unimportant images on plugin buttons + +--- + gui/simple-greeter/gdm-greeter-login-window.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 4e147ea..0ec21a3 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -2016,8 +2016,14 @@ on_button_action_icon_name_changed (GtkWidget *button) + + action = gtk_widget_get_action (button); + +- image = gtk_action_create_icon (GTK_ACTION (action), GTK_ICON_SIZE_BUTTON); ++ if (gtk_action_get_is_important (action)) { ++ image = gtk_action_create_icon (GTK_ACTION (action), GTK_ICON_SIZE_BUTTON); ++ } else { ++ image = NULL; ++ } ++ + gtk_button_set_image (GTK_BUTTON (button), image); ++ + } + + static void +-- +1.6.5.1 + + +From c860fc44cf9d64c77418bcd68fc76b2afa1985e3 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 14:10:35 -0400 +Subject: [PATCH 67/81] Add visibility concept to task iface + +--- + gui/simple-greeter/libgdmsimplegreeter/gdm-task.c | 6 ++++++ + gui/simple-greeter/libgdmsimplegreeter/gdm-task.h | 2 ++ + 2 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c +index 05fd75c..858b1ef 100644 +--- a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c ++++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.c +@@ -94,6 +94,12 @@ gdm_task_is_choosable (GdmTask *task) + return GDM_TASK_GET_IFACE (task)->is_choosable (task); + } + ++gboolean ++gdm_task_is_visible (GdmTask *task) ++{ ++ return GDM_TASK_GET_IFACE (task)->is_visible (task); ++} ++ + 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 c75bf29..51e2b0a 100644 +--- a/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h ++++ b/gui/simple-greeter/libgdmsimplegreeter/gdm-task.h +@@ -45,6 +45,7 @@ struct _GdmTaskIface + char * (* get_description) (GdmTask *task); + char * (* get_name) (GdmTask *task); + gboolean (* is_choosable) (GdmTask *task); ++ gboolean (* is_visible) (GdmTask *task); + /* signals */ + void (* enabled) (GdmTask *task); + void (* disabled) (GdmTask *task); +@@ -59,6 +60,7 @@ void gdm_task_set_enabled (GdmTask *task, + gboolean should_enable); + gboolean gdm_task_is_enabled (GdmTask *task); + gboolean gdm_task_is_choosable (GdmTask *task); ++gboolean gdm_task_is_visible (GdmTask *task); + G_END_DECLS + + #endif /* __GDM_TASK_H */ +-- +1.6.5.1 + + +From 3422e1dad813487e78494ea4692fb3be9d61efda Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 14:10:50 -0400 +Subject: [PATCH 68/81] adapt fingerprint to task iface + +--- + .../fingerprint/gdm-fingerprint-extension.c | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c +index 316ef46..e1fc0ed 100644 +--- a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c ++++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c +@@ -194,6 +194,12 @@ gdm_fingerprint_extension_is_choosable (GdmTask *task) + return FALSE; + } + ++gboolean ++gdm_fingerprint_extension_is_visible (GdmTask *task) ++{ ++ return TRUE; ++} ++ + static void + gdm_task_iface_init (GdmTaskIface *iface) + { +@@ -201,6 +207,7 @@ gdm_task_iface_init (GdmTaskIface *iface) + iface->get_description = gdm_fingerprint_extension_get_description; + iface->get_name = gdm_fingerprint_extension_get_name; + iface->is_choosable = gdm_fingerprint_extension_is_choosable; ++ iface->is_visible = gdm_fingerprint_extension_is_visible; + } + + static void +-- +1.6.5.1 + + +From 7c1ab32679980a32fae94905d01cc822031e4bca Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 14:11:05 -0400 +Subject: [PATCH 69/81] adapt smartcard plugin to task iface + +--- + .../plugins/smartcard/gdm-smartcard-extension.c | 7 +++++++ + 1 files changed, 7 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 274132e..9967d5f 100644 +--- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c ++++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c +@@ -309,6 +309,12 @@ gdm_smartcard_extension_is_choosable (GdmTask *task) + return TRUE; + } + ++gboolean ++gdm_smartcard_extension_is_visible (GdmTask *task) ++{ ++ return TRUE; ++} ++ + static void + gdm_task_iface_init (GdmTaskIface *iface) + { +@@ -316,6 +322,7 @@ gdm_task_iface_init (GdmTaskIface *iface) + iface->get_description = gdm_smartcard_extension_get_description; + iface->get_name = gdm_smartcard_extension_get_name; + iface->is_choosable = gdm_smartcard_extension_is_choosable; ++ iface->is_visible = gdm_smartcard_extension_is_visible; + } + + static void +-- +1.6.5.1 + + +From 43803699c351da5ba35197cf7412cb959560e8a0 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 14:10:50 -0400 +Subject: [PATCH 70/81] adapt password to task iface + +--- + .../plugins/password/gdm-password-extension.c | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/plugins/password/gdm-password-extension.c b/gui/simple-greeter/plugins/password/gdm-password-extension.c +index 4922c65..255283e 100644 +--- a/gui/simple-greeter/plugins/password/gdm-password-extension.c ++++ b/gui/simple-greeter/plugins/password/gdm-password-extension.c +@@ -194,6 +194,12 @@ gdm_password_extension_is_choosable (GdmTask *task) + return FALSE; + } + ++gboolean ++gdm_password_extension_is_visible (GdmTask *task) ++{ ++ return TRUE; ++} ++ + static void + gdm_task_iface_init (GdmTaskIface *iface) + { +@@ -201,6 +207,7 @@ gdm_task_iface_init (GdmTaskIface *iface) + iface->get_description = gdm_password_extension_get_description; + iface->get_name = gdm_password_extension_get_name; + iface->is_choosable = gdm_password_extension_is_choosable; ++ iface->is_visible = gdm_password_extension_is_visible; + } + + static void +-- +1.6.5.1 + + +From d28601ec6717b9d352367593fccef27a6f2fdea9 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 16:05:14 -0400 +Subject: [PATCH 71/81] Return a different error code for "service won't work" than "auth failed" + +If we bubble it up to the greeter then we should be able to have +a more sensible UI when e.g. fingerprinting isn't enabled. +--- + daemon/gdm-session-worker.c | 12 ++++++++++-- + daemon/gdm-session-worker.h | 1 + + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index 9a9f364..35d6b2c 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -1291,7 +1291,7 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker, + */ + g_set_error (error, + GDM_SESSION_WORKER_ERROR, +- GDM_SESSION_WORKER_ERROR_AUTHENTICATING, ++ GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE, + _("error initiating conversation with authentication system - %s"), + error_code == PAM_ABORT? _("general failure") : + error_code == PAM_BUF_ERR? _("out of memory") : +@@ -1403,7 +1403,15 @@ gdm_session_worker_authenticate_user (GdmSessionWorker *worker, + /* blocking call, does the actual conversation */ + error_code = pam_authenticate (worker->priv->pam_handle, authentication_flags); + +- if (error_code != PAM_SUCCESS) { ++ if (error_code == PAM_AUTHINFO_UNAVAIL) { ++ g_debug ("GdmSessionWorker: authentication service unavailable"); ++ ++ g_set_error (error, ++ GDM_SESSION_WORKER_ERROR, ++ GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE, ++ "%s", pam_strerror (worker->priv->pam_handle, error_code)); ++ goto out; ++ } else if (error_code != PAM_SUCCESS) { + g_debug ("GdmSessionWorker: authentication returned %d: %s", error_code, pam_strerror (worker->priv->pam_handle, error_code)); + + g_set_error (error, +diff --git a/daemon/gdm-session-worker.h b/daemon/gdm-session-worker.h +index ee5465a..b1c8285 100644 +--- a/daemon/gdm-session-worker.h ++++ b/daemon/gdm-session-worker.h +@@ -41,6 +41,7 @@ typedef enum _GdmSessionWorkerError { + GDM_SESSION_WORKER_ERROR_OPENING_MESSAGE_PIPE, + GDM_SESSION_WORKER_ERROR_COMMUNICATING, + GDM_SESSION_WORKER_ERROR_WORKER_DIED, ++ GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE, + GDM_SESSION_WORKER_ERROR_AUTHENTICATING, + GDM_SESSION_WORKER_ERROR_AUTHORIZING, + GDM_SESSION_WORKER_ERROR_OPENING_LOG_FILE, +-- +1.6.5.1 + + +From 1d4ed3a5bbf11ef7211227bb9775c605b67f4e66 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 21:32:00 -0400 +Subject: [PATCH 72/81] Emit "service-unavailable" from session when pam service refuses to work + +--- + daemon/gdm-session-direct.c | 26 +++++++++++++++++++++++--- + daemon/gdm-session-private.h | 2 ++ + daemon/gdm-session-relay.c | 33 +++++++++++++++++++++++++++++++++ + daemon/gdm-session-worker.c | 29 ++++++++++++++++++++++------- + daemon/gdm-session.c | 21 +++++++++++++++++++++ + daemon/gdm-session.h | 2 ++ + 6 files changed, 103 insertions(+), 10 deletions(-) + +diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c +index 7cc5511..8a22409 100644 +--- a/daemon/gdm-session-direct.c ++++ b/daemon/gdm-session-direct.c +@@ -275,9 +275,27 @@ on_session_exited (GdmSession *session, + } + + static DBusHandlerResult +-gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, +- GdmSessionConversation *conversation, +- DBusMessage *message) ++gdm_session_direct_handle_service_unavailable (GdmSessionDirect *session, ++ GdmSessionConversation *conversation, ++ DBusMessage *message) ++{ ++ DBusMessage *reply; ++ ++ g_debug ("GdmSessionDirect: Emitting 'service-unavailable' signal"); ++ ++ reply = dbus_message_new_method_return (message); ++ dbus_connection_send (conversation->worker_connection, reply, NULL); ++ dbus_message_unref (reply); ++ ++ _gdm_session_service_unavailable (GDM_SESSION (session), conversation->service_name); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ ++static DBusHandlerResult ++gdm_session_direct_handle_setup_complete (GdmSessionDirect *session, ++ GdmSessionConversation *conversation, ++ DBusMessage *message) + { + DBusMessage *reply; + +@@ -1236,6 +1254,8 @@ session_worker_message (DBusConnection *connection, + return gdm_session_direct_handle_problem (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "CancelPendingQuery")) { + return gdm_session_direct_handle_cancel_pending_query (session, conversation, message); ++ } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ServiceUnavailable")) { ++ return gdm_session_direct_handle_service_unavailable (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupComplete")) { + return gdm_session_direct_handle_setup_complete (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupFailed")) { +diff --git a/daemon/gdm-session-private.h b/daemon/gdm-session-private.h +index 36781dd..e0a810e 100644 +--- a/daemon/gdm-session-private.h ++++ b/daemon/gdm-session-private.h +@@ -31,6 +31,8 @@ void _gdm_session_conversation_started (GdmSession *sessio + const char *service_name); + void _gdm_session_conversation_stopped (GdmSession *session, + const char *service_name); ++void _gdm_session_service_unavailable (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-relay.c b/daemon/gdm-session-relay.c +index 3bf8ed7..a933557 100644 +--- a/daemon/gdm-session-relay.c ++++ b/daemon/gdm-session-relay.c +@@ -463,6 +463,34 @@ handle_problem (GdmSessionRelay *session_relay, + } + + static DBusHandlerResult ++handle_service_unavailable (GdmSessionRelay *session_relay, ++ DBusConnection *connection, ++ DBusMessage *message) ++{ ++ DBusMessage *reply; ++ DBusError error; ++ char *service_name; ++ ++ dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &service_name, ++ DBUS_TYPE_INVALID)) { ++ g_warning ("ERROR: %s", error.message); ++ } ++ dbus_error_free (&error); ++ ++ g_debug ("GdmSessionRelay: ServiceUnavailable"); ++ ++ reply = dbus_message_new_method_return (message); ++ dbus_connection_send (connection, reply, NULL); ++ dbus_message_unref (reply); ++ ++ _gdm_session_service_unavailable (GDM_SESSION (session_relay), service_name); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ ++static DBusHandlerResult + handle_setup_complete (GdmSessionRelay *session_relay, + DBusConnection *connection, + DBusMessage *message) +@@ -841,6 +869,8 @@ session_handle_child_message (DBusConnection *connection, + return handle_info (session_relay, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Problem")) { + return handle_problem (session_relay, connection, message); ++ } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "ServiceUnavailable")) { ++ return handle_service_unavailable (session_relay, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SetupComplete")) { + return handle_setup_complete (session_relay, connection, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SetupFailed")) { +@@ -898,6 +928,9 @@ do_introspect (DBusConnection *connection, + " \n" + " \n" + " \n" ++ " \n" ++ " \n" ++ " \n" + " \n" + " \n" + " \n" +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index 35d6b2c..c4ad1c0 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -2353,9 +2353,16 @@ do_setup (GdmSessionWorker *worker) + worker->priv->display_device, + &error); + if (! res) { +- send_dbus_string_method (worker->priv->connection, +- "SetupFailed", +- error->message); ++ if (g_error_matches (error, ++ GDM_SESSION_WORKER_ERROR, ++ GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE)) { ++ send_dbus_void_method (worker->priv->connection, ++ "ServiceUnavailable"); ++ } else { ++ send_dbus_string_method (worker->priv->connection, ++ "SetupFailed", ++ error->message); ++ } + g_error_free (error); + return; + } +@@ -2376,10 +2383,18 @@ do_authenticate (GdmSessionWorker *worker) + worker->priv->password_is_required, + &error); + if (! res) { +- g_debug ("GdmSessionWorker: Unable to verify user"); +- send_dbus_string_method (worker->priv->connection, +- "AuthenticationFailed", +- error->message); ++ if (g_error_matches (error, ++ GDM_SESSION_WORKER_ERROR, ++ GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE)) { ++ g_debug ("GdmSessionWorker: Unable to use authentication service"); ++ send_dbus_void_method (worker->priv->connection, ++ "ServiceUnavailable"); ++ } else { ++ g_debug ("GdmSessionWorker: Unable to verify user"); ++ send_dbus_string_method (worker->priv->connection, ++ "AuthenticationFailed", ++ error->message); ++ } + g_error_free (error); + return; + } +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 8858071..8c4548a 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -31,6 +31,7 @@ + enum { + CONVERSATION_STARTED = 0, + CONVERSATION_STOPPED, ++ SERVICE_UNAVAILABLE, + SETUP_COMPLETE, + SETUP_FAILED, + RESET_COMPLETE, +@@ -251,6 +252,17 @@ gdm_session_class_init (gpointer g_iface) + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, G_TYPE_STRING); ++ signals [SERVICE_UNAVAILABLE] = ++ g_signal_new ("service-unavailable", ++ iface_type, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmSessionIface, service_unavailable), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, ++ 1, ++ G_TYPE_STRING); + signals [SETUP_COMPLETE] = + g_signal_new ("setup-complete", + iface_type, +@@ -525,6 +537,15 @@ gdm_session_class_init (gpointer g_iface) + } + + void ++_gdm_session_service_unavailable (GdmSession *session, ++ const char *service_name) ++{ ++ g_return_if_fail (GDM_IS_SESSION (session)); ++ ++ g_signal_emit (session, signals [SERVICE_UNAVAILABLE], 0, service_name); ++} ++ ++void + _gdm_session_setup_complete (GdmSession *session, + const char *service_name) + { +diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h +index 22c2ccb..9636b92 100644 +--- a/daemon/gdm-session.h ++++ b/daemon/gdm-session.h +@@ -49,6 +49,8 @@ struct _GdmSessionIface + const char *service_name); + void (* stop_conversation) (GdmSession *session, + const char *service_name); ++ void (* service_unavailable) (GdmSession *session, ++ const char *service_name); + void (* setup) (GdmSession *session, + const char *service_name); + void (* setup_for_user) (GdmSession *session, +-- +1.6.5.1 + + +From 0a51dbadadfb9695624ee14b5ec12574e9f647bf Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 21:38:52 -0400 +Subject: [PATCH 73/81] Bubble service-unavailable up to greeter + +--- + daemon/gdm-greeter-server.c | 8 ++++++++ + daemon/gdm-greeter-server.h | 2 ++ + daemon/gdm-simple-slave.c | 17 +++++++++++++++++ + 3 files changed, 27 insertions(+), 0 deletions(-) + +diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c +index ecb2ad6..1ae64a7 100644 +--- a/daemon/gdm-greeter-server.c ++++ b/daemon/gdm-greeter-server.c +@@ -285,6 +285,14 @@ gdm_greeter_server_problem (GdmGreeterServer *greeter_server, + } + + gboolean ++gdm_greeter_server_service_unavailable (GdmGreeterServer *greeter_server, ++ const char *service_name) ++{ ++ send_dbus_string_signal (greeter_server, "ServiceUnavailable", service_name); ++ return TRUE; ++} ++ ++gboolean + gdm_greeter_server_reset (GdmGreeterServer *greeter_server) + { + send_dbus_void_signal (greeter_server, "Reset"); +diff --git a/daemon/gdm-greeter-server.h b/daemon/gdm-greeter-server.h +index 976f0b7..c1da2f4 100644 +--- a/daemon/gdm-greeter-server.h ++++ b/daemon/gdm-greeter-server.h +@@ -93,6 +93,8 @@ gboolean gdm_greeter_server_info (GdmGreeterServer * + gboolean gdm_greeter_server_problem (GdmGreeterServer *greeter_server, + const char *service_name, + const char *text); ++gboolean gdm_greeter_server_service_unavailable (GdmGreeterServer *greeter_server, ++ const char *service_name); + gboolean gdm_greeter_server_reset (GdmGreeterServer *greeter_server); + gboolean gdm_greeter_server_ready (GdmGreeterServer *greeter_server, + const char *service_name); +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index 63ea82c..29d0aee 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -206,6 +206,19 @@ queue_greeter_reset (GdmSimpleSlave *slave) + } + + static void ++on_session_service_unavailable (GdmSession *session, ++ const char *service_name, ++ GdmSimpleSlave *slave) ++{ ++ if (slave->priv->greeter_server != NULL) { ++ gdm_greeter_server_service_unavailable (slave->priv->greeter_server, ++ service_name); ++ } ++ ++ gdm_session_stop_conversation (session, service_name); ++} ++ ++static void + on_session_setup_complete (GdmSession *session, + const char *service_name, + GdmSimpleSlave *slave) +@@ -677,6 +690,10 @@ create_new_session (GdmSimpleSlave *slave) + G_CALLBACK (on_session_conversation_stopped), + slave); + g_signal_connect (slave->priv->session, ++ "service-unavailable", ++ G_CALLBACK (on_session_service_unavailable), ++ slave); ++ g_signal_connect (slave->priv->session, + "setup-complete", + G_CALLBACK (on_session_setup_complete), + slave); +-- +1.6.5.1 + + +From ebf9fce3ff13743a65e14a65f6393cfc3cec4e0c Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 21:46:39 -0400 +Subject: [PATCH 74/81] Catch service-unavailable from server in client and propagate it + +--- + gui/simple-greeter/gdm-greeter-client.c | 20 ++++++++++++++++++++ + gui/simple-greeter/gdm-greeter-client.h | 2 ++ + 2 files changed, 22 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-client.c b/gui/simple-greeter/gdm-greeter-client.c +index a9321aa..57126fc 100644 +--- a/gui/simple-greeter/gdm-greeter-client.c ++++ b/gui/simple-greeter/gdm-greeter-client.c +@@ -63,6 +63,7 @@ enum { + PROBLEM, + INFO_QUERY, + SECRET_INFO_QUERY, ++ SERVICE_UNAVAILABLE, + READY, + CONVERSATION_STOPPED, + RESET, +@@ -264,6 +265,13 @@ on_problem (GdmGreeterClient *client, + } + + static void ++on_service_unavailable (GdmGreeterClient *client, ++ DBusMessage *message) ++{ ++ emit_string_signal_for_message (client, "ServiceUnavailable", message, SERVICE_UNAVAILABLE); ++} ++ ++static void + on_ready (GdmGreeterClient *client, + DBusMessage *message) + { +@@ -766,6 +774,8 @@ client_dbus_handle_message (DBusConnection *connection, + on_info (client, message); + } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "Problem")) { + on_problem (client, message); ++ } else if (dbus_message_is_signal (message, GREETER_SERVER_DBUS_INTERFACE, "ServiceUnavailable")) { ++ on_service_unavailable (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")) { +@@ -999,6 +1009,16 @@ gdm_greeter_client_class_init (GdmGreeterClientClass *klass) + 2, + G_TYPE_STRING, G_TYPE_STRING); + ++ gdm_greeter_client_signals[SERVICE_UNAVAILABLE] = ++ g_signal_new ("service-unavailable", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmGreeterClientClass, service_unavailable), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, 1, G_TYPE_STRING); ++ + gdm_greeter_client_signals[READY] = + g_signal_new ("ready", + 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 f879307..801bae4 100644 +--- a/gui/simple-greeter/gdm-greeter-client.h ++++ b/gui/simple-greeter/gdm-greeter-client.h +@@ -59,6 +59,8 @@ typedef struct + void (* problem) (GdmGreeterClient *client, + const char *service_name, + const char *problem); ++ void (* service_unavailable) (GdmGreeterClient *client, ++ const char *service_name); + void (* ready) (GdmGreeterClient *client, + const char *service_name); + void (* conversation_stopped) (GdmGreeterClient *client, +-- +1.6.5.1 + + +From 4e6491ba559c142189a0b17342db780b7a462d6c Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 22:04:44 -0400 +Subject: [PATCH 75/81] Fix memory handling of task in task list + +--- + 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 162b784..be50832 100644 +--- a/gui/simple-greeter/gdm-task-list.c ++++ b/gui/simple-greeter/gdm-task-list.c +@@ -203,7 +203,8 @@ gdm_task_list_add_task (GdmTaskList *task_list, + gtk_widget_show (button); + + gtk_container_add (GTK_CONTAINER (task_list->priv->box), button); +- task_list->priv->tasks = g_list_append (task_list->priv->tasks, task); ++ task_list->priv->tasks = g_list_append (task_list->priv->tasks, ++ g_object_ref (task)); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + g_signal_emit (task_list, signals[ACTIVATED], 0, task); +@@ -261,7 +262,7 @@ gdm_task_list_finalize (GObject *object) + + widget = GDM_TASK_LIST (object); + +- g_list_foreach (widget->priv->tasks, (GFunc) g_free, NULL); ++ g_list_foreach (widget->priv->tasks, (GFunc) g_object_unref, NULL); + g_list_free (widget->priv->tasks); + + G_OBJECT_CLASS (gdm_task_list_parent_class)->finalize (object); +-- +1.6.5.1 + + +From 7a609b6bc2e02c1afe47540dfb3daca37cd48cd1 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 22:09:45 -0400 +Subject: [PATCH 76/81] Add gdm_task_list_remove_task + +--- + gui/simple-greeter/gdm-task-list.c | 29 +++++++++++++++++++++++++++++ + gui/simple-greeter/gdm-task-list.h | 3 +++ + 2 files changed, 32 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c +index be50832..dd77ed6 100644 +--- a/gui/simple-greeter/gdm-task-list.c ++++ b/gui/simple-greeter/gdm-task-list.c +@@ -211,6 +211,35 @@ gdm_task_list_add_task (GdmTaskList *task_list, + } + } + ++void ++gdm_task_list_remove_task (GdmTaskList *task_list, ++ GdmTask *task) ++{ ++ GtkWidget *image; ++ GtkWidget *button; ++ GIcon *icon; ++ char *description; ++ ++ task_list->priv->tasks = g_list_remove (task_list->priv->tasks, task); ++ ++ button = g_object_get_data (G_OBJECT (task), "gdm-task-list-button"); ++ ++ if (button != NULL) { ++ g_signal_handlers_disconnect_by_func (G_OBJECT (task), ++ G_CALLBACK (on_task_enabled), ++ task_list); ++ g_signal_handlers_disconnect_by_func (G_OBJECT (task), ++ G_CALLBACK (on_task_disabled), ++ task_list); ++ gtk_widget_destroy (button); ++ g_object_set_data (G_OBJECT (task), "gdm-task-list-button", NULL); ++ } ++ ++ g_object_unref (task); ++ ++ activate_first_available_task (task_list); ++} ++ + static void + gdm_task_list_class_init (GdmTaskListClass *klass) + { +diff --git a/gui/simple-greeter/gdm-task-list.h b/gui/simple-greeter/gdm-task-list.h +index 8bc0c0e..3df5415 100644 +--- a/gui/simple-greeter/gdm-task-list.h ++++ b/gui/simple-greeter/gdm-task-list.h +@@ -74,6 +74,9 @@ GdmTask * gdm_task_list_foreach_task (GdmTaskList *widget, + void gdm_task_list_add_task (GdmTaskList *widget, + GdmTask *task); + ++void gdm_task_list_remove_task (GdmTaskList *widget, ++ GdmTask *task); ++ + int gdm_task_list_get_number_of_tasks (GdmTaskList *widget); + G_END_DECLS + +-- +1.6.5.1 + + +From 249388ea72690fe3526ff48797aaf0206d40a49c Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 21:58:44 -0400 +Subject: [PATCH 77/81] Remove task from task list if unavailable + +--- + gui/simple-greeter/gdm-greeter-login-window.c | 20 ++++++++++++++++++++ + gui/simple-greeter/gdm-greeter-login-window.h | 3 +++ + gui/simple-greeter/gdm-greeter-session.c | 14 ++++++++++++++ + 3 files changed, 37 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 0ec21a3..6a5b77e 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -872,6 +872,26 @@ gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, + return TRUE; + } + ++gboolean ++gdm_greeter_login_window_service_unavailable (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: service unavailable: %s", service_name); ++ ++ task = find_task_with_service_name (login_window, service_name); ++ ++ if (task != NULL) { ++ gdm_task_list_remove_task (GDM_TASK_LIST (login_window->priv->conversation_list), ++ task); ++ g_object_unref (task); ++ } ++ ++ return TRUE; ++} ++ + void + gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, + const char *username, +diff --git a/gui/simple-greeter/gdm-greeter-login-window.h b/gui/simple-greeter/gdm-greeter-login-window.h +index c312a47..041cbc4 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.h ++++ b/gui/simple-greeter/gdm-greeter-login-window.h +@@ -94,6 +94,9 @@ gboolean gdm_greeter_login_window_problem (GdmGreeterLogin + const char *service_name, + const char *text); + ++gboolean gdm_greeter_login_window_service_unavailable (GdmGreeterLoginWindow *login_window, ++ const char *service_name); ++ + void gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, + const char *username, + int delay); +diff --git a/gui/simple-greeter/gdm-greeter-session.c b/gui/simple-greeter/gdm-greeter-session.c +index 848ea1e..3bf24e8 100644 +--- a/gui/simple-greeter/gdm-greeter-session.c ++++ b/gui/simple-greeter/gdm-greeter-session.c +@@ -90,6 +90,16 @@ on_problem (GdmGreeterClient *client, + } + + static void ++on_service_unavailable (GdmGreeterClient *client, ++ const char *service_name, ++ GdmGreeterSession *session) ++{ ++ g_debug ("GdmGreeterSession: Service Unavailable: %s", service_name); ++ ++ gdm_greeter_login_window_service_unavailable (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), service_name); ++} ++ ++static void + on_ready (GdmGreeterClient *client, + const char *service_name, + GdmGreeterSession *session) +@@ -670,6 +680,10 @@ gdm_greeter_session_init (GdmGreeterSession *session) + G_CALLBACK (on_problem), + session); + g_signal_connect (session->priv->client, ++ "service-unavailable", ++ G_CALLBACK (on_service_unavailable), ++ session); ++ g_signal_connect (session->priv->client, + "ready", + G_CALLBACK (on_ready), + session); +-- +1.6.5.1 + + +From 1a44c10dda2b2cdab965cc15db392513aaafd339 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 28 Oct 2009 23:55:00 -0400 +Subject: [PATCH 78/81] Don't add task to UI if it's invisible + +--- + gui/simple-greeter/gdm-greeter-login-window.c | 14 +++++++++++--- + 1 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c +index 6a5b77e..9280d76 100644 +--- a/gui/simple-greeter/gdm-greeter-login-window.c ++++ b/gui/simple-greeter/gdm-greeter-login-window.c +@@ -2141,6 +2141,17 @@ gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, + + g_object_unref (actions); + ++ name = gdm_task_get_name (GDM_TASK (extension)); ++ description = gdm_task_get_description (GDM_TASK (extension)); ++ ++ if (!gdm_task_is_visible (GDM_TASK (extension))) { ++ g_debug ("GdmGreeterLoginWindow: new extension '%s - %s' won't be added", ++ name, description); ++ g_free (name); ++ g_free (description); ++ return; ++ } ++ + g_signal_connect_swapped (GDM_CONVERSATION (extension), + "answer", + G_CALLBACK (on_conversation_answer), +@@ -2154,9 +2165,6 @@ gdm_greeter_login_window_add_extension (GdmGreeterLoginWindow *login_window, + G_CALLBACK (on_conversation_chose_user), + 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); + +-- +1.6.5.1 + + +From 8bcb4b752b8d8efb62f9d4560de8076fbf2ed4bb Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 29 Oct 2009 00:39:20 -0400 +Subject: [PATCH 79/81] add lame check to see if fingerprint is enabled + +--- + .../fingerprint/gdm-fingerprint-extension.c | 35 +++++++++++++++++++- + 1 files changed, 34 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c +index e1fc0ed..b749ac1 100644 +--- a/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c ++++ b/gui/simple-greeter/plugins/fingerprint/gdm-fingerprint-extension.c +@@ -197,7 +197,40 @@ gdm_fingerprint_extension_is_choosable (GdmTask *task) + gboolean + gdm_fingerprint_extension_is_visible (GdmTask *task) + { +- return TRUE; ++ char *contents, **lines; ++ gboolean ret; ++ guint i; ++ ++ /* Stolen from gnome-about-me. ++ * ++ * FIXME: We should fix pam_fprintd to return authinfo_unavail instead of ++ * doing this distro specific hack. ++ */ ++ ++ if (g_file_get_contents ("/etc/sysconfig/authconfig", ++ &contents, NULL, NULL) == FALSE) ++ return FALSE; ++ ++ lines = g_strsplit (contents, "\n", -1); ++ g_free (contents); ++ ++ ret = FALSE; ++ ++ for (i = 0; lines[i] ; i++) { ++ if (g_str_has_prefix (lines[i], "USEFPRINTD=") != FALSE) { ++ char *value; ++ ++ value = lines[i] + strlen ("USEFPRINTD="); ++ if (g_strcmp0 (value, "yes") == 0) { ++ ret = TRUE; ++ break; ++ } ++ } ++ } ++ ++ g_strfreev (lines); ++ ++ return ret; + } + + static void +-- +1.6.5.1 + + +From f289a1f28d2000c00a35efa164cd207793be1b9f Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 29 Oct 2009 00:10:40 -0400 +Subject: [PATCH 80/81] don't activate invisible tasks + +--- + gui/simple-greeter/gdm-task-list.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/gui/simple-greeter/gdm-task-list.c b/gui/simple-greeter/gdm-task-list.c +index dd77ed6..c9d7451 100644 +--- a/gui/simple-greeter/gdm-task-list.c ++++ b/gui/simple-greeter/gdm-task-list.c +@@ -335,6 +335,10 @@ gdm_task_list_set_active_task (GdmTaskList *widget, + gboolean was_sensitive; + gboolean was_activated; + ++ if (!gdm_task_is_visible (task)) { ++ return FALSE; ++ } ++ + was_sensitive = GTK_WIDGET_SENSITIVE (widget); + gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE); + +-- +1.6.5.1 + + +From 8144b99a3ab9511d85ff6169ca9612c350010612 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 29 Oct 2009 00:46:34 -0400 +Subject: [PATCH 81/81] Add lame check for smart card daemon + +We don't want to show the smart card bits if the daemon isn't running + +This is just a temporary hack. We need a better solution. +--- + .../plugins/smartcard/gdm-smartcard-extension.c | 18 +++++++++++++++++- + 1 files changed, 17 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c +index 9967d5f..903e18d 100644 +--- a/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c ++++ b/gui/simple-greeter/plugins/smartcard/gdm-smartcard-extension.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -312,7 +313,22 @@ gdm_smartcard_extension_is_choosable (GdmTask *task) + gboolean + gdm_smartcard_extension_is_visible (GdmTask *task) + { +- return TRUE; ++ char *contents; ++ pid_t pid; ++ ++ if (g_file_get_contents ("/var/run/pcscd.pid", ++ &contents, NULL, NULL) == FALSE) { ++ return FALSE; ++ } ++ ++ pid = (pid_t) atoi (contents); ++ g_free (contents); ++ ++ if (pid == 0) { ++ return FALSE; ++ } ++ ++ return kill (pid, 0); + } + + static void +-- +1.6.5.1 + diff --git a/gdm-system-keyboard.patch b/gdm-system-keyboard.patch index c35cf19..b260199 100644 --- a/gdm-system-keyboard.patch +++ b/gdm-system-keyboard.patch @@ -1,17 +1,22 @@ -diff -up gdm-2.25.2/configure.ac.system-keyboard gdm-2.25.2/configure.ac ---- gdm-2.25.2/configure.ac.system-keyboard 2009-02-24 22:51:00.058815966 -0500 -+++ gdm-2.25.2/configure.ac 2009-02-24 22:51:00.154816109 -0500 -@@ -69,6 +69,7 @@ AC_SUBST(COMMON_LIBS) - PKG_CHECK_MODULES(DAEMON, +# +# Description: Get default keyboard layout from hal +# Ubuntu: https://bugs.launchpad.net/bugs/395103 +# Fedora: http://cvs.fedoraproject.org/viewvc//devel/gdm/gdm-system-keyboard.patch?view=markup +# +diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/configure.ac gdm-2.28.0.new/configure.ac +--- gdm-2.28.0/configure.ac 2009-09-21 22:06:40.000000000 +0200 ++++ gdm-2.28.0.new/configure.ac 2009-10-01 12:35:50.345762314 +0200 +@@ -70,6 +70,7 @@ dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION gobject-2.0 >= $GLIB_REQUIRED_VERSION -+ hal + gio-2.0 >= $GLIB_REQUIRED_VERSION ++ hal ) AC_SUBST(DAEMON_CFLAGS) AC_SUBST(DAEMON_LIBS) -diff -up gdm-2.25.2/daemon/gdm-session-direct.c.system-keyboard gdm-2.25.2/daemon/gdm-session-direct.c ---- gdm-2.25.2/daemon/gdm-session-direct.c.system-keyboard 2008-08-26 15:04:00.000000000 -0400 -+++ gdm-2.25.2/daemon/gdm-session-direct.c 2009-02-24 22:55:02.656566009 -0500 +diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/daemon/gdm-session-direct.c gdm-2.28.0.new/daemon/gdm-session-direct.c +--- gdm-2.28.0/daemon/gdm-session-direct.c 2009-09-21 22:05:27.000000000 +0200 ++++ gdm-2.28.0.new/daemon/gdm-session-direct.c 2009-10-01 12:34:43.000000000 +0200 @@ -45,6 +45,8 @@ #include #include @@ -21,7 +26,7 @@ diff -up gdm-2.25.2/daemon/gdm-session-direct.c.system-keyboard gdm-2.25.2/daemo #include "gdm-session-direct.h" #include "gdm-session.h" #include "gdm-session-private.h" -@@ -595,14 +597,66 @@ get_default_language_name (GdmSessionDir +@@ -598,14 +600,87 @@ return setlocale (LC_MESSAGES, NULL); } @@ -33,6 +38,7 @@ diff -up gdm-2.25.2/daemon/gdm-session-direct.c.system-keyboard gdm-2.25.2/daemo + char **devices; + int n_devices; + char *layout; ++ char *variant; + char *result; + + result = NULL; @@ -60,8 +66,27 @@ diff -up gdm-2.25.2/daemon/gdm-session-direct.c.system-keyboard gdm-2.25.2/daemo + "input.xkb.layout", + NULL); + } -+ result = g_strdup (layout); -+ libhal_free_string (layout); ++ if (!layout) ++ goto out; ++ ++ variant = libhal_device_get_property_string (ctx, ++ devices[0], ++ "input.x11_options.XkbVariant", ++ NULL); ++ if (!variant) { ++ variant = libhal_device_get_property_string (ctx, ++ devices[0], ++ "input.xkb.variant", ++ NULL); ++ } ++ ++ if (variant != NULL && variant[0] != '\0') { ++ result = g_strdup_printf("%s\t%s", layout, variant); ++ libhal_free_string (variant); ++ } else { ++ result = g_strdup (layout); ++ } ++ libhal_free_string (layout); + } + + libhal_free_string_array (devices); @@ -74,6 +99,7 @@ diff -up gdm-2.25.2/daemon/gdm-session-direct.c.system-keyboard gdm-2.25.2/daemo + result = g_strdup ("us"); + } + ++ g_debug ("GdmSessionDirect: System default keyboard layout: '%s'", result); + return result; +} + @@ -82,7 +108,7 @@ diff -up gdm-2.25.2/daemon/gdm-session-direct.c.system-keyboard gdm-2.25.2/daemo { - if (session->priv->saved_layout != NULL) { - return session->priv->saved_layout; -+ if (session->priv->saved_layout == NULL) { ++ if (!session->priv->saved_layout) { + session->priv->saved_layout = get_system_default_layout (session); } @@ -91,16 +117,3 @@ diff -up gdm-2.25.2/daemon/gdm-session-direct.c.system-keyboard gdm-2.25.2/daemo } static char * -diff -up gdm-2.25.2/daemon/gdm-session-settings.c.system-keyboard gdm-2.25.2/daemon/gdm-session-settings.c ---- gdm-2.25.2/daemon/gdm-session-settings.c.system-keyboard 2008-08-26 15:04:00.000000000 -0400 -+++ gdm-2.25.2/daemon/gdm-session-settings.c 2009-02-24 22:51:00.158815919 -0500 -@@ -149,8 +149,7 @@ gdm_session_settings_set_layout_name (Gd - { - g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings)); - -- if (settings->priv->layout_name == NULL || -- strcmp (settings->priv->layout_name, layout_name) != 0) { -+ if (g_strcmp0 (settings->priv->layout_name, layout_name) != 0) { - settings->priv->layout_name = g_strdup (layout_name); - g_object_notify (G_OBJECT (settings), "layout-name"); - } diff --git a/gdm.spec b/gdm.spec index 7852030..e03c548 100644 --- a/gdm.spec +++ b/gdm.spec @@ -15,8 +15,8 @@ Summary: The GNOME Display Manager Name: gdm -Version: 2.28.0 -Release: 5%{?dist} +Version: 2.28.1 +Release: 20%{?dist} Epoch: 1 License: GPLv2+ Group: User Interface/X @@ -95,17 +95,24 @@ Requires: audit-libs >= %{libauditver} Patch2: gdm-2.26.0-force-active-vt.patch Patch3: gdm-2.23.92-save-root-window.patch -# https://bugzilla.gnome.org/show_bug.cgi?id=596569 -Patch4: gdm-2.28.0-use-devicekit-power.patch - # uses /etc/sysconfig/keyboard and is thus not directly upstreamable # should probably be changed to get the system layout from the X server +# https://bugzilla.gnome.org/show_bug.cgi?id=572765 Patch13: gdm-system-keyboard.patch -Patch19: gdm-multistack.patch -Patch20: 0001-Fix-gdm_slave_get_timed_login_details.patch +Patch20: gdm-2.28.1-move-shutdown-functions.patch +Patch21: fix-clock.patch +Patch22: fix-timer.patch +Patch23: fix-na-tray.patch +Patch24: fix-computer-info.patch +Patch25: fix-run-dir-permissions.patch +Patch26: make-user-list-animation-smoother.patch +Patch27: 0001-Don-t-show-lock-screen-option-if-locked-down.patch +Patch96: gdm-multistack.patch # Fedora-specific +Patch97: gdm-bubble-location.patch +Patch98: tray-padding.patch Patch99: gdm-2.23.1-fedora-logo.patch %package user-switch-applet @@ -145,12 +152,20 @@ The GDM fingerprint plugin provides functionality necessary to use a fingerprint %setup -q %patch2 -p1 -b .force-active-vt %patch3 -p1 -b .save-root-window -%patch4 -p1 -b .use-devicekit-power %patch13 -p1 -b .system-keyboard -%patch19 -p1 -b .multistack -%patch20 -p1 -b .autologin +%patch20 -p1 -b .move-shutdown-functions +%patch21 -p1 -b .fix-clock +%patch22 -p1 -b .fix-timer +%patch23 -p1 -b .fix-na-tray +%patch24 -p1 -b .fix-computer-info +%patch25 -p1 -b .fix-run-dir-permission +%patch26 -p1 -b .make-user-list-animation-smoother +%patch27 -p1 -b .dont-show-lock-screen-if-locked-down +%patch96 -p1 -b .multistack +%patch97 -p1 -b .bubble-location +%patch98 -p1 -b .tray-padding %patch99 -p1 -b .fedora-logo autoreconf -i -f @@ -219,6 +234,8 @@ mkdir -p $RPM_BUILD_ROOT%{_datadir}/gdm/autostart/LoginWindow # temporarily manually copy this cp -f %{SOURCE10} $RPM_BUILD_ROOT%{_datadir}/gdm/autostart/LoginWindow/polkit-gnome-authentication-agent-1.desktop +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/gdm/greeter + rm -rf $RPM_BUILD_ROOT%{_localstatedir}/scrollkeeper find $RPM_BUILD_ROOT -name '*.a' -delete @@ -372,10 +389,12 @@ fi %config %{_datadir}/gdm/autostart/LoginWindow/* %dir %{_localstatedir}/log/gdm %dir %{_localstatedir}/spool/gdm +%dir %{_localstatedir}/run/gdm/greeter %attr(1770, gdm, gdm) %dir %{_localstatedir}/lib/gdm %attr(1750, gdm, gdm) %dir %{_localstatedir}/lib/gdm/.gconf.mandatory %attr(1640, gdm, gdm) %dir %{_localstatedir}/lib/gdm/.gconf.mandatory/*.xml %attr(1640, gdm, gdm) %dir %{_localstatedir}/lib/gdm/.gconf.path +%attr(1755, gdm, gdm) %dir %{_localstatedir}/run/gdm/greeter %attr(1770, root, gdm) %dir %{_localstatedir}/gdm %attr(1777, root, gdm) %dir %{_localstatedir}/run/gdm %attr(1755, root, gdm) %dir %{_localstatedir}/cache/gdm @@ -400,8 +419,87 @@ fi %{_libdir}/gdm/simple-greeter/plugins/fingerprint.so %changelog -* Wed Oct 07 2009 Ray Strode - 1:2.28.0-5 -- Fix xguest +* Sat Oct 31 2009 Matthias Clasen 2.28.1-20 +- Don't show 'Lock Screen' in the user switcher if locked down + +* Sat Oct 31 2009 Matthias Clasen 2.28.1-18 +- Actually set up statusicon padding + +* Fri Oct 30 2009 Ray Strode 2.28.1-17 +- Make the user list slide animation smoother + +* Thu Oct 29 2009 Ray Strode 2.28.1-16 +- Shrink autologin timer +- Make language dialog not double spaced + +* Thu Oct 29 2009 Ray Strode 2.28.1-15 +- Don't show fingerprint task button unless fingerprint is + enabled +- Don't show smartcard task button and list item unless + pcscd is running. + +* Wed Oct 28 2009 Ray Strode 2.28.1-14 +- Don't show image on login button + +* Wed Oct 28 2009 Ray Strode 2.28.1-13 +- Fix double free during user switching (might address + bug 512944) + +* Tue Oct 27 2009 Ray Strode 2.28.1-12 +- One more go at bug 527920 + +* Tue Oct 27 2009 Ray Strode 2.28.1-11 +- Tighten permissions on /var/run/gdm (bug 531063) + +* Mon Oct 26 2009 Ray Strode 2.28.1-10 +- Position shutdown menu properly on multihead machines + +* Fri Oct 23 2009 Ray Strode 2.28.1-9 +- Don't show hostname by default if it's localhost + +* Fri Oct 23 2009 Ray Strode 2.28.1-8 +- Attempt to fix crash some users see. +- Clean up rebase + +* Fri Oct 23 2009 Ray Strode 2.28.1-7 +- Show Other user even when there are no other users + (bug 527920) + +* Fri Oct 23 2009 Ray Strode 2.28.1-6 +- Properly read default keyboard layout (bug 530452) + +* Fri Oct 23 2009 Ray Strode 2.28.1-5 +- Remove tool tip from login button + +* Thu Oct 22 2009 Ray Strode 2.28.1-4 +- Fix autologin window spasms +- Fix autologin timer animation +- Make autologin and multistack play better together +- Add padding to notification tray + +* Wed Oct 21 2009 Ray Strode 2.28.1-3 +- Move date from panel to clock tooltip + +* Tue Oct 20 2009 Ray Strode 2.28.1-2 +- Move shutdown functions to panel from login window + +* Tue Oct 20 2009 Ray Strode 2.28.1-1 +- Update to 2.28.1 + +* Fri Oct 09 2009 Ray Strode 2.28.0-9 +- Fix Other... user. + +* Fri Oct 9 2009 Matthias Clasen - 1:2.28.0-8 +- Move bubbles to the lower right on the login screen + +* Wed Oct 07 2009 Ray Strode - 1:2.28.0-7 +- Fix gdm-password / xguest interaction (bug 524421) + +* Mon Oct 5 2009 Matthias Clasen - 1:2.28.4-6 +- Fix the autostart file for at-spi-registryd + +* Thu Oct 1 2009 Matthias Clasen - 1:2.28.4-5 +- Handle keyboard layout variants * Mon Sep 28 2009 Ray Strode - 1:2.28.0-4 - Add cache dir to package manifest diff --git a/make-user-list-animation-smoother.patch b/make-user-list-animation-smoother.patch new file mode 100644 index 0000000..102286d --- /dev/null +++ b/make-user-list-animation-smoother.patch @@ -0,0 +1,408 @@ +From 7980049944d064e803522aca8241256a62e90925 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 30 Oct 2009 11:18:13 -0400 +Subject: [PATCH 1/6] Fix typo in chooser grow code + +--- + gui/simple-greeter/gdm-chooser-widget.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c +index cbd5072..9347eee 100644 +--- a/gui/simple-greeter/gdm-chooser-widget.c ++++ b/gui/simple-greeter/gdm-chooser-widget.c +@@ -894,7 +894,7 @@ start_grow_animation (GdmChooserWidget *widget) + height = get_height_of_screen (widget); + } + gdm_scrollable_widget_slide_to_height (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), +- widget->priv->height_when_grown, ++ height, + (GdmScrollableWidgetSlideStepFunc) + on_grow_animation_step, widget, + (GdmScrollableWidgetSlideDoneFunc) +-- +1.6.5.1 + + +From e2cde131a24e2933588bed8c741ca14bb007c6eb Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 30 Oct 2009 12:13:32 -0400 +Subject: [PATCH 2/6] Don't start grow animation until chooser is loaded + +This makes it smoother when first starting up +--- + gui/simple-greeter/gdm-chooser-widget.c | 37 ++---------------------------- + 1 files changed, 3 insertions(+), 34 deletions(-) + +diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c +index 9347eee..1147104 100644 +--- a/gui/simple-greeter/gdm-chooser-widget.c ++++ b/gui/simple-greeter/gdm-chooser-widget.c +@@ -92,7 +92,6 @@ struct GdmChooserWidgetPrivate + + guint32 should_hide_inactive_items : 1; + guint32 emit_activated_after_resize_animation : 1; +- guint32 was_fully_grown : 1; + + GdmChooserWidgetPosition separator_position; + GdmChooserWidgetState state; +@@ -807,29 +806,12 @@ on_grow_animation_complete (GdmScrollableWidget *scrollable_widget, + { + g_assert (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_GROWING); + widget->priv->state = GDM_CHOOSER_WIDGET_STATE_GROWN; +- widget->priv->was_fully_grown = TRUE; + gtk_tree_view_set_enable_search (GTK_TREE_VIEW (widget->priv->items_view), TRUE); + + _grab_focus (GTK_WIDGET (widget)); + } + + static int +-get_height_of_screen (GdmChooserWidget *widget) +-{ +- GdkScreen *screen; +- GdkRectangle area; +- int monitor; +- +- screen = gtk_widget_get_screen (GTK_WIDGET (widget)); +- +- monitor = gdk_screen_get_monitor_at_window (screen, +- gdk_screen_get_root_window (screen)); +- gdk_screen_get_monitor_geometry (screen, monitor, &area); +- +- return area.height; +-} +- +-static int + get_number_of_on_screen_rows (GdmChooserWidget *widget) + { + GtkTreePath *start_path; +@@ -876,7 +858,6 @@ start_grow_animation (GdmChooserWidget *widget) + { + int number_of_visible_rows; + int number_of_rows; +- int height; + + number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); + number_of_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->list_store), NULL); +@@ -888,13 +869,8 @@ start_grow_animation (GdmChooserWidget *widget) + + set_inactive_items_visible (widget, TRUE); + +- if (widget->priv->was_fully_grown) { +- height = widget->priv->height_when_grown; +- } else { +- height = get_height_of_screen (widget); +- } + gdm_scrollable_widget_slide_to_height (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), +- height, ++ widget->priv->height_when_grown, + (GdmScrollableWidgetSlideStepFunc) + on_grow_animation_step, widget, + (GdmScrollableWidgetSlideDoneFunc) +@@ -912,7 +888,6 @@ skip_resize_animation (GdmChooserWidget *widget) + set_inactive_items_visible (GDM_CHOOSER_WIDGET (widget), TRUE); + gtk_tree_view_set_enable_search (GTK_TREE_VIEW (widget->priv->items_view), TRUE); + widget->priv->state = GDM_CHOOSER_WIDGET_STATE_GROWN; +- widget->priv->was_fully_grown = FALSE; + _grab_focus (GTK_WIDGET (widget)); + } + } +@@ -922,7 +897,6 @@ gdm_chooser_widget_grow (GdmChooserWidget *widget) + { + if (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_SHRINKING) { + gdm_scrollable_widget_stop_sliding (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget)); +- widget->priv->was_fully_grown = FALSE; + } + + gtk_alignment_set (GTK_ALIGNMENT (widget->priv->frame_alignment), +@@ -1233,9 +1207,7 @@ gdm_chooser_widget_size_allocate (GtkWidget *widget, + chooser_widget = GDM_CHOOSER_WIDGET (widget); + + if (chooser_widget->priv->state == GDM_CHOOSER_WIDGET_STATE_GROWN) { +- if (chooser_widget->priv->was_fully_grown) { +- chooser_widget->priv->height_when_grown = allocation->height; +- } ++ chooser_widget->priv->height_when_grown = allocation->height; + } + } + +@@ -1801,8 +1773,6 @@ gdm_chooser_widget_init (GdmChooserWidget *widget) + */ + GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); + +- widget->priv->height_when_grown = get_height_of_screen (widget); +- + gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 0, 0); + + add_frame (widget); +@@ -1935,9 +1905,7 @@ gdm_chooser_widget_init (GdmChooserWidget *widget) + gtk_tree_row_reference_free); + + add_separator (widget); +- + queue_column_visibility_update (widget); +- gdm_chooser_widget_grow (widget); + } + + static void +@@ -2544,5 +2512,6 @@ gdm_chooser_widget_propagate_pending_key_events (GdmChooserWidget *widget) + void + gdm_chooser_widget_loaded (GdmChooserWidget *widget) + { ++ gdm_chooser_widget_grow (widget); + g_signal_emit (widget, signals[LOADED], 0); + } +-- +1.6.5.1 + + +From 3f707bba808b3484be7380a11aebfadb2bc98ab6 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 30 Oct 2009 14:41:54 -0400 +Subject: [PATCH 3/6] Hide user list frame when list is empty. + +--- + gui/simple-greeter/gdm-chooser-widget.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c +index 1147104..4124195 100644 +--- a/gui/simple-greeter/gdm-chooser-widget.c ++++ b/gui/simple-greeter/gdm-chooser-widget.c +@@ -600,9 +600,9 @@ static void + update_chooser_visibility (GdmChooserWidget *widget) + { + if (gdm_chooser_widget_get_number_of_items (widget) > 0) { +- gtk_widget_show (widget->priv->scrollable_widget); ++ gtk_widget_show (widget->priv->frame); + } else { +- gtk_widget_hide (widget->priv->scrollable_widget); ++ gtk_widget_hide (widget->priv->frame); + } + g_object_notify (G_OBJECT (widget), "list-visible"); + } +-- +1.6.5.1 + + +From 6197ec180d369899bf4b87c5e8adaed62ed3fdeb Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 30 Oct 2009 14:52:04 -0400 +Subject: [PATCH 4/6] Dynamically slide destination from step function + +This lets us add items or swift directions while the animation is going. +--- + gui/simple-greeter/gdm-chooser-widget.c | 10 +++++----- + gui/simple-greeter/gdm-scrollable-widget.c | 19 ++++++++++++++++++- + gui/simple-greeter/gdm-scrollable-widget.h | 1 + + 3 files changed, 24 insertions(+), 6 deletions(-) + +diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c +index 4124195..4df03a6 100644 +--- a/gui/simple-greeter/gdm-chooser-widget.c ++++ b/gui/simple-greeter/gdm-chooser-widget.c +@@ -97,7 +97,6 @@ struct GdmChooserWidgetPrivate + GdmChooserWidgetState state; + + double active_row_normalized_position; +- int height_when_grown; + }; + + enum { +@@ -552,6 +551,7 @@ set_frame_text (GdmChooserWidget *widget, + static void + on_shrink_animation_step (GdmScrollableWidget *scrollable_widget, + double progress, ++ int *new_height, + GdmChooserWidget *widget) + { + GtkTreePath *active_row_path; +@@ -839,6 +839,7 @@ get_number_of_on_screen_rows (GdmChooserWidget *widget) + static void + on_grow_animation_step (GdmScrollableWidget *scrollable_widget, + double progress, ++ int *new_height, + GdmChooserWidget *widget) + { + int number_of_visible_rows; +@@ -851,6 +852,8 @@ on_grow_animation_step (GdmScrollableWidget *scrollable_widget, + gdm_scrollable_widget_stop_sliding (scrollable_widget); + return; + } ++ ++ *new_height = GTK_BIN (scrollable_widget)->child->requisition.height; + } + + static void +@@ -870,7 +873,7 @@ start_grow_animation (GdmChooserWidget *widget) + set_inactive_items_visible (widget, TRUE); + + gdm_scrollable_widget_slide_to_height (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), +- widget->priv->height_when_grown, ++ GTK_BIN (widget->priv->scrollable_widget)->child->requisition.height, + (GdmScrollableWidgetSlideStepFunc) + on_grow_animation_step, widget, + (GdmScrollableWidgetSlideDoneFunc) +@@ -1206,9 +1209,6 @@ gdm_chooser_widget_size_allocate (GtkWidget *widget, + + chooser_widget = GDM_CHOOSER_WIDGET (widget); + +- if (chooser_widget->priv->state == GDM_CHOOSER_WIDGET_STATE_GROWN) { +- chooser_widget->priv->height_when_grown = allocation->height; +- } + } + + static gboolean +diff --git a/gui/simple-greeter/gdm-scrollable-widget.c b/gui/simple-greeter/gdm-scrollable-widget.c +index 2c0407d..6d9dc83 100644 +--- a/gui/simple-greeter/gdm-scrollable-widget.c ++++ b/gui/simple-greeter/gdm-scrollable-widget.c +@@ -132,9 +132,26 @@ on_animation_tick (GdmScrollableWidgetAnimation *animation, + gtk_widget_set_size_request (animation->widget, width, height); + + if (animation->step_func != NULL) { ++ GdmTimer *timer; ++ ++ height = animation->desired_height; ++ ++ height -= animation->widget->style->ythickness * 2; ++ height -= GTK_CONTAINER (animation->widget)->border_width * 2; ++ ++ timer = g_object_ref (animation->timer); + animation->step_func (GDM_SCROLLABLE_WIDGET (animation->widget), + progress, ++ &height, + animation->step_func_user_data); ++ ++ if (gdm_timer_is_started (timer)) { ++ height += animation->widget->style->ythickness * 2; ++ height += GTK_CONTAINER (animation->widget)->border_width * 2; ++ ++ animation->desired_height = height; ++ } ++ g_object_unref (timer); + } + } + +@@ -708,7 +725,7 @@ gdm_scrollable_widget_slide_to_height (GdmScrollableWidget *scrollable_widget, + + if (!input_redirected || gdm_scrollable_widget_animations_are_disabled (scrollable_widget)) { + if (step_func != NULL) { +- step_func (scrollable_widget, 0.0, step_user_data); ++ step_func (scrollable_widget, 0.0, &height, step_user_data); + } + + if (done_func != NULL) { +diff --git a/gui/simple-greeter/gdm-scrollable-widget.h b/gui/simple-greeter/gdm-scrollable-widget.h +index 9b8877e..2241cb1 100644 +--- a/gui/simple-greeter/gdm-scrollable-widget.h ++++ b/gui/simple-greeter/gdm-scrollable-widget.h +@@ -40,6 +40,7 @@ typedef struct GdmScrollableWidget GdmScrollableWidget; + typedef struct GdmScrollableWidgetPrivate GdmScrollableWidgetPrivate; + typedef void (* GdmScrollableWidgetSlideStepFunc) (GdmScrollableWidget *scrollable_widget, + double progress, ++ int *new_height, + gpointer *user_data); + typedef void (* GdmScrollableWidgetSlideDoneFunc) (GdmScrollableWidget *scrollable_widget, + gpointer *user_data); +-- +1.6.5.1 + + +From a31d6dd70213fd3ab8572da2923b99fcbe5449a6 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 30 Oct 2009 14:47:45 -0400 +Subject: [PATCH 5/6] Drop checks for growing too far + +We're now very exact about where to grow so we don't need it. +--- + gui/simple-greeter/gdm-chooser-widget.c | 16 ---------------- + 1 files changed, 0 insertions(+), 16 deletions(-) + +diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c +index 4df03a6..6c29d23 100644 +--- a/gui/simple-greeter/gdm-chooser-widget.c ++++ b/gui/simple-greeter/gdm-chooser-widget.c +@@ -848,28 +848,12 @@ on_grow_animation_step (GdmScrollableWidget *scrollable_widget, + number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); + number_of_on_screen_rows = get_number_of_on_screen_rows (widget); + +- if (number_of_on_screen_rows >= number_of_visible_rows) { +- gdm_scrollable_widget_stop_sliding (scrollable_widget); +- return; +- } +- + *new_height = GTK_BIN (scrollable_widget)->child->requisition.height; + } + + static void + start_grow_animation (GdmChooserWidget *widget) + { +- int number_of_visible_rows; +- int number_of_rows; +- +- number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); +- number_of_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->list_store), NULL); +- +- if (number_of_visible_rows >= number_of_rows) { +- on_grow_animation_complete (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), widget); +- return; +- } +- + set_inactive_items_visible (widget, TRUE); + + gdm_scrollable_widget_slide_to_height (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), +-- +1.6.5.1 + + +From f685f9fe038d891026fce69a47a7ab7c3e438d37 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 30 Oct 2009 16:44:29 -0400 +Subject: [PATCH 6/6] Compute needs-scrollbar logic differently + +This way is a little clearer to read and seems to work +around a bug where the scrollbar gets shown briefly at +the end of an animation. +--- + gui/simple-greeter/gdm-scrollable-widget.c | 16 +++++++++++++--- + 1 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/gui/simple-greeter/gdm-scrollable-widget.c b/gui/simple-greeter/gdm-scrollable-widget.c +index 6d9dc83..d55013d 100644 +--- a/gui/simple-greeter/gdm-scrollable-widget.c ++++ b/gui/simple-greeter/gdm-scrollable-widget.c +@@ -252,7 +252,7 @@ gdm_scrollable_widget_animation_stop (GdmScrollableWidgetAnimation *animation) + static gboolean + gdm_scrollable_widget_needs_scrollbar (GdmScrollableWidget *widget) + { +- GtkAdjustment *adjustment; ++ gboolean needs_scrollbar; + + if (widget->priv->scrollbar == NULL) { + return FALSE; +@@ -266,9 +266,19 @@ gdm_scrollable_widget_needs_scrollbar (GdmScrollableWidget *widget) + return FALSE; + } + +- adjustment = gtk_range_get_adjustment (GTK_RANGE (widget->priv->scrollbar)); ++ if (GTK_BIN (widget)->child != NULL) { ++ GtkRequisition child_requisition; ++ int available_height; ++ ++ gtk_widget_get_child_requisition (GTK_BIN (widget)->child, ++ &child_requisition); ++ available_height = GTK_WIDGET (widget)->allocation.height; ++ needs_scrollbar = child_requisition.height > available_height; ++ } else { ++ needs_scrollbar = FALSE; ++ } + +- return adjustment->upper - adjustment->lower > adjustment->page_size; ++ return needs_scrollbar; + } + + static void +-- +1.6.5.1 + diff --git a/sources b/sources index 3ba58ac..41ab0e7 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -7724929a6b75ba269fd519d4a4995bbb gdm-2.28.0.tar.bz2 +917dc80f5ef6adcdc15193de238476db gdm-2.28.1.tar.bz2 diff --git a/tray-padding.patch b/tray-padding.patch new file mode 100644 index 0000000..d0c7039 --- /dev/null +++ b/tray-padding.patch @@ -0,0 +1,15 @@ +diff -up gdm-2.28.1/data/session-setup.entries.tray-padding gdm-2.28.1/data/session-setup.entries +--- gdm-2.28.1/data/session-setup.entries.tray-padding 2009-10-31 18:07:29.437799765 -0400 ++++ gdm-2.28.1/data/session-setup.entries 2009-10-31 18:08:20.758793871 -0400 +@@ -761,5 +761,11 @@ + bottom_right + + ++ ++ /apps/notification_area_applet/prefs/padding ++ ++ 3 ++ ++ + +