PolicyKit: Branch 'master'
David Zeuthen
david at kemper.freedesktop.org
Sat Aug 7 09:52:05 PDT 2010
docs/polkit/polkit-1-docs.xml | 1
docs/polkit/polkit-1-sections.txt | 19
docs/polkit/polkit-1.types | 1
src/polkit/Makefile.am | 2
src/polkit/polkit.h | 1
src/polkit/polkitpermission.c | 844 ++++++++++++++++++++++++++++++++++++++
src/polkit/polkitpermission.h | 56 ++
src/polkit/polkittypes.h | 3
8 files changed, 927 insertions(+)
New commits:
commit f23aeb680fb3ea5db4edcd090fe9fea417a9cdfe
Author: David Zeuthen <davidz at redhat.com>
Date: Sat Aug 7 12:48:07 2010 -0400
Add a GPermission implementation
Based on code from Matthias Clasen <mclasen at redhat.com>.
Signed-off-by: David Zeuthen <davidz at redhat.com>
diff --git a/docs/polkit/polkit-1-docs.xml b/docs/polkit/polkit-1-docs.xml
index 4ddf9cd..12a1af9 100644
--- a/docs/polkit/polkit-1-docs.xml
+++ b/docs/polkit/polkit-1-docs.xml
@@ -73,6 +73,7 @@
<xi:include href="xml/polkiterror.xml"/>
<xi:include href="xml/polkitactiondescription.xml"/>
<xi:include href="xml/polkittemporaryauthorization.xml"/>
+ <xi:include href="xml/polkitpermission.xml"/>
<chapter id="subjects">
<title>Subjects</title>
<xi:include href="xml/polkitsubject.xml"/>
diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt
index 5826e54..1a0b869 100644
--- a/docs/polkit/polkit-1-sections.txt
+++ b/docs/polkit/polkit-1-sections.txt
@@ -468,3 +468,22 @@ POLKIT_TEMPORARY_AUTHORIZATION_CLASS
POLKIT_TEMPORARY_IS_AUTHORIZATION_CLASS
POLKIT_TEMPORARY_AUTHORIZATION_GET_CLASS
</SECTION>
+
+<SECTION>
+<FILE>polkitpermission</FILE>
+PolkitPermission
+polkit_permission_new
+polkit_permission_new_finish
+polkit_permission_new_sync
+polkit_permission_get_action_id
+polkit_permission_get_subject
+<SUBSECTION Standard>
+PolkitPermissionClass
+POLKIT_PERMISSION
+POLKIT_IS_PERMISSION
+POLKIT_TYPE_PERMISSION
+polkit_permission_get_type
+POLKIT_PERMISSION_CLASS
+POLKIT_IS_PERMISSION_CLASS
+POLKIT_PERMISSION_GET_CLASS
+</SECTION>
diff --git a/docs/polkit/polkit-1.types b/docs/polkit/polkit-1.types
index 749b8bc..2cab12a 100644
--- a/docs/polkit/polkit-1.types
+++ b/docs/polkit/polkit-1.types
@@ -13,6 +13,7 @@ polkit_system_bus_name_get_type
polkit_error_get_type
polkit_authorization_result_get_type
polkit_temporary_authorization_get_type
+polkit_permission_get_type
polkit_backend_authority_get_type
polkit_backend_interactive_authority_get_type
diff --git a/src/polkit/Makefile.am b/src/polkit/Makefile.am
index befe905..a2410b0 100644
--- a/src/polkit/Makefile.am
+++ b/src/polkit/Makefile.am
@@ -55,6 +55,7 @@ libpolkit_gobject_1include_HEADERS = \
polkitcheckauthorizationflags.h \
polkitimplicitauthorization.h \
polkittemporaryauthorization.h \
+ polkitpermission.h \
$(NULL)
libpolkit_gobject_1_la_SOURCES = \
@@ -76,6 +77,7 @@ libpolkit_gobject_1_la_SOURCES = \
polkitcheckauthorizationflags.c polkitcheckauthorizationflags.h \
polkitimplicitauthorization.c polkitimplicitauthorization.h \
polkittemporaryauthorization.c polkittemporaryauthorization.h \
+ polkitpermission.c polkitpermission.h \
$(NULL)
libpolkit_gobject_1_la_CFLAGS = \
diff --git a/src/polkit/polkit.h b/src/polkit/polkit.h
index 5e5fc66..f677ca1 100644
--- a/src/polkit/polkit.h
+++ b/src/polkit/polkit.h
@@ -42,6 +42,7 @@
#include <polkit/polkitauthority.h>
#include <polkit/polkitdetails.h>
#include <polkit/polkittemporaryauthorization.h>
+#include <polkit/polkitpermission.h>
#undef _POLKIT_INSIDE_POLKIT_H
diff --git a/src/polkit/polkitpermission.c b/src/polkit/polkitpermission.c
new file mode 100644
index 0000000..857a584
--- /dev/null
+++ b/src/polkit/polkitpermission.c
@@ -0,0 +1,844 @@
+/*
+ * Copyright (C) 2008-2010 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Matthias Clasen <mclasen at redhat.com>
+ * David Zeuthen <davidz at redhat.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <gio/gio.h>
+#include "polkitpermission.h"
+#include <polkit/polkit.h>
+
+#include "polkitpermission.h"
+
+/**
+ * SECTION:polkitpermission
+ * @title: PolkitPermission
+ * @short_description: PolicyKit #GPermission implementation
+ * @stability: Stable
+ *
+ * #PolkitPermission is a #GPermission implementation. It can be used
+ * with e.g. #GtkLockButton. See the #GPermission documentation for
+ * more information.
+ */
+
+typedef GPermissionClass PolkitPermissionClass;
+
+/**
+ * PolkitPermission:
+ *
+ * The #PolkitPermission struct should not be accessed directly.
+ */
+struct _PolkitPermission
+{
+ GPermission parent_instance;
+
+ PolkitAuthority *authority;
+ PolkitSubject *subject;
+
+ gchar *action_id;
+
+ /* non-NULL exactly when authorized with a temporary authorization */
+ gchar *tmp_authz_id;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ACTION_ID,
+ PROP_SUBJECT
+};
+
+static void process_result (PolkitPermission *permission,
+ PolkitAuthorizationResult *result);
+
+static void on_authority_changed (PolkitAuthority *authority,
+ gpointer user_data);
+
+static gboolean acquire (GPermission *permission,
+ GCancellable *cancellable,
+ GError **error);
+static void acquire_async (GPermission *permission,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+static gboolean acquire_finish (GPermission *permission,
+ GAsyncResult *result,
+ GError **error);
+
+static gboolean release (GPermission *permission,
+ GCancellable *cancellable,
+ GError **error);
+static void release_async (GPermission *permission,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+static gboolean release_finish (GPermission *permission,
+ GAsyncResult *result,
+ GError **error);
+
+static void initable_iface_init (GInitableIface *initable_iface);
+static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
+
+static gboolean polkit_permission_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error);
+
+G_DEFINE_TYPE_WITH_CODE (PolkitPermission, polkit_permission, G_TYPE_PERMISSION,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init))
+
+
+static void
+polkit_permission_init (PolkitPermission *simple)
+{
+}
+
+static void
+polkit_permission_constructed (GObject *object)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (object);
+
+ if (permission->subject == NULL)
+ permission->subject = polkit_unix_process_new (getpid ());
+
+ if (G_OBJECT_CLASS (polkit_permission_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (polkit_permission_parent_class)->constructed (object);
+}
+
+static void
+polkit_permission_finalize (GObject *object)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (object);
+
+ g_free (permission->action_id);
+ g_free (permission->tmp_authz_id);
+ g_object_unref (permission->subject);
+
+ g_signal_handlers_disconnect_by_func (permission->authority,
+ on_authority_changed,
+ permission);
+ g_object_unref (permission->authority);
+
+ if (G_OBJECT_CLASS (polkit_permission_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (polkit_permission_parent_class)->finalize (object);
+}
+
+static void
+polkit_permission_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (object);
+
+ switch (property_id)
+ {
+ case PROP_ACTION_ID:
+ g_value_set_string (value, permission->action_id);
+ break;
+
+ case PROP_SUBJECT:
+ g_value_set_object (value, permission->subject);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+polkit_permission_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (object);
+
+ switch (property_id)
+ {
+ case PROP_ACTION_ID:
+ permission->action_id = g_value_dup_string (value);
+ break;
+
+ case PROP_SUBJECT:
+ permission->subject = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+polkit_permission_class_init (PolkitPermissionClass *class)
+{
+ GObjectClass *object_class;
+ GPermissionClass *permission_class;
+
+ permission_class = G_PERMISSION_CLASS (class);
+ permission_class->acquire = acquire;
+ permission_class->acquire_async = acquire_async;
+ permission_class->acquire_finish = acquire_finish;
+ permission_class->release = release;
+ permission_class->release_async = release_async;
+ permission_class->release_finish = release_finish;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = polkit_permission_finalize;
+ object_class->constructed = polkit_permission_constructed;
+ object_class->get_property = polkit_permission_get_property;
+ object_class->set_property = polkit_permission_set_property;
+
+ /**
+ * PolkitPermission:action-id:
+ *
+ * The action identifier to use for the permission.
+ */
+ g_object_class_install_property (object_class,
+ PROP_ACTION_ID,
+ g_param_spec_string ("action-id",
+ "Action Identifier",
+ "The action identifier to use for the permission",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+ /**
+ * PolkitPermission:subject:
+ *
+ * The #PolkitSubject to use for the permission. If not set during
+ * construction, it will be set to match the current process.
+ */
+ g_object_class_install_property (object_class,
+ PROP_SUBJECT,
+ g_param_spec_object ("subject",
+ "Subject",
+ "The subject to use for the permission",
+ POLKIT_TYPE_SUBJECT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * polkit_permission_new:
+ * @action_id: The PolicyKit action identifier.
+ * @subject: A #PolkitSubject or %NULL for the current process.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: The data to pass to @callback.
+ *
+ * Creates a #GPermission instance for the PolicyKit action
+ * @action_id.
+ *
+ * When the operation is finished, @callback will be invoked. You can
+ * then call polkit_permission_new_finish() to get the result of the
+ * operation.
+ *
+ * This is a asynchronous failable constructor. See
+ * polkit_permission_new_sync() for the synchronous version.
+ */
+void
+polkit_permission_new (const gchar *action_id,
+ PolkitSubject *subject,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (action_id != NULL);
+ g_return_if_fail (subject == NULL || POLKIT_IS_SUBJECT (subject));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ g_async_initable_new_async (POLKIT_TYPE_PERMISSION,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "action-id", action_id,
+ "subject", subject,
+ NULL);
+}
+
+/**
+ * polkit_permission_new_finish:
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to polkit_permission_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with polkit_permission_new().
+ *
+ * Returns: A #GPermission or %NULL if @error is set.
+ */
+GPermission *
+polkit_permission_new_finish (GAsyncResult *res,
+ GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ source_object = g_async_result_get_source_object (res);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
+ res,
+ error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return G_PERMISSION (object);
+ else
+ return NULL;
+}
+
+/**
+ * polkit_permission_new_sync:
+ * @action_id: The PolicyKit action identifier.
+ * @subject: A #PolkitSubject or %NULL for the current process.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Creates a #GPermission instance for the PolicyKit action
+ * @action_id.
+ *
+ * This is a synchronous failable constructor. See
+ * polkit_permission_new() for the asynchronous version.
+ *
+ * Returns: A #GPermission or %NULL if @error is set.
+ */
+GPermission *
+polkit_permission_new_sync (const gchar *action_id,
+ PolkitSubject *subject,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (action_id != NULL, NULL);
+ g_return_val_if_fail (subject == NULL || POLKIT_IS_SUBJECT (subject), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ return g_initable_new (POLKIT_TYPE_PERMISSION,
+ cancellable,
+ error,
+ "action-id", action_id,
+ "subject", subject,
+ NULL);
+}
+
+static void
+initable_iface_init (GInitableIface *initable_iface)
+{
+ initable_iface->init = polkit_permission_initable_init;
+}
+
+static void
+async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
+{
+ /* for now, we use default implementation to run GInitable code in a
+ * thread - would probably be nice to have real async version to
+ * avoid the thread-overhead
+ */
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * polkit_permission_get_action_id:
+ * @permission: A #PolkitPermission.
+ *
+ * Gets the PolicyKit action identifier used for @permission.
+ *
+ * Returns: A string owned by @permission. Do not free.
+ */
+const gchar *
+polkit_permission_get_action_id (PolkitPermission *permission)
+{
+ g_return_val_if_fail (POLKIT_IS_PERMISSION (permission), NULL);
+ return permission->action_id;
+}
+
+/**
+ * polkit_permission_get_action_id:
+ * @permission: A #PolkitPermission.
+ *
+ * Gets the subject used for @permission.
+ *
+ * Returns: An object owned by @permission. Do not free.
+ */
+PolkitSubject *
+polkit_permission_get_subject (PolkitPermission *permission)
+{
+ g_return_val_if_fail (POLKIT_IS_PERMISSION (permission), NULL);
+ return permission->subject;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+polkit_permission_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (initable);
+ PolkitAuthorizationResult *result;
+ gboolean ret;
+
+ ret = FALSE;
+
+ /* TODO: use sync failable getter instead */
+ permission->authority = polkit_authority_get ();
+
+ g_signal_connect (permission->authority,
+ "changed",
+ G_CALLBACK (on_authority_changed),
+ permission);
+
+ result = polkit_authority_check_authorization_sync (permission->authority,
+ permission->subject,
+ permission->action_id,
+ NULL, /* PolkitDetails */
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+ cancellable,
+ error);
+ if (result == NULL)
+ goto out;
+
+ process_result (permission, result);
+ g_object_unref (result);
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+changed_check_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (user_data);
+ PolkitAuthorizationResult *result;
+ GError *error;
+
+ error = NULL;
+ result = polkit_authority_check_authorization_finish (permission->authority,
+ res,
+ &error);
+ if (result != NULL)
+ {
+ process_result (permission, result);
+ }
+ else
+ {
+ /* this really should never fail (since we are not passing any
+ * details) so log to stderr if it happens
+ */
+ g_warning ("Error checking authorization for action id %s: %s",
+ permission->action_id,
+ error->message);
+ g_error_free (error);
+ }
+ g_object_unref (permission);
+}
+
+static void
+on_authority_changed (PolkitAuthority *authority,
+ gpointer user_data)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (user_data);
+
+ polkit_authority_check_authorization (permission->authority,
+ permission->subject,
+ permission->action_id,
+ NULL, /* PolkitDetails */
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+ NULL /* cancellable */,
+ changed_check_cb,
+ g_object_ref (permission));
+}
+
+static void
+process_result (PolkitPermission *permission,
+ PolkitAuthorizationResult *result)
+{
+ gboolean can_acquire;
+ gboolean can_release;
+ gboolean allowed;
+
+ /* save the temporary authorization id */
+ g_free (permission->tmp_authz_id);
+ permission->tmp_authz_id = g_strdup (polkit_authorization_result_get_temporary_authorization_id (result));
+ allowed = polkit_authorization_result_get_is_authorized (result);
+ if (permission->tmp_authz_id != NULL)
+ {
+ can_acquire = FALSE;
+ can_release = TRUE;
+ }
+ else
+ {
+ if (allowed)
+ can_acquire = FALSE;
+ else
+ can_acquire = polkit_authorization_result_get_retains_authorization (result);
+ can_release = FALSE;
+ }
+ g_permission_impl_update (G_PERMISSION (permission), allowed, can_acquire, can_release);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+ PolkitPermission *permission;
+ GSimpleAsyncResult *simple;
+} AcquireData;
+
+static void
+acquire_data_free (AcquireData *data)
+{
+ g_object_unref (data->simple);
+ g_free (data);
+}
+
+static void
+acquire_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ AcquireData *data = user_data;
+ PolkitAuthorizationResult *result;
+ GError *error;
+ gboolean ret;
+
+ ret = FALSE;
+
+ error = NULL;
+ result = polkit_authority_check_authorization_finish (data->permission->authority,
+ res,
+ &error);
+ if (result != NULL)
+ {
+ /* Process the result such that allowed, can_acquire and
+ * can_release are updated before returning to the user - see
+ * also release_cb for where we do this as well
+ */
+ process_result (data->permission, result);
+ if (!polkit_authorization_result_get_is_authorized (result))
+ {
+ g_simple_async_result_set_error (data->simple,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Failed to acquire permission for action-id %s",
+ data->permission->action_id);
+ }
+ g_object_unref (result);
+ }
+ else
+ {
+ g_simple_async_result_set_from_error (data->simple, error);
+ g_error_free (error);
+ }
+ /* don't complete in idle since we're already completing in idle
+ * due to how PolkitAuthority works
+ */
+ g_simple_async_result_complete (data->simple);
+ acquire_data_free (data);
+}
+
+static void
+acquire_async (GPermission *gpermission,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (gpermission);
+ AcquireData *data;
+
+ data = g_new0 (AcquireData, 1);
+ data->permission = permission;
+ data->simple = g_simple_async_result_new (G_OBJECT (permission),
+ callback,
+ user_data,
+ acquire_async);
+
+ polkit_authority_check_authorization (permission->authority,
+ permission->subject,
+ permission->action_id,
+ NULL, /* PolkitDetails */
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ cancellable,
+ acquire_cb,
+ data);
+}
+
+static gboolean
+acquire_finish (GPermission *gpermission,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == acquire_async);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+acquire (GPermission *gpermission,
+ GCancellable *cancellable,
+ GError **error)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (gpermission);
+ PolkitAuthorizationResult *result;
+ gboolean ret;
+
+ ret = FALSE;
+
+ result = polkit_authority_check_authorization_sync (permission->authority,
+ permission->subject,
+ permission->action_id,
+ NULL, /* PolkitDetails */
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ cancellable,
+ error);
+ if (result != NULL)
+ {
+ /* need to update allowed, can_acquire, can_release before returning to the user */
+ process_result (permission, result);
+ if (polkit_authorization_result_get_is_authorized (result))
+ {
+ ret = TRUE;
+ }
+ else
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Failed to acquire permission for action-id %s",
+ permission->action_id);
+ }
+ g_object_unref (result);
+ }
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+ PolkitPermission *permission;
+ GSimpleAsyncResult *simple;
+} ReleaseData;
+
+static void
+release_data_free (ReleaseData *data)
+{
+ g_object_unref (data->simple);
+ g_free (data);
+}
+
+static void
+release_check_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ReleaseData *data = user_data;
+ PolkitAuthorizationResult *result;
+ GError *error;
+
+ error = NULL;
+ result = polkit_authority_check_authorization_finish (data->permission->authority,
+ res,
+ &error);
+ if (result == NULL)
+ {
+ g_prefix_error (&error,
+ "Error checking authorization for action id %s after releasing the permission: ",
+ data->permission->action_id);
+ g_simple_async_result_set_from_error (data->simple, error);
+ g_error_free (error);
+ }
+ else
+ {
+ process_result (data->permission, result);
+ g_object_unref (result);
+ }
+ /* don't complete in idle since we're already completing in idle
+ * due to how PolkitAuthority works
+ */
+ g_simple_async_result_complete (data->simple);
+ release_data_free (data);
+}
+
+static void
+release_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ReleaseData *data = user_data;
+ GError *error;
+ gboolean ret;
+
+ ret = FALSE;
+
+ error = NULL;
+ ret = polkit_authority_revoke_temporary_authorization_by_id_finish (data->permission->authority,
+ res,
+ &error);
+ if (!ret)
+ {
+ g_simple_async_result_set_from_error (data->simple, error);
+ g_error_free (error);
+ /* don't complete in idle since we're already completing in idle
+ * due to how PolkitAuthority works
+ */
+ g_simple_async_result_complete (data->simple);
+ release_data_free (data);
+ }
+ else
+ {
+ /* need to update allowed, can_acquire and can_release before
+ * returning to the user - see also acquire_cb where we do this
+ * as well
+ */
+ polkit_authority_check_authorization (data->permission->authority,
+ data->permission->subject,
+ data->permission->action_id,
+ NULL, /* PolkitDetails */
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+ NULL /* cancellable */,
+ release_check_cb,
+ data);
+ }
+}
+
+static void
+release_async (GPermission *gpermission,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (gpermission);
+ ReleaseData *data;
+
+ data = g_new0 (ReleaseData, 1);
+ data->permission = permission;
+ data->simple = g_simple_async_result_new (G_OBJECT (permission),
+ callback,
+ user_data,
+ release_async);
+
+ if (permission->tmp_authz_id == NULL)
+ {
+ g_simple_async_result_set_error (data->simple,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Cannot release permission: no temporary authorization for action-id %s exist",
+ permission->action_id);
+ g_simple_async_result_complete_in_idle (data->simple);
+ release_data_free (data);
+ goto out;
+ }
+
+ polkit_authority_revoke_temporary_authorization_by_id (permission->authority,
+ permission->tmp_authz_id,
+ cancellable,
+ release_cb,
+ data);
+ out:
+ ;
+}
+
+static gboolean
+release_finish (GPermission *gpermission,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == release_async);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+release (GPermission *gpermission,
+ GCancellable *cancellable,
+ GError **error)
+{
+ PolkitPermission *permission = POLKIT_PERMISSION (gpermission);
+ PolkitAuthorizationResult *result;
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (permission->tmp_authz_id == NULL)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Cannot release permission: no temporary authorization for action-id %s exist",
+ permission->action_id);
+ goto out;
+ }
+
+ ret = polkit_authority_revoke_temporary_authorization_by_id_sync (permission->authority,
+ permission->tmp_authz_id,
+ cancellable,
+ error);
+ if (!ret)
+ goto out;
+
+ /* need to update allowed, can_acquire, can_release before returning to the user */
+ result = polkit_authority_check_authorization_sync (permission->authority,
+ permission->subject,
+ permission->action_id,
+ NULL, /* PolkitDetails */
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+ cancellable,
+ error);
+ if (result == NULL)
+ goto out;
+ process_result (permission, result);
+ g_object_unref (result);
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/polkit/polkitpermission.h b/src/polkit/polkitpermission.h
new file mode 100644
index 0000000..3640f0c
--- /dev/null
+++ b/src/polkit/polkitpermission.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008-2010 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Matthias Clasen <mclasen at redhat.com>
+ * David Zeuthen <davidz at redhat.com>
+ */
+
+#if !defined (_POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H)
+#error "Only <polkit/polkit.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_PERMISSION_H
+#define __POLKIT_PERMISSION_H
+
+#include <polkit/polkittypes.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_TYPE_PERMISSION (polkit_permission_get_type ())
+#define POLKIT_PERMISSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_TYPE_PERMISSION, PolkitPermission))
+#define POLKIT_IS_PERMISSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_TYPE_PERMISSION))
+
+GType polkit_permission_get_type (void) G_GNUC_CONST;
+void polkit_permission_new (const gchar *action_id,
+ PolkitSubject *subject,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GPermission *polkit_permission_new_finish (GAsyncResult *res,
+ GError **error);
+GPermission *polkit_permission_new_sync (const gchar *action_id,
+ PolkitSubject *subject,
+ GCancellable *cancellable,
+ GError **error);
+const gchar *polkit_permission_get_action_id (PolkitPermission *permission);
+PolkitSubject *polkit_permission_get_subject (PolkitPermission *permission);
+
+G_END_DECLS
+
+#endif /* __POLKIT_PERMISSION_H */
diff --git a/src/polkit/polkittypes.h b/src/polkit/polkittypes.h
index 0da7faf..636b418 100644
--- a/src/polkit/polkittypes.h
+++ b/src/polkit/polkittypes.h
@@ -58,4 +58,7 @@ typedef struct _PolkitDetails PolkitDetails;
struct _PolkitTemporaryAuthorization;
typedef struct _PolkitTemporaryAuthorization PolkitTemporaryAuthorization;
+struct _PolkitPermission;
+typedef struct _PolkitPermission PolkitPermission;
+
#endif /* __POLKIT_TYPES_H */
More information about the hal-commit
mailing list