split out the polkit code from the daemon so it can be used in other modules without passing the daemon ref around

This commit is contained in:
Richard Hughes 2008-11-13 16:55:45 +00:00
parent d891912126
commit b71c61335a
5 changed files with 506 additions and 330 deletions

View file

@ -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 \

View file

@ -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,6 +562,127 @@ gpk_daemon_device_event_signal_handler (DevkitClient *client, const char *action
}
}
#if 0
/**
* gpk_daemon_throw_error:
**/
static gboolean
gpk_daemon_throw_error (DBusGMethodInvocation *context, int error_code, const char *format, ...)
{
GError *error;
va_list args;
gchar *message;
va_start (args, format);
message = g_strdup_vprintf (format, args);
va_end (args);
error = g_error_new (DKP_DAEMON_ERROR, error_code, message);
dbus_g_method_return_error (context, error);
g_error_free (error);
g_free (message);
return TRUE;
}
#endif
/* exported methods */
/**
* dkp_daemon_enumerate_devices:
**/
gboolean
dkp_daemon_enumerate_devices (DkpDaemon *daemon, DBusGMethodInvocation *context)
{
guint i;
const GPtrArray *array;
GPtrArray *object_paths;
DkpDevice *device;
/* build a pointer array of the object paths */
object_paths = g_ptr_array_new ();
array = dkp_device_list_get_array (daemon->priv->list);
for (i=0; i<array->len; i++) {
device = (DkpDevice *) g_ptr_array_index (array, i);
g_ptr_array_add (object_paths, g_strdup (dkp_device_get_object_path (device)));
}
/* return it on the bus */
dbus_g_method_return (context, object_paths);
/* free */
g_ptr_array_foreach (object_paths, (GFunc) g_free, NULL);
g_ptr_array_free (object_paths, TRUE);
return TRUE;
}
/**
* dkp_daemon_suspend:
**/
gboolean
dkp_daemon_suspend (DkpDaemon *daemon, DBusGMethodInvocation *context)
{
gboolean ret;
GError *error;
GError *error_local = NULL;
PolKitCaller *caller;
caller = dkp_polkit_get_caller (daemon->priv->polkit, context);
if (caller == NULL)
goto out;
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);
if (!ret) {
error = g_error_new (DKP_DAEMON_ERROR,
DKP_DAEMON_ERROR_GENERAL,
"Cannot spawn: %s", error_local->message);
g_error_free (error_local);
dbus_g_method_return_error (context, error);
goto out;
}
dbus_g_method_return (context, NULL);
out:
if (caller != NULL)
polkit_caller_unref (caller);
return TRUE;
}
/**
* dkp_daemon_hibernate:
**/
gboolean
dkp_daemon_hibernate (DkpDaemon *daemon, DBusGMethodInvocation *context)
{
gboolean ret;
GError *error;
GError *error_local = NULL;
PolKitCaller *caller;
caller = dkp_polkit_get_caller (daemon->priv->polkit, context);
if (caller == NULL)
goto out;
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);
if (!ret) {
error = g_error_new (DKP_DAEMON_ERROR,
DKP_DAEMON_ERROR_GENERAL,
"Cannot spawn: %s", error_local->message);
g_error_free (error_local);
dbus_g_method_return_error (context, error);
goto out;
}
dbus_g_method_return (context, NULL);
out:
if (caller != NULL)
polkit_caller_unref (caller);
return TRUE;
}
/**
* gpk_daemon_register_power_daemon:
**/
@ -642,81 +694,36 @@ gpk_daemon_register_power_daemon (DkpDaemon *daemon)
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) {
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->system_bus_connection);
connection = dbus_g_connection_get_connection (daemon->priv->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,
dbus_g_connection_register_g_object (daemon->priv->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..
*/
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);
/* 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);
@ -771,186 +778,3 @@ dkp_daemon_new (void)
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:
**/
static gboolean
gpk_daemon_throw_error (DBusGMethodInvocation *context, int error_code, const char *format, ...)
{
GError *error;
va_list args;
gchar *message;
va_start (args, format);
message = g_strdup_vprintf (format, args);
va_end (args);
error = g_error_new (DKP_DAEMON_ERROR,
error_code,
message);
dbus_g_method_return_error (context, error);
g_error_free (error);
g_free (message);
return TRUE;
}
#endif
/* exported methods */
/**
* dkp_daemon_enumerate_devices:
**/
gboolean
dkp_daemon_enumerate_devices (DkpDaemon *daemon, DBusGMethodInvocation *context)
{
guint i;
const GPtrArray *array;
GPtrArray *object_paths;
DkpDevice *device;
/* build a pointer array of the object paths */
object_paths = g_ptr_array_new ();
array = dkp_device_list_get_array (daemon->priv->list);
for (i=0; i<array->len; i++) {
device = (DkpDevice *) g_ptr_array_index (array, i);
g_ptr_array_add (object_paths, g_strdup (dkp_device_get_object_path (device)));
}
/* return it on the bus */
dbus_g_method_return (context, object_paths);
/* free */
g_ptr_array_foreach (object_paths, (GFunc) g_free, NULL);
g_ptr_array_free (object_paths, TRUE);
return TRUE;
}
/**
* dkp_daemon_suspend:
**/
gboolean
dkp_daemon_suspend (DkpDaemon *daemon, DBusGMethodInvocation *context)
{
gboolean ret;
GError *error;
GError *error_local = NULL;
PolKitCaller *pk_caller;
pk_caller = dkp_daemon_local_get_caller_for_context (daemon, context);
if (pk_caller == NULL)
goto out;
if (!dkp_daemon_local_check_auth (daemon, pk_caller, "org.freedesktop.devicekit.power.suspend", context))
goto out;
ret = g_spawn_command_line_async ("/usr/sbin/pm-suspend", &error_local);
if (!ret) {
error = g_error_new (DKP_DAEMON_ERROR,
DKP_DAEMON_ERROR_GENERAL,
"Cannot spawn: %s", error_local->message);
g_error_free (error_local);
dbus_g_method_return_error (context, error);
goto out;
}
dbus_g_method_return (context, NULL);
out:
if (pk_caller != NULL)
polkit_caller_unref (pk_caller);
return TRUE;
}
/**
* dkp_daemon_hibernate:
**/
gboolean
dkp_daemon_hibernate (DkpDaemon *daemon, DBusGMethodInvocation *context)
{
gboolean ret;
GError *error;
GError *error_local = NULL;
PolKitCaller *pk_caller;
pk_caller = dkp_daemon_local_get_caller_for_context (daemon, context);
if (pk_caller == NULL)
goto out;
if (!dkp_daemon_local_check_auth (daemon, pk_caller, "org.freedesktop.devicekit.power.hibernate", context))
goto out;
ret = g_spawn_command_line_async ("/usr/sbin/pm-hibernate", &error_local);
if (!ret) {
error = g_error_new (DKP_DAEMON_ERROR,
DKP_DAEMON_ERROR_GENERAL,
"Cannot spawn: %s", error_local->message);
g_error_free (error_local);
dbus_g_method_return_error (context, error);
goto out;
}
dbus_g_method_return (context, NULL);
out:
if (pk_caller != NULL)
polkit_caller_unref (pk_caller);
return TRUE;
}

View file

@ -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,

301
src/dkp-polkit.c Normal file
View file

@ -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);
}

62
src/dkp-polkit.h Normal file
View file

@ -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 */