diff options
Diffstat (limited to 'src/users-service-dbus.c')
-rw-r--r-- | src/users-service-dbus.c | 1481 |
1 files changed, 768 insertions, 713 deletions
diff --git a/src/users-service-dbus.c b/src/users-service-dbus.c index 09f916d..fec17dc 100644 --- a/src/users-service-dbus.c +++ b/src/users-service-dbus.c @@ -4,6 +4,7 @@ * * Authors: * Cody Russell <crussell@canonical.com> + * Charles Kerr <charles.kerr@canonical.com> * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -19,101 +20,134 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <string.h> +#include <glib.h> + #include <errno.h> -#include <pwd.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-lowlevel.h> +#include <pwd.h> /* getpwuid() */ -#include "dbus-shared-names.h" -#include "display-manager-client.h" +#include "dbus-accounts.h" +#include "dbus-consolekit-manager.h" +#include "dbus-consolekit-seat.h" +#include "dbus-consolekit-session.h" +#include "dbus-display-manager.h" +#include "dbus-user.h" +#include "shared-names.h" #include "users-service-dbus.h" -#include "accounts-service-client.h" -#include "consolekit-manager-client.h" -#include "consolekit-session-client.h" -#include "consolekit-seat-client.h" #define CK_ADDR "org.freedesktop.ConsoleKit" #define CK_SESSION_IFACE "org.freedesktop.ConsoleKit.Session" +/** +*** +**/ + +static void update_user_list (UsersServiceDbus * self); + +static gchar* get_seat (UsersServiceDbus * service); + +static void on_user_added (Accounts * o, + const gchar * user_object_path, + UsersServiceDbus * service); + +static void on_user_deleted (Accounts * o, + const gchar * user_object_path, + UsersServiceDbus * service); -static void users_service_dbus_class_init (UsersServiceDbusClass *klass); -static void users_service_dbus_init (UsersServiceDbus *self); -static void users_service_dbus_dispose (GObject *object); -static void users_service_dbus_finalize (GObject *object); -static void create_display_manager_proxy (UsersServiceDbus *self); -static void create_accounts_service_proxy (UsersServiceDbus *self); -static void create_seat_proxy (UsersServiceDbus *self); -static void create_ck_proxy (UsersServiceDbus *self); -static void create_cksession_proxy (UsersServiceDbus *self); -static gchar *get_seat (UsersServiceDbus *service); -static void user_added (DBusGProxy *proxy, - const gchar *user_id, - gpointer user_data); -static void user_deleted (DBusGProxy *proxy, - const gchar *user_id, - gpointer user_data); -static void user_changed (DBusGProxy *proxy, - gpointer user_data); -static void seat_proxy_session_added (DBusGProxy *seat_proxy, - const gchar *session_id, - UsersServiceDbus *service); -static void seat_proxy_session_removed (DBusGProxy *seat_proxy, - const gchar *session_id, - UsersServiceDbus *service); -static void sync_users (UsersServiceDbus *self); -static gboolean do_add_session (UsersServiceDbus *service, - UserData *user, - const gchar *ssid); -static gchar * get_seat_internal (DBusGProxy *proxy); - -/* Private */ -typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate; +static void on_session_added (ConsoleKitSeat * seat, + const gchar * ssid, + UsersServiceDbus * service); + +static void on_session_removed (ConsoleKitSeat * seat, + const gchar * ssid, + UsersServiceDbus * service); + +static void on_session_list (ConsoleKitSeat * seat, + GAsyncResult * result, + UsersServiceDbus * service); + +/*** +**** Priv Struct +***/ struct _UsersServiceDbusPrivate { - GHashTable *users; - gint count; - gchar *seat; - gchar *ssid; - - DBusGConnection *system_bus; + gchar * seat; + gchar * guest_ssid; - DBusGProxy *accounts_service_proxy; - DBusGProxy *display_manager_proxy; - DBusGProxy *display_manager_props_proxy; - DBusGProxy *ck_proxy; - DBusGProxy *seat_proxy; - DBusGProxy *session_proxy; + /* ssid -> AccountsUser lookup */ + GHashTable * sessions; - GHashTable *exclusions; - GHashTable *sessions; + /* user object path -> AccountsUser lookup */ + GHashTable * users; - DbusmenuMenuitem * guest_item; - gchar * guest_session_id; - gboolean guest_session_enabled; + GCancellable * cancellable; + ConsoleKitSeat * seat_proxy; + ConsoleKitManager * ck_manager_proxy; + Accounts * accounts_proxy; }; -#define USERS_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusPrivate)) +/*** +**** GObject +***/ -/* Signals */ -enum { - USER_ADDED, - USER_DELETED, - LAST_SIGNAL +enum +{ + USER_LIST_CHANGED, + USER_LOGGED_IN_CHANGED, + GUEST_LOGGED_IN_CHANGED, + N_SIGNALS }; -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[N_SIGNALS] = { 0 }; -/* GObject Boilerplate */ G_DEFINE_TYPE (UsersServiceDbus, users_service_dbus, G_TYPE_OBJECT); static void +users_service_dbus_dispose (GObject *object) +{ + UsersServiceDbusPrivate * priv = USERS_SERVICE_DBUS(object)->priv; + + g_clear_object (&priv->accounts_proxy); + g_clear_object (&priv->seat_proxy); + g_clear_object (&priv->ck_manager_proxy); + + if (priv->cancellable != NULL) + { + g_cancellable_cancel (priv->cancellable); + g_clear_object (&priv->cancellable); + } + + if (priv->users != NULL) + { + g_hash_table_destroy (priv->users); + priv->users = NULL; + } + + if (priv->sessions != NULL) + { + g_hash_table_destroy (priv->sessions); + priv->sessions = NULL; + } + + G_OBJECT_CLASS (users_service_dbus_parent_class)->dispose (object); +} + +static void +users_service_dbus_finalize (GObject *object) +{ + UsersServiceDbusPrivate * priv = USERS_SERVICE_DBUS(object)->priv; + + g_free (priv->guest_ssid); + g_free (priv->seat); + + G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object); +} + +static void users_service_dbus_class_init (UsersServiceDbusClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -123,845 +157,866 @@ users_service_dbus_class_init (UsersServiceDbusClass *klass) object_class->dispose = users_service_dbus_dispose; object_class->finalize = users_service_dbus_finalize; - signals[USER_ADDED] = g_signal_new ("user-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (UsersServiceDbusClass, user_added), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - signals[USER_DELETED] = g_signal_new ("user-deleted", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (UsersServiceDbusClass, user_deleted), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + signals[USER_LIST_CHANGED] = g_signal_new ( + "user-list-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (UsersServiceDbusClass, user_list_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[USER_LOGGED_IN_CHANGED] = g_signal_new ( + "user-logged-in-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (UsersServiceDbusClass, user_logged_in_changed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + signals[GUEST_LOGGED_IN_CHANGED] = g_signal_new ( + "guest-logged-in-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (UsersServiceDbusClass, guest_logged_in_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void users_service_dbus_init (UsersServiceDbus *self) { - GError *error = NULL; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + GError * error = NULL; - priv->users = NULL; - priv->count = 0; - priv->guest_item = NULL; - priv->guest_session_id = NULL; - - priv->guest_session_enabled = FALSE; + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + USERS_SERVICE_DBUS_TYPE, + UsersServiceDbusPrivate); - /* Get the system bus */ - priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + UsersServiceDbusPrivate * p = self->priv; + + p->cancellable = g_cancellable_new (); + + /* ssid -> AccountsUser */ + p->sessions = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_object_unref); + + /* user object path -> AccountsUser */ + p->users = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_object_unref); + + /** + *** create the consolekit manager proxy... + **/ + + p->ck_manager_proxy = console_kit_manager_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + NULL, + &error); if (error != NULL) { - g_error ("Unable to get system bus"); - g_error_free(error); - - return; + g_warning ("%s: %s", G_STRLOC, error->message); + g_clear_error (&error); } - priv->sessions = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); + p->seat = get_seat (self); - priv->users = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); + /** + *** create the consolekit seat proxy... + **/ + + if (p->seat != NULL) + { + ConsoleKitSeat * proxy = console_kit_seat_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.ConsoleKit", + p->seat, + NULL, + &error); - create_ck_proxy (self); - create_seat_proxy (self); - create_display_manager_proxy (self); - create_accounts_service_proxy (self); + if (error != NULL) + { + g_warning ("Failed to connect to the ConsoleKit seat: %s", error->message); + g_clear_error (&error); + } + else + { + g_signal_connect (proxy, "session-added", + G_CALLBACK (on_session_added), self); + g_signal_connect (proxy, "session-removed", + G_CALLBACK (on_session_removed), self); + console_kit_seat_call_get_sessions (proxy, p->cancellable, + (GAsyncReadyCallback)on_session_list, self); + p->seat_proxy = proxy; + } + } + + /** + *** create the accounts manager proxy... + **/ + + Accounts * proxy = accounts_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + "/org/freedesktop/Accounts", + NULL, + &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } + else + { + g_signal_connect (proxy, "user-added", G_CALLBACK(on_user_added), self); + g_signal_connect (proxy, "user-deleted", G_CALLBACK(on_user_deleted), self); + p->accounts_proxy = proxy; + update_user_list (self); + } } +/*** +**** +***/ + static void -users_service_dbus_dispose (GObject *object) +emit_user_list_changed (UsersServiceDbus * self) { - G_OBJECT_CLASS (users_service_dbus_parent_class)->dispose (object); + g_signal_emit (self, signals[USER_LIST_CHANGED], 0); } static void -users_service_dbus_finalize (GObject *object) +emit_user_login_changed (UsersServiceDbus * self, AccountsUser * user) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (object); - - if (priv->guest_session_id != NULL) { - g_free(priv->guest_session_id); - priv->guest_session_id = NULL; - } - - G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object); + g_signal_emit (self, signals[USER_LOGGED_IN_CHANGED], 0, user); } - static void -create_display_manager_proxy (UsersServiceDbus *self) -{ - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GError *error = NULL; - const gchar *seat = NULL; - - seat = g_getenv ("XDG_SEAT_PATH"); - g_debug ("CREATING DM PROXIES WITH %s", seat); - priv->display_manager_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.DisplayManager", - seat, - "org.freedesktop.DisplayManager.Seat"); - - priv->display_manager_props_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.DisplayManager", - seat, - "org.freedesktop.DBus.Properties"); - - - if (!priv->display_manager_proxy) - { - g_warning ("Failed to get DisplayManager seat proxy."); - return; - } - if (!priv->display_manager_props_proxy) - { - g_warning ("Failed to get DisplayManager Properties seat proxy."); - return; - } - - GValue has_guest_session = {0}; - g_value_init (&has_guest_session, G_TYPE_BOOLEAN); - if (!dbus_g_proxy_call (priv->display_manager_props_proxy, - "Get", - &error, - G_TYPE_STRING, - "org.freedesktop.DisplayManager.Seat", - G_TYPE_STRING, - "HasGuestAccount", - G_TYPE_INVALID, - G_TYPE_VALUE, - &has_guest_session, - G_TYPE_INVALID)) - { - g_warning ("Failed to get the HasGuestSession property from the DisplayManager Properties seat proxy. error: %s", error->message); - g_error_free (error); - return; - } - g_debug ("Does seat have a guest account = %i", g_value_get_boolean (&has_guest_session)); - priv->guest_session_enabled = g_value_get_boolean (&has_guest_session); +emit_guest_login_changed (UsersServiceDbus * self) +{ + g_signal_emit (self, signals[GUEST_LOGGED_IN_CHANGED], 0); } -static void -create_accounts_service_proxy (UsersServiceDbus *self) -{ - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GPtrArray *users = g_ptr_array_new (); - GError *error = NULL; - - priv->accounts_service_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.Accounts", - "/org/freedesktop/Accounts", - "org.freedesktop.Accounts"); - - dbus_g_proxy_add_signal (priv->accounts_service_proxy, - "UserAdded", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - - dbus_g_proxy_add_signal (priv->accounts_service_proxy, - "UserChanged", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - - dbus_g_proxy_add_signal (priv->accounts_service_proxy, - "UserDeleted", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->accounts_service_proxy, - "UserAdded", - G_CALLBACK (user_added), - self, - NULL); - - dbus_g_proxy_connect_signal (priv->accounts_service_proxy, - "UserDeleted", - G_CALLBACK (user_deleted), - self, - NULL); - - if (!org_freedesktop_Accounts_list_cached_users (priv->accounts_service_proxy, - &users, - &error)) - { - g_warning ("failed to retrieve user count: %s", error->message); - g_error_free (error); +/*** +**** +***/ - return; +static ConsoleKitSession* +create_consolekit_session_proxy (const char * ssid) +{ + GError * error = NULL; + + ConsoleKitSession * p = console_kit_session_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + CK_ADDR, + ssid, + NULL, + &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); } - priv->count = users->len; - g_ptr_array_free (users, TRUE); - sync_users (self); + return p; } -static void -create_ck_proxy (UsersServiceDbus *self) +static gchar * +get_seat_from_session_proxy (ConsoleKitSession * session_proxy) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + gchar * seat = NULL; - priv->ck_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.ConsoleKit", - "/org/freedesktop/ConsoleKit/Manager", - "org.freedesktop.ConsoleKit.Manager"); - - if (!priv->ck_proxy) + GError * error = NULL; + console_kit_session_call_get_seat_id_sync (session_proxy, + &seat, + NULL, + &error); + if (error != NULL) { - g_warning ("Failed to get ConsoleKit proxy."); - return; + g_debug ("%s: %s", G_STRLOC, error->message); + g_error_free (error); } + + return seat; } -/* Get the initial sessions when starting up */ -static void -get_cksessions_cb (DBusGProxy *proxy, GPtrArray * sessions, GError * error, gpointer userdata) +static gchar * +get_seat (UsersServiceDbus *service) { - if (error != NULL) { - g_warning("Unable to get initial sessions: %s", error->message); - return; - } + gchar * seat = NULL; + gchar * ssid = NULL; + GError * error = NULL; + UsersServiceDbusPrivate * priv = service->priv; - /* If there's no error we should at least get an - array of zero entries */ - g_return_if_fail(sessions != NULL); - g_debug("Got %d initial sessions", sessions->len); + console_kit_manager_call_get_current_session_sync (priv->ck_manager_proxy, + &ssid, + NULL, + &error); - int i; - for (i = 0; i < sessions->len; i++) { - seat_proxy_session_added(proxy, g_ptr_array_index(sessions, i), USERS_SERVICE_DBUS(userdata)); - } + if (error != NULL) + { + g_debug ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + } + else + { + ConsoleKitSession * session = create_consolekit_session_proxy (ssid); + + if (session != NULL) + { + seat = get_seat_from_session_proxy (session); + g_object_unref (session); + } + } - return; + return seat; } -static void -create_seat_proxy (UsersServiceDbus *self) +/*** +**** AccountsUser add-ons for tracking sessions +***/ + +static GHashTable* +user_get_sessions_hashset (AccountsUser * user) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GError *error = NULL; + static GQuark q = 0; - priv->seat = get_seat (self); - if (priv->seat == NULL) + if (G_UNLIKELY(!q)) { - return; + q = g_quark_from_static_string ("sessions"); } - priv->seat_proxy = dbus_g_proxy_new_for_name_owner (priv->system_bus, - "org.freedesktop.ConsoleKit", - priv->seat, - "org.freedesktop.ConsoleKit.Seat", - &error); - - if (!priv->seat_proxy) + GObject * o = G_OBJECT (user); + GHashTable * h = g_object_get_qdata (o, q); + if (h == NULL) { - if (error != NULL) - { - g_warning ("Failed to connect to the ConsoleKit seat: %s", error->message); - g_error_free (error); - } - - return; + h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_object_set_qdata_full (o, q, h, (GDestroyNotify)g_hash_table_destroy); } - dbus_g_proxy_add_signal (priv->seat_proxy, - "SessionAdded", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->seat_proxy, - "SessionRemoved", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); + return h; +} - dbus_g_proxy_connect_signal (priv->seat_proxy, - "SessionAdded", - G_CALLBACK (seat_proxy_session_added), - self, - NULL); - dbus_g_proxy_connect_signal (priv->seat_proxy, - "SessionRemoved", - G_CALLBACK (seat_proxy_session_removed), - self, - NULL); +static void +user_add_session (AccountsUser * user, const char * ssid) +{ + g_hash_table_add (user_get_sessions_hashset(user), g_strdup(ssid)); +} - org_freedesktop_ConsoleKit_Seat_get_sessions_async (priv->seat_proxy, get_cksessions_cb, self); +static void +user_remove_session (AccountsUser * user, const char * ssid) +{ + g_hash_table_remove (user_get_sessions_hashset(user), ssid); +} - return; +static guint +user_count_sessions (AccountsUser * user) +{ + return g_hash_table_size (user_get_sessions_hashset(user)); } +/*** +**** Users +***/ + +/* adds this user session to the user's and service's session tables */ static void -create_cksession_proxy (UsersServiceDbus *service) +add_user_session (UsersServiceDbus * service, + AccountsUser * user, + const gchar * ssid) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); + ConsoleKitSession * session_proxy = create_consolekit_session_proxy (ssid); + if (session_proxy != NULL) + { + UsersServiceDbusPrivate * priv = service->priv; + gchar * seat = get_seat_from_session_proxy (session_proxy); - priv->session_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - CK_ADDR, - priv->ssid, - CK_SESSION_IFACE); + /* is this session in our seat? */ + if (seat && priv->seat && !g_strcmp0 (seat, priv->seat)) + { + /* does this session have a display? */ + gchar * display = NULL; + console_kit_session_call_get_x11_display_sync (session_proxy, + &display, + NULL, NULL); + const gboolean has_display = display && *display; + g_free (display); + + if (has_display) + { + const gchar * username = accounts_user_get_user_name (user); + g_debug ("%s adding %s's session '%s' to our tables", + G_STRLOC, username, ssid); - if (!priv->session_proxy) - { - g_warning ("Failed to get ConsoleKit session proxy"); - return; + g_hash_table_insert (priv->sessions, + g_strdup (ssid), + g_object_ref (user)); + + user_add_session (user, ssid); + } + } + + g_free (seat); + g_object_unref (session_proxy); } } -static gchar * -get_seat (UsersServiceDbus *service) +/* calls add_user_session() for each of this user's sessions */ +static void +add_user_sessions (UsersServiceDbus *self, AccountsUser * user) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - GError *error = NULL; - gchar *ssid = NULL; - gchar *seat; + const guint64 uid = accounts_user_get_uid (user); + const char * username = accounts_user_get_user_name (user); + g_debug ("%s adding %s (%i)", G_STRLOC, username, (int)uid); + + GError * error = NULL; + gchar ** sessions = NULL; + console_kit_manager_call_get_sessions_for_unix_user_sync ( + self->priv->ck_manager_proxy, + uid, + &sessions, + NULL, + &error); - if (!dbus_g_proxy_call (priv->ck_proxy, - "GetCurrentSession", - &error, - G_TYPE_INVALID, - DBUS_TYPE_G_OBJECT_PATH, - &ssid, - G_TYPE_INVALID)) + if (error != NULL) { - if (error) + g_debug ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + } + else if (sessions != NULL) + { + int i; + + for (i=0; sessions[i]; i++) { - g_debug ("Failed to call GetCurrentSession: %s", error->message); - g_error_free (error); + const char * const ssid = sessions[i]; + g_debug ("%s adding %s's session %s", G_STRLOC, username, ssid); + add_user_session (self, user, ssid); } - if (ssid) - g_free (ssid); - - return NULL; + g_strfreev (sessions); } +} - priv->ssid = ssid; - create_cksession_proxy (service); - - seat = get_seat_internal (priv->session_proxy); - - return seat; +/* returns true if this property is one we use */ +static gboolean +is_interesting_user_property (const char * key) +{ + return !g_strcmp0 (key, "IconFile") + || !g_strcmp0 (key, "LoginFrequency") + || !g_strcmp0 (key, "RealName") + || !g_strcmp0 (key, "Uid") + || !g_strcmp0 (key, "UserName"); } -static gchar * -get_seat_internal (DBusGProxy *proxy) +static void +sync_user_properties (GDBusProxy * source, GDBusProxy * target) { - GError *error = NULL; - gchar *seat = NULL; + gchar ** keys = g_dbus_proxy_get_cached_property_names (source); - if (!org_freedesktop_ConsoleKit_Session_get_seat_id (proxy, &seat, &error)) + if (keys != NULL) { - if (error) + int i; + GVariantBuilder builder; + gboolean changed = FALSE; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + + for (i=0; keys[i]; i++) { - g_debug ("Failed to call GetSeatId: %s", error->message); + const gchar * const key = keys[i]; - return NULL; + if (is_interesting_user_property (key)) + { + GVariant * oldval = g_dbus_proxy_get_cached_property (target, key); + GVariant * newval = g_dbus_proxy_get_cached_property (source, key); + + /* all the properties we're interested in are + basic types safe for g_variant_compare()... */ + g_assert (g_variant_type_is_basic(g_variant_get_type(newval))); + + if (g_variant_compare (oldval, newval)) + { + changed = TRUE; + g_dbus_proxy_set_cached_property (target, key, newval); + g_variant_builder_add (&builder, "{sv}", key, newval); + } + + g_variant_unref (newval); + g_variant_unref (oldval); + } } - } - return seat; -} - -static gboolean -get_unix_user (UsersServiceDbus *service, - const gchar *session_id, - uid_t *uidp) -{ - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - GError *error = NULL; - guint uid; - DBusGProxy *session_proxy; - - g_debug("Building session proxy for: %s", session_id); - session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus, - CK_ADDR, - session_id, - CK_SESSION_IFACE, - &error); - - if (error != NULL) { - g_warning("Unable to get CK Session proxy: %s", error->message); - g_error_free(error); - return FALSE; - } - - if (!org_freedesktop_ConsoleKit_Session_get_unix_user(session_proxy, &uid, &error)) - { - if (error) + if (changed) { - g_warning ("Failed to call GetUnixUser: %s", error->message); - g_error_free (error); + g_signal_emit_by_name (target, "g-properties-changed", g_variant_builder_end(&builder), keys); } - g_object_unref(session_proxy); - return FALSE; + g_variant_builder_clear (&builder); + g_strfreev (keys); } +} - if (uidp != NULL) +/** + * The AccountsUserProxy's properties aren't being updated automatically + * for some reason... the only update we get is the 'changed' signal. + * This function is a workaround to update our User object's properties. + */ +static void +on_user_changed (AccountsUser * user, UsersServiceDbus * service) +{ + AccountsUser * tmp = accounts_user_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + g_dbus_proxy_get_object_path (G_DBUS_PROXY(user)), + NULL, + NULL); + if (tmp != NULL) { - *uidp = (uid_t)uid; + sync_user_properties (G_DBUS_PROXY(tmp), G_DBUS_PROXY(user)); + g_object_unref (tmp); } - - g_object_unref(session_proxy); - return TRUE; } -static gboolean -do_add_session (UsersServiceDbus *service, - UserData *user, - const gchar *ssid) -{ - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - GError *error = NULL; - gchar *seat = NULL; - gchar *xdisplay = NULL; - DBusGProxy * session_proxy; - GList *l; - - session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus, - CK_ADDR, - ssid, - CK_SESSION_IFACE, - &error); - - if (error != NULL) { - g_warning("Unable to get CK Session proxy: %s", error->message); - g_error_free(error); - return FALSE; - } - - seat = get_seat_internal (session_proxy); - - if (!seat || !priv->seat || strcmp (seat, priv->seat) != 0) { - g_object_unref(session_proxy); - return FALSE; - } - - if (!org_freedesktop_ConsoleKit_Session_get_x11_display (session_proxy, &xdisplay, &error)) - { - if (error) - { - g_debug ("Failed to call GetX11Display: %s", error->message); - g_error_free (error); - } - - g_object_unref(session_proxy); - return FALSE; - } - - g_object_unref(session_proxy); - - if (!xdisplay || xdisplay[0] == '\0') - return FALSE; +static void +add_user_from_object_path (UsersServiceDbus * self, + const char * user_object_path) +{ + GError * error = NULL; - g_hash_table_insert (priv->sessions, - g_strdup (ssid), - g_strdup (user->user_name)); + AccountsUser * user = accounts_user_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + user_object_path, + NULL, + &error); - l = g_list_find_custom (user->sessions, ssid, (GCompareFunc)g_strcmp0); - if (l == NULL) + if (error != NULL) { - g_debug ("Adding session %s", ssid); - - user->sessions = g_list_prepend (user->sessions, g_strdup (ssid)); - - if (user->menuitem != NULL) { - dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, TRUE); - } + g_warning ("%s: %s", G_STRLOC, error->message); + g_clear_error (&error); } else { - g_debug ("User %s already has session %s", user->user_name, ssid); - } + AccountsUser * prev = g_hash_table_lookup (self->priv->users, user_object_path); + + if (prev != NULL) /* we've already got this user... sync its properties */ + { + sync_user_properties (G_DBUS_PROXY(user), G_DBUS_PROXY(prev)); + g_object_unref (user); + user = prev; + } + else /* ooo, we got a new user */ + { + g_signal_connect (user, "changed", G_CALLBACK(on_user_changed), self); + g_hash_table_insert (self->priv->users, g_strdup(user_object_path), user); + } - return TRUE; + add_user_sessions (self, user); + } } + +/* asks org.freedesktop.Accounts for a list of users and + * calls add_user_from_object_path() on each of those users */ static void -add_sessions_for_user (UsersServiceDbus *self, - UserData *user) +update_user_list (UsersServiceDbus *self) { - g_return_if_fail (IS_USERS_SERVICE_DBUS(self)); + g_return_if_fail(IS_USERS_SERVICE_DBUS(self)); - g_debug ("!!!!!!!!!! - add_sessions_for_user %i %s", - (int)user->uid, user->user_name); + GError * error = NULL; + char ** object_paths = NULL; + UsersServiceDbusPrivate * priv = self->priv; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GError *error; - GPtrArray *sessions; - int i; + accounts_call_list_cached_users_sync (priv->accounts_proxy, + &object_paths, + NULL, + &error); - error = NULL; - if (!org_freedesktop_ConsoleKit_Manager_get_sessions_for_unix_user(priv->ck_proxy, user->uid, &sessions, &error)) + if (error != NULL) { - g_debug ("Failed to call GetSessionsForUnixUser: %s", error->message); - g_error_free (error); - - return; + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); } - - for (i = 0; i < sessions->len; i++) + else if (object_paths != NULL) { - char *ssid; + gint i; - ssid = g_ptr_array_index (sessions, i); - do_add_session (self, user, ssid); + for (i=0; object_paths[i] != NULL; ++i) + { + add_user_from_object_path (self, object_paths[i]); + } + + emit_user_list_changed (self); + + g_strfreev (object_paths); } - g_ptr_array_foreach (sessions, (GFunc)g_free, NULL); - g_ptr_array_free (sessions, TRUE); + g_debug ("%s finished updating the user list", G_STRLOC); } +static void +on_user_added (Accounts * o G_GNUC_UNUSED, + const gchar * user_path G_GNUC_UNUSED, + UsersServiceDbus * service) +{ + /* We see a new user but we might not want to list it -- + for example, lightdm shows up when we switch to the greeter. + So instead of adding the user directly here, let's ask + org.freedesktop.Accounts for a fresh list of users + because it filters out special cases. */ + update_user_list (service); +} static void -seat_proxy_session_added (DBusGProxy *seat_proxy, - const gchar *session_id, - UsersServiceDbus *service) +on_user_deleted (Accounts * o G_GNUC_UNUSED, + const gchar * user_path, + UsersServiceDbus * service) { - g_return_if_fail(IS_USERS_SERVICE_DBUS(service)); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - uid_t uid; - struct passwd *pwent; - UserData *user; + AccountsUser * user = g_hash_table_lookup (service->priv->users, user_path); - if (!get_unix_user (service, session_id, &uid)) + if (user != NULL) { - g_warning ("Failed to lookup user for session"); - return; + GObject * o = g_object_ref (G_OBJECT(user)); + g_hash_table_remove (service->priv->users, user_path); + emit_user_list_changed (service); + g_object_unref (o); } +} - errno = 0; - pwent = getpwuid (uid); - if (!pwent) - { - g_warning ("Failed to lookup user id %d: %s", (int)uid, g_strerror (errno)); - return; - } +static AccountsUser * +find_user_from_username (UsersServiceDbus * self, + const gchar * username) +{ + AccountsUser * match = NULL; - /* We need to special case guest here because it doesn't - show up in the GDM user tables. */ - if (g_strcmp0("guest", pwent->pw_name) == 0) { - if (priv->guest_item != NULL) { - dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, TRUE); - } - priv->guest_session_id = g_strdup(session_id); - g_debug("Found guest session: %s", priv->guest_session_id); - return; - } + g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), match); - user = users_service_dbus_get_user_by_username (service, pwent->pw_name); - if (!user) - return; + gpointer user; + GHashTableIter iter; + g_hash_table_iter_init (&iter, self->priv->users); + while (!match && g_hash_table_iter_next (&iter, NULL, &user)) + { + if (!g_strcmp0 (username, accounts_user_get_user_name (user))) + { + match = user; + } + } - do_add_session (service, user, session_id); + return match; } +/*** +**** Sessions +***/ + static void -seat_proxy_session_removed (DBusGProxy *seat_proxy, - const gchar *session_id, - UsersServiceDbus *service) -{ - g_return_if_fail(IS_USERS_SERVICE_DBUS(service)); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - UserData *user; - gchar *username; - GList *l; - - username = g_hash_table_lookup (priv->sessions, session_id); - if (!username) { - if (g_strcmp0(session_id, priv->guest_session_id) == 0) { - g_debug("Removing guest session: %s", priv->guest_session_id); - if (priv->guest_item != NULL) { - dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, FALSE); - } - g_free(priv->guest_session_id); - priv->guest_session_id = NULL; - } - return; - } - - user = users_service_dbus_get_user_by_username (service, username); - if (!user) - return; - - l = g_list_find_custom (user->sessions, - session_id, - (GCompareFunc)g_strcmp0); - if (l) - { - g_debug ("Removing session %s", session_id); - - g_free (l->data); - user->sessions = g_list_delete_link (user->sessions, l); - if (user->menuitem != NULL && user->sessions == NULL) { - dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, FALSE); - } +on_session_removed (ConsoleKitSeat * seat_proxy, + const gchar * ssid, + UsersServiceDbus * service) +{ + g_return_if_fail (IS_USERS_SERVICE_DBUS (service)); + + UsersServiceDbusPrivate * priv = service->priv; + g_debug ("%s %s() session removed %s", G_STRLOC, G_STRFUNC, ssid); + + if (!g_strcmp0 (ssid, priv->guest_ssid)) + { + g_debug ("%s removing guest session %s", G_STRLOC, ssid); + g_clear_pointer (&priv->guest_ssid, g_free); + emit_guest_login_changed (service); } else { - g_debug ("Session not found: %s", session_id); + AccountsUser * user = g_hash_table_lookup (priv->sessions, ssid); + if (user == NULL) + { + g_debug ("%s we're not tracking ssid %s", G_STRLOC, ssid); + } + else + { + GObject * o = g_object_ref (G_OBJECT(user)); + g_hash_table_remove (service->priv->users, ssid); + user_remove_session (user, ssid); + emit_user_login_changed (service, user); + g_object_unref (o); + } } } -static void -sync_users (UsersServiceDbus *self) +static gchar* +get_unix_username_from_ssid (UsersServiceDbus * self, + const gchar * ssid) { - g_return_if_fail(IS_USERS_SERVICE_DBUS(self)); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + gchar * username = NULL; - if (priv->count > MINIMUM_USERS) + ConsoleKitSession * session_proxy = create_consolekit_session_proxy (ssid); + if (session_proxy != NULL) { - GPtrArray *users = NULL; - GError *error = NULL; - gint i; - - users = g_ptr_array_new (); - - if (!org_freedesktop_Accounts_list_cached_users (priv->accounts_service_proxy, - &users, - &error)) + guint uid = 0; + GError * error = NULL; + console_kit_session_call_get_unix_user_sync (session_proxy, + &uid, + NULL, &error); + if (error != NULL) { - g_warning ("failed to retrieve user list: %s", error->message); - g_error_free (error); - - return; + g_warning ("%s: %s", G_STRLOC, error->message); + g_clear_error (&error); } - - for (i = 0; i < users->len; i++) + else { - gchar *id; - DBusGProxy *proxy; - UserData *user; - GError *error = NULL; - - id = g_ptr_array_index (users, i); - - proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.Accounts", - id, - "org.freedesktop.DBus.Properties"); - - GHashTable *properties; - if (!dbus_g_proxy_call (proxy, "GetAll", &error, - G_TYPE_STRING, "org.freedesktop.Accounts.User", G_TYPE_INVALID, - dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &properties, G_TYPE_INVALID)) - { - g_warning ("unable to retrieve user info: %s", error->message); - g_error_free (error); - - continue; - } - - user = g_hash_table_lookup (priv->users, id); - // Double check we havent processed this user already - if (user != NULL) + errno = 0; + const struct passwd * pwent = getpwuid (uid); + if (pwent == NULL) { - g_free(user->user_name); - g_free(user->real_name); - g_free(user->icon_file); - user->real_name_conflict = FALSE; - //continue; + g_warning ("Failed to lookup user id %d: %s", (int)uid, g_strerror(errno)); } else - { - user = g_new0 (UserData, 1); + { + username = g_strdup (pwent->pw_name); } - // Can't subscribe to the Changed signal on each individual user path - // for some reason. - dbus_g_proxy_add_signal (proxy, - "Changed", - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (proxy, "Changed", - G_CALLBACK(user_changed), - self, - NULL); - user->uid = g_value_get_uint64 (g_hash_table_lookup (properties, "Uid")); - user->user_name = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "UserName"))); - user->real_name = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "RealName"))); - user->icon_file = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "IconFile"))); - user->real_name_conflict = FALSE; - user->menuitem = NULL; - - g_hash_table_unref (properties); - - g_hash_table_insert (priv->users, - g_strdup (id), - user); - - add_sessions_for_user (self, user); } - g_ptr_array_free (users, TRUE); + g_object_unref (session_proxy); } + + return username; } -static void -user_changed (DBusGProxy *proxy, - gpointer user_data) +static gboolean +is_guest_username (const char * username) { - g_debug ("JUST RESYNCED THE USERS FROM A USER CHANGE"); - UsersServiceDbus *service = (UsersServiceDbus *)user_data; - sync_users (service); + if (!g_strcmp0 (username, "guest")) + return TRUE; + + if (username && g_str_has_prefix (username, "guest-")) + return TRUE; + + return FALSE; } +/* If the new session belongs to 'guest', update our guest_ssid. + Otherwise, call add_user_session() to update our session tables */ static void -user_added (DBusGProxy *proxy, - const gchar *user_id, - gpointer user_data) +on_session_added (ConsoleKitSeat * seat_proxy G_GNUC_UNUSED, + const gchar * ssid, + UsersServiceDbus * service) { - UsersServiceDbus *service = (UsersServiceDbus *)user_data; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - priv->count++; - sync_users (service); - g_signal_emit (service, - signals[USER_ADDED], - 0, - user_id); -} + g_return_if_fail (IS_USERS_SERVICE_DBUS(service)); -static void -user_deleted (DBusGProxy *proxy, - const gchar *user_id, - gpointer user_data) -{ - UsersServiceDbus *service = (UsersServiceDbus *)user_data; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); + gchar * username = get_unix_username_from_ssid (service, ssid); + g_debug ("%s %s() username %s has new session %s", G_STRLOC, G_STRFUNC, username, ssid); + + if (is_guest_username (username)) + { + /* handle guest as a special case -- it's not in the GDM + user tables and there isn't be an AccountsUser for it */ + g_debug("Found guest session: %s", ssid); + g_free (service->priv->guest_ssid); + service->priv->guest_ssid = g_strdup (ssid); + emit_guest_login_changed (service); + } + else + { + AccountsUser * user = find_user_from_username (service, username); - priv->count--; - g_hash_table_remove (priv->users, user_id); + if (user != NULL) + { + add_user_session (service, user, ssid); + emit_user_login_changed (service, user); + } + } - g_signal_emit (service, - signals[USER_DELETED], - 0, - user_id); - + g_free (username); } -UserData * -users_service_dbus_get_user_by_username (UsersServiceDbus *self, - const gchar *username) +/* Receives a list of sessions and calls on_session_added() for each of them */ +static void +on_session_list (ConsoleKitSeat * seat_proxy, + GAsyncResult * result, + UsersServiceDbus * self) { - GHashTableIter iter; - gpointer value; + GError * error = NULL; + gchar ** sessions = NULL; + g_debug ("%s bootstrapping the session list", G_STRLOC); - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), NULL); + console_kit_seat_call_get_sessions_finish (seat_proxy, + &sessions, + result, + &error); + + if (error != NULL) + { + g_debug ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + } + else if (sessions != NULL) + { + int i; + + for (i=0; sessions[i]; i++) + { + g_debug ("%s adding initial session '%s'", G_STRLOC, sessions[i]); + on_session_added (seat_proxy, sessions[i], self); + } + + g_strfreev (sessions); + } + + g_debug ("%s done bootstrapping the session list", G_STRLOC); +} - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); +static DisplayManagerSeat * +create_display_proxy (UsersServiceDbus * self) +{ + const gchar * const seat = g_getenv ("XDG_SEAT_PATH"); + g_debug ("%s creating a DisplayManager proxy for seat %s", G_STRLOC, seat); + + GError * error = NULL; + DisplayManagerSeat * p = display_manager_seat_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.DisplayManager", + seat, + NULL, + &error); - g_hash_table_iter_init (&iter, priv->users); - while (g_hash_table_iter_next (&iter, NULL, &value)) + if (error != NULL) { - UserData *user = value; - if (strcmp (user->user_name, username) == 0) - return user; + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); } - return NULL; + return p; } +/*** +**** Public API +***/ + +/** + * users_service_dbus_get_user_list: + * + * Returns: (transfer container): a list of AccountsUser objects + */ GList * -users_service_dbus_get_user_list (UsersServiceDbus *self) +users_service_dbus_get_user_list (UsersServiceDbus * self) { g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), NULL); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + return g_hash_table_get_values (self->priv->users); +} + +/** + * users_service_dbus_show_greeter: + * + * Ask the Display Mnaager to switch to the greeter screen. + */ +void +users_service_dbus_show_greeter (UsersServiceDbus * self) +{ + g_return_if_fail (IS_USERS_SERVICE_DBUS(self)); - return g_hash_table_get_values (priv->users); + DisplayManagerSeat * dp = create_display_proxy (self); + display_manager_seat_call_switch_to_greeter_sync (dp, NULL, NULL); + g_clear_object (&dp); } -gboolean -users_service_dbus_show_greeter (UsersServiceDbus *self) +/** + * users_service_dbus_activate_guest_session: + * + * Activates the guest account. + */ +void +users_service_dbus_activate_guest_session (UsersServiceDbus * self) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return org_freedesktop_DisplayManager_Seat_switch_to_greeter(priv->display_manager_proxy, NULL); + g_return_if_fail(IS_USERS_SERVICE_DBUS(self)); + + DisplayManagerSeat * dp = create_display_proxy (self); + display_manager_seat_call_switch_to_guest_sync (dp, "", NULL, NULL); + g_clear_object (&dp); } -/* Activates the guest account if it can. */ -gboolean -users_service_dbus_activate_guest_session (UsersServiceDbus *self) +/** + * users_service_dbus_activate_user_session: + * + * Activates a specific user. + */ +void +users_service_dbus_activate_user_session (UsersServiceDbus * self, + AccountsUser * user) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return org_freedesktop_DisplayManager_Seat_switch_to_guest(priv->display_manager_proxy, "", NULL); + g_return_if_fail (IS_USERS_SERVICE_DBUS(self)); + + const char * const username = accounts_user_get_user_name (user); + DisplayManagerSeat * dp = create_display_proxy (self); + display_manager_seat_call_switch_to_user_sync (dp, username, "", NULL, NULL); + g_clear_object (&dp); } -/* Activates a specific user */ +/** + * users_service_dbus_guest_session_enabled: + * + * Tells whether or not guest sessions are allowed. + */ gboolean -users_service_dbus_activate_user_session (UsersServiceDbus *self, - UserData *user) +users_service_dbus_guest_session_enabled (UsersServiceDbus * self) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return org_freedesktop_DisplayManager_Seat_switch_to_user(priv->display_manager_proxy, user->user_name, "", NULL); + g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); + + DisplayManagerSeat * dp = create_display_proxy (self); + const gboolean enabled = display_manager_seat_get_has_guest_account (dp); + g_clear_object (&dp); + return enabled; } gboolean -users_service_dbus_can_activate_session (UsersServiceDbus *self) +users_service_dbus_can_activate_session (UsersServiceDbus * self) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); gboolean can_activate = FALSE; - GError *error = NULL; - if (!priv->seat_proxy) - { - create_seat_proxy (self); - } - - if (!priv->seat || priv->seat[0] == '\0') - { - return FALSE; - } + g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), can_activate); - if (!dbus_g_proxy_call (priv->seat_proxy, - "CanActivateSessions", - &error, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &can_activate, - G_TYPE_INVALID)) + GError * error = NULL; + console_kit_seat_call_can_activate_sessions_sync (self->priv->seat_proxy, + &can_activate, + NULL, + &error); + if (error != NULL) { - if (error != NULL){ - g_warning ("Failed to determine if seat can activate sessions: %s", - error->message); - g_error_free (error); - } - return FALSE; + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); } return can_activate; } -/* Sets the menu item that represents the guest account */ -void -users_service_dbus_set_guest_item (UsersServiceDbus * self, DbusmenuMenuitem * mi) +gboolean +users_service_dbus_is_guest_logged_in (UsersServiceDbus * self) { - g_return_if_fail(IS_USERS_SERVICE_DBUS(self)); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - priv->guest_item = mi; + g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), FALSE); - if (priv->guest_session_id != NULL) { - dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, TRUE); - } - - return; + return self->priv->guest_ssid != NULL; } -gboolean users_service_dbus_guest_session_enabled (UsersServiceDbus * self) +gboolean +users_service_dbus_is_user_logged_in (UsersServiceDbus * self, + AccountsUser * user) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - - return priv->guest_session_enabled; -} + g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), FALSE); + g_return_val_if_fail (IS_ACCOUNTS_USER(user), FALSE); + return user_count_sessions (user) > 0; +} |