summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2012-01-25 14:26:52 +0100
committerStef Walter <stefw@gnome.org>2012-02-03 20:44:44 +0100
commitc6c6afa2cc95aff8344bcc264b89f98fbb63e931 (patch)
treedf61eac746dcc9808ceca81f1007a37bfe6f4630
parentf44aae6efa58c388bebd5778a169a62c6ddf3525 (diff)
downloadlibsecret-c6c6afa2cc95aff8344bcc264b89f98fbb63e931.tar.gz
Rework how the initialization work for various proxy objects
* Fix bugs and tests
-rw-r--r--.gitignore1
-rw-r--r--configure.ac2
-rw-r--r--library/Makefile.am24
-rw-r--r--library/gsecret-collection.c442
-rw-r--r--library/gsecret-enum-types.c.template43
-rw-r--r--library/gsecret-enum-types.h.template28
-rw-r--r--library/gsecret-item.c157
-rw-r--r--library/gsecret-password.c19
-rw-r--r--library/gsecret-private.h4
-rw-r--r--library/gsecret-service.c873
-rw-r--r--library/gsecret-service.h28
-rw-r--r--library/gsecret-session.c12
-rw-r--r--library/tests/test-collection.c11
-rw-r--r--library/tests/test-item.c17
-rw-r--r--library/tests/test-prompt.c11
-rw-r--r--library/tests/test-service.c46
-rw-r--r--library/tests/test-session.c12
-rw-r--r--po/POTFILES.in2
18 files changed, 1091 insertions, 641 deletions
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);
}
-typedef struct {
- GSecretCollection *collection;
- GCancellable *cancellable;
- GHashTable *items;
- gint items_loading;
-} LoadClosure;
-
-static void
-load_closure_free (gpointer data)
+static GSecretItem *
+collection_lookup_item (GSecretCollection *self,
+ const gchar *path)
{
- LoadClosure *closure = data;
- g_object_unref (closure->collection);
- g_clear_object (&closure->cancellable);
- g_hash_table_unref (closure->items);
- g_slice_free (LoadClosure, closure);
-}
+ GSecretItem *item = NULL;
-static GSimpleAsyncResult *
-load_result_new (GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *res;
- LoadClosure *closure;
+ g_mutex_lock (&self->pv->mutex);
- 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);
+ item = g_hash_table_lookup (self->pv->items, path);
+ if (item != NULL)
+ g_object_ref (item);
+
+ g_mutex_unlock (&self->pv->mutex);
- return res;
+ return item;
}
static void
-load_items_complete (GSimpleAsyncResult *res)
+collection_update_items (GSecretCollection *self,
+ GHashTable *items)
{
- LoadClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
- GSecretCollection *self = closure->collection;
- GHashTable *items;
+ GHashTable *previous;
- g_assert (closure->items_loading == 0);
-
- g_hash_table_ref (closure->items);
+ g_hash_table_ref (items);
g_mutex_lock (&self->pv->mutex);
- items = self->pv->items;
- self->pv->items = closure->items;
+ previous = self->pv->items;
+ self->pv->items = items;
g_mutex_unlock (&self->pv->mutex);
- g_hash_table_unref (items);
+ g_hash_table_unref (previous);
+}
- g_simple_async_result_complete (res);
+typedef struct {
+ GCancellable *cancellable;
+ GHashTable *items;
+ gint items_loading;
+} ItemsClosure;
+
+static void
+items_closure_free (gpointer data)
+{
+ ItemsClosure *closure = data;
+ g_clear_object (&closure->cancellable);
+ g_hash_table_unref (closure->items);
+ g_slice_free (ItemsClosure, closure);
}
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);
- closure->collection = g_object_ref (self);
+ paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
+ g_return_if_fail (paths != NULL);
- g_variant_iter_init (&iter, item_paths);
- while (g_variant_iter_loop (&iter, "o", &item_path)) {
+ 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_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) {
+ 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 (closure->items_loading == 0)
- load_items_complete (res);
+ 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);
-
- // 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);
+ proxy = G_DBUS_PROXY (service);
- 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 <glib-object.h>
+
+#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 <gsecret/gsecret.h> can be included directly."
+#endif
+
+#ifndef __GSECRET_ENUM_TYPES_H__
+#define __GSECRET_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+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 gboolean
+gsecret_item_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDBusProxy *proxy;
+
+ 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
-all_properties_changed (GSecretItem *item)
+gsecret_item_initable_iface (GInitableIface *iface)
{
- GObject *obj = G_OBJECT (item);
- gchar **property_names;
- guint i;
+ gsecret_item_initable_parent_iface = g_type_interface_peek_parent (iface);
- 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);
+ 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);
-
- // 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);
+ proxy = G_DBUS_PROXY (service);
- 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;
@@ -91,6 +100,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)
{
GSecretService *self = GSECRET_SERVICE (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_object_unref (res);
+ g_mutex_lock (&self->pv->mutex);
+ perform = self->pv->collections != NULL;
+ g_mutex_unlock (&self->pv->mutex);
+
+ 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,313 +256,417 @@ 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));
}
-void
-_gsecret_service_set_default_bus_name (const gchar *bus_name)
+typedef struct {
+ GCancellable *cancellable;
+ GSecretServiceFlags flags;
+} InitClosure;
+
+static void
+init_closure_free (gpointer data)
{
- g_return_if_fail (bus_name != NULL);
- default_bus_name = bus_name;
+ InitClosure *closure = data;
+ g_clear_object (&closure->cancellable);
+ g_slice_free (InitClosure, closure);
}
-static void
-on_service_instance_gone (gpointer user_data,
- GObject *where_the_object_was)
+static gboolean
+service_ensure_for_flags_sync (GSecretService *self,
+ GSecretServiceFlags flags,
+ GCancellable *cancellable,
+ GError **error)
{
- G_LOCK (service_instance);
+ if (flags & GSECRET_SERVICE_OPEN_SESSION)
+ if (!gsecret_service_ensure_session_sync (self, cancellable, error))
+ return FALSE;
- g_assert (service_instance == where_the_object_was);
- service_instance = NULL;
+ if (flags & GSECRET_SERVICE_LOAD_COLLECTIONS)
+ if (!gsecret_service_ensure_collections_sync (self, cancellable, error))
+ return FALSE;
- G_UNLOCK (service_instance);
+ return TRUE;
}
-GSecretService *
-_gsecret_service_bare_instance (GDBusConnection *connection,
- const gchar *bus_name)
+static void
+on_ensure_collections (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GSecretService *service = NULL;
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GSecretService *self = GSECRET_SERVICE (source);
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);
+ if (!gsecret_service_ensure_collections_finish (self, result, &error))
+ g_simple_async_result_take_error (res, error);
- G_UNLOCK (service_instance);
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
- if (service != NULL)
- return service;
+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;
- /* Alternate bus name is only used for testing */
- if (bus_name == NULL)
- bus_name = default_bus_name;
+ if (!gsecret_service_ensure_session_finish (self, result, &error)) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
- 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);
+ } else if (closure->flags & GSECRET_SERVICE_LOAD_COLLECTIONS) {
+ gsecret_service_ensure_collections (self, closure->cancellable,
+ on_ensure_collections, g_object_ref (res));
- if (error != NULL) {
- g_warning ("couldn't create GSecretService object: %s", error->message);
- g_clear_error (&error);
- return NULL;
+ } else {
+ g_simple_async_result_complete_in_idle (res);
}
- g_assert (GSECRET_IS_SERVICE (service));
+ g_object_unref (res);
+}
- G_LOCK (service_instance);
+static void
+service_ensure_for_flags_async (GSecretService *self,
+ GSecretServiceFlags flags,
+ GSimpleAsyncResult *res)
+{
+ InitClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
- 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);
- }
+ closure->flags = flags;
- G_UNLOCK (service_instance);
+ if (closure->flags & GSECRET_SERVICE_OPEN_SESSION)
+ gsecret_service_ensure_session (self, closure->cancellable,
+ on_ensure_session, g_object_ref (res));
- return service;
-}
+ else if (closure->flags & GSECRET_SERVICE_LOAD_COLLECTIONS)
+ gsecret_service_ensure_collections (self, closure->cancellable,
+ on_ensure_collections, g_object_ref (res));
-typedef struct {
- GCancellable *cancellable;
- GSecretService *service;
- gboolean ensure_session;
- gchar *bus_name;
-} ConnectClosure;
+ else
+ g_simple_async_result_complete_in_idle (res);
+}
-static void
-connect_closure_free (gpointer data)
+static gboolean
+gsecret_service_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
{
- ConnectClosure *closure = data;
- g_clear_object (&closure->cancellable);
- g_clear_object (&closure->service);
- g_slice_free (ConnectClosure, closure);
+ 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
-on_connect_ensure (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
+gsecret_service_initable_iface (GInitableIface *iface)
{
- 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);
+ gsecret_service_initable_parent_iface = g_type_interface_peek_parent (iface);
- g_simple_async_result_complete (res);
- g_object_unref (res);
+ iface->init = gsecret_service_initable_init;
}
static void
-on_connect_bus (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
+on_init_base (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;
+ GSecretService *self = GSECRET_SERVICE (source);
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 {
+ 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);
}
-void
-_gsecret_service_bare_connect (const gchar *bus_name,
- gboolean ensure_session,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+static void
+gsecret_service_async_initable_init_async (GAsyncInitable *initable,
+ int io_priority,
+ 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;
+ InitClosure *closure;
- 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);
+ 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;
- closure->ensure_session = ensure_session;
- g_simple_async_result_set_op_res_gpointer (res, closure, connect_closure_free);
+ g_simple_async_result_set_op_res_gpointer (res, closure, init_closure_free);
- g_bus_get (G_BUS_TYPE_SESSION, cancellable, on_connect_bus, g_object_ref (res));
+ gsecret_service_async_initable_parent_iface->init_async (initable, io_priority,
+ cancellable,
+ on_init_base,
+ g_object_ref (res));
g_object_unref (res);
}
-GSecretService *
-_gsecret_service_bare_connect_finish (GAsyncResult *result,
- GError **error)
+static gboolean
+gsecret_service_async_initable_init_finish (GAsyncInitable *initable,
+ GAsyncResult *result,
+ GError **error)
{
- ConnectClosure *closure;
- GSimpleAsyncResult *res;
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable),
+ gsecret_service_async_initable_init_async), FALSE);
- 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);
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
- res = G_SIMPLE_ASYNC_RESULT (result);
- if (g_simple_async_result_propagate_error (res, error))
- return NULL;
+ return TRUE;
+}
- closure = g_simple_async_result_get_op_res_gpointer (res);
- return g_object_ref (closure->service);
+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;
}
-typedef struct {
- GCancellable *cancellable;
- GSecretService *service;
-} ServiceClosure;
+void
+_gsecret_service_set_default_bus_name (const gchar *bus_name)
+{
+ g_return_if_fail (bus_name != NULL);
+ default_bus_name = bus_name;
+}
static void
-service_closure_free (gpointer data)
+on_service_instance_gone (gpointer user_data,
+ GObject *where_the_object_was)
{
- ServiceClosure *closure = data;
- g_clear_object (&closure->cancellable);
- g_clear_object (&closure->service);
- g_slice_free (ServiceClosure, closure);
+ G_LOCK (service_instance);
+
+ g_assert (service_instance == where_the_object_was);
+ service_instance = NULL;
+
+ G_UNLOCK (service_instance);
}
-static void
-on_service_properties (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
+void
+gsecret_service_get (GSecretServiceFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- GError *error = NULL;
+ GSecretService *service = NULL;
+ GSimpleAsyncResult *res;
+ InitClosure *closure;
- _gsecret_util_get_properties_finish (G_DBUS_PROXY (source),
- gsecret_service_get,
- result, &error);
+ G_LOCK (service_instance);
+ if (service_instance != NULL)
+ service = g_object_ref (service_instance);
+ G_UNLOCK (service_instance);
- if (error != NULL)
- g_simple_async_result_take_error (res, error);
- g_simple_async_result_complete (res);
+ /* 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);
+
+ /* 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);
+ }
}
-static void
-on_service_connected (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
+GSecretService *
+gsecret_service_get_finish (GAsyncResult *result,
+ GError **error)
{
- GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- ServiceClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
- GError *error = NULL;
+ GObject *service = NULL;
+ GObject *source_object;
- closure->service = _gsecret_service_bare_connect_finish (result, &error);
- if (error != NULL)
- g_simple_async_result_take_error (res, error);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- _gsecret_util_get_properties (G_DBUS_PROXY (closure->service),
- gsecret_service_get, closure->cancellable,
- on_service_properties, g_object_ref (res));
+ source_object = g_async_result_get_source_object (result);
- g_object_unref (res);
+ /* 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;
+
+ return GSECRET_SERVICE (service);
+}
+
+GSecretService *
+gsecret_service_get_sync (GSecretServiceFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GSecretService *service = NULL;
+
+ G_LOCK (service_instance);
+ if (service_instance != NULL)
+ service = g_object_ref (service_instance);
+ G_UNLOCK (service_instance);
+
+ 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;
+
+ 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);
+
+ } else {
+ if (!service_ensure_for_flags_sync (service, flags, cancellable, error)) {
+ g_object_unref (service);
+ return NULL;
+ }
+ }
+
+ return service;
}
void
-gsecret_service_get (GCancellable *cancellable,
+gsecret_service_new (const gchar *service_bus_name,
+ GSecretServiceFlags flags,
+ GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GSimpleAsyncResult *res;
- ServiceClosure *closure;
-
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- 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);
-
- _gsecret_service_bare_connect (NULL, FALSE, cancellable,
- on_service_connected, g_object_ref (res));
+ if (service_bus_name == NULL)
+ service_bus_name = default_bus_name;
- g_object_unref (res);
+ 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_get_finish (GAsyncResult *result,
+gsecret_service_new_finish (GAsyncResult *result,
GError **error)
{
- GSimpleAsyncResult *res;
- GSecretService *service;
+ 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);
- 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);
+ 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;
- service = g_simple_async_result_get_op_res_gpointer (res);
- if (service != NULL)
- g_object_ref (service);
- return service;
+ return GSECRET_SERVICE (object);
}
GSecretService *
-gsecret_service_get_sync (GCancellable *cancellable,
+gsecret_service_new_sync (const gchar *service_bus_name,
+ GSecretServiceFlags flags,
+ GCancellable *cancellable,
GError **error)
{
- GSecretService *service;
- GSecretSync *sync;
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ if (service_bus_name == NULL)
+ service_bus_name = default_bus_name;
- sync = _gsecret_sync_new ();
- g_main_context_push_thread_default (sync->context);
+ 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);
+}
- gsecret_service_get (cancellable, _gsecret_sync_on_result, sync);
+GSecretServiceFlags
+gsecret_service_get_flags (GSecretService *self)
+{
+ GSecretServiceFlags flags = 0;
- g_main_loop_run (sync->loop);
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), GSECRET_SERVICE_NONE);
- service = gsecret_service_get_finish (sync->result, error);
+ g_mutex_lock (&self->pv->mutex);
- g_main_context_pop_thread_default (sync->context);
- _gsecret_sync_free (sync);
+ if (self->pv->session)
+ flags |= GSECRET_SERVICE_OPEN_SESSION;
+ if (self->pv->collections)
+ flags |= GSECRET_SERVICE_LOAD_COLLECTIONS;
- return service;
+ g_mutex_unlock (&self->pv->mutex);
+
+ return flags;
}
GList *
@@ -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 <stdlib.h>
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 <stdlib.h>
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 <stdlib.h>
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 <errno.h>
#include <stdlib.h>
-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 <stdlib.h>
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