]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
Refactor liblightdm user scanning to be simpler and more reliable. This fixes bugs...
authorRobert Ancell <robert.ancell@canonical.com>
Wed, 30 Oct 2013 00:14:02 +0000 (00:14 +0000)
committerTarmac <Unknown>
Wed, 30 Oct 2013 00:14:02 +0000 (00:14 +0000)
Approved by PS Jenkins bot, Robert Ancell.

debian/patches/01_transition_ubuntu2d_ubuntu_desktop.patch
liblightdm-gobject/user.c
tests/src/status.c
tests/src/test-runner.c

index b5275b400717c52b4baf5d4cb01c8bc9c1b8b4a1..5a51e1a244ef166f404eb2e8e2e3499cc1bc6605 100644 (file)
@@ -2,20 +2,20 @@
 #              starting from quantal. llvmpipe is used in case no hardware
 #              acceleration is available.
 === modified file 'liblightdm-gobject/user.c'
-Index: lightdm-1.7.4/liblightdm-gobject/user.c
+Index: user-refactor/liblightdm-gobject/user.c
 ===================================================================
---- lightdm-1.7.4.orig/liblightdm-gobject/user.c       2013-07-01 15:49:24.038864562 +1200
-+++ lightdm-1.7.4/liblightdm-gobject/user.c    2013-07-01 15:49:24.034864562 +1200
-@@ -1307,6 +1307,12 @@
-     load_dmrc (user);
-     load_accounts_service (user); // overrides dmrc values
+--- user-refactor.orig/liblightdm-gobject/user.c       2013-10-29 16:16:48.505903621 -0700
++++ user-refactor/liblightdm-gobject/user.c    2013-10-29 16:16:48.501905620 -0700
+@@ -1115,6 +1115,12 @@
+         load_accounts_user (user);
+     else
+         load_dmrc (user);
++ 
 +    if (g_strcmp0 (priv->session, "ubuntu-2d") == 0)
 +    {
 +        g_free(priv->session);
 +        priv->session = g_strdup ("ubuntu");
 +    }
-+
-     /* Ensure a few guarantees */
-     if (priv->layouts == NULL)
-     {
+ }
+ /**
index d8bd2e083a3074f5b504f3abf5c21962fbba5230..aaed5855fb3c5794cce06cbd781705e04655014f 100644 (file)
@@ -61,16 +61,20 @@ static guint user_signals[LAST_USER_SIGNAL] = { 0 };
 
 typedef struct
 {
-    /* Connection to AccountsService */
-    GDBusProxy *accounts_service_proxy;
-    GList *user_account_objects;
+    /* Bus connection being communicated on */
+    GDBusConnection *bus;
 
-    /* Connection to DisplayManager */
-    GDBusProxy *display_manager_proxy;
+    /* D-Bus signals for accounts service events */
+    guint user_added_signal;
+    guint user_removed_signal;
+
+    /* D-Bus signals for display manager events */
+    guint session_added_signal;
+    guint session_removed_signal;
 
     /* File monitor for password file */
     GFileMonitor *passwd_monitor;
-  
+
     /* TRUE if have scanned users */
     gboolean have_users;
 
@@ -83,24 +87,46 @@ typedef struct
 
 typedef struct
 {
-    GDBusProxy *proxy;
-    LightDMUser *user;
-} UserAccountObject;
-
-typedef struct
-{
+    /* User list this user is part of */
     LightDMUserList *user_list;
 
+    /* TRUE if have loaded user properties */
+    gboolean loaded_values;
+
+    /* Accounts service path */
+    gchar *path;
+
+    /* DMRC file */
+    GKeyFile *dmrc_file;
+
+    /* Update signal from accounts service */
+    guint changed_signal;
+
+    /* Username */
     gchar *name;
+
+    /* Descriptive name for user */
     gchar *real_name;
+
+    /* Home directory of user */
     gchar *home_directory;
+
+    /* Image for user */
     gchar *image;
+
+    /* Background image for users */
     gchar *background;
+
+    /* TRUE if this user has messages available */
     gboolean has_messages;
 
-    GKeyFile *dmrc_file;
+    /* User chosen language */
     gchar *language;
+
+    /* User layout preferences */
     gchar **layouts;
+
+    /* User default session */
     gchar *session;
 } LightDMUserPrivate;
 
@@ -154,7 +180,23 @@ get_user_by_name (LightDMUserList *user_list, const gchar *username)
     for (link = priv->users; link; link = link->next)
     {
         LightDMUser *user = link->data;
-        if (strcmp (lightdm_user_get_name (user), username) == 0)
+        if (g_strcmp0 (lightdm_user_get_name (user), username) == 0)
+            return user;
+    }
+
+    return NULL;
+}
+
+static LightDMUser *
+get_user_by_path (LightDMUserList *user_list, const gchar *path)
+{
+    LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
+    GList *link;
+  
+    for (link = priv->users; link; link = link->next)
+    {
+        LightDMUser *user = link->data;
+        if (g_strcmp0 (GET_USER_PRIVATE (user)->path, path) == 0)
             return user;
     }
 
@@ -165,7 +207,7 @@ static gint
 compare_user (gconstpointer a, gconstpointer b)
 {
     LightDMUser *user_a = (LightDMUser *) a, *user_b = (LightDMUser *) b;
-    return strcmp (lightdm_user_get_display_name (user_a), lightdm_user_get_display_name (user_b));
+    return g_strcmp0 (lightdm_user_get_display_name (user_a), lightdm_user_get_display_name (user_b));
 }
 
 static gboolean
@@ -173,6 +215,7 @@ update_passwd_user (LightDMUser *user, const gchar *real_name, const gchar *home
 {
     LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
 
+    /* Skip if already set to this */
     if (g_strcmp0 (lightdm_user_get_real_name (user), real_name) == 0 &&
         g_strcmp0 (lightdm_user_get_home_directory (user), home_directory) == 0 &&
         g_strcmp0 (lightdm_user_get_image (user), image) == 0)
@@ -189,9 +232,9 @@ update_passwd_user (LightDMUser *user, const gchar *real_name, const gchar *home
 }
 
 static void
-user_changed_cb (LightDMUser *user, LightDMUserList *user_list)
+user_changed_cb (LightDMUser *user)
 {
-    g_signal_emit (user_list, list_signals[USER_CHANGED], 0, user);
+    g_signal_emit (GET_USER_PRIVATE (user)->user_list, list_signals[USER_CHANGED], 0, user);
 }
 
 static void
@@ -334,7 +377,7 @@ load_passwd_file (LightDMUserList *user_list, gboolean emit_add_signal)
     {
         LightDMUser *info = link->data;
         g_debug ("User %s added", lightdm_user_get_name (info));
-        g_signal_connect (info, "changed", G_CALLBACK (user_changed_cb), user_list);
+        g_signal_connect (info, "changed", G_CALLBACK (user_changed_cb), NULL);
         if (emit_add_signal)
             g_signal_emit (user_list, list_signals[USER_ADDED], 0, info);
     }
@@ -378,18 +421,49 @@ passwd_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileM
     }
 }
 
+static gboolean load_accounts_user (LightDMUser *user);
+
+static void
+accounts_user_changed_cb (GDBusConnection *connection,
+                          const gchar *sender_name,
+                          const gchar *object_path,
+                          const gchar *interface_name,
+                          const gchar *signal_name,
+                          GVariant *parameters,
+                          gpointer data)
+{
+    LightDMUser *user = data;
+    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);  
+
+    g_debug ("User %s changed", priv->path);
+    load_accounts_user (user);
+    g_signal_emit (user, user_signals[CHANGED], 0);
+}
+
 static gboolean
-update_user (UserAccountObject *object)
+load_accounts_user (LightDMUser *user)
 {
-    LightDMUserPrivate *priv = GET_USER_PRIVATE (object->user);
+    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
     GVariant *result, *value;
     GVariantIter *iter;
     gchar *name;
     GError *error = NULL;
 
-    result = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (object->proxy),
+    /* Get the properties for this user */
+    if (!priv->changed_signal)
+        priv->changed_signal = g_dbus_connection_signal_subscribe (GET_LIST_PRIVATE (priv->user_list)->bus,
+                                                                   "org.freedesktop.Accounts",
+                                                                   "org.freedesktop.Accounts.User",
+                                                                   "Changed",
+                                                                   priv->path,
+                                                                   NULL,
+                                                                   G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                   accounts_user_changed_cb,
+                                                                   user,
+                                                                   NULL);
+    result = g_dbus_connection_call_sync (GET_LIST_PRIVATE (priv->user_list)->bus,
                                           "org.freedesktop.Accounts",
-                                          g_dbus_proxy_get_object_path (object->proxy),
+                                          priv->path,
                                           "org.freedesktop.DBus.Properties",
                                           "GetAll",
                                           g_variant_new ("(s)", "org.freedesktop.Accounts.User"),
@@ -399,55 +473,73 @@ update_user (UserAccountObject *object)
                                           NULL,
                                           &error);
     if (error)
-        g_warning ("Error updating user %s: %s", g_dbus_proxy_get_object_path (object->proxy), error->message);
+        g_warning ("Error updating user %s: %s", priv->path, error->message);
     g_clear_error (&error);
     if (!result)
         return FALSE;
 
+    /* Store the properties we need */
     g_variant_get (result, "(a{sv})", &iter);
     while (g_variant_iter_loop (iter, "{&sv}", &name, &value))
     {
         if (strcmp (name, "UserName") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
         {
-            gchar *user_name;
-            g_variant_get (value, "&s", &user_name);
             g_free (priv->name);
-            priv->name = g_strdup (user_name);
+            priv->name = g_variant_dup_string (value, NULL);
         }
         else if (strcmp (name, "RealName") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
         {
-            gchar *real_name;
-            g_variant_get (value, "&s", &real_name);
             g_free (priv->real_name);
-            priv->real_name = g_strdup (real_name);
+            priv->real_name = g_variant_dup_string (value, NULL);
         }
         else if (strcmp (name, "HomeDirectory") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
         {
-            gchar *home_directory;
-            g_variant_get (value, "&s", &home_directory);
             g_free (priv->home_directory);
-            priv->home_directory = g_strdup (home_directory);
+            priv->home_directory = g_variant_dup_string (value, NULL);
+        }
+        else if (strcmp (name, "Language") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+        {
+            if (priv->language)
+                g_free (priv->language);
+            priv->language = g_variant_dup_string (value, NULL);
         }
         else if (strcmp (name, "IconFile") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
         {
-            gchar *icon_file;
-            g_variant_get (value, "&s", &icon_file);
             g_free (priv->image);
-            if (strcmp (icon_file, "") == 0)
+            priv->image = g_variant_dup_string (value, NULL);
+            if (strcmp (priv->image, "") == 0)
+            {
+                g_free (priv->image);
                 priv->image = NULL;
-            else
-                priv->image = g_strdup (icon_file);
+            }
+        }
+        else if (strcmp (name, "XSession") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+        {
+            g_free (priv->session);
+            priv->session = g_variant_dup_string (value, NULL);
         }
         else if (strcmp (name, "BackgroundFile") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
         {
-            gchar *background_file;
-            g_variant_get (value, "&s", &background_file);
             g_free (priv->background);
-            if (strcmp (background_file, "") == 0)
+            priv->background = g_variant_dup_string (value, NULL);
+            if (strcmp (priv->background, "") == 0)
+            {
+                g_free (priv->background);
                 priv->background = NULL;
-            else
-                priv->background = g_strdup (background_file);
+            }
+        }
+        else if (strcmp (name, "XKeyboardLayouts") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING_ARRAY))
+        {
+            g_strfreev (priv->layouts);
+            priv->layouts = g_variant_dup_strv (value, NULL);
+            if (!priv->layouts)
+            {
+                priv->layouts = g_malloc (sizeof (gchar *) * 1);
+                priv->layouts[0] = NULL;
+            }
         }
+        else if (strcmp (name, "XHasMessages") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
+            priv->has_messages = g_variant_get_boolean (value);
     }
     g_variant_iter_free (iter);
 
@@ -457,135 +549,83 @@ update_user (UserAccountObject *object)
 }
 
 static void
-user_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, UserAccountObject *object)
-{
-    if (strcmp (signal_name, "Changed") == 0)
-    {
-        if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("()")))
-        {
-            g_debug ("User %s changed", g_dbus_proxy_get_object_path (object->proxy));
-            update_user (object);
-            g_signal_emit (object->user, user_signals[CHANGED], 0);
-        }
-        else
-            g_warning ("Got org.freedesktop.Accounts.User signal Changed with unknown parameters %s", g_variant_get_type_string (parameters));
-    }
-}
-
-static UserAccountObject *
-user_account_object_new (LightDMUserList *user_list, const gchar *path)
+add_accounts_user (LightDMUserList *user_list, const gchar *path, gboolean emit_signal)
 {
-    GDBusProxy *proxy;
-    UserAccountObject *object;
-    GError *error = NULL;
+    LightDMUserListPrivate *list_priv = GET_LIST_PRIVATE (user_list);
+    LightDMUser *user;
+    LightDMUserPrivate *priv;
 
-    proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-                                           G_DBUS_PROXY_FLAGS_NONE,
-                                           NULL,
-                                           "org.freedesktop.Accounts",
-                                           path,
-                                           "org.freedesktop.Accounts.User",
-                                           NULL,
-                                           &error);
-    if (error)
-        g_warning ("Error getting user %s: %s", path, error->message);
-    g_clear_error (&error);
-    if (!proxy)
-        return NULL;
+    user = g_object_new (LIGHTDM_TYPE_USER, NULL);
+    priv = GET_USER_PRIVATE (user);
 
-    object = g_malloc0 (sizeof (UserAccountObject));  
-    object->user = g_object_new (LIGHTDM_TYPE_USER, NULL);
-    GET_USER_PRIVATE (object->user)->user_list = user_list;
-    object->proxy = proxy;
-    g_signal_connect (proxy, "g-signal", G_CALLBACK (user_signal_cb), object);
-  
-    return object;
+    g_debug ("User %s added", path);
+    priv->user_list = user_list;
+    priv->path = g_strdup (path);
+    list_priv->users = g_list_insert_sorted (list_priv->users, user, compare_user);
+    g_signal_connect (user, "changed", G_CALLBACK (user_changed_cb), NULL);
+    if (emit_signal)
+        g_signal_emit (user_list, list_signals[USER_ADDED], 0, user);
 }
 
 static void
-user_account_object_free (UserAccountObject *object)
+accounts_user_added_cb (GDBusConnection *connection,
+                        const gchar *sender_name,
+                        const gchar *object_path,
+                        const gchar *interface_name,
+                        const gchar *signal_name,
+                        GVariant *parameters,
+                        gpointer data)
 {
-    if (!object)
-        return;
-    g_object_unref (object->user);
-    g_object_unref (object->proxy);
-    g_free (object);
-}
-
-static UserAccountObject *
-find_user_account_object (LightDMUserList *user_list, const gchar *path)
-{
-    LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
-    GList *link;
-
-    for (link = priv->user_account_objects; link; link = link->next)
+    LightDMUserList *user_list = data;
+    gchar *path;
+    LightDMUser *user;
+  
+    if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
     {
-        UserAccountObject *object = link->data;
-        if (strcmp (g_dbus_proxy_get_object_path (object->proxy), path) == 0)
-            return object;
+        g_warning ("Got UserAccounts signal UserAdded with unknown parameters %s", g_variant_get_type_string (parameters));
+        return;
     }
 
-    return NULL;
+    g_variant_get (parameters, "(&o)", &path);
+
+    /* Add user if we haven't got them */
+    user = get_user_by_path (user_list, path);
+    if (!user)
+        add_accounts_user (user_list, path, TRUE);
 }
 
 static void
-user_accounts_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, LightDMUserList *user_list)
+accounts_user_deleted_cb (GDBusConnection *connection,
+                          const gchar *sender_name,
+                          const gchar *object_path,
+                          const gchar *interface_name,
+                          const gchar *signal_name,
+                          GVariant *parameters,
+                          gpointer data)
 {
+    LightDMUserList *user_list = data;
     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
-  
-    if (strcmp (signal_name, "UserAdded") == 0)
-    {
-        if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
-        {
-            gchar *path;
-            UserAccountObject *object;
-
-            g_variant_get (parameters, "(&o)", &path);
-
-            /* Ignore duplicate requests */
-            object = find_user_account_object (user_list, path);
-            if (object)
-                return;
+    gchar *path;
+    LightDMUser *user;
 
-            object = user_account_object_new (user_list, path);
-            if (object && update_user (object))
-            {
-                g_debug ("User %s added", path);
-                priv->user_account_objects = g_list_append (priv->user_account_objects, object);
-                priv->users = g_list_insert_sorted (priv->users, g_object_ref (object->user), compare_user);
-                g_signal_connect (object->user, "changed", G_CALLBACK (user_changed_cb), user_list);
-                g_signal_emit (user_list, list_signals[USER_ADDED], 0, object->user);
-            }
-            else
-                user_account_object_free (object);
-        }
-        else
-            g_warning ("Got UserAccounts signal UserAdded with unknown parameters %s", g_variant_get_type_string (parameters));
-    }
-    else if (strcmp (signal_name, "UserDeleted") == 0)
+    if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
     {
-        if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
-        {
-            gchar *path;
-            UserAccountObject *object;
-
-            g_variant_get (parameters, "(&o)", &path);
+        g_warning ("Got UserAccounts signal UserDeleted with unknown parameters %s", g_variant_get_type_string (parameters));
+        return;
+    }
 
-            object = find_user_account_object (user_list, path);
-            if (!object)
-                return;
+    g_variant_get (parameters, "(&o)", &path);
 
-            g_debug ("User %s deleted", path);
-            priv->users = g_list_remove (priv->users, object->user);
-            g_object_unref (object->user);
+    /* Delete user if we know of them */
+    user = get_user_by_path (user_list, path);
+    if (user)
+    {
+        g_debug ("User %s deleted", path);
+        priv->users = g_list_remove (priv->users, user);
 
-            g_signal_emit (user_list, list_signals[USER_REMOVED], 0, object->user);
+        g_signal_emit (user_list, list_signals[USER_REMOVED], 0, user);
 
-            priv->user_account_objects = g_list_remove (priv->user_account_objects, object);
-            user_account_object_free (object);
-        }
-        else
-            g_warning ("Got UserAccounts signal UserDeleted with unknown parameters %s", g_variant_get_type_string (parameters));
+        g_object_unref (user);
     }
 }
 
@@ -597,7 +637,7 @@ load_session (LightDMUserList *user_list, const gchar *path)
     GVariant *result, *username;
     GError *error = NULL;
 
-    result = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (priv->display_manager_proxy),
+    result = g_dbus_connection_call_sync (priv->bus,
                                           "org.freedesktop.DisplayManager",
                                           path,
                                           "org.freedesktop.DBus.Properties",
@@ -634,145 +674,140 @@ load_session (LightDMUserList *user_list, const gchar *path)
 }
 
 static void
-display_manager_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, LightDMUserList *user_list)
+session_added_cb (GDBusConnection *connection,
+                  const gchar *sender_name,
+                  const gchar *object_path,
+                  const gchar *interface_name,
+                  const gchar *signal_name,
+                  GVariant *parameters,
+                  gpointer data)
+{
+    LightDMUserList *user_list = data;
+    gchar *path;
+    Session *session;
+    LightDMUser *user = NULL;
+
+    if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
+    {
+        g_warning ("Got DisplayManager signal SessionAdded with unknown parameters %s", g_variant_get_type_string (parameters));
+        return;
+    }
+
+    g_variant_get (parameters, "(&o)", &path);
+    session = load_session (user_list, path);
+    if (session)
+        user = get_user_by_name (user_list, session->username);
+    if (user)
+        g_signal_emit (user, user_signals[CHANGED], 0);
+}
+
+static void
+session_removed_cb (GDBusConnection *connection,
+                    const gchar *sender_name,
+                    const gchar *object_path,
+                    const gchar *interface_name,
+                    const gchar *signal_name,
+                    GVariant *parameters,
+                    gpointer data)
 {
+    LightDMUserList *user_list = data;
     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
+    gchar *path;
+    GList *link;
 
-    if (strcmp (signal_name, "SessionAdded") == 0)
+    if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
     {
-        if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
-        {
-            gchar *path;
-            Session *session;
-            LightDMUser *user = NULL;
-
-            g_variant_get (parameters, "(&o)", &path);
-            session = load_session (user_list, path);
-            if (session)
-                user = get_user_by_name (user_list, session->username);
-            if (user)
-                g_signal_emit (user, user_signals[CHANGED], 0);
-        }
+        g_warning ("Got DisplayManager signal SessionRemoved with unknown parameters %s", g_variant_get_type_string (parameters));
+        return;
     }
-    else if (strcmp (signal_name, "SessionRemoved") == 0)
+
+    g_variant_get (parameters, "(&o)", &path);
+
+    for (link = priv->sessions; link; link = link->next)
     {
-        if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)")))
+        Session *session = link->data;
+        if (strcmp (session->path, path) == 0)
         {
-            gchar *path;
-            GList *link;
-
-            g_variant_get (parameters, "(&o)", &path);
+            LightDMUser *user;
 
-            for (link = priv->sessions; link; link = link->next)
-            {
-                Session *session = link->data;
-                if (strcmp (session->path, path) == 0)
-                {
-                    LightDMUser *user;
-
-                    g_debug ("Session %s removed", path);
-                    priv->sessions = g_list_remove_link (priv->sessions, link);
-                    user = get_user_by_name (user_list, session->username);
-                    if (user)
-                        g_signal_emit (user, user_signals[CHANGED], 0);
-                    g_object_unref (session);
-                    break;
-                }
-            }
+            g_debug ("Session %s removed", path);
+            priv->sessions = g_list_remove_link (priv->sessions, link);
+            user = get_user_by_name (user_list, session->username);
+            if (user)
+                g_signal_emit (user, user_signals[CHANGED], 0);
+            g_object_unref (session);
+            break;
         }
     }
 }
 
 static void
-update_users (LightDMUserList *user_list)
+load_users (LightDMUserList *user_list)
 {
     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
+    GVariant *result;
     GError *error = NULL;
 
     if (priv->have_users)
         return;
     priv->have_users = TRUE;
 
-    priv->accounts_service_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-                                                                  G_DBUS_PROXY_FLAGS_NONE,
-                                                                  NULL,
+    /* Get user list from accounts service and fall back to /etc/passwd if that fails */
+    priv->user_added_signal = g_dbus_connection_signal_subscribe (priv->bus,
                                                                   "org.freedesktop.Accounts",
-                                                                  "/org/freedesktop/Accounts",
                                                                   "org.freedesktop.Accounts",
+                                                                  "UserAdded",
+                                                                  "/org/freedesktop/Accounts",
                                                                   NULL,
-                                                                  &error);
+                                                                  G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                  accounts_user_added_cb,
+                                                                  user_list,
+                                                                  NULL);
+    priv->user_removed_signal = g_dbus_connection_signal_subscribe (priv->bus,
+                                                                    "org.freedesktop.Accounts",
+                                                                    "org.freedesktop.Accounts",
+                                                                    "UserDeleted",
+                                                                    "/org/freedesktop/Accounts",
+                                                                    NULL,
+                                                                    G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                    accounts_user_deleted_cb,
+                                                                    user_list,
+                                                                    NULL);
+    result = g_dbus_connection_call_sync (priv->bus,
+                                          "org.freedesktop.Accounts",
+                                          "/org/freedesktop/Accounts",
+                                          "org.freedesktop.Accounts",
+                                          "ListCachedUsers",
+                                          g_variant_new ("()"),
+                                          G_VARIANT_TYPE ("(ao)"),
+                                          G_DBUS_CALL_FLAGS_NONE,
+                                          -1,
+                                          NULL,
+                                          &error);
     if (error)
-        g_warning ("Error contacting org.freedesktop.Accounts: %s", error->message);
+        g_warning ("Error getting user list from org.freedesktop.Accounts: %s", error->message);
     g_clear_error (&error);
-
-    /* Check if the service exists */
-    if (priv->accounts_service_proxy)
+    if (result)
     {
-        gchar *name;
-
-        name = g_dbus_proxy_get_name_owner (priv->accounts_service_proxy);
-        if (!name)
-        {
-            g_debug ("org.freedesktop.Accounts does not exist, falling back to passwd file");
-            g_object_unref (priv->accounts_service_proxy);
-            priv->accounts_service_proxy = NULL;
-        }
-        g_free (name);
-    }
-
-    if (priv->accounts_service_proxy)
-    {
-        GVariant *result;
-
-        g_signal_connect (priv->accounts_service_proxy, "g-signal", G_CALLBACK (user_accounts_signal_cb), user_list);
-
-        result = g_dbus_proxy_call_sync (priv->accounts_service_proxy,
-                                         "ListCachedUsers",
-                                         g_variant_new ("()"),
-                                         G_DBUS_CALL_FLAGS_NONE,
-                                         -1,
-                                         NULL,
-                                         &error);
-        if (error)
-            g_warning ("Error getting user list from org.freedesktop.Accounts: %s", error->message);
-        g_clear_error (&error);
-        if (!result)
-            return;
-
-        if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(ao)")))
-        {
-            GVariantIter *iter;
-            const gchar *path;
-
-            g_debug ("Loading users from org.freedesktop.Accounts");
-            g_variant_get (result, "(ao)", &iter);
-            while (g_variant_iter_loop (iter, "&o", &path))
-            {
-                UserAccountObject *object;
-
-                g_debug ("Loading user %s", path);
-
-                object = user_account_object_new (user_list, path);
-                if (object && update_user (object))
-                {
-                    priv->user_account_objects = g_list_append (priv->user_account_objects, object);
-                    priv->users = g_list_insert_sorted (priv->users, g_object_ref (object->user), compare_user);
-                    g_signal_connect (object->user, "changed", G_CALLBACK (user_changed_cb), user_list);
-                }
-                else
-                    user_account_object_free (object);
-            }
-            g_variant_iter_free (iter);
-        }
-        else
-            g_warning ("Unexpected type from ListCachedUsers: %s", g_variant_get_type_string (result));
-
+        GVariantIter *iter;
+        const gchar *path;
+
+        g_debug ("Loading users from org.freedesktop.Accounts");
+        g_variant_get (result, "(ao)", &iter);
+        while (g_variant_iter_loop (iter, "&o", &path))
+            add_accounts_user (user_list, path, FALSE);
+        g_variant_iter_free (iter);
         g_variant_unref (result);
     }
     else
     {
         GFile *passwd_file;
 
+        g_dbus_connection_signal_unsubscribe (priv->bus, priv->user_added_signal);
+        priv->user_added_signal = 0;
+        g_dbus_connection_signal_unsubscribe (priv->bus, priv->user_removed_signal);
+        priv->user_removed_signal = 0;
+
         load_passwd_file (user_list, FALSE);
 
         /* Watch for changes to user list */
@@ -787,41 +822,43 @@ update_users (LightDMUserList *user_list)
         g_clear_error (&error);
     }
 
-    priv->display_manager_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-                                                                 G_DBUS_PROXY_FLAGS_NONE,
-                                                                 NULL,
-                                                                 "org.freedesktop.DisplayManager",
-                                                                 "/org/freedesktop/DisplayManager",
-                                                                 "org.freedesktop.DisplayManager",
-                                                                 NULL,
-                                                                 &error);
+    priv->session_added_signal = g_dbus_connection_signal_subscribe (priv->bus,
+                                                                     "org.freedesktop.DisplayManager",
+                                                                     "org.freedesktop.DisplayManager",
+                                                                     "SessionAdded",
+                                                                     "/org/freedesktop/DisplayManager",
+                                                                     NULL,
+                                                                     G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                     session_added_cb,
+                                                                     user_list,
+                                                                     NULL);
+    priv->session_removed_signal = g_dbus_connection_signal_subscribe (priv->bus,
+                                                                       "org.freedesktop.DisplayManager",
+                                                                       "org.freedesktop.DisplayManager",
+                                                                       "SessionRemoved",
+                                                                       "/org/freedesktop/DisplayManager",
+                                                                       NULL,
+                                                                       G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                       session_removed_cb,
+
+                                                                    user_list,
+                                                                    NULL);
+    result = g_dbus_connection_call_sync (priv->bus,
+                                          "org.freedesktop.DisplayManager",
+                                          "/org/freedesktop/DisplayManager",
+                                          "org.freedesktop.DBus.Properties",
+                                          "Get",
+                                          g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"),
+                                          G_VARIANT_TYPE ("(v)"),
+                                          G_DBUS_CALL_FLAGS_NONE,
+                                          -1,
+                                          NULL,
+                                          &error);
     if (error)
