X-Git-Url: http://rtime.felk.cvut.cz/gitweb/sojka/lightdm.git/blobdiff_plain/438fbe1568f21c32fee9d3f30a6dbd7e1119b511..7802c213778feccb9bb22b507b4fab2385c62f10:/liblightdm-gobject/user.c diff --git a/liblightdm-gobject/user.c b/liblightdm-gobject/user.c index 0c9025fb..75f65438 100644 --- a/liblightdm-gobject/user.c +++ b/liblightdm-gobject/user.c @@ -1,34 +1,31 @@ -/* +/* -*- Mode: C; indent-tabs-mode:nil; tab-width:4 -*- + * * Copyright (C) 2010 Robert Ancell. - * Author: Robert Ancell - * + * Copyright (C) 2014 Canonical, Ltd. + * Authors: Robert Ancell + * Michael Terry + * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at your option) any - * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the - * license. + * Software Foundation; either version 2 or version 3 of the License. + * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. */ #include -#include -#include -#include -#include -#include - +#include "user-list.h" #include "lightdm/user.h" enum { - LIST_PROP_0, - LIST_PROP_NUM_USERS, + LIST_PROP_NUM_USERS = 1, + LIST_PROP_LENGTH, LIST_PROP_USERS, }; enum { - USER_PROP_0, + USER_PROP_COMMON_USER = 1, USER_PROP_NAME, USER_PROP_REAL_NAME, USER_PROP_DISPLAY_NAME, @@ -37,8 +34,11 @@ enum USER_PROP_BACKGROUND, USER_PROP_LANGUAGE, USER_PROP_LAYOUT, + USER_PROP_LAYOUTS, USER_PROP_SESSION, - USER_PROP_LOGGED_IN + USER_PROP_LOGGED_IN, + USER_PROP_HAS_MESSAGES, + USER_PROP_UID, }; enum @@ -59,72 +59,23 @@ static guint user_signals[LAST_USER_SIGNAL] = { 0 }; typedef struct { - /* Connection to AccountsService */ - GDBusProxy *accounts_service_proxy; - GList *user_account_objects; - - /* Connection to DisplayManager */ - GDBusProxy *display_manager_proxy; - - /* File monitor for password file */ - GFileMonitor *passwd_monitor; - - /* TRUE if have scanned users */ - gboolean have_users; + gboolean initialized; - /* List of users */ - GList *users; - - /* List of sessions */ - GList *sessions; + /* Wrapper list, kept locally to preserve transfer-none promises */ + GList *lightdm_list; } LightDMUserListPrivate; typedef struct { - GDBusProxy *proxy; - LightDMUser *user; -} UserAccountObject; - -typedef struct -{ - LightDMUserList *user_list; - - gchar *name; - gchar *real_name; - gchar *home_directory; - gchar *image; - gchar *background; - - GKeyFile *dmrc_file; - gchar *language; - gchar *layout; - gchar *session; + CommonUser *common_user; } LightDMUserPrivate; -typedef struct -{ - GObject parent_instance; - gchar *path; - gchar *username; -} Session; - -typedef struct -{ - GObjectClass parent_class; -} SessionClass; - G_DEFINE_TYPE (LightDMUserList, lightdm_user_list, G_TYPE_OBJECT); G_DEFINE_TYPE (LightDMUser, lightdm_user, G_TYPE_OBJECT); -#define SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), session_get_type (), Session)) -GType session_get_type (void); -G_DEFINE_TYPE (Session, session, G_TYPE_OBJECT); #define GET_LIST_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER_LIST, LightDMUserListPrivate) #define GET_USER_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER, LightDMUserPrivate) -#define PASSWD_FILE "/etc/passwd" -#define USER_CONFIG_FILE "/etc/lightdm/users.conf" - static LightDMUserList *singleton = NULL; /** @@ -132,7 +83,7 @@ static LightDMUserList *singleton = NULL; * * Get the user list. * - * Return value: (tranfer none): the #LightDMUserList + * Return value: (transfer none): the #LightDMUserList **/ LightDMUserList * lightdm_user_list_get_instance (void) @@ -142,703 +93,93 @@ lightdm_user_list_get_instance (void) return singleton; } -static LightDMUser * -get_user_by_name (LightDMUserList *user_list, const gchar *username) -{ - LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list); - GList *link; - - for (link = priv->users; link; link = link->next) - { - LightDMUser *user = link->data; - if (strcmp (lightdm_user_get_name (user), username) == 0) - return user; - } - - return NULL; -} - -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)); -} - -static gboolean -update_passwd_user (LightDMUser *user, const gchar *real_name, const gchar *home_directory, const gchar *image) -{ - LightDMUserPrivate *priv = GET_USER_PRIVATE (user); - - 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) - return FALSE; - - g_free (priv->real_name); - priv->real_name = g_strdup (real_name); - g_free (priv->home_directory); - priv->home_directory = g_strdup (home_directory); - g_free (priv->image); - priv->image = g_strdup (image); - - return TRUE; -} - -static void -user_changed_cb (LightDMUser *user, LightDMUserList *user_list) -{ - g_signal_emit (user_list, list_signals[USER_CHANGED], 0, user); -} - -static void -load_passwd_file (LightDMUserList *user_list, gboolean emit_add_signal) -{ - LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list); - GKeyFile *config; - gchar *value; - gint minimum_uid; - gchar **hidden_users, **hidden_shells; - GList *users = NULL, *old_users, *new_users = NULL, *changed_users = NULL, *link; - GError *error = NULL; - - g_debug ("Loading user config from %s", USER_CONFIG_FILE); - - config = g_key_file_new (); - g_key_file_load_from_file (config, USER_CONFIG_FILE, G_KEY_FILE_NONE, &error); - if (error && !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) - g_warning ("Failed to load configuration from %s: %s", USER_CONFIG_FILE, error->message); // FIXME: Don't make warning on no file, just info - g_clear_error (&error); - - if (g_key_file_has_key (config, "UserList", "minimum-uid", NULL)) - minimum_uid = g_key_file_get_integer (config, "UserList", "minimum-uid", NULL); - else - minimum_uid = 500; - - value = g_key_file_get_string (config, "UserList", "hidden-users", NULL); - if (!value) - value = g_strdup ("nobody nobody4 noaccess"); - hidden_users = g_strsplit (value, " ", -1); - g_free (value); - - value = g_key_file_get_string (config, "UserList", "hidden-shells", NULL); - if (!value) - value = g_strdup ("/bin/false /usr/sbin/nologin"); - hidden_shells = g_strsplit (value, " ", -1); - g_free (value); - - g_key_file_free (config); - - setpwent (); - - while (TRUE) - { - struct passwd *entry; - LightDMUser *user; - LightDMUserPrivate *user_priv; - char **tokens; - gchar *real_name, *image; - int i; - - errno = 0; - entry = getpwent (); - if (!entry) - break; - - /* Ignore system users */ - if (entry->pw_uid < minimum_uid) - continue; - - /* Ignore users disabled by shell */ - if (entry->pw_shell) - { - for (i = 0; hidden_shells[i] && strcmp (entry->pw_shell, hidden_shells[i]) != 0; i++); - if (hidden_shells[i]) - continue; - } - - /* Ignore certain users */ - for (i = 0; hidden_users[i] && strcmp (entry->pw_name, hidden_users[i]) != 0; i++); - if (hidden_users[i]) - continue; - - tokens = g_strsplit (entry->pw_gecos, ",", -1); - if (tokens[0] != NULL && tokens[0][0] != '\0') - real_name = g_strdup (tokens[0]); - else - real_name = g_strdup (""); - g_strfreev (tokens); - - image = g_build_filename (entry->pw_dir, ".face", NULL); - if (!g_file_test (image, G_FILE_TEST_EXISTS)) - { - g_free (image); - image = g_build_filename (entry->pw_dir, ".face.icon", NULL); - if (!g_file_test (image, G_FILE_TEST_EXISTS)) - { - g_free (image); - image = NULL; - } - } - - user = g_object_new (LIGHTDM_TYPE_USER, NULL); - user_priv = GET_USER_PRIVATE (user); - user_priv->user_list = user_list; - g_free (user_priv->name); - user_priv->name = g_strdup (entry->pw_name); - g_free (user_priv->real_name); - user_priv->real_name = real_name; - g_free (user_priv->home_directory); - user_priv->home_directory = g_strdup (entry->pw_dir); - g_free (user_priv->image); - user_priv->image = image; - - /* Update existing users if have them */ - for (link = priv->users; link; link = link->next) - { - LightDMUser *info = link->data; - if (strcmp (lightdm_user_get_name (info), lightdm_user_get_name (user)) == 0) - { - if (update_passwd_user (info, lightdm_user_get_real_name (user), lightdm_user_get_home_directory (user), lightdm_user_get_image (user))) - changed_users = g_list_insert_sorted (changed_users, info, compare_user); - g_object_unref (user); - user = info; - break; - } - } - if (!link) - { - /* Only notify once we have loaded the user list */ - if (priv->have_users) - new_users = g_list_insert_sorted (new_users, user, compare_user); - } - users = g_list_insert_sorted (users, user, compare_user); - } - g_strfreev (hidden_users); - g_strfreev (hidden_shells); - - if (errno != 0) - g_warning ("Failed to read password database: %s", strerror (errno)); - - endpwent (); - - /* Use new user list */ - old_users = priv->users; - priv->users = users; - - /* Notify of changes */ - for (link = new_users; link; link = link->next) - { - 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); - if (emit_add_signal) - g_signal_emit (user_list, list_signals[USER_ADDED], 0, info); - } - g_list_free (new_users); - for (link = changed_users; link; link = link->next) - { - LightDMUser *info = link->data; - g_debug ("User %s changed", lightdm_user_get_name (info)); - g_signal_emit (info, user_signals[CHANGED], 0); - } - g_list_free (changed_users); - for (link = old_users; link; link = link->next) - { - GList *new_link; - - /* See if this user is in the current list */ - for (new_link = priv->users; new_link; new_link = new_link->next) - { - if (new_link->data == link->data) - break; - } - - if (!new_link) - { - LightDMUser *info = link->data; - g_debug ("User %s removed", lightdm_user_get_name (info)); - g_signal_emit (user_list, list_signals[USER_REMOVED], 0, info); - g_object_unref (info); - } - } - g_list_free (old_users); -} - static void -passwd_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, LightDMUserList *user_list) +user_changed_cb (CommonUser *common_user, LightDMUser *lightdm_user) { - if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) - { - g_debug ("%s changed, reloading user list", g_file_get_path (file)); - load_passwd_file (user_list, TRUE); - } + g_signal_emit (lightdm_user, user_signals[CHANGED], 0); } -static gboolean -update_user (UserAccountObject *object) -{ - LightDMUserPrivate *priv = GET_USER_PRIVATE (object->user); - GVariant *result, *value; - GVariantIter *iter; - gchar *name; - GError *error = NULL; - - result = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (object->proxy), - "org.freedesktop.Accounts", - g_dbus_proxy_get_object_path (object->proxy), - "org.freedesktop.DBus.Properties", - "GetAll", - g_variant_new ("(s)", "org.freedesktop.Accounts.User"), - G_VARIANT_TYPE ("(a{sv})"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - if (error) - g_warning ("Error updating user %s: %s", g_dbus_proxy_get_object_path (object->proxy), error->message); - g_clear_error (&error); - if (!result) - return FALSE; - - 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); - } - 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); - } - 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); - } - 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 = NULL; - else - priv->image = g_strdup (icon_file); - } - 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 = NULL; - else - priv->background = g_strdup (background_file); - } - } - g_variant_iter_free (iter); - - g_variant_unref (result); - - return TRUE; -} - -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) +static LightDMUser * +wrap_common_user (CommonUser *user) { - GDBusProxy *proxy; - UserAccountObject *object; - GError *error = NULL; - - 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; - - 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; + LightDMUser *lightdm_user = g_object_new (LIGHTDM_TYPE_USER, "common-user", user, NULL); + g_signal_connect (user, USER_SIGNAL_CHANGED, G_CALLBACK (user_changed_cb), lightdm_user); + return lightdm_user; } static void -user_account_object_free (UserAccountObject *object) -{ - 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) +user_list_added_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list) { LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list); - GList *link; - - for (link = priv->user_account_objects; link; link = link->next) - { - UserAccountObject *object = link->data; - if (strcmp (g_dbus_proxy_get_object_path (object->proxy), path) == 0) - return object; - } - - return NULL; + GList *common_users = common_user_list_get_users (common_list); + LightDMUser *lightdm_user = wrap_common_user (common_user); + priv->lightdm_list = g_list_insert (priv->lightdm_list, lightdm_user, g_list_index (common_users, common_user)); + g_signal_emit (user_list, list_signals[USER_ADDED], 0, lightdm_user); } static void -user_accounts_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, LightDMUserList *user_list) +user_list_changed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list) { 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; - - 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)"))) - { - gchar *path; - UserAccountObject *object; - - g_variant_get (parameters, "(&o)", &path); - - object = find_user_account_object (user_list, path); - if (!object) - return; - - g_debug ("User %s deleted", path); - priv->users = g_list_remove (priv->users, object->user); - g_object_unref (object->user); - - g_signal_emit (user_list, list_signals[USER_REMOVED], 0, object->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)); - } -} - -static Session * -load_session (LightDMUserList *user_list, const gchar *path) -{ - LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list); - Session *session = NULL; - GVariant *result, *username; - GError *error = NULL; - - result = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (priv->display_manager_proxy), - "org.freedesktop.DisplayManager", - path, - "org.freedesktop.DBus.Properties", - "Get", - g_variant_new ("(ss)", "org.freedesktop.DisplayManager.Session", "UserName"), - G_VARIANT_TYPE ("(v)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - if (error) - g_warning ("Error getting UserName from org.freedesktop.DisplayManager.Session: %s", error->message); - g_clear_error (&error); - if (!result) - return NULL; - - g_variant_get (result, "(v)", &username); - if (g_variant_is_of_type (username, G_VARIANT_TYPE_STRING)) - { - gchar *name; - - g_variant_get (username, "&s", &name); - - g_debug ("Loaded session %s (%s)", path, name); - session = g_object_new (session_get_type (), NULL); - session->username = g_strdup (name); - session->path = g_strdup (path); - priv->sessions = g_list_append (priv->sessions, session); - } - g_variant_unref (username); - g_variant_unref (result); - - return session; + GList *common_users = common_user_list_get_users (common_list); + LightDMUser *lightdm_user = g_list_nth_data (priv->lightdm_list, g_list_index (common_users, common_user)); + g_signal_emit (user_list, list_signals[USER_CHANGED], 0, lightdm_user); } static void -display_manager_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, LightDMUserList *user_list) +user_list_removed_cb (CommonUserList *common_list, CommonUser *common_user, LightDMUserList *user_list) { LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list); + GList *link; - if (strcmp (signal_name, "SessionAdded") == 0) + for (link = priv->lightdm_list; link; link = link->next) { - if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)"))) + LightDMUser *lightdm_user = link->data; + LightDMUserPrivate *user_priv = GET_USER_PRIVATE (lightdm_user); + if (user_priv->common_user == common_user) { - 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); - } - } - else if (strcmp (signal_name, "SessionRemoved") == 0) - { - if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(o)"))) - { - gchar *path; - GList *link; - - g_variant_get (parameters, "(&o)", &path); - - 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; - } - } + priv->lightdm_list = g_list_delete_link (priv->lightdm_list, link); + g_signal_emit (user_list, list_signals[USER_REMOVED], 0, lightdm_user); + g_object_unref (lightdm_user); + break; } } } static void -update_users (LightDMUserList *user_list) +initialize_user_list_if_needed (LightDMUserList *user_list, const gchar *username) { LightDMUserListPrivate *priv = GET_LIST_PRIVATE (user_list); - GError *error = NULL; + GList *common_users; + GList *link; - if (priv->have_users) + if (priv->initialized) 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, - "org.freedesktop.Accounts", - "/org/freedesktop/Accounts", - "org.freedesktop.Accounts", - NULL, - &error); - if (error) - g_warning ("Error contacting org.freedesktop.Accounts: %s", error->message); - g_clear_error (&error); - - /* Check if the service exists */ - if (priv->accounts_service_proxy) - { - 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) + if (!username) { - 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)"))) + common_users = common_user_list_get_users (common_user_list_get_instance ()); + for (link = common_users; link; link = link->next) { - 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); + CommonUser *user = link->data; + LightDMUser *lightdm_user = wrap_common_user (user); + priv->lightdm_list = g_list_prepend (priv->lightdm_list, lightdm_user); } - else - g_warning ("Unexpected type from ListCachedUsers: %s", g_variant_get_type_string (result)); + priv->lightdm_list = g_list_reverse (priv->lightdm_list); - g_variant_unref (result); + priv->initialized = TRUE; } else { - GFile *passwd_file; - - load_passwd_file (user_list, FALSE); - - /* Watch for changes to user list */ - passwd_file = g_file_new_for_path (PASSWD_FILE); - priv->passwd_monitor = g_file_monitor (passwd_file, G_FILE_MONITOR_NONE, NULL, &error); - g_object_unref (passwd_file); - if (error) - g_warning ("Error monitoring %s: %s", PASSWD_FILE, error->message); - else - g_signal_connect (priv->passwd_monitor, "changed", G_CALLBACK (passwd_changed_cb), user_list); - g_clear_error (&error); + CommonUser *user = common_user_list_get_user_by_name (common_user_list_get_instance (), username); + LightDMUser *lightdm_user = wrap_common_user (user); + priv->lightdm_list = g_list_append (priv->lightdm_list, lightdm_user); } - 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); - if (error) - g_warning ("Error contacting org.freedesktop.DisplayManager: %s", error->message); - g_clear_error (&error); - - if (priv->display_manager_proxy) - { - 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; - GVariantIter *iter; - const gchar *path; - - g_variant_get (result, "(v)", &value); - - g_debug ("Loading sessions from org.freedesktop.DisplayManager"); - g_variant_get (value, "ao", &iter); - while (g_variant_iter_loop (iter, "&o", &path)) - load_session (user_list, path); - g_variant_iter_free (iter); - - g_variant_unref (value); - } - else - g_warning ("Unexpected type from org.freedesktop.DisplayManager.Sessions: %s", g_variant_get_type_string (result)); - - g_variant_unref (result); - } + CommonUserList *common_list = common_user_list_get_instance (); + g_signal_connect (common_list, USER_LIST_SIGNAL_USER_ADDED, G_CALLBACK (user_list_added_cb), user_list); + g_signal_connect (common_list, USER_LIST_SIGNAL_USER_CHANGED, G_CALLBACK (user_list_changed_cb), user_list); + g_signal_connect (common_list, USER_LIST_SIGNAL_USER_REMOVED, G_CALLBACK (user_list_removed_cb), user_list); } /** @@ -851,8 +192,8 @@ 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); - return g_list_length (GET_LIST_PRIVATE (user_list)->users); + initialize_user_list_if_needed (user_list, NULL); + return g_list_length (GET_LIST_PRIVATE (user_list)->lightdm_list); } /** @@ -868,8 +209,8 @@ 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); - return GET_LIST_PRIVATE (user_list)->users; + initialize_user_list_if_needed (user_list, NULL); + return GET_LIST_PRIVATE (user_list)->lightdm_list; } /** @@ -884,12 +225,21 @@ lightdm_user_list_get_users (LightDMUserList *user_list) LightDMUser * lightdm_user_list_get_user_by_name (LightDMUserList *user_list, const gchar *username) { + GList *link; + g_return_val_if_fail (LIGHTDM_IS_USER_LIST (user_list), NULL); g_return_val_if_fail (username != NULL, NULL); - update_users (user_list); + initialize_user_list_if_needed (user_list, username); + + for (link = GET_LIST_PRIVATE (user_list)->lightdm_list; link; link = link->next) + { + LightDMUser *user = link->data; + if (g_strcmp0 (lightdm_user_get_name (user), username) == 0) + return user; + } - return get_user_by_name (user_list, username); + return NULL; } static void @@ -898,10 +248,10 @@ lightdm_user_list_init (LightDMUserList *user_list) } static void -lightdm_user_list_set_property (GObject *object, - guint prop_id, +lightdm_user_list_set_property (GObject *object, + guint prop_id, const GValue *value, - GParamSpec *pspec) + GParamSpec *pspec) { G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -919,6 +269,7 @@ lightdm_user_list_get_property (GObject *object, switch (prop_id) { case LIST_PROP_NUM_USERS: + case LIST_PROP_LENGTH: g_value_set_int (value, lightdm_user_list_get_length (self)); break; default: @@ -933,13 +284,7 @@ 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); - g_list_free_full (priv->users, g_object_unref); - g_list_free_full (priv->sessions, g_object_unref); + g_list_free_full (priv->lightdm_list, g_object_unref); G_OBJECT_CLASS (lightdm_user_list_parent_class)->finalize (object); } @@ -961,7 +306,23 @@ lightdm_user_list_class_init (LightDMUserListClass *klass) "num-users", "Number of login users", 0, G_MAXINT, 0, + G_PARAM_DEPRECATED | G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + LIST_PROP_LENGTH, + g_param_spec_int ("length", + "length", + "Number of login users", + 0, G_MAXINT, 0, G_PARAM_READABLE)); + + /*g_object_class_install_property (object_class, + LIST_PROP_USERS, + g_param_spec_int ("users", + "users", + "Users to present to user", + 0, G_MAXINT, 0, + G_PARAM_READABLE));*/ /** * LightDMUserList::user-added: * @user_list: A #LightDMUserList @@ -970,12 +331,12 @@ lightdm_user_list_class_init (LightDMUserListClass *klass) * The ::user-added signal gets emitted when a user account is created. **/ list_signals[USER_ADDED] = - g_signal_new ("user-added", + g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_ADDED, G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (LightDMUserListClass, user_added), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + NULL, G_TYPE_NONE, 1, LIGHTDM_TYPE_USER); /** @@ -986,12 +347,12 @@ lightdm_user_list_class_init (LightDMUserListClass *klass) * The ::user-changed signal gets emitted when a user account is modified. **/ list_signals[USER_CHANGED] = - g_signal_new ("user-changed", + g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_CHANGED, G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (LightDMUserListClass, user_changed), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + NULL, G_TYPE_NONE, 1, LIGHTDM_TYPE_USER); /** @@ -1002,34 +363,34 @@ lightdm_user_list_class_init (LightDMUserListClass *klass) * The ::user-removed signal gets emitted when a user account is removed. **/ list_signals[USER_REMOVED] = - g_signal_new ("user-removed", + g_signal_new (LIGHTDM_USER_LIST_SIGNAL_USER_REMOVED, G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (LightDMUserListClass, user_removed), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + NULL, G_TYPE_NONE, 1, LIGHTDM_TYPE_USER); } /** * lightdm_user_get_name: * @user: A #LightDMUser - * + * * Get the name of a user. - * + * * Return value: The name of the given user **/ const gchar * lightdm_user_get_name (LightDMUser *user) { g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - return GET_USER_PRIVATE (user)->name; + return common_user_get_name (GET_USER_PRIVATE (user)->common_user); } /** * lightdm_user_get_real_name: * @user: A #LightDMUser - * + * * Get the real name of a user. * * Return value: The real name of the given user @@ -1038,273 +399,177 @@ const gchar * lightdm_user_get_real_name (LightDMUser *user) { g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - return GET_USER_PRIVATE (user)->real_name; + return common_user_get_real_name (GET_USER_PRIVATE (user)->common_user); } /** * lightdm_user_get_display_name: * @user: A #LightDMUser - * + * * Get the display name of a user. - * + * * Return value: The display name of the given user **/ const gchar * lightdm_user_get_display_name (LightDMUser *user) { - LightDMUserPrivate *priv; - g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - - priv = GET_USER_PRIVATE (user); - if (strcmp (priv->real_name, "")) - return priv->real_name; - else - return priv->name; + return common_user_get_display_name (GET_USER_PRIVATE (user)->common_user); } /** * lightdm_user_get_home_directory: * @user: A #LightDMUser - * + * * Get the home directory for a user. - * + * * Return value: The users home directory */ const gchar * lightdm_user_get_home_directory (LightDMUser *user) { g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - return GET_USER_PRIVATE (user)->home_directory; + return common_user_get_home_directory (GET_USER_PRIVATE (user)->common_user); } /** * lightdm_user_get_image: * @user: A #LightDMUser - * + * * Get the image URI for a user. - * - * Return value: The image URI for the given user or #NULL if no URI + * + * Return value: (nullable): The image URI for the given user or #NULL if no URI **/ const gchar * lightdm_user_get_image (LightDMUser *user) { g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - return GET_USER_PRIVATE (user)->image; + return common_user_get_image (GET_USER_PRIVATE (user)->common_user); } /** * lightdm_user_get_background: * @user: A #LightDMUser - * + * * Get the background file path for a user. - * - * Return value: The background file path for the given user or #NULL if no path + * + * Return value: (nullable): The background file path for the given user or #NULL if no path **/ const gchar * lightdm_user_get_background (LightDMUser *user) { g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - return GET_USER_PRIVATE (user)->background; -} - -static void -load_dmrc (LightDMUser *user) -{ - LightDMUserPrivate *priv = GET_USER_PRIVATE (user); - gchar *path; - //gboolean have_dmrc; - - 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 - - if (priv->language) - g_free (priv->language); - if (priv->layout) - g_free (priv->layout); - if (priv->session) - g_free (priv->session); - - /* The Language field is actually a locale, strip the codeset off it to get the language */ - priv->language = g_key_file_get_string (priv->dmrc_file, "Desktop", "Language", NULL); - if (priv->language) - { - gchar *codeset = strchr (priv->language, '.'); - if (codeset) - *codeset = '\0'; - } - - priv->layout = g_key_file_get_string (priv->dmrc_file, "Desktop", "Layout", NULL); - priv->session = g_key_file_get_string (priv->dmrc_file, "Desktop", "Session", NULL); -} - -static gchar * -get_string_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 ("s"))) - { - g_warning ("Unexpected accounts property type for %s: %s", - property, g_variant_get_type_string (answer)); - g_variant_unref (answer); - return NULL; - } - - g_variant_get (answer, "s", &rv); - - 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); - - /* First, find AccountObject proxy */ - UserAccountObject *account = NULL; - GList *iter; - for (iter = list_priv->user_account_objects; iter; iter = iter->next) - { - if (((UserAccountObject *)iter->data)->user == user) - { - account = (UserAccountObject *)iter->data; - break; - } - } - if (!account) - return FALSE; - - /* We have proxy, let's grab some properties */ - if (priv->language) - g_free (priv->language); - if (priv->session) - g_free (priv->session); - priv->language = get_string_property (account->proxy, "Language"); - priv->session = get_string_property (account->proxy, "XSession"); - - return TRUE; -} - -/* Loads language/layout/session info for user */ -static void -load_user_values (LightDMUser *user) -{ - load_dmrc (user); - load_accounts_service (user); // overrides dmrc values + return common_user_get_background (GET_USER_PRIVATE (user)->common_user); } /** - * lightdm_user_get_language + * lightdm_user_get_language: * @user: A #LightDMUser - * + * * Get the language for a user. - * - * Return value: The language for the given user or #NULL if using system defaults. + * + * Return value: (nullable): The language in the form of a local specification (e.g. "de_DE.UTF-8") for the given user or #NULL if using the system default locale. **/ const gchar * lightdm_user_get_language (LightDMUser *user) { g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - load_user_values (user); - return GET_USER_PRIVATE (user)->language; + return common_user_get_language (GET_USER_PRIVATE (user)->common_user); } /** - * lightdm_user_get_layout + * lightdm_user_get_layout: * @user: A #LightDMUser - * + * * Get the keyboard layout for a user. - * - * Return value: The keyboard layoyt for the given user or #NULL if using system defaults. + * + * Return value: (nullable): The keyboard layout for the given user or #NULL if using system defaults. Copy the value if you want to use it long term. **/ const gchar * lightdm_user_get_layout (LightDMUser *user) { g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - load_user_values (user); - return GET_USER_PRIVATE (user)->layout; + return common_user_get_layout (GET_USER_PRIVATE (user)->common_user); +} + +/** + * lightdm_user_get_layouts: + * @user: A #LightDMUser + * + * Get the configured keyboard layouts for a user. + * + * Return value: (transfer none): A NULL-terminated array of keyboard layouts for the given user. Copy the values if you want to use them long term. + **/ +const gchar * const * +lightdm_user_get_layouts (LightDMUser *user) +{ + g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); + return common_user_get_layouts (GET_USER_PRIVATE (user)->common_user); } /** - * lightdm_user_get_session + * lightdm_user_get_session: * @user: A #LightDMUser - * + * * Get the session for a user. - * - * Return value: The session for the given user or #NULL if using system defaults. + * + * Return value: (nullable): The session for the given user or #NULL if using system defaults. **/ const gchar * lightdm_user_get_session (LightDMUser *user) { g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); - load_user_values (user); - return GET_USER_PRIVATE (user)->session; + return common_user_get_session (GET_USER_PRIVATE (user)->common_user); } /** * lightdm_user_get_logged_in: * @user: A #LightDMUser - * + * * Check if a user is logged in. - * + * * Return value: #TRUE if the user is currently logged in. **/ gboolean lightdm_user_get_logged_in (LightDMUser *user) { - LightDMUserPrivate *priv = GET_USER_PRIVATE (user); - LightDMUserListPrivate *list_priv = GET_LIST_PRIVATE (priv->user_list); - GList *link; - g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE); + return common_user_get_logged_in (GET_USER_PRIVATE (user)->common_user); +} - for (link = list_priv->sessions; link; link = link->next) - { - Session *session = link->data; - if (strcmp (session->username, priv->name) == 0) - return TRUE; - } +/** + * lightdm_user_get_has_messages: + * @user: A #LightDMUser + * + * Check if a user has waiting messages. + * + * Return value: #TRUE if the user has waiting messages. + **/ +gboolean +lightdm_user_get_has_messages (LightDMUser *user) +{ + g_return_val_if_fail (LIGHTDM_IS_USER (user), FALSE); + return common_user_get_has_messages (GET_USER_PRIVATE (user)->common_user); +} - return FALSE; +/** + * lightdm_user_get_uid: + * @user: A #LightDMUser + * + * Get the uid of a user. + * + * Return value: The uid of the given user + **/ +uid_t +lightdm_user_get_uid (LightDMUser *user) +{ + g_return_val_if_fail (LIGHTDM_IS_USER (user), (uid_t)-1); + return common_user_get_uid (GET_USER_PRIVATE (user)->common_user); } static void lightdm_user_init (LightDMUser *user) { - LightDMUserPrivate *priv = GET_USER_PRIVATE (user); - - priv->name = g_strdup (""); - priv->real_name = g_strdup (""); - priv->home_directory = g_strdup (""); - priv->image = g_strdup (""); - priv->background = g_strdup (""); - priv->language = g_strdup (""); - priv->layout = g_strdup (""); - priv->session = g_strdup (""); } static void @@ -1313,7 +578,18 @@ lightdm_user_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + LightDMUser *self = LIGHTDM_USER (object); + LightDMUserPrivate *priv = GET_USER_PRIVATE (self); + + switch (prop_id) + { + case USER_PROP_COMMON_USER: + priv->common_user = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void @@ -1352,12 +628,21 @@ lightdm_user_get_property (GObject *object, case USER_PROP_LAYOUT: g_value_set_string (value, lightdm_user_get_layout (self)); break; + case USER_PROP_LAYOUTS: + g_value_set_boxed (value, g_strdupv ((gchar **) lightdm_user_get_layouts (self))); + break; case USER_PROP_SESSION: g_value_set_string (value, lightdm_user_get_session (self)); break; case USER_PROP_LOGGED_IN: g_value_set_boolean (value, lightdm_user_get_logged_in (self)); break; + case USER_PROP_HAS_MESSAGES: + g_value_set_boolean (value, lightdm_user_get_has_messages (self)); + break; + case USER_PROP_UID: + g_value_set_uint64 (value, lightdm_user_get_uid (self)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1370,40 +655,43 @@ lightdm_user_finalize (GObject *object) LightDMUser *self = LIGHTDM_USER (object); LightDMUserPrivate *priv = GET_USER_PRIVATE (self); - g_free (priv->name); - g_free (priv->real_name); - g_free (priv->home_directory); - g_free (priv->image); - g_free (priv->background); - if (priv->dmrc_file) - g_key_file_free (priv->dmrc_file); + g_object_unref (priv->common_user); + + G_OBJECT_CLASS (lightdm_user_parent_class)->finalize (object); } static void lightdm_user_class_init (LightDMUserClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - + g_type_class_add_private (klass, sizeof (LightDMUserPrivate)); object_class->set_property = lightdm_user_set_property; object_class->get_property = lightdm_user_get_property; object_class->finalize = lightdm_user_finalize; + g_object_class_install_property (object_class, + USER_PROP_COMMON_USER, + g_param_spec_object ("common-user", + "common-user", + "Internal user object", + COMMON_TYPE_USER, + G_PARAM_PRIVATE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_WRITABLE)); g_object_class_install_property (object_class, USER_PROP_NAME, g_param_spec_string ("name", "name", "Username", NULL, - G_PARAM_READWRITE)); + G_PARAM_READABLE)); g_object_class_install_property (object_class, USER_PROP_REAL_NAME, g_param_spec_string ("real-name", "real-name", "Users real name", NULL, - G_PARAM_READWRITE)); + G_PARAM_READABLE)); g_object_class_install_property (object_class, USER_PROP_DISPLAY_NAME, g_param_spec_string ("display-name", @@ -1417,21 +705,21 @@ lightdm_user_class_init (LightDMUserClass *klass) "home-directory", "Home directory", NULL, - G_PARAM_READWRITE)); + G_PARAM_READABLE)); g_object_class_install_property (object_class, USER_PROP_IMAGE, g_param_spec_string ("image", "image", "Avatar image", NULL, - G_PARAM_READWRITE)); + G_PARAM_READABLE)); g_object_class_install_property (object_class, USER_PROP_BACKGROUND, g_param_spec_string ("background", "background", "User background", NULL, - G_PARAM_READWRITE)); + G_PARAM_READABLE)); g_object_class_install_property (object_class, USER_PROP_LANGUAGE, g_param_spec_string ("language", @@ -1446,6 +734,13 @@ lightdm_user_class_init (LightDMUserClass *klass) "Keyboard layout used by this user", NULL, G_PARAM_READABLE)); + g_object_class_install_property (object_class, + USER_PROP_LAYOUTS, + g_param_spec_boxed ("layouts", + "layouts", + "Keyboard layouts used by this user", + G_TYPE_STRV, + G_PARAM_READABLE)); g_object_class_install_property (object_class, USER_PROP_SESSION, g_param_spec_string ("session", @@ -1459,7 +754,21 @@ lightdm_user_class_init (LightDMUserClass *klass) "logged-in", "TRUE if the user is currently in a session", FALSE, - G_PARAM_READWRITE)); + G_PARAM_READABLE)); + g_object_class_install_property (object_class, + USER_PROP_LOGGED_IN, + g_param_spec_boolean ("has-messages", + "has-messages", + "TRUE if the user is has waiting messages", + FALSE, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, + USER_PROP_UID, + g_param_spec_uint64 ("uid", + "uid", + "User UID", + 0, G_MAXUINT64, 0, + G_PARAM_READABLE)); /** * LightDMUser::changed: @@ -1468,32 +777,11 @@ lightdm_user_class_init (LightDMUserClass *klass) * The ::changed signal gets emitted this user account is modified. **/ user_signals[CHANGED] = - g_signal_new ("changed", + g_signal_new (LIGHTDM_SIGNAL_USER_CHANGED, G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (LightDMUserClass, changed), NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, G_TYPE_NONE, 0); } - -static void -session_init (Session *session) -{ -} - -static void -session_finalize (GObject *object) -{ - Session *self = SESSION (object); - - g_free (self->path); - g_free (self->username); -} - -static void -session_class_init (SessionClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = session_finalize; -}