[PolicyKit-gnome] Support multiple outstanding authentication requests



commit f32cb7faa7197b9db55b569677732742c3c7fdc1
Author: David Zeuthen <davidz redhat com>
Date:   Tue Nov 10 09:30:05 2009 -0500

    Support multiple outstanding authentication requests
    
    Simply queue up authentication requests and process them one by
    one. We could have done this in parallel but that's probably not a
    very good user experience.
    
    This feature was requested here
    
     https://bugzilla.redhat.com/show_bug.cgi?id=526053
    
    and while it's a sign of bad design to be in a situation where
    multiple outstanding requests are pending, this is not the right place
    to fix it.
    
    One example of this feature is that you can now run 'pkexec bash' from
    two different terminals and you get two authentication requests right
    after each other.

 src/polkitgnomeauthenticator.c |    8 ++++-
 src/polkitgnomelistener.c      |   67 ++++++++++++++++++++++++----------------
 2 files changed, 47 insertions(+), 28 deletions(-)
---
diff --git a/src/polkitgnomeauthenticator.c b/src/polkitgnomeauthenticator.c
index 8fd15cd..019388c 100644
--- a/src/polkitgnomeauthenticator.c
+++ b/src/polkitgnomeauthenticator.c
@@ -485,7 +485,13 @@ polkit_gnome_authenticator_cancel (PolkitGnomeAuthenticator *authenticator)
   authenticator->was_cancelled = TRUE;
 
   if (authenticator->session != NULL)
-    polkit_agent_session_cancel (authenticator->session);
+    {
+      polkit_agent_session_cancel (authenticator->session);
+    }
+  else
+    {
+      g_signal_emit_by_name (authenticator, "completed", FALSE);
+    }
 }
 
 const gchar *
diff --git a/src/polkitgnomelistener.c b/src/polkitgnomelistener.c
index c85b63e..f09bef9 100644
--- a/src/polkitgnomelistener.c
+++ b/src/polkitgnomelistener.c
@@ -31,8 +31,10 @@ struct _PolkitGnomeListener
 {
   PolkitAgentListener parent_instance;
 
-  /* we only support a single active authenticator right now */
-  PolkitGnomeAuthenticator *the_authenticator;
+  /* we support multiple authenticators - they are simply queued up */
+  GList *authenticators;
+
+  PolkitGnomeAuthenticator *active_authenticator;
 };
 
 struct _PolkitGnomeListenerClass
@@ -97,6 +99,8 @@ polkit_gnome_listener_new (void)
 typedef struct
 {
   PolkitGnomeListener *listener;
+  PolkitGnomeAuthenticator *authenticator;
+
   GSimpleAsyncResult *simple;
   GCancellable *cancellable;
 
@@ -105,6 +109,7 @@ typedef struct
 
 static AuthData *
 auth_data_new (PolkitGnomeListener *listener,
+               PolkitGnomeAuthenticator *authenticator,
                GSimpleAsyncResult *simple,
                GCancellable *cancellable)
 {
@@ -112,6 +117,7 @@ auth_data_new (PolkitGnomeListener *listener,
 
   data = g_new0 (AuthData, 1);
   data->listener = g_object_ref (listener);
+  data->authenticator = g_object_ref (authenticator);
   data->simple = g_object_ref (simple);
   data->cancellable = g_object_ref (cancellable);
   return data;
@@ -121,6 +127,7 @@ static void
 auth_data_free (AuthData *data)
 {
   g_object_unref (data->listener);
+  g_object_unref (data->authenticator);
   g_object_unref (data->simple);
   if (data->cancellable != NULL && data->cancel_id > 0)
     g_signal_handler_disconnect (data->cancellable, data->cancel_id);
@@ -129,20 +136,33 @@ auth_data_free (AuthData *data)
 }
 
 static void
+maybe_initiate_next_authenticator (PolkitGnomeListener *listener)
+{
+  if (listener->active_authenticator == NULL && listener->authenticators != NULL)
+    {
+      polkit_gnome_authenticator_initiate (POLKIT_GNOME_AUTHENTICATOR (listener->authenticators->data));
+      listener->active_authenticator = listener->authenticators->data;
+    }
+}
+
+static void
 authenticator_completed (PolkitGnomeAuthenticator *authenticator,
                          gboolean                  gained_authorization,
                          gpointer                  user_data)
 {
   AuthData *data = user_data;
 
-  g_warn_if_fail (authenticator == data->listener->the_authenticator);
+  data->listener->authenticators = g_list_remove (data->listener->authenticators, authenticator);
+  if (authenticator == data->listener->active_authenticator)
+    data->listener->active_authenticator = NULL;
 
-  g_object_unref (data->listener->the_authenticator);
-  data->listener->the_authenticator = NULL;
+  g_object_unref (authenticator);
 
   g_simple_async_result_complete (data->simple);
   g_object_unref (data->simple);
 
+  maybe_initiate_next_authenticator (data->listener);
+
   auth_data_free (data);
 }
 
@@ -152,7 +172,7 @@ cancelled_cb (GCancellable *cancellable,
 {
   AuthData *data = user_data;
 
-  polkit_gnome_authenticator_cancel (data->listener->the_authenticator);
+  polkit_gnome_authenticator_cancel (data->authenticator);
 }
 
 static void
@@ -169,6 +189,7 @@ polkit_gnome_listener_initiate_authentication (PolkitAgentListener  *agent_liste
 {
   PolkitGnomeListener *listener = POLKIT_GNOME_LISTENER (agent_listener);
   GSimpleAsyncResult *simple;
+  PolkitGnomeAuthenticator *authenticator;
   AuthData *data;
 
   simple = g_simple_async_result_new (G_OBJECT (listener),
@@ -176,35 +197,25 @@ polkit_gnome_listener_initiate_authentication (PolkitAgentListener  *agent_liste
                                       user_data,
                                       polkit_gnome_listener_initiate_authentication);
 
-  if (listener->the_authenticator != NULL)
+  authenticator = polkit_gnome_authenticator_new (action_id,
+                                                  message,
+                                                  icon_name,
+                                                  details,
+                                                  cookie,
+                                                  identities);
+  if (authenticator == NULL)
     {
       g_simple_async_result_set_error (simple,
                                        POLKIT_ERROR,
                                        POLKIT_ERROR_FAILED,
-                                       "Authentication is already in progress for another action");
+                                       "Error creating authentication object");
       g_simple_async_result_complete (simple);
       goto out;
     }
 
-  listener->the_authenticator = polkit_gnome_authenticator_new (action_id,
-                                                                message,
-                                                                icon_name,
-                                                                details,
-                                                                cookie,
-                                                                identities);
-  if (listener->the_authenticator == NULL)
-    {
-      g_simple_async_result_set_error (simple,
-                                       POLKIT_ERROR,
-                                       POLKIT_ERROR_FAILED,
-                                       "Authentication is already in progress for another action");
-      g_simple_async_result_complete (simple);
-      goto out;
-    }
+  data = auth_data_new (listener, authenticator, simple, cancellable);
 
-  data = auth_data_new (listener, simple, cancellable);
-
-  g_signal_connect (listener->the_authenticator,
+  g_signal_connect (authenticator,
                     "completed",
                     G_CALLBACK (authenticator_completed),
                     data);
@@ -217,7 +228,9 @@ polkit_gnome_listener_initiate_authentication (PolkitAgentListener  *agent_liste
                                           data);
     }
 
-  polkit_gnome_authenticator_initiate (listener->the_authenticator);
+  listener->authenticators = g_list_append (listener->authenticators, authenticator);
+
+  maybe_initiate_next_authenticator (listener);
 
  out:
   ;



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