[gnome-keyring] gcr: Don't initialize pkcs11 modules automatically.



commit 0211c4b844e0cc84370ec1ef46ede8d1bffef209
Author: Stef Walter <stefw collabora co uk>
Date:   Thu Aug 25 14:25:58 2011 +0200

    gcr: Don't initialize pkcs11 modules automatically.
    
    Only load and initialize the pkcs11 modules when they're needed rather
    than when anything in gcr is touched. For starters this is lighter,
    and secondly modules can block while loading.
    
    Add async initialization functions, and treat the initialization
    of PkcS#11 modules as something that can block.

 gcr/gcr-certificate.c        |    2 +-
 gcr/gcr-combo-selector.c     |    2 +-
 gcr/gcr-gnupg-collection.c   |    2 +-
 gcr/gcr-import-dialog.c      |    2 +-
 gcr/gcr-importer.c           |    2 +-
 gcr/gcr-internal.h           |   12 ++-
 gcr/gcr-library.c            |  179 +++++++++++++++++-----
 gcr/gcr-list-selector.c      |    2 +-
 gcr/gcr-parser.c             |    4 +-
 gcr/gcr-pkcs11-certificate.c |   96 +++++++-----
 gcr/gcr-simple-certificate.c |    2 +-
 gcr/gcr-simple-collection.c  |    2 +-
 gcr/gcr-tree-selector.c      |    2 +-
 gcr/gcr-trust.c              |  346 ++++++++++++++++--------------------------
 14 files changed, 354 insertions(+), 301 deletions(-)
---
diff --git a/gcr/gcr-certificate.c b/gcr/gcr-certificate.c
index 69ae7d2..c4728ea 100644
--- a/gcr/gcr-certificate.c
+++ b/gcr/gcr-certificate.c
@@ -995,7 +995,7 @@ gcr_certificate_mixin_class_init (GObjectClass *object_class)
 	if (!g_object_class_find_property (object_class, "expiry"))
 		g_object_class_override_property (object_class, PROP_EXPIRY, "expiry");
 
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 /**
diff --git a/gcr/gcr-combo-selector.c b/gcr/gcr-combo-selector.c
index f890a3c..ee9c79d 100644
--- a/gcr/gcr-combo-selector.c
+++ b/gcr/gcr-combo-selector.c
@@ -189,7 +189,7 @@ gcr_combo_selector_class_init (GcrComboSelectorClass *klass)
 	           g_param_spec_object ("collection", "Collection", "Collection to select from",
 	                                GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gcr/gcr-gnupg-collection.c b/gcr/gcr-gnupg-collection.c
index 42d8c2c..9a64ebd 100644
--- a/gcr/gcr-gnupg-collection.c
+++ b/gcr/gcr-gnupg-collection.c
@@ -152,7 +152,7 @@ _gcr_gnupg_collection_class_init (GcrGnupgCollectionClass *klass)
 	                                NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
 	g_type_class_add_private (gobject_class, sizeof (GcrGnupgCollectionPrivate));
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 static guint
diff --git a/gcr/gcr-import-dialog.c b/gcr/gcr-import-dialog.c
index 2858c7b..aa1c406 100644
--- a/gcr/gcr-import-dialog.c
+++ b/gcr/gcr-import-dialog.c
@@ -273,7 +273,7 @@ _gcr_import_dialog_class_init (GcrImportDialogClass *klass)
 	           g_param_spec_string ("secondary-text", "Secondary Text", "Dialog secondary text",
 	                                NULL, G_PARAM_READWRITE));
 
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gcr/gcr-importer.c b/gcr/gcr-importer.c
index 1302fe0..01b26c4 100644
--- a/gcr/gcr-importer.c
+++ b/gcr/gcr-importer.c
@@ -691,7 +691,7 @@ gcr_importer_class_init (GcrImporterClass *klass)
 	                                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, 
 	                                G_TYPE_NONE, 1, GCK_TYPE_OBJECT);
 
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 static gpointer
diff --git a/gcr/gcr-internal.h b/gcr/gcr-internal.h
index 99200c7..6923f5d 100644
--- a/gcr/gcr-internal.h
+++ b/gcr/gcr-internal.h
@@ -26,7 +26,17 @@
 
 #include <glib.h>
 
-void              _gcr_initialize                  (void);
+void              _gcr_initialize_library          (void);
+
+gboolean          _gcr_initialize_pkcs11           (GCancellable *cancellable,
+                                                    GError **error);
+
+void              _gcr_initialize_pkcs11_async     (GCancellable *cancellable,
+                                                    GAsyncReadyCallback callback,
+                                                    gpointer user_data);
+
+gboolean          _gcr_initialize_pkcs11_finish    (GAsyncResult *result,
+                                                    GError **error);
 
 void              _gcr_set_pkcs11_config_dir       (const gchar *dir);
 
diff --git a/gcr/gcr-library.c b/gcr/gcr-library.c
index 310d7f8..0c920aa 100644
--- a/gcr/gcr-library.c
+++ b/gcr/gcr-library.c
@@ -77,8 +77,12 @@
  * The #GError domain for data parsing errors.
  */
 
+G_LOCK_DEFINE_STATIC (modules);
 static GList *all_modules = NULL;
+static gboolean initialized_modules = FALSE;
 
+G_LOCK_DEFINE_STATIC (uris);
+static gboolean initialized_uris = FALSE;
 static gchar *trust_store_uri = NULL;
 static gchar **trust_lookup_uris = NULL;
 
@@ -175,55 +179,152 @@ egg_memory_fallback (void *p, size_t sz)
  */
 
 void
