Commit 2b25c7e3 authored by David Zeuthen's avatar David Zeuthen

add Changed() signal that is fired when actions/authorizations change

parent 79439afa
......@@ -249,5 +249,9 @@
</arg>
</method>
<signal name="Changed">
<annotation name="org.gtk.EggDBus.DocString" value="Emitted when actions and/or authorizations change"/>
</signal>
</interface>
</node>
......@@ -46,13 +46,10 @@ Core TODO items
sudo-style authentication (e.g. select one or more identities that the
user can choose to authenticate as)
- emit a Changed() signal on the Authority interface when authorizations
change
- provide a way to cancel a CheckAuthorization() call
- use file monitors on the /usr/share/polkit-1/actions and
/var/lib/polkit-1 directories and DTRT
- maybe use file monitors on /var/lib/polkit-1 directories and
emit the Changed() signal
Backend TODO items
------------------
......
......@@ -57,8 +57,25 @@ struct _PolkitAuthorityClass
static PolkitAuthority *the_authority = NULL;
enum
{
CHANGED_SIGNAL,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = {0};
G_DEFINE_TYPE (PolkitAuthority, polkit_authority, G_TYPE_OBJECT);
static void
real_authority_changed (_PolkitAuthority *real_authority,
gpointer user_data)
{
PolkitAuthority *authority = POLKIT_AUTHORITY (user_data);
g_signal_emit_by_name (authority, "changed");
}
static void
polkit_authority_init (PolkitAuthority *authority)
{
......@@ -69,6 +86,11 @@ polkit_authority_init (PolkitAuthority *authority)
"/org/freedesktop/PolicyKit1/Authority");
authority->real = _POLKIT_QUERY_INTERFACE_AUTHORITY (authority->authority_object_proxy);
g_signal_connect (authority->real,
"changed",
(GCallback) real_authority_changed,
authority);
}
static void
......@@ -93,6 +115,22 @@ polkit_authority_class_init (PolkitAuthorityClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = polkit_authority_finalize;
/**
* PolkitAuthority::changed:
* @authority: A #PolkitAuthority.
*
* Emitted when actions and/or authorizations change
*/
signals[CHANGED_SIGNAL] = g_signal_new ("changed",
POLKIT_TYPE_AUTHORITY,
G_SIGNAL_RUN_LAST,
0, /* class offset */
NULL, /* accumulator */
NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
PolkitAuthority *
......
......@@ -19,8 +19,6 @@
* Author: David Zeuthen <davidz@redhat.com>
*/
/* TODO: watch for directory / file changes */
#include "config.h"
#include <errno.h>
#include <pwd.h>
......@@ -88,6 +86,8 @@ typedef struct
/* directory with .policy files, e.g. /usr/share/polkit-1/actions */
GFile *directory;
GFileMonitor *dir_monitor;
/* maps from action_id to a ParsedAction struct */
GHashTable *parsed_actions;
......@@ -107,6 +107,14 @@ enum
#define POLKIT_BACKEND_ACTION_POOL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_BACKEND_TYPE_ACTION_POOL, PolkitBackendActionPoolPrivate))
enum
{
CHANGED_SIGNAL,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = {0};
G_DEFINE_TYPE (PolkitBackendActionPool, polkit_backend_action_pool, G_TYPE_OBJECT);
static void
......@@ -139,6 +147,9 @@ polkit_backend_action_pool_finalize (GObject *object)
if (priv->directory != NULL)
g_object_unref (priv->directory);
if (priv->dir_monitor != NULL)
g_object_unref (priv->dir_monitor);
if (priv->parsed_actions != NULL)
g_hash_table_unref (priv->parsed_actions);
......@@ -172,6 +183,32 @@ polkit_backend_action_pool_get_property (GObject *object,
}
}
static void
dir_monitor_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
PolkitBackendActionPool *pool;
PolkitBackendActionPoolPrivate *priv;
pool = POLKIT_BACKEND_ACTION_POOL (user_data);
priv = POLKIT_BACKEND_ACTION_POOL_GET_PRIVATE (pool);
/* TODO: maybe rate-limit so storms of events are collapsed into one with a 500ms resolution?
* Because when editing a file with emacs we get 4-8 events..
*/
/* now throw away all caches */
g_hash_table_remove_all (priv->parsed_files);
g_hash_table_remove_all (priv->parsed_actions);
priv->has_loaded_all_files = FALSE;
g_signal_emit_by_name (pool, "changed");
}
static void
polkit_backend_action_pool_set_property (GObject *object,
guint prop_id,
......@@ -180,6 +217,7 @@ polkit_backend_action_pool_set_property (GObject *object,
{
PolkitBackendActionPool *pool;
PolkitBackendActionPoolPrivate *priv;
GError *error;
pool = POLKIT_BACKEND_ACTION_POOL (object);
priv = POLKIT_BACKEND_ACTION_POOL_GET_PRIVATE (pool);
......@@ -188,6 +226,24 @@ polkit_backend_action_pool_set_property (GObject *object,
{
case PROP_DIRECTORY:
priv->directory = g_value_dup_object (value);
error = NULL;
priv->dir_monitor = g_file_monitor_directory (priv->directory,
G_FILE_MONITOR_NONE,
NULL,
&error);
if (priv->dir_monitor == NULL)
{
g_warning ("Error monitoring actions directory: %s", error->message);
g_error_free (error);
}
else
{
g_signal_connect (priv->dir_monitor,
"changed",
(GCallback) dir_monitor_changed,
pool);
}
break;
default:
......@@ -223,6 +279,22 @@ polkit_backend_action_pool_class_init (PolkitBackendActionPoolClass *klass)
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
/**
* PolkitBackendActionPool::changed:
* @action_pool: A #PolkitBackendActionPool.
*
* Emitted when action files in the supplied directory changes.
*/
signals[CHANGED_SIGNAL] = g_signal_new ("changed",
POLKIT_BACKEND_TYPE_ACTION_POOL,
G_SIGNAL_RUN_LAST,
0, /* class offset */
NULL, /* accumulator */
NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
/**
......
......@@ -26,6 +26,14 @@
#include <polkit/polkit.h>
#include "polkitbackendauthority.h"
enum
{
CHANGED_SIGNAL,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = {0};
G_DEFINE_ABSTRACT_TYPE (PolkitBackendAuthority, polkit_backend_authority, G_TYPE_OBJECT);
static void
......@@ -36,6 +44,21 @@ polkit_backend_authority_init (PolkitBackendAuthority *local_authority)
static void
polkit_backend_authority_class_init (PolkitBackendAuthorityClass *klass)
{
/**
* PolkitBackendAuthority::changed:
* @authority: A #PolkitBackendAuthority.
*
* Emitted when actions and/or authorizations change
*/
signals[CHANGED_SIGNAL] = g_signal_new ("changed",
POLKIT_BACKEND_TYPE_AUTHORITY,
G_SIGNAL_RUN_LAST,
0, /* class offset */
NULL, /* accumulator */
NULL, /* accumulator data */
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
void
......
......@@ -51,6 +51,11 @@ struct _PolkitBackendAuthorityClass
/*< public >*/
/* Signals */
void (*changed) (PolkitBackendAuthority *authority);
/* VTable */
/* TODO: need something more efficient such that we don't watch all name changes */
void (*system_bus_name_owner_changed) (PolkitBackendAuthority *authority,
const gchar *name,
......
......@@ -184,22 +184,36 @@ static void polkit_backend_local_authority_authentication_agent_response (Polkit
/* ---------------------------------------------------------------------------------------------------- */
static void
action_pool_changed (PolkitBackendActionPool *action_pool,
PolkitBackendLocalAuthority *authority)
{
g_signal_emit_by_name (authority, "changed");
}
/* ---------------------------------------------------------------------------------------------------- */
G_DEFINE_TYPE (PolkitBackendLocalAuthority, polkit_backend_local_authority, POLKIT_BACKEND_TYPE_AUTHORITY);
#define POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY, PolkitBackendLocalAuthorityPrivate))
static void
polkit_backend_local_authority_init (PolkitBackendLocalAuthority *local_authority)
polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
{
PolkitBackendLocalAuthorityPrivate *priv;
GFile *action_desc_directory;
priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
action_desc_directory = g_file_new_for_path (PACKAGE_DATA_DIR "/polkit-1/actions");
priv->action_pool = polkit_backend_action_pool_new (action_desc_directory);
g_object_unref (action_desc_directory);
g_signal_connect (priv->action_pool,
"changed",
(GCallback) action_pool_changed,
authority);
priv->hash_identity_to_authority_store = g_hash_table_new_full ((GHashFunc) polkit_identity_hash,
(GEqualFunc) polkit_identity_equal,
(GDestroyNotify) g_object_unref,
......@@ -2219,6 +2233,9 @@ add_authorization_for_identity (PolkitBackendLocalAuthority *authority,
authorization,
error);
if (ret)
g_signal_emit_by_name (authority, "changed");
out:
return ret;
}
......
......@@ -51,6 +51,8 @@ struct _PolkitBackendServer
EggDBusBus *bus;
gulong name_owner_changed_id;
gulong authority_changed_id;
};
struct _PolkitBackendServerClass
......@@ -82,6 +84,8 @@ polkit_backend_server_finalize (GObject *object)
g_object_unref (server->system_bus);
g_signal_handler_disconnect (server->authority, server->authority_changed_id);
g_object_unref (server->authority);
}
......@@ -105,6 +109,13 @@ name_owner_changed (EggDBusBus *instance,
polkit_backend_authority_system_bus_name_owner_changed (server->authority, name, old_owner, new_owner);
}
static void
authority_changed (PolkitBackendAuthority *authority,
PolkitBackendServer *server)
{
_polkit_authority_emit_signal_changed (_POLKIT_AUTHORITY (server), NULL);
}
PolkitBackendServer *
polkit_backend_server_new (PolkitBackendAuthority *authority)
{
......@@ -128,6 +139,11 @@ polkit_backend_server_new (PolkitBackendAuthority *authority)
(GCallback) name_owner_changed,
server);
server->authority_changed_id = g_signal_connect (authority,
"changed",
(GCallback) authority_changed,
server);
return server;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment