summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2008-11-13 16:55:45 +0000
committerRichard Hughes <richard@hughsie.com>2008-11-13 16:55:45 +0000
commitb71c61335a2c5af679feab0d681826506b81180c (patch)
tree2973e92da21206b4a429a566eb6c6f7ac8c18026 /src
parentd891912126a45a22184c694781830e8f8c90f014 (diff)
split out the polkit code from the daemon so it can be used in other modules without passing the daemon ref around
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/dkp-daemon.c414
-rw-r--r--src/dkp-daemon.h14
-rw-r--r--src/dkp-polkit.c301
-rw-r--r--src/dkp-polkit.h62
5 files changed, 484 insertions, 308 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7d7c2b4..d8f57a2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -56,6 +56,7 @@ dbusif_DATA = \
devkit_power_daemon_SOURCES = \
egg-debug.c \
egg-debug.h \
+ dkp-polkit.h dkp-polkit.c \
dkp-daemon.h dkp-daemon.c \
dkp-device.h dkp-device.c \
dkp-device-list.h dkp-device-list.c \
diff --git a/src/dkp-daemon.c b/src/dkp-daemon.c
index e4d50a2..1d95f2f 100644
--- a/src/dkp-daemon.c
+++ b/src/dkp-daemon.c
@@ -1,6 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 David Zeuthen <davidz@redhat.com>
+ * Copyright (C) 2008 Richard Hughes <richard@hughsie.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
@@ -34,6 +35,7 @@
#include "egg-debug.h"
#include "egg-string.h"
+#include "dkp-polkit.h"
#include "dkp-daemon.h"
#include "dkp-device.h"
#include "dkp-supply.h"
@@ -70,15 +72,12 @@ static guint signals[LAST_SIGNAL] = { 0 };
struct DkpDaemonPrivate
{
- DBusGConnection *system_bus_connection;
- DBusGProxy *system_bus_proxy;
- PolKitContext *pk_context;
- PolKitTracker *pk_tracker;
-
+ DBusGConnection *connection;
+ DBusGProxy *proxy;
+ DkpPolkit *polkit;
DkpDeviceList *list;
gboolean on_battery;
gboolean low_battery;
-
DevkitClient *devkit_client;
};
@@ -284,6 +283,7 @@ static void
dkp_daemon_init (DkpDaemon *daemon)
{
daemon->priv = DKP_DAEMON_GET_PRIVATE (daemon);
+ daemon->priv->polkit = dkp_polkit_new ();
}
/**
@@ -301,88 +301,19 @@ dkp_daemon_finalize (GObject *object)
g_return_if_fail (daemon->priv != NULL);
- if (daemon->priv->pk_context != NULL)
- polkit_context_unref (daemon->priv->pk_context);
- if (daemon->priv->pk_tracker != NULL)
- polkit_tracker_unref (daemon->priv->pk_tracker);
- if (daemon->priv->system_bus_proxy != NULL)
- g_object_unref (daemon->priv->system_bus_proxy);
- if (daemon->priv->system_bus_connection != NULL)
- dbus_g_connection_unref (daemon->priv->system_bus_connection);
+ if (daemon->priv->proxy != NULL)
+ g_object_unref (daemon->priv->proxy);
+ if (daemon->priv->connection != NULL)
+ dbus_g_connection_unref (daemon->priv->connection);
if (daemon->priv->devkit_client != NULL)
g_object_unref (daemon->priv->devkit_client);
if (daemon->priv->list != NULL)
g_object_unref (daemon->priv->list);
+ g_object_unref (daemon->priv->polkit);
G_OBJECT_CLASS (dkp_daemon_parent_class)->finalize (object);
}
-/**
- * pk_io_watch_have_data:
- **/
-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;
-}
-
-/**
- * pk_io_add_watch:
- **/
-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;
-}
-
-/**
- * pk_io_remove_watch:
- **/
-static void
-pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
-{
- g_source_remove (watch_id);
-}
-
-/**
- * gpk_daemon_dbus_filter:
- **/
-static DBusHandlerResult
-gpk_daemon_dbus_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
-{
- DkpDaemon *daemon = DKP_DAEMON (user_data);
- const gchar *interface;
-
- interface = dbus_message_get_interface (message);
-
- /* pass NameOwnerChanged signals from the bus to PolKitTracker */
- if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
- polkit_tracker_dbus_func (daemon->priv->pk_tracker, message);
-
- /* pass ConsoleKit signals to PolKitTracker */
- if (interface != NULL && g_str_has_prefix (interface, "org.freedesktop.ConsoleKit"))
- polkit_tracker_dbus_func (daemon->priv->pk_tracker, message);
-
- /* other filters might want to process this message too */
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
static gboolean gpk_daemon_device_add (DkpDaemon *daemon, DevkitDevice *d, gboolean emit_event);
static void gpk_daemon_device_remove (DkpDaemon *daemon, DevkitDevice *d);
@@ -631,206 +562,6 @@ gpk_daemon_device_event_signal_handler (DevkitClient *client, const char *action
}
}
-/**
- * gpk_daemon_register_power_daemon:
- **/
-static gboolean
-gpk_daemon_register_power_daemon (DkpDaemon *daemon)
-{
- DBusConnection *connection;
- DBusError dbus_error;
- GError *error = NULL;
- guint i;
-
- daemon->priv->pk_context = polkit_context_new ();
- polkit_context_set_io_watch_functions (daemon->priv->pk_context, pk_io_add_watch, pk_io_remove_watch);
- if (!polkit_context_init (daemon->priv->pk_context, NULL)) {
- g_critical ("cannot initialize libpolkit");
- goto error;
- }
-
- error = NULL;
- daemon->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
- if (daemon->priv->system_bus_connection == NULL) {
- if (error != NULL) {
- g_critical ("error getting system bus: %s", error->message);
- g_error_free (error);
- }
- goto error;
- }
- connection = dbus_g_connection_get_connection (daemon->priv->system_bus_connection);
-
- daemon->priv->pk_tracker = polkit_tracker_new ();
- polkit_tracker_set_system_bus_connection (daemon->priv->pk_tracker, connection);
- polkit_tracker_init (daemon->priv->pk_tracker);
-
- dbus_g_connection_register_g_object (daemon->priv->system_bus_connection,
- "/org/freedesktop/DeviceKit/Power",
- G_OBJECT (daemon));
-
- daemon->priv->system_bus_proxy = dbus_g_proxy_new_for_name (daemon->priv->system_bus_connection,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
-
- /* TODO FIXME: I'm pretty sure dbus-glib blows in a way that
- * we can't say we're interested in all signals from all
- * members on all interfaces for a given service... So we do
- * this..
- */
-
- dbus_error_init (&dbus_error);
-
- /* need to listen to NameOwnerChanged */
- dbus_bus_add_match (connection,
- "type='signal'"
- ",interface='"DBUS_INTERFACE_DBUS"'"
- ",sender='"DBUS_SERVICE_DBUS"'"
- ",member='NameOwnerChanged'",
- &dbus_error);
-
- if (dbus_error_is_set (&dbus_error)) {
- egg_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
- dbus_error_free (&dbus_error);
- goto error;
- }
-
- /* need to listen to ConsoleKit signals */
- dbus_bus_add_match (connection,
- "type='signal',sender='org.freedesktop.ConsoleKit'",
- &dbus_error);
-
- if (dbus_error_is_set (&dbus_error)) {
- egg_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
- dbus_error_free (&dbus_error);
- goto error;
- }
-
- if (!dbus_connection_add_filter (connection,
- gpk_daemon_dbus_filter,
- daemon,
- NULL)) {
- egg_warning ("Cannot add D-Bus filter: %s: %s", dbus_error.name, dbus_error.message);
- goto error;
- }
-
- /* connect to the DeviceKit daemon */
- for (i=0; subsystems[i] != NULL; i++)
- egg_debug ("registering subsystem : %s", subsystems[i]);
- daemon->priv->devkit_client = devkit_client_new (subsystems);
- if (!devkit_client_connect (daemon->priv->devkit_client, &error)) {
- egg_warning ("Couldn't open connection to DeviceKit daemon: %s", error->message);
- g_error_free (error);
- goto error;
- }
- g_signal_connect (daemon->priv->devkit_client, "device-event",
- G_CALLBACK (gpk_daemon_device_event_signal_handler), daemon);
-
- return TRUE;
-error:
- return FALSE;
-}
-
-/**
- * dkp_daemon_new:
- **/
-DkpDaemon *
-dkp_daemon_new (void)
-{
- DkpDaemon *daemon;
- GError *error = NULL;
- GList *devices;
- GList *l;
-
- daemon = DKP_DAEMON (g_object_new (DKP_TYPE_DAEMON, NULL));
-
- daemon->priv->list = dkp_device_list_new ();
- if (!gpk_daemon_register_power_daemon (DKP_DAEMON (daemon))) {
- g_object_unref (daemon);
- return NULL;
- }
-
- devices = devkit_client_enumerate_by_subsystem (daemon->priv->devkit_client, subsystems, &error);
- if (error != NULL) {
- egg_warning ("Cannot enumerate devices: %s", error->message);
- g_error_free (error);
- g_object_unref (daemon);
- return NULL;
- }
-
- for (l = devices; l != NULL; l = l->next) {
- DevkitDevice *device = l->data;
- gpk_daemon_device_add (daemon, device, FALSE);
- }
- g_list_foreach (devices, (GFunc) g_object_unref, NULL);
- g_list_free (devices);
-
- daemon->priv->on_battery = dkp_daemon_get_on_battery_local (daemon);
- daemon->priv->low_battery = dkp_daemon_get_low_battery_local (daemon);
-
- return daemon;
-}
-
-/**
- * dkp_daemon_local_get_caller_for_context:
- **/
-PolKitCaller *
-dkp_daemon_local_get_caller_for_context (DkpDaemon *daemon, DBusGMethodInvocation *context)
-{
- const gchar *sender;
- GError *error;
- DBusError dbus_error;
- PolKitCaller *pk_caller;
-
- sender = dbus_g_method_get_sender (context);
- dbus_error_init (&dbus_error);
- pk_caller = polkit_tracker_get_caller_from_dbus_name (daemon->priv->pk_tracker,
- sender,
- &dbus_error);
- if (pk_caller == NULL) {
- error = g_error_new (DKP_DAEMON_ERROR,
- DKP_DAEMON_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);
- g_error_free (error);
- return NULL;
- }
-
- return pk_caller;
-}
-
-/**
- * dkp_daemon_local_check_auth:
- **/
-gboolean
-dkp_daemon_local_check_auth (DkpDaemon *daemon, PolKitCaller *pk_caller, const char *action_id, DBusGMethodInvocation *context)
-{
- gboolean ret = FALSE;
- GError *error;
- DBusError d_error;
- PolKitAction *pk_action;
- PolKitResult pk_result;
-
- pk_action = polkit_action_new ();
- polkit_action_set_action_id (pk_action, action_id);
- pk_result = polkit_context_is_caller_authorized (daemon->priv->pk_context, pk_action, pk_caller, TRUE, NULL);
- if (pk_result == POLKIT_RESULT_YES) {
- ret = TRUE;
- } else {
- dbus_error_init (&d_error);
- polkit_dbus_error_generate (pk_action, pk_result, &d_error);
- error = NULL;
- dbus_set_g_error (&error, &d_error);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- dbus_error_free (&d_error);
- }
- polkit_action_unref (pk_action);
- return ret;
-}
-
#if 0
/**
* gpk_daemon_throw_error:
@@ -846,9 +577,7 @@ gpk_daemon_throw_error (DBusGMethodInvocation *context, int error_code, const ch
message = g_strdup_vprintf (format, args);
va_end (args);
- error = g_error_new (DKP_DAEMON_ERROR,
- error_code,
- message);
+ error = g_error_new (DKP_DAEMON_ERROR, error_code, message);
dbus_g_method_return_error (context, error);
g_error_free (error);
g_free (message);
@@ -895,13 +624,13 @@ dkp_daemon_suspend (DkpDaemon *daemon, DBusGMethodInvocation *context)
gboolean ret;
GError *error;
GError *error_local = NULL;
- PolKitCaller *pk_caller;
+ PolKitCaller *caller;
- pk_caller = dkp_daemon_local_get_caller_for_context (daemon, context);
- if (pk_caller == NULL)
+ caller = dkp_polkit_get_caller (daemon->priv->polkit, context);
+ if (caller == NULL)
goto out;
- if (!dkp_daemon_local_check_auth (daemon, pk_caller, "org.freedesktop.devicekit.power.suspend", context))
+ if (!dkp_polkit_check_auth (daemon->priv->polkit, caller, "org.freedesktop.devicekit.power.suspend", context))
goto out;
ret = g_spawn_command_line_async ("/usr/sbin/pm-suspend", &error_local);
@@ -915,8 +644,8 @@ dkp_daemon_suspend (DkpDaemon *daemon, DBusGMethodInvocation *context)
}
dbus_g_method_return (context, NULL);
out:
- if (pk_caller != NULL)
- polkit_caller_unref (pk_caller);
+ if (caller != NULL)
+ polkit_caller_unref (caller);
return TRUE;
}
@@ -929,13 +658,13 @@ dkp_daemon_hibernate (DkpDaemon *daemon, DBusGMethodInvocation *context)
gboolean ret;
GError *error;
GError *error_local = NULL;
- PolKitCaller *pk_caller;
+ PolKitCaller *caller;
- pk_caller = dkp_daemon_local_get_caller_for_context (daemon, context);
- if (pk_caller == NULL)
+ caller = dkp_polkit_get_caller (daemon->priv->polkit, context);
+ if (caller == NULL)
goto out;
- if (!dkp_daemon_local_check_auth (daemon, pk_caller, "org.freedesktop.devicekit.power.hibernate", context))
+ if (!dkp_polkit_check_auth (daemon->priv->polkit, caller, "org.freedesktop.devicekit.power.hibernate", context))
goto out;
ret = g_spawn_command_line_async ("/usr/sbin/pm-hibernate", &error_local);
@@ -949,8 +678,103 @@ dkp_daemon_hibernate (DkpDaemon *daemon, DBusGMethodInvocation *context)
}
dbus_g_method_return (context, NULL);
out:
- if (pk_caller != NULL)
- polkit_caller_unref (pk_caller);
+ if (caller != NULL)
+ polkit_caller_unref (caller);
return TRUE;
}
+/**
+ * gpk_daemon_register_power_daemon:
+ **/
+static gboolean
+gpk_daemon_register_power_daemon (DkpDaemon *daemon)
+{
+ DBusConnection *connection;
+ DBusError dbus_error;
+ GError *error = NULL;
+ guint i;
+
+ error = NULL;
+ daemon->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (daemon->priv->connection == NULL) {
+ if (error != NULL) {
+ g_critical ("error getting system bus: %s", error->message);
+ g_error_free (error);
+ }
+ goto error;
+ }
+ connection = dbus_g_connection_get_connection (daemon->priv->connection);
+
+ dbus_g_connection_register_g_object (daemon->priv->connection,
+ "/org/freedesktop/DeviceKit/Power",
+ G_OBJECT (daemon));
+
+ daemon->priv->proxy = dbus_g_proxy_new_for_name (daemon->priv->connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ dbus_error_init (&dbus_error);
+ if (dbus_error_is_set (&dbus_error)) {
+ egg_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto error;
+ }
+
+ /* connect to the DeviceKit daemon */
+ for (i=0; subsystems[i] != NULL; i++)
+ egg_debug ("registering subsystem : %s", subsystems[i]);
+
+ daemon->priv->devkit_client = devkit_client_new (subsystems);
+ if (!devkit_client_connect (daemon->priv->devkit_client, &error)) {
+ egg_warning ("Couldn't open connection to DeviceKit daemon: %s", error->message);
+ g_error_free (error);
+ goto error;
+ }
+ g_signal_connect (daemon->priv->devkit_client, "device-event",
+ G_CALLBACK (gpk_daemon_device_event_signal_handler), daemon);
+
+ return TRUE;
+error:
+ return FALSE;
+}
+
+/**
+ * dkp_daemon_new:
+ **/
+DkpDaemon *
+dkp_daemon_new (void)
+{
+ DkpDaemon *daemon;
+ GError *error = NULL;
+ GList *devices;
+ GList *l;
+
+ daemon = DKP_DAEMON (g_object_new (DKP_TYPE_DAEMON, NULL));
+
+ daemon->priv->list = dkp_device_list_new ();
+ if (!gpk_daemon_register_power_daemon (DKP_DAEMON (daemon))) {
+ g_object_unref (daemon);
+ return NULL;
+ }
+
+ devices = devkit_client_enumerate_by_subsystem (daemon->priv->devkit_client, subsystems, &error);
+ if (error != NULL) {
+ egg_warning ("Cannot enumerate devices: %s", error->message);
+ g_error_free (error);
+ g_object_unref (daemon);
+ return NULL;
+ }
+
+ for (l = devices; l != NULL; l = l->next) {
+ DevkitDevice *device = l->data;
+ gpk_daemon_device_add (daemon, device, FALSE);
+ }
+ g_list_foreach (devices, (GFunc) g_object_unref, NULL);
+ g_list_free (devices);
+
+ daemon->priv->on_battery = dkp_daemon_get_on_battery_local (daemon);
+ daemon->priv->low_battery = dkp_daemon_get_low_battery_local (daemon);
+
+ return daemon;
+}
+
diff --git a/src/dkp-daemon.h b/src/dkp-daemon.h
index 9797cac..b7a5c41 100644
--- a/src/dkp-daemon.h
+++ b/src/dkp-daemon.h
@@ -28,7 +28,7 @@
G_BEGIN_DECLS
#define DKP_TYPE_DAEMON (dkp_daemon_get_type ())
-#define DKP_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_DAEMON, DkpDaemon))
+#define DKP_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_DAEMON, DkpDaemon))
#define DKP_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_TYPE_DAEMON, DkpDaemonClass))
#define DKP_IS_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_TYPE_DAEMON))
#define DKP_IS_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_TYPE_DAEMON))
@@ -63,18 +63,6 @@ GType dkp_daemon_error_get_type (void);
GQuark dkp_daemon_error_quark (void);
GType dkp_daemon_get_type (void);
DkpDaemon *dkp_daemon_new (void);
-
-/* local methods */
-
-PolKitCaller *dkp_daemon_local_get_caller_for_context (DkpDaemon *daemon,
- DBusGMethodInvocation *context);
-
-gboolean dkp_daemon_local_check_auth (DkpDaemon *daemon,
- PolKitCaller *pk_caller,
- const char *action_id,
- DBusGMethodInvocation *context);
-
-/* exported methods */
gboolean dkp_daemon_enumerate_devices (DkpDaemon *daemon,
DBusGMethodInvocation *context);
gboolean dkp_daemon_get_on_battery (DkpDaemon *daemon,
diff --git a/src/dkp-polkit.c b/src/dkp-polkit.c
new file mode 100644
index 0000000..101b84a
--- /dev/null
+++ b/src/dkp-polkit.c
@@ -0,0 +1,301 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 David Zeuthen <davidz@redhat.com>
+ * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit/polkit.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+#include "egg-debug.h"
+
+#include "dkp-polkit.h"
+#include "dkp-daemon.h"
+
+#define DKP_POLKIT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_TYPE_POLKIT, DkpPolkitPrivate))
+
+struct DkpPolkitPrivate
+{
+ DBusGConnection *connection;
+ PolKitContext *context;
+ PolKitTracker *tracker;
+};
+
+G_DEFINE_TYPE (DkpPolkit, dkp_polkit, G_TYPE_OBJECT)
+static gpointer dkp_polkit_object = NULL;
+
+/**
+ * pk_polkit_io_watch_have_data:
+ **/
+static gboolean
+pk_polkit_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+ int fd;
+ PolKitContext *context = user_data;
+ fd = g_io_channel_unix_get_fd (channel);
+ polkit_context_io_func (context, fd);
+ return TRUE;
+}
+
+/**
+ * pk_polkit_io_add_watch:
+ **/
+static int
+pk_polkit_io_add_watch (PolKitContext *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_polkit_io_watch_have_data, context);
+ if (id == 0) {
+ g_io_channel_unref (channel);
+ goto out;
+ }
+ g_io_channel_unref (channel);
+out:
+ return id;
+}
+
+/**
+ * pk_polkit_io_remove_watch:
+ **/
+static void
+pk_polkit_io_remove_watch (PolKitContext *context, int watch_id)
+{
+ g_source_remove (watch_id);
+}
+
+/**
+ * gpk_polkit_dbus_filter:
+ **/
+static DBusHandlerResult
+gpk_polkit_dbus_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ DkpPolkit *polkit = DKP_POLKIT (user_data);
+ const gchar *interface;
+
+ interface = dbus_message_get_interface (message);
+
+ /* pass NameOwnerChanged signals from the bus to PolKitTracker */
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
+ polkit_tracker_dbus_func (polkit->priv->tracker, message);
+
+ /* pass ConsoleKit signals to PolKitTracker */
+ if (interface != NULL && g_str_has_prefix (interface, "org.freedesktop.ConsoleKit"))
+ polkit_tracker_dbus_func (polkit->priv->tracker, message);
+
+ /* other filters might want to process this message too */
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/**
+ * dkp_polkit_get_caller:
+ **/
+PolKitCaller *
+dkp_polkit_get_caller (DkpPolkit *polkit, DBusGMethodInvocation *context)
+{
+ const gchar *sender;
+ GError *error;
+ DBusError dbus_error;
+ PolKitCaller *caller;
+
+ sender = dbus_g_method_get_sender (context);
+ dbus_error_init (&dbus_error);
+ caller = polkit_tracker_get_caller_from_dbus_name (polkit->priv->tracker, sender, &dbus_error);
+ if (caller == NULL) {
+ error = g_error_new (DKP_DAEMON_ERROR,
+ DKP_DAEMON_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);
+ g_error_free (error);
+ return NULL;
+ }
+
+ return caller;
+}
+
+/**
+ * dkp_polkit_check_auth:
+ **/
+gboolean
+dkp_polkit_check_auth (DkpPolkit *polkit, PolKitCaller *caller, const gchar *action_id, DBusGMethodInvocation *context)
+{
+ gboolean ret = FALSE;
+ GError *error;
+ DBusError dbus_error;
+ PolKitAction *action;
+ PolKitResult result;
+
+ action = polkit_action_new ();
+ polkit_action_set_action_id (action, action_id);
+ result = polkit_context_is_caller_authorized (polkit->priv->context, action, caller, TRUE, NULL);
+ if (result == POLKIT_RESULT_YES) {
+ ret = TRUE;
+ } else {
+ dbus_error_init (&dbus_error);
+ polkit_dbus_error_generate (action, result, &dbus_error);
+ error = NULL;
+ dbus_set_g_error (&error, &dbus_error);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ dbus_error_free (&dbus_error);
+ }
+ polkit_action_unref (action);
+ return ret;
+}
+
+/**
+ * dkp_polkit_finalize:
+ **/
+static void
+dkp_polkit_finalize (GObject *object)
+{
+ DkpPolkit *polkit;
+ g_return_if_fail (DKP_IS_POLKIT (object));
+ polkit = DKP_POLKIT (object);
+
+ if (polkit->priv->connection != NULL)
+ dbus_g_connection_unref (polkit->priv->connection);
+ if (polkit->priv->tracker != NULL)
+ polkit_tracker_unref (polkit->priv->tracker);
+ polkit_context_unref (polkit->priv->context);
+
+ G_OBJECT_CLASS (dkp_polkit_parent_class)->finalize (object);
+}
+
+/**
+ * dkp_polkit_class_init:
+ **/
+static void
+dkp_polkit_class_init (DkpPolkitClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = dkp_polkit_finalize;
+ g_type_class_add_private (klass, sizeof (DkpPolkitPrivate));
+}
+
+/**
+ * dkp_polkit_init:
+ *
+ * initializes the polkit class. NOTE: We expect polkit objects
+ * to *NOT* be removed or added during the session.
+ * We only control the first polkit object if there are more than one.
+ **/
+static void
+dkp_polkit_init (DkpPolkit *polkit)
+{
+
+ DBusConnection *connection;
+ DBusError dbus_error;
+ GError *error = NULL;
+
+ polkit->priv = DKP_POLKIT_GET_PRIVATE (polkit);
+
+ error = NULL;
+ polkit->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (polkit->priv->connection == NULL) {
+ if (error != NULL) {
+ g_critical ("error getting system bus: %s", error->message);
+ g_error_free (error);
+ }
+ goto out;
+ }
+ connection = dbus_g_connection_get_connection (polkit->priv->connection);
+
+ polkit->priv->context = polkit_context_new ();
+ polkit_context_set_io_watch_functions (polkit->priv->context, pk_polkit_io_add_watch, pk_polkit_io_remove_watch);
+ if (!polkit_context_init (polkit->priv->context, NULL)) {
+ g_critical ("cannot initialize libpolkit");
+ goto out;
+ }
+
+ polkit->priv->tracker = polkit_tracker_new ();
+ polkit_tracker_set_system_bus_connection (polkit->priv->tracker, connection);
+ polkit_tracker_init (polkit->priv->tracker);
+
+ /* TODO FIXME: I'm pretty sure dbus-glib blows in a way that
+ * we can't say we're interested in all signals from all
+ * members on all interfaces for a given service... So we do
+ * this..
+ */
+
+ dbus_error_init (&dbus_error);
+
+ /* need to listen to NameOwnerChanged */
+ dbus_bus_add_match (connection,
+ "type='signal'"
+ ",interface='"DBUS_INTERFACE_DBUS"'"
+ ",sender='"DBUS_SERVICE_DBUS"'"
+ ",member='NameOwnerChanged'",
+ &dbus_error);
+
+ if (dbus_error_is_set (&dbus_error)) {
+ egg_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ /* need to listen to ConsoleKit signals */
+ dbus_bus_add_match (connection,
+ "type='signal',sender='org.freedesktop.ConsoleKit'",
+ &dbus_error);
+
+ if (dbus_error_is_set (&dbus_error)) {
+ egg_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ if (!dbus_connection_add_filter (connection, gpk_polkit_dbus_filter, polkit, NULL)) {
+ egg_warning ("Cannot add D-Bus filter: %s: %s", dbus_error.name, dbus_error.message);
+ goto out;
+ }
+
+out:
+ return;
+}
+
+/**
+ * dkp_polkit_new:
+ * Return value: A new polkit class instance.
+ **/
+DkpPolkit *
+dkp_polkit_new (void)
+{
+ if (dkp_polkit_object != NULL) {
+ g_object_ref (dkp_polkit_object);
+ } else {
+ dkp_polkit_object = g_object_new (DKP_TYPE_POLKIT, NULL);
+ g_object_add_weak_pointer (dkp_polkit_object, &dkp_polkit_object);
+ }
+ return DKP_POLKIT (dkp_polkit_object);
+}
+
diff --git a/src/dkp-polkit.h b/src/dkp-polkit.h
new file mode 100644
index 0000000..b54c82f
--- /dev/null
+++ b/src/dkp-polkit.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __DKP_POLKIT_H
+#define __DKP_POLKIT_H
+
+#include <glib-object.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+G_BEGIN_DECLS
+
+#define DKP_TYPE_POLKIT (dkp_polkit_get_type ())
+#define DKP_POLKIT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_POLKIT, DkpPolkit))
+#define DKP_POLKIT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_TYPE_POLKIT, DkpPolkitClass))
+#define DKP_IS_POLKIT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_TYPE_POLKIT))
+#define DKP_IS_POLKIT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_TYPE_POLKIT))
+#define DKP_POLKIT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_TYPE_POLKIT, DkpPolkitClass))
+
+typedef struct DkpPolkitPrivate DkpPolkitPrivate;
+
+typedef struct
+{
+ GObject parent;
+ DkpPolkitPrivate *priv;
+} DkpPolkit;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} DkpPolkitClass;
+
+GType dkp_polkit_get_type (void) G_GNUC_CONST;
+DkpPolkit *dkp_polkit_new (void);
+PolKitCaller *dkp_polkit_get_caller (DkpPolkit *polkit,
+ DBusGMethodInvocation *context);
+gboolean dkp_polkit_check_auth (DkpPolkit *polkit,
+ PolKitCaller *pk_caller,
+ const gchar *action_id,
+ DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __DKP_POLKIT_H */
+