rudimentary monitoring of seats and sessions
authorDavid Zeuthen <davidz@redhat.com>
Tue, 13 Jan 2009 23:37:59 +0000 (18:37 -0500)
committerDavid Zeuthen <davidz@redhat.com>
Tue, 13 Jan 2009 23:37:59 +0000 (18:37 -0500)
Will add public API a'la

 gboolean polkit_session_monitor_is_subject_active ();

as needed.

src/polkitbackend/polkitbackendlocalauthority.c
src/polkitbackend/polkitbackendsessionmonitor.c

index cbc5b4a..ea292c2 100644 (file)
 #include "polkitbackendlocalauthority.h"
 #include "polkitbackendactionpool.h"
 #include "polkitbackendpendingcall.h"
+#include "polkitbackendsessionmonitor.h"
 
 typedef struct
 {
   PolkitBackendActionPool *action_pool;
 
+  PolkitBackendSessionMonitor *session_monitor;
+
 } PolkitBackendLocalAuthorityPrivate;
 
 static void polkit_backend_local_authority_enumerate_actions (PolkitBackendAuthority   *authority,
@@ -64,6 +67,8 @@ polkit_backend_local_authority_init (PolkitBackendLocalAuthority *local_authorit
   action_desc_directory = g_file_new_for_path (PACKAGE_DATA_DIR "/polkit-1/actions");
   priv->action_pool = polkit_backend_action_pool_new (action_desc_directory);
   g_object_unref (action_desc_directory);
+
+  priv->session_monitor = polkit_backend_session_monitor_new ();
 }
 
 static void
@@ -78,6 +83,9 @@ polkit_backend_local_authority_finalize (GObject *object)
   if (priv->action_pool != NULL)
     g_object_unref (priv->action_pool);
 
+  if (priv->session_monitor != NULL)
+    g_object_unref (priv->session_monitor);
+
   G_OBJECT_CLASS (polkit_backend_local_authority_parent_class)->finalize (object);
 }
 
index ac370f7..ae97423 100644 (file)
@@ -32,8 +32,13 @@ struct _PolkitBackendSessionMonitor
 {
   GObject parent_instance;
 
+  EggDBusConnection *system_bus;
+
   EggDBusObjectProxy *ck_manager_object_proxy;
+
   CkManager *ck_manager;
+  EggDBusHashMap *seat_object_path_to_object_proxy;
+  EggDBusHashMap *session_object_path_to_object_proxy;
 };
 
 struct _PolkitBackendSessionMonitorClass
@@ -42,22 +47,236 @@ struct _PolkitBackendSessionMonitorClass
 
 };
 
+static void seat_session_added (CkSeat      *seat,
+                                const gchar *object_path,
+                                gpointer     user_data);
+
+static void seat_session_removed (CkSeat      *seat,
+                                  const gchar *object_path,
+                                  gpointer     user_data);
+
+static void session_active_changed (CkSession   *session,
+                                    gboolean     is_active,
+                                    gpointer     user_data);
+
 G_DEFINE_TYPE (PolkitBackendSessionMonitor, polkit_backend_session_monitor, G_TYPE_OBJECT);
 
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+add_seat (PolkitBackendSessionMonitor *monitor,
+          const gchar                 *object_path)
+{
+  CkSeat *seat;
+  EggDBusObjectProxy *object_proxy;
+
+  object_proxy = egg_dbus_connection_get_object_proxy (monitor->system_bus,
+                                                       "org.freedesktop.ConsoleKit",
+                                                       object_path);
+
+  egg_dbus_hash_map_insert (monitor->seat_object_path_to_object_proxy,
+                            g_strdup (object_path),
+                            object_proxy);
+
+  seat = CK_QUERY_INTERFACE_SEAT (object_proxy);
+
+  g_signal_connect (seat,
+                    "session-added",
+                    G_CALLBACK (seat_session_added),
+                    monitor);
+
+  g_signal_connect (seat,
+                    "session-removed",
+                    G_CALLBACK (seat_session_removed),
+                    monitor);
+}
+
+static void
+add_session (PolkitBackendSessionMonitor *monitor,
+             const gchar                 *object_path)
+{
+  CkSession *session;
+  EggDBusObjectProxy *object_proxy;
+
+  g_debug ("foo %s", object_path);
+
+  object_proxy = egg_dbus_connection_get_object_proxy (monitor->system_bus,
+                                                       "org.freedesktop.ConsoleKit",
+                                                       object_path);
+
+  egg_dbus_hash_map_insert (monitor->session_object_path_to_object_proxy,
+                            g_strdup (object_path),
+                            object_proxy);
+
+  session = CK_QUERY_INTERFACE_SESSION (object_proxy);
+
+  g_signal_connect (session,
+                    "active-changed",
+                    G_CALLBACK (session_active_changed),
+                    monitor);
+}
+
+static void
+remove_seat (PolkitBackendSessionMonitor *monitor,
+             const gchar                 *object_path)
+{
+  egg_dbus_hash_map_remove (monitor->seat_object_path_to_object_proxy,
+                            object_path);
+}
+
+static void
+remove_session (PolkitBackendSessionMonitor *monitor,
+                const gchar                 *object_path)
+{
+  egg_dbus_hash_map_remove (monitor->session_object_path_to_object_proxy,
+                            object_path);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* D-Bus signal handlers */
+
+static void
+manager_seat_added (CkManager   *manager,
+                    const gchar *object_path,
+                    gpointer     user_data)
+{
+  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
+
+  g_debug ("seat %s added", object_path);
+
+  add_seat (monitor, object_path);
+}
+
+static void
+manager_seat_removed (CkManager   *manager,
+                      const gchar *object_path,
+                      gpointer     user_data)
+{
+  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
+
+  g_debug ("seat %s removed", object_path);
+
+  remove_seat (monitor, object_path);
+}
+
+static void
+seat_session_added (CkSeat      *seat,
+                    const gchar *object_path,
+                    gpointer     user_data)
+{
+  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
+
+  g_debug ("session %s added", object_path);
+
+  add_session (monitor, object_path);
+}
+
+static void
+seat_session_removed (CkSeat      *seat,
+                      const gchar *object_path,
+                      gpointer     user_data)
+{
+  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
+
+  g_debug ("session %s removed", object_path);
+
+  remove_session (monitor, object_path);
+}
+
+static void
+session_active_changed (CkSession   *session,
+                        gboolean     is_active,
+                        gpointer     user_data)
+{
+  EggDBusObjectProxy *object_proxy;
+
+  object_proxy = egg_dbus_interface_proxy_get_object_proxy (EGG_DBUS_INTERFACE_PROXY (session));
+
+  g_debug ("session %s active changed to %d",
+           egg_dbus_object_proxy_get_object_path (object_proxy),
+           is_active);
+
+  egg_dbus_object_proxy_invalidate_properties (object_proxy);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 static void
 polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor)
 {
-  EggDBusConnection *system_bus;
+  GError *error;
+  gchar **seats_object_paths;
+  gchar **sessions_object_paths;
+  guint n;
+
+  error = NULL;
+  seats_object_paths = NULL;
+  sessions_object_paths = NULL;
 
-  system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM);
+  monitor->seat_object_path_to_object_proxy = egg_dbus_hash_map_new (G_TYPE_STRING,
+                                                                     g_free,
+                                                                     EGG_DBUS_TYPE_OBJECT_PROXY,
+                                                                     g_object_unref);
 
-  monitor->ck_manager_object_proxy = egg_dbus_connection_get_object_proxy (system_bus,
+  monitor->session_object_path_to_object_proxy = egg_dbus_hash_map_new (G_TYPE_STRING,
+                                                                        g_free,
+                                                                        EGG_DBUS_TYPE_OBJECT_PROXY,
+                                                                        g_object_unref);
+
+  monitor->system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM);
+
+  monitor->ck_manager_object_proxy = egg_dbus_connection_get_object_proxy (monitor->system_bus,
                                                                            "org.freedesktop.ConsoleKit",
                                                                            "/org/freedesktop/ConsoleKit/Manager");
 
   monitor->ck_manager = CK_QUERY_INTERFACE_MANAGER (monitor->ck_manager_object_proxy);
 
-  g_object_unref (system_bus);
+  g_signal_connect (monitor->ck_manager,
+                    "seat-added",
+                    G_CALLBACK (manager_seat_added),
+                    monitor);
+
+  g_signal_connect (monitor->ck_manager,
+                    "seat-removed",
+                    G_CALLBACK (manager_seat_removed),
+                    monitor);
+
+  /* TODO: it would be a lot nicer to do all of this async; once we have
+   *       GFiber (bgo #565501) it will be a lot easier...
+   */
+  if (!ck_manager_get_seats_sync (monitor->ck_manager,
+                                  EGG_DBUS_CALL_FLAGS_NONE,
+                                  &seats_object_paths,
+                                  NULL,
+                                  &error))
+    {
+      g_warning ("Error getting seats: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  for (n = 0; seats_object_paths[n] != NULL; n++)
+    add_seat (monitor, seats_object_paths[n]);
+
+  if (!ck_manager_get_sessions_sync (monitor->ck_manager,
+                                     EGG_DBUS_CALL_FLAGS_NONE,
+                                     &sessions_object_paths,
+                                     NULL,
+                                     &error))
+    {
+      g_warning ("Error getting sessions: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  for (n = 0; sessions_object_paths[n] != NULL; n++)
+    add_session (monitor, sessions_object_paths[n]);
+
+ out:
+
+  g_strfreev (seats_object_paths);
+  g_strfreev (sessions_object_paths);
 }
 
 static void
@@ -65,7 +284,10 @@ polkit_backend_session_monitor_finalize (GObject *object)
 {
   PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (object);
 
+  g_object_unref (monitor->seat_object_path_to_object_proxy);
+  g_object_unref (monitor->session_object_path_to_object_proxy);
   g_object_unref (monitor->ck_manager_object_proxy);
+  g_object_unref (monitor->system_bus);
 
   if (G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize != NULL)
     G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize (object);