-        g_warning ("Error contacting org.freedesktop.DisplayManager: %s", error->message);
+        g_warning ("Error getting session list from org.freedesktop.DisplayManager: %s", error->message);
     g_clear_error (&error);
-
-    if (priv->display_manager_proxy)
+    if (result)
     {
-        GVariant *result;
-
-        g_signal_connect (priv->display_manager_proxy, "g-signal", G_CALLBACK (display_manager_signal_cb), user_list);
-
-        result = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (priv->display_manager_proxy),
-                                              "org.freedesktop.DisplayManager",
-                                              "/org/freedesktop/DisplayManager",
-                                              "org.freedesktop.DBus.Properties",
-                                              "Get",
-                                              g_variant_new ("(ss)", "org.freedesktop.DisplayManager", "Sessions"),
-                                              G_VARIANT_TYPE ("(v)"),
-                                              G_DBUS_CALL_FLAGS_NONE,
-                                              -1,
-                                              NULL,
-                                              &error);
-        if (error)
-            g_warning ("Error getting session list from org.freedesktop.DisplayManager: %s", error->message);
-        g_clear_error (&error);
-        if (!result)
-            return;
-
         if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(v)")))
         {
             GVariant *value;
@@ -855,7 +892,7 @@ gint
 lightdm_user_list_get_length (LightDMUserList *user_list)
 {
     g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), 0);
-    update_users (user_list);
+    load_users (user_list);
     return g_list_length (GET_LIST_PRIVATE (user_list)->users);
 }
 
@@ -872,7 +909,7 @@ GList *
 lightdm_user_list_get_users (LightDMUserList *user_list)
 {
     g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
-    update_users (user_list);
+    load_users (user_list);
     return GET_LIST_PRIVATE (user_list)->users;
 }
 
@@ -891,7 +928,7 @@ lightdm_user_list_get_user_by_name (LightDMUserList *user_list, const gchar *use
     g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL);
     g_return_val_if_fail (username != NULL, NULL);
 
-    update_users (user_list);
+    load_users (user_list);
 
     return get_user_by_name (user_list, username);
 }
@@ -899,6 +936,9 @@ lightdm_user_list_get_user_by_name (LightDMUserList *user_list, const gchar *use
 static void
 lightdm_user_list_init (LightDMUserList *user_list)
 {
+    LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list);
+
+    priv->bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
 }
 
 static void
@@ -937,14 +977,22 @@ lightdm_user_list_finalize (GObject *object)
     LightDMUserList *self = LIGHTDM_USER_LIST (object);
     LightDMUserListPrivate *priv = GET_LIST_PRIVATE (self);
 
-    if (priv->accounts_service_proxy)
-        g_object_unref (priv->accounts_service_proxy);
-    g_list_free_full (priv->user_account_objects, (GDestroyNotify) user_account_object_free);
-    if (priv->passwd_monitor)
-        g_object_unref (priv->passwd_monitor);
+    /* Remove children first, they might access us */
     g_list_free_full (priv->users, g_object_unref);
     g_list_free_full (priv->sessions, g_object_unref);
 
+    if (priv->user_added_signal)
+        g_dbus_connection_signal_unsubscribe (priv->bus, priv->user_added_signal);
+    if (priv->user_removed_signal)
+        g_dbus_connection_signal_unsubscribe (priv->bus, priv->user_removed_signal);
+    if (priv->session_added_signal)
+        g_dbus_connection_signal_unsubscribe (priv->bus, priv->session_added_signal);
+    if (priv->session_removed_signal)
+        g_dbus_connection_signal_unsubscribe (priv->bus, priv->session_removed_signal);
+    g_object_unref (priv->bus);
+    if (priv->passwd_monitor)
+        g_object_unref (priv->passwd_monitor);
+
     G_OBJECT_CLASS (lightdm_user_list_parent_class)->finalize (object);
 }
 
@@ -1015,6 +1063,60 @@ lightdm_user_list_class_init (LightDMUserListClass *klass)
                       G_TYPE_NONE, 1, LIGHTDM_TYPE_USER);
 }
 
+static void
+load_dmrc (LightDMUser *user)
+{
+    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
+    gchar *path;
+    //gboolean have_dmrc;
+
+    if (!priv->dmrc_file)
+        priv->dmrc_file = g_key_file_new ();
+
+    /* Load from the user directory */  
+    path = g_build_filename (priv->home_directory, ".dmrc", NULL);
+    /*have_dmrc = */g_key_file_load_from_file (priv->dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, NULL);
+    g_free (path);
+
+    /* If no ~/.dmrc, then load from the cache */
+    // FIXME
+
+    // FIXME: Watch for changes
+
+    /* The Language field contains the locale */
+    if (priv->language)
+        g_free (priv->language);
+    priv->language = g_key_file_get_string (priv->dmrc_file, "Desktop", "Language", NULL);
+
+    if (g_key_file_has_key (priv->dmrc_file, "Desktop", "Layout", NULL))
+    {
+        g_strfreev (priv->layouts);
+        priv->layouts = g_malloc (sizeof (gchar *) * 2);
+        priv->layouts[0] = g_key_file_get_string (priv->dmrc_file, "Desktop", "Layout", NULL);
+        priv->layouts[1] = NULL;
+    }
+
+    if (priv->session)
+        g_free (priv->session);
+    priv->session = g_key_file_get_string (priv->dmrc_file, "Desktop", "Session", NULL);
+}
+
+/* Loads language/layout/session info for user */
+static void
+load_user_values (LightDMUser *user)
+{
+    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
+
+    if (priv->loaded_values)
+        return;
+    priv->loaded_values = TRUE;
+
+    if (priv->path)
+        load_accounts_user (user);
+    else
+        load_dmrc (user);
+}
+
 /**
  * lightdm_user_get_name:
  * @user: A #LightDMUser
@@ -1027,6 +1129,7 @@ const gchar *
 lightdm_user_get_name (LightDMUser *user)
 {
     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
+    load_user_values (user);
     return GET_USER_PRIVATE (user)->name;
 }
 
@@ -1042,6 +1145,7 @@ const gchar *
 lightdm_user_get_real_name (LightDMUser *user)
 {
     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
+    load_user_values (user);
     return GET_USER_PRIVATE (user)->real_name;
 }
 
@@ -1060,11 +1164,13 @@ lightdm_user_get_display_name (LightDMUser *user)
 
     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
 
+    load_user_values (user);
+
     priv = GET_USER_PRIVATE (user);
-    if (strcmp (priv->real_name, ""))
-        return priv->real_name;
-    else
+    if (!priv->real_name || strcmp (priv->real_name, "") == 0)
         return priv->name;
+    else
+        return priv->real_name;
 }
 
 /**
@@ -1079,6 +1185,7 @@ const gchar *
 lightdm_user_get_home_directory (LightDMUser *user)
 {
     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
+    load_user_values (user);
     return GET_USER_PRIVATE (user)->home_directory;
 }
 
@@ -1094,6 +1201,7 @@ const gchar *
 lightdm_user_get_image (LightDMUser *user)
 {
     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
+    load_user_values (user);
     return GET_USER_PRIVATE (user)->image;
 }
 
@@ -1109,212 +1217,10 @@ const gchar *
 lightdm_user_get_background (LightDMUser *user)
 {
     g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL);
+    load_user_values (user);
     return GET_USER_PRIVATE (user)->background;
 }
 
-static void
-load_dmrc (LightDMUser *user)
-{
-    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
-    gchar *path;
-    //gboolean have_dmrc;
-
-    if (!priv->dmrc_file)
-        priv->dmrc_file = g_key_file_new ();
-
-    /* Load from the user directory */  
-    path = g_build_filename (priv->home_directory, ".dmrc", NULL);
-    /*have_dmrc = */g_key_file_load_from_file (priv->dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, NULL);
-    g_free (path);
-
-    /* If no ~/.dmrc, then load from the cache */
-    // FIXME
-
-    // FIXME: Watch for changes
-
-    /* The Language field contains the locale */
-    if (priv->language)
-        g_free (priv->language);
-    priv->language = g_key_file_get_string (priv->dmrc_file, "Desktop", "Language", NULL);
-
-    if (priv->layouts)
-    {
-        g_strfreev (priv->layouts);
-        priv->layouts = NULL;
-    }
-    if (g_key_file_has_key (priv->dmrc_file, "Desktop", "Layout", NULL))
-    {
-        priv->layouts = g_malloc (sizeof (gchar *) * 2);
-        priv->layouts[0] = g_key_file_get_string (priv->dmrc_file, "Desktop", "Layout", NULL);
-        priv->layouts[1] = NULL;
-    }
-
-    if (priv->session)
-        g_free (priv->session);
-    priv->session = g_key_file_get_string (priv->dmrc_file, "Desktop", "Session", NULL);
-}
-
-static GVariant *
-get_property (GDBusProxy *proxy, const gchar *property)
-{
-    GVariant *answer;
-
-    if (!proxy)
-        return NULL;
-
-    answer = g_dbus_proxy_get_cached_property (proxy, property);
-
-    if (!answer)
-    {
-        g_warning ("Could not get accounts property %s", property);
-        return NULL;
-    }
-
-    return answer;
-}
-
-static gboolean
-get_boolean_property (GDBusProxy *proxy, const gchar *property)
-{
-    GVariant *answer;
-    gboolean rv;
-
-    answer = get_property (proxy, property);
-    if (!g_variant_is_of_type (answer, G_VARIANT_TYPE_BOOLEAN))
-    {
-        g_warning ("Unexpected accounts property type for %s: %s",
-                   property, g_variant_get_type_string (answer));
-        g_variant_unref (answer);
-        return FALSE;
-    }
-
-    rv = g_variant_get_boolean (answer);
-    g_variant_unref (answer);
-
-    return rv;
-}
-
-static gchar *
-get_string_property (GDBusProxy *proxy, const gchar *property)
-{
-    GVariant *answer;
-    gchar *rv;
-  
-    answer = get_property (proxy, property);
-    if (!g_variant_is_of_type (answer, G_VARIANT_TYPE_STRING))
-    {
-        g_warning ("Unexpected accounts property type for %s: %s",
-                   property, g_variant_get_type_string (answer));
-        g_variant_unref (answer);
-        return NULL;
-    }
-
-    rv = g_strdup (g_variant_get_string (answer, NULL));
-    if (strcmp (rv, "") == 0)
-    {
-        g_free (rv);
-        rv = NULL;
-    }
-    g_variant_unref (answer);
-
-    return rv;
-}
-
-static gchar **
-get_string_array_property (GDBusProxy *proxy, const gchar *property)
-{
-    GVariant *answer;
-    gchar **rv;
-
-    if (!proxy)
-        return NULL;
-
-    answer = g_dbus_proxy_get_cached_property (proxy, property);
-
-    if (!answer)
-    {
-        g_warning ("Could not get accounts property %s", property);
-        return NULL;
-    }
-
-    if (!g_variant_is_of_type (answer, G_VARIANT_TYPE ("as")))
-    {
-        g_warning ("Unexpected accounts property type for %s: %s",
-                   property, g_variant_get_type_string (answer));
-        g_variant_unref (answer);
-        return NULL;
-    }
-
-    rv = g_variant_dup_strv (answer, NULL);
-
-    g_variant_unref (answer);
-    return rv;
-}
-
-static gboolean
-load_accounts_service (LightDMUser *user)
-{
-    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
-    LightDMUserListPrivate *list_priv = GET_LIST_PRIVATE (priv->user_list);
-    UserAccountObject *account = NULL;
-    GList *iter;
-    gchar **value;
-
-    /* First, find AccountObject proxy */
-    for (iter = list_priv->user_account_objects; iter; iter = iter->next)
-    {
-        UserAccountObject *a = iter->data;
-        if (a->user == user)
-        {
-            account = a;
-            break;
-        }
-    }
-    if (!account)
-        return FALSE;
-
-    /* We have proxy, let's grab some properties */
-    if (priv->language)
-        g_free (priv->language);
-    priv->language = get_string_property (account->proxy, "Language");
-    if (priv->session)
-        g_free (priv->session);
-    priv->session = get_string_property (account->proxy, "XSession");
-
-    value = get_string_array_property (account->proxy, "XKeyboardLayouts");
-    if (value)
-    {
-        if (value[0])
-        {
-            g_strfreev (priv->layouts);
-            priv->layouts = value;
-        }
-        else
-            g_strfreev (value);
-    }
-
-    priv->has_messages = get_boolean_property (account->proxy, "XHasMessages");
-
-    return TRUE;
-}
-
-/* Loads language/layout/session info for user */
-static void
-load_user_values (LightDMUser *user)
-{
-    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
-
-    load_dmrc (user);
-    load_accounts_service (user); // overrides dmrc values
-
-    /* Ensure a few guarantees */
-    if (priv->layouts == NULL)
-    {
-        priv->layouts = g_malloc (sizeof (gchar *) * 1);
-        priv->layouts[0] = NULL;
-    }
-}
-
 /**
  * lightdm_user_get_language:
  * @user: A #LightDMUser
@@ -1390,12 +1296,15 @@ lightdm_user_get_session (LightDMUser *user)
 gboolean
 lightdm_user_get_logged_in (LightDMUser *user)
 {
-    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
-    LightDMUserListPrivate *list_priv = GET_LIST_PRIVATE (priv->user_list);
+    LightDMUserPrivate *priv;
+    LightDMUserListPrivate *list_priv;
     GList *link;
 
     g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE);
 
+    priv = GET_USER_PRIVATE (user);
+    list_priv = GET_LIST_PRIVATE (priv->user_list);
+
     for (link = list_priv->sessions; link; link = link->next)
     {
         Session *session = link->data;
@@ -1425,6 +1334,9 @@ lightdm_user_get_has_messages (LightDMUser *user)
 static void
 lightdm_user_init (LightDMUser *user)
 {
+    LightDMUserPrivate *priv = GET_USER_PRIVATE (user);
+    priv->layouts = g_malloc (sizeof (gchar *) * 1);
+    priv->layouts[0] = NULL;
 }
 
 static void
@@ -1496,6 +1408,9 @@ lightdm_user_finalize (GObject *object)
     LightDMUser *self = LIGHTDM_USER (object);
     LightDMUserPrivate *priv = GET_USER_PRIVATE (self);
 
+    g_free (priv->path);
+    if (priv->changed_signal)
+        g_dbus_connection_signal_unsubscribe (GET_LIST_PRIVATE (priv->user_list)->bus, priv->changed_signal);
     g_free (priv->name);
     g_free (priv->real_name);
     g_free (priv->home_directory);
index 71f654b140344c20c61c454765ac8e54f572014d..96bb874406325edfae3a4aea2e6d2194f264ebf2 100644 (file)
@@ -68,7 +68,11 @@ status_connect (StatusRequestFunc request_cb)
     g_clear_error (&error);
     g_free (path);
     if (!result)
+    {
+        g_object_unref (status_socket);
+        status_socket = NULL;
         return FALSE;
+    }
 
     source = g_socket_create_source (status_socket, G_IO_IN, NULL);
     g_source_set_callback (source, (GSourceFunc) status_request_cb, NULL, NULL);
@@ -80,6 +84,8 @@ status_connect (StatusRequestFunc request_cb)
 void
 status_notify (const gchar *format, ...)
 {
+    gboolean written = FALSE;
+
     gchar status[1024];
     va_list ap;
 
@@ -93,12 +99,13 @@ status_notify (const gchar *format, ...)
         int length;
 
         length = strlen (status);
-        g_socket_send (status_socket, (gchar *) &length, sizeof (length), NULL, &error);
-        g_socket_send (status_socket, status, strlen (status), NULL, &error);
+        written = g_socket_send (status_socket, (gchar *) &length, sizeof (length), NULL, &error) == sizeof (length) &&
+                  g_socket_send (status_socket, status, strlen (status), NULL, &error) == strlen (status);
         if (error)
             g_printerr ("Failed to write to status socket: %s\n", error->message);
         g_clear_error (&error);
     }
-    else
+
+    if (!written)
         g_printerr ("%s\n", status);
 }
index 14b1c18661d6dbcb7723571580f90e791518c3c4..2e2fe0b594b07256c25ae70368e1f77e9f6b62ee 100644 (file)
@@ -1544,6 +1544,12 @@ load_passwd_file (void)
             }
             user->xsession = g_key_file_get_string (dmrc_file, "Desktop", "Session", NULL);
             user->layouts = g_key_file_get_string_list (dmrc_file, "X-Accounts", "Layouts", NULL, NULL);
+            if (!user->layouts)
+            {
+                user->layouts = g_malloc (sizeof (gchar *) * 2);
+                user->layouts[0] = g_key_file_get_string (dmrc_file, "Desktop", "Layout", NULL);
+                user->layouts[1] = NULL;
+            }
             user->path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", uid);
             accounts_user_set_hidden (user, user->hidden, FALSE);
 
@@ -1999,79 +2005,74 @@ main (int argc, char **argv)
     {
         gchar *user_name;
         gchar *password;
-        gboolean have_home_dir;
         gchar *real_name;
-        gchar *xsession;
-        gchar *dmrc_layout;
-        gchar *dbus_layouts;
-        gchar *language;
         gint uid;
     } users[] =
     {
         /* Root account */
-        {"root",             "",         TRUE,  "root",               NULL,  NULL, NULL,          NULL,             0},
+        {"root",             "",          "root",                  0},
         /* Unprivileged account for greeters */
-        {"lightdm",          "",         TRUE,  "",                   NULL,  NULL, NULL,          NULL,           100},
+        {"lightdm",          "",          "",                    100},
         /* These accounts have a password */
-        {"have-password1",   "password", TRUE,  "Password User 1",    NULL,  NULL, NULL,          NULL,          1000},
-        {"have-password2",   "password", TRUE,  "Password User 2",    NULL,  NULL, NULL,          NULL,          1001},
-        {"have-password3",   "password", TRUE,  "Password User 3",    NULL,  NULL, NULL,          NULL,          1002},
-        {"have-password4",   "password", TRUE,  "Password User 4",    NULL,  NULL, NULL,          NULL,          1003},
+        {"have-password1",   "password",  "Password User 1",    1000},
+        {"have-password2",   "password",  "Password User 2",    1001},
+        {"have-password3",   "password",  "Password User 3",    1002},
+        {"have-password4",   "password",  "Password User 4",    1003},
         /* This account always prompts for a password, even if using the lightdm-autologin service */
-        {"always-password",  "password", TRUE,  "Password User 4",    NULL,  NULL, NULL,          NULL,          1004},
+        {"always-password",  "password",  "Password User 4",    1004},
         /* These accounts have no password */
-        {"no-password1",     "",         TRUE,  "No Password User 1", NULL,  NULL, NULL,          NULL,          1005},
-        {"no-password2",     "",         TRUE,  "No Password User 2", NULL,  NULL, NULL,          NULL,          1006},
-        {"no-password3",     "",         TRUE,  "No Password User 3", NULL,  NULL, NULL,          NULL,          1007},
-        {"no-password4",     "",         TRUE,  "No Password User 4", NULL,  NULL, NULL,          NULL,          1008},
+        {"no-password1",     "",          "No Password User 1", 1005},
+        {"no-password2",     "",          "No Password User 2", 1006},
+        {"no-password3",     "",          "No Password User 3", 1007},
+        {"no-password4",     "",          "No Password User 4", 1008},
         /* This account has a keyboard layout */
-        {"have-layout",      "",         TRUE,  "Layout User",        NULL,  "us", NULL,          NULL,          1009},
+        {"have-layout",      "",          "Layout User",        1009},
         /* This account has a set of keyboard layouts */
-        {"have-layouts",     "",         TRUE,  "Layouts User",       NULL,  "ru", "fr\toss;ru;", NULL,          1010},
+        {"have-layouts",     "",          "Layouts User",       1010},
         /* This account has a language set */
-        {"have-language",    "",         TRUE,  "Language User",      NULL,  NULL, NULL,          "en_AU.utf8",  1011},
+        {"have-language",    "",          "Language User",      1011},
         /* This account has a preconfigured session */
-        {"have-session",            "",  TRUE,  "Session User", "alternative", NULL, NULL,        NULL,          1012},
+        {"have-session",            "",   "Session User",       1012},
         /* This account has the home directory mounted on login */
-        {"mount-home-dir",   "",         FALSE, "Mounted Home Dir User", NULL, NULL, NULL,        NULL,          1013},
+        {"mount-home-dir",   "",          "Mounted Home Dir User", 1013},
         /* This account is denied access */
-        {"denied",           "",         TRUE,  "Denied User",        NULL,  NULL, NULL,          NULL,          1014},
+        {"denied",           "",          "Denied User",        1014},
         /* This account has expired */
-        {"expired",          "",         TRUE,  "Expired User",       NULL,  NULL, NULL,          NULL,          1015},
+        {"expired",          "",          "Expired User",       1015},
         /* This account needs a password change */
-        {"new-authtok",      "",         TRUE,  "New Token User",     NULL,  NULL, NULL,          NULL,          1016},
+        {"new-authtok",      "",          "New Token User",     1016},
         /* This account is switched to change-user2 when authentication succeeds */
-        {"change-user1",     "",         TRUE,  "Change User 1",      NULL,  NULL, NULL,          NULL,          1017},
-        {"change-user2",     "",         TRUE,  "Change User 2",      NULL,  NULL, NULL,          NULL,          1018},
+        {"change-user1",     "",          "Change User 1",      1017},
+        {"change-user2",     "",          "Change User 2",      1018},
         /* This account switches to invalid-user when authentication succeeds */
-        {"change-user-invalid", "",      TRUE,  "Invalid Change User",NULL,  NULL, NULL,          NULL,          1019},
+        {"change-user-invalid", "",       "Invalid Change User", 1019},
         /* This account crashes on authentication */
-        {"crash-authenticate", "",       TRUE,  "Crash Auth User",    NULL,  NULL, NULL,          NULL,          1020},
+        {"crash-authenticate", "",        "Crash Auth User",    1020},
         /* This account shows an informational prompt on login */
-        {"info-prompt",      "password", TRUE,  "Info Prompt",        NULL,  NULL, NULL,          NULL,          1021},
+        {"info-prompt",      "password",  "Info Prompt",        1021},
         /* This account shows multiple informational prompts on login */
-        {"multi-info-prompt","password", TRUE,  "Multi Info Prompt",  NULL,  NULL, NULL,          NULL,          1022},
+        {"multi-info-prompt","password",  "Multi Info Prompt",  1022},
         /* This account uses two factor authentication */
-        {"two-factor",       "password", TRUE,  "Two Factor",         NULL,  NULL, NULL,          NULL,          1023},
+        {"two-factor",       "password",  "Two Factor",         1023},
         /* This account has a special group */
-        {"group-member",     "password", TRUE,  "Group Member",       NULL,  NULL, NULL,          NULL,          1024},
+        {"group-member",     "password",  "Group Member",       1024},
         /* This account has the home directory created when the session starts */
-        {"make-home-dir",    "",         FALSE, "Make Home Dir User", NULL,  NULL, NULL,          NULL,          1025},
+        {"make-home-dir",    "",          "Make Home Dir User", 1025},
         /* This account fails to open a session */
-        {"session-error",    "password", TRUE,  "Session Error",      NULL,  NULL, NULL,          NULL,          1026},
+        {"session-error",    "password",  "Session Error",      1026},
         /* This account can't establish credentials */
-        {"cred-error",       "password", TRUE,  "Cred Error",         NULL,  NULL, NULL,          NULL,          1027},
+        {"cred-error",       "password",  "Cred Error",         1027},
         /* This account has expired credentials */
-        {"cred-expired",     "password", TRUE,  "Cred Expired",       NULL,  NULL, NULL,          NULL,          1028},
+        {"cred-expired",     "password",  "Cred Expired",       1028},
         /* This account has cannot access their credentials */
-        {"cred-unavail",     "password", TRUE,  "Cred Unavail",       NULL,  NULL, NULL,          NULL,          1029},
+        {"cred-unavail",     "password",  "Cred Unavail",       1029},
         /* This account sends informational messages for each PAM function that is called */
-        {"log-pam",          "password", TRUE,  "Log PAM",            NULL,  NULL, NULL,          NULL,          1030},
+        {"log-pam",          "password",  "Log PAM",            1030},
         /* This account shows multiple prompts on login */
-        {"multi-prompt",     "password", TRUE,  "Multi Prompt",       NULL,  NULL, NULL,          NULL,          1031},
+        {"multi-prompt",     "password",  "Multi Prompt",       1031},
         /* This account has an existing corrupt X authority */
-        {"corrupt-xauth",    "password", TRUE,  "Corrupt Xauthority", NULL,  NULL, NULL,          NULL,          1032},
-        {NULL,               NULL,       FALSE, NULL,                 NULL,  NULL, NULL,          NULL,             0}
+        {"corrupt-xauth",    "password",  "Corrupt Xauthority", 1032},
+        {NULL,               NULL,        NULL,                    0}
     };
     passwd_data = g_string_new ("");
     group_data = g_string_new ("");
@@ -2080,7 +2081,7 @@ main (int argc, char **argv)
         GKeyFile *dmrc_file;
         gboolean save_dmrc = FALSE;
 
-        if (users[i].have_home_dir)
+        if (strcmp (users[i].user_name, "mount-home-dir") != 0 && strcmp (users[i].user_name, "make-home-dir") != 0)
         {
             path = g_build_filename (home_dir, users[i].user_name, NULL);
             g_mkdir_with_parents (path, 0755);
@@ -2090,25 +2091,25 @@ main (int argc, char **argv)
         }
 
         dmrc_file = g_key_file_new ();
-        if (users[i].xsession)
+        if (strcmp (users[i].user_name, "have-session") == 0)
         {
-            g_key_file_set_string (dmrc_file, "Desktop", "Session", users[i].xsession);
+            g_key_file_set_string (dmrc_file, "Desktop", "Session", "alternative");
             save_dmrc = TRUE;
         }
-        if (users[i].dmrc_layout)
+        if (strcmp (users[i].user_name, "have-layout") == 0)
         {
-            g_key_file_set_string (dmrc_file, "Desktop", "Layout", users[i].dmrc_layout);
+            g_key_file_set_string (dmrc_file, "Desktop", "Layout", "us");
             save_dmrc = TRUE;
         }
-        if (users[i].dbus_layouts)
+        if (strcmp (users[i].user_name, "have-layouts") == 0)
         {
-            g_key_file_set_string (dmrc_file, "X-Accounts", "Layouts", users[i].dbus_layouts);
+            g_key_file_set_string (dmrc_file, "Desktop", "Layout", "ru");
+            g_key_file_set_string (dmrc_file, "X-Accounts", "Layouts", "fr\toss;ru;");
             save_dmrc = TRUE;
-
         }
-        if (users[i].language)
+        if (strcmp (users[i].user_name, "have-language") == 0)
         {
-            g_key_file_set_string (dmrc_file, "Desktop", "Language", users[i].language);
+            g_key_file_set_string (dmrc_file, "Desktop", "Language", "en_AU.utf8");
             save_dmrc = TRUE;
         }