From c6c6afa2cc95aff8344bcc264b89f98fbb63e931 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Wed, 25 Jan 2012 14:26:52 +0100 Subject: [PATCH] Rework how the initialization work for various proxy objects * Fix bugs and tests --- .gitignore | 1 + configure.ac | 2 + library/Makefile.am | 24 +- library/gsecret-collection.c | 454 +++++++----- library/gsecret-enum-types.c.template | 43 ++ library/gsecret-enum-types.h.template | 28 + library/gsecret-item.c | 159 +++-- library/gsecret-password.c | 19 +- library/gsecret-private.h | 4 +- library/gsecret-service.c | 981 +++++++++++++++----------- library/gsecret-service.h | 28 +- library/gsecret-session.c | 12 +- library/tests/test-collection.c | 11 +- library/tests/test-item.c | 17 +- library/tests/test-prompt.c | 11 +- library/tests/test-service.c | 46 +- library/tests/test-session.c | 12 +- po/POTFILES.in | 2 +- 18 files changed, 1152 insertions(+), 702 deletions(-) create mode 100644 library/gsecret-enum-types.c.template create mode 100644 library/gsecret-enum-types.h.template diff --git a/.gitignore b/.gitignore index 9b4c7c2..27ba13e 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ stamp* !/egg/tests/test-*.c /library/gsecret-dbus-generated.[ch] +/library/gsecret-enum-types.[ch] /library/tests/test-* !/library/tests/test-*.c diff --git a/configure.ac b/configure.ac index 1a0426b..b20e5f5 100644 --- a/configure.ac +++ b/configure.ac @@ -41,6 +41,8 @@ PKG_CHECK_MODULES(GLIB, LIBS="$LIBS $GLIB_LIBS" CFLAGS="$CFLAGS $GLIB_CFLAGS" +AC_PATH_PROG(GLIB_MKENUMS, glib-mkenums) + # -------------------------------------------------------------------- # libgcrypt # diff --git a/library/Makefile.am b/library/Makefile.am index 720b1e7..c8fbb7e 100644 --- a/library/Makefile.am +++ b/library/Makefile.am @@ -9,10 +9,22 @@ module_flags = \ -no-undefined \ -export-symbols-regex '^gsecret_' +INCLUDES = \ + -DGSECRET_COMPILATION + lib_LTLIBRARIES = libgsecret.la +HEADER_FILES = \ + gsecret-collection.h \ + gsecret-item.h \ + gsecret-password.h \ + gsecret-prompt.h \ + gsecret-service.h \ + gsecret-value.h + BUILT_SOURCES = \ - gsecret-dbus-generated.c gsecret-dbus-generated.h + gsecret-dbus-generated.c gsecret-dbus-generated.h \ + gsecret-enum-types.c gsecret-enum-types.h libgsecret_la_SOURCES = \ gsecret-collection.h gsecret-collection.c \ @@ -45,5 +57,15 @@ gsecret-dbus-generated.c: $(DBUS_XML_DEFINITIONS) Makefile.am $(AM_V_GEN) sed -i -e '1i #define GLIB_DISABLE_DEPRECATION_WARNINGS' gsecret-dbus-generated.c gsecret-dbus-generated.h: gsecret-dbus-generated.c +gsecret-enum-types.h: gsecret-enum-types.h.template $(HEADER_FILES) + $(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@ + +gsecret-enum-types.c: gsecret-enum-types.c.template $(HEADER_FILES) + $(AM_V_GEN) $(GLIB_MKENUMS) --template $^ > $@ + +EXTRA_DIST = \ + gsecret-enum-types.h.template \ + gsecret-enum-types.c.template + check-memory: make -C tests check-memory \ No newline at end of file diff --git a/library/gsecret-collection.c b/library/gsecret-collection.c index 3f1a8fa..6c4bc81 100644 --- a/library/gsecret-collection.c +++ b/library/gsecret-collection.c @@ -42,7 +42,18 @@ struct _GSecretCollectionPrivate { GHashTable *items; }; -G_DEFINE_TYPE (GSecretCollection, gsecret_collection, G_TYPE_DBUS_PROXY); +static GInitableIface *gsecret_collection_initable_parent_iface = NULL; + +static GAsyncInitableIface *gsecret_collection_async_initable_parent_iface = NULL; + +static void gsecret_collection_initable_iface (GInitableIface *iface); + +static void gsecret_collection_async_initable_iface (GAsyncInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GSecretCollection, gsecret_collection, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gsecret_collection_initable_iface); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, gsecret_collection_async_initable_iface); +); static GHashTable * items_table_new (void) @@ -166,69 +177,63 @@ gsecret_collection_finalize (GObject *obj) G_OBJECT_CLASS (gsecret_collection_parent_class)->finalize (obj); } +static GSecretItem * +collection_lookup_item (GSecretCollection *self, + const gchar *path) +{ + GSecretItem *item = NULL; + + g_mutex_lock (&self->pv->mutex); + + item = g_hash_table_lookup (self->pv->items, path); + if (item != NULL) + g_object_ref (item); + + g_mutex_unlock (&self->pv->mutex); + + return item; +} + +static void +collection_update_items (GSecretCollection *self, + GHashTable *items) +{ + GHashTable *previous; + + g_hash_table_ref (items); + + g_mutex_lock (&self->pv->mutex); + previous = self->pv->items; + self->pv->items = items; + g_mutex_unlock (&self->pv->mutex); + + g_hash_table_unref (previous); +} + typedef struct { - GSecretCollection *collection; GCancellable *cancellable; GHashTable *items; gint items_loading; -} LoadClosure; +} ItemsClosure; static void -load_closure_free (gpointer data) +items_closure_free (gpointer data) { - LoadClosure *closure = data; - g_object_unref (closure->collection); + ItemsClosure *closure = data; g_clear_object (&closure->cancellable); g_hash_table_unref (closure->items); - g_slice_free (LoadClosure, closure); -} - -static GSimpleAsyncResult * -load_result_new (GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *res; - LoadClosure *closure; - - res = g_simple_async_result_new (NULL, callback, user_data, load_result_new); - closure = g_slice_new0 (LoadClosure); - closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - closure->items = items_table_new (); - g_simple_async_result_set_op_res_gpointer (res, closure, load_closure_free); - - return res; + g_slice_free (ItemsClosure, closure); } static void -load_items_complete (GSimpleAsyncResult *res) -{ - LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res); - GSecretCollection *self = closure->collection; - GHashTable *items; - - g_assert (closure->items_loading == 0); - - g_hash_table_ref (closure->items); - - g_mutex_lock (&self->pv->mutex); - items = self->pv->items; - self->pv->items = closure->items; - g_mutex_unlock (&self->pv->mutex); - - g_hash_table_unref (items); - - g_simple_async_result_complete (res); -} - -static void -on_item_loading (GObject *source, - GAsyncResult *result, - gpointer user_data) +on_load_item (GObject *source, + GAsyncResult *result, + gpointer user_data) { GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); - LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res); - const gchar *item_path; + ItemsClosure *closure = g_simple_async_result_get_op_res_gpointer (res); + GSecretCollection *self = GSECRET_COLLECTION (g_async_result_get_source_object (user_data)); + const gchar *path; GError *error = NULL; GSecretItem *item; @@ -240,57 +245,118 @@ on_item_loading (GObject *source, g_simple_async_result_take_error (res, error); if (item != NULL) { - item_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item)); - g_hash_table_insert (closure->items, g_strdup (item_path), item); + path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item)); + g_hash_table_insert (closure->items, g_strdup (path), item); } - if (closure->items_loading == 0) - load_items_complete (res); + if (closure->items_loading == 0) { + collection_update_items (self, closure->items); + g_simple_async_result_complete_in_idle (res); + } + g_object_unref (self); g_object_unref (res); } static void -load_items_perform (GSecretCollection *self, - GSimpleAsyncResult *res, - GVariant *item_paths) +collection_load_items_async (GSecretCollection *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { - LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res); + ItemsClosure *closure; GSecretItem *item; + GSimpleAsyncResult *res; + const gchar *path; + GVariant *paths; GVariantIter iter; - gchar *item_path; - g_assert (GSECRET_IS_COLLECTION (self)); - g_assert (item_paths != NULL); - g_assert (closure->collection == NULL); + paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items"); + g_return_if_fail (paths != NULL); - closure->collection = g_object_ref (self); + res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, + collection_load_items_async); + closure = g_slice_new0 (ItemsClosure); + closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + closure->items = items_table_new (); + g_simple_async_result_set_op_res_gpointer (res, closure, items_closure_free); - g_variant_iter_init (&iter, item_paths); - while (g_variant_iter_loop (&iter, "o", &item_path)) { - - g_mutex_lock (&self->pv->mutex); - item = g_hash_table_lookup (self->pv->items, item_path); - if (item != NULL) - g_object_ref (item); - g_mutex_unlock (&self->pv->mutex); + g_variant_iter_init (&iter, paths); + while (g_variant_iter_loop (&iter, "&o", &path)) { + item = collection_lookup_item (self, path); + /* No such collection yet create a new one */ if (item == NULL) { - // TODO: xxxxxxxxxxxx; - gsecret_item_new (self->pv->service, item_path, - closure->cancellable, on_item_loading, - g_object_ref (res)); + gsecret_item_new (self->pv->service, path, cancellable, + on_load_item, g_object_ref (res)); closure->items_loading++; } else { - g_hash_table_insert (closure->items, - g_strdup (item_path), item); + g_hash_table_insert (closure->items, g_strdup (path), item); } - } - if (closure->items_loading == 0) - load_items_complete (res); + if (closure->items_loading == 0) { + collection_update_items (self, closure->items); + g_simple_async_result_complete_in_idle (res); + } + + g_variant_unref (paths); + g_object_unref (res); +} + +static gboolean +collection_load_items_finish (GSecretCollection *self, + GAsyncResult *result, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) + return FALSE; + + return TRUE; +} + + +static gboolean +collection_load_items_sync (GSecretCollection *self, + GCancellable *cancellable, + GError **error) +{ + GSecretItem *item; + GHashTable *items; + GVariant *paths; + GVariantIter iter; + const gchar *path; + gboolean ret = TRUE; + + paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items"); + g_return_val_if_fail (paths != NULL, FALSE); + + items = items_table_new (); + + g_variant_iter_init (&iter, paths); + while (g_variant_iter_next (&iter, "&o", &path)) { + item = collection_lookup_item (self, path); + + /* No such collection yet create a new one */ + if (item == NULL) { + item = gsecret_item_new_sync (self->pv->service, path, + cancellable, error); + if (item == NULL) { + ret = FALSE; + break; + } + } + + g_hash_table_insert (items, g_strdup (path), item); + } + + if (ret) + collection_update_items (self, items); + + g_hash_table_unref (items); + g_variant_unref (paths); + return ret; } static void @@ -298,8 +364,6 @@ handle_property_changed (GSecretCollection *self, const gchar *property_name, GVariant *value) { - GSimpleAsyncResult *res; - if (g_str_equal (property_name, "Label")) g_object_notify (G_OBJECT (self), "label"); @@ -312,24 +376,8 @@ handle_property_changed (GSecretCollection *self, else if (g_str_equal (property_name, "Modified")) g_object_notify (G_OBJECT (self), "modified"); - else if (g_str_equal (property_name, "Items") && !self->pv->constructing) { - res = load_result_new (self->pv->cancellable, NULL, NULL); - - if (value == NULL) - value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items"); - else - g_variant_ref (value); - if (value == NULL) { - g_warning ("couldn't retrieve Collection Items property"); - g_simple_async_result_complete (res); - } else { - // TODO: yyyy; - load_items_perform (self, res, value); - g_variant_unref (value); - } - - g_object_unref (res); - } + else if (g_str_equal (property_name, "Items") && !self->pv->constructing) + collection_load_items_async (self, self->pv->cancellable, NULL, NULL); } static void @@ -392,49 +440,147 @@ gsecret_collection_class_init (GSecretCollectionClass *klass) g_type_class_add_private (gobject_class, sizeof (GSecretCollectionPrivate)); } -static void -on_collection_new (GObject *source, - GAsyncResult *result, - gpointer user_data) +static gboolean +gsecret_collection_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) { - GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); GSecretCollection *self; - GObject *source_object; - GError *error = NULL; - GVariant *item_paths; - GObject *object; GDBusProxy *proxy; - source_object = g_async_result_get_source_object (result); - object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), - result, &error); - g_object_unref (source_object); + if (!gsecret_collection_initable_parent_iface->init (initable, cancellable, error)) + return FALSE; - proxy = G_DBUS_PROXY (object); - if (error == NULL && !_gsecret_util_have_cached_properties (proxy)) { - g_set_error (&error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, - "No such secret collection at path: %s", g_dbus_proxy_get_object_path (proxy)); + proxy = G_DBUS_PROXY (initable); + + if (!_gsecret_util_have_cached_properties (proxy)) { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, + "No such secret collection at path: %s", + g_dbus_proxy_get_object_path (proxy)); + return FALSE; } - if (error == NULL) { - self = GSECRET_COLLECTION (object); - self->pv->constructing = FALSE; + self = GSECRET_COLLECTION (initable); - item_paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), "Items"); - g_return_if_fail (item_paths != NULL); - // TODO: yyyy; - load_items_perform (self, res, item_paths); - g_variant_unref (item_paths); + if (!collection_load_items_sync (self, cancellable, error)) + return FALSE; - } else { + return TRUE; +} + +static void +gsecret_collection_initable_iface (GInitableIface *iface) +{ + gsecret_collection_initable_parent_iface = g_type_interface_peek_parent (iface); + + iface->init = gsecret_collection_initable_init; +} + +typedef struct { + GCancellable *cancellable; +} InitClosure; + +static void +init_closure_free (gpointer data) +{ + InitClosure *closure = data; + g_clear_object (&closure->cancellable); + g_slice_free (InitClosure, closure); +} + +static void +on_init_items (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); + GSecretCollection *self = GSECRET_COLLECTION (source); + GError *error = NULL; + + if (!collection_load_items_finish (self, result, &error)) + g_simple_async_result_take_error (res, error); + + g_simple_async_result_complete (res); + g_object_unref (res); +} + +static void +on_init_base (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); + GSecretCollection *self = GSECRET_COLLECTION (source); + InitClosure *closure = g_simple_async_result_get_op_res_gpointer (res); + GDBusProxy *proxy = G_DBUS_PROXY (self); + GError *error = NULL; + + if (!gsecret_collection_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self), + result, &error)) { g_simple_async_result_take_error (res, error); g_simple_async_result_complete (res); + + } else if (!_gsecret_util_have_cached_properties (proxy)) { + g_simple_async_result_set_error (res, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, + "No such secret collection at path: %s", + g_dbus_proxy_get_object_path (proxy)); + g_simple_async_result_complete (res); + + } else { + collection_load_items_async (self, closure->cancellable, + on_init_items, g_object_ref (res)); } - g_clear_object (&object); g_object_unref (res); } +static void +gsecret_collection_async_initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *res; + InitClosure *closure; + + res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, + gsecret_collection_async_initable_init_async); + closure = g_slice_new0 (InitClosure); + closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + g_simple_async_result_set_op_res_gpointer (res, closure, init_closure_free); + + gsecret_collection_async_initable_parent_iface->init_async (initable, io_priority, + cancellable, + on_init_base, + g_object_ref (res)); + + g_object_unref (res); +} + +static gboolean +gsecret_collection_async_initable_init_finish (GAsyncInitable *initable, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable), + gsecret_collection_async_initable_init_async), FALSE); + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) + return FALSE; + + return TRUE; +} + +static void +gsecret_collection_async_initable_iface (GAsyncInitableIface *iface) +{ + gsecret_collection_async_initable_parent_iface = g_type_interface_peek_parent (iface); + + iface->init_async = gsecret_collection_async_initable_init_async; + iface->init_finish = gsecret_collection_async_initable_init_finish; +} + void gsecret_collection_new (GSecretService *service, const gchar *collection_path, @@ -442,22 +588,16 @@ gsecret_collection_new (GSecretService *service, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; GDBusProxy *proxy; g_return_if_fail (GSECRET_IS_SERVICE (service)); g_return_if_fail (collection_path != NULL); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); - res = load_result_new (cancellable, callback, user_data); proxy = G_DBUS_PROXY (service); g_async_initable_new_async (GSECRET_SERVICE_GET_CLASS (service)->collection_gtype, - G_PRIORITY_DEFAULT, - cancellable, - // TODO: zzzz; - on_collection_new, - g_object_ref (res), + G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", G_DBUS_CALL_FLAGS_NONE, "g-interface-info", _gsecret_gen_collection_interface_info (), "g-name", g_dbus_proxy_get_name (proxy), @@ -466,27 +606,27 @@ gsecret_collection_new (GSecretService *service, "g-interface-name", GSECRET_COLLECTION_INTERFACE, "service", service, NULL); - - g_object_unref (res); } GSecretCollection * gsecret_collection_new_finish (GAsyncResult *result, GError **error) { - GSimpleAsyncResult *res; - LoadClosure *closure; + GObject *source_object; + GObject *object; - g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, load_result_new), NULL); + g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); - res = G_SIMPLE_ASYNC_RESULT (result); + source_object = g_async_result_get_source_object (result); + object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), + result, error); + g_object_unref (source_object); - if (g_simple_async_result_propagate_error (res, error)) + if (object == NULL) return NULL; - closure = g_simple_async_result_get_op_res_gpointer (res); - return g_object_ref (closure->collection); + return GSECRET_COLLECTION (object); } GSecretCollection * @@ -495,29 +635,25 @@ gsecret_collection_new_sync (GSecretService *service, GCancellable *cancellable, GError **error) { - GSecretSync *sync; - GSecretCollection *collection; + GDBusProxy *proxy; g_return_val_if_fail (GSECRET_IS_SERVICE (service), NULL); g_return_val_if_fail (collection_path != NULL, NULL); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); - sync = _gsecret_sync_new (); - g_main_context_push_thread_default (sync->context); + proxy = G_DBUS_PROXY (service); - // TODO: xxxxx; - gsecret_collection_new (service, collection_path, cancellable, - _gsecret_sync_on_result, sync); - - g_main_loop_run (sync->loop); - - collection = gsecret_collection_new_finish (sync->result, error); - - g_main_context_pop_thread_default (sync->context); - _gsecret_sync_free (sync); - - return collection; + return g_initable_new (GSECRET_SERVICE_GET_CLASS (service)->collection_gtype, + cancellable, error, + "g-flags", G_DBUS_CALL_FLAGS_NONE, + "g-interface-info", _gsecret_gen_collection_interface_info (), + "g-name", g_dbus_proxy_get_name (proxy), + "g-connection", g_dbus_proxy_get_connection (proxy), + "g-object-path", collection_path, + "g-interface-name", GSECRET_COLLECTION_INTERFACE, + "service", service, + NULL); } void diff --git a/library/gsecret-enum-types.c.template b/library/gsecret-enum-types.c.template new file mode 100644 index 0000000..5560289 --- /dev/null +++ b/library/gsecret-enum-types.c.template @@ -0,0 +1,43 @@ +/*** BEGIN file-header ***/ + +#include + +#ifndef GSECRET_COMPILATION +#define GSECRET_COMPILATION +#endif + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +#include "@filename@" +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; + +GType +@enum_name@_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + } + return etype; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ + /**/ +/*** END file-tail ***/ diff --git a/library/gsecret-enum-types.h.template b/library/gsecret-enum-types.h.template new file mode 100644 index 0000000..3ec8564 --- /dev/null +++ b/library/gsecret-enum-types.h.template @@ -0,0 +1,28 @@ +/*** BEGIN file-header ***/ +#if !defined (__GSECRET_INSIDE_HEADER__) && !defined (GSECRET_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GSECRET_ENUM_TYPES_H__ +#define __GSECRET_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __GSECRET_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/library/gsecret-item.c b/library/gsecret-item.c index 9522dbf..0190629 100644 --- a/library/gsecret-item.c +++ b/library/gsecret-item.c @@ -37,7 +37,18 @@ typedef struct _GSecretItemPrivate { GCancellable *cancellable; } GSecretItemPrivate; -G_DEFINE_TYPE (GSecretItem, gsecret_item, G_TYPE_DBUS_PROXY); +static GInitableIface *gsecret_item_initable_parent_iface = NULL; + +static GAsyncInitableIface *gsecret_item_async_initable_parent_iface = NULL; + +static void gsecret_item_initable_iface (GInitableIface *iface); + +static void gsecret_item_async_initable_iface (GAsyncInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GSecretItem, gsecret_item, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gsecret_item_initable_iface); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, gsecret_item_async_initable_iface); +); static void gsecret_item_init (GSecretItem *self) @@ -248,20 +259,102 @@ gsecret_item_class_init (GSecretItemClass *klass) g_type_class_add_private (gobject_class, sizeof (GSecretItemPrivate)); } -#if 0 -static void -all_properties_changed (GSecretItem *item) +static gboolean +gsecret_item_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) { - GObject *obj = G_OBJECT (item); - gchar **property_names; - guint i; + GDBusProxy *proxy; - property_names = g_dbus_proxy_get_cached_property_names (G_DBUS_PROXY (item)); - for (i = 0; property_names != NULL && property_names[i] != NULL; i++) - handle_property_changed (obj, property_names[i]); - g_strfreev (property_names); + if (!gsecret_item_initable_parent_iface->init (initable, cancellable, error)) + return FALSE; + + proxy = G_DBUS_PROXY (initable); + + if (!_gsecret_util_have_cached_properties (proxy)) { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, + "No such secret item at path: %s", + g_dbus_proxy_get_object_path (proxy)); + return FALSE; + } + + return TRUE; +} + +static void +gsecret_item_initable_iface (GInitableIface *iface) +{ + gsecret_item_initable_parent_iface = g_type_interface_peek_parent (iface); + + iface->init = gsecret_item_initable_init; +} + +static void +on_init_base (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); + GSecretItem *self = GSECRET_ITEM (source); + GDBusProxy *proxy = G_DBUS_PROXY (self); + GError *error = NULL; + + if (!gsecret_item_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self), + result, &error)) { + g_simple_async_result_take_error (res, error); + + } else if (!_gsecret_util_have_cached_properties (proxy)) { + g_simple_async_result_set_error (res, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, + "No such secret item at path: %s", + g_dbus_proxy_get_object_path (proxy)); + } + + g_simple_async_result_complete (res); + g_object_unref (res); +} + +static void +gsecret_item_async_initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *res; + + res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, + gsecret_item_async_initable_init_async); + + gsecret_item_async_initable_parent_iface->init_async (initable, io_priority, + cancellable, + on_init_base, + g_object_ref (res)); + + g_object_unref (res); +} + +static gboolean +gsecret_item_async_initable_init_finish (GAsyncInitable *initable, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable), + gsecret_item_async_initable_init_async), FALSE); + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) + return FALSE; + + return TRUE; +} + +static void +gsecret_item_async_initable_iface (GAsyncInitableIface *iface) +{ + gsecret_item_async_initable_parent_iface = g_type_interface_peek_parent (iface); + + iface->init_async = gsecret_item_async_initable_init_async; + iface->init_finish = gsecret_item_async_initable_init_finish; } -#endif void gsecret_item_new (GSecretService *service, @@ -279,10 +372,7 @@ gsecret_item_new (GSecretService *service, proxy = G_DBUS_PROXY (service); g_async_initable_new_async (GSECRET_SERVICE_GET_CLASS (service)->item_gtype, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, + G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", G_DBUS_CALL_FLAGS_NONE, "g-interface-info", _gsecret_gen_item_interface_info (), "g-name", g_dbus_proxy_get_name (proxy), @@ -299,7 +389,6 @@ gsecret_item_new_finish (GAsyncResult *result, { GObject *object; GObject *source_object; - GDBusProxy *proxy; source_object = g_async_result_get_source_object (result); object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), @@ -309,14 +398,6 @@ gsecret_item_new_finish (GAsyncResult *result, if (object == NULL) return NULL; - proxy = G_DBUS_PROXY (object); - if (!_gsecret_util_have_cached_properties (proxy)) { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, - "No such secret item at path: %s", g_dbus_proxy_get_object_path (proxy)); - g_object_unref (object); - return NULL; - } - return GSECRET_ITEM (object); } @@ -326,29 +407,25 @@ gsecret_item_new_sync (GSecretService *service, GCancellable *cancellable, GError **error) { - GSecretSync *sync; - GSecretItem *item; + GDBusProxy *proxy; g_return_val_if_fail (GSECRET_IS_SERVICE (service), NULL); g_return_val_if_fail (item_path != NULL, NULL); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); - sync = _gsecret_sync_new (); - g_main_context_push_thread_default (sync->context); + proxy = G_DBUS_PROXY (service); - // TODO: xxxxx; - gsecret_item_new (service, item_path, cancellable, - _gsecret_sync_on_result, sync); - - g_main_loop_run (sync->loop); - - item = gsecret_item_new_finish (sync->result, error); - - g_main_context_pop_thread_default (sync->context); - _gsecret_sync_free (sync); - - return item; + return g_initable_new (GSECRET_SERVICE_GET_CLASS (service)->item_gtype, + cancellable, error, + "g-flags", G_DBUS_CALL_FLAGS_NONE, + "g-interface-info", _gsecret_gen_item_interface_info (), + "g-name", g_dbus_proxy_get_name (proxy), + "g-connection", g_dbus_proxy_get_connection (proxy), + "g-object-path", item_path, + "g-interface-name", GSECRET_ITEM_INTERFACE, + "service", service, + NULL); } void diff --git a/library/gsecret-password.c b/library/gsecret-password.c index 1629c73..08ac755 100644 --- a/library/gsecret-password.c +++ b/library/gsecret-password.c @@ -68,7 +68,7 @@ on_store_connected (GObject *source, GSecretService *service; GError *error = NULL; - service = _gsecret_service_bare_connect_finish (result, &error); + service = gsecret_service_get_finish (result, &error); if (error == NULL) { gsecret_service_storev (service, closure->schema, closure->attributes, @@ -147,8 +147,8 @@ gsecret_password_storev (const GSecretSchema *schema, closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; g_simple_async_result_set_op_res_gpointer (res, closure, store_closure_free); - _gsecret_service_bare_connect (NULL, TRUE, cancellable, - on_store_connected, g_object_ref (res)); + gsecret_service_get (GSECRET_SERVICE_OPEN_SESSION, cancellable, + on_store_connected, g_object_ref (res)); g_object_unref (res); } @@ -306,7 +306,7 @@ on_lookup_connected (GObject *source, GSecretService *service; GError *error = NULL; - service = _gsecret_service_bare_connect_finish (result, &error); + service = gsecret_service_get_finish (result, &error); if (error != NULL) { g_simple_async_result_take_error (res, error); g_simple_async_result_complete (res); @@ -338,8 +338,8 @@ gsecret_password_lookupv (GHashTable *attributes, closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; g_simple_async_result_set_op_res_gpointer (res, closure, lookup_closure_free); - _gsecret_service_bare_connect (NULL, TRUE, cancellable, - on_lookup_connected, g_object_ref (res)); + gsecret_service_get (GSECRET_SERVICE_OPEN_SESSION, cancellable, + on_lookup_connected, g_object_ref (res)); g_object_unref (res); } @@ -490,7 +490,7 @@ on_delete_connect (GObject *source, GSecretService *service; GError *error = NULL; - service = _gsecret_service_bare_connect_finish (result, &error); + service = gsecret_service_get_finish (result, &error); if (error == NULL) { gsecret_service_removev (service, closure->attributes, closure->cancellable, on_delete_complete, @@ -524,9 +524,8 @@ gsecret_password_removev (GHashTable *attributes, closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free); - _gsecret_service_bare_connect (NULL, FALSE, cancellable, - on_delete_connect, - g_object_ref (res)); + gsecret_service_get (GSECRET_SERVICE_NONE, cancellable, + on_delete_connect, g_object_ref (res)); g_object_unref (res); } diff --git a/library/gsecret-private.h b/library/gsecret-private.h index 8ebf4b0..1a74f35 100644 --- a/library/gsecret-private.h +++ b/library/gsecret-private.h @@ -99,6 +99,7 @@ gboolean _gsecret_util_have_cached_properties (GDBusProxy *prox void _gsecret_service_set_default_bus_name (const gchar *bus_name); +#if 0 GSecretService * _gsecret_service_bare_instance (GDBusConnection *connection, const gchar *bus_name); @@ -110,6 +111,7 @@ void _gsecret_service_bare_connect (const gchar *bus GSecretService * _gsecret_service_bare_connect_finish (GAsyncResult *result, GError **error); +#endif GSecretSession * _gsecret_service_get_session (GSecretService *self); @@ -135,7 +137,7 @@ void _gsecret_session_open (GSecretService * GAsyncReadyCallback callback, gpointer user_data); -GSecretSession * _gsecret_session_open_finish (GAsyncResult *result, +gboolean _gsecret_session_open_finish (GAsyncResult *result, GError **error); GVariant * _gsecret_session_encode_secret (GSecretSession *session, diff --git a/library/gsecret-service.c b/library/gsecret-service.c index be26d88..1cbc5ac 100644 --- a/library/gsecret-service.c +++ b/library/gsecret-service.c @@ -15,6 +15,7 @@ #include "gsecret-collection.h" #include "gsecret-dbus-generated.h" +#include "gsecret-enum-types.h" #include "gsecret-item.h" #include "gsecret-private.h" #include "gsecret-service.h" @@ -36,12 +37,14 @@ static const gchar *default_bus_name = GSECRET_SERVICE_BUS_NAME; enum { PROP_0, + PROP_FLAGS, PROP_COLLECTIONS }; typedef struct _GSecretServicePrivate { /* No change between construct and finalize */ GCancellable *cancellable; + GSecretServiceFlags init_flags; /* Locked by mutex */ GMutex mutex; @@ -52,14 +55,18 @@ typedef struct _GSecretServicePrivate { G_LOCK_DEFINE (service_instance); static gpointer service_instance = NULL; -G_DEFINE_TYPE (GSecretService, gsecret_service, G_TYPE_DBUS_PROXY); +static GInitableIface *gsecret_service_initable_parent_iface = NULL; -static GHashTable * -collections_table_new (void) -{ - return g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_object_unref); -} +static GAsyncInitableIface *gsecret_service_async_initable_parent_iface = NULL; + +static void gsecret_service_initable_iface (GInitableIface *iface); + +static void gsecret_service_async_initable_iface (GAsyncInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GSecretService, gsecret_service, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gsecret_service_initable_iface); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, gsecret_service_async_initable_iface); +); static void gsecret_service_init (GSecretService *self) @@ -69,7 +76,6 @@ gsecret_service_init (GSecretService *self) g_mutex_init (&self->pv->mutex); self->pv->cancellable = g_cancellable_new (); - self->pv->collections = collections_table_new (); } static void @@ -81,6 +87,9 @@ gsecret_service_get_property (GObject *obj, GSecretService *self = GSECRET_SERVICE (obj); switch (prop_id) { + case PROP_FLAGS: + g_value_set_flags (value, gsecret_service_get_flags (self)); + break; case PROP_COLLECTIONS: g_value_take_boxed (value, gsecret_service_get_collections (self)); break; @@ -90,6 +99,24 @@ gsecret_service_get_property (GObject *obj, } } +static void +gsecret_service_set_property (GObject *obj, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GSecretService *self = GSECRET_SERVICE (obj); + + switch (prop_id) { + case PROP_FLAGS: + self->pv->init_flags = g_value_get_flags (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } +} + static void gsecret_service_dispose (GObject *obj) { @@ -106,7 +133,8 @@ gsecret_service_finalize (GObject *obj) GSecretService *self = GSECRET_SERVICE (obj); _gsecret_session_free (self->pv->session); - g_hash_table_destroy (self->pv->collections); + if (self->pv->collections) + g_hash_table_destroy (self->pv->collections); g_clear_object (&self->pv->cancellable); G_OBJECT_CLASS (gsecret_service_parent_class)->finalize (obj); @@ -171,152 +199,21 @@ gsecret_service_real_prompt_finish (GSecretService *self, return g_simple_async_result_get_op_res_gboolean (res); } -typedef struct { - GCancellable *cancellable; - GHashTable *collections; - gint collections_loading; -} LoadClosure; - -static void -load_closure_free (gpointer data) -{ - LoadClosure *closure = data; - g_clear_object (&closure->cancellable); - g_hash_table_unref (closure->collections); - g_slice_free (LoadClosure, closure); -} - -static GSimpleAsyncResult * -load_result_new (GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *res; - LoadClosure *closure; - - res = g_simple_async_result_new (NULL, callback, user_data, load_result_new); - closure = g_slice_new (LoadClosure); - closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - closure->collections = collections_table_new (); - g_simple_async_result_set_op_res_gpointer (res, closure, load_closure_free); - - return res; -} - -static void -load_collections_complete (GSecretService *self, - GSimpleAsyncResult *res) -{ - LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res); - GHashTable *collections; - - g_assert (closure->collections_loading == 0); - - g_hash_table_ref (closure->collections); - - g_mutex_lock (&self->pv->mutex); - collections = self->pv->collections; - self->pv->collections = closure->collections; - g_mutex_unlock (&self->pv->mutex); - - g_hash_table_unref (collections); - - g_simple_async_result_complete (res); -} - -static void -on_collection_loading (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); - GSecretService *self = GSECRET_SERVICE (g_async_result_get_source_object (user_data)); - LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res); - GSecretCollection *collection; - const gchar *collection_path; - GError *error = NULL; - - closure->collections_loading--; - - collection = gsecret_collection_new_finish (result, &error); - - if (error != NULL) - g_simple_async_result_take_error (res, error); - - if (collection != NULL) { - collection_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self)); - g_hash_table_insert (closure->collections, g_strdup (collection_path), collection); - } - - if (closure->collections_loading == 0) - load_collections_complete (self, res); - - g_object_unref (self); - g_object_unref (res); -} - -static void -load_collections_perform (GSecretService *self, - GSimpleAsyncResult *res, - GVariant *collection_paths) -{ - LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res); - GSecretCollection *collection; - gchar *collection_path; - GVariantIter iter; - - g_variant_iter_init (&iter, collection_paths); - while (g_variant_iter_loop (&iter, "o", &collection_path)) { - - /* Lookup the collection */ - g_mutex_lock (&self->pv->mutex); - collection = g_hash_table_lookup (self->pv->collections, collection_path); - if (collection != NULL) - g_object_ref (collection); - g_mutex_unlock (&self->pv->mutex); - - if (collection == NULL) { - // TODO: xxxxx; - gsecret_collection_new (self, collection_path, closure->cancellable, - on_collection_loading, g_object_ref (res)); - closure->collections_loading++; - } else { - g_hash_table_insert (closure->collections, - g_strdup (collection_path), - collection); - } - } - - if (closure->collections_loading == 0) - load_collections_complete (self, res); - - g_variant_unref (collection_paths); -} - static void handle_property_changed (GSecretService *self, const gchar *property_name, GVariant *value) { - GSimpleAsyncResult *res; + gboolean perform; if (g_str_equal (property_name, "Collections")) { - res = load_result_new (self->pv->cancellable, NULL, NULL); - if (value == NULL) - value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Collections"); - else - g_variant_ref (value); - if (value == NULL) { - g_warning ("couldn't retrieve Service Collections property"); - g_simple_async_result_complete (res); - } else { - // TODO: yyyy; - load_collections_perform (self, res, value); - g_variant_unref (value); - } + g_mutex_lock (&self->pv->mutex); + perform = self->pv->collections != NULL; + g_mutex_unlock (&self->pv->mutex); - g_object_unref (res); + if (perform) + gsecret_service_ensure_collections (self, self->pv->cancellable, NULL, NULL); } } @@ -346,6 +243,7 @@ gsecret_service_class_init (GSecretServiceClass *klass) GDBusProxyClass *proxy_class = G_DBUS_PROXY_CLASS (klass); object_class->get_property = gsecret_service_get_property; + object_class->set_property = gsecret_service_set_property; object_class->dispose = gsecret_service_dispose; object_class->finalize = gsecret_service_finalize; @@ -358,9 +256,198 @@ gsecret_service_class_init (GSecretServiceClass *klass) klass->item_gtype = GSECRET_TYPE_ITEM; klass->collection_gtype = GSECRET_TYPE_COLLECTION; + g_object_class_install_property (object_class, PROP_FLAGS, + g_param_spec_flags ("flags", "Flags", "Service flags", + g_secret_service_flags_get_type (), GSECRET_SERVICE_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_COLLECTIONS, + g_param_spec_boxed ("collections", "Collections", "Secret Service Collections", + _gsecret_list_get_type (), G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_type_class_add_private (klass, sizeof (GSecretServicePrivate)); } +typedef struct { + GCancellable *cancellable; + GSecretServiceFlags flags; +} InitClosure; + +static void +init_closure_free (gpointer data) +{ + InitClosure *closure = data; + g_clear_object (&closure->cancellable); + g_slice_free (InitClosure, closure); +} + +static gboolean +service_ensure_for_flags_sync (GSecretService *self, + GSecretServiceFlags flags, + GCancellable *cancellable, + GError **error) +{ + if (flags & GSECRET_SERVICE_OPEN_SESSION) + if (!gsecret_service_ensure_session_sync (self, cancellable, error)) + return FALSE; + + if (flags & GSECRET_SERVICE_LOAD_COLLECTIONS) + if (!gsecret_service_ensure_collections_sync (self, cancellable, error)) + return FALSE; + + return TRUE; +} + +static void +on_ensure_collections (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); + GSecretService *self = GSECRET_SERVICE (source); + GError *error = NULL; + + if (!gsecret_service_ensure_collections_finish (self, result, &error)) + g_simple_async_result_take_error (res, error); + + g_simple_async_result_complete (res); + g_object_unref (res); +} + +static void +on_ensure_session (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); + InitClosure *closure = g_simple_async_result_get_op_res_gpointer (res); + GSecretService *self = GSECRET_SERVICE (source); + GError *error = NULL; + + if (!gsecret_service_ensure_session_finish (self, result, &error)) { + g_simple_async_result_take_error (res, error); + g_simple_async_result_complete (res); + + } else if (closure->flags & GSECRET_SERVICE_LOAD_COLLECTIONS) { + gsecret_service_ensure_collections (self, closure->cancellable, + on_ensure_collections, g_object_ref (res)); + + } else { + g_simple_async_result_complete_in_idle (res); + } + + g_object_unref (res); +} + +static void +service_ensure_for_flags_async (GSecretService *self, + GSecretServiceFlags flags, + GSimpleAsyncResult *res) +{ + InitClosure *closure = g_simple_async_result_get_op_res_gpointer (res); + + closure->flags = flags; + + if (closure->flags & GSECRET_SERVICE_OPEN_SESSION) + gsecret_service_ensure_session (self, closure->cancellable, + on_ensure_session, g_object_ref (res)); + + else if (closure->flags & GSECRET_SERVICE_LOAD_COLLECTIONS) + gsecret_service_ensure_collections (self, closure->cancellable, + on_ensure_collections, g_object_ref (res)); + + else + g_simple_async_result_complete_in_idle (res); +} + +static gboolean +gsecret_service_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + GSecretService *self; + + if (!gsecret_service_initable_parent_iface->init (initable, cancellable, error)) + return FALSE; + + self = GSECRET_SERVICE (initable); + return service_ensure_for_flags_sync (self, self->pv->init_flags, cancellable, error); +} + +static void +gsecret_service_initable_iface (GInitableIface *iface) +{ + gsecret_service_initable_parent_iface = g_type_interface_peek_parent (iface); + + iface->init = gsecret_service_initable_init; +} + +static void +on_init_base (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); + GSecretService *self = GSECRET_SERVICE (source); + GError *error = NULL; + + if (!gsecret_service_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self), + result, &error)) { + g_simple_async_result_take_error (res, error); + g_simple_async_result_complete (res); + } + + service_ensure_for_flags_async (self, self->pv->init_flags, res); + g_object_unref (res); +} + +static void +gsecret_service_async_initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *res; + InitClosure *closure; + + res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, + gsecret_service_async_initable_init_async); + closure = g_slice_new0 (InitClosure); + closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + g_simple_async_result_set_op_res_gpointer (res, closure, init_closure_free); + + gsecret_service_async_initable_parent_iface->init_async (initable, io_priority, + cancellable, + on_init_base, + g_object_ref (res)); + + g_object_unref (res); +} + +static gboolean +gsecret_service_async_initable_init_finish (GAsyncInitable *initable, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable), + gsecret_service_async_initable_init_async), FALSE); + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) + return FALSE; + + return TRUE; +} + +static void +gsecret_service_async_initable_iface (GAsyncInitableIface *iface) +{ + gsecret_service_async_initable_parent_iface = g_type_interface_peek_parent (iface); + + iface->init_async = gsecret_service_async_initable_init_async; + iface->init_finish = gsecret_service_async_initable_init_finish; +} + void _gsecret_service_set_default_bus_name (const gchar *bus_name) { @@ -380,293 +467,208 @@ on_service_instance_gone (gpointer user_data, G_UNLOCK (service_instance); } -GSecretService * -_gsecret_service_bare_instance (GDBusConnection *connection, - const gchar *bus_name) -{ - GSecretService *service = NULL; - GError *error = NULL; - - g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); - - G_LOCK (service_instance); - - if (service_instance != NULL) - service = g_object_ref (service_instance); - - G_UNLOCK (service_instance); - - if (service != NULL) - return service; - - /* Alternate bus name is only used for testing */ - if (bus_name == NULL) - bus_name = default_bus_name; - - service = g_initable_new (GSECRET_TYPE_SERVICE, NULL, &error, - "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - "g-interface-info", _gsecret_gen_service_interface_info (), - "g-name", bus_name, - "g-connection", connection, - "g-object-path", GSECRET_SERVICE_PATH, - "g-interface-name", GSECRET_SERVICE_INTERFACE, - NULL); - - if (error != NULL) { - g_warning ("couldn't create GSecretService object: %s", error->message); - g_clear_error (&error); - return NULL; - } - - g_assert (GSECRET_IS_SERVICE (service)); - - G_LOCK (service_instance); - - if (service_instance == NULL) { - service_instance = service; - g_object_weak_ref (G_OBJECT (service), on_service_instance_gone, NULL); - } else { - g_object_unref (service); - service = g_object_ref (service_instance); - } - - G_UNLOCK (service_instance); - - return service; -} - -typedef struct { - GCancellable *cancellable; - GSecretService *service; - gboolean ensure_session; - gchar *bus_name; -} ConnectClosure; - -static void -connect_closure_free (gpointer data) -{ - ConnectClosure *closure = data; - g_clear_object (&closure->cancellable); - g_clear_object (&closure->service); - g_slice_free (ConnectClosure, closure); -} - -static void -on_connect_ensure (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); - GError *error = NULL; - - gsecret_service_ensure_session_finish (GSECRET_SERVICE (source), result, &error); - if (error != NULL) - g_simple_async_result_take_error (res, error); - - g_simple_async_result_complete (res); - g_object_unref (res); -} - -static void -on_connect_bus (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); - ConnectClosure *closure = g_simple_async_result_get_op_res_gpointer (res); - GDBusConnection *connection; - GError *error = NULL; - - connection = g_bus_get_finish (result, &error); - if (error == NULL) { - closure->service = _gsecret_service_bare_instance (connection, closure->bus_name); - if (closure->ensure_session) - gsecret_service_ensure_session (closure->service, closure->cancellable, - on_connect_ensure, g_object_ref (res)); - - else - g_simple_async_result_complete (res); - - g_object_unref (connection); - - } else { - g_simple_async_result_take_error (res, error); - g_simple_async_result_complete (res); - } - - g_object_unref (res); -} - void -_gsecret_service_bare_connect (const gchar *bus_name, - gboolean ensure_session, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *res; - ConnectClosure *closure; - - g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); - - if (bus_name == NULL) - bus_name = default_bus_name; - - res = g_simple_async_result_new (NULL, callback, user_data, - _gsecret_service_bare_connect); - closure = g_slice_new0 (ConnectClosure); - closure->bus_name = g_strdup (bus_name); - closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - closure->ensure_session = ensure_session; - g_simple_async_result_set_op_res_gpointer (res, closure, connect_closure_free); - - g_bus_get (G_BUS_TYPE_SESSION, cancellable, on_connect_bus, g_object_ref (res)); - - g_object_unref (res); -} - -GSecretService * -_gsecret_service_bare_connect_finish (GAsyncResult *result, - GError **error) -{ - ConnectClosure *closure; - GSimpleAsyncResult *res; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, - _gsecret_service_bare_connect), NULL); - - res = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (res, error)) - return NULL; - - closure = g_simple_async_result_get_op_res_gpointer (res); - return g_object_ref (closure->service); -} - -typedef struct { - GCancellable *cancellable; - GSecretService *service; -} ServiceClosure; - -static void -service_closure_free (gpointer data) -{ - ServiceClosure *closure = data; - g_clear_object (&closure->cancellable); - g_clear_object (&closure->service); - g_slice_free (ServiceClosure, closure); -} - -static void -on_service_properties (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); - GError *error = NULL; - - _gsecret_util_get_properties_finish (G_DBUS_PROXY (source), - gsecret_service_get, - result, &error); - - if (error != NULL) - g_simple_async_result_take_error (res, error); - g_simple_async_result_complete (res); - - g_object_unref (res); -} - -static void -on_service_connected (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); - ServiceClosure *closure = g_simple_async_result_get_op_res_gpointer (res); - GError *error = NULL; - - closure->service = _gsecret_service_bare_connect_finish (result, &error); - if (error != NULL) - g_simple_async_result_take_error (res, error); - - _gsecret_util_get_properties (G_DBUS_PROXY (closure->service), - gsecret_service_get, closure->cancellable, - on_service_properties, g_object_ref (res)); - - g_object_unref (res); -} - -void -gsecret_service_get (GCancellable *cancellable, +gsecret_service_get (GSecretServiceFlags flags, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + GSecretService *service = NULL; GSimpleAsyncResult *res; - ServiceClosure *closure; + InitClosure *closure; - g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + G_LOCK (service_instance); + if (service_instance != NULL) + service = g_object_ref (service_instance); + G_UNLOCK (service_instance); - res = g_simple_async_result_new (NULL, callback, user_data, - gsecret_service_get); - closure = g_slice_new0 (ServiceClosure); - closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - g_simple_async_result_set_op_res_gpointer (res, closure, service_closure_free); + /* Create a whole new service */ + if (service == NULL) { + g_async_initable_new_async (GSECRET_TYPE_SERVICE, G_PRIORITY_DEFAULT, + cancellable, callback, user_data, + "g-flags", G_DBUS_PROXY_FLAGS_NONE, + "g-interface-info", _gsecret_gen_service_interface_info (), + "g-name", default_bus_name, + "g-bus-type", G_BUS_TYPE_SESSION, + "g-object-path", GSECRET_SERVICE_PATH, + "g-interface-name", GSECRET_SERVICE_INTERFACE, + "flags", flags, + NULL); - _gsecret_service_bare_connect (NULL, FALSE, cancellable, - on_service_connected, g_object_ref (res)); + /* Just have to ensure that the service matches flags */ + } else { + res = g_simple_async_result_new (G_OBJECT (service), callback, + user_data, gsecret_service_get); + closure = g_slice_new0 (InitClosure); + closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + closure->flags = flags; + g_simple_async_result_set_op_res_gpointer (res, closure, init_closure_free); - g_object_unref (res); + service_ensure_for_flags_async (service, flags, res); + + g_object_unref (res); + } } GSecretService * gsecret_service_get_finish (GAsyncResult *result, GError **error) { - GSimpleAsyncResult *res; - GSecretService *service; + GObject *service = NULL; + GObject *source_object; g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); - g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, - gsecret_service_get), NULL); - res = G_SIMPLE_ASYNC_RESULT (result); + source_object = g_async_result_get_source_object (result); - if (g_simple_async_result_propagate_error (res, error)) + /* Just ensuring that the service matches flags */ + if (g_simple_async_result_is_valid (result, source_object, gsecret_service_get)) { + if (!g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) + service = g_object_ref (source_object); + + /* Creating a whole new service */ + } else { + service = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error); + } + + if (source_object) + g_object_unref (source_object); + + if (service == NULL) return NULL; - service = g_simple_async_result_get_op_res_gpointer (res); - if (service != NULL) - g_object_ref (service); - return service; + return GSECRET_SERVICE (service); } GSecretService * -gsecret_service_get_sync (GCancellable *cancellable, +gsecret_service_get_sync (GSecretServiceFlags flags, + GCancellable *cancellable, GError **error) { - GSecretService *service; - GSecretSync *sync; + GSecretService *service = NULL; - g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + G_LOCK (service_instance); + if (service_instance != NULL) + service = g_object_ref (service_instance); + G_UNLOCK (service_instance); - sync = _gsecret_sync_new (); - g_main_context_push_thread_default (sync->context); + if (service == NULL) { + service = g_initable_new (GSECRET_TYPE_SERVICE, cancellable, error, + "g-flags", G_DBUS_PROXY_FLAGS_NONE, + "g-interface-info", _gsecret_gen_service_interface_info (), + "g-name", default_bus_name, + "g-bus-type", G_BUS_TYPE_SESSION, + "g-object-path", GSECRET_SERVICE_PATH, + "g-interface-name", GSECRET_SERVICE_INTERFACE, + "flags", flags, + NULL); + if (service == NULL) + return NULL; - gsecret_service_get (cancellable, _gsecret_sync_on_result, sync); + G_LOCK (service_instance); + if (service_instance == NULL) { + service_instance = service; + g_object_weak_ref (G_OBJECT (service), on_service_instance_gone, NULL); + } + G_UNLOCK (service_instance); - g_main_loop_run (sync->loop); - - service = gsecret_service_get_finish (sync->result, error); - - g_main_context_pop_thread_default (sync->context); - _gsecret_sync_free (sync); + } else { + if (!service_ensure_for_flags_sync (service, flags, cancellable, error)) { + g_object_unref (service); + return NULL; + } + } return service; } +void +gsecret_service_new (const gchar *service_bus_name, + GSecretServiceFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + if (service_bus_name == NULL) + service_bus_name = default_bus_name; + + g_async_initable_new_async (GSECRET_TYPE_SERVICE, G_PRIORITY_DEFAULT, + cancellable, callback, user_data, + "g-flags", G_DBUS_PROXY_FLAGS_NONE, + "g-interface-info", _gsecret_gen_service_interface_info (), + "g-name", service_bus_name, + "g-bus-type", G_BUS_TYPE_SESSION, + "g-object-path", GSECRET_SERVICE_PATH, + "g-interface-name", GSECRET_SERVICE_INTERFACE, + "flags", flags, + NULL); +} + +GSecretService * +gsecret_service_new_finish (GAsyncResult *result, + GError **error) +{ + GObject *source_object; + GObject *object; + + g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + source_object = g_async_result_get_source_object (result); + object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), + result, error); + g_object_unref (source_object); + + if (object == NULL) + return NULL; + + return GSECRET_SERVICE (object); +} + +GSecretService * +gsecret_service_new_sync (const gchar *service_bus_name, + GSecretServiceFlags flags, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); + + if (service_bus_name == NULL) + service_bus_name = default_bus_name; + + return g_initable_new (GSECRET_TYPE_SERVICE, cancellable, error, + "g-flags", G_DBUS_PROXY_FLAGS_NONE, + "g-interface-info", _gsecret_gen_service_interface_info (), + "g-name", service_bus_name, + "g-bus-type", G_BUS_TYPE_SESSION, + "g-object-path", GSECRET_SERVICE_PATH, + "g-interface-name", GSECRET_SERVICE_INTERFACE, + "flags", flags, + NULL); +} + +GSecretServiceFlags +gsecret_service_get_flags (GSecretService *self) +{ + GSecretServiceFlags flags = 0; + + g_return_val_if_fail (GSECRET_IS_SERVICE (self), GSECRET_SERVICE_NONE); + + g_mutex_lock (&self->pv->mutex); + + if (self->pv->session) + flags |= GSECRET_SERVICE_OPEN_SESSION; + if (self->pv->collections) + flags |= GSECRET_SERVICE_LOAD_COLLECTIONS; + + g_mutex_unlock (&self->pv->mutex); + + return flags; +} + GList * gsecret_service_get_collections (GSecretService *self) { @@ -675,9 +677,16 @@ gsecret_service_get_collections (GSecretService *self) g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL); g_mutex_lock (&self->pv->mutex); - collections = g_hash_table_get_values (self->pv->collections); - for (l = collections; l != NULL; l = g_list_next (l)) - g_object_ref (l->data); + + if (self->pv->collections == NULL) { + collections = NULL; + + } else { + collections = g_hash_table_get_values (self->pv->collections); + for (l = collections; l != NULL; l = g_list_next (l)) + g_object_ref (l->data); + } + g_mutex_unlock (&self->pv->mutex); return collections; @@ -719,7 +728,7 @@ _gsecret_service_get_session (GSecretService *self) g_mutex_lock (&self->pv->mutex); session = self->pv->session; - g_mutex_lock (&self->pv->mutex); + g_mutex_unlock (&self->pv->mutex); return session; } @@ -815,7 +824,7 @@ gsecret_service_ensure_session_finish (GSecretService *self, } g_return_val_if_fail (self->pv->session != NULL, NULL); - return gsecret_service_get_session_path (self->pv->session); + return gsecret_service_get_session_path (self); } const gchar * @@ -846,19 +855,146 @@ gsecret_service_ensure_session_sync (GSecretService *self, return path; } -#if 0 +static GSecretCollection * +service_lookup_collection (GSecretService *self, + const gchar *path) +{ + GSecretCollection *collection = NULL; + + g_mutex_lock (&self->pv->mutex); + + if (self->pv->collections) { + collection = g_hash_table_lookup (self->pv->collections, path); + if (collection != NULL) + g_object_ref (collection); + } + + g_mutex_unlock (&self->pv->mutex); + + return collection; +} + +static void +service_update_collections (GSecretService *self, + GHashTable *collections) +{ + GHashTable *previous; + + g_hash_table_ref (collections); + + g_mutex_lock (&self->pv->mutex); + + previous = self->pv->collections; + self->pv->collections = collections; + + g_mutex_unlock (&self->pv->mutex); + + if (previous != NULL) + g_hash_table_unref (previous); +} + +typedef struct { + GCancellable *cancellable; + GHashTable *collections; + gint collections_loading; +} EnsureClosure; + +static GHashTable * +collections_table_new (void) +{ + return g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); +} + +static void +ensure_closure_free (gpointer data) +{ + EnsureClosure *closure = data; + g_clear_object (&closure->cancellable); + g_hash_table_unref (closure->collections); + g_slice_free (EnsureClosure, closure); +} + +static void +on_ensure_collection (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); + GSecretService *self = GSECRET_SERVICE (g_async_result_get_source_object (user_data)); + EnsureClosure *closure = g_simple_async_result_get_op_res_gpointer (res); + GSecretCollection *collection; + const gchar *path; + GError *error = NULL; + + closure->collections_loading--; + + collection = gsecret_collection_new_finish (result, &error); + + if (error != NULL) + g_simple_async_result_take_error (res, error); + + if (collection != NULL) { + path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self)); + g_hash_table_insert (closure->collections, g_strdup (path), collection); + } + + if (closure->collections_loading == 0) { + service_update_collections (self, closure->collections); + g_simple_async_result_complete (res); + } + + g_object_unref (self); + g_object_unref (res); +} + void gsecret_service_ensure_collections (GSecretService *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + EnsureClosure *closure; + GSecretCollection *collection; GSimpleAsyncResult *res; + const gchar *path; + GVariant *paths; + GVariantIter iter; g_return_if_fail (GSECRET_IS_SERVICE (self)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Collections"); + g_return_if_fail (paths == NULL); + res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, + gsecret_service_ensure_collections); + closure = g_slice_new0 (EnsureClosure); + closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + closure->collections = collections_table_new (); + g_simple_async_result_set_op_res_gpointer (res, closure, ensure_closure_free); + + g_variant_iter_init (&iter, paths); + while (g_variant_iter_loop (&iter, "&o", &path)) { + collection = service_lookup_collection (self, path); + + /* No such collection yet create a new one */ + if (collection == NULL) { + gsecret_collection_new (self, path, cancellable, + on_ensure_collection, g_object_ref (res)); + closure->collections_loading++; + } else { + g_hash_table_insert (closure->collections, g_strdup (path), collection); + } + } + + if (closure->collections_loading == 0) { + service_update_collections (self, closure->collections); + g_simple_async_result_complete_in_idle (res); + } + + g_variant_unref (paths); + g_object_unref (res); } gboolean @@ -871,7 +1007,10 @@ gsecret_service_ensure_collections_finish (GSecretService *self, g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), gsecret_service_ensure_collections), FALSE); + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) + return FALSE; + return TRUE; } gboolean @@ -879,13 +1018,45 @@ gsecret_service_ensure_collections_sync (GSecretService *self, GCancellable *cancellable, GError **error) { + GSecretCollection *collection; + GHashTable *collections; + GVariant *paths; + GVariantIter iter; + const gchar *path; + gboolean ret = TRUE; + g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Collections"); + g_return_val_if_fail (paths == NULL, FALSE); + collections = collections_table_new (); + + g_variant_iter_init (&iter, paths); + while (g_variant_iter_next (&iter, "&o", &path)) { + collection = service_lookup_collection (self, path); + + /* No such collection yet create a new one */ + if (collection == NULL) { + collection = gsecret_collection_new_sync (self, path, cancellable, error); + if (collection == NULL) { + ret = FALSE; + break; + } + } + + g_hash_table_insert (collections, g_strdup (path), collection); + } + + if (ret) + service_update_collections (self, collections); + + g_hash_table_unref (collections); + g_variant_unref (paths); + return ret; } -#endif static void on_search_items_complete (GObject *source, diff --git a/library/gsecret-service.h b/library/gsecret-service.h index 197a1fa..b2eb012 100644 --- a/library/gsecret-service.h +++ b/library/gsecret-service.h @@ -22,6 +22,12 @@ G_BEGIN_DECLS +typedef enum { + GSECRET_SERVICE_NONE, + GSECRET_SERVICE_OPEN_SESSION = 1 << 1, + GSECRET_SERVICE_LOAD_COLLECTIONS = 1 << 2, +} GSecretServiceFlags; + #define GSECRET_TYPE_SERVICE (gsecret_service_get_type ()) #define GSECRET_SERVICE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GSECRET_TYPE_SERVICE, GSecretService)) #define GSECRET_SERVICE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GSECRET_TYPE_SERVICE, GSecretServiceClass)) @@ -63,16 +69,34 @@ struct _GSecretServiceClass { GType gsecret_service_get_type (void) G_GNUC_CONST; -void gsecret_service_get (GCancellable *cancellable, +void gsecret_service_get (GSecretServiceFlags flags, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); GSecretService * gsecret_service_get_finish (GAsyncResult *result, GError **error); -GSecretService * gsecret_service_get_sync (GCancellable *cancellable, +GSecretService * gsecret_service_get_sync (GSecretServiceFlags flags, + GCancellable *cancellable, GError **error); +void gsecret_service_new (const gchar *service_bus_name, + GSecretServiceFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +GSecretService * gsecret_service_new_finish (GAsyncResult *result, + GError **error); + +GSecretService * gsecret_service_new_sync (const gchar *service_bus_name, + GSecretServiceFlags flags, + GCancellable *cancellable, + GError **error); + +GSecretServiceFlags gsecret_service_get_flags (GSecretService *self); + const gchar * gsecret_service_get_session_algorithms (GSecretService *self); const gchar * gsecret_service_get_session_path (GSecretService *self); diff --git a/library/gsecret-session.c b/library/gsecret-session.c index 7548ad7..e691459 100644 --- a/library/gsecret-session.c +++ b/library/gsecret-session.c @@ -334,20 +334,14 @@ _gsecret_session_open (GSecretService *service, g_object_unref (res); } -GSecretSession * +gboolean _gsecret_session_open_finish (GAsyncResult *result, GError **error) { - OpenSessionClosure *closure; - GSecretSession *session; - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) - return NULL; + return FALSE; - closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)); - session = closure->session; - closure->session = NULL; - return session; + return TRUE; } #ifdef WITH_GCRYPT diff --git a/library/tests/test-collection.c b/library/tests/test-collection.c index 7b0f3c3..1ac00d0 100644 --- a/library/tests/test-collection.c +++ b/library/tests/test-collection.c @@ -29,7 +29,6 @@ #include typedef struct { - GDBusConnection *connection; GSecretService *service; } Test; @@ -43,26 +42,18 @@ setup (Test *test, mock_service_start (mock_script, &error); g_assert_no_error (error); - test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + test->service = gsecret_service_get_sync (GSECRET_SERVICE_NONE, NULL, &error); g_assert_no_error (error); - - test->service = _gsecret_service_bare_instance (test->connection, NULL); } static void teardown (Test *test, gconstpointer unused) { - GError *error = NULL; - g_object_unref (test->service); egg_assert_not_object (test->service); mock_service_stop (); - - g_dbus_connection_flush_sync (test->connection, NULL, &error); - g_assert_no_error (error); - g_object_unref (test->connection); } static void diff --git a/library/tests/test-item.c b/library/tests/test-item.c index 9bf239d..3cf8565 100644 --- a/library/tests/test-item.c +++ b/library/tests/test-item.c @@ -29,7 +29,6 @@ #include typedef struct { - GDBusConnection *connection; GSecretService *service; } Test; @@ -43,26 +42,18 @@ setup (Test *test, mock_service_start (mock_script, &error); g_assert_no_error (error); - test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + test->service = gsecret_service_get_sync (GSECRET_SERVICE_NONE, NULL, &error); g_assert_no_error (error); - - test->service = _gsecret_service_bare_instance (test->connection, NULL); } static void teardown (Test *test, gconstpointer unused) { - GError *error = NULL; - g_object_unref (test->service); egg_assert_not_object (test->service); mock_service_stop (); - - g_dbus_connection_flush_sync (test->connection, NULL, &error); - g_assert_no_error (error); - g_object_unref (test->connection); } static void @@ -87,7 +78,6 @@ on_notify_stop (GObject *obj, g_assert (*sigs > 0); if (--(*sigs) == 0) egg_test_wait_stop (); -g_printerr ("sigs: %u\n", *sigs); } static void @@ -520,15 +510,14 @@ main (int argc, char **argv) g_test_add ("/item/properties", Test, "mock-service-normal.py", setup, test_properties, teardown); g_test_add ("/item/set-label-sync", Test, "mock-service-normal.py", setup, test_set_label_sync, teardown); g_test_add ("/item/set-label-async", Test, "mock-service-normal.py", setup, test_set_label_async, teardown); + g_test_add ("/item/set-label-prop", Test, "mock-service-normal.py", setup, test_set_label_prop, teardown); g_test_add ("/item/set-attributes-sync", Test, "mock-service-normal.py", setup, test_set_attributes_sync, teardown); g_test_add ("/item/set-attributes-async", Test, "mock-service-normal.py", setup, test_set_attributes_async, teardown); + g_test_add ("/item/set-attributes-prop", Test, "mock-service-normal.py", setup, test_set_attributes_prop, teardown); g_test_add ("/item/get-secret-sync", Test, "mock-service-normal.py", setup, test_get_secret_sync, teardown); g_test_add ("/item/get-secret-async", Test, "mock-service-normal.py", setup, test_get_secret_async, teardown); g_test_add ("/item/delete-sync", Test, "mock-service-normal.py", setup, test_delete_sync, teardown); g_test_add ("/item/delete-async", Test, "mock-service-normal.py", setup, test_delete_async, teardown); - g_test_add ("/item/set-attributes-prop", Test, "mock-service-normal.py", setup, test_set_attributes_prop, teardown); - g_test_add ("/item/set-label-prop", Test, "mock-service-normal.py", setup, test_set_label_prop, teardown); - return egg_tests_run_with_loop (); } diff --git a/library/tests/test-prompt.c b/library/tests/test-prompt.c index 7283076..d01a41a 100644 --- a/library/tests/test-prompt.c +++ b/library/tests/test-prompt.c @@ -30,7 +30,6 @@ #include typedef struct { - GDBusConnection *connection; GSecretService *service; } Test; @@ -44,26 +43,18 @@ setup (Test *test, mock_service_start (mock_script, &error); g_assert_no_error (error); - test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + test->service = gsecret_service_get_sync (GSECRET_SERVICE_NONE, NULL, &error); g_assert_no_error (error); - - test->service = _gsecret_service_bare_instance (test->connection, NULL); } static void teardown (Test *test, gconstpointer unused) { - GError *error = NULL; - g_object_unref (test->service); egg_assert_not_object (test->service); mock_service_stop (); - - g_dbus_connection_flush_sync (test->connection, NULL, &error); - g_assert_no_error (error); - g_object_unref (test->connection); } diff --git a/library/tests/test-service.c b/library/tests/test-service.c index 61f7b8e..619d66a 100644 --- a/library/tests/test-service.c +++ b/library/tests/test-service.c @@ -25,8 +25,6 @@ #include #include -static gchar *MOCK_NAME = "org.mock.Service"; - static const GSecretSchema DELETE_SCHEMA = { "org.mock.schema.Delete", { @@ -37,8 +35,6 @@ static const GSecretSchema DELETE_SCHEMA = { }; typedef struct { - GPid pid; - GDBusConnection *connection; GSecretService *service; } Test; @@ -61,10 +57,8 @@ setup (Test *test, setup_mock (test, data); - test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + test->service = gsecret_service_get_sync (GSECRET_SERVICE_NONE, NULL, &error); g_assert_no_error (error); - - test->service = _gsecret_service_bare_instance (test->connection, NULL); } static void @@ -83,8 +77,6 @@ teardown (Test *test, g_object_unref (test->service); egg_assert_not_object (test->service); - g_clear_object (&test->connection); - teardown_mock (test, unused); } @@ -107,15 +99,14 @@ test_instance (void) GSecretService *service2; GSecretService *service3; GError *error = NULL; - GDBusConnection *connection; - - connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); - g_assert_no_error (error); /* Both these sohuld point to the same thing */ - service1 = _gsecret_service_bare_instance (connection, MOCK_NAME); - service2 = _gsecret_service_bare_instance (connection, MOCK_NAME); + service1 = gsecret_service_get_sync (GSECRET_SERVICE_NONE, NULL, &error); + g_assert_no_error (error); + + service2 = gsecret_service_get_sync (GSECRET_SERVICE_NONE, NULL, &error); + g_assert_no_error (error); g_assert (GSECRET_IS_SERVICE (service1)); g_assert (service1 == service2); @@ -127,18 +118,17 @@ test_instance (void) egg_assert_not_object (service2); /* Services were unreffed, so this should create a new one */ - service3 = _gsecret_service_bare_instance (connection, MOCK_NAME); + service3 = gsecret_service_get_sync (GSECRET_SERVICE_NONE, NULL, &error); g_assert (GSECRET_IS_SERVICE (service3)); + g_assert_no_error (error); g_object_unref (service3); egg_assert_not_object (service3); - - g_object_unref (connection); } static void -test_connect_sync (Test *test, - gconstpointer used) +test_connect_async (Test *test, + gconstpointer used) { GError *error = NULL; GAsyncResult *result = NULL; @@ -146,12 +136,12 @@ test_connect_sync (Test *test, const gchar *path; /* Passing false, not session */ - _gsecret_service_bare_connect (MOCK_NAME, FALSE, NULL, on_complete_get_result, &result); + gsecret_service_get (GSECRET_SERVICE_NONE, NULL, on_complete_get_result, &result); g_assert (result == NULL); egg_test_wait (); - service = _gsecret_service_bare_connect_finish (result, &error); + service = gsecret_service_get_finish (result, &error); g_assert (GSECRET_IS_SERVICE (service)); g_assert_no_error (error); g_object_unref (result); @@ -164,8 +154,8 @@ test_connect_sync (Test *test, } static void -test_connect_ensure_sync (Test *test, - gconstpointer used) +test_connect_ensure_async (Test *test, + gconstpointer used) { GError *error = NULL; GAsyncResult *result = NULL; @@ -173,12 +163,12 @@ test_connect_ensure_sync (Test *test, const gchar *path; /* Passing true, ensures session is established */ - _gsecret_service_bare_connect (MOCK_NAME, TRUE, NULL, on_complete_get_result, &result); + gsecret_service_get (GSECRET_SERVICE_OPEN_SESSION, NULL, on_complete_get_result, &result); g_assert (result == NULL); egg_test_wait (); - service = _gsecret_service_bare_connect_finish (result, &error); + service = gsecret_service_get_finish (result, &error); g_assert_no_error (error); g_assert (GSECRET_IS_SERVICE (service)); g_object_unref (result); @@ -593,8 +583,8 @@ main (int argc, char **argv) g_test_add_func ("/service/instance", test_instance); - g_test_add ("/service/connect-sync", Test, "mock-service-normal.py", setup_mock, test_connect_sync, teardown_mock); - g_test_add ("/service/connect-ensure-sync", Test, "mock-service-normal.py", setup_mock, test_connect_ensure_sync, teardown_mock); + g_test_add ("/service/connect-sync", Test, "mock-service-normal.py", setup_mock, test_connect_async, teardown_mock); + g_test_add ("/service/connect-ensure-sync", Test, "mock-service-normal.py", setup_mock, test_connect_ensure_async, teardown_mock); g_test_add ("/service/search-for-paths", Test, "mock-service-normal.py", setup, test_search_paths, teardown); g_test_add ("/service/search-for-paths-async", Test, "mock-service-normal.py", setup, test_search_paths_async, teardown); diff --git a/library/tests/test-session.c b/library/tests/test-session.c index 08c689d..125c78b 100644 --- a/library/tests/test-session.c +++ b/library/tests/test-session.c @@ -27,8 +27,6 @@ #include typedef struct { - GPid pid; - GDBusConnection *connection; GSecretService *service; } Test; @@ -42,26 +40,18 @@ setup (Test *test, mock_service_start (mock_script, &error); g_assert_no_error (error); - test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + test->service = gsecret_service_get_sync (GSECRET_SERVICE_NONE, NULL, &error); g_assert_no_error (error); - - test->service = _gsecret_service_bare_instance (test->connection, NULL); } static void teardown (Test *test, gconstpointer unused) { - GError *error = NULL; - g_object_unref (test->service); egg_assert_not_object (test->service); mock_service_stop (); - - g_dbus_connection_flush_sync (test->connection, NULL, &error); - g_assert_no_error (error); - g_object_unref (test->connection); } static void diff --git a/po/POTFILES.in b/po/POTFILES.in index ce1ace3..1ac9a1d 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,2 +1,2 @@ library/gsecret-item.c -library/gsecret-service.c +library/gsecret-session.c