diff -u -r gdm-2.28.2.pristine/gui/simple-greeter/gdm-user.c gdm-2.28.2/gui/simple-greeter/gdm-user.c
--- gdm-2.28.2.pristine/gui/simple-greeter/gdm-user.c	2010-01-22 11:17:50.731384714 -0500
+++ gdm-2.28.2/gui/simple-greeter/gdm-user.c	2010-01-24 01:19:38.803538369 -0500
@@ -1,24 +1,27 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- * Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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
- */
+  *
+  * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
+  * Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu>
+  * 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
+  */
 
-#include <config.h>
+#define _XOPEN_SOURCE
+
+#include "config.h"
 
 #include <float.h>
 #include <string.h>
@@ -26,207 +29,179 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include <glib.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 #include <gtk/gtk.h>
 
-#include "gdm-user-manager.h"
-#include "gdm-user-private.h"
+#include <dbus/dbus-glib.h>
+
+#include "gdm-user.h"
 
-#define GDM_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_USER, GdmUserClass))
-#define GDM_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_USER))
+ #define GDM_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_USER, GdmUserClass))
+ #define GDM_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_USER))
 #define GDM_USER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), GDM_TYPE_USER, GdmUserClass))
 
-#define GLOBAL_FACEDIR    DATADIR "/faces"
-#define MAX_ICON_SIZE     128
 #define MAX_FILE_SIZE     65536
-#define MINIMAL_UID       100
-
-enum {
-        PROP_0,
-        PROP_MANAGER,
-        PROP_REAL_NAME,
-        PROP_DISPLAY_NAME,
-        PROP_USER_NAME,
-        PROP_UID,
-        PROP_HOME_DIR,
-        PROP_SHELL,
-        PROP_LOGIN_FREQUENCY,
-};
-
-enum {
-        ICON_CHANGED,
-        SESSIONS_CHANGED,
-        LAST_SIGNAL
-};
-
-struct _GdmUser {
-        GObject         parent;
-
-        GdmUserManager *manager;
 
+typedef struct {
         uid_t           uid;
-        char           *user_name;
-        char           *real_name;
-        char           *display_name;
-        char           *home_dir;
-        char           *shell;
-        GList          *sessions;
-        gulong          login_frequency;
-
-        GFileMonitor   *icon_monitor;
-};
+        gchar          *user_name;
+        gchar          *real_name;
+        gint            account_type;
+        gint            password_mode;
+        gchar          *password_hint;
+        gchar          *email;
+        gchar          *language;
+        gchar          *location;
+        guint64         login_frequency;
+        gchar          *icon_file;
+        gboolean        locked;
+        gboolean        automatic_login;
+} UserProperties;
 
-typedef struct _GdmUserClass
+static void
+collect_props (const gchar    *key,
+               const GValue   *value,
+               UserProperties *props)
 {
-        GObjectClass parent_class;
-
-        void (* icon_changed)     (GdmUser *user);
-        void (* sessions_changed) (GdmUser *user);
-} GdmUserClass;
-
-static void gdm_user_finalize     (GObject      *object);
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE (GdmUser, gdm_user, G_TYPE_OBJECT)
+        gboolean handled = TRUE;
 
-static int
-session_compare (const char *a,
-                 const char *b)
-{
-        if (a == NULL) {
-                return 1;
-        } else if (b == NULL) {
-                return -1;
+        if (strcmp (key, "Uid") == 0) {
+                props->uid = g_value_get_uint64 (value);
+        }
+        else if (strcmp (key, "UserName") == 0) {
+                props->user_name = g_value_dup_string (value);
+        }
+        else if (strcmp (key, "RealName") == 0) {
+                props->real_name = g_value_dup_string (value);
+        }
+        else if (strcmp (key, "AccountType") == 0) {
+                props->account_type = g_value_get_int (value);
+        }
+        else if (strcmp (key, "Email") == 0) {
+                props->email = g_value_dup_string (value);
+        }
+        else if (strcmp (key, "Language") == 0) {
+                props->language = g_value_dup_string (value);
+        }
+        else if (strcmp (key, "Location") == 0) {
+                props->location = g_value_dup_string (value);
+        }
+        else if (strcmp (key, "LoginFrequency") == 0) {
+                props->login_frequency = g_value_get_uint64 (value);
+        }
+        else if (strcmp (key, "IconFile") == 0) {
+                props->icon_file = g_value_dup_string (value);
+        }
+        else if (strcmp (key, "Locked") == 0) {
+                props->locked = g_value_get_boolean (value);
+        }
+        else if (strcmp (key, "AutomaticLogin") == 0) {
+                props->automatic_login = g_value_get_boolean (value);
+        }
+        else if (strcmp (key, "PasswordMode") == 0) {
+                props->password_mode = g_value_get_int (value);
+        }
+        else if (strcmp (key, "PasswordHint") == 0) {
+                props->password_hint = g_value_dup_string (value);
+        }
+        else if (strcmp (key, "HomeDirectory") == 0) {
+                /* ignore */
+        }
+        else if (strcmp (key, "Shell") == 0) {
+                /* ignore */
+        }
+        else {
+                handled = FALSE;
         }
 
-        return strcmp (a, b);
+        if (!handled)
+                g_debug ("unhandled property %s", key);
 }
 
-void
-_gdm_user_add_session (GdmUser    *user,
-                       const char *ssid)
+static void
+user_properties_free (UserProperties *props)
 {
-        GList *li;
-
-        g_return_if_fail (GDM_IS_USER (user));
-        g_return_if_fail (ssid != NULL);
-
-        li = g_list_find_custom (user->sessions, ssid, (GCompareFunc)session_compare);
-        if (li == NULL) {
-                g_debug ("GdmUser: adding session %s", ssid);
-                user->sessions = g_list_prepend (user->sessions, g_strdup (ssid));
-                g_signal_emit (user, signals[SESSIONS_CHANGED], 0);
-        } else {
-                g_debug ("GdmUser: session already present: %s", ssid);
-        }
+        g_free (props->user_name);
+        g_free (props->real_name);
+        g_free (props->password_hint);
+        g_free (props->email);
+        g_free (props->language);
+        g_free (props->location);
+        g_free (props->icon_file);
+        g_free (props);
 }
 
-void
-_gdm_user_remove_session (GdmUser    *user,
-                          const char *ssid)
+static UserProperties *
+user_properties_get (DBusGConnection *bus,
+                     const gchar     *object_path)
 {
-        GList *li;
+        UserProperties *props;
+        GError *error;
+        DBusGProxy *proxy;
+        GHashTable *hash_table;
 
-        g_return_if_fail (GDM_IS_USER (user));
-        g_return_if_fail (ssid != NULL);
+        props = g_new0 (UserProperties, 1);
 
-        li = g_list_find_custom (user->sessions, ssid, (GCompareFunc)session_compare);
-        if (li != NULL) {
-                g_debug ("GdmUser: removing session %s", ssid);
-                g_free (li->data);
-                user->sessions = g_list_delete_link (user->sessions, li);
-                g_signal_emit (user, signals[SESSIONS_CHANGED], 0);
-        } else {
-                g_debug ("GdmUser: session not found: %s", ssid);
+        proxy = dbus_g_proxy_new_for_name (bus,
+                                           "org.freedesktop.Accounts",
+                                           object_path,
+                                           "org.freedesktop.DBus.Properties");
+        error = NULL;
+        if (!dbus_g_proxy_call (proxy,
+                                "GetAll",
+                                &error,
+                                G_TYPE_STRING,
+                                "org.freedesktop.Accounts.User",
+                                G_TYPE_INVALID,
+                                dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+                                &hash_table,
+                                G_TYPE_INVALID)) {
+                g_debug ("Error calling GetAll() when retrieving properties for %s: %s", object_path, error->message);
+                g_error_free (error);
+                g_free (props);
+                props = NULL;
+                goto out;
         }
-}
+        g_hash_table_foreach (hash_table, (GHFunc) collect_props, props);
+        g_hash_table_unref (hash_table);
 
-guint
-gdm_user_get_num_sessions (GdmUser    *user)
-{
-        return g_list_length (user->sessions);
+ out:
+        g_object_unref (proxy);
+        return props;
 }
 
-GList *
-gdm_user_get_sessions (GdmUser *user)
-{
-        return user->sessions;
-}
 
-static void
-_gdm_user_set_login_frequency (GdmUser *user,
-                               gulong   login_frequency)
-{
-        user->login_frequency = login_frequency;
-        g_object_notify (G_OBJECT (user), "login-frequency");
-}
+struct _GdmUser {
+        GObject         parent;
 
-static void
-gdm_user_set_property (GObject      *object,
-                       guint         param_id,
-                       const GValue *value,
-                       GParamSpec   *pspec)
-{
-        GdmUser *user;
+        DBusGConnection *bus;
+        DBusGProxy      *proxy;
+        gchar           *object_path;
 
-        user = GDM_USER (object);
+        UserProperties  *props;
+        GList           *sessions;
 
-        switch (param_id) {
-        case PROP_MANAGER:
-                user->manager = g_value_get_object (value);
-                g_assert (user->manager);
-                break;
-        case PROP_LOGIN_FREQUENCY:
-                _gdm_user_set_login_frequency (user, g_value_get_ulong (value));
-                break;
-        default:
-                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-                break;
-        }
-}
+        gchar           *display_name;
+};
 
-static void
-gdm_user_get_property (GObject    *object,
-                       guint       param_id,
-                       GValue     *value,
-                       GParamSpec *pspec)
+typedef struct _GdmUserClass
 {
-        GdmUser *user;
+        GObjectClass parent_class;
+} GdmUserClass;
 
-        user = GDM_USER (object);
+enum {
+        CHANGED,
+        SESSIONS_CHANGED,
+        LAST_SIGNAL
+};
 
-        switch (param_id) {
-        case PROP_MANAGER:
-                g_value_set_object (value, user->manager);
-                break;
-        case PROP_USER_NAME:
-                g_value_set_string (value, user->user_name);
-                break;
-        case PROP_REAL_NAME:
-                g_value_set_string (value, user->real_name);
-                break;
-        case PROP_DISPLAY_NAME:
-                g_value_set_string (value, user->display_name);
-                break;
-        case PROP_HOME_DIR:
-                g_value_set_string (value, user->home_dir);
-                break;
-        case PROP_UID:
-                g_value_set_ulong (value, user->uid);
-                break;
-        case PROP_SHELL:
-                g_value_set_string (value, user->shell);
-                break;
-        case PROP_LOGIN_FREQUENCY:
-                g_value_set_ulong (value, user->login_frequency);
-                break;
-        default:
-                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-                break;
-        }
-}
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void gdm_user_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmUser, gdm_user, G_TYPE_OBJECT)
 
 static void
 gdm_user_class_init (GdmUserClass *class)
@@ -235,86 +210,20 @@
 
         gobject_class = G_OBJECT_CLASS (class);
 
-        gobject_class->set_property = gdm_user_set_property;
-        gobject_class->get_property = gdm_user_get_property;
         gobject_class->finalize = gdm_user_finalize;
 
-        g_object_class_install_property (gobject_class,
-                                         PROP_MANAGER,
-                                         g_param_spec_object ("manager",
-                                                              _("Manager"),
-                                                              _("The user manager object this user is controlled by."),
-                                                              GDM_TYPE_USER_MANAGER,
-                                                              (G_PARAM_READWRITE |
-                                                               G_PARAM_CONSTRUCT_ONLY)));
-
-        g_object_class_install_property (gobject_class,
-                                         PROP_REAL_NAME,
-                                         g_param_spec_string ("real-name",
-                                                              "Real Name",
-                                                              "The real name to display for this user.",
-                                                              NULL,
-                                                              G_PARAM_READABLE));
-
-        g_object_class_install_property (gobject_class,
-                                         PROP_DISPLAY_NAME,
-                                         g_param_spec_string ("display-name",
-                                                              "Display Name",
-                                                              "The unique name to display for this user.",
-                                                              NULL,
-                                                              G_PARAM_READABLE));
-
-        g_object_class_install_property (gobject_class,
-                                         PROP_UID,
-                                         g_param_spec_ulong ("uid",
-                                                             "User ID",
-                                                             "The UID for this user.",
-                                                             0, G_MAXULONG, 0,
-                                                             G_PARAM_READABLE));
-        g_object_class_install_property (gobject_class,
-                                         PROP_USER_NAME,
-                                         g_param_spec_string ("user-name",
-                                                              "User Name",
-                                                              "The login name for this user.",
-                                                              NULL,
-                                                              G_PARAM_READABLE));
-        g_object_class_install_property (gobject_class,
-                                         PROP_HOME_DIR,
-                                         g_param_spec_string ("home-directory",
-                                                              "Home Directory",
-                                                              "The home directory for this user.",
-                                                              NULL,
-                                                              G_PARAM_READABLE));
-        g_object_class_install_property (gobject_class,
-                                         PROP_SHELL,
-                                         g_param_spec_string ("shell",
-                                                              "Shell",
-                                                              "The shell for this user.",
-                                                              NULL,
-                                                              G_PARAM_READABLE));
-        g_object_class_install_property (gobject_class,
-                                         PROP_LOGIN_FREQUENCY,
-                                         g_param_spec_ulong ("login-frequency",
-                                                             "login frequency",
-                                                             "login frequency",
-                                                             0,
-                                                             G_MAXULONG,
-                                                             0,
-                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
-        signals [ICON_CHANGED] =
-                g_signal_new ("icon-changed",
-                              G_TYPE_FROM_CLASS (class),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdmUserClass, icon_changed),
-                              NULL, NULL,
-                              g_cclosure_marshal_VOID__VOID,
-                              G_TYPE_NONE, 0);
+        signals[CHANGED] = g_signal_new ("changed",
+                                         G_TYPE_FROM_CLASS (class),
+                                         G_SIGNAL_RUN_LAST,
+                                         0,
+                                         NULL, NULL,
+                                         g_cclosure_marshal_VOID__VOID,
+                                         G_TYPE_NONE, 0);
         signals [SESSIONS_CHANGED] =
                 g_signal_new ("sessions-changed",
                               G_TYPE_FROM_CLASS (class),
                               G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdmUserClass, sessions_changed),
+                              0,
                               NULL, NULL,
                               g_cclosure_marshal_VOID__VOID,
                               G_TYPE_NONE, 0);
@@ -322,67 +231,8 @@
 
 
 static void
-on_icon_monitor_changed (GFileMonitor     *monitor,
-                         GFile            *file,
-                         GFile            *other_file,
-                         GFileMonitorEvent event_type,
-                         GdmUser          *user)
-{
-        g_debug ("Icon changed: %d", event_type);
-
-        if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
-            event_type != G_FILE_MONITOR_EVENT_CREATED) {
-                return;
-        }
-
-        _gdm_user_icon_changed (user);
-}
-
-static void
-update_icon_monitor (GdmUser *user)
-{
-        GFile  *file;
-        GError *error;
-        char   *path;
-
-        if (user->home_dir == NULL) {
-                return;
-        }
-
-        if (user->icon_monitor != NULL) {
-                g_file_monitor_cancel (user->icon_monitor);
-                user->icon_monitor = NULL;
-        }
-
-        path = g_build_filename (user->home_dir, ".face", NULL);
-        g_debug ("adding monitor for '%s'", path);
-        file = g_file_new_for_path (path);
-        error = NULL;
-        user->icon_monitor = g_file_monitor_file (file,
-                                                  G_FILE_MONITOR_NONE,
-                                                  NULL,
-                                                  &error);
-        if (user->icon_monitor != NULL) {
-                g_signal_connect (user->icon_monitor,
-                                  "changed",
-                                  G_CALLBACK (on_icon_monitor_changed),
-                                  user);
-        } else {
-                g_warning ("Unable to monitor %s: %s", path, error->message);
-                g_error_free (error);
-        }
-        g_object_unref (file);
-        g_free (path);
-}
-
-static void
 gdm_user_init (GdmUser *user)
 {
-        user->manager = NULL;
-        user->user_name = NULL;
-        user->real_name = NULL;
-        user->display_name = NULL;
-        user->sessions = NULL;
 }
 
 static void
@@ -392,265 +242,59 @@
 
         user = GDM_USER (object);
 
-        g_file_monitor_cancel (user->icon_monitor);
-
-        g_free (user->user_name);
-        g_free (user->real_name);
-        g_free (user->display_name);
-
-        if (G_OBJECT_CLASS (gdm_user_parent_class)->finalize)
-                (*G_OBJECT_CLASS (gdm_user_parent_class)->finalize) (object);
-}
-
-/**
- * _gdm_user_update:
- * @user: the user object to update.
- * @pwent: the user data to use.
- *
- * Updates the properties of @user using the data in @pwent.
- *
- * Since: 1.0
- **/
-void
-_gdm_user_update (GdmUser             *user,
-                  const struct passwd *pwent)
-{
-        gchar *real_name = NULL;
-
-        g_return_if_fail (GDM_IS_USER (user));
-        g_return_if_fail (pwent != NULL);
-
-        g_object_freeze_notify (G_OBJECT (user));
+        dbus_g_connection_unref (user->bus);
+        g_free (user->object_path);
 
-        /* Display Name */
-        if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0') {
-                gchar *first_comma = NULL;
-                gchar *valid_utf8_name = NULL;
-
-                if (g_utf8_validate (pwent->pw_gecos, -1, NULL)) {
-                        valid_utf8_name = pwent->pw_gecos;
-                        first_comma = g_utf8_strchr (valid_utf8_name, -1, ',');
-                } else {
-                        g_warning ("User %s has invalid UTF-8 in GECOS field. "
-                                   "It would be a good thing to check /etc/passwd.",
-                                   pwent->pw_name ? pwent->pw_name : "");
-                }
+        if (user->proxy != NULL)
+                g_object_unref (user->proxy);
 
-                if (first_comma) {
-                        real_name = g_strndup (valid_utf8_name,
-                                                  (first_comma - valid_utf8_name));
-                } else if (valid_utf8_name) {
-                        real_name = g_strdup (valid_utf8_name);
-                } else {
-                        real_name = NULL;
-                }
+        if (user->props != NULL)
+                user_properties_free (user->props);
 
-                if (real_name && real_name[0] == '\0') {
-                        g_free (real_name);
-                        real_name = NULL;
-                }
-        } else {
-                real_name = NULL;
-        }
-
-        if ((real_name && !user->real_name) ||
-            (!real_name && user->real_name) ||
-            (real_name &&
-             user->real_name &&
-             strcmp (real_name, user->real_name) != 0)) {
-                g_free (user->real_name);
-                user->real_name = real_name;
-                g_object_notify (G_OBJECT (user), "real-name");
-        } else {
-                g_free (real_name);
-        }
-
-        /* Unique Display Name */
-        if ((!user->real_name && user->display_name) ||
-            (user->real_name &&
-             user->display_name &&
-             strncmp (user->real_name, user->display_name, strlen (user->real_name)) != 0)) {
-                g_free (user->display_name);
-                user->display_name = NULL;
-                g_object_notify (G_OBJECT (user), "display-name");
-        }
-
-        /* UID */
-        if (pwent->pw_uid != user->uid) {
-                user->uid = pwent->pw_uid;
-                g_object_notify (G_OBJECT (user), "uid");
-        }
-
-        /* Username */
-        if ((pwent->pw_name && !user->user_name) ||
-            (!pwent->pw_name && user->user_name) ||
-            (pwent->pw_name &&
-             user->user_name &&
-             strcmp (user->user_name, pwent->pw_name) != 0)) {
-                g_free (user->user_name);
-                user->user_name = g_strdup (pwent->pw_name);
-                g_object_notify (G_OBJECT (user), "user-name");
-        }
-
-        /* Home Directory */
-        if ((pwent->pw_dir && !user->home_dir) ||
-            (!pwent->pw_dir && user->home_dir) ||
-            strcmp (user->home_dir, pwent->pw_dir) != 0) {
-                g_free (user->home_dir);
-                user->home_dir = g_strdup (pwent->pw_dir);
-                g_object_notify (G_OBJECT (user), "home-directory");
-                g_signal_emit (user, signals[ICON_CHANGED], 0);
-        }
-
-        /* Shell */
-        if ((pwent->pw_shell && !user->shell) ||
-            (!pwent->pw_shell && user->shell) ||
-            (pwent->pw_shell &&
-             user->shell &&
-             strcmp (user->shell, pwent->pw_shell) != 0)) {
-                g_free (user->shell);
-                user->shell = g_strdup (pwent->pw_shell);
-                g_object_notify (G_OBJECT (user), "shell");
-        }
-
-        update_icon_monitor (user);
-
-        g_object_thaw_notify (G_OBJECT (user));
-}
-
-/**
- * _gdm_user_icon_changed:
- * @user: the user to emit the signal for.
- *
- * Emits the "icon-changed" signal for @user.
- *
- * Since: 1.0
- **/
-void
-_gdm_user_icon_changed (GdmUser *user)
-{
-        g_return_if_fail (GDM_IS_USER (user));
+        g_free (user->display_name);
 
-        g_signal_emit (user, signals[ICON_CHANGED], 0);
+        (*G_OBJECT_CLASS (gdm_user_parent_class)->finalize) (object);
 }
 
-/**
- * gdm_user_get_uid:
- * @user: the user object to examine.
- *
- * Retrieves the ID of @user.
- *
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- *
- * Since: 1.0
- **/
-
 uid_t
 gdm_user_get_uid (GdmUser *user)
 {
         g_return_val_if_fail (GDM_IS_USER (user), -1);
 
-        return user->uid;
+        return user->props->uid;
 }
 
-/**
- * gdm_user_get_real_name:
- * @user: the user object to examine.
- *
- * Retrieves the display name of @user.
- *
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- *
- * Since: 1.0
- **/
-G_CONST_RETURN gchar *
+const gchar *
 gdm_user_get_real_name (GdmUser *user)
 {
         g_return_val_if_fail (GDM_IS_USER (user), NULL);
 
-        return (user->real_name ? user->real_name : user->user_name);
+        return user->props->real_name;
 }
 
-/**
- * gdm_user_get_display_name:
- * @user: the user object to examine.
- *
- * Retrieves the unique display name of @user.
- *
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- *
- * Since: 1.0
- **/
-G_CONST_RETURN gchar *
+const gchar *
 gdm_user_get_display_name (GdmUser *user)
 {
         g_return_val_if_fail (GDM_IS_USER (user), NULL);
 
-        return (user->display_name ? user->display_name
-                : gdm_user_get_real_name (user));
+       return user->display_name ? user->display_name
+                                 : user->props->real_name;
 }
 
-/**
- * gdm_user_get_user_name:
- * @user: the user object to examine.
- *
- * Retrieves the login name of @user.
- *
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- *
- * Since: 1.0
- **/
-
-G_CONST_RETURN gchar *
+const gchar *
 gdm_user_get_user_name (GdmUser *user)
 {
         g_return_val_if_fail (GDM_IS_USER (user), NULL);
 
-        return user->user_name;
+        return user->props->user_name;
 }
 
-/**
- * gdm_user_get_home_directory:
- * @user: the user object to examine.
- *
- * Retrieves the home directory of @user.
- *
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- *
- * Since: 1.0
- **/
-
-G_CONST_RETURN gchar *
-gdm_user_get_home_directory (GdmUser *user)
+gint
+gdm_user_get_account_type (GdmUser *user)
 {
-        g_return_val_if_fail (GDM_IS_USER (user), NULL);
-
-        return user->home_dir;
-}
-
-/**
- * gdm_user_get_shell:
- * @user: the user object to examine.
- *
- * Retrieves the login shell of @user.
- *
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- *
- * Since: 1.0
- **/
-
-G_CONST_RETURN gchar *
-gdm_user_get_shell (GdmUser *user)
-{
-        g_return_val_if_fail (GDM_IS_USER (user), NULL);
+        g_return_val_if_fail (GDM_IS_USER (user), 0);
 
-        return user->shell;
+        return user->props->account_type;
 }
 
 gulong
@@ -658,66 +302,10 @@
 {
         g_return_val_if_fail (GDM_IS_USER (user), 0);
 
-        return user->login_frequency;
+        return user->props->login_frequency;
 }
 
-/**
- * _gdm_user_show_full_display_name:
- * @user: the user object to examine.
- *
- * Updates the unique display name of @user to "Real Name (username)".
- *
- * Since: 1.0
- **/
-void
-_gdm_user_show_full_display_name (GdmUser *user)
-{
-        char *uniq_name;
-
-        g_return_if_fail (GDM_IS_USER (user));
-
-        if (user->real_name != NULL) {
-                uniq_name = g_strdup_printf ("%s (%s)",
-                                             user->real_name,
-                                             user->user_name);
-        } else {
-                uniq_name = NULL;
-        }
-
-        if ((user->real_name && !user->display_name) ||
-            (!user->real_name && user->display_name) ||
-            (user->real_name &&
-             user->display_name &&
-             strcmp (uniq_name, user->display_name) != 0)) {
-                g_free (user->display_name);
-                user->display_name = uniq_name;
-                g_object_notify (G_OBJECT (user), "display-name");
-        } else {
-                g_free (uniq_name);
-        }
-}
-
-/**
- * _gdm_user_show_short_display_name:
- * @user: the user object to examine.
- *
- * Resets the unique display name of @user.
- *
- * Since: 1.0
- **/
-void
-_gdm_user_show_short_display_name (GdmUser *user)
-{
-        g_return_if_fail (GDM_IS_USER (user));
-
-        if (user->display_name) {
-                g_free (user->display_name);
-                user->display_name = NULL;
-                g_object_notify (G_OBJECT (user), "display-name");
-        }
-}
-
-int
+gint
 gdm_user_collate (GdmUser *user1,
                   GdmUser *user2)
 {
@@ -729,21 +317,8 @@
         g_return_val_if_fail (GDM_IS_USER (user1), 0);
         g_return_val_if_fail (GDM_IS_USER (user2), 0);
 
-        if (user1->real_name != NULL) {
-                str1 = user1->real_name;
-        } else {
-                str1 = user1->user_name;
-        }
-
-        if (user2->real_name != NULL) {
-                str2 = user2->real_name;
-        } else {
-                str2 = user2->user_name;
-        }
-
-        num1 = user1->login_frequency;
-        num2 = user2->login_frequency;
-        g_debug ("Login freq 1=%u 2=%u", (guint)num1, (guint)num2);
+        num1 = user1->props->login_frequency;
+        num2 = user2->props->login_frequency;
         if (num1 > num2) {
                 return -1;
         }
@@ -753,6 +328,18 @@
         }
 
         /* if login frequency is equal try names */
+        if (user1->props->real_name != NULL) {
+                str1 = user1->props->real_name;
+        } else {
+                str1 = user1->props->user_name;
+        }
+
+        if (user2->props->real_name != NULL) {
+                str2 = user2->props->real_name;
+        } else {
+                str2 = user2->props->user_name;
+        }
+
         if (str1 == NULL && str2 != NULL) {
                 return -1;
         }
@@ -799,66 +386,6 @@
         return TRUE;
 }
 
