[gconf] Move GConf to PolicyKit 1.0 API



commit d6a74d1dd539fe0c9bdf731bc2848d033d8351b8
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Aug 13 13:19:22 2009 -0400

    Move GConf to PolicyKit 1.0 API
    
    This patch updates the gconf defaults mechanism to use
    the new PolicyKit 1.0 API.

 configure.in                   |    9 +-
 defaults/Makefile.am           |    7 +-
 defaults/gconf-defaults-main.c |   39 ++
 defaults/gconf-defaults.c      | 1119 ++++++++++++++++++++++++++--------------
 defaults/gconf-defaults.h      |    8 +
 defaults/gconf-defaults.xml    |   14 +-
 6 files changed, 785 insertions(+), 411 deletions(-)
---
diff --git a/configure.in b/configure.in
index e407734..e4e50be 100644
--- a/configure.in
+++ b/configure.in
@@ -181,7 +181,7 @@ AC_ARG_ENABLE(defaults_service,
   , enable_defaults_service=auto)
 
 if test "x$enable_defaults_service" != "xno" ; then
-  PKG_CHECK_MODULES(DEFAULTS, glib-2.0 gobject-2.0 dbus-1 dbus-glib-1 polkit-dbus, HAVE_POLKIT=yes)
+  PKG_CHECK_MODULES(DEFAULTS, glib-2.0 gobject-2.0 dbus-1 dbus-glib-1 polkit-gobject-1, HAVE_POLKIT=yes)
   if test "x$HAVE_POLKIT" = "xno"; then
     if test "x$enable_defaults_service" = "xyes" ; then
       AC_MSG_ERROR([[
@@ -194,13 +194,6 @@ fi
 
 if test "x$enable_defaults_service" != "xno" ; then
   AC_DEFINE(ENABLE_DEFAULTS_SERVICE, 1, [enable defaults DBus service])
-
-  AC_CHECK_PROG([POLKIT_POLICY_FILE_VALIDATE],
-    [polkit-policy-file-validate], [polkit-policy-file-validate])
-
-  if test -z "$POLKIT_POLICY_FILE_VALIDATE"; then
-    AC_MSG_ERROR([polkit-policy-file-validate not found])
-  fi
 fi
 
 AM_CONDITIONAL(ENABLE_DEFAULTS_SERVICE, [test "x$enable_defaults_service" != "xno"])
diff --git a/defaults/Makefile.am b/defaults/Makefile.am
index a3b8d6e..f1db711 100644
--- a/defaults/Makefile.am
+++ b/defaults/Makefile.am
@@ -20,13 +20,13 @@ INCLUDES = \
 
 gconf_defaults_mechanism_LDADD = \
 	$(top_builddir)/gconf/libgconf-2.la \
-	$(DEFAULTS_LIBS) 
+	$(DEFAULTS_LIBS)
 
 BUILT_SOURCES = gconf-defaults-glue.h
 
 dbus_servicesdir = $(datadir)/dbus-1/system-services
 dbus_confdir = $(sysconfdir)/dbus-1/system.d
-polkitdir = $(datadir)/PolicyKit/policy
+polkitdir = $(datadir)/polkit-1/actions
 
 dbus_services_in_files = org.gnome.GConf.Defaults.service.in
 polkit_in_files = org.gnome.gconf.defaults.policy.in
@@ -41,9 +41,6 @@ dbus_conf_DATA = org.gnome.GConf.Defaults.conf
 @INTLTOOL_POLICY_RULE@
 polkit_DATA = $(polkit_in_files:.policy.in=.policy)
 
-check:
-	$(POLKIT_POLICY_FILE_VALIDATE) $(polkit_DATA)
-
 EXTRA_DIST =					\
 	$(dbus_services_in_files)		\
 	org.gnome.GConf.Defaults.conf		\
diff --git a/defaults/gconf-defaults-main.c b/defaults/gconf-defaults-main.c
index 5a4af52..7ed7700 100644
--- a/defaults/gconf-defaults-main.c
+++ b/defaults/gconf-defaults-main.c
@@ -122,6 +122,29 @@ get_system_bus (void)
         return bus;
 }
 
+extern gboolean disable_killtimer;
+gboolean debug = FALSE;
+
+GOptionEntry entries [] = {
+	{ "debug", 0, 0, G_OPTION_ARG_NONE, &debug, "Emit debug output", NULL },
+	{ "no-kill", 0, 0, G_OPTION_ARG_NONE, &disable_killtimer, "Don't exit when idle", NULL },
+	{ NULL, }
+};
+
+static gint log_levels = (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
+
+void
+log_default_handler (const gchar   *log_domain,
+                     GLogLevelFlags log_level,
+                     const gchar   *message,
+                     gpointer       unused_data)
+{
+	if ((log_level & log_levels) != 0) {
+		g_log_default_handler (log_domain, log_level, message, unused_data);
+	}
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -130,6 +153,8 @@ main (int argc, char **argv)
         DBusGProxy          *bus_proxy;
         DBusGConnection     *connection;
         int                  ret;
+	GOptionContext      *options;
+	GError              *error = NULL;
 
         ret = 1;
 
@@ -139,8 +164,22 @@ main (int argc, char **argv)
         dbus_g_thread_init ();
         g_type_init ();
 
+	options = g_option_context_new (NULL);
+	g_option_context_add_main_entries (options, entries, NULL);
+	if (!g_option_context_parse (options, &argc, &argv, &error)) {
+		g_warning ("Failed to parse options: %s\n", error->message);
+		g_error_free (error);
+	}
+	g_option_context_free (options);
+
+	g_log_set_default_handler (log_default_handler, NULL);
+	if (debug) {
+		log_levels = log_levels | G_LOG_LEVEL_DEBUG;
+	}
+
         connection = get_system_bus ();
         if (connection == NULL) {
+                g_warning ("Could not get system bus connection; bailing out");
                 goto out;
         }
 
diff --git a/defaults/gconf-defaults.c b/defaults/gconf-defaults.c
index e477435..11a38ad 100644
--- a/defaults/gconf-defaults.c
+++ b/defaults/gconf-defaults.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2008 Matthias Clasen <mclasen redhat com>
+ * Copyright (C) 2008, 2009 Matthias Clasen <mclasen redhat com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -37,7 +37,6 @@
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
-#include <polkit-dbus/polkit-dbus.h>
 #include <polkit/polkit.h>
 
 #define GCONF_ENABLE_INTERNALS
@@ -50,34 +49,61 @@
 static gboolean
 do_exit (gpointer user_data)
 {
-	g_debug ("Exiting due to inactivity");
-	exit (1);
-	return FALSE;
+        g_debug ("Exiting due to inactivity");
+        exit (1);
+        return FALSE;
 }
 
 static guint timer_id = 0;
+gboolean disable_killtimer = FALSE;
 
 static void
 stop_killtimer (void)
 {
-	if (timer_id > 0) {
-		g_source_remove (timer_id);
+	if (disable_killtimer)
+		return;
+
+        if (timer_id > 0) {
+                g_source_remove (timer_id);
 		timer_id = 0;
-	}
+        }
 }
 
 static void
 start_killtimer (void)
 {
-	g_debug ("Setting killtimer to 30 seconds...");
-	timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+	if (disable_killtimer)
+		return;
+
+	if (timer_id == 0) {
+        	g_debug ("Setting killtimer to 30 seconds...");
+        	timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+	}
+}
+
+static gint operations = 0;
+
+static void
+start_operation (void)
+{
+	if (operations == 0)
+		stop_killtimer ();
+	operations++;
+}
+
+static void
+stop_operation (void)
+{
+	if (operations == 1)
+		start_killtimer ();
+	operations --;
 }
 
 struct GConfDefaultsPrivate
 {
-	DBusGConnection *system_bus_connection;
-	DBusGProxy      *system_bus_proxy;
-	PolKitContext   *pol_ctx;
+        DBusGConnection *system_bus_connection;
+        DBusGProxy      *system_bus_proxy;
+        PolkitAuthority *auth;
 };
 
 static void gconf_defaults_finalize (GObject *object);
@@ -89,13 +115,13 @@ G_DEFINE_TYPE (GConfDefaults, gconf_defaults, G_TYPE_OBJECT)
 GQuark
 gconf_defaults_error_quark (void)
 {
-	static GQuark ret = 0;
+        static GQuark ret = 0;
 
-	if (ret == 0) {
-		ret = g_quark_from_static_string ("gconf_defaults_error");
-	}
+        if (ret == 0) {
+                ret = g_quark_from_static_string ("gconf_defaults_error");
+        }
 
-	return ret;
+        return ret;
 }
 
 
@@ -104,21 +130,23 @@ gconf_defaults_error_quark (void)
 GType
 gconf_defaults_error_get_type (void)
 {
-	static GType etype = 0;
+        static GType etype = 0;
 
-	if (etype == 0) {
-		static const GEnumValue values[] = {
-			ENUM_ENTRY (GCONF_DEFAULTS_ERROR_GENERAL, "GeneralError"),
-			ENUM_ENTRY (GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
-			{ 0, 0, 0 }
-		};
+        if (etype == 0)
+        {
+                static const GEnumValue values[] =
+                        {
+                                ENUM_ENTRY (GCONF_DEFAULTS_ERROR_GENERAL, "GeneralError"),
+                                ENUM_ENTRY (GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
+                                { 0, 0, 0 }
+                        };
 
-		g_assert (GCONF_DEFAULTS_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
+                g_assert (GCONF_DEFAULTS_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
 
-		etype = g_enum_register_static ("GConfDefaultsError", values);
-	}
+                etype = g_enum_register_static ("GConfDefaultsError", values);
+        }
 
-	return etype;
+        return etype;
 }
 
 
@@ -127,17 +155,17 @@ gconf_defaults_constructor (GType                  type,
                             guint                  n_construct_properties,
                             GObjectConstructParam *construct_properties)
 {
-	GConfDefaults      *mechanism;
-	GConfDefaultsClass *klass;
+        GConfDefaults      *mechanism;
+        GConfDefaultsClass *klass;
 
-	klass = GCONF_DEFAULTS_CLASS (g_type_class_peek (GCONF_TYPE_DEFAULTS));
+        klass = GCONF_DEFAULTS_CLASS (g_type_class_peek (GCONF_TYPE_DEFAULTS));
 
-	mechanism = GCONF_DEFAULTS (G_OBJECT_CLASS (gconf_defaults_parent_class)->constructor (
-						type,
-						n_construct_properties,
-						construct_properties));
+        mechanism = GCONF_DEFAULTS (G_OBJECT_CLASS (gconf_defaults_parent_class)->constructor (
+                                                type,
+                                                n_construct_properties,
+                                                construct_properties));
 
-	return G_OBJECT (mechanism);
+        return G_OBJECT (mechanism);
 }
 
 enum {
@@ -150,10 +178,10 @@ static guint signals[LAST_SIGNAL] = { 0 };
 static void
 gconf_defaults_class_init (GConfDefaultsClass *klass)
 {
-	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
-	object_class->constructor = gconf_defaults_constructor;
-	object_class->finalize = gconf_defaults_finalize;
+        object_class->constructor = gconf_defaults_constructor;
+        object_class->finalize = gconf_defaults_finalize;
 
 	signals[SYSTEM_SET] = g_signal_new ("system-set",
 					    G_OBJECT_CLASS_TYPE (object_class),
@@ -162,149 +190,114 @@ gconf_defaults_class_init (GConfDefaultsClass *klass)
 					    NULL, NULL,
 					    g_cclosure_marshal_VOID__BOXED,
 					    G_TYPE_NONE, 1, G_TYPE_STRV);
+ 
+        g_type_class_add_private (klass, sizeof (GConfDefaultsPrivate));
 
-	g_type_class_add_private (klass, sizeof (GConfDefaultsPrivate));
+        dbus_g_object_type_install_info (GCONF_TYPE_DEFAULTS, &dbus_glib_gconf_defaults_object_info);
 
-	dbus_g_object_type_install_info (GCONF_TYPE_DEFAULTS, &dbus_glib_gconf_defaults_object_info);
+        dbus_g_error_domain_register (GCONF_DEFAULTS_ERROR, NULL, GCONF_DEFAULTS_TYPE_ERROR);
 
-	dbus_g_error_domain_register (GCONF_DEFAULTS_ERROR, NULL, GCONF_DEFAULTS_TYPE_ERROR);
 }
 
 static void
 gconf_defaults_init (GConfDefaults *mechanism)
 {
-	mechanism->priv = GCONF_DEFAULTS_GET_PRIVATE (mechanism);
+        mechanism->priv = GCONF_DEFAULTS_GET_PRIVATE (mechanism);
 }
 
 static void
 gconf_defaults_finalize (GObject *object)
 {
-	GConfDefaults *mechanism;
+        GConfDefaults *mechanism;
 
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (GCONF_IS_DEFAULTS (object));
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GCONF_IS_DEFAULTS (object));
 
-	mechanism = GCONF_DEFAULTS (object);
+        mechanism = GCONF_DEFAULTS (object);
 
-	g_return_if_fail (mechanism->priv != NULL);
+        g_return_if_fail (mechanism->priv != NULL);
 
-	g_object_unref (mechanism->priv->system_bus_proxy);
+	g_object_unref (mechanism->priv->auth);
+        g_object_unref (mechanism->priv->system_bus_proxy);
 
-	G_OBJECT_CLASS (gconf_defaults_parent_class)->finalize (object);
-}
-
-static gboolean
-pk_io_watch_have_data (GIOChannel   *channel,
-                       GIOCondition  condition,
-                       gpointer      user_data)
-{
-	int fd;
-	PolKitContext *pk_context = user_data;
-	fd = g_io_channel_unix_get_fd (channel);
-	polkit_context_io_func (pk_context, fd);
-	return TRUE;
-}
-
-static int
-pk_io_add_watch (PolKitContext *pk_context, int fd)
-{
-	guint id = 0;
-	GIOChannel *channel;
-	channel = g_io_channel_unix_new (fd);
-	if (channel == NULL)
-		goto out;
-	id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
-	if (id == 0) {
-		g_io_channel_unref (channel);
-		goto out;
-	}
-	g_io_channel_unref (channel);
-out:
-	return id;
-}
-
-static void
-pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
-{
-	g_source_remove (watch_id);
+        G_OBJECT_CLASS (gconf_defaults_parent_class)->finalize (object);
 }
 
 static gboolean
 register_mechanism (GConfDefaults *mechanism)
 {
-	GError *error = NULL;
+        GError *error = NULL;
 
-	mechanism->priv->pol_ctx = polkit_context_new ();
-	polkit_context_set_io_watch_functions (mechanism->priv->pol_ctx, pk_io_add_watch, pk_io_remove_watch);
-	if (!polkit_context_init (mechanism->priv->pol_ctx, NULL)) {
-		g_critical ("cannot initialize libpolkit");
-		goto error;
-	}
+        mechanism->priv->auth = polkit_authority_get ();
 
-	error = NULL;
-	mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
-	if (mechanism->priv->system_bus_connection == NULL) {
-		if (error != NULL) {
-			g_critical ("error getting system bus: %s", error->message);
-			g_error_free (error);
-		}
-		goto error;
-	}
+        error = NULL;
+        mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (mechanism->priv->system_bus_connection == NULL) {
+                if (error != NULL) {
+                        g_critical ("error getting system bus: %s", error->message);
+                        g_error_free (error);
+                }
+                goto error;
+        }
 
-	dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/",
-					     G_OBJECT (mechanism));
+        dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/",
+                                             G_OBJECT (mechanism));
 
-	mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
-								       DBUS_SERVICE_DBUS,
-								       DBUS_PATH_DBUS,
-								       DBUS_INTERFACE_DBUS);
+        mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
+                                                                      DBUS_SERVICE_DBUS,
+                                                                      DBUS_PATH_DBUS,
+                                                                      DBUS_INTERFACE_DBUS);
 
-	start_killtimer ();
+        start_killtimer ();
 
-	return TRUE;
+        return TRUE;
 
 error:
-	return FALSE;
+        return FALSE;
 }
 
 
 GConfDefaults *
 gconf_defaults_new (void)
 {
-	GObject *object;
-	gboolean res;
+        GObject *object;
+        gboolean res;
 
-	object = g_object_new (GCONF_TYPE_DEFAULTS, NULL);
+        object = g_object_new (GCONF_TYPE_DEFAULTS, NULL);
 
-	res = register_mechanism (GCONF_DEFAULTS (object));
-	if (! res) {
-		g_object_unref (object);
-		return NULL;
-	}
+        res = register_mechanism (GCONF_DEFAULTS (object));
+        if (! res) {
+                g_object_unref (object);
+                return NULL;
+        }
 
-	return GCONF_DEFAULTS (object);
+        return GCONF_DEFAULTS (object);
 }
 
 static const char *
 polkit_action_for_gconf_path (GConfDefaults *mechanism,
+			      GList         *action_descriptions,
 			      const char    *annotation_key,
 			      const char    *path)
 {
-	PolKitPolicyCache *cache;
-	PolKitPolicyFileEntry *entry;
 	char *prefix, *p;
 	const char *action;
+        GList *l;
+        PolkitActionDescription *action_description;
+	const gchar *annotation;
 
-	cache = polkit_context_get_policy_cache (mechanism->priv->pol_ctx);
 	prefix = g_strdup (path);
 
 	while (1) {
-		entry = polkit_policy_cache_get_entry_by_annotation (cache,
-								     annotation_key,
-								     prefix);
-		if (entry) {
-			action = polkit_policy_file_entry_get_id (entry);
-			break;
+                for (l = action_descriptions; l; l = l->next) {
+			action_description = l->data;
+
+			annotation = polkit_action_description_get_annotation (action_description, annotation_key);
+			if (g_strcmp0 (prefix, annotation) == 0) {
+				action = polkit_action_description_get_action_id (action_description);
+				g_debug ("action for path '%s': '%s'\n", action, path);
+				break;
+			}
 		}
 
 		p = strrchr (prefix, '/');
@@ -322,56 +315,160 @@ polkit_action_for_gconf_path (GConfDefaults *mechanism,
 	return action;
 }
 
-static gboolean
-check_polkit_for_action (GConfDefaults         *mechanism,
-                         DBusGMethodInvocation *context,
-                         const char            *action)
+static void
+throw_error (DBusGMethodInvocation *context,
+             gint                   error_code,
+             const gchar           *format,
+             ...)
 {
-	const char *sender;
 	GError *error;
-	DBusError dbus_error;
-	PolKitCaller *pk_caller;
-	PolKitAction *pk_action;
-	PolKitResult pk_result;
+	va_list args;
+	gchar *message;
+
+	va_start (args, format);
+	message = g_strdup_vprintf (format, args);
+	va_end (args);
+
+	error = g_error_new (GCONF_DEFAULTS_ERROR,
+			     error_code,
+			     "%s", message);
+	dbus_g_method_return_error (context, error);
+	g_error_free (error);
+	g_free (message);
+}
 
-	error = NULL;
+typedef void (*AuthObtainedCallback) (GConfDefaults          *mechanism,
+                                      DBusGMethodInvocation  *context,
+                                      gpointer                user_data);
+
+typedef struct
+{
+	GConfDefaults                   *mechanism;
+	DBusGMethodInvocation           *context;
+	gchar                          **actions;
+	gint				 id;
+	gint				 flags;
+	AuthObtainedCallback             auth_obtained_callback;
+	GAsyncReadyCallback		 check_auth_callback;
+	gpointer                         user_data;
+	GDestroyNotify                   destroy;
+	PolkitSubject			*subject;
+	gboolean			 challenge;
+} CheckAuthData;
+
+static void
+check_auth_data_free (CheckAuthData *data)
+{
+	g_object_unref (data->mechanism);
+	g_strfreev (data->actions);
+	if (data->destroy)
+		data->destroy (data->user_data);
+        g_object_unref (data->subject);
+	g_free (data);
+}
+
+static void check_next_action (CheckAuthData *data);
+
+static void
+check_authorization_callback (PolkitAuthority *authority,
+                              GAsyncResult    *res,
+                              gpointer         user_data)
+{
+	CheckAuthData *data = user_data;
+	PolkitAuthorizationResult *result;
+	GError *error;
+	gboolean is_authorized;
+
+	is_authorized = FALSE;
 
-	/* Check that caller is privileged */
-	sender = dbus_g_method_get_sender (context);
-	dbus_error_init (&dbus_error);
-	pk_caller = polkit_caller_new_from_dbus_name (
-	dbus_g_connection_get_connection (mechanism->priv->system_bus_connection),
-					  sender,
-					  &dbus_error);
-	if (pk_caller == NULL) {
-		error = g_error_new (GCONF_DEFAULTS_ERROR,
-				     GCONF_DEFAULTS_ERROR_GENERAL,
-				     "Error getting information about caller: %s: %s",
-				     dbus_error.name, dbus_error.message);
-		dbus_error_free (&dbus_error);
-		dbus_g_method_return_error (context, error);
+	error = NULL;
+	result = polkit_authority_check_authorization_finish (authority,
+							      res,
+							      &error);
+	if (error != NULL) {
+		g_debug ("error checking action '%s'\n", error->message);
+		throw_error (data->context,
+                             GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+                             "Not Authorized: %s", error->message);
 		g_error_free (error);
-		return FALSE;
+	}
+	else {
+		if (polkit_authorization_result_get_is_authorized (result)) {
+			g_debug ("result for '%s': authorized\n",
+				 data->actions[data->id]);
+			is_authorized = TRUE;
+		}
+		else if (polkit_authorization_result_get_is_challenge (result)) {
+			g_debug ("result for '%s': challenge\n",
+				 data->actions[data->id]);
+			throw_error (data->context,
+                                     GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+                                     "Authorization is required");
+		}
+		else {
+			g_debug ("result for '%s': not authorized\n",
+				 data->actions[data->id]);
+			throw_error (data->context,
+                                     GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+                                     "Not Authorized");
+		}
 	}
 
-	pk_action = polkit_action_new ();
-	polkit_action_set_action_id (pk_action, action);
-	pk_result = polkit_context_is_caller_authorized (mechanism->priv->pol_ctx, pk_action, pk_caller, TRUE, NULL);
-	polkit_caller_unref (pk_caller);
-
-	if (pk_result != POLKIT_RESULT_YES) {
-		dbus_error_init (&dbus_error);
-		polkit_dbus_error_generate (pk_action, pk_result, &dbus_error);
-		dbus_set_g_error (&error, &dbus_error);
-		dbus_g_method_return_error (context, error);
-		dbus_error_free (&dbus_error);
-		g_error_free (error);
-		polkit_action_unref (pk_action);
-		return FALSE;
+	if (is_authorized) {
+		data->id++;
+		if (data->actions[data->id] == NULL)
+			data->auth_obtained_callback (data->mechanism,
+					   	      data->context,
+						      data->user_data);
+		else {
+			check_next_action (data);
+			return; /* continue operation */
+		}
 	}
 
-	polkit_action_unref (pk_action);
-	return TRUE;
+	check_auth_data_free (data);
+	g_object_unref (result);
+	stop_operation ();
+}
+
+static void
+check_next_action (CheckAuthData *data)
+{
+	g_debug ("checking action '%s'\n", data->actions[data->id]);
+        polkit_authority_check_authorization (data->mechanism->priv->auth,
+                                              data->subject,
+                                              data->actions[data->id],
+					      NULL,
+					      data->flags,
+                                              NULL,
+                                              data->check_auth_callback,
+                                              data);
+}
+
+static void
+check_polkit_for_actions (GConfDefaults                   *mechanism,
+                          DBusGMethodInvocation           *context,
+                          gchar                          **actions,
+                          AuthObtainedCallback             auth_obtained_callback,
+                          gpointer                         user_data,
+			  GDestroyNotify                   destroy)
+{
+        CheckAuthData *data;
+
+	data = g_new0 (CheckAuthData, 1);
+	data->mechanism = g_object_ref (mechanism);
+	data->context = context;
+	data->actions = actions;
+        data->flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
+	data->id = 0;
+	data->auth_obtained_callback = auth_obtained_callback;
+	data->check_auth_callback = (GAsyncReadyCallback)check_authorization_callback;
+	data->user_data = user_data;
+	data->destroy = destroy;
+	data->subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context));
+	data->challenge = FALSE;
+
+	check_next_action (data);
 }
 
 static char *
@@ -379,7 +476,7 @@ gconf_address_for_caller (GConfDefaults          *mechanism,
 			  DBusGMethodInvocation  *context,
 			  GError                **gerror)
 {
-	char *sender;
+        char *sender;
 	DBusConnection *conn;
 	uid_t uid;
 	struct passwd *pwd;
@@ -387,7 +484,7 @@ gconf_address_for_caller (GConfDefaults          *mechanism,
 	DBusError error;
 
 	conn = dbus_g_connection_get_connection (mechanism->priv->system_bus_connection);
-	sender = dbus_g_method_get_sender (context);
+        sender = dbus_g_method_get_sender (context);
 
 	dbus_error_init (&error);
 	uid = dbus_bus_get_unix_user (conn, sender, &error);
@@ -470,56 +567,56 @@ copy_entry (GConfClient     *src,
 	}
 }
 
+typedef void (*ChangeSetCallback) (GConfDefaults  *mechanism,
+                                   GConfChangeSet *changes,
+                                   gpointer        data);
+
+typedef struct
+{
+	GConfDefaults                   *mechanism;
+	DBusGMethodInvocation           *context;
+	const char 			*dest_address;
+	char 			       **actions;
+	char            	       **includes;
+	char            	       **excludes;
+        GConfValue                      *value;
+	ChangeSetCallback 		 changeset_callback;
+	gpointer			 user_data;
+	GDestroyNotify			 destroy;
+} CopyData;
 
 static void
-do_copy (GConfDefaults          *mechanism,
-	 gboolean                mandatory,
-	 const char            **includes,
-	 const char            **excludes,
-	 DBusGMethodInvocation  *context,
-	 GConfChangeSet        **changeset_out)
+copy_data_free (gpointer user_data)
 {
-        char *address = NULL;
+	CopyData *data = user_data;
+
+	g_object_unref (data->mechanism);
+	g_strfreev (data->includes);
+	g_strfreev (data->excludes);
+	g_strfreev (data->actions);
+	if (data->value)
+		gconf_value_free (data->value);
+	if (data->destroy)
+		data->destroy (data->user_data);
+	g_free (data);
+}
+
+static void
+do_copy_authorized (GConfDefaults          *mechanism,
+                    DBusGMethodInvocation  *context,
+		    gpointer                user_data)
+{
+        CopyData    *data = user_data;
 	GConfClient *source = NULL;
 	GConfClient *dest = NULL;
 	GConfChangeSet *changes = NULL;
 	GConfEngine *engine;
+        char *address = NULL;
+        gint i;
 	GError *error;
-	GError *error2;
-	const char *action;
-	const char *annotation_key;
-	const char *default_action;
-	const char *dest_address;
-	int i;
-
-	if (changeset_out)
-		*changeset_out = NULL;
-
-        stop_killtimer ();
-
-	/* check privileges for each include */
-	if (mandatory) {
-		annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix"; 
-		default_action = "org.gnome.gconf.defaults.set-mandatory";
-		dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory";
-	}
-	else {
-		annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
-		default_action = "org.gnome.gconf.defaults.set-system";
-		dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.system";
-	}
-
-	for (i = 0; includes[i]; i++) {
-		action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]);
-		if (action == NULL)
-			action = default_action;
-
-		if (!check_polkit_for_action (mechanism, context, action))
-			goto out;
-	}
 
 	error = NULL;
-	engine = gconf_engine_get_local (dest_address, &error);
+	engine = gconf_engine_get_local (data->dest_address, &error);
 	if (error)
 		goto cleanup;
 
@@ -527,7 +624,7 @@ do_copy (GConfDefaults          *mechanism,
 	gconf_engine_unref (engine);
 
 	/* find the address to from the caller id */
-	address = gconf_address_for_caller (mechanism, context, &error);
+        address = gconf_address_for_caller (data->mechanism, data->context, &error);
 	if (error)
 		goto cleanup;
 
@@ -540,20 +637,27 @@ do_copy (GConfDefaults          *mechanism,
 
 	changes = gconf_change_set_new ();
 
- 	/* recursively copy each include, leaving out the excludes */
-	for (i = 0; includes[i]; i++) {
-		if (gconf_client_dir_exists (source, includes[i], NULL))
-			copy_tree (source, includes[i], changes, excludes);
-		else
-			copy_entry (source, includes[i], changes, excludes);
+	if (data->value) {
+		g_assert (data->includes[1] == NULL);
+                g_assert (data->excludes == NULL);
+
+		gconf_change_set_set (changes, data->includes[0], data->value);
+	}
+	else {
+	 	/* recursively copy each include, leaving out the excludes */
+		for (i = 0; data->includes[i]; i++) {
+			if (gconf_client_dir_exists (source, data->includes[i], NULL))
+				copy_tree (source, data->includes[i], changes, (const char **)data->excludes);
+			else
+				copy_entry (source, data->includes[i], changes, (const char **)data->excludes);
+		}
 	}
 
 	gconf_client_commit_change_set (dest, changes, FALSE, &error);
 	gconf_client_suggest_sync (dest, NULL);
 
-	if (changeset_out) {
-		*changeset_out = changes;
-		changes = NULL;
+	if (data->changeset_callback) {
+		data->changeset_callback (data->mechanism, changes, data->user_data);
 	}
 
 cleanup:
@@ -566,20 +670,153 @@ cleanup:
 		g_object_unref (source);
 
 	if (error) {
-		g_print ("failed to set GConf values:  %s\n", error->message);
-		error2 = g_error_new_literal (GCONF_DEFAULTS_ERROR,
-					      GCONF_DEFAULTS_ERROR_GENERAL,
-					      error->message);
+		throw_error (data->context,
+			     GCONF_DEFAULTS_ERROR_GENERAL,
+			     "%s", error->message);
 		g_error_free (error);
-
-		dbus_g_method_return_error (context, error2);
-		g_error_free (error2);
 	}
 	else
-		dbus_g_method_return (context);
+        	dbus_g_method_return (data->context);
+}
 
-out:
-	start_killtimer ();
+typedef void (*ActionsReadyCallback) (GConfDefaults          *mechanism,
+				      DBusGMethodInvocation  *context,
+				      gchar                 **actions,
+                          	      AuthObtainedCallback    auth_obtained_callback,
+				      gpointer                data,
+				      GDestroyNotify          destroy);
+
+typedef struct
+{
+	GConfDefaults 			*mechanism;
+	DBusGMethodInvocation           *context;
+	char                           **includes;
+	const char			*default_action;
+	const char			*annotation_key;
+        ActionsReadyCallback		 actions_ready_callback;
+	AuthObtainedCallback             auth_obtained_callback;
+	gpointer			 data;
+	GDestroyNotify			 destroy;
+} ActionData;
+
+static void
+action_data_free (ActionData *data)
+{
+	g_object_unref (data->mechanism);
+	g_strfreev (data->includes);
+	if (data->destroy)
+		data->destroy (data->data);
+	g_free (data);
+}
+
+static void
+actions_ready_cb (GObject      *source,
+		  GAsyncResult *res,
+		  gpointer      user_data)
+{
+	ActionData *data = user_data;
+	GList *action_descriptions;
+	GError *error = NULL;
+	int i;
+	GHashTable *obtained;
+	GHashTableIter iter;
+	const gchar *action;
+	gchar **actions;
+	gpointer key, value;
+
+	action_descriptions = polkit_authority_enumerate_actions_finish (data->mechanism->priv->auth, res, &error);
+
+	if (error) {
+		throw_error (data->context,
+                             GCONF_DEFAULTS_ERROR_GENERAL,
+                             "Failed to get action descriptions: %s", error->message);
+		g_error_free (error);
+		action_data_free (data);
+		stop_operation ();
+		return;
+	}
+
+	obtained = g_hash_table_new (g_str_hash, g_str_equal);
+
+	for (i = 0; data->includes[i]; i++) {
+		action = polkit_action_for_gconf_path (data->mechanism, action_descriptions, data->annotation_key, data->includes[i]);
+		if (action == NULL) {
+			g_debug ("using default action '%s' for path '%s'",
+				 data->default_action, data->includes[i]);
+			action = data->default_action;
+		}
+
+		g_hash_table_insert (obtained, (gpointer)action, (gpointer)action);
+	}
+	actions = g_new0 (char *, g_hash_table_size (obtained) + 1);
+	g_hash_table_iter_init (&iter, obtained);
+	i = 0;
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		actions[i] = g_strdup ((char *)key);
+		i++;
+	}
+	g_hash_table_destroy (obtained);
+	g_list_foreach (action_descriptions, (GFunc)g_object_unref, NULL);
+	g_list_free (action_descriptions);
+
+	data->actions_ready_callback (data->mechanism, data->context, actions, data->auth_obtained_callback, data->data, data->destroy);
+
+	data->destroy = NULL;
+	action_data_free (data);
+}
+
+static void
+do_copy (GConfDefaults          *mechanism,
+	 gboolean                mandatory,
+	 const gchar           **includes,
+	 const gchar           **excludes,
+	 GConfValue             *value,
+	 DBusGMethodInvocation  *context,
+	 ChangeSetCallback       changeset_callback,
+	 gpointer                user_data,
+         GDestroyNotify          destroy)
+{
+	CopyData *cdata;
+	ActionData *adata;
+
+        start_operation ();
+
+	cdata = g_new0 (CopyData, 1);
+	cdata->mechanism = g_object_ref (mechanism);
+	cdata->context = context;
+	cdata->includes = g_strdupv ((gchar **)includes);
+	cdata->excludes = g_strdupv ((gchar **)excludes);
+        cdata->value = value;
+	cdata->actions = NULL;
+	cdata->changeset_callback = changeset_callback;
+	cdata->user_data = user_data;
+	cdata->destroy = destroy;
+
+	adata = g_new0 (ActionData, 1);
+	adata->mechanism = g_object_ref (mechanism);
+	adata->context = context;
+	adata->includes = g_strdupv ((gchar **)includes);
+	adata->actions_ready_callback = check_polkit_for_actions;
+	adata->auth_obtained_callback = do_copy_authorized;
+	adata->data = cdata;
+	adata->destroy = copy_data_free;
+
+	/* check privileges for each include */
+	if (mandatory) {
+		adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+		adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+		cdata->dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory";
+	}
+	else {
+		adata->annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
+		adata->default_action = "org.gnome.gconf.defaults.set-system";
+		cdata->dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.system";
+	}
+
+        polkit_authority_enumerate_actions (mechanism->priv->auth,
+				            NULL,
+				            actions_ready_cb,
+				            adata);
 }
 
 static void
@@ -594,14 +831,12 @@ append_key (GConfChangeSet *cs,
 }
 
 static void
-emit_system_set_signal (GConfDefaults  *mechanism,
-                        GConfChangeSet *changes)
+set_system_changes (GConfDefaults  *mechanism,
+		    GConfChangeSet *changes,
+                    gpointer        data)
 {
 	GPtrArray *keys;
 
-	if (!changes)
-		return;
-
 	keys = g_ptr_array_new ();
 	gconf_change_set_foreach (changes, append_key, keys);
 	g_ptr_array_add (keys, NULL);
@@ -617,12 +852,7 @@ gconf_defaults_set_system (GConfDefaults          *mechanism,
 			   const char            **excludes,
 			   DBusGMethodInvocation  *context)
 {
-	GConfChangeSet *changes = NULL;
-
-	do_copy (mechanism, FALSE, includes, excludes, context, &changes);
-
-	emit_system_set_signal (mechanism, changes);
-	gconf_change_set_unref (changes);
+	do_copy (mechanism, FALSE, includes, excludes, NULL, context, set_system_changes, NULL, NULL);
 }
 
 void
@@ -631,120 +861,7 @@ gconf_defaults_set_mandatory (GConfDefaults          *mechanism,
                               const char            **excludes,
                               DBusGMethodInvocation  *context)
 {
-	do_copy (mechanism, FALSE, includes, excludes, context, NULL);
-}
-
-static void
-do_set_value (GConfDefaults          *mechanism,
-              gboolean                mandatory,
-              const char             *path,
-              const char             *value,
-              DBusGMethodInvocation  *context,
-              GConfChangeSet        **changeset_out)
-{
-	GConfClient *dest = NULL;
-	GConfChangeSet *changes = NULL;
-	GConfEngine *engine;
-	GConfValue *gvalue;
-	GError *error;
-	GError *error2;
-	const char *action;
-	const char *annotation_key;
-	const char *default_action;
-	const char *dest_address;
-
-	if (changeset_out)
-		*changeset_out = NULL;
-
-	stop_killtimer ();
-
-	if (mandatory) {
-		annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
-		default_action = "org.gnome.gconf.defaults.set-mandatory";
-		dest_address = "xml:merged:/etc/gconf/gconf.xml.mandatory";
-	}
-	else {
-		annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
-		default_action = "org.gnome.gconf.defaults.set-system";
-		dest_address = "xml:merged:/etc/gconf/gconf.xml.system";
-	}
-
-	action = polkit_action_for_gconf_path (mechanism, annotation_key, path);
-	if (action == NULL)
-		action = default_action;
-
-	if (!check_polkit_for_action (mechanism, context, action))
-		goto out;
-
-	error = NULL;
-	engine = gconf_engine_get_local (dest_address, &error);
-	if (error)
-		goto cleanup;
-
-	dest = gconf_client_get_for_engine (engine);
-	gconf_engine_unref (engine);
-
-	changes = gconf_change_set_new ();
-
-	gvalue = gconf_value_decode (value);
-	if (!gvalue)
-		goto cleanup;
-
-	gconf_change_set_set (changes, path, gvalue);
-	gconf_value_free (gvalue);
-
-	gconf_client_commit_change_set (dest, changes, FALSE, &error);
-	gconf_client_suggest_sync (dest, NULL);
-
-	if (changeset_out) {
-		*changeset_out = changes;
-		changes = NULL;
-	}
-
-cleanup:
-	if (changes)
-		gconf_change_set_unref (changes);
-	if (dest)
-		g_object_unref (dest);
-
-	if (error) {
-		g_print ("failed to set GConf values:  %s\n", error->message);
-		error2 = g_error_new_literal (GCONF_DEFAULTS_ERROR,
-					      GCONF_DEFAULTS_ERROR_GENERAL,
-					      error->message);
-		g_error_free (error);
-
-		dbus_g_method_return_error (context, error2);
-		g_error_free (error2);
-	}
-	else
-		dbus_g_method_return (context);
-
-out:
-	start_killtimer ();
-}
-
-void
-gconf_defaults_set_system_value (GConfDefaults         *mechanism,
-                                 const char            *path,
-                                 const char            *value,
-                                 DBusGMethodInvocation *context)
-{
-	GConfChangeSet *changes = NULL;
-
-	do_set_value (mechanism, FALSE, path, value, context, &changes);
-
-        emit_system_set_signal (mechanism, changes);
-	gconf_change_set_unref (changes);
-}
-
-void
-gconf_defaults_set_mandatory_value (GConfDefaults         *mechanism,
-                                    const char            *path,
-                                    const char            *value,
-                                    DBusGMethodInvocation *context)
-{
-	do_set_value (mechanism, TRUE, path, value, context, NULL);
+	do_copy (mechanism, TRUE, includes, excludes, NULL, context, NULL, NULL, NULL);
 }
 
 static void
@@ -756,13 +873,13 @@ unset_tree (GConfClient     *dest,
 	GSList *list, *l;
 	GConfEntry *entry;
 
-	if (path_is_excluded (path, excludes)) 
+	if (path_is_excluded (path, excludes))
 		return;
 
 	list = gconf_client_all_entries (dest, path, NULL);
 	for (l = list; l; l = l->next) {
 		entry = l->data;
-		if (!path_is_excluded (entry->key, excludes)) 
+		if (!path_is_excluded (entry->key, excludes))
 			gconf_change_set_unset (changes, entry->key);
 	}
 	g_slist_foreach (list, (GFunc)gconf_entry_free, NULL);
@@ -774,25 +891,25 @@ unset_tree (GConfClient     *dest,
 	g_slist_foreach (list, (GFunc)g_free, NULL);
 	g_slist_free (list);
 }
-            
+
 static void
 unset_entry (GConfClient     *dest,
              const char      *path,
 	     GConfChangeSet  *changes,
              const char     **excludes)
 {
-	if (path_is_excluded (path, excludes)) 
+	if (path_is_excluded (path, excludes))
 		return;
 
 	gconf_change_set_unset (changes, path);
 }
-            
+
 static void
-unset_in_db (GConfDefaults  *mechanism,
-	     const char     *address,
-             const char    **includes,
-             const char    **excludes,
-	     GError        **error)
+unset_in_db (GConfDefaults   *mechanism,
+	     const gchar     *address,
+             const gchar    **includes,
+             const gchar    **excludes,
+	     GError         **error)
 {
 	GConfEngine *engine;
 	GConfClient *dest = NULL;
@@ -800,7 +917,7 @@ unset_in_db (GConfDefaults  *mechanism,
 	int i;
 
 	engine = gconf_engine_get_local (address, error);
-	if (*error) 
+	if (*error)
 		goto out;
 
 	dest = gconf_client_get_for_engine (engine);
@@ -826,48 +943,256 @@ out:
 		gconf_change_set_unref (changes);
 }
 
+typedef struct
+{
+	GConfDefaults          *mechanism;
+        DBusGMethodInvocation  *context;
+        char                  **includes;
+        char                  **excludes;
+} UnsetData;
+
+static void
+unset_data_free (gpointer user_data)
+{
+	UnsetData *data = user_data;
+
+	g_object_unref (data->mechanism);
+	g_strfreev (data->includes);
+	g_strfreev (data->excludes);
+	g_free (data);
+}
+
+static void
+do_unset_authorized (GConfDefaults          *mechanism,
+                     DBusGMethodInvocation  *context,
+		     gpointer 		     user_data)
+{
+        UnsetData *data = user_data;
+	GError *error;
+
+	error = NULL;
+	unset_in_db (mechanism, "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory", 
+		     (const gchar **)data->includes,
+		     (const gchar **)data->excludes, &error);
+
+	if (error) {
+		throw_error (data->context,
+			     GCONF_DEFAULTS_ERROR,
+			     GCONF_DEFAULTS_ERROR_GENERAL,
+			     "%s", error->message);
+		g_error_free (error);
+	}
+	else
+        	dbus_g_method_return (data->context);
+}
+
 void
 gconf_defaults_unset_mandatory (GConfDefaults          *mechanism,
                                 const char            **includes,
                                 const char            **excludes,
                                 DBusGMethodInvocation  *context)
 {
-	const char *annotation_key;
-	const char *default_action;
-	int i;
-	const char *action;
+	UnsetData *udata;
+	ActionData *adata;
+
+	start_operation ();
+
+	udata = g_new0 (UnsetData, 1);
+	udata->mechanism = g_object_ref (mechanism);
+	udata->context = context;
+	udata->includes = g_strdupv ((gchar **)includes);
+	udata->excludes = g_strdupv ((gchar **)excludes);
+
+	adata = g_new0 (ActionData, 1);
+	adata->mechanism = g_object_ref (mechanism);
+	adata->context = context;
+	adata->includes = g_strdupv ((gchar **)includes);
+	adata->auth_obtained_callback = do_unset_authorized;
+	adata->data = udata;
+	adata->destroy = unset_data_free;
+
+	adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+	adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+
+	polkit_authority_enumerate_actions (mechanism->priv->auth,
+					    NULL,
+					    actions_ready_cb,
+					    adata);
+}
+
+static void
+check_authorization_only_callback (PolkitAuthority *authority,
+                                   GAsyncResult    *res,
+                                   gpointer         user_data)
+{
+	CheckAuthData *data = user_data;
+	PolkitAuthorizationResult *result;
 	GError *error;
-	GError *error2;
+	gboolean is_authorized;
 
-	stop_killtimer ();
+	is_authorized = FALSE;
 
-	annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix"; 
-	default_action = "org.gnome.gconf.defaults.set-mandatory";
+	error = NULL;
+	result = polkit_authority_check_authorization_finish (authority,
+							      res,
+							      &error);
+	if (error != NULL) {
+		g_debug ("error checking action '%s'\n", error->message);
+		throw_error (data->context,
+                             GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+                             "Not Authorized: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+	else {
+		if (polkit_authorization_result_get_is_authorized (result)) {
+                        g_debug ("result for '%s': authorized\n",
+                                 data->actions[data->id]);
+			is_authorized = TRUE;
+		}
+		else if (polkit_authorization_result_get_is_challenge (result)) {
+			g_debug ("result for '%s': challenge\n",
+                                 data->actions[data->id]);
+			is_authorized = TRUE;
+			data->challenge = TRUE;
+		}
+		else {
+			g_debug ("result for '%s': not authorized\n",
+                                 data->actions[data->id]);
+			is_authorized = FALSE;
+		}
+	}
 
-	for (i = 0; includes[i]; i++) {
-		action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]);
-		if (action == NULL) 
-			action = default_action;
+	if (is_authorized) {
+		data->id++;
+		if (data->actions[data->id] == NULL) {
+			gint result;
 
-		if (!check_polkit_for_action (mechanism, context, action)) 
-			goto out;
+			result = data->challenge ? 1 : 2;
+			g_debug ("return %d\n", result);
+			dbus_g_method_return (data->context, result);
+		}
+		else {
+			check_next_action (data);
+			return; /* continue operation */
+		}
+	}
+	else {
+		g_debug ("return 0\n");
+		dbus_g_method_return (data->context, 0);
 	}
 
-	error = NULL;
-	unset_in_db (mechanism, "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory", 
-		     includes, excludes, &error);
+out:
+	check_auth_data_free (data);
+	g_object_unref (result);
+	stop_operation ();
+}
 
-	if (error) {
-		error2 = g_error_new_literal (GCONF_DEFAULTS_ERROR,
-					      GCONF_DEFAULTS_ERROR_GENERAL,
-					      error->message);
-		g_error_free (error);
+static void
+check_permissions_only (GConfDefaults                   *mechanism,
+                        DBusGMethodInvocation           *context,
+                        gchar                          **actions,
+                        AuthObtainedCallback             auth_obtained_callback,
+                        gpointer                         user_data,
+ 	 		GDestroyNotify                   destroy)
+{
+        CheckAuthData *data;
+
+	data = g_new0 (CheckAuthData, 1);
+	data->mechanism = g_object_ref (mechanism);
+	data->context = context;
+	data->actions = actions;
+	data->flags = 0;
+	data->id = 0;
+	data->check_auth_callback = (GAsyncReadyCallback)check_authorization_only_callback;
+	data->auth_obtained_callback = NULL;
+	data->user_data = NULL;
+	data->destroy = NULL;
+	data->subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context));
+	data->challenge = FALSE;
+
+	check_next_action (data);
+}
+
+static void
+do_check (GConfDefaults          *mechanism,
+          gboolean                mandatory,
+          const gchar           **includes,
+          DBusGMethodInvocation  *context)
+{
+	ActionData *adata;
+
+	start_operation ();
 
-		dbus_g_method_return_error (context, error2);
-		g_error_free (error2);
+	adata = g_new0 (ActionData, 1);
+	adata->mechanism = g_object_ref (mechanism);
+	adata->context = context;
+	adata->includes = g_strdupv ((gchar **)includes);
+	adata->actions_ready_callback = check_permissions_only;
+	adata->auth_obtained_callback = NULL;
+	adata->data = NULL;
+	adata->destroy = NULL;
+
+	if (mandatory) {
+		adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+		adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+	}
+	else {
+		adata->annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
+		adata->default_action = "org.gnome.gconf.defaults.set-system";
+	}
+
+	polkit_authority_enumerate_actions (mechanism->priv->auth,
+					    NULL,
+					    actions_ready_cb,
+					    adata);
+}
+
+void
+gconf_defaults_can_set_system (GConfDefaults          *mechanism,
+			       const char            **includes,
+			       DBusGMethodInvocation  *context)
+{
+	do_check (mechanism, FALSE, includes, context);
+}
+
+void
+gconf_defaults_can_set_mandatory (GConfDefaults          *mechanism,
+			          const char            **includes,
+			          DBusGMethodInvocation  *context)
+{
+	do_check (mechanism, TRUE, includes, context);
+}
+
+void
+gconf_defaults_set_system_value (GConfDefaults         *mechanism,
+                                 const char            *path,
+                                 const char            *value,
+                                 DBusGMethodInvocation *context)
+{
+	GConfValue *gvalue;
+ 	const char *includes[] = { NULL, NULL };
+
+	gvalue = gconf_value_decode (value);
+	if (gvalue) {
+		includes[0] = path;
+		do_copy (mechanism, FALSE, includes, NULL, gvalue, context, set_system_changes, NULL, NULL);
+	}
+}
+
+void
+gconf_defaults_set_mandatory_value (GConfDefaults         *mechanism,
+                                    const char            *path,
+                                    const char            *value,
+                                    DBusGMethodInvocation *context)
+{
+	GConfValue *gvalue;
+ 	const char *includes[] = { NULL, NULL };
+
+	gvalue = gconf_value_decode (value);
+	if (gvalue) {
+		includes[0] = path;
+		do_copy (mechanism, TRUE, includes, NULL, gvalue, context, NULL, NULL, NULL);
 	}
-	else
-        	dbus_g_method_return (context);
-out:
-	start_killtimer();
 }
+
diff --git a/defaults/gconf-defaults.h b/defaults/gconf-defaults.h
index 2194828..6f71814 100644
--- a/defaults/gconf-defaults.h
+++ b/defaults/gconf-defaults.h
@@ -93,6 +93,14 @@ void           gconf_defaults_unset_mandatory     (GConfDefaults          *mecha
                                                    const char            **excludes,
                                                    DBusGMethodInvocation  *context);
 
+void		gconf_defaults_can_set_system    (GConfDefaults         *mechanism,
+						  const char	       **includes,
+                                                  DBusGMethodInvocation  *context);
+
+void		gconf_defaults_can_set_mandatory (GConfDefaults         *mechanism,
+						  const char	       **includes,
+                                                  DBusGMethodInvocation  *context);
+
 G_END_DECLS
 
 #endif /* GCONF_DEFAULTS_H */
diff --git a/defaults/gconf-defaults.xml b/defaults/gconf-defaults.xml
index 683c094..03340bd 100644
--- a/defaults/gconf-defaults.xml
+++ b/defaults/gconf-defaults.xml
@@ -38,6 +38,12 @@
       <arg name="value" direction="in" type="s"/>
     </method>
 
+    <method name="CanSetSystem">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg name="includes" direction="in" type="as"/>
+      <arg name="result" direction="out" type="u"/>
+     </method>
+
     <signal name="SystemSet">
       <arg name="keys" type="as"/>
     </signal>
@@ -93,6 +99,12 @@
       <arg name="includes" direction="in" type="as"/>
       <arg name="excludes" direction="in" type="as"/>
     </method>
-   
+
+    <method name="CanSetMandatory">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg name="includes" direction="in" type="as"/>
+      <arg name="result" direction="out" type="u"/>
+    </method>
+
   </interface>
 </node>



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