[Spice-devel] [vdagent-linux v2 3/5] console-kit: implement check for locked session

Victor Toso victortoso at redhat.com
Sat Apr 23 10:53:15 UTC 2016


We register to read the Lock, Unlock and IdleHintChanged signals from
ConsoleKit.Session. The Lock/Unlock signals should be the right signals for the
job but not all Desktop Managers implement its locking in a way that trigger
those signals. That's why we double-check with IdleHintChanged signal that it
might be triggered by other services like screen savers.
---
 src/console-kit.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 4 deletions(-)

diff --git a/src/console-kit.c b/src/console-kit.c
index 9662d3d..748a6bc 100644
--- a/src/console-kit.c
+++ b/src/console-kit.c
@@ -35,6 +35,9 @@ struct session_info {
     char *active_session;
     int verbose;
     gchar *match_seat_signals;
+    gchar *match_session_signals;
+    gboolean session_is_locked;
+    gboolean session_idle_hint;
 };
 
 #define INTERFACE_CONSOLE_KIT "org.freedesktop.ConsoleKit"
@@ -45,8 +48,15 @@ struct session_info {
 
 #define INTERFACE_CK_SEAT       INTERFACE_CONSOLE_KIT ".Seat"
 
+#define INTERFACE_CK_SESSION    INTERFACE_CONSOLE_KIT ".Session"
+#define OBJ_PATH_CK_SESSION     OBJ_PATH_CONSOLE_KIT "/Session"
+
 #define CK_SEAT_SIGNAL_ACTIVE_SESSION_CHANGED       "ActiveSessionChanged"
 
+#define CK_SESSION_SIGNAL_LOCK                      "Lock"
+#define CK_SESSION_SIGNAL_UNLOCK                    "Unlock"
+#define CK_SESSION_SIGNAL_IDLE_HINT_CHANGED         "IdleHintChanged"
+
 static char *console_kit_get_first_seat(struct session_info *si);
 static char *console_kit_check_active_session_change(struct session_info *si);
 
@@ -63,6 +73,18 @@ static void si_dbus_match_remove(struct session_info *si)
                    si->match_seat_signals);
         g_free(si->match_seat_signals);
     }
+
+    if (si->match_session_signals != NULL) {
+        dbus_error_init(&error);
+        dbus_bus_remove_match(si->connection,
+                              si->match_session_signals,
+                              &error);
+
+        if (si->verbose)
+            syslog(LOG_DEBUG, "(console-kit) session match removed: %s",
+                   si->match_session_signals);
+        g_free(si->match_session_signals);
+    }
 }
 
 static void si_dbus_match_rule_update(struct session_info *si)
@@ -96,6 +118,28 @@ static void si_dbus_match_rule_update(struct session_info *si)
             g_free(si->match_seat_signals);
         }
     }
+
+    /* Session signals */
+    if (si->active_session != NULL) {
+        si->match_session_signals =
+            g_strdup_printf ("type='signal',interface='%s',path='%s'",
+                             INTERFACE_CK_SESSION,
+                             si->active_session);
+        if (si->verbose)
+            syslog(LOG_DEBUG, "(console-kit) session match: %s",
+                   si->match_session_signals);
+
+        dbus_error_init(&error);
+        dbus_bus_add_match(si->connection,
+                           si->match_session_signals,
+                           &error);
+        if (dbus_error_is_set(&error)) {
+            syslog(LOG_WARNING, "Unable to add dbus rule match: %s",
+                   error.message);
+            dbus_error_free(&error);
+            g_free(si->match_session_signals);
+        }
+    }
 }
 
 static void
@@ -129,6 +173,7 @@ si_dbus_read_signals(struct session_info *si)
                 dbus_message_iter_get_basic(&iter, &session);
                 if (session != NULL && session[0] != '\0') {
                     si->active_session = g_strdup(session);
+                    si_dbus_match_rule_update(si);
                 } else if (si->verbose) {
                     syslog(LOG_WARNING, "(console-kit) received invalid session. "
                            "No active-session at the moment");
@@ -141,6 +186,25 @@ si_dbus_read_signals(struct session_info *si)
                        "ActiveSessionChanged message has unexpected type: '%c'",
                        type);
             }
+        } else if (g_strcmp0(member, CK_SESSION_SIGNAL_LOCK) == 0) {
+            si->session_is_locked = TRUE;
+        } else if (g_strcmp0(member, CK_SESSION_SIGNAL_UNLOCK) == 0) {
+            si->session_is_locked = FALSE;
+        } else if (g_strcmp0(member, CK_SESSION_SIGNAL_IDLE_HINT_CHANGED) == 0) {
+            DBusMessageIter iter;
+            gint type;
+            dbus_bool_t idle_hint;
+
+            dbus_message_iter_init(message, &iter);
+            type = dbus_message_iter_get_arg_type(&iter);
+            if (type == DBUS_TYPE_BOOLEAN) {
+                dbus_message_iter_get_basic(&iter, &idle_hint);
+                si->session_idle_hint = (idle_hint);
+            } else {
+                syslog(LOG_ERR,
+                       "(console-kit) IdleHintChanged has unexpected type: '%c'",
+                       type);
+            }
         } else if (si->verbose) {
             syslog(LOG_DEBUG, "(console-kit) Signal not handled: %s", member);
         }
@@ -161,6 +225,8 @@ struct session_info *session_info_create(int verbose)
         return NULL;
 
     si->verbose = verbose;
+    si->session_is_locked = FALSE;
+    si->session_idle_hint = FALSE;
 
     dbus_error_init(&error);
     si->connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
@@ -324,6 +390,7 @@ const char *session_info_get_active_session(struct session_info *si)
     }
 
     si->active_session = strdup(session);
+    si_dbus_match_rule_update(si);
 
 exit:
     if (reply != NULL) {
@@ -413,13 +480,23 @@ static char *console_kit_check_active_session_change(struct session_info *si)
     if (si->verbose)
         syslog(LOG_DEBUG, "(console-kit) active-session: '%s'",
                (si->active_session ? si->active_session : "None"));
-
     return si->active_session;
 }
 
 gboolean session_info_session_is_locked(struct session_info *si)
 {
-    /* TODO: It could be implemented based on Lock/Unlock signals from Session
-     * interface. */
-    return FALSE;
+    if (si == NULL)
+        return FALSE;
+
+    /* Not every system does emit Lock and Unlock signals (for instance, such
+     * is the case for RHEL6) but most of the systems seems to emit the
+     * IdleHintChanged. So, we give priority to the Lock signal, if it is Locked
+     * we return that the session is locked, otherwise we double check with the
+     * IdleHint value */
+    si_dbus_read_signals(si);
+    if (si->verbose) {
+        syslog(LOG_DEBUG, "(console-kit) session is locked: %s",
+               (si->session_is_locked || si->session_idle_hint) ? "yes" : "no");
+    }
+    return (si->session_is_locked || si->session_idle_hint);
 }
-- 
2.5.5



More information about the Spice-devel mailing list