[gdm] slave: don't fail if user session already active when activating from unlock



commit 99c4f960c0689d310a799e87f6361fb25a8862f6
Author: Ray Strode <rstrode redhat com>
Date:   Thu Oct 11 17:29:07 2012 -0400

    slave: don't fail if user session already active when activating from unlock
    
    After GDM successfully reauthenticates a user it runs
    
    gdm_slave_switch_to_user_session
    
    to jump to the user's VT and unlock it.  Of course, if the user
    is reauthenticating from an unlock screen instead of a user
    switched login screen, then they'll already be on the right VT.
    
    gdm_slave_switch_to_user_session fails if the user is already
    switched to the session specified.  This failing behavior is used
    at login time to decide start a user's session (versus switching
    to a user's already running session).
    
    This commit changes gdm_slave_switch_to_user_session to take
    an additional parameter to decide whether or not switching to
    an already active session should fail, or merely skip to the
    unlocking step.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=685988

 daemon/gdm-simple-slave.c |   29 ++++++++++++----
 daemon/gdm-slave.c        |   81 +++++++++++++++++++++++++++++++++++++-------
 daemon/gdm-slave.h        |    3 +-
 3 files changed, 92 insertions(+), 21 deletions(-)
---
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 2e0b68b..9bc8522 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -311,17 +311,18 @@ gdm_simple_slave_start_session_when_ready (GdmSimpleSlave *slave,
 }
 
 static gboolean
-try_migrate_session (GdmSimpleSlave  *slave)
+switch_to_and_unlock_session (GdmSimpleSlave  *slave,
+                              gboolean         fail_if_already_switched)
 {
         char    *username;
         gboolean res;
 
-        g_debug ("GdmSimpleSlave: trying to migrate session");
-
         username = gdm_session_get_username (slave->priv->session);
 
+        g_debug ("GdmSimpleSlave: trying to switch to session for user %s", username);
+
         /* try to switch to an existing session */
-        res = gdm_slave_switch_to_user_session (GDM_SLAVE (slave), username);
+        res = gdm_slave_switch_to_user_session (GDM_SLAVE (slave), username, fail_if_already_switched);
         g_free (username);
 
         return res;
@@ -392,11 +393,18 @@ static gboolean
 start_session_timeout (GdmSimpleSlave  *slave)
 {
         gboolean migrated;
-
+        gboolean fail_if_already_switched = TRUE;
 
         g_debug ("GdmSimpleSlave: accredited");
 
-        migrated = try_migrate_session (slave);
+        /* If there's already a session running, jump to it.
+         * If the only session running is the one we just opened,
+         * start a session on it.
+         *
+         * We assume we're in the former case if we need to switch
+         * VTs, and we assume we're in the latter case if we don't.
+         */
+        migrated = switch_to_and_unlock_session (slave, fail_if_already_switched);
         g_debug ("GdmSimpleSlave: migrated: %d", migrated);
         if (migrated) {
                 /* We don't stop the slave here because
@@ -438,7 +446,14 @@ on_session_reauthenticated (GdmSession       *session,
                             const char       *service_name,
                             GdmSimpleSlave   *slave)
 {
-        try_migrate_session (slave);
+        gboolean fail_if_already_switched = FALSE;
+
+        /* There should already be a session running, so jump to it's
+         * VT. In the event we're already on the right VT, (i.e. user
+         * used an unlock screen instead of a user switched login screen),
+         * then silently succeed and unlock the session.
+         */
+        switch_to_and_unlock_session (slave, fail_if_already_switched);
 }
 
 static void
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index f011207..287c7d6 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -1474,15 +1474,6 @@ activate_session_id_for_systemd (GdmSlave   *slave,
         GError *error = NULL;
         GVariant *reply;
 
-        /* Can't activate what's already active. We want this
-         * to fail, because we don't want migration to succeed
-         * if the only active session is the one just created
-         * at the login screen.
-         */
-        if (sd_session_is_active (session_id) > 0) {
-                return FALSE;
-        }
-
         reply = g_dbus_connection_call_sync (slave->priv->connection,
                                              "org.freedesktop.login1",
                                              "/org/freedesktop/login1",
@@ -1559,6 +1550,59 @@ activate_session_id (GdmSlave   *slave,
 #endif
 }
 
+#ifdef WITH_CONSOLE_KIT
+static gboolean
+ck_session_is_active (GdmSlave   *slave,
+                      const char *seat_id,
+                      const char *session_id)
+{
+        GError *error = NULL;
+        GVariant *reply;
+        gboolean is_active;
+
+        reply = g_dbus_connection_call_sync (slave->priv->connection,
+                                             CK_NAME,
+                                             session_id,
+                                             "org.freedesktop.ConsoleKit.Session",
+                                             "IsActive",
+                                             NULL,
+                                             G_VARIANT_TYPE ("(b)"),
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL,
+                                             &error);
+        if (reply == NULL) {
+                g_debug ("GdmSlave: ConsoleKit IsActive %s raised:\n %s\n\n",
+                         g_dbus_error_get_remote_error (error), error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        g_variant_get (reply, "(b)", &is_active);
+        g_variant_unref (reply);
+
+        return is_active;
+}
+#endif
+
+static gboolean
+session_is_active (GdmSlave   *slave,
+                   const char *seat_id,
+                   const char *session_id)
+{
+#ifdef WITH_SYSTEMD
+        if (sd_booted () > 0) {
+                return sd_session_is_active (session_id) > 0;
+        }
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+        return ck_session_is_active (slave, seat_id, session_id);
+#else
+        return FALSE;
+#endif
+}
+
 #ifdef WITH_SYSTEMD
 static gboolean
 session_unlock_for_systemd (GdmSlave   *slave,
@@ -1645,10 +1689,12 @@ session_unlock (GdmSlave   *slave,
 
 gboolean
 gdm_slave_switch_to_user_session (GdmSlave   *slave,
-                                  const char *username)
+                                  const char *username,
+                                  gboolean    fail_if_already_switched)
 {
         gboolean    res;
         gboolean    ret;
+        gboolean    session_already_switched;
         char       *ssid_to_activate;
 
         ret = FALSE;
@@ -1659,14 +1705,23 @@ gdm_slave_switch_to_user_session (GdmSlave   *slave,
                 goto out;
         }
 
+        session_already_switched = session_is_active (slave, slave->priv->display_seat_id, ssid_to_activate);
+
         g_debug ("GdmSlave: Activating session: '%s'", ssid_to_activate);
 
-        res = activate_session_id (slave, slave->priv->display_seat_id, ssid_to_activate);
-        if (! res) {
-                g_debug ("GdmSlave: unable to activate session: %s", ssid_to_activate);
+        if (session_already_switched && fail_if_already_switched) {
+                g_debug ("GdmSlave: unable to activate session since it's already active: %s", ssid_to_activate);
                 goto out;
         }
 
+        if (!session_already_switched) {
+                res = activate_session_id (slave, slave->priv->display_seat_id, ssid_to_activate);
+                if (! res) {
+                        g_debug ("GdmSlave: unable to activate session: %s", ssid_to_activate);
+                        goto out;
+                }
+        }
+
         res = session_unlock (slave, ssid_to_activate);
         if (!res) {
                 /* this isn't fatal */
diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h
index 98e25f5..0647618 100644
--- a/daemon/gdm-slave.h
+++ b/daemon/gdm-slave.h
@@ -99,7 +99,8 @@ gboolean            gdm_slave_add_user_authorization (GdmSlave   *slave,
                                                       char      **filename);
 
 gboolean            gdm_slave_switch_to_user_session (GdmSlave   *slave,
-                                                      const char *username);
+                                                      const char *username,
+                                                      gboolean    fail_if_already_switched);
 
 gboolean            gdm_slave_connect_to_x11_display (GdmSlave   *slave);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]