diff options
author | Robert Ancell <robert.ancell@canonical.com> | 2011-07-19 14:20:47 +1000 |
---|---|---|
committer | Robert Ancell <robert.ancell@canonical.com> | 2011-07-19 14:20:47 +1000 |
commit | 2096109b3c2af4c725b5a11dc9f23608d69f7f2b (patch) | |
tree | 87bdd5842b34746a5c0d8345cd0edc98af0e0fff | |
parent | 11e1860d0a89ed5235a34a84a66ffdef49b6d15a (diff) | |
download | lightdm-2096109b3c2af4c725b5a11dc9f23608d69f7f2b.tar.gz |
Use AccountsService if it is available
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | doc/lightdm-gobject-1-sections.txt | 1 | ||||
-rw-r--r-- | doc/tmpl/user.sgml | 8 | ||||
-rw-r--r-- | greeters/gtk/lightdm-gtk-greeter.c | 4 | ||||
-rw-r--r-- | liblightdm-gobject/greeter.c | 2 | ||||
-rw-r--r-- | liblightdm-gobject/lightdm/user.h | 1 | ||||
-rw-r--r-- | liblightdm-gobject/user-list.c | 298 | ||||
-rw-r--r-- | liblightdm-gobject/user.c | 58 |
8 files changed, 334 insertions, 39 deletions
@@ -17,6 +17,7 @@ Overview of changes in lightdm 0.9.0 - Face images are now local paths not URIs - liblightdm-gobject now uses lightdm_ prefix instead of ldm_ - liblightdm-gobject splits UserList into its own class + - liblightdm-gobject uses AccountsService if it is available * D-Bus API changes: - Make an object per seat - Add a CanSwitch property diff --git a/doc/lightdm-gobject-1-sections.txt b/doc/lightdm-gobject-1-sections.txt index a1041f36..303a1083 100644 --- a/doc/lightdm-gobject-1-sections.txt +++ b/doc/lightdm-gobject-1-sections.txt @@ -38,6 +38,7 @@ lightdm_layout_get_type <SECTION> <FILE>user</FILE> <TITLE>LightDMUser</TITLE> +changed lightdm_user_get_name lightdm_user_get_real_name lightdm_user_get_display_name diff --git a/doc/tmpl/user.sgml b/doc/tmpl/user.sgml index fcfa9a92..c5aa4750 100644 --- a/doc/tmpl/user.sgml +++ b/doc/tmpl/user.sgml @@ -36,6 +36,14 @@ A user has the following properties: <!-- ##### SECTION Image ##### --> +<!-- ##### USER_FUNCTION changed ##### --> +<para> + +</para> + +@user: + + <!-- ##### FUNCTION lightdm_user_get_name ##### --> <para> diff --git a/greeters/gtk/lightdm-gtk-greeter.c b/greeters/gtk/lightdm-gtk-greeter.c index 2d793be9..6d2304c0 100644 --- a/greeters/gtk/lightdm-gtk-greeter.c +++ b/greeters/gtk/lightdm-gtk-greeter.c @@ -623,7 +623,7 @@ main(int argc, char **argv) signal (SIGTERM, sigterm_cb); - g_type_init (); + gtk_init (&argc, &argv); greeter = lightdm_greeter_new (); g_signal_connect (greeter, "connected", G_CALLBACK (connected_cb), NULL); @@ -634,8 +634,6 @@ main(int argc, char **argv) g_signal_connect (greeter, "quit", G_CALLBACK (quit_cb), NULL); lightdm_greeter_connect_to_server (greeter); - gtk_init (&argc, &argv); - gtk_main (); return 0; diff --git a/liblightdm-gobject/greeter.c b/liblightdm-gobject/greeter.c index 7e22b087..8035de23 100644 --- a/liblightdm-gobject/greeter.c +++ b/liblightdm-gobject/greeter.c @@ -1446,8 +1446,6 @@ lightdm_greeter_init (LightDMGreeter *greeter) priv->read_buffer = g_malloc (HEADER_SIZE); priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - g_debug ("default-language=%s", lightdm_greeter_get_default_language (greeter)); } static void diff --git a/liblightdm-gobject/lightdm/user.h b/liblightdm-gobject/lightdm/user.h index 1cbd371e..6e6e1eb7 100644 --- a/liblightdm-gobject/lightdm/user.h +++ b/liblightdm-gobject/lightdm/user.h @@ -31,6 +31,7 @@ typedef struct typedef struct { GObjectClass parent_class; + void (*changed)(LightDMUser *user); } LightDMUserClass; GType lightdm_user_get_type (void); diff --git a/liblightdm-gobject/user-list.c b/liblightdm-gobject/user-list.c index 84ee8b4d..1acca818 100644 --- a/liblightdm-gobject/user-list.c +++ b/liblightdm-gobject/user-list.c @@ -35,8 +35,9 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { - /* Connection to system bus */ - GDBusConnection *system_bus; + /* Connection to AccountsService */ + GDBusProxy *accounts_service_proxy; + GList *user_account_objects; /* File monitor for password file */ GFileMonitor *passwd_monitor; @@ -48,6 +49,12 @@ typedef struct GList *users; } LightDMUserListPrivate; +typedef struct +{ + GDBusProxy *proxy; + LightDMUser *user; +} UserAccountObject; + G_DEFINE_TYPE (LightDMUserList, lightdm_user_list, G_TYPE_OBJECT); #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER_LIST, LightDMUserListPrivate) @@ -92,7 +99,7 @@ compare_user (gconstpointer a, gconstpointer b) } static gboolean -update_user (LightDMUser *user, const gchar *real_name, const gchar *home_directory, const gchar *image, gboolean logged_in) +update_passwd_user (LightDMUser *user, const gchar *real_name, const gchar *home_directory, const gchar *image, gboolean logged_in) { if (g_strcmp0 (lightdm_user_get_real_name (user), real_name) == 0 && g_strcmp0 (lightdm_user_get_home_directory (user), home_directory) == 0 && @@ -101,13 +108,18 @@ update_user (LightDMUser *user, const gchar *real_name, const gchar *home_direct return FALSE; g_object_set (user, "real-name", real_name, "home-directory", home_directory, "image", image, "logged-in", logged_in, NULL); - // FIXME: emit changed return TRUE; } static void -load_users (LightDMUserList *user_list) +user_changed_cb (LightDMUser *user, LightDMUserList *user_list) +{ + g_signal_emit (user_list, signals[USER_CHANGED], 0, user); +} + +static void +load_passwd_file (LightDMUserList *user_list) { LightDMUserListPrivate *priv = GET_PRIVATE (user_list); GKeyFile *config; @@ -205,7 +217,7 @@ load_users (LightDMUserList *user_list) LightDMUser *info = link->data; if (strcmp (lightdm_user_get_name (info), lightdm_user_get_name (user)) == 0) { - if (update_user (info, lightdm_user_get_real_name (user), lightdm_user_get_home_directory (user), lightdm_user_get_image (user), lightdm_user_get_logged_in (user))) + if (update_passwd_user (info, lightdm_user_get_real_name (user), lightdm_user_get_home_directory (user), lightdm_user_get_image (user), lightdm_user_get_logged_in (user))) changed_users = g_list_insert_sorted (changed_users, info, compare_user); g_object_unref (user); user = info; @@ -237,6 +249,7 @@ load_users (LightDMUserList *user_list) { 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_emit (user_list, signals[USER_ADDED], 0, info); } g_list_free (new_users); @@ -244,7 +257,7 @@ load_users (LightDMUserList *user_list) { LightDMUser *info = link->data; g_debug ("User %s changed", lightdm_user_get_name (info)); - g_signal_emit (user_list, signals[USER_CHANGED], 0, info); + g_signal_emit_by_name (info, "changed"); } g_list_free (changed_users); for (link = old_users; link; link = link->next) @@ -275,7 +288,186 @@ passwd_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileM if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { g_debug ("%s changed, reloading user list", g_file_get_path (file)); - load_users (user_list); + load_passwd_file (user_list); + } +} + +static gboolean +update_user (UserAccountObject *object) +{ + 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 (!result) + 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)) + { + g_debug ("%s=?", name); + 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_object_set (object->user, "name", user_name, 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_object_set (object->user, "real-name", real_name, 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_object_set (object->user, "home-directory", home_directory, 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_object_set (object->user, "image", icon_file, NULL); + } + } + g_debug ("!1"); + g_variant_iter_free (iter); + g_debug ("!2"); + + g_variant_unref (result); + g_debug ("!3"); + + 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_by_name (object->user, "changed"); + } + 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 (const gchar *path) +{ + 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 (!proxy) + 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); + object->proxy = proxy; + g_signal_connect (proxy, "g-signal", G_CALLBACK (user_signal_cb), object); + + return object; +} + +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 void +user_accounts_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, LightDMUserList *user_list) +{ + LightDMUserListPrivate *priv = GET_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); + g_debug ("User %s added", path); + + object = user_account_object_new (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); + g_signal_emit (user_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; + GList *link; + + g_variant_get (parameters, "(&o)", &path); + g_debug ("User %s deleted", path); + + 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) + { + priv->users = g_list_remove (priv->users, object->user); + g_object_unref (object->user); + + g_signal_emit (user_list, signals[USER_REMOVED], 0, object->user); + + priv->user_account_objects = g_list_remove (priv->user_account_objects, object); + user_account_object_free (object); + break; + } + } + } + else + g_warning ("Got UserAccounts signal UserDeleted with unknown parameters %s", g_variant_get_type_string (parameters)); } } @@ -288,20 +480,83 @@ update_users (LightDMUserList *user_list) if (priv->have_users) return; + priv->have_users = TRUE; - load_users (user_list); - - /* 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 (!priv->passwd_monitor) - 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); + 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 (!priv->accounts_service_proxy) + g_warning ("Error contacting AccountsService: %s", error->message); g_clear_error (&error); - priv->have_users = TRUE; + 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 (!result) + g_warning ("Error getting user list from AccountsService: %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 AccountsService"); + 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 (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)); + + g_variant_unref (result); + } + else + { + load_passwd_file (user_list); + + /* 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 (!priv->passwd_monitor) + 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); + } } /** @@ -395,8 +650,9 @@ lightdm_user_list_finalize (GObject *object) LightDMUserList *self = LIGHTDM_USER_LIST (object); LightDMUserListPrivate *priv = GET_PRIVATE (self); - if (priv->system_bus) - g_object_unref (priv->system_bus); + 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); diff --git a/liblightdm-gobject/user.c b/liblightdm-gobject/user.c index 2ef39011..9641fcbf 100644 --- a/liblightdm-gobject/user.c +++ b/liblightdm-gobject/user.c @@ -9,6 +9,8 @@ * license. */ +#include <string.h> + #include "lightdm/user.h" enum { @@ -24,6 +26,12 @@ enum { PROP_LOGGED_IN }; +enum { + CHANGED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + typedef struct { gchar *name; @@ -63,7 +71,7 @@ lightdm_user_get_name (LightDMUser *user) * * Get the real name of a user. * - * Return value: The real name of the given user (may be blank) + * Return value: The real name of the given user **/ const gchar * lightdm_user_get_real_name (LightDMUser *user) @@ -88,7 +96,7 @@ lightdm_user_get_display_name (LightDMUser *user) g_return_val_if_fail (LIGHTDM_IS_USER (user), NULL); priv = GET_PRIVATE (user); - if (priv->real_name) + if (strcmp (priv->real_name, "")) return priv->real_name; else return priv->name; @@ -214,13 +222,22 @@ lightdm_user_get_logged_in (LightDMUser *user) static void lightdm_user_init (LightDMUser *user) { + LightDMUserPrivate *priv = GET_PRIVATE (user); + + priv->name = g_strdup (""); + priv->real_name = g_strdup (""); + priv->home_directory = g_strdup (""); + priv->image = g_strdup (""); + priv->language = g_strdup (""); + priv->layout = g_strdup (""); + priv->session = g_strdup (""); } static void lightdm_user_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) + guint prop_id, + const GValue *value, + GParamSpec *pspec) { LightDMUser *self = LIGHTDM_USER (object); LightDMUserPrivate *priv = GET_PRIVATE (self); @@ -253,9 +270,9 @@ lightdm_user_set_property (GObject *object, static void lightdm_user_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) + guint prop_id, + GValue *value, + GParamSpec *pspec) { LightDMUser *self; @@ -326,14 +343,14 @@ lightdm_user_class_init (LightDMUserClass *klass) "name", "Username", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_REAL_NAME, g_param_spec_string("real-name", "real-name", "Users real name", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_DISPLAY_NAME, g_param_spec_string("display-name", @@ -347,14 +364,14 @@ lightdm_user_class_init (LightDMUserClass *klass) "home-directory", "Home directory", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_IMAGE, g_param_spec_string("image", "image", "Avatar image", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_LANGUAGE, g_param_spec_string("language", @@ -382,5 +399,20 @@ lightdm_user_class_init (LightDMUserClass *klass) "logged-in", "TRUE if the user is currently in a session", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); + + /** + * LightDMUser::changed: + * @user: A #LightDMUser + * + * The ::changed signal gets emitted this user account is modified. + **/ + signals[CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (LightDMUserClass, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } |