aboutsummaryrefslogtreecommitdiff
path: root/src/users-service-dbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/users-service-dbus.c')
-rw-r--r--src/users-service-dbus.c1481
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;
+}