-static char *
-get_filesystem_type (const char *path)
-{
-        GFile      *file;
-        GFileInfo  *file_info;
-        GError     *error;
-        char       *filesystem_type;
-
-        file = g_file_new_for_path (path);
-        error = NULL;
-        file_info = g_file_query_filesystem_info (file,
-                                                  G_FILE_ATTRIBUTE_FILESYSTEM_TYPE,
-                                                  NULL,
-                                                  &error);
-        if (file_info == NULL) {
-                g_warning ("Unable to query filesystem type for %s: %s", path, error->message);
-                g_error_free (error);
-                g_object_unref (file);
-                return NULL;
-        }
-
-        filesystem_type = g_strdup (g_file_info_get_attribute_string (file_info,
-                                                                      G_FILE_ATTRIBUTE_FILESYSTEM_TYPE));
-        if (filesystem_type == NULL) {
-                g_warning ("GIO returned NULL filesystem type for %s", path);
-        }
-
-        g_object_unref (file);
-        g_object_unref (file_info);
-
-        return filesystem_type;
-}
-
-static GdkPixbuf *
-render_icon_from_cache (GdmUser *user,
-                        int      icon_size)
-{
-        GdkPixbuf  *retval;
-        char       *path;
-        gboolean    is_autofs;
-        gboolean    res;
-        char       *filesystem_type;
-
-        path = g_build_filename (GDM_CACHE_DIR, user->user_name, "face", NULL);
-        res = check_user_file (path,
-                               MAX_FILE_SIZE);
-        if (res) {
-                retval = gdk_pixbuf_new_from_file_at_size (path,
-                                                           icon_size,
-                                                           icon_size,
-                                                           NULL);
-        } else {
-                g_debug ("Could not access face icon %s", path);
-                retval = NULL;
-        }
-        g_free (path);
-
-        return retval;
-}
-
 static void
 curved_rectangle (cairo_t *cr,
                   double   x0,
@@ -1092,62 +619,51 @@
 
 GdkPixbuf *
 gdm_user_render_icon (GdmUser   *user,
-                      gint       icon_size)
+                     gboolean  with_frame,
+                     gint      icon_size)
 {
         GdkPixbuf    *pixbuf;
         GdkPixbuf    *framed;
-        char         *path;
-        char         *tmp;
         gboolean      res;
+        GError       *error;
 
         g_return_val_if_fail (GDM_IS_USER (user), NULL);
         g_return_val_if_fail (icon_size > 12, NULL);
 
-        path = NULL;
+        pixbuf = NULL;
+        if (user->props->icon_file) {
+                res = check_user_file (user->props->icon_file,
+                                       MAX_FILE_SIZE);
+                if (res) {
+                        pixbuf = gdk_pixbuf_new_from_file_at_size (user->props->icon_file,
+                                                                   icon_size,
+                                                                   icon_size,
+                                                                   NULL);
+                }
+                else {
+                        pixbuf = NULL;
+                }
+        }
 
-        pixbuf = render_icon_from_cache (user, icon_size);
         if (pixbuf != NULL) {
                 goto out;
         }
 
-        /* Try ${GlobalFaceDir}/${username} */
-        path = g_build_filename (GLOBAL_FACEDIR, user->user_name, NULL);
-        res = check_user_file (path,
-                               MAX_FILE_SIZE);
-        if (res) {
-                pixbuf = gdk_pixbuf_new_from_file_at_size (path,
-                                                           icon_size,
-                                                           icon_size,
-                                                           NULL);
-        } else {
-                g_debug ("Could not access global face icon %s", path);
-                pixbuf = NULL;
-        }
+        error = NULL;
+        pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
 
-        g_free (path);
-        if (pixbuf != NULL) {
-                goto out;
+                                           "stock_person",
+                                           icon_size,
+                                           GTK_ICON_LOOKUP_FORCE_SIZE,
+                                           &error);
+        if (error) {
+                g_warning ("%s", error->message);
+                g_error_free (error);
         }
 
-        /* Finally, ${GlobalFaceDir}/${username}.png */
-        tmp = g_strconcat (user->user_name, ".png", NULL);
-        path = g_build_filename (GLOBAL_FACEDIR, tmp, NULL);
-        g_free (tmp);
-        res = check_user_file (path,
-                               MAX_FILE_SIZE);
-        if (res) {
-                pixbuf = gdk_pixbuf_new_from_file_at_size (path,
-                                                           icon_size,
-                                                           icon_size,
-                                                           NULL);
-        } else {
-                g_debug ("Could not access global face icon %s", path);
-                pixbuf = NULL;
-        }
-        g_free (path);
  out:
 
-        if (pixbuf != NULL) {
+        if (pixbuf != NULL && with_frame) {
                 framed = frame_pixbuf (pixbuf);
                 if (framed != NULL) {
                         g_object_unref (pixbuf);
@@ -1157,3 +673,232 @@
 
         return pixbuf;
 }
+
+const gchar *
+gdm_user_get_email (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), NULL);
+
+        return user->props->email;
+}
+
+const gchar *
+gdm_user_get_language (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), NULL);
+
+        if (*user->props->language == '\0')
+                return NULL;
+        return user->props->language;
+}
+
+const gchar *
+gdm_user_get_location (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), NULL);
+
+        return user->props->location;
+}
+
+gint
+gdm_user_get_password_mode (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), 0);
+
+        return user->props->password_mode;
+}
+
+const char *
+gdm_user_get_password_hint (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), NULL);
+
+        return user->props->password_hint;
+}
+
+const char *
+gdm_user_get_icon_file (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), NULL);
+
+        return user->props->icon_file;
+}
+
+gboolean
+gdm_user_get_automatic_login (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), FALSE);
+
+        return user->props->automatic_login;
+}
+
+const gchar *
+gdm_user_get_object_path (GdmUser *user)
+{
+        g_return_val_if_fail (GDM_IS_USER (user), NULL);
+
+        return user->object_path;
+}
+
+static gboolean
+update_info (GdmUser *user)
+{
+        UserProperties *props;
+
+        props = user_properties_get (user->bus, user->object_path);
+        if (props != NULL) {
+                if (user->props != NULL)
+                        user_properties_free (user->props);
+                user->props = props;
+                return TRUE;
+        }
+        else {
+                return FALSE;
+        }
+}
+
+static void
+changed_handler (DBusGProxy *proxy,
+                 gpointer   *data)
+{
+        GdmUser *user = GDM_USER (data);
+
+        if (update_info (user)) {
+                g_signal_emit (user, signals[CHANGED], 0);
+        }
+}
+
+GdmUser *
+gdm_user_new_from_object_path (const gchar *object_path)
+{
+        GdmUser *user;
+        GError *error;
+
+        user = (GdmUser *)g_object_new (GDM_TYPE_USER, NULL);
+        user->object_path = g_strdup (object_path);
+
+        error = NULL;
+        user->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (user->bus == NULL) {
+                g_warning ("Couldn't connect to system bus: %s", error->message);
+                goto error;
+        }
+
+        user->proxy = dbus_g_proxy_new_for_name (user->bus,
+                                                 "org.freedesktop.Accounts",
+                                                 user->object_path,
+                                                 "org.freedesktop.Accounts.User");
+        dbus_g_proxy_set_default_timeout (user->proxy, INT_MAX);
+        dbus_g_proxy_add_signal (user->proxy, "Changed", G_TYPE_INVALID);
+
+        dbus_g_proxy_connect_signal (user->proxy, "Changed",
+                                     G_CALLBACK (changed_handler), user, NULL);
+
+        if (!update_info (user))
+                goto error;
+
+        return user;
+
+ error:
+        g_object_unref (user);
+        return NULL;
+}
+
+gboolean
+gdm_user_is_logged_in (GdmUser *user)
+{
+        return user->sessions != NULL;
+}
+
+static int
+session_compare (const char *a,
+                 const char *b)
+{
+        if (a == NULL) {
+                return 1;
+        } else if (b == NULL) {
+                return -1;
+        }
+
+        return strcmp (a, b);
+}
+
+void
+_gdm_user_add_session (GdmUser    *user,
+                       const char *ssid)
+{
+        GList *li;
+
+        g_return_if_fail (GDM_IS_USER (user));
+        g_return_if_fail (ssid != NULL);
+
+        li = g_list_find_custom (user->sessions, ssid, (GCompareFunc)session_compare);
+        if (li == NULL) {
+                g_debug ("GdmUser: adding session %s", ssid);
+                user->sessions = g_list_prepend (user->sessions, g_strdup (ssid));
+                g_signal_emit (user, signals[SESSIONS_CHANGED], 0);
+        } else {
+                g_debug ("GdmUser: session already present: %s", ssid);
+        }
+}
+
+void
+_gdm_user_remove_session (GdmUser    *user,
+                          const char *ssid)
+{
+        GList *li;
+
+        g_return_if_fail (GDM_IS_USER (user));
+        g_return_if_fail (ssid != NULL);
+
+        li = g_list_find_custom (user->sessions, ssid, (GCompareFunc)session_compare);
+        if (li != NULL) {
+                g_debug ("GdmUser: removing session %s", ssid);
+                g_free (li->data);
+                user->sessions = g_list_delete_link (user->sessions, li);
+                g_signal_emit (user, signals[SESSIONS_CHANGED], 0);
+        } else {
+                g_debug ("GdmUser: session not found: %s", ssid);
+        }
+}
+
+guint
+gdm_user_get_num_sessions (GdmUser    *user)
+{
+        return g_list_length (user->sessions);
+}
+
+void
+_gdm_user_show_full_display_name (GdmUser *user)
+{
+        char *uniq_name;
+
+        g_return_if_fail (GDM_IS_USER (user));
+
+        if (user->props->real_name != NULL) {
+                uniq_name = g_strdup_printf ("%s (%s)",
+                                             user->props->real_name,
+                                             user->props->user_name);
+        } else {
+                uniq_name = NULL;
+        }
+
+        if (uniq_name && g_strcmp0 (uniq_name, user->display_name) != 0) {
+                g_free (user->display_name);
+                user->display_name = uniq_name;
+        }
+        else {
+                g_free (uniq_name);
+        }
+}
+
+void
+_gdm_user_show_short_display_name (GdmUser *user)
+{
+        g_return_if_fail (GDM_IS_USER (user));
+
+        if (user->display_name) {
+                g_free (user->display_name);
+                user->display_name = NULL;
+        }
+}
diff -u -r gdm-2.28.2.pristine/gui/simple-greeter/gdm-user-chooser-widget.c gdm-2.28.2/gui/simple-greeter/gdm-user-chooser-widget.c
--- gdm-2.28.2.pristine/gui/simple-greeter/gdm-user-chooser-widget.c	2010-01-22 11:17:50.380384095 -0500
+++ gdm-2.28.2/gui/simple-greeter/gdm-user-chooser-widget.c	2010-01-23 21:24:57.782789151 -0500
@@ -130,8 +130,6 @@
 static void
 update_other_user_visibility (GdmUserChooserWidget *widget)
 {
-        int number_of_users;
-
         if (!widget->priv->show_user_other) {
                 if (widget->priv->has_user_other) {
                         remove_user_other (widget);
@@ -392,7 +390,7 @@
         }
 
         size = get_icon_height_for_widget (GTK_WIDGET (widget));
-        pixbuf = gdm_user_render_icon (user, size);
+        pixbuf = gdm_user_render_icon (user, TRUE, size);
         if (pixbuf == NULL && widget->priv->stock_person_pixbuf != NULL) {
                 pixbuf = g_object_ref (widget->priv->stock_person_pixbuf);
         }
@@ -400,7 +398,7 @@
         tooltip = g_strdup_printf (_("Log in as %s"),
                                    gdm_user_get_user_name (user));
 
-        is_logged_in = gdm_user_get_num_sessions (user) > 0;
+        is_logged_in = gdm_user_is_logged_in (user);
 
         g_debug ("GdmUserChooserWidget: User added name:%s logged-in:%d pixbuf:%p",
                  gdm_user_get_user_name (user),
@@ -458,6 +456,55 @@
 }
 
 static void
+on_user_changed (GdmUserManager       *manager,
+                 GdmUser              *user,
+                 GdmUserChooserWidget *widget)
+{
+        GdkPixbuf    *pixbuf;
+        char         *tooltip;
+        gboolean      is_logged_in;
+        int           size;
+
+        /* wait for all users to be loaded */
+        if (! widget->priv->loaded) {
+                return;
+        }
+        if (!widget->priv->show_normal_users) {
+                return;
+        }
+
+        size = get_icon_height_for_widget (GTK_WIDGET (widget));
+        pixbuf = gdm_user_render_icon (user, TRUE, size);
+        if (pixbuf == NULL && widget->priv->stock_person_pixbuf != NULL) {
+                pixbuf = g_object_ref (widget->priv->stock_person_pixbuf);
+        }
+
+        tooltip = g_strdup_printf (_("Log in as %s"),
+                                   gdm_user_get_user_name (user));
+
+        is_logged_in = gdm_user_is_logged_in (user);
+
+        g_debug ("GdmUserChooserWidget: User added name:%s logged-in:%d pixbuf:%p",
+                 gdm_user_get_user_name (user),
+                 is_logged_in,
+                 pixbuf);
+
+        gdm_chooser_widget_update_item (GDM_CHOOSER_WIDGET (widget),
+                                        gdm_user_get_user_name (user),
+                                        pixbuf,
+                                        gdm_user_get_display_name (user),
+                                        tooltip,
+                                        gdm_user_get_login_frequency (user),
+                                        is_logged_in,
+                                        FALSE);
+        g_free (tooltip);
+
+        if (pixbuf != NULL) {
+                g_object_unref (pixbuf);
+        }
+}
+
+static void
 on_user_is_logged_in_changed (GdmUserManager       *manager,
                               GdmUser              *user,
                               GdmUserChooserWidget *widget)
@@ -468,7 +515,7 @@
         g_debug ("GdmUserChooserWidget: User logged in changed: %s", gdm_user_get_user_name (user));
 
         user_name = gdm_user_get_user_name (user);
-        is_logged_in = gdm_user_get_num_sessions (user) > 0;
+        is_logged_in = gdm_user_is_logged_in (user);
 
         gdm_chooser_widget_set_item_in_use (GDM_CHOOSER_WIDGET (widget),
                                             user_name,
@@ -533,6 +580,10 @@
                                   G_CALLBACK (on_user_removed),
                                   widget);
                 g_signal_connect (widget->priv->manager,
+                                  "user-changed",
+                                  G_CALLBACK (on_user_changed),
+                                  widget);
+                g_signal_connect (widget->priv->manager,
                                   "users-loaded",
                                   G_CALLBACK (on_users_loaded),
                                   widget);
diff -u -r gdm-2.28.2.pristine/gui/simple-greeter/gdm-user.h gdm-2.28.2/gui/simple-greeter/gdm-user.h
--- gdm-2.28.2.pristine/gui/simple-greeter/gdm-user.h	2010-01-22 11:17:50.819429703 -0500
+++ gdm-2.28.2/gui/simple-greeter/gdm-user.h	2010-01-24 00:16:21.332539155 -0500
@@ -23,7 +23,7 @@
  */
 
 #ifndef __GDM_USER__
-#define __GDM_USER__ 1
+#define __GDM_USER__
 
 #include <sys/types.h>
 #include <gtk/gtk.h>
@@ -37,23 +37,36 @@
 
 typedef struct _GdmUser GdmUser;
 
-GType                 gdm_user_get_type            (void) G_GNUC_CONST;
+GType          gdm_user_get_type            (void) G_GNUC_CONST;
 
-uid_t                 gdm_user_get_uid             (GdmUser   *user);
-G_CONST_RETURN char  *gdm_user_get_user_name       (GdmUser   *user);
-G_CONST_RETURN char  *gdm_user_get_real_name       (GdmUser   *user);
-G_CONST_RETURN char  *gdm_user_get_display_name    (GdmUser   *user);
-G_CONST_RETURN char  *gdm_user_get_home_directory  (GdmUser   *user);
-G_CONST_RETURN char  *gdm_user_get_shell           (GdmUser   *user);
-guint                 gdm_user_get_num_sessions    (GdmUser   *user);
-GList                *gdm_user_get_sessions        (GdmUser   *user);
-gulong                gdm_user_get_login_frequency (GdmUser   *user);
+GdmUser        *gdm_user_new_from_object_path (const gchar *path);
+const gchar   *gdm_user_get_object_path      (GdmUser *user);
 
-GdkPixbuf            *gdm_user_render_icon         (GdmUser   *user,
-                                                    gint       icon_size);
-
-gint                  gdm_user_collate             (GdmUser   *user1,
-                                                    GdmUser   *user2);
+uid_t          gdm_user_get_uid             (GdmUser   *user);
+const gchar   *gdm_user_get_user_name       (GdmUser   *user);
+const gchar   *gdm_user_get_display_name    (GdmUser   *user);
+const gchar   *gdm_user_get_real_name       (GdmUser   *user);
+const gchar   *gdm_user_get_display_name    (GdmUser   *user);
+gint           gdm_user_get_account_type    (GdmUser   *user);
+const gchar   *gdm_user_get_email           (GdmUser   *user);
+const gchar   *gdm_user_get_language        (GdmUser   *user);
+const gchar   *gdm_user_get_location        (GdmUser   *user);
+const gchar   *gdm_user_get_home_directory  (GdmUser   *user);
+const gchar   *gdm_user_get_shell           (GdmUser   *user);
+gulong         gdm_user_get_login_frequency (GdmUser   *user);
+gint           gdm_user_get_password_mode   (GdmUser   *user);
+const gchar   *gdm_user_get_password_hint   (GdmUser   *user);
+const gchar   *gdm_user_get_icon_file       (GdmUser   *user);
+gboolean       gdm_user_get_automatic_login (GdmUser   *user);
+
+gboolean       gdm_user_is_logged_in        (GdmUser   *user);
+guint          gdm_user_get_num_sessions    (GdmUser   *user);
+
+GdkPixbuf     *gdm_user_render_icon         (GdmUser   *user,
+                                            gboolean  framed,
+                                            gint      icon_size);
+gint           gdm_user_collate             (GdmUser   *user1,
+                                            GdmUser   *user2);
 
 G_END_DECLS
 
diff -u -r gdm-2.28.2.pristine/gui/simple-greeter/gdm-user-manager.c gdm-2.28.2/gui/simple-greeter/gdm-user-manager.c
--- gdm-2.28.2.pristine/gui/simple-greeter/gdm-user-manager.c	2010-01-22 11:17:50.731384714 -0500
+++ gdm-2.28.2/gui/simple-greeter/gdm-user-manager.c	2010-01-24 16:57:33.169124287 -0500
@@ -1,10 +1,10 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu>
+ * Copyright (C) 2009-2010 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
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -16,6 +16,7 @@
  * 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: Matthias Clasen <mclasen@redhat.com>
  */
 
 #include "config.h"
@@ -29,6 +30,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <pwd.h>
 
 #ifdef HAVE_PATHS_H
 #include <paths.h>
@@ -40,91 +42,23 @@
 #include <glib-object.h>
 #include <gio/gio.h>
 
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include "gdm-user-manager.h"
-#include "gdm-user-private.h"
-
-#define GDM_USER_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_MANAGER, GdmUserManagerPrivate))
-
 #define CK_NAME      "org.freedesktop.ConsoleKit"
 #define CK_PATH      "/org/freedesktop/ConsoleKit"
 #define CK_INTERFACE "org.freedesktop.ConsoleKit"
-
 #define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
 #define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
 #define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
 #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
 
-/* Prefs Defaults */
-#define DEFAULT_ALLOW_ROOT      TRUE
-#define DEFAULT_MAX_ICON_SIZE   128
-#define DEFAULT_USER_MAX_FILE   65536
-
-#ifdef __sun
-#define DEFAULT_MINIMAL_UID     100
-#else
-#define DEFAULT_MINIMAL_UID     500
-#endif
-
-#ifndef _PATH_SHELLS
-#define _PATH_SHELLS    "/etc/shells"
-#endif
-#define PATH_PASSWD     "/etc/passwd"
-
-#define DEFAULT_GLOBAL_FACE_DIR DATADIR "/faces"
-#define DEFAULT_USER_ICON       "stock_person"
-#define DEFAULT_EXCLUDE         { "bin",        \
-                                  "root",       \
-                                  "daemon",     \
-                                  "adm",        \
-                                  "lp",         \
-                                  "sync",       \
-                                  "shutdown",   \
-                                  "halt",       \
-                                  "mail",       \
-                                  "news",       \
-                                  "uucp",       \
-                                  "operator",   \
-                                  "nobody",     \
-                                  "nobody4",    \
-                                  "noaccess",   \
-                                  GDM_USERNAME, \
-                                  "postgres",   \
-                                  "pvm",        \
-                                  "rpm",        \
-                                  "nfsnobody",  \
-                                  "pcap",       \
-                                  NULL }
-
-struct GdmUserManagerPrivate
-{
-        GHashTable            *users;
-        GHashTable            *sessions;
-        GHashTable            *exclusions;
-        GHashTable            *shells;
-        DBusGConnection       *connection;
-        DBusGProxy            *seat_proxy;
-        char                  *seat_id;
-
-        GFileMonitor          *passwd_monitor;
-        GFileMonitor          *shells_monitor;
-
-        guint                  reload_id;
-        guint                  ck_history_id;
-
-        guint8                 users_dirty : 1;
-};
+#include "gdm-user-manager.h"
+#include "gdm-user-private.h"
 
 enum {
-        LOADING_USERS,
         USERS_LOADED,
         USER_ADDED,
         USER_REMOVED,
+        USER_CHANGED,
         USER_IS_LOGGED_IN_CHANGED,
-        USER_LOGIN_FREQUENCY_CHANGED,
         LAST_SIGNAL
 };
 
@@ -132,356 +66,285 @@
 
 static void     gdm_user_manager_class_init (GdmUserManagerClass *klass);
 static void     gdm_user_manager_init       (GdmUserManager      *user_manager);
-static void     gdm_user_manager_finalize   (GObject             *object);
+static void     gdm_user_manager_finalize   (GObject            *object);
 
 static gpointer user_manager_object = NULL;
 
 G_DEFINE_TYPE (GdmUserManager, gdm_user_manager, G_TYPE_OBJECT)
 
-GQuark
-gdm_user_manager_error_quark (void)
+static void
+gdm_user_manager_class_init (GdmUserManagerClass *klass)
 {
-        static GQuark ret = 0;
-        if (ret == 0) {
-                ret = g_quark_from_static_string ("gdm_user_manager_error");
-        }
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
-        return ret;
+        object_class->finalize = gdm_user_manager_finalize;
+
+       signals [USERS_LOADED] =
+                g_signal_new ("users-loaded",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GdmUserManagerClass, users_loaded),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE, 0);
+
+        signals [USER_ADDED] =
+                g_signal_new ("user-added",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GdmUserManagerClass, user_added),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE, 1, GDM_TYPE_USER);
+        signals [USER_REMOVED] =
+                g_signal_new ("user-removed",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GdmUserManagerClass, user_removed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE, 1, GDM_TYPE_USER);
+        signals [USER_CHANGED] =
+                g_signal_new ("user-changed",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GdmUserManagerClass, user_changed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE, 1, GDM_TYPE_USER);
+        signals [USER_IS_LOGGED_IN_CHANGED] =
+                g_signal_new ("user-is-logged-in-changed",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GdmUserManagerClass, user_is_logged_in_changed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE, 1, GDM_TYPE_USER);
 }
 
 static gboolean
-start_new_login_session (GdmUserManager *manager)
+match_real_name_hrfunc (gpointer key,
+                        gpointer value,
+                        gpointer user)
 {
-        GError  *error;
-        gboolean res;
+        return (value != user && g_strcmp0 (gdm_user_get_real_name (user), gdm_user_get_real_name (value)) == 0);
+}
 
-        res = g_spawn_command_line_async ("gdmflexiserver -s", &error);
-        if (! res) {
-                if (error != NULL) {
-                        g_warning ("Unable to start new login: %s", error->message);
-                        g_error_free (error);
-                } else {
-                        g_warning ("Unable to start new login");
-                }
+static void
+user_changed_handler (GdmUser        *user,
+                      GdmUserManager *manager)
+{
+        GdmUser *dup;
+
+        dup = g_hash_table_find (manager->user_by_object_path,
+                                 match_real_name_hrfunc,
+                                 user);
+        if (dup != NULL) {
+                _gdm_user_show_full_display_name (user);
+                _gdm_user_show_full_display_name (dup);
+        }
+        else {
+                _gdm_user_show_short_display_name (user);
         }
 
-        return res;
+        g_signal_emit (manager, signals[USER_CHANGED], 0, user);
 }
 
-/* needs to stay in sync with gdm-slave */
 static char *
-_get_primary_user_session_id (GdmUserManager *manager,
-                              GdmUser        *user)
+get_seat_id_for_session (DBusGConnection *connection,
+                         const char      *session_id)
 {
-        gboolean    res;
-        gboolean    can_activate_sessions;
-        GError     *error;
-        GList      *sessions;
-        GList      *l;
-        char       *primary_ssid;
-
-        if (manager->priv->seat_id == NULL || manager->priv->seat_id[0] == '\0') {
-                g_debug ("GdmUserManager: display seat id is not set; can't switch sessions");
-                return NULL;
-        }
+        DBusGProxy      *proxy;
+        GError          *error;
+        char            *seat_id;
+        gboolean         res;
 
-        primary_ssid = NULL;
-        sessions = NULL;
+        proxy = NULL;
+        seat_id = NULL;
 
-        g_debug ("GdmUserManager: checking if seat can activate sessions");
+        proxy = dbus_g_proxy_new_for_name (connection,
+                                           CK_NAME,
+                                           session_id,
+                                           CK_SESSION_INTERFACE);
+        if (proxy == NULL) {
+                g_warning ("Failed to connect to the ConsoleKit session object");
+                goto out;
+        }
 
         error = NULL;
-        res = dbus_g_proxy_call (manager->priv->seat_proxy,
-                                 "CanActivateSessions",
+        res = dbus_g_proxy_call (proxy,
+                                 "GetSeatId",
                                  &error,
                                  G_TYPE_INVALID,
-                                 G_TYPE_BOOLEAN, &can_activate_sessions,
+                                 DBUS_TYPE_G_OBJECT_PATH, &seat_id,
                                  G_TYPE_INVALID);
         if (! res) {
                 if (error != NULL) {
-                        g_warning ("unable to determine if seat can activate sessions: %s",
-                                   error->message);
+                        g_debug ("Failed to identify the current seat: %s", error->message);
                         g_error_free (error);
                 } else {
-                        g_warning ("unable to determine if seat can activate sessions");
-                }
-                goto out;
-        }
-
-        if (! can_activate_sessions) {
-                g_debug ("GdmUserManager: seat is unable to activate sessions");
-                goto out;
-        }
-
-        sessions = gdm_user_get_sessions (user);
-        if (sessions == NULL) {
-                g_warning ("unable to determine sessions for user: %s",
-                           gdm_user_get_user_name (user));
-                goto out;
-        }
-
-        for (l = sessions; l != NULL; l = l->next) {
-                const char *ssid;
-
-                ssid = l->data;
-
-                /* FIXME: better way to choose? */
-                if (ssid != NULL) {
-                        primary_ssid = g_strdup (ssid);
-                        break;
-                }
-        }
-
- out:
-
-        return primary_ssid;
-}
-
-static gboolean
-activate_session_id (GdmUserManager *manager,
-                     const char     *seat_id,
-                     const char     *session_id)
-{
-        DBusError    local_error;
-        DBusMessage *message;
-        DBusMessage *reply;
-        gboolean     ret;
-
-        ret = FALSE;
-        reply = NULL;
-
-        dbus_error_init (&local_error);
-        message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
-                                                seat_id,
-                                                "org.freedesktop.ConsoleKit.Seat",
-                                                "ActivateSession");
-        if (message == NULL) {
-                goto out;
-        }
-
-        if (! dbus_message_append_args (message,
-                                        DBUS_TYPE_OBJECT_PATH, &session_id,
-                                        DBUS_TYPE_INVALID)) {
-                goto out;
-        }
-
-
-        dbus_error_init (&local_error);
-        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (manager->priv->connection),
-                                                           message,
-                                                           -1,
-                                                           &local_error);
-        if (reply == NULL) {
-                if (dbus_error_is_set (&local_error)) {
-                        g_warning ("Unable to activate session: %s", local_error.message);
-                        dbus_error_free (&local_error);
-                        goto out;
+                        g_debug ("Failed to identify the current seat");
                 }
         }
-
-        ret = TRUE;
  out:
-        if (message != NULL) {
-                dbus_message_unref (message);
-        }
-        if (reply != NULL) {
-                dbus_message_unref (reply);
+        if (proxy != NULL) {
+                g_object_unref (proxy);
         }
-
-        return ret;
+        return seat_id;
 }
 
-static gboolean
-session_is_login_window (GdmUserManager *manager,
-                         const char     *session_id)
+static char *
+get_x11_display_for_session (DBusGConnection *connection,
+                             const char      *session_id)
 {
         DBusGProxy      *proxy;
         GError          *error;
+        char            *x11_display;
         gboolean         res;
-        gboolean         ret;
-        char            *session_type;
 
-        ret = FALSE;
+        proxy = NULL;
+        x11_display = NULL;
 
-        proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
+        proxy = dbus_g_proxy_new_for_name (connection,
                                            CK_NAME,
                                            session_id,
                                            CK_SESSION_INTERFACE);
         if (proxy == NULL) {
-                g_warning ("Failed to connect to the ConsoleKit seat object");
+                g_warning ("Failed to connect to the ConsoleKit session object");
                 goto out;
         }
-
-        session_type = NULL;
         error = NULL;
         res = dbus_g_proxy_call (proxy,
-                                 "GetSessionType",
+                                 "GetX11Display",
                                  &error,
                                  G_TYPE_INVALID,
-                                 G_TYPE_STRING, &session_type,
+                                 G_TYPE_STRING, &x11_display,
                                  G_TYPE_INVALID);
         if (! res) {
                 if (error != NULL) {
-                        g_debug ("Failed to identify the session type: %s", error->message);
+                        g_debug ("Failed to identify the x11 display: %s", error->message);
                         g_error_free (error);
                 } else {
-                        g_debug ("Failed to identify the session type");
+                        g_debug ("Failed to identify the x11 display");
                 }
-                goto out;
-        }
-
-        if (session_type == NULL || session_type[0] == '\0' || strcmp (session_type, "LoginWindow") != 0) {
-                goto out;
         }
-
-        ret = TRUE;
-
  out:
         if (proxy != NULL) {
                 g_object_unref (proxy);
         }
 
-        return ret;
+        return x11_display;
 }
 
-static char *
-_get_login_window_session_id (GdmUserManager *manager)
+static gboolean
+maybe_add_session_for_user (GdmUserManager *manager,
+                            GdmUser        *user,
+                            const char     *ssid)
 {
-        gboolean    res;
-        gboolean    can_activate_sessions;
-        GError     *error;
-        GPtrArray  *sessions;
-        char       *primary_ssid;
-        int         i;
+        char    *sid;
+        char    *x11_display;
+        gboolean ret;
 
-        if (manager->priv->seat_id == NULL || manager->priv->seat_id[0] == '\0') {
-                g_debug ("GdmUserManager: display seat id is not set; can't switch sessions");
-                return NULL;
-        }
+        ret = FALSE;
+        sid = NULL;
+        x11_display = NULL;
 
-        primary_ssid = NULL;
-        sessions = NULL;
+        /* skip if on another seat */
+        sid = get_seat_id_for_session (manager->bus, ssid);
+        if (sid == NULL
+            || manager->seat_id == NULL
+            || strcmp (sid, manager->seat_id) != 0) {
+                g_debug ("GdmUserManager: not adding session on other seat: %s", ssid);
+                goto out;
+        }
 
-        g_debug ("GdmSlave: checking if seat can activate sessions");
+        /* skip if doesn't have an x11 display */
+        x11_display = get_x11_display_for_session (manager->bus, ssid);
+        if (x11_display == NULL || x11_display[0] == '\0') {
+                g_debug ("GdmUserManager: not adding session without a x11 display: %s", ssid);
+                goto out;
+        }
 
-        error = NULL;
-        res = dbus_g_proxy_call (manager->priv->seat_proxy,
-                                 "CanActivateSessions",
-                                 &error,
-                                 G_TYPE_INVALID,
-                                 G_TYPE_BOOLEAN, &can_activate_sessions,
-                                 G_TYPE_INVALID);
-        if (! res) {
-                if (error != NULL) {
-                        g_warning ("unable to determine if seat can activate sessions: %s",
-                                   error->message);
-                        g_error_free (error);
-                } else {
-                        g_warning ("unable to determine if seat can activate sessions");
-                }
+#if 0
+        if (g_hash_table_lookup (manager->exclusions, gdm_user_get_user_name (user))) {
+                g_debug ("GdmUserManager: excluding user '%s'", gdm_user_get_user_name (user));
                 goto out;
         }
+#endif
+
+        g_hash_table_insert (manager->sessions,
+                             g_strdup (ssid),
+                             g_strdup (gdm_user_get_user_name (user)));
+
+        _gdm_user_add_session (user, ssid);
+        g_debug ("GdmUserManager: added session for user: %s", gdm_user_get_user_name (user));
+
+        ret = TRUE;
+
+ out:
+        g_free (sid);
+        g_free (x11_display);
+
+        return ret;
+}
+
+static void
+add_sessions_for_user (GdmUserManager *manager,
+                       GdmUser        *user)
+{
+        DBusGProxy      *proxy;
+        GError          *error;
+        gboolean         res;
+        guint32          uid;
+        GPtrArray       *sessions;
+        int              i;
 
-        if (! can_activate_sessions) {
-                g_debug ("GdmSlave: seat is unable to activate sessions");
+        proxy = dbus_g_proxy_new_for_name (manager->bus,
+                                           CK_NAME,
+                                           CK_MANAGER_PATH,
+                                           CK_MANAGER_INTERFACE);
+        if (proxy == NULL) {
+                g_warning ("Failed to connect to the ConsoleKit manager object");
                 goto out;
         }
+        uid = gdm_user_get_uid (user);
+
+        g_debug ("Getting list of sessions for user %u", uid);
 
         error = NULL;
-        res = dbus_g_proxy_call (manager->priv->seat_proxy,
-                                 "GetSessions",
+        res = dbus_g_proxy_call (proxy,
+                                 "GetSessionsForUnixUser",
                                  &error,
+                                 G_TYPE_UINT, uid,
                                  G_TYPE_INVALID,
-                                 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions,
+                                 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
+                                 &sessions,
                                  G_TYPE_INVALID);
         if (! res) {
                 if (error != NULL) {
-                        g_warning ("unable to determine sessions for user: %s",
-                                   error->message);
+                        g_debug ("Failed to find sessions for user: %s", error->message);
                         g_error_free (error);
                 } else {
-                        g_warning ("unable to determine sessions for user");
+                        g_debug ("Failed to find sessions for user");
                 }
                 goto out;
         }
 
+        g_debug ("Found %d sessions for user %s", sessions->len, gdm_user_get_user_name (user));
+
         for (i = 0; i < sessions->len; i++) {
                 char *ssid;
 
                 ssid = g_ptr_array_index (sessions, i);
-
-                if (session_is_login_window (manager, ssid)) {
-                        primary_ssid = g_strdup (ssid);
-                        break;
-                }
+                maybe_add_session_for_user (manager, user, ssid);
         }
+
         g_ptr_array_foreach (sessions, (GFunc)g_free, NULL);
         g_ptr_array_free (sessions, TRUE);
-
  out:
-
-        return primary_ssid;
-}
-
-gboolean
-gdm_user_manager_goto_login_session (GdmUserManager *manager)
-{
-        gboolean ret;
-        gboolean res;
-        char    *ssid;
-
-        g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), FALSE);
-
-        ret = FALSE;
-
-        /* First look for any existing LoginWindow sessions on the seat.
-           If none are found, create a new one. */
-
-        ssid = _get_login_window_session_id (manager);
-        if (ssid != NULL) {
-                res = activate_session_id (manager, manager->priv->seat_id, ssid);
-                if (res) {
-                        ret = TRUE;
-                }
-        }
-
-        if (! ret) {
-                res = start_new_login_session (manager);
-                if (res) {
-                        ret = TRUE;
-                }
-        }
-
-        return ret;
-}
-
-gboolean
-gdm_user_manager_activate_user_session (GdmUserManager *manager,
-                                        GdmUser        *user)
-{
-        gboolean ret;
-        char    *ssid;
-        gboolean res;
-
-        g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), FALSE);
-        g_return_val_if_fail (GDM_IS_USER (user), FALSE);
-
-        ret = FALSE;
-
-        ssid = _get_primary_user_session_id (manager, user);
-        if (ssid == NULL) {
-                goto out;
-        }
-
-        res = activate_session_id (manager, manager->priv->seat_id, ssid);
-        if (! res) {
-                g_debug ("GdmUserManager: unable to activate session: %s", ssid);
-                goto out;
-        }
-
-        ret = TRUE;
- out:
-        return ret;
+        if (proxy != NULL) {
+                g_object_unref (proxy);
+        }
 }
 
 static void
@@ -505,282 +368,99 @@
 }
 
 static void
-on_user_icon_changed (GdmUser        *user,
-                      GdmUserManager *manager)
-{
-        g_debug ("GdmUserManager: user icon changed");
-}
-
-static char *
-get_seat_id_for_session (DBusGConnection *connection,
-                         const char      *session_id)
+user_added_handler (DBusGProxy *proxy,
+                    const char *object_path,
+                    gpointer    user_data)
 {
-        DBusGProxy      *proxy;
-        GError          *error;
-        char            *seat_id;
-        gboolean         res;
-
-        proxy = NULL;
-        seat_id = NULL;
+        GdmUserManager *manager = GDM_USER_MANAGER (user_data);
+        GdmUser *user;
+        GdmUser *dup;
 
-        proxy = dbus_g_proxy_new_for_name (connection,
-                                           CK_NAME,
-                                           session_id,
-                                           CK_SESSION_INTERFACE);
-        if (proxy == NULL) {
-                g_warning ("Failed to connect to the ConsoleKit session object");
-                goto out;
-        }
+        if (g_hash_table_lookup (manager->user_by_object_path, object_path))
+                return;
 
-        error = NULL;
-        res = dbus_g_proxy_call (proxy,
-                                 "GetSeatId",
-                                 &error,
-                                 G_TYPE_INVALID,
-                                 DBUS_TYPE_G_OBJECT_PATH, &seat_id,
-                                 G_TYPE_INVALID);
-        if (! res) {
-                if (error != NULL) {
-                        g_debug ("Failed to identify the current seat: %s", error->message);
-                        g_error_free (error);
-                } else {
-                        g_debug ("Failed to identify the current seat");
-                }
-        }
- out:
-        if (proxy != NULL) {
-                g_object_unref (proxy);
+        user = gdm_user_new_from_object_path (object_path);
+        g_signal_connect (user, "sessions-changed",
+                          G_CALLBACK (on_user_sessions_changed), manager);
+        add_sessions_for_user (manager, user);
+        dup = g_hash_table_find (manager->user_by_object_path,
+                                 match_real_name_hrfunc,
+                                 user);
+        if (dup != NULL) {
+                _gdm_user_show_full_display_name (user);
+                _gdm_user_show_full_display_name (dup);
         }
 
-        return seat_id;
+        g_signal_connect (user, "changed",
+                          G_CALLBACK (user_changed_handler), manager);
+        g_hash_table_insert (manager->user_by_object_path, (gpointer)gdm_user_get_object_path (user), g_object_ref (user));
+        g_hash_table_insert (manager->user_by_name, (gpointer)gdm_user_get_user_name (user), g_object_ref (user));
+        g_signal_emit (manager, signals[USER_ADDED], 0, user);
+        g_object_unref (user);
 }
 
-static char *
-get_x11_display_for_session (DBusGConnection *connection,
-                             const char      *session_id)
+static void
+user_deleted_handler (DBusGProxy *proxy,
+                      const char *object_path,
+                      gpointer    user_data)
 {
-        DBusGProxy      *proxy;
-        GError          *error;
-        char            *x11_display;
-        gboolean         res;
-
-        proxy = NULL;
-        x11_display = NULL;
-
-        proxy = dbus_g_proxy_new_for_name (connection,
-                                           CK_NAME,
-                                           session_id,
-                                           CK_SESSION_INTERFACE);
-        if (proxy == NULL) {
-                g_warning ("Failed to connect to the ConsoleKit session object");
-                goto out;
-        }
-
-        error = NULL;
-        res = dbus_g_proxy_call (proxy,
-                                 "GetX11Display",
-                                 &error,
-                                 G_TYPE_INVALID,
-                                 G_TYPE_STRING, &x11_display,
-                                 G_TYPE_INVALID);
-        if (! res) {
-                if (error != NULL) {
-                        g_debug ("Failed to identify the x11 display: %s", error->message);
-                        g_error_free (error);
-                } else {
-                        g_debug ("Failed to identify the x11 display");
-                }
-        }
- out:
-        if (proxy != NULL) {
-                g_object_unref (proxy);
-        }
+        GdmUserManager *manager = GDM_USER_MANAGER (user_data);
+        GdmUser *user;
 
-        return x11_display;
+        user = g_hash_table_lookup (manager->user_by_object_path, object_path);
+        g_object_ref (user);
+        g_signal_handlers_disconnect_by_func (user, user_changed_handler, manager);
+        g_hash_table_remove (manager->user_by_object_path, gdm_user_get_object_path (user));
+        g_hash_table_remove (manager->user_by_name, gdm_user_get_user_name (user));
+        g_signal_emit (manager, signals[USER_REMOVED], 0, user);
+        g_object_unref (user);
 }
 
-static gboolean
-maybe_add_session_for_user (GdmUserManager *manager,
-                            GdmUser        *user,
-                            const char     *ssid)
+static void
+add_user (const gchar   *object_path,
+          GdmUserManager *manager)
 {
-        char    *sid;
-        char    *x11_display;
-        gboolean ret;
-
-        ret = FALSE;
-        sid = NULL;
-        x11_display = NULL;
-
-        /* skip if on another seat */
-        sid = get_seat_id_for_session (manager->priv->connection, ssid);
-        if (sid == NULL
-            || manager->priv->seat_id == NULL
-            || strcmp (sid, manager->priv->seat_id) != 0) {
-                g_debug ("GdmUserManager: not adding session on other seat: %s", ssid);
-                goto out;
-        }
-
-        /* skip if doesn't have an x11 display */
-        x11_display = get_x11_display_for_session (manager->priv->connection, ssid);
-        if (x11_display == NULL || x11_display[0] == '\0') {
-                g_debug ("GdmUserManager: not adding session without a x11 display: %s", ssid);
-                goto out;
-        }
-
-        if (g_hash_table_lookup (manager->priv->exclusions, gdm_user_get_user_name (user))) {
-                g_debug ("GdmUserManager: excluding user '%s'", gdm_user_get_user_name (user));
-                goto out;
-        }
-
-        g_hash_table_insert (manager->priv->sessions,
-                             g_strdup (ssid),
-                             g_strdup (gdm_user_get_user_name (user)));
-
-        _gdm_user_add_session (user, ssid);
-        g_debug ("GdmUserManager: added session for user: %s", gdm_user_get_user_name (user));
-
-        ret = TRUE;
-
- out:
-        g_free (sid);
-        g_free (x11_display);
-
-        return ret;
+        user_added_handler (NULL, object_path, manager);
 }
 
 static void
-add_sessions_for_user (GdmUserManager *manager,
-                       GdmUser        *user)
+got_users (DBusGProxy     *proxy,
+           DBusGProxyCall *call_id,
+           gpointer        data)
 {
-        DBusGProxy      *proxy;
-        GError          *error;
-        gboolean         res;
-        guint32          uid;
-        GPtrArray       *sessions;
-        int              i;
-
-        proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
-                                           CK_NAME,
-                                           CK_MANAGER_PATH,
-                                           CK_MANAGER_INTERFACE);
-        if (proxy == NULL) {
-                g_warning ("Failed to connect to the ConsoleKit manager object");
-                goto out;
-        }
-
-        uid = gdm_user_get_uid (user);
-
-        g_debug ("Getting list of sessions for user %u", uid);
-
-        error = NULL;
-        res = dbus_g_proxy_call (proxy,
-                                 "GetSessionsForUnixUser",
-                                 &error,
-                                 G_TYPE_UINT, uid,
-                                 G_TYPE_INVALID,
-                                 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
-                                 &sessions,
-                                 G_TYPE_INVALID);
-        if (! res) {
-                if (error != NULL) {
-                        g_debug ("Failed to find sessions for user: %s", error->message);
-                        g_error_free (error);
-                } else {
-                        g_debug ("Failed to find sessions for user");
-                }
-                goto out;
-        }
+        GdmUserManager *manager = data;
+        GError *error = NULL;
+        GPtrArray *paths;
 
-        g_debug ("Found %d sessions for user %s", sessions->len, gdm_user_get_user_name (user));
-
-        for (i = 0; i < sessions->len; i++) {
-                char *ssid;
-
-                ssid = g_ptr_array_index (sessions, i);
-                maybe_add_session_for_user (manager, user, ssid);
-        }
-
-        g_ptr_array_foreach (sessions, (GFunc)g_free, NULL);
-        g_ptr_array_free (sessions, TRUE);
-
- out:
-        if (proxy != NULL) {
-                g_object_unref (proxy);
+        if (!dbus_g_proxy_end_call (proxy,
+                                    call_id,
+                                    &error,
+                                    dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &paths,
+                                    G_TYPE_INVALID)) {
+                manager->no_service = TRUE;
+                g_error_free (error);
+                goto done;
         }
-}
 
-static GdmUser *
-create_user (GdmUserManager *manager)
-{
-        GdmUser *user;
-
-        user = g_object_new (GDM_TYPE_USER, "manager", manager, NULL);
-        g_signal_connect (user,
-                          "sessions-changed",
-                          G_CALLBACK (on_user_sessions_changed),
-                          manager);
-        g_signal_connect (user,
-                          "icon-changed",
-                          G_CALLBACK (on_user_icon_changed),
-                          manager);
-        return user;
-}
-
-static gint
-match_real_name_cmpfunc (gconstpointer a,
-                         gconstpointer b)
-{
-        if (a == b)
-                return -1;
+        g_ptr_array_foreach (paths, (GFunc)add_user, manager);
 
-        return g_strcmp0 (gdm_user_get_real_name ((GdmUser *) a),
-                          gdm_user_get_real_name ((GdmUser *) b));
-}
+        g_ptr_array_foreach (paths, (GFunc)g_free, NULL);
+        g_ptr_array_free (paths, TRUE);
 
-static gboolean
-match_real_name_hrfunc (gpointer key,
-                        gpointer value,
-                        gpointer user_data)
-{
-        return (g_strcmp0 (user_data, gdm_user_get_real_name (value)) == 0);
+ done:
+        g_signal_emit (G_OBJECT (manager), signals[USERS_LOADED], 0);
 }
 
 static void
-add_user (GdmUserManager *manager,
-          GdmUser        *user)
-{
-        GdmUser *dup;
-
-        add_sessions_for_user (manager, user);
-        dup = g_hash_table_find (manager->priv->users,
-                                 match_real_name_hrfunc,
-                                 (char *) gdm_user_get_real_name (user));
-        if (dup != NULL) {
-                _gdm_user_show_full_display_name (user);
-                _gdm_user_show_full_display_name (dup);
-        }
-        g_hash_table_insert (manager->priv->users,
-                             g_strdup (gdm_user_get_user_name (user)),
-                             g_object_ref (user));
-
-        g_signal_emit (manager, signals[USER_ADDED], 0, user);
-}
-
-static GdmUser *
-add_new_user_for_pwent (GdmUserManager *manager,
-                        struct passwd  *pwent)
+get_users (GdmUserManager *manager)
 {
-        GdmUser *user;
-
-        g_debug ("Creating new user");
-
-        user = create_user (manager);
-        _gdm_user_update (user, pwent);
-
-        add_user (manager, user);
-
-        return user;
+        g_debug ("calling 'ListCachedUsers'");
+        dbus_g_proxy_begin_call (manager->proxy,
+                                 "ListCachedUsers",
+                                 got_users,
+                                 manager,
+                                 NULL,
+                                 G_TYPE_INVALID);
 }
 
 static char *
@@ -824,7 +504,6 @@
         }
 
         seat_id = get_seat_id_for_session (connection, session_id);
-
  out:
         if (proxy != NULL) {
                 g_object_unref (proxy);
@@ -844,7 +523,7 @@
         guint            uid;
         gboolean         res;
 
-        proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
+        proxy = dbus_g_proxy_new_for_name (manager->bus,
                                            CK_NAME,
                                            session_id,
                                            CK_SESSION_INTERFACE);
@@ -905,19 +584,19 @@
                 return;
         }
 
+#if 0
         /* check exclusions up front */
         if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) {
                 g_debug ("GdmUserManager: excluding user '%s'", pwent->pw_name);
                 return;
         }
+#endif
 
-        user = g_hash_table_lookup (manager->priv->users, pwent->pw_name);
+        user = g_hash_table_lookup (manager->user_by_name, pwent->pw_name);
         if (user == NULL) {
-                g_debug ("Creating new user");
-
-                user = create_user (manager);
-                _gdm_user_update (user, pwent);
                 is_new = TRUE;
+                /* TODO call service to look up user */
+                return;
         } else {
                 is_new = FALSE;
         }
@@ -926,11 +605,13 @@
 
         /* only add the user if we added a session */
         if (is_new) {
+#if 0
                 if (res) {
                         add_user (manager, user);
                 } else {
                         g_object_unref (user);
                 }
+#endif
         }
 }
 
@@ -945,14 +626,14 @@
         g_debug ("Session removed: %s", session_id);
 
         /* since the session object may already be gone
-         * we can't query CK directly */
+ *          * we can't query CK directly */
 
-        username = g_hash_table_lookup (manager->priv->sessions, session_id);
+        username = g_hash_table_lookup (manager->sessions, session_id);
         if (username == NULL) {
                 return;
         }
 
-        user = g_hash_table_lookup (manager->priv->users, username);
+        user = g_hash_table_lookup (manager->user_by_name, username);
         if (user == NULL) {
                 /* nothing to do */
                 return;
@@ -962,13 +643,14 @@
         _gdm_user_remove_session (user, session_id);
 }
 
+
 static void
 on_proxy_destroy (DBusGProxy     *proxy,
                   GdmUserManager *manager)
 {
         g_debug ("GdmUserManager: seat proxy destroyed");
 
-        manager->priv->seat_proxy = NULL;
+        manager->seat_proxy = NULL;
 }
 
 static void
@@ -977,31 +659,19 @@
         DBusGProxy      *proxy;
         GError          *error;
 
-        g_assert (manager->priv->seat_proxy == NULL);
+        g_assert (manager->seat_proxy == NULL);
 
-        error = NULL;
-        manager->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
-        if (manager->priv->connection == NULL) {
-                if (error != NULL) {
-                        g_warning ("Failed to connect to the D-Bus daemon: %s", error->message);
-                        g_error_free (error);
-                } else {
-                        g_warning ("Failed to connect to the D-Bus daemon");
-                }
+        manager->seat_id = get_current_seat_id (manager->bus);
+        if (manager->seat_id == NULL) {
                 return;
         }
 
-        manager->priv->seat_id = get_current_seat_id (manager->priv->connection);
-        if (manager->priv->seat_id == NULL) {
-                return;
-        }
-
-        g_debug ("GdmUserManager: Found current seat: %s", manager->priv->seat_id);
+        g_debug ("GdmUserManager: Found current seat: %s", manager->seat_id);
 
         error = NULL;
-        proxy = dbus_g_proxy_new_for_name_owner (manager->priv->connection,
+        proxy = dbus_g_proxy_new_for_name_owner (manager->bus,
                                                  CK_NAME,
-                                                 manager->priv->seat_id,
+                                                 manager->seat_id,
                                                  CK_SEAT_INTERFACE,
                                                  &error);
 
@@ -1036,718 +706,145 @@
                                      G_CALLBACK (seat_session_removed),
                                      manager,
                                      NULL);
-        manager->priv->seat_proxy = proxy;
-
-}
-
-/**
- * gdm_manager_get_user:
- * @manager: the manager to query.
- * @username: the login name of the user to get.
- *
- * Retrieves a pointer to the #GdmUser object for the login named @username
- * from @manager. This pointer is not a reference, and should not be released.
- *
- * Returns: a pointer to a #GdmUser object.
- **/
-GdmUser *
-gdm_user_manager_get_user (GdmUserManager *manager,
-                           const char     *username)
-{
-        GdmUser *user;
-
-        g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL);
-        g_return_val_if_fail (username != NULL && username[0] != '\0', NULL);
-
-        user = g_hash_table_lookup (manager->priv->users, username);
-
-        if (user == NULL) {
-                struct passwd *pwent;
-
-                pwent = getpwnam (username);
-
-                if (pwent != NULL) {
-                        user = add_new_user_for_pwent (manager, pwent);
-                }
-        }
-
-        return user;
-}
-
-GdmUser *
-gdm_user_manager_get_user_by_uid (GdmUserManager *manager,
-                                  uid_t           uid)
-{
-        GdmUser       *user;
-        struct passwd *pwent;
-
-        g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL);
-
-        pwent = getpwuid (uid);
-        if (pwent == NULL) {
-                g_warning ("GdmUserManager: unable to lookup uid %d", (int)uid);
-                return NULL;
-        }
-
-        user = g_hash_table_lookup (manager->priv->users, pwent->pw_name);
-
-        if (user == NULL) {
-                user = add_new_user_for_pwent (manager, pwent);
-        }
-
-        return user;
+        manager->seat_proxy = proxy;
 }
 
 static void
-listify_hash_values_hfunc (gpointer key,
-                           gpointer value,
-                           gpointer user_data)
-{
-        GSList **list = user_data;
-
-        *list = g_slist_prepend (*list, value);
-}
-
-GSList *
-gdm_user_manager_list_users (GdmUserManager *manager)
-{
-        GSList *retval;
-
-        g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL);
-
-        retval = NULL;
-        g_hash_table_foreach (manager->priv->users, listify_hash_values_hfunc, &retval);
-
-        return g_slist_sort (retval, (GCompareFunc) gdm_user_collate);
-}
-
-static gboolean
-parse_value_as_ulong (const char *value,
-                      gulong     *ulongval)
-{
-        char  *end_of_valid_long;
-        glong  long_value;
-        gulong ulong_value;
-
-        errno = 0;
-        long_value = strtol (value, &end_of_valid_long, 10);
-
-        if (*value == '\0' || *end_of_valid_long != '\0') {
-                return FALSE;
-        }
-
-        ulong_value = long_value;
-        if (ulong_value != long_value || errno == ERANGE) {
-                return FALSE;
-        }
-
-        *ulongval = ulong_value;
-
-        return TRUE;
-}
-
-static gboolean
-parse_ck_history_line (const char *line,
-                       char      **user_namep,
-                       gulong     *frequencyp)
-{
-        GRegex     *re;
-        GMatchInfo *match_info;
-        gboolean    res;
-        gboolean    ret;
-        GError     *error;
-
-        ret = FALSE;
-        re = NULL;
-        match_info = NULL;
-
-        error = NULL;
-        re = g_regex_new ("(?P<username>[0-9a-zA-Z]+)[ ]+(?P<frequency>[0-9]+)", 0, 0, &error);
-        if (re == NULL) {
-                if (error != NULL) {
-                        g_critical ("%s", error->message);
-                } else {
-                        g_critical ("Error in regex call");
-                }
-                goto out;
-        }
-
-        g_regex_match (re, line, 0, &match_info);
-
-        res = g_match_info_matches (match_info);
-        if (! res) {
-                g_warning ("Unable to parse history: %s", line);
-                goto out;
-        }
-
-        if (user_namep != NULL) {
-                *user_namep = g_match_info_fetch_named (match_info, "username");
-        }
-
-        if (frequencyp != NULL) {
-                char *freq;
-                freq = g_match_info_fetch_named (match_info, "frequency");
-                res = parse_value_as_ulong (freq, frequencyp);
-                g_free (freq);
-                if (! res) {
-                        goto out;
-                }
-        }
-
-        ret = TRUE;
-
- out:
-        if (match_info != NULL) {
-                g_match_info_free (match_info);
-        }
-        if (re != NULL) {
-                g_regex_unref (re);
-        }
-        return ret;
-}
-
-static void
-process_ck_history_line (GdmUserManager *manager,
-                         const char     *line)
-{
-        gboolean res;
-        char    *username;
-        gulong   frequency;
-        GdmUser *user;
-
-        frequency = 0;
-        username = NULL;
-        res = parse_ck_history_line (line, &username, &frequency);
-        if (! res) {
-                return;
-        }
-
-        if (g_hash_table_lookup (manager->priv->exclusions, username)) {
-                g_debug ("GdmUserManager: excluding user '%s'", username);
-                g_free (username);
-                return;
-        }
-
-        user = gdm_user_manager_get_user (manager, username);
-        if (user == NULL) {
-                g_debug ("GdmUserManager: unable to lookup user '%s'", username);
-                g_free (username);
-                return;
-        }
-
-        g_object_set (user, "login-frequency", frequency, NULL);
-        g_signal_emit (manager, signals [USER_LOGIN_FREQUENCY_CHANGED], 0, user);
-        g_free (username);
-}
-
-static gboolean
-ck_history_watch (GIOChannel     *source,
-                  GIOCondition    condition,
-                  GdmUserManager *manager)
-{
-        GIOStatus status;
-        gboolean  done  = FALSE;
-
-        g_return_val_if_fail (manager != NULL, FALSE);
-
-        if (condition & G_IO_IN) {
-                char   *str;
-                GError *error;
-
-                error = NULL;
-                status = g_io_channel_read_line (source, &str, NULL, NULL, &error);
-                if (error != NULL) {
-                        g_warning ("GdmUserManager: unable to read line: %s", error->message);
-                        g_error_free (error);
-                }
-
-                if (status == G_IO_STATUS_NORMAL) {
-                        g_debug ("GdmUserManager: history output: %s", str);
-                        process_ck_history_line (manager, str);
-                } else if (status == G_IO_STATUS_EOF) {
-                        done = TRUE;
-                }
-
-                g_free (str);
-        } else if (condition & G_IO_HUP) {
-                done = TRUE;
-        }
-
-        if (done) {
-                g_signal_emit (G_OBJECT (manager), signals[USERS_LOADED], 0);
-
-                manager->priv->ck_history_id = 0;
-                return FALSE;
-        }
-
-        return TRUE;
-}
-
-static void
-reload_ck_history (GdmUserManager *manager)
+gdm_user_manager_init (GdmUserManager *manager)
 {
-        char       *command;
-        const char *seat_id;
-        GError     *error;
-        gboolean    res;
-        char      **argv;
-        int         standard_out;
-        GIOChannel *channel;
-
-        seat_id = NULL;
-        if (manager->priv->seat_id != NULL
-            && g_str_has_prefix (manager->priv->seat_id, "/org/freedesktop/ConsoleKit/")) {
+        GError *error = NULL;
 
-                seat_id = manager->priv->seat_id + strlen ("/org/freedesktop/ConsoleKit/");
-        }
+        manager->user_by_object_path = g_hash_table_new_full (g_str_hash,
+                                                              g_str_equal,
+                                                              NULL,
+                                                              g_object_unref);
+        manager->user_by_name = g_hash_table_new_full (g_str_hash,
+                                                       g_str_equal,
+                                                       NULL,
+                                                       g_object_unref);
 
-        if (seat_id == NULL) {
-                g_warning ("Unable to find users: no seat-id found");
-                return;
-        }
+        manager->sessions = g_hash_table_new_full (g_str_hash,
+                                                   g_str_equal,
+                                                   g_free,
+                                                   g_free);
+
+        manager->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (manager->bus == NULL) {
+                g_warning ("Couldn't connect to system bus: %s", error->message);
+                g_error_free (error);
+                goto error;
+        }
+
+        manager->proxy = dbus_g_proxy_new_for_name (manager->bus,
+                                                    "org.freedesktop.Accounts",
+                                                    "/org/freedesktop/Accounts",
+                                                    "org.freedesktop.Accounts");
+
+        dbus_g_proxy_add_signal (manager->proxy, "UserAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+        dbus_g_proxy_add_signal (manager->proxy, "UserDeleted", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+
+        dbus_g_proxy_connect_signal (manager->proxy, "UserAdded",
+                                     G_CALLBACK (user_added_handler), manager, NULL);
+        dbus_g_proxy_connect_signal (manager->proxy, "UserDeleted",
+                                     G_CALLBACK (user_deleted_handler), manager, NULL);
 
-        command = g_strdup_printf ("ck-history --frequent --seat='%s' --session-type=''",
-                                   seat_id);
-        g_debug ("GdmUserManager: running '%s'", command);
-        error = NULL;
-        if (! g_shell_parse_argv (command, NULL, &argv, &error)) {
-                if (error != NULL) {
-                        g_warning ("Could not parse command: %s", error->message);
-                        g_error_free (error);
-                } else {
-                        g_warning ("Could not parse command");
-                }
-                goto out;
-        }
-
-        error = NULL;
-        res = g_spawn_async_with_pipes (NULL,
-                                        argv,
-                                        NULL,
-                                        G_SPAWN_SEARCH_PATH,
-                                        NULL,
-                                        NULL,
-                                        NULL, /* pid */
-                                        NULL,
-                                        &standard_out,
-                                        NULL,
-                                        &error);
-        g_strfreev (argv);
-        if (! res) {
-                if (error != NULL) {
-                        g_warning ("Unable to run ck-history: %s", error->message);
-                        g_error_free (error);
-                } else {
-                        g_warning ("Unable to run ck-history");
-                }
-                goto out;
-        }
+        get_seat_proxy (manager);
 
-        channel = g_io_channel_unix_new (standard_out);
-        g_io_channel_set_close_on_unref (channel, TRUE);
-        g_io_channel_set_flags (channel,
-                                g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK,
-                                NULL);
-        manager->priv->ck_history_id = g_io_add_watch (channel,
-                                                       G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-                                                       (GIOFunc)ck_history_watch,
-                                                       manager);
-        g_io_channel_unref (channel);
+        get_users (manager);
 
- out:
-        g_free (command);
+ error: ;
 }
 
 static void
-reload_passwd (GdmUserManager *manager)
+gdm_user_manager_finalize (GObject *object)
 {
-        struct passwd *pwent;
-        GSList        *old_users;
-        GSList        *new_users;
-        GSList        *list;
-        GSList        *dup;
-        FILE          *fp;
-
-        old_users = NULL;
-        new_users = NULL;
-
-        errno = 0;
-        fp = fopen (PATH_PASSWD, "r");
-        if (fp == NULL) {
-                g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno));
-                goto out;
-        }
-
-        g_hash_table_foreach (manager->priv->users, listify_hash_values_hfunc, &old_users);
-        g_slist_foreach (old_users, (GFunc) g_object_ref, NULL);
-
-        /* Make sure we keep users who are logged in no matter what. */
-        for (list = old_users; list; list = list->next) {
-                if (gdm_user_get_num_sessions (list->data) > 0) {
-                        g_object_freeze_notify (G_OBJECT (list->data));
-                        _gdm_user_show_short_display_name (list->data);
-                        new_users = g_slist_prepend (new_users, g_object_ref (list->data));
-                }
-        }
-
-        for (pwent = fgetpwent (fp); pwent != NULL; pwent = fgetpwent (fp)) {
-                GdmUser *user;
-
-                user = NULL;
-
-                /* Skip users below MinimalUID... */
-                if (pwent->pw_uid < DEFAULT_MINIMAL_UID) {
-                        continue;
-                }
-
-                /* ...And users w/ invalid shells... */
-                if (pwent->pw_shell == NULL ||
-                    !g_hash_table_lookup (manager->priv->shells, pwent->pw_shell)) {
-                        g_debug ("GdmUserManager: skipping user with bad shell: %s", pwent->pw_name);
-                        continue;
-                }
-
-                /* ...And explicitly excluded users */
-                if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) {
-                        g_debug ("GdmUserManager: explicitly skipping user: %s", pwent->pw_name);
-                        continue;
-                }
-
-                user = g_hash_table_lookup (manager->priv->users, pwent->pw_name);
-
-                /* Update users already in the *new* list */
-                if (g_slist_find (new_users, user)) {
-                        _gdm_user_update (user, pwent);
-                        continue;
-                }
-
-                if (user == NULL) {
-                        user = create_user (manager);
-                } else {
-                        g_object_ref (user);
-                }
-
-                /* Freeze & update users not already in the new list */
-                g_object_freeze_notify (G_OBJECT (user));
-                _gdm_user_update (user, pwent);
-
-                new_users = g_slist_prepend (new_users, user);
-        }
-
-        /* Go through and handle removed users */
-        for (list = old_users; list; list = list->next) {
-                if (! g_slist_find (new_users, list->data)) {
-                        g_signal_emit (manager, signals[USER_REMOVED], 0, list->data);
-                        g_hash_table_remove (manager->priv->users,
-                                             gdm_user_get_user_name (list->data));
-                }
-        }
-
-        /* Go through and handle added users or update display names */
-        for (list = new_users; list; list = list->next) {
-                if (g_slist_find (old_users, list->data)) {
-                        dup = g_slist_find_custom (new_users,
-                                                   list->data,
-                                                   match_real_name_cmpfunc);
-                        if (dup != NULL) {
-                                _gdm_user_show_full_display_name (list->data);
-                                _gdm_user_show_full_display_name (dup->data);
-                        }
-                } else {
-                        add_user (manager, list->data);
-                }
-        }
-
- out:
-        /* Cleanup */
-
-        fclose (fp);
-
-        g_slist_foreach (new_users, (GFunc) g_object_thaw_notify, NULL);
-        g_slist_foreach (new_users, (GFunc) g_object_unref, NULL);
-        g_slist_free (new_users);
-
-        g_slist_foreach (old_users, (GFunc) g_object_unref, NULL);
-        g_slist_free (old_users);
-}
+        GdmUserManager *manager;
 
-static void
-reload_users (GdmUserManager *manager)
-{
-        reload_ck_history (manager);
-        reload_passwd (manager);
-}
+        manager = GDM_USER_MANAGER (object);
 
-static gboolean
-reload_users_timeout (GdmUserManager *manager)
-{
-        reload_users (manager);
-        manager->priv->reload_id = 0;
+        g_hash_table_destroy (manager->user_by_object_path);
+        g_hash_table_destroy (manager->user_by_name);
+        g_hash_table_destroy (manager->sessions);
 
-        return FALSE;
+        G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object);
 }
 
-static void
-queue_reload_users (GdmUserManager *manager)
+GdmUserManager *
+gdm_user_manager_ref_default (void)
 {
-        if (manager->priv->reload_id > 0) {
-                return;
+        if (user_manager_object != NULL) {
+                g_object_ref (user_manager_object);
+        } else {
+                user_manager_object = g_object_new (GDM_TYPE_USER_MANAGER, NULL);
+                g_object_add_weak_pointer (user_manager_object,
+                                           (gpointer *) &user_manager_object);
         }
 
-        g_signal_emit (G_OBJECT (manager), signals[LOADING_USERS], 0);
-        manager->priv->reload_id = g_idle_add ((GSourceFunc)reload_users_timeout, manager);
+        return GDM_USER_MANAGER (user_manager_object);
 }
 
-static void
-reload_shells (GdmUserManager *manager)
-{
-        char *shell;
-
-        setusershell ();
-
-        g_hash_table_remove_all (manager->priv->shells);
-        for (shell = getusershell (); shell != NULL; shell = getusershell ()) {
-                /* skip well known not-real shells */
-                if (shell == NULL
-                    || strcmp (shell, "/sbin/nologin") == 0
-                    || strcmp (shell, "/bin/false") == 0) {
-                        g_debug ("GdmUserManager: skipping shell %s", shell);
-                        continue;
-                }
-                g_hash_table_insert (manager->priv->shells,
-                                     g_strdup (shell),
-                                     GUINT_TO_POINTER (TRUE));
-        }
-
-        endusershell ();
+void
+gdm_user_manager_create_user (GdmUserManager *manager,
+                             const char    *user_name,
+                             const char    *real_name)
+{
+        dbus_g_proxy_call_no_reply (manager->proxy,
+                                    "CreateUser",
+                                    G_TYPE_STRING, user_name,
+                                    G_TYPE_STRING, real_name,
+                                    G_TYPE_INVALID);
+}
+
+void
+gdm_user_manager_delete_user (GdmUserManager *manager,
+                             GdmUser        *user,
+                             gboolean       remove_files)
+{
+        dbus_g_proxy_call_no_reply (manager->proxy,
+                                    "DeleteUser",
+                                    G_TYPE_INT64, gdm_user_get_uid (user),
+                                    G_TYPE_BOOLEAN, remove_files,
+                                    G_TYPE_INVALID);
 }
 
-static void
-on_shells_monitor_changed (GFileMonitor     *monitor,
-                           GFile            *file,
-                           GFile            *other_file,
-                           GFileMonitorEvent event_type,
-                           GdmUserManager   *manager)
+GSList *
+gdm_user_manager_list_users (GdmUserManager *manager)
 {
-        if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
-            event_type != G_FILE_MONITOR_EVENT_CREATED) {
-                return;
-        }
-
-        reload_shells (manager);
-        reload_passwd (manager);
-}
+        GSList *list = NULL;
+        GHashTableIter iter;
+        gpointer value;
 
-static void
-on_passwd_monitor_changed (GFileMonitor     *monitor,
-                           GFile            *file,
-                           GFile            *other_file,
-                           GFileMonitorEvent event_type,
-                           GdmUserManager   *manager)
-{
-        if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
-            event_type != G_FILE_MONITOR_EVENT_CREATED) {
-                return;
+        g_hash_table_iter_init (&iter, manager->user_by_name);
+        while (g_hash_table_iter_next (&iter, NULL, &value)) {
+                list = g_slist_prepend (list, value);
         }
 
-        reload_passwd (manager);
+        return g_slist_sort (list, (GCompareFunc) gdm_user_collate);
 }
 
-static void
-gdm_user_manager_class_init (GdmUserManagerClass *klass)
-{
-        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
-
-        object_class->finalize = gdm_user_manager_finalize;
-
-        signals [LOADING_USERS] =
-                g_signal_new ("loading-users",
-                              G_TYPE_FROM_CLASS (klass),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdmUserManagerClass, loading_users),
-                              NULL, NULL,
-                              g_cclosure_marshal_VOID__VOID,
-                              G_TYPE_NONE, 0);
-        signals [USERS_LOADED] =
-                g_signal_new ("users-loaded",
-                              G_TYPE_FROM_CLASS (klass),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdmUserManagerClass, users_loaded),
-                              NULL, NULL,
-                              g_cclosure_marshal_VOID__VOID,
-                              G_TYPE_NONE, 0);
-        signals [USER_ADDED] =
-                g_signal_new ("user-added",
-                              G_TYPE_FROM_CLASS (klass),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdmUserManagerClass, user_added),
-                              NULL, NULL,
-                              g_cclosure_marshal_VOID__OBJECT,
-                              G_TYPE_NONE, 1, GDM_TYPE_USER);
-        signals [USER_REMOVED] =
-                g_signal_new ("user-removed",
-                              G_TYPE_FROM_CLASS (klass),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdmUserManagerClass, user_removed),
-                              NULL, NULL,
-                              g_cclosure_marshal_VOID__OBJECT,
-                              G_TYPE_NONE, 1, GDM_TYPE_USER);
-        signals [USER_IS_LOGGED_IN_CHANGED] =
-                g_signal_new ("user-is-logged-in-changed",
-                              G_TYPE_FROM_CLASS (klass),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdmUserManagerClass, user_is_logged_in_changed),
-                              NULL, NULL,
-                              g_cclosure_marshal_VOID__OBJECT,
-                              G_TYPE_NONE, 1, GDM_TYPE_USER);
-        signals [USER_LOGIN_FREQUENCY_CHANGED] =
-                g_signal_new ("user-login-frequency-changed",
-                              G_TYPE_FROM_CLASS (klass),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdmUserManagerClass, user_login_frequency_changed),
-                              NULL, NULL,
-                              g_cclosure_marshal_VOID__OBJECT,
-                              G_TYPE_NONE, 1, GDM_TYPE_USER);
-
-        g_type_class_add_private (klass, sizeof (GdmUserManagerPrivate));
-}
-
-static void
-gdm_user_manager_init (GdmUserManager *manager)
+GdmUser *
+gdm_user_manager_get_user (GdmUserManager *manager,
+                          const gchar   *name)
 {
-        int            i;
-        GFile         *file;
-        GError        *error;
-        const char    *exclude_default[] = DEFAULT_EXCLUDE;
-
-        manager->priv = GDM_USER_MANAGER_GET_PRIVATE (manager);
-
-        /* sessions */
-        manager->priv->sessions = g_hash_table_new_full (g_str_hash,
-                                                         g_str_equal,
-                                                         g_free,
-                                                         g_free);
-
-        /* exclusions */
-        manager->priv->exclusions = g_hash_table_new_full (g_str_hash,
-                                                           g_str_equal,
-                                                           g_free,
-                                                           NULL);
-        for (i = 0; exclude_default[i] != NULL; i++) {
-                g_hash_table_insert (manager->priv->exclusions,
-                                     g_strdup (exclude_default [i]),
-                                     GUINT_TO_POINTER (TRUE));
-        }
-
-        /* /etc/shells */
-        manager->priv->shells = g_hash_table_new_full (g_str_hash,
-                                                       g_str_equal,
-                                                       g_free,
-                                                       NULL);
-        reload_shells (manager);
-        file = g_file_new_for_path (_PATH_SHELLS);
-        error = NULL;
-        manager->priv->shells_monitor = g_file_monitor_file (file,
-                                                             G_FILE_MONITOR_NONE,
-                                                             NULL,
-                                                             &error);
-        if (manager->priv->shells_monitor != NULL) {
-                g_signal_connect (manager->priv->shells_monitor,
-                                  "changed",
-                                  G_CALLBACK (on_shells_monitor_changed),
-                                  manager);
-        } else {
-                if (error != NULL) {
-                        g_warning ("Unable to monitor %s: %s", _PATH_SHELLS, error->message);
-                        g_error_free (error);
-                } else {
-                        g_warning ("Unable to monitor %s", _PATH_SHELLS);
-                }
-        }
-        g_object_unref (file);
-
-        /* /etc/passwd */
-        manager->priv->users = g_hash_table_new_full (g_str_hash,
-                                                      g_str_equal,
-                                                      g_free,
-                                                      (GDestroyNotify) g_object_run_dispose);
-        file = g_file_new_for_path (PATH_PASSWD);
-        manager->priv->passwd_monitor = g_file_monitor_file (file,
-                                                             G_FILE_MONITOR_NONE,
-                                                             NULL,
-                                                             &error);
-        if (manager->priv->passwd_monitor != NULL) {
-                g_signal_connect (manager->priv->passwd_monitor,
-                                  "changed",
-                                  G_CALLBACK (on_passwd_monitor_changed),
-                                  manager);
-        } else {
-                if (error != NULL) {
-                        g_warning ("Unable to monitor %s: %s", PATH_PASSWD, error->message);
-                        g_error_free (error);
-                } else {
-                        g_warning ("Unable to monitor %s", PATH_PASSWD);
-                }
-        }
-        g_object_unref (file);
-
-
-        get_seat_proxy (manager);
-
-        queue_reload_users (manager);
-
-        manager->priv->users_dirty = FALSE;
+        return g_hash_table_lookup (manager->user_by_name, name);
 }
 
-static void
-gdm_user_manager_finalize (GObject *object)
+GdmUser *
+gdm_user_manager_get_user_by_id (GdmUserManager *manager,
+                                uid_t          uid)
 {
-        GdmUserManager *manager;
-
-        g_return_if_fail (object != NULL);
-        g_return_if_fail (GDM_IS_USER_MANAGER (object));
-
-        manager = GDM_USER_MANAGER (object);
-
-        g_return_if_fail (manager->priv != NULL);
-
-        if (manager->priv->seat_proxy != NULL) {
-                g_object_unref (manager->priv->seat_proxy);
-        }
+        struct  passwd *pwent;
 
-        if (manager->priv->ck_history_id != 0) {
-                g_source_remove (manager->priv->ck_history_id);
-                manager->priv->ck_history_id = 0;
-        }
-
-        if (manager->priv->reload_id > 0) {
-                g_source_remove (manager->priv->reload_id);
-                manager->priv->reload_id = 0;
+        pwent = getpwuid (uid);
+        if (!pwent) {
+                return NULL;
         }
 
-        g_hash_table_destroy (manager->priv->sessions);
-
-        g_file_monitor_cancel (manager->priv->passwd_monitor);
-        g_hash_table_destroy (manager->priv->users);
-
-        g_file_monitor_cancel (manager->priv->shells_monitor);
-        g_hash_table_destroy (manager->priv->shells);
-
-        g_free (manager->priv->seat_id);
-
-        G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object);
+        return gdm_user_manager_get_user (manager, pwent->pw_name);
 }
 
-GdmUserManager *
-gdm_user_manager_ref_default (void)
+gboolean
+gdm_user_manager_no_service (GdmUserManager *manager)
 {
-        if (user_manager_object != NULL) {
-                g_object_ref (user_manager_object);
-        } else {
-                user_manager_object = g_object_new (GDM_TYPE_USER_MANAGER, NULL);
-                g_object_add_weak_pointer (user_manager_object,
-                                           (gpointer *) &user_manager_object);
-        }
-
-        return GDM_USER_MANAGER (user_manager_object);
+        return manager->no_service;
 }
diff -u -r gdm-2.28.2.pristine/gui/simple-greeter/gdm-user-manager.h gdm-2.28.2/gui/simple-greeter/gdm-user-manager.h
--- gdm-2.28.2.pristine/gui/simple-greeter/gdm-user-manager.h	2010-01-22 11:17:50.300384192 -0500
+++ gdm-2.28.2/gui/simple-greeter/gdm-user-manager.h	2010-01-24 00:14:29.430538656 -0500
@@ -1,10 +1,10 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ * Copyright (C) 2009-2010 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
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -18,10 +18,11 @@
  *
  */
 
-#ifndef __GDM_USER_MANAGER_H
-#define __GDM_USER_MANAGER_H
+#ifndef __GDM_USER_MANAGER__
+#define __GDM_USER_MANAGER__
 
 #include <glib-object.h>
+#include <dbus/dbus-glib.h>
 
 #include "gdm-user.h"
 
@@ -34,54 +35,57 @@
 #define GDM_IS_USER_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_MANAGER))
 #define GDM_USER_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_MANAGER, GdmUserManagerClass))
 
-typedef struct GdmUserManagerPrivate GdmUserManagerPrivate;
-
 typedef struct
 {
-        GObject                parent;
-        GdmUserManagerPrivate *priv;
+        GObject parent;
+
+        DBusGConnection *bus;
+        DBusGProxy *proxy;
+
+        GHashTable *user_by_object_path;
+        GHashTable *user_by_name;
+
+        gboolean no_service;
+
+        GHashTable *sessions;
+        DBusGProxy *seat_proxy;
+        gchar      *seat_id;
 } GdmUserManager;
 
 typedef struct
 {
         GObjectClass   parent_class;
 
-        void          (* loading_users)             (GdmUserManager *user_manager);
-        void          (* users_loaded)              (GdmUserManager *user_manager);
+        void          (* users_loaded)              (GdmUserManager *user_managaer);
         void          (* user_added)                (GdmUserManager *user_manager,
                                                      GdmUser        *user);
         void          (* user_removed)              (GdmUserManager *user_manager,
                                                      GdmUser        *user);
+        void          (* user_changed)              (GdmUserManager *user_manager,
+                                                     GdmUser        *user);
         void          (* user_is_logged_in_changed) (GdmUserManager *user_manager,
                                                      GdmUser        *user);
-        void          (* user_login_frequency_changed) (GdmUserManager *user_manager,
-                                                        GdmUser        *user);
 } GdmUserManagerClass;
 
-typedef enum
-{
-        GDM_USER_MANAGER_ERROR_GENERAL,
-        GDM_USER_MANAGER_ERROR_KEY_NOT_FOUND
-} GdmUserManagerError;
-
-#define GDM_USER_MANAGER_ERROR gdm_user_manager_error_quark ()
 
-GQuark              gdm_user_manager_error_quark           (void);
-GType               gdm_user_manager_get_type              (void);
+GType              gdm_user_manager_get_type              (void);
 
 GdmUserManager *    gdm_user_manager_ref_default           (void);
 
-GSList *            gdm_user_manager_list_users            (GdmUserManager *manager);
-GdmUser *           gdm_user_manager_get_user              (GdmUserManager *manager,
-                                                            const char     *user_name);
-GdmUser *           gdm_user_manager_get_user_by_uid       (GdmUserManager *manager,
-                                                            uid_t           uid);
+gboolean           gdm_user_manager_no_service            (GdmUserManager *manager);
 
-gboolean            gdm_user_manager_activate_user_session (GdmUserManager *manager,
-                                                            GdmUser        *user);
-
-gboolean            gdm_user_manager_goto_login_session    (GdmUserManager *manager);
+GSList *           gdm_user_manager_list_users            (GdmUserManager *manager);
+GdmUser *           gdm_user_manager_get_user              (GdmUserManager *manager,
+                                                          const char    *user_name);
+GdmUser *           gdm_user_manager_get_user_by_id        (GdmUserManager *manager,
+                                                          uid_t          uid);
+void               gdm_user_manager_create_user           (GdmUserManager *manager,
+                                                          const char    *user_name,
+                                                          const char    *real_name);
+void               gdm_user_manager_delete_user           (GdmUserManager *manager,
+                                                          GdmUser        *user,
+                                                          gboolean       remove_files);
 
 G_END_DECLS
 
-#endif /* __GDM_USER_MANAGER_H */
+#endif /* __GDM_USER_MANAGER__ */
diff -u -r gdm-2.28.2.pristine/gui/simple-greeter/gdm-user-private.h gdm-2.28.2/gui/simple-greeter/gdm-user-private.h
--- gdm-2.28.2.pristine/gui/simple-greeter/gdm-user-private.h	2010-01-22 11:17:50.325386253 -0500
+++ gdm-2.28.2/gui/simple-greeter/gdm-user-private.h	2010-01-23 22:13:18.335788575 -0500
@@ -30,15 +30,11 @@
 
 G_BEGIN_DECLS
 
-void _gdm_user_update           (GdmUser             *user,
-                                 const struct passwd *pwent);
 void _gdm_user_add_session      (GdmUser             *user,
                                  const char          *session_id);
 void _gdm_user_remove_session   (GdmUser             *user,
                                  const char          *session_id);
 
-void _gdm_user_icon_changed     (GdmUser             *user);
-
 void _gdm_user_show_full_display_name (GdmUser   *user);
 void _gdm_user_show_short_display_name  (GdmUser   *user);
 
