summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Toso <victortoso@redhat.com>2016-04-12 10:31:30 +0200
committerVictor Toso <victortoso@redhat.com>2016-05-04 09:23:28 +0200
commit1700c0244f37dc67a48519765543ddd7c3f4c17b (patch)
treeb4eb57d87cb499b3a81fbe3905052b7880dc7350
parent364b6bba068bd694d7c4355b6275f88482d9f3f8 (diff)
console-kit: implement check for locked session
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. Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
-rw-r--r--src/console-kit.c88
1 files changed, 85 insertions, 3 deletions
diff --git a/src/console-kit.c b/src/console-kit.c
index a50f812..3dd40d9 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_CONSOLE_KIT_SEAT INTERFACE_CONSOLE_KIT ".Seat"
+#define INTERFACE_CONSOLE_KIT_SESSION INTERFACE_CONSOLE_KIT ".Session"
+#define OBJ_PATH_CONSOLE_KIT_SESSION OBJ_PATH_CONSOLE_KIT "/Session"
+
#define SEAT_SIGNAL_ACTIVE_SESSION_CHANGED "ActiveSessionChanged"
+#define SESSION_SIGNAL_LOCK "Lock"
+#define SESSION_SIGNAL_UNLOCK "Unlock"
+#define SESSION_SIGNAL_IDLE_HINT_CHANGED "IdleHintChanged"
+
static char *console_kit_get_first_seat(struct session_info *info);
static char *console_kit_check_active_session_change(struct session_info *info);
@@ -64,6 +74,19 @@ static void si_dbus_match_remove(struct session_info *info)
g_free(info->match_seat_signals);
info->match_seat_signals = NULL;
}
+
+ if (info->match_session_signals != NULL) {
+ dbus_error_init(&error);
+ dbus_bus_remove_match(info->connection,
+ info->match_session_signals,
+ &error);
+
+ if (info->verbose)
+ syslog(LOG_DEBUG, "(console-kit) session match removed: %s",
+ info->match_session_signals);
+ g_free(info->match_session_signals);
+ info->match_session_signals = NULL;
+ }
}
static void si_dbus_match_rule_update(struct session_info *info)
@@ -98,6 +121,29 @@ static void si_dbus_match_rule_update(struct session_info *info)
info->match_seat_signals = NULL;
}
}
+
+ /* Session signals */
+ if (info->active_session != NULL) {
+ info->match_session_signals =
+ g_strdup_printf ("type='signal',interface='%s',path='%s'",
+ INTERFACE_CONSOLE_KIT_SESSION,
+ info->active_session);
+ if (info->verbose)
+ syslog(LOG_DEBUG, "(console-kit) session match: %s",
+ info->match_session_signals);
+
+ dbus_error_init(&error);
+ dbus_bus_add_match(info->connection,
+ info->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(info->match_session_signals);
+ info->match_session_signals = NULL;
+ }
+ }
}
static void
@@ -128,6 +174,7 @@ si_dbus_read_signals(struct session_info *info)
dbus_message_iter_get_basic(&iter, &session);
if (session != NULL && session[0] != '\0') {
info->active_session = g_strdup(session);
+ si_dbus_match_rule_update(info);
} else {
syslog(LOG_WARNING, "(console-kit) received invalid session. "
"No active-session at the moment");
@@ -137,6 +184,25 @@ si_dbus_read_signals(struct session_info *info)
"ActiveSessionChanged message has unexpected type: '%c'",
type);
}
+ } else if (g_strcmp0(member, SESSION_SIGNAL_LOCK) == 0) {
+ info->session_is_locked = TRUE;
+ } else if (g_strcmp0(member, SESSION_SIGNAL_UNLOCK) == 0) {
+ info->session_is_locked = FALSE;
+ } else if (g_strcmp0(member, 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);
+ info->session_idle_hint = (idle_hint);
+ } else {
+ syslog(LOG_ERR,
+ "(console-kit) IdleHintChanged has unexpected type: '%c'",
+ type);
+ }
} else {
if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) {
syslog(LOG_WARNING, "(console-kit) received non signal message");
@@ -161,6 +227,8 @@ struct session_info *session_info_create(int verbose)
return NULL;
info->verbose = verbose;
+ info->session_is_locked = FALSE;
+ info->session_idle_hint = FALSE;
dbus_error_init(&error);
info->connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
@@ -323,6 +391,7 @@ const char *session_info_get_active_session(struct session_info *info)
}
info->active_session = strdup(session);
+ si_dbus_match_rule_update(info);
exit:
if (reply != NULL) {
@@ -418,7 +487,20 @@ static char *console_kit_check_active_session_change(struct session_info *info)
gboolean session_info_session_is_locked(struct session_info *info)
{
- /* TODO: It could be implemented based on Lock/Unlock signals from Session
- * interface. */
- return FALSE;
+ gboolean locked;
+
+ g_return_val_if_fail (info != NULL, 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(info);
+ locked = (info->session_is_locked || info->session_idle_hint);
+ if (info->verbose) {
+ syslog(LOG_DEBUG, "(console-kit) session is locked: %s",
+ locked ? "yes" : "no");
+ }
+ return locked;
}