diff options
Diffstat (limited to 'src/polkitmatelistener.c')
-rw-r--r-- | src/polkitmatelistener.c | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/src/polkitmatelistener.c b/src/polkitmatelistener.c new file mode 100644 index 0000000..d70836f --- /dev/null +++ b/src/polkitmatelistener.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Author: David Zeuthen <[email protected]> + */ + + +#include "config.h" + +#include <string.h> + +#include "polkitmatelistener.h" +#include "polkitmateauthenticator.h" + +struct _PolkitMateListener +{ + PolkitAgentListener parent_instance; + + /* we support multiple authenticators - they are simply queued up */ + GList *authenticators; + + PolkitMateAuthenticator *active_authenticator; +}; + +struct _PolkitMateListenerClass +{ + PolkitAgentListenerClass parent_class; +}; + +static void polkit_mate_listener_initiate_authentication (PolkitAgentListener *listener, + const gchar *action_id, + const gchar *message, + const gchar *icon_name, + PolkitDetails *details, + const gchar *cookie, + GList *identities, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +static gboolean polkit_mate_listener_initiate_authentication_finish (PolkitAgentListener *listener, + GAsyncResult *res, + GError **error); + +G_DEFINE_TYPE (PolkitMateListener, polkit_mate_listener, POLKIT_AGENT_TYPE_LISTENER); + +static void +polkit_mate_listener_init (PolkitMateListener *listener) +{ +} + +static void +polkit_mate_listener_finalize (GObject *object) +{ + PolkitMateListener *listener; + + listener = POLKIT_MATE_LISTENER (object); + + if (G_OBJECT_CLASS (polkit_mate_listener_parent_class)->finalize != NULL) + G_OBJECT_CLASS (polkit_mate_listener_parent_class)->finalize (object); +} + +static void +polkit_mate_listener_class_init (PolkitMateListenerClass *klass) +{ + GObjectClass *gobject_class; + PolkitAgentListenerClass *listener_class; + + gobject_class = G_OBJECT_CLASS (klass); + listener_class = POLKIT_AGENT_LISTENER_CLASS (klass); + + gobject_class->finalize = polkit_mate_listener_finalize; + + listener_class->initiate_authentication = polkit_mate_listener_initiate_authentication; + listener_class->initiate_authentication_finish = polkit_mate_listener_initiate_authentication_finish; +} + +PolkitAgentListener * +polkit_mate_listener_new (void) +{ + return POLKIT_AGENT_LISTENER (g_object_new (POLKIT_MATE_TYPE_LISTENER, NULL)); +} + +typedef struct +{ + PolkitMateListener *listener; + PolkitMateAuthenticator *authenticator; + + GSimpleAsyncResult *simple; + GCancellable *cancellable; + + gulong cancel_id; +} AuthData; + +static AuthData * +auth_data_new (PolkitMateListener *listener, + PolkitMateAuthenticator *authenticator, + GSimpleAsyncResult *simple, + GCancellable *cancellable) +{ + AuthData *data; + + 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; +} + +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); + g_object_unref (data->cancellable); + g_free (data); +} + +static void +maybe_initiate_next_authenticator (PolkitMateListener *listener) +{ + if (listener->active_authenticator == NULL && listener->authenticators != NULL) + { + polkit_mate_authenticator_initiate (POLKIT_MATE_AUTHENTICATOR (listener->authenticators->data)); + listener->active_authenticator = listener->authenticators->data; + } +} + +static void +authenticator_completed (PolkitMateAuthenticator *authenticator, + gboolean gained_authorization, + gpointer user_data) +{ + AuthData *data = user_data; + + data->listener->authenticators = g_list_remove (data->listener->authenticators, authenticator); + if (authenticator == data->listener->active_authenticator) + data->listener->active_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); +} + +static void +cancelled_cb (GCancellable *cancellable, + gpointer user_data) +{ + AuthData *data = user_data; + + polkit_mate_authenticator_cancel (data->authenticator); +} + +static void +polkit_mate_listener_initiate_authentication (PolkitAgentListener *agent_listener, + const gchar *action_id, + const gchar *message, + const gchar *icon_name, + PolkitDetails *details, + const gchar *cookie, + GList *identities, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + PolkitMateListener *listener = POLKIT_MATE_LISTENER (agent_listener); + GSimpleAsyncResult *simple; + PolkitMateAuthenticator *authenticator; + AuthData *data; + + simple = g_simple_async_result_new (G_OBJECT (listener), + callback, + user_data, + polkit_mate_listener_initiate_authentication); + + authenticator = polkit_mate_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, + "Error creating authentication object"); + g_simple_async_result_complete (simple); + goto out; + } + + data = auth_data_new (listener, authenticator, simple, cancellable); + + g_signal_connect (authenticator, + "completed", + G_CALLBACK (authenticator_completed), + data); + + if (cancellable != NULL) + { + data->cancel_id = g_signal_connect (cancellable, + "cancelled", + G_CALLBACK (cancelled_cb), + data); + } + + listener->authenticators = g_list_append (listener->authenticators, authenticator); + + maybe_initiate_next_authenticator (listener); + + out: + ; +} + +static gboolean +polkit_mate_listener_initiate_authentication_finish (PolkitAgentListener *listener, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_mate_listener_initiate_authentication); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + return TRUE; +} + |