Add support for old style Secret Service signals

* As used by ksecretservice
This commit is contained in:
Stef Walter 2012-02-19 13:09:07 +01:00
parent 2bc2140d43
commit 605e0b1f9b
3 changed files with 178 additions and 1 deletions

View File

@ -428,6 +428,87 @@ secret_collection_properties_changed (GDBusProxy *proxy,
g_object_thaw_notify (G_OBJECT (self)); g_object_thaw_notify (G_OBJECT (self));
} }
static void
secret_collection_signal (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters)
{
SecretCollection *self = SECRET_COLLECTION (proxy);
SecretItem *item;
const gchar *item_path;
GVariantBuilder builder;
gboolean found = FALSE;
GVariantIter iter;
GVariant *value;
GVariant *paths;
GVariant *path;
/*
* Remember that these signals come from a time before PropertiesChanged.
* We support them because they're in the spec, and ksecretservice uses them.
*/
paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
/* A new collection was added, add it to the Collections property */
if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CREATED)) {
g_variant_get (parameters, "@o", &value);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
g_variant_iter_init (&iter, paths);
while ((path = g_variant_iter_next_value (&iter)) != NULL) {
if (g_variant_equal (path, value)) {
found = TRUE;
break;
}
g_variant_builder_add_value (&builder, path);
g_variant_unref (path);
}
if (!found) {
g_variant_builder_add_value (&builder, value);
handle_property_changed (self, "Items", g_variant_builder_end (&builder));
}
g_variant_builder_clear (&builder);
g_variant_unref (value);
/* A collection was deleted, remove it from the Collections property */
} else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_DELETED)) {
g_variant_get (parameters, "@o", &value);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
g_variant_iter_init (&iter, paths);
while ((path = g_variant_iter_next_value (&iter)) != NULL) {
if (g_variant_equal (path, value))
found = TRUE;
else
g_variant_builder_add_value (&builder, path);
g_variant_unref (path);
}
if (found)
handle_property_changed (self, "Items", g_variant_builder_end (&builder));
g_variant_unref (value);
/* The collection changed, update it */
} else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CHANGED)) {
g_variant_get (parameters, "&o", &item_path);
g_mutex_lock (&self->pv->mutex);
if (self->pv->items)
item = g_hash_table_lookup (self->pv->items, item_path);
else
item = NULL;
if (item)
g_object_ref (item);
g_mutex_unlock (&self->pv->mutex);
secret_item_refresh (item);
g_object_unref (item);
}
g_variant_unref (paths);
}
static void static void
secret_collection_class_init (SecretCollectionClass *klass) secret_collection_class_init (SecretCollectionClass *klass)
{ {
@ -440,6 +521,7 @@ secret_collection_class_init (SecretCollectionClass *klass)
gobject_class->finalize = secret_collection_finalize; gobject_class->finalize = secret_collection_finalize;
proxy_class->g_properties_changed = secret_collection_properties_changed; proxy_class->g_properties_changed = secret_collection_properties_changed;
proxy_class->g_signal = secret_collection_signal;
/** /**
* SecretCollection:service: * SecretCollection:service:

View File

@ -37,6 +37,12 @@ typedef struct _SecretSession SecretSession;
#define SECRET_PROMPT_INTERFACE "org.freedesktop.Secret.Prompt" #define SECRET_PROMPT_INTERFACE "org.freedesktop.Secret.Prompt"
#define SECRET_SERVICE_INTERFACE "org.freedesktop.Secret.Service" #define SECRET_SERVICE_INTERFACE "org.freedesktop.Secret.Service"
#define SECRET_SIGNAL_COLLECTION_CREATED "CollectionCreated"
#define SECRET_SIGNAL_COLLECTION_CHANGED "CollectionChanged"
#define SECRET_SIGNAL_COLLECTION_DELETED "CollectionDeleted"
#define SECRET_SIGNAL_ITEM_CREATED "ItemCreated"
#define SECRET_SIGNAL_ITEM_CHANGED "ItemChanged"
#define SECRET_SIGNAL_ITEM_DELETED "ItemDeleted"
#define SECRET_PROMPT_SIGNAL_COMPLETED "Completed" #define SECRET_PROMPT_SIGNAL_COMPLETED "Completed"
#define SECRET_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" #define SECRET_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
@ -56,6 +62,9 @@ gchar * _secret_util_parent_path (const gchar *path
gboolean _secret_util_empty_path (const gchar *path); gboolean _secret_util_empty_path (const gchar *path);
gint _secret_util_array_index_of (GVariant *array,
GVariant *value);
GType _secret_list_get_type (void) G_GNUC_CONST; GType _secret_list_get_type (void) G_GNUC_CONST;
GVariant * _secret_util_variant_for_attributes (GHashTable *attributes); GVariant * _secret_util_variant_for_attributes (GHashTable *attributes);

View File

@ -272,6 +272,8 @@ handle_property_changed (SecretService *self,
{ {
gboolean perform; gboolean perform;
g_variant_ref_sink (value);
if (g_str_equal (property_name, "Collections")) { if (g_str_equal (property_name, "Collections")) {
g_mutex_lock (&self->pv->mutex); g_mutex_lock (&self->pv->mutex);
@ -281,6 +283,8 @@ handle_property_changed (SecretService *self,
if (perform) if (perform)
secret_service_ensure_collections (self, self->pv->cancellable, NULL, NULL); secret_service_ensure_collections (self, self->pv->cancellable, NULL, NULL);
} }
g_variant_unref (value);
} }
static void static void
@ -302,6 +306,87 @@ secret_service_properties_changed (GDBusProxy *proxy,
g_object_thaw_notify (G_OBJECT (self)); g_object_thaw_notify (G_OBJECT (self));
} }
static void
secret_service_signal (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters)
{
SecretService *self = SECRET_SERVICE (proxy);
SecretCollection *collection;
const gchar *collection_path;
GVariantBuilder builder;
gboolean found = FALSE;
GVariantIter iter;
GVariant *value;
GVariant *paths;
GVariant *path;
/*
* Remember that these signals come from a time before PropertiesChanged.
* We support them because they're in the spec, and ksecretservice uses them.
*/
paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Collections");
/* A new collection was added, add it to the Collections property */
if (g_str_equal (signal_name, SECRET_SIGNAL_COLLECTION_CREATED)) {
g_variant_get (parameters, "@o", &value);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
g_variant_iter_init (&iter, paths);
while ((path = g_variant_iter_next_value (&iter)) != NULL) {
if (g_variant_equal (path, value)) {
found = TRUE;
break;
}
g_variant_builder_add_value (&builder, path);
g_variant_unref (path);
}
if (!found) {
g_variant_builder_add_value (&builder, value);
handle_property_changed (self, "Collections", g_variant_builder_end (&builder));
}
g_variant_builder_clear (&builder);
g_variant_unref (value);
/* A collection was deleted, remove it from the Collections property */
} else if (g_str_equal (signal_name, SECRET_SIGNAL_COLLECTION_DELETED)) {
g_variant_get (parameters, "@o", &value);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
g_variant_iter_init (&iter, paths);
while ((path = g_variant_iter_next_value (&iter)) != NULL) {
if (g_variant_equal (path, value))
found = TRUE;
else
g_variant_builder_add_value (&builder, path);
g_variant_unref (path);
}
if (found)
handle_property_changed (self, "Collections", g_variant_builder_end (&builder));
g_variant_unref (value);
/* The collection changed, update it */
} else if (g_str_equal (signal_name, SECRET_SIGNAL_COLLECTION_CHANGED)) {
g_variant_get (parameters, "&o", &collection_path);
g_mutex_lock (&self->pv->mutex);
if (self->pv->collections)
collection = g_hash_table_lookup (self->pv->collections, collection_path);
else
collection = NULL;
if (collection)
g_object_ref (collection);
g_mutex_unlock (&self->pv->mutex);
secret_collection_refresh (collection);
g_object_unref (collection);
}
g_variant_unref (paths);
}
static void static void
secret_service_class_init (SecretServiceClass *klass) secret_service_class_init (SecretServiceClass *klass)
{ {
@ -314,6 +399,7 @@ secret_service_class_init (SecretServiceClass *klass)
object_class->finalize = secret_service_finalize; object_class->finalize = secret_service_finalize;
proxy_class->g_properties_changed = secret_service_properties_changed; proxy_class->g_properties_changed = secret_service_properties_changed;
proxy_class->g_signal = secret_service_signal;
klass->prompt_sync = secret_service_real_prompt_sync; klass->prompt_sync = secret_service_real_prompt_sync;
klass->prompt_async = secret_service_real_prompt_async; klass->prompt_async = secret_service_real_prompt_async;