[gdm] manager: close up timed login race



commit e24484f72bdf1d7c96131c6b7bae6409fabed210
Author: Ray Strode <rstrode redhat com>
Date:   Thu Jun 5 17:01:48 2014 -0400

    manager: close up timed login race
    
    Previously we would emit the timed-login-requested signal after the
    client connects, which might be before it was listening for the
    signal.
    
    Now we only emit the signal in direct response to a GetTimedLoginDetails
    call, which we make implicitly when the appropiate proxy interface is
    set up.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=680348

 daemon/gdm-manager.c   |   92 +-----------------------------------------------
 daemon/gdm-session.c   |   44 ++++++++++++++++++-----
 daemon/gdm-session.h   |    2 +-
 daemon/gdm-session.xml |    5 +++
 libgdm/gdm-client.c    |   24 ++++++++++++
 5 files changed, 66 insertions(+), 101 deletions(-)
---
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 9c3be71..dbcc8bc 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1573,51 +1573,6 @@ get_display_device (GdmManager *manager,
 }
 
 static void
-on_ready_to_request_timed_login (GdmSession         *session,
-                                 GSimpleAsyncResult *result,
-                                 gpointer           *user_data)
-{
-        g_debug ("GdmManager: ready to request timed login");
-        int delay = GPOINTER_TO_INT (user_data);
-        GCancellable *cancellable;
-        char         *username;
-
-        cancellable = g_object_get_data (G_OBJECT (result),
-                                         "cancellable");
-        if (g_cancellable_is_cancelled (cancellable)) {
-                return;
-        }
-
-        username = g_simple_async_result_get_source_tag (result);
-
-        gdm_session_request_timed_login (session, username, delay);
-
-        g_object_weak_unref (G_OBJECT (session),
-                             (GWeakNotify)
-                             g_cancellable_cancel,
-                             cancellable);
-        g_object_weak_unref (G_OBJECT (session),
-                             (GWeakNotify)
-                             g_object_unref,
-                             cancellable);
-        g_object_weak_unref (G_OBJECT (session),
-                             (GWeakNotify)
-                             g_free,
-                             username);
-
-        g_free (username);
-}
-
-static gboolean
-on_wait_for_greeter_timeout (GSimpleAsyncResult *result)
-{
-        g_debug ("GdmManager: wait for greeter timeout");
-        g_simple_async_result_complete (result);
-
-        return FALSE;
-}
-
-static void
 on_session_reauthenticated (GdmSession *session,
                             const char *service_name,
                             GdmManager *manager)
@@ -1685,53 +1640,8 @@ on_session_client_connected (GdmSession      *session,
                 return;
         }
 
-        /* temporary hack to fix timed login
-         * http://bugzilla.gnome.org/680348
-         */
         if (delay > 0) {
-                GSimpleAsyncResult *result;
-                GCancellable       *cancellable;
-                guint               timeout_id;
-                gpointer            source_tag;
-
-                delay = MAX (delay, 4);
-
-                cancellable = g_cancellable_new ();
-                source_tag = g_strdup (username);
-                result = g_simple_async_result_new (G_OBJECT (session),
-                                                    (GAsyncReadyCallback)
-                                                    on_ready_to_request_timed_login,
-                                                    GINT_TO_POINTER (delay),
-                                                    source_tag);
-                g_simple_async_result_set_check_cancellable (result, cancellable);
-                g_object_set_data (G_OBJECT (result),
-                                   "cancellable",
-                                   cancellable);
-
-                timeout_id = g_timeout_add_seconds_full (delay - 2,
-                                                         G_PRIORITY_DEFAULT,
-                                                         (GSourceFunc)
-                                                         on_wait_for_greeter_timeout,
-                                                         g_object_ref (result),
-                                                         (GDestroyNotify)
-                                                         g_object_unref);
-                g_cancellable_connect (cancellable,
-                                       G_CALLBACK (g_source_remove),
-                                       GINT_TO_POINTER (timeout_id),
-                                       NULL);
-
-                g_object_weak_ref (G_OBJECT (session),
-                                   (GWeakNotify)
-                                   g_cancellable_cancel,
-                                   cancellable);
-                g_object_weak_ref (G_OBJECT (session),
-                                   (GWeakNotify)
-                                   g_object_unref,
-                                   cancellable);
-                g_object_weak_ref (G_OBJECT (session),
-                                   (GWeakNotify)
-                                   g_free,
-                                   source_tag);
+                gdm_session_set_timed_login_details (session, username, delay);
         }
 
         g_free (username);
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 07eed5e..60667c5 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -88,6 +88,10 @@ struct _GdmSessionPrivate
         char                *selected_user;
         char                *user_x11_authority_file;
 
+        char                *timed_login_username;
+        int                  timed_login_delay;
+        GList               *pending_timed_login_invocations;
+
         GHashTable          *conversations;
 
         GdmSessionConversation *session_conversation;
@@ -1296,6 +1300,27 @@ gdm_session_handle_client_start_session_when_ready (GdmDBusGreeter        *greet
 }
 
 static gboolean
+gdm_session_handle_get_timed_login_details (GdmDBusGreeter        *greeter_interface,
+                                            GDBusMethodInvocation *invocation,
+                                            GdmSession            *self)
+{
+
+        if (self->priv->greeter_interface != NULL) {
+                gdm_dbus_greeter_complete_get_timed_login_details (greeter_interface,
+                                                                   invocation,
+                                                                   self->priv->timed_login_username != NULL,
+                                                                   self->priv->timed_login_username != NULL? 
self->priv->timed_login_username : "",
+                                                                   self->priv->timed_login_delay);
+                if (self->priv->timed_login_username != NULL) {
+                        gdm_dbus_greeter_emit_timed_login_requested (self->priv->greeter_interface,
+                                                                     self->priv->timed_login_username,
+                                                                     self->priv->timed_login_delay);
+                }
+        }
+        return TRUE;
+}
+
+static gboolean
 gdm_session_handle_client_begin_auto_login (GdmDBusGreeter        *greeter_interface,
                                             GDBusMethodInvocation *invocation,
                                             const char            *username,
@@ -1368,6 +1393,10 @@ export_greeter_interface (GdmSession      *self,
                           "handle-start-session-when-ready",
                           G_CALLBACK (gdm_session_handle_client_start_session_when_ready),
                           self);
+        g_signal_connect (greeter_interface,
+                          "handle-get-timed-login-details",
+                          G_CALLBACK (gdm_session_handle_get_timed_login_details),
+                          self);
 
         g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (greeter_interface),
                                           connection,
@@ -2609,16 +2638,13 @@ gdm_session_reset (GdmSession *self)
 }
 
 void
-gdm_session_request_timed_login (GdmSession *self,
-                                 const char *username,
-                                 int         delay)
+gdm_session_set_timed_login_details (GdmSession *self,
+                                     const char *username,
+                                     int         delay)
 {
-        g_debug ("GdmSession: requesting timed login");
-        if (self->priv->greeter_interface != NULL) {
-                gdm_dbus_greeter_emit_timed_login_requested (self->priv->greeter_interface,
-                                                             username,
-                                                             delay);
-        }
+        g_debug ("GdmSession: timed login details %s %d", username, delay);
+        self->priv->timed_login_username = g_strdup (username);
+        self->priv->timed_login_delay = delay;
 }
 
 gboolean
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index fe2eb53..8a2cb1b 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -177,7 +177,7 @@ void              gdm_session_select_session              (GdmSession *session,
                                                            const char *session_name);
 void              gdm_session_select_user                 (GdmSession *session,
                                                            const char *username);
-void              gdm_session_request_timed_login         (GdmSession *session,
+void              gdm_session_set_timed_login_details     (GdmSession *session,
                                                            const char *username,
                                                            int         delay);
 gboolean          gdm_session_client_is_connected         (GdmSession *session);
diff --git a/daemon/gdm-session.xml b/daemon/gdm-session.xml
index 97216c3..2a83087 100644
--- a/daemon/gdm-session.xml
+++ b/daemon/gdm-session.xml
@@ -85,6 +85,11 @@
     <method name="BeginAutoLogin">
       <arg name="username" direction="in" type="s"/>
     </method>
+    <method name="GetTimedLoginDetails">
+      <arg name="enabled" direction="out" type="b"/>
+      <arg name="username" direction="out" type="s"/>
+      <arg name="delay" direction="out" type="i"/>
+    </method>
     <method name="StartSessionWhenReady">
       <arg name="service_name" direction="in" type="s"/>
       <arg name="should_start_session" direction="in" type="b"/>
diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c
index 4542c3e..3cd298e 100644
--- a/libgdm/gdm-client.c
+++ b/libgdm/gdm-client.c
@@ -794,6 +794,26 @@ gdm_client_get_user_verifier_finish (GdmClient       *client,
 }
 
 static void
+on_timed_login_details_got (GdmGreeter   *greeter,
+                            GAsyncResult *result)
+{
+    gdm_greeter_call_get_timed_login_details_finish (greeter, NULL, NULL, NULL, result, NULL);
+}
+
+static void
+query_for_timed_login_requested_signal (GdmGreeter *greeter)
+{
+        /* This just makes sure a timed-login-requested signal gets fired
+         * off if appropriate.
+         */
+        gdm_greeter_call_get_timed_login_details (greeter,
+                                                  NULL,
+                                                  (GAsyncReadyCallback)
+                                                  on_timed_login_details_got,
+                                                  NULL);
+}
+
+static void
 on_greeter_proxy_created (GObject            *source,
                           GAsyncResult       *result,
                           GSimpleAsyncResult *operation_result)
@@ -813,6 +833,8 @@ on_greeter_proxy_created (GObject            *source,
                                                    (GDestroyNotify)
                                                    g_object_unref);
         g_simple_async_result_complete_in_idle (operation_result);
+
+        query_for_timed_login_requested_signal (greeter);
 }
 
 static void
@@ -980,6 +1002,8 @@ gdm_client_get_greeter_sync (GdmClient     *client,
                                    (GWeakNotify)
                                    g_clear_object,
                                    &client->priv->connection);
+
+                query_for_timed_login_requested_signal (client->priv->greeter);
         }
 
         return client->priv->greeter;


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