-_gcr_initialize (void)
+_gcr_initialize_library (void)
 {
-	static volatile gsize gcr_initialized = 0;
-	CK_FUNCTION_LIST_PTR_PTR module_list;
-	GPtrArray *uris;
-	GError *error = NULL;
-	gchar *uri;
-	guint i;
+	static gint gcr_initialize = 0;
+
+	if (g_atomic_int_exchange_and_add (&gcr_initialize, 1) == 0)
+		return;
 
 	/* Initialize the libgcrypt library if needed */
 	egg_libgcrypt_initialize ();
 
-	if (g_once_init_enter (&gcr_initialized)) {
+	g_type_class_unref (g_type_class_ref (GCR_TYPE_CERTIFICATE_RENDERER));
+	g_type_class_unref (g_type_class_ref (GCR_TYPE_KEY_RENDERER));
 
-		/* This calls p11_kit_initialize_registered */
-		all_modules = gck_modules_initialize_registered (NULL, &error);
-		if (error != NULL) {
-			g_warning ("%s", error->message);
-			g_clear_error (&error);
-		}
+	_gcr_debug ("initialized library");
+}
+
+static void
+initialize_uris (void)
+{
+	GPtrArray *uris;
+	GList *l;
+	gchar *uri;
+
+	g_return_if_fail (initialized_modules);
 
-		module_list = p11_kit_registered_modules ();
+	if (initialized_uris)
+		return;
 
+	G_LOCK (uris);
+
+	if (!initialized_uris) {
 		/* Ask for the global x-trust-store option */
 		trust_store_uri = p11_kit_registered_option (NULL, "x-trust-store");
-		for (i = 0; !trust_store_uri && module_list[i]; i++)
-			trust_store_uri = p11_kit_registered_option (module_list[i], "x-trust-store");
+		for (l = all_modules; !trust_store_uri && l != NULL; l = g_list_next (l)) {
+			trust_store_uri = p11_kit_registered_option (gck_module_get_functions (l->data),
+			                                             "x-trust-store");
+		}
 
 		uris = g_ptr_array_new ();
 		uri = p11_kit_registered_option (NULL, "x-trust-lookup");
 		if (uri != NULL)
 			g_ptr_array_add (uris, uri);
-		for (i = 0; module_list[i]; i++) {
-			uri = p11_kit_registered_option (module_list[i], "x-trust-lookup");
+		for (l = all_modules; !trust_store_uri && l != NULL; l = g_list_next (l)) {
+			uri = p11_kit_registered_option (gck_module_get_functions (l->data),
+			                                 "x-trust-lookup");
 			if (uri != NULL)
 				g_ptr_array_add (uris, uri);
 		}
 		g_ptr_array_add (uris, NULL);
 
 		trust_lookup_uris = (gchar**)g_ptr_array_free (uris, FALSE);
-		free (module_list);
+		initialized_uris = TRUE;
+	}
+
+	G_UNLOCK (uris);
+}
+
+static void
+on_initialize_registered (GObject *object,
+                          GAsyncResult *result,
+                          gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	GError *error = NULL;
+	GList *results;
 
-		g_once_init_leave (&gcr_initialized, 1);
+	results = gck_modules_initialize_registered_finish (result, &error);
+	if (error != NULL) {
+		g_simple_async_result_take_error (res, error);
+
+	} else {
+
+		G_LOCK (modules);
+
+		if (!initialized_modules) {
+			all_modules = g_list_concat(all_modules, results);
+			results = NULL;
+			initialized_modules = TRUE;
+		}
+
+		G_UNLOCK (modules);
 	}
 
-	g_type_class_unref (g_type_class_ref (GCR_TYPE_CERTIFICATE_RENDERER));
-	g_type_class_unref (g_type_class_ref (GCR_TYPE_KEY_RENDERER));
+	gck_list_unref_free (results);
+	g_simple_async_result_complete (res);
+	g_object_unref (res);
+}
 
-	_gcr_debug ("initialized library");
+void
+_gcr_initialize_pkcs11_async (GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+
+	res = g_simple_async_result_new (NULL, callback, user_data,
+	                                 _gcr_initialize_pkcs11_async);
+
+	if (initialized_modules)
+		g_simple_async_result_complete_in_idle (res);
+	else
+		gck_modules_initialize_registered_async (cancellable,
+		                                         on_initialize_registered,
+		                                         g_object_ref (res));
+
+	g_object_unref (res);
+}
+
+gboolean
+_gcr_initialize_pkcs11_finish (GAsyncResult *result,
+                               GError **error)
+{
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
+	                      _gcr_initialize_pkcs11_async), FALSE);
+
+	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+		return FALSE;
+
+	return TRUE;
+}
+
+gboolean
+_gcr_initialize_pkcs11 (GCancellable *cancellable,
+                        GError **error)
+{
+	GList *results;
+
+	if (initialized_modules)
+		return TRUE;
+
+	results = gck_modules_initialize_registered (cancellable, error);
+	if (error == NULL) {
+
+		G_LOCK (modules);
+
+		if (!initialized_modules) {
+			all_modules = g_list_concat(all_modules, results);
+			results = NULL;
+			initialized_modules = TRUE;
+		}
+
+		G_UNLOCK (modules);
+	}
+
+	gck_list_unref_free (results);
+	return (error == NULL);
 }
 
 /**
@@ -239,7 +340,7 @@ _gcr_initialize (void)
 GList*
 gcr_pkcs11_get_modules (void)
 {
-	_gcr_initialize ();
+	g_return_val_if_fail (initialized_modules, NULL);
 	return gck_list_ref_copy (all_modules);
 }
 
@@ -259,14 +360,13 @@ gcr_pkcs11_set_modules (GList *modules)
 {
 	GList *l;
 
-	_gcr_initialize ();
-
 	for (l = modules; l; l = g_list_next (l))
 		g_return_if_fail (GCK_IS_MODULE (l->data));
 
 	modules = gck_list_ref_copy (modules);
 	gck_list_unref_free (all_modules);
 	all_modules = modules;
+	initialized_modules = TRUE;
 }
 
 /**
@@ -284,7 +384,6 @@ void
 gcr_pkcs11_add_module (GckModule *module)
 {
 	g_return_if_fail (GCK_IS_MODULE (module));
-	_gcr_initialize ();
 	all_modules = g_list_append (all_modules, g_object_ref (module));
 }
 
@@ -338,8 +437,9 @@ gcr_pkcs11_get_trust_store_slot (void)
 	GckSlot *slot;
 	GError *error = NULL;
 
-	_gcr_initialize ();
+	g_return_val_if_fail (initialized_modules, NULL);
 
+	initialize_uris ();
 	slot = gck_modules_token_for_uri (all_modules, trust_store_uri, &error);
 	if (!slot) {
 		if (error) {
@@ -370,7 +470,8 @@ gcr_pkcs11_get_trust_lookup_slots (void)
 	GckSlot *slot;
 	gchar **uri;
 
-	_gcr_initialize ();
+	g_return_val_if_fail (initialized_modules, NULL);
+	initialize_uris ();
 
 	for (uri = trust_lookup_uris; uri && *uri; ++uri) {
 		slot = gck_modules_token_for_uri (all_modules, *uri, &error);
@@ -397,7 +498,7 @@ gcr_pkcs11_get_trust_lookup_slots (void)
 const gchar*
 gcr_pkcs11_get_trust_store_uri (void)
 {
-	_gcr_initialize ();
+	initialize_uris ();
 	return trust_store_uri;
 }
 
@@ -414,9 +515,13 @@ gcr_pkcs11_get_trust_store_uri (void)
 void
 gcr_pkcs11_set_trust_store_uri (const gchar *pkcs11_uri)
 {
-	_gcr_initialize ();
+	G_LOCK (uris);
+
 	g_free (trust_store_uri);
 	trust_store_uri = g_strdup (pkcs11_uri);
+	initialized_uris = TRUE;
+
+	G_UNLOCK (uris);
 }
 
 
@@ -431,8 +536,8 @@ gcr_pkcs11_set_trust_store_uri (const gchar *pkcs11_uri)
 const gchar**
 gcr_pkcs11_get_trust_lookup_uris (void)
 {
-	_gcr_initialize ();
-	return (const gchar**)	trust_lookup_uris;
+	initialize_uris ();
+	return (const gchar **)trust_lookup_uris;
 }
 
 /**
@@ -448,7 +553,11 @@ gcr_pkcs11_get_trust_lookup_uris (void)
 void
 gcr_pkcs11_set_trust_lookup_uris (const gchar **pkcs11_uris)
 {
-	_gcr_initialize ();
+	G_LOCK (uris);
+
 	g_strfreev (trust_lookup_uris);
 	trust_lookup_uris = g_strdupv ((gchar**)pkcs11_uris);
+	initialized_uris = TRUE;
+
+	G_UNLOCK (uris);
 }
diff --git a/gcr/gcr-list-selector.c b/gcr/gcr-list-selector.c
index 20cf3a9..17b7d8a 100644
--- a/gcr/gcr-list-selector.c
+++ b/gcr/gcr-list-selector.c
@@ -353,7 +353,7 @@ gcr_list_selector_class_init (GcrListSelectorClass *klass)
 	           g_param_spec_object ("collection", "Collection", "Collection to select from",
 	                                GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c
index 48d3a6b..1766e06 100644
--- a/gcr/gcr-parser.c
+++ b/gcr/gcr-parser.c
@@ -1615,8 +1615,8 @@ gcr_parser_class_init (GcrParserClass *klass)
 	                                G_TYPE_NONE, 0);
 	
 	init_quarks ();
-	_gcr_initialize ();
-	
+	_gcr_initialize_library ();
+
 	/* Check that the format tables are in order */
 	for (i = 1; i < G_N_ELEMENTS (parser_formats); ++i)
 		g_assert (parser_formats[i].format_id >= parser_formats[i - 1].format_id);
diff --git a/gcr/gcr-pkcs11-certificate.c b/gcr/gcr-pkcs11-certificate.c
index e26be47..81a56d5 100644
--- a/gcr/gcr-pkcs11-certificate.c
+++ b/gcr/gcr-pkcs11-certificate.c
@@ -76,18 +76,26 @@ G_DEFINE_TYPE_WITH_CODE (GcrPkcs11Certificate, gcr_pkcs11_certificate, GCK_TYPE_
 	G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_iface);
 );
 
-/* ----------------------------------------------------------------------------
- * INTERAL
- */
+typedef struct {
+	GckAttributes *search;
+	GcrCertificate *result;
+} lookup_issuer_closure;
+
+static void
+lookup_issuer_free (gpointer data)
+{
+	lookup_issuer_closure *closure = data;
+	gck_attributes_unref (closure->search);
+	g_clear_object (&closure->result);
+	g_free (closure);
+}
 
-static GckEnumerator*
+static GckAttributes *
 prepare_lookup_certificate_issuer (GcrCertificate *cert)
 {
 	GckAttributes *search;
-	GckEnumerator *en;
 	gpointer data;
 	gsize n_data;
-	GList *modules;
 
 	search = gck_attributes_new ();
 	gck_attributes_add_ulong (search, CKA_CLASS, CKO_CERTIFICATE);
@@ -97,24 +105,31 @@ prepare_lookup_certificate_issuer (GcrCertificate *cert)
 	gck_attributes_add_data (search, CKA_SUBJECT, data, n_data);
 	g_free (data);
 
-	modules = gcr_pkcs11_get_modules ();
-	en = gck_modules_enumerate_objects (modules, search, 0);
-	gck_attributes_unref (search);
-	gck_list_unref_free (modules);
-
-	return en;
+	return search;
 }
 
 static GcrCertificate*
-perform_lookup_certificate (GckEnumerator *en, GCancellable *cancel, GError **error)
+perform_lookup_certificate (GckAttributes *search,
+                            GCancellable *cancellable,
+                            GError **error)
 {
 	GcrCertificate *cert;
 	GckObject *object;
 	GckAttributes *attrs;
 	GckModule *module;
 	GckSession *session;
+	GckEnumerator *en;
+	GList *modules;
 
-	object = gck_enumerator_next (en, cancel, error);
+	if (!_gcr_initialize_pkcs11 (cancellable, error))
+		return NULL;
+
+	modules = gcr_pkcs11_get_modules ();
+	en = gck_modules_enumerate_objects (modules, search, 0);
+	gck_list_unref_free (modules);
+
+	object = gck_enumerator_next (en, cancellable, error);
+	g_object_unref (en);
 
 	if (object == NULL)
 		return NULL;
@@ -123,7 +138,7 @@ perform_lookup_certificate (GckEnumerator *en, GCancellable *cancel, GError **er
 	 * Only the CKA_VALUE, CKA_CLASS and CKA_CERTIFICATE_TYPE
 	 * is strictly necessary here, but we get more attrs.
 	 */
-	attrs = gck_object_get (object, cancel, error,
+	attrs = gck_object_get (object, cancellable, error,
 	                        CKA_VALUE, CKA_LABEL,
 	                        CKA_ID, CKA_CLASS,
 	                        CKA_CERTIFICATE_TYPE,
@@ -158,21 +173,15 @@ perform_lookup_certificate (GckEnumerator *en, GCancellable *cancel, GError **er
 static void
 thread_lookup_certificate (GSimpleAsyncResult *res, GObject *object, GCancellable *cancel)
 {
+	lookup_issuer_closure *closure;
 	GError *error = NULL;
-	GcrCertificate *cert;
 
-	cert = perform_lookup_certificate (GCK_ENUMERATOR (object), cancel, &error);
+	closure = g_simple_async_result_get_op_res_gpointer (res);
+	closure->result = perform_lookup_certificate (closure->search, cancel, &error);
 
 	if (error != NULL) {
-		g_assert (!cert);
 		g_simple_async_result_set_from_error (res, error);
 		g_clear_error (&error);
-
-	} else if (cert != NULL) {
-		g_simple_async_result_set_op_res_gpointer (res, cert, g_object_unref);
-
-	} else {
-		g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
 	}
 }
 
@@ -286,7 +295,7 @@ gcr_pkcs11_certificate_class_init (GcrPkcs11CertificateClass *klass)
 	g_type_class_add_private (gobject_class, sizeof (GcrPkcs11CertificatePrivate));
 
 	gcr_certificate_mixin_class_init (gobject_class);
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 static gconstpointer
@@ -352,16 +361,19 @@ GcrCertificate*
 gcr_pkcs11_certificate_lookup_issuer (GcrCertificate *certificate, GCancellable *cancellable,
                                       GError **error)
 {
-	GckEnumerator *en;
+	GckAttributes *search;
 	GcrCertificate *issuer;
 
 	g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), NULL);
 
-	en = prepare_lookup_certificate_issuer (certificate);
-	g_return_val_if_fail (en, FALSE);
+	if (!_gcr_initialize_pkcs11 (cancellable, error))
+		return NULL;
 
-	issuer = perform_lookup_certificate (en, cancellable, error);
-	g_object_unref (en);
+	search = prepare_lookup_certificate_issuer (certificate);
+	g_return_val_if_fail (search, FALSE);
+
+	issuer = perform_lookup_certificate (search, cancellable, error);
+	gck_attributes_unref (search);
 
 	return issuer;
 }
@@ -386,21 +398,21 @@ gcr_pkcs11_certificate_lookup_issuer_async (GcrCertificate *certificate, GCancel
                                             GAsyncReadyCallback callback, gpointer user_data)
 {
 	GSimpleAsyncResult *async;
-	GckEnumerator *en;
+	lookup_issuer_closure *closure;
 
 	g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
 
-	en = prepare_lookup_certificate_issuer (certificate);
-	g_return_if_fail (en);
-
-	async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+	async = g_simple_async_result_new (G_OBJECT (certificate), callback, user_data,
 	                                   gcr_pkcs11_certificate_lookup_issuer_async);
+	closure = g_new0 (lookup_issuer_closure, 1);
+	closure->search = prepare_lookup_certificate_issuer (certificate);
+	g_return_if_fail (closure->search);
+	g_simple_async_result_set_op_res_gpointer (async, closure, lookup_issuer_free);
 
 	g_simple_async_result_run_in_thread (async, thread_lookup_certificate,
 	                                     G_PRIORITY_DEFAULT, cancellable);
 
 	g_object_unref (async);
-	g_object_unref (en);
 }
 
 /**
@@ -419,10 +431,11 @@ gcr_pkcs11_certificate_lookup_issuer_async (GcrCertificate *certificate, GCancel
 GcrCertificate*
 gcr_pkcs11_certificate_lookup_issuer_finish (GAsyncResult *result, GError **error)
 {
-	GcrCertificate *cert;
+	lookup_issuer_closure *closure;
 	GObject *source;
 
 	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
 	source = g_async_result_get_source_object (result);
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, source,
 	                      gcr_pkcs11_certificate_lookup_issuer_async), NULL);
@@ -431,9 +444,8 @@ gcr_pkcs11_certificate_lookup_issuer_finish (GAsyncResult *result, GError **erro
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
 
-	cert = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
-	if (cert != NULL)
-		g_object_ref (cert);
-
-	return cert;
+	closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+	if (closure->result != NULL)
+		g_object_ref (closure->result);
+	return closure->result;
 }
diff --git a/gcr/gcr-simple-certificate.c b/gcr/gcr-simple-certificate.c
index ac13b51..3d88421 100644
--- a/gcr/gcr-simple-certificate.c
+++ b/gcr/gcr-simple-certificate.c
@@ -102,7 +102,7 @@ gcr_simple_certificate_class_init (GcrSimpleCertificateClass *klass)
 	g_type_class_add_private (gobject_class, sizeof (GcrSimpleCertificatePrivate));
 
 	gcr_certificate_mixin_class_init (gobject_class);
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 static gconstpointer
diff --git a/gcr/gcr-simple-collection.c b/gcr/gcr-simple-collection.c
index 4340532..fe0788f 100644
--- a/gcr/gcr-simple-collection.c
+++ b/gcr/gcr-simple-collection.c
@@ -102,7 +102,7 @@ gcr_simple_collection_class_init (GcrSimpleCollectionClass *klass)
 	gobject_class->dispose = gcr_simple_collection_dispose;
 	gobject_class->finalize = gcr_simple_collection_finalize;
 	g_type_class_add_private (gobject_class, sizeof (GcrSimpleCollectionPrivate));
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 static guint
diff --git a/gcr/gcr-tree-selector.c b/gcr/gcr-tree-selector.c
index f527999..736f840 100644
--- a/gcr/gcr-tree-selector.c
+++ b/gcr/gcr-tree-selector.c
@@ -378,7 +378,7 @@ gcr_tree_selector_class_init (GcrTreeSelectorClass *klass)
 	           g_param_spec_pointer ("columns", "Columns", "Columns to display in selector",
 	                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
-	_gcr_initialize ();
+	_gcr_initialize_library ();
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gcr/gcr-trust.c b/gcr/gcr-trust.c
index d255d97..6a3c8fb 100644
--- a/gcr/gcr-trust.c
+++ b/gcr/gcr-trust.c
@@ -101,53 +101,17 @@
  * HELPERS
  */
 
-typedef struct _GcrTrustOperation {
-	GckEnumerator *en;
+typedef struct {
 	GckAttributes *attrs;
 	gboolean found;
-} GcrTrustOperation;
+} trust_closure;
 
 static void
-trust_operation_free (gpointer data)
+trust_closure_free (gpointer data)
 {
-	GcrTrustOperation *op = data;
-	g_assert (data);
-
-	/* No reference held */
-	g_assert (GCK_IS_ENUMERATOR (op->en));
-	op->en = NULL;
-
-	g_assert (op->attrs);
-	gck_attributes_unref (op->attrs);
-	op->attrs = NULL;
-
-	g_slice_free (GcrTrustOperation, op);
-}
-
-static void
-trust_operation_init (GckEnumerator *en, GckAttributes *attrs)
-{
-	GcrTrustOperation *op;
-
-	g_assert (GCK_IS_ENUMERATOR (en));
-	g_assert (!g_object_get_data (G_OBJECT (en), "trust-operation"));
-	g_assert (attrs);
-
-	op = g_slice_new0 (GcrTrustOperation);
-	op->attrs = gck_attributes_ref (attrs);
-
-	/* No reference held, GckEnumerator owns */
-	op->en = en;
-	g_object_set_data_full (G_OBJECT (en), "trust-operation", op, trust_operation_free);
-}
-
-static GcrTrustOperation*
-trust_operation_get (GckEnumerator *en)
-{
-	GcrTrustOperation *op = g_object_get_data (G_OBJECT (en), "trust-operation");
-	g_assert (op);
-	g_assert (op->en == en);
-	return op;
+	trust_closure *closure = data;
+	gck_attributes_unref (closure->attrs);
+	g_free (closure);
 }
 
 static GckAttributes*
@@ -172,12 +136,10 @@ prepare_trust_attrs (GcrCertificate *certificate, CK_X_ASSERTION_TYPE type)
  * GET PINNED CERTIFICATE
  */
 
-static GckEnumerator*
+static GckAttributes *
 prepare_is_certificate_pinned (GcrCertificate *certificate, const gchar *purpose, const gchar *peer)
 {
 	GckAttributes *attrs;
-	GckEnumerator *en;
-	GList *slots;
 
 	attrs = prepare_trust_attrs (certificate, CKT_X_PINNED_CERTIFICATE);
 	g_return_val_if_fail (attrs, NULL);
@@ -185,33 +147,32 @@ prepare_is_certificate_pinned (GcrCertificate *certificate, const gchar *purpose
 	gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
 	gck_attributes_add_string (attrs, CKA_X_PEER, peer);
 
-	slots = gcr_pkcs11_get_trust_lookup_slots ();
-	en = gck_slots_enumerate_objects (slots, attrs, 0);
-	trust_operation_init (en, attrs);
-	gck_attributes_unref (attrs);
-	gck_list_unref_free (slots);
-
-	return en;
+	return attrs;
 }
 
 static gboolean
-perform_is_certificate_pinned (GckEnumerator *en, GCancellable *cancellable, GError **error)
+perform_is_certificate_pinned (GckAttributes *search,
+                               GCancellable *cancellable,
+                               GError **error)
 {
-	GcrTrustOperation *op;
+	GckEnumerator *en;
+	GList *slots;
 	GckObject *object;
 
-	op = trust_operation_get (en);
+	if (!_gcr_initialize_pkcs11 (cancellable, error))
+		return FALSE;
 
-	g_assert (op != NULL);
-	g_assert (op->found == FALSE);
+	slots = gcr_pkcs11_get_trust_lookup_slots ();
+	en = gck_slots_enumerate_objects (slots, search, 0);
+	gck_list_unref_free (slots);
 
 	object = gck_enumerator_next (en, cancellable, error);
-	op->found = (object != NULL);
+	g_object_unref (en);
 
 	if (object)
 		g_object_unref (object);
 
-	return op->found;
+	return (object != NULL);
 }
 
 /**
@@ -237,21 +198,18 @@ gboolean
 gcr_trust_is_certificate_pinned (GcrCertificate *certificate, const gchar *purpose,
                                  const gchar *peer, GCancellable *cancellable, GError **error)
 {
-	GckEnumerator *en;
+	GckAttributes *search;
 	gboolean ret;
 
 	g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), FALSE);
 	g_return_val_if_fail (purpose, FALSE);
 	g_return_val_if_fail (peer, FALSE);
 
-	_gcr_initialize ();
-
-	en = prepare_is_certificate_pinned (certificate, purpose, peer);
-	g_return_val_if_fail (en, FALSE);
+	search = prepare_is_certificate_pinned (certificate, purpose, peer);
+	g_return_val_if_fail (search, FALSE);
 
-	ret = perform_is_certificate_pinned (en, cancellable, error);
-
-	g_object_unref (en);
+	ret = perform_is_certificate_pinned (search, cancellable, error);
+	gck_attributes_unref (search);
 
 	return ret;
 }
@@ -260,8 +218,10 @@ static void
 thread_is_certificate_pinned (GSimpleAsyncResult *result, GObject *object, GCancellable *cancel)
 {
 	GError *error = NULL;
+	trust_closure *closure;
 
-	perform_is_certificate_pinned (GCK_ENUMERATOR (object), cancel, &error);
+	closure = g_simple_async_result_get_op_res_gpointer (result);
+	closure->found = perform_is_certificate_pinned (closure->attrs, cancel, &error);
 
 	if (error != NULL) {
 		g_simple_async_result_set_from_error (result, error);
@@ -291,25 +251,23 @@ gcr_trust_is_certificate_pinned_async (GcrCertificate *certificate, const gchar
                                        GAsyncReadyCallback callback, gpointer user_data)
 {
 	GSimpleAsyncResult *async;
-	GckEnumerator *en;
+	trust_closure *closure;
 
 	g_return_if_fail (GCR_CERTIFICATE (certificate));
 	g_return_if_fail (purpose);
 	g_return_if_fail (peer);
 
-	_gcr_initialize ();
-
-	en = prepare_is_certificate_pinned (certificate, purpose, peer);
-	g_return_if_fail (en);
-
-	async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+	async = g_simple_async_result_new (NULL, callback, user_data,
 	                                   gcr_trust_is_certificate_pinned_async);
+	closure = g_new0 (trust_closure, 1);
+	closure->attrs = prepare_is_certificate_pinned (certificate, purpose, peer);
+	g_return_if_fail (closure->attrs);
+	g_simple_async_result_set_op_res_gpointer (async, closure, trust_closure_free);
 
 	g_simple_async_result_run_in_thread (async, thread_is_certificate_pinned,
 	                                     G_PRIORITY_DEFAULT, cancellable);
 
 	g_object_unref (async);
-	g_object_unref (en);
 }
 
 /**
@@ -328,38 +286,29 @@ gcr_trust_is_certificate_pinned_async (GcrCertificate *certificate, const gchar
 gboolean
 gcr_trust_is_certificate_pinned_finish (GAsyncResult *result, GError **error)
 {
-	GcrTrustOperation *op;
-	GObject *object;
-	gboolean found;
+	trust_closure *closure;
 
 	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
 	g_return_val_if_fail (!error || !*error, FALSE);
 
-	_gcr_initialize ();
-
-	object = g_async_result_get_source_object (result);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, object,
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
 	                      gcr_trust_is_certificate_pinned_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
 
-	op = trust_operation_get (GCK_ENUMERATOR (object));
-	found = op->found;
-	g_object_unref (object);
-	return found;
+	closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+	return closure->found;
 }
 
 /* ----------------------------------------------------------------------------------
  * ADD PINNED CERTIFICATE
  */
 
-static GckEnumerator*
+static GckAttributes *
 prepare_add_pinned_certificate (GcrCertificate *certificate, const gchar *purpose, const gchar *peer)
 {
 	GckAttributes *attrs;
-	GckEnumerator *en;
-	GList *slots;
 
 	attrs = prepare_trust_attrs (certificate, CKT_X_PINNED_CERTIFICATE);
 	g_return_val_if_fail (attrs, NULL);
@@ -368,34 +317,37 @@ prepare_add_pinned_certificate (GcrCertificate *certificate, const gchar *purpos
 	gck_attributes_add_string (attrs, CKA_X_PEER, peer);
 	gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
 
-	slots = gcr_pkcs11_get_trust_lookup_slots ();
-	en = gck_slots_enumerate_objects (slots, attrs, CKF_RW_SESSION);
-	trust_operation_init (en, attrs);
-	gck_attributes_unref (attrs);
-	gck_list_unref_free (slots);
-
-	return en;
+	return attrs;
 }
 
 static gboolean
-perform_add_pinned_certificate (GckEnumerator *en, GCancellable *cancellable, GError **error)
+perform_add_pinned_certificate (GckAttributes *search,
+                                GCancellable *cancellable,
+                                GError **error)
 {
-	GcrTrustOperation *op;
 	GckAttributes *attrs;
 	gboolean ret = FALSE;
 	GError *lerr = NULL;
 	GckObject *object;
 	GckSession *session;
 	GckSlot *slot;
+	GckEnumerator *en;
+	GList *slots;
+
+	if (!_gcr_initialize_pkcs11 (cancellable, error))
+		return FALSE;
 
-	op = trust_operation_get (en);
-	g_assert (op != NULL);
+	slots = gcr_pkcs11_get_trust_lookup_slots ();
+	en = gck_slots_enumerate_objects (slots, search, CKF_RW_SESSION);
+	gck_list_unref_free (slots);
 
 	/* We need an error below */
 	if (error && !*error)
 		*error = lerr;
 
 	object = gck_enumerator_next (en, cancellable, error);
+	g_object_unref (en);
+
 	if (*error)
 		return FALSE;
 
@@ -406,7 +358,7 @@ perform_add_pinned_certificate (GckEnumerator *en, GCancellable *cancellable, GE
 	}
 
 	attrs = gck_attributes_new ();
-	gck_attributes_add_all (attrs, op->attrs);
+	gck_attributes_add_all (attrs, search);
 
 	/* TODO: Add relevant label */
 
@@ -466,21 +418,18 @@ gboolean
 gcr_trust_add_pinned_certificate (GcrCertificate *certificate, const gchar *purpose, const gchar *peer,
                                   GCancellable *cancellable, GError **error)
 {
-	GckEnumerator *en;
+	GckAttributes *search;
 	gboolean ret;
 
 	g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), FALSE);
 	g_return_val_if_fail (purpose, FALSE);
 	g_return_val_if_fail (peer, FALSE);
 
-	_gcr_initialize ();
+	search = prepare_add_pinned_certificate (certificate, purpose, peer);
+	g_return_val_if_fail (search, FALSE);
 
-	en = prepare_add_pinned_certificate (certificate, purpose, peer);
-	g_return_val_if_fail (en, FALSE);
-
-	ret = perform_add_pinned_certificate (en, cancellable, error);
-
-	g_object_unref (en);
+	ret = perform_add_pinned_certificate (search, cancellable, error);
+	gck_attributes_unref (search);
 
 	return ret;
 }
@@ -489,8 +438,10 @@ static void
 thread_add_pinned_certificate (GSimpleAsyncResult *result, GObject *object, GCancellable *cancel)
 {
 	GError *error = NULL;
+	trust_closure *closure;
 
-	perform_add_pinned_certificate (GCK_ENUMERATOR (object), cancel, &error);
+	closure = g_simple_async_result_get_op_res_gpointer (result);
+	perform_add_pinned_certificate (closure->attrs, cancel, &error);
 
 	if (error != NULL) {
 		g_simple_async_result_set_from_error (result, error);
@@ -524,25 +475,23 @@ gcr_trust_add_pinned_certificate_async (GcrCertificate *certificate, const gchar
                                         GAsyncReadyCallback callback, gpointer user_data)
 {
 	GSimpleAsyncResult *async;
-	GckEnumerator *en;
+	trust_closure *closure;
 
 	g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
 	g_return_if_fail (purpose);
 	g_return_if_fail (peer);
 
-	_gcr_initialize ();
-
-	en = prepare_add_pinned_certificate (certificate, purpose, peer);
-	g_return_if_fail (en);
-
-	async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+	async = g_simple_async_result_new (NULL, callback, user_data,
 	                                   gcr_trust_add_pinned_certificate_async);
+	closure = g_new0 (trust_closure, 1);
+	closure->attrs = prepare_add_pinned_certificate (certificate, purpose, peer);
+	g_return_if_fail (closure->attrs);
+	g_simple_async_result_set_op_res_gpointer (async, closure, trust_closure_free);
 
 	g_simple_async_result_run_in_thread (async, thread_add_pinned_certificate,
 	                                     G_PRIORITY_DEFAULT, cancellable);
 
 	g_object_unref (async);
-	g_object_unref (en);
 }
 
 /**
@@ -558,17 +507,11 @@ gcr_trust_add_pinned_certificate_async (GcrCertificate *certificate, const gchar
 gboolean
 gcr_trust_add_pinned_certificate_finish (GAsyncResult *result, GError **error)
 {
-	GObject *object;
-
 	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
 	g_return_val_if_fail (!error || !*error, FALSE);
 
-	_gcr_initialize ();
-
-	object = g_async_result_get_source_object (result);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, object,
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
 	                      gcr_trust_add_pinned_certificate_async), FALSE);
-	g_object_unref (object);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
@@ -580,13 +523,11 @@ gcr_trust_add_pinned_certificate_finish (GAsyncResult *result, GError **error)
  * REMOVE PINNED CERTIFICATE
  */
 
-static GckEnumerator*
+static GckAttributes *
 prepare_remove_pinned_certificate (GcrCertificate *certificate, const gchar *purpose,
                                    const gchar *peer)
 {
 	GckAttributes *attrs;
-	GckEnumerator *en;
-	GList *slots;
 
 	attrs = prepare_trust_attrs (certificate, CKT_X_PINNED_CERTIFICATE);
 	g_return_val_if_fail (attrs, NULL);
@@ -594,30 +535,33 @@ prepare_remove_pinned_certificate (GcrCertificate *certificate, const gchar *pur
 	gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
 	gck_attributes_add_string (attrs, CKA_X_PEER, peer);
 
-	slots = gcr_pkcs11_get_trust_lookup_slots ();
-	en = gck_slots_enumerate_objects (slots, attrs, CKF_RW_SESSION);
-	trust_operation_init (en, attrs);
-	gck_attributes_unref (attrs);
-	gck_list_unref_free (slots);
-
-	return en;
+	return attrs;
 }
 
 static gboolean
-perform_remove_pinned_certificate (GckEnumerator *en, GCancellable *cancellable, GError **error)
+perform_remove_pinned_certificate (GckAttributes *attrs,
+                                   GCancellable *cancellable,
+                                   GError **error)
 {
-	GcrTrustOperation *op;
 	GList *objects, *l;
 	GError *lerr = NULL;
+	GckEnumerator *en;
+	GList *slots;
+
+	if (!_gcr_initialize_pkcs11 (cancellable, error))
+		return FALSE;
 
-	op = trust_operation_get (en);
-	g_assert (op != NULL);
+	slots = gcr_pkcs11_get_trust_lookup_slots ();
+	en = gck_slots_enumerate_objects (slots, attrs, CKF_RW_SESSION);
+	gck_list_unref_free (slots);
 
 	/* We need an error below */
 	if (error && !*error)
 		*error = lerr;
 
 	objects = gck_enumerator_next_n (en, -1, cancellable, error);
+	g_object_unref (en);
+
 	if (*error)
 		return FALSE;
 
@@ -661,21 +605,18 @@ gboolean
 gcr_trust_remove_pinned_certificate (GcrCertificate *certificate, const gchar *purpose, const gchar *peer,
                                      GCancellable *cancellable, GError **error)
 {
-	GckEnumerator *en;
+	GckAttributes *search;
 	gboolean ret;
 
 	g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), FALSE);
 	g_return_val_if_fail (purpose, FALSE);
 	g_return_val_if_fail (peer, FALSE);
 
-	_gcr_initialize ();
-
-	en = prepare_remove_pinned_certificate (certificate, purpose, peer);
-	g_return_val_if_fail (en, FALSE);
+	search = prepare_remove_pinned_certificate (certificate, purpose, peer);
+	g_return_val_if_fail (search, FALSE);
 
-	ret = perform_remove_pinned_certificate (en, cancellable, error);
-
-	g_object_unref (en);
+	ret = perform_remove_pinned_certificate (search, cancellable, error);
+	gck_attributes_unref (search);
 
 	return ret;
 }
@@ -684,8 +625,10 @@ static void
 thread_remove_pinned_certificate (GSimpleAsyncResult *result, GObject *object, GCancellable *cancel)
 {
 	GError *error = NULL;
+	trust_closure *closure;
 
-	perform_remove_pinned_certificate (GCK_ENUMERATOR (object), cancel, &error);
+	closure = g_simple_async_result_get_op_res_gpointer (result);
+	perform_remove_pinned_certificate (closure->attrs, cancel, &error);
 
 	if (error != NULL) {
 		g_simple_async_result_set_from_error (result, error);
@@ -717,25 +660,23 @@ gcr_trust_remove_pinned_certificate_async (GcrCertificate *certificate, const gc
                                            GAsyncReadyCallback callback, gpointer user_data)
 {
 	GSimpleAsyncResult *async;
-	GckEnumerator *en;
+	trust_closure *closure;
 
 	g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
 	g_return_if_fail (purpose);
 	g_return_if_fail (peer);
 
-	_gcr_initialize ();
-
-	en = prepare_remove_pinned_certificate (certificate, purpose, peer);
-	g_return_if_fail (en);
-
-	async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+	async = g_simple_async_result_new (NULL, callback, user_data,
 	                                   gcr_trust_remove_pinned_certificate_async);
+	closure = g_new0 (trust_closure, 1);
+	closure->attrs = prepare_remove_pinned_certificate (certificate, purpose, peer);
+	g_return_if_fail (closure->attrs);
+	g_simple_async_result_set_op_res_gpointer (async, closure, trust_closure_free);
 
 	g_simple_async_result_run_in_thread (async, thread_remove_pinned_certificate,
 	                                     G_PRIORITY_DEFAULT, cancellable);
 
 	g_object_unref (async);
-	g_object_unref (en);
 }
 
 /**
@@ -751,17 +692,11 @@ gcr_trust_remove_pinned_certificate_async (GcrCertificate *certificate, const gc
 gboolean
 gcr_trust_remove_pinned_certificate_finish (GAsyncResult *result, GError **error)
 {
-	GObject *object;
-
 	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
 	g_return_val_if_fail (!error || !*error, FALSE);
 
-	_gcr_initialize ();
-
-	object = g_async_result_get_source_object (result);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, object,
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
 	                      gcr_trust_remove_pinned_certificate_async), FALSE);
-	g_object_unref (object);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
@@ -773,45 +708,42 @@ gcr_trust_remove_pinned_certificate_finish (GAsyncResult *result, GError **error
  * CERTIFICATE ROOT
  */
 
-static GckEnumerator*
+static GckAttributes *
 prepare_is_certificate_anchored (GcrCertificate *certificate, const gchar *purpose)
 {
 	GckAttributes *attrs;
-	GckEnumerator *en;
-	GList *slots;
 
 	attrs = prepare_trust_attrs (certificate, CKT_X_ANCHORED_CERTIFICATE);
 	g_return_val_if_fail (attrs, NULL);
 
 	gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
 
-	slots = gcr_pkcs11_get_trust_lookup_slots ();
-	en = gck_slots_enumerate_objects (slots, attrs, 0);
-	trust_operation_init (en, attrs);
-	gck_attributes_unref (attrs);
-	gck_list_unref_free (slots);
-
-	return en;
+	return attrs;
 }
 
 static gboolean
-perform_is_certificate_anchored (GckEnumerator *en, GCancellable *cancellable, GError **error)
+perform_is_certificate_anchored (GckAttributes *attrs,
+                                 GCancellable *cancellable,
+                                 GError **error)
 {
-	GcrTrustOperation *op;
+	GckEnumerator *en;
+	GList *slots;
 	GckObject *object;
 
-	op = trust_operation_get (en);
-	g_assert (op != NULL);
+	if (!_gcr_initialize_pkcs11 (cancellable, error))
+		return FALSE;
+
+	slots = gcr_pkcs11_get_trust_lookup_slots ();
+	en = gck_slots_enumerate_objects (slots, attrs, 0);
+	gck_list_unref_free (slots);
 
 	object = gck_enumerator_next (en, cancellable, error);
-	if (object != NULL) {
-		op->found = TRUE;
+	g_object_unref (en);
+
+	if (object != NULL)
 		g_object_unref (object);
-	} else {
-		op->found = FALSE;
-	}
 
-	return op->found;
+	return (object != NULL);
 }
 
 /**
@@ -837,20 +769,17 @@ gboolean
 gcr_trust_is_certificate_anchored (GcrCertificate *certificate, const gchar *purpose,
                                    GCancellable *cancellable, GError **error)
 {
-	GckEnumerator *en;
+	GckAttributes *search;
 	gboolean ret;
 
 	g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), FALSE);
 	g_return_val_if_fail (purpose, FALSE);
 
-	_gcr_initialize ();
+	search = prepare_is_certificate_anchored (certificate, purpose);
+	g_return_val_if_fail (search, FALSE);
 
-	en = prepare_is_certificate_anchored (certificate, purpose);
-	g_return_val_if_fail (en, FALSE);
-
-	ret = perform_is_certificate_anchored (en, cancellable, error);
-
-	g_object_unref (en);
+	ret = perform_is_certificate_anchored (search, cancellable, error);
+	gck_attributes_unref (search);
 
 	return ret;
 }
@@ -859,8 +788,10 @@ static void
 thread_is_certificate_anchored (GSimpleAsyncResult *result, GObject *object, GCancellable *cancel)
 {
 	GError *error = NULL;
+	trust_closure *closure;
 
-	perform_is_certificate_anchored (GCK_ENUMERATOR (object), cancel, &error);
+	closure = g_simple_async_result_get_op_res_gpointer (result);
+	closure->found = perform_is_certificate_anchored (closure->attrs, cancel, &error);
 
 	if (error != NULL) {
 		g_simple_async_result_set_from_error (result, error);
@@ -889,24 +820,22 @@ gcr_trust_is_certificate_anchored_async (GcrCertificate *certificate, const gcha
                                          gpointer user_data)
 {
 	GSimpleAsyncResult *async;
-	GckEnumerator *en;
+	trust_closure *closure;
 
 	g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
 	g_return_if_fail (purpose);
 
-	_gcr_initialize ();
-
-	en = prepare_is_certificate_anchored (certificate, purpose);
-	g_return_if_fail (en);
-
-	async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+	async = g_simple_async_result_new (NULL, callback, user_data,
 	                                   gcr_trust_is_certificate_anchored_async);
+	closure = g_new0 (trust_closure, 1);
+	closure->attrs = prepare_is_certificate_anchored (certificate, purpose);
+	g_return_if_fail (closure->attrs);
+	g_simple_async_result_set_op_res_gpointer (async, closure, trust_closure_free);
 
 	g_simple_async_result_run_in_thread (async, thread_is_certificate_anchored,
 	                                     G_PRIORITY_DEFAULT, cancellable);
 
 	g_object_unref (async);
-	g_object_unref (en);
 }
 
 /**
@@ -925,24 +854,17 @@ gcr_trust_is_certificate_anchored_async (GcrCertificate *certificate, const gcha
 gboolean
 gcr_trust_is_certificate_anchored_finish (GAsyncResult *result, GError **error)
 {
-	GcrTrustOperation *op;
-	GObject *object;
-	gboolean found;
+	trust_closure *closure;
 
 	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
 	g_return_val_if_fail (!error || !*error, FALSE);
 
-	_gcr_initialize ();
-
-	object = g_async_result_get_source_object (result);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, object,
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
 	                      gcr_trust_is_certificate_anchored_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
 
-	op = trust_operation_get (GCK_ENUMERATOR (object));
-	found = op->found;
-	g_object_unref (object);
-	return found;
+	closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+	return closure->found;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]