[gcr] gck: Rename GckObjectAttributes to GckObjectCache



commit 55961a2887b5636c256367a3013c662adccf5928
Author: Stef Walter <stefw collabora co uk>
Date:   Thu Dec 8 14:30:23 2011 +0100

    gck: Rename GckObjectAttributes to GckObjectCache
    
     * And allow updating of the attributes, in particula adding
       attributes that are discovered.
     * Add a gck_object_cache_lookup() methods which load attributes
       and then updates the cache if the object has a cache.

 docs/reference/gck/gck.types        |    2 +-
 gck/Makefile.am                     |    2 +-
 gck/gck-enumerator.c                |   10 +-
 gck/gck-object-attributes.c         |  111 -----------
 gck/gck-object-cache.c              |  352 +++++++++++++++++++++++++++++++++++
 gck/gck.h                           |   70 ++++++--
 gck/gck.symbols                     |   13 +-
 gck/tests/test-gck-enumerator.c     |   27 ++-
 gcr/gcr-key-mechanisms.c            |   23 +--
 gcr/gcr-key-renderer.c              |  146 +++++++++++++--
 gcr/gcr-subject-public-key.c        |   52 ++++--
 gcr/tests/test-subject-public-key.c |   27 +++-
 12 files changed, 636 insertions(+), 199 deletions(-)
---
diff --git a/docs/reference/gck/gck.types b/docs/reference/gck/gck.types
index 773f02a..a1a8375 100644
--- a/docs/reference/gck/gck.types
+++ b/docs/reference/gck/gck.types
@@ -10,6 +10,6 @@ gck_slot_get_type
 gck_session_info_get_type
 gck_session_get_type
 gck_object_get_type
-gck_object_attributes_get_type
+gck_object_cache_get_type
 gck_password_get_type
 gck_uri_data_get_type
diff --git a/gck/Makefile.am b/gck/Makefile.am
index aab5feb..b761819 100644
--- a/gck/Makefile.am
+++ b/gck/Makefile.am
@@ -41,7 +41,7 @@ PUBLIC_FILES = \
 	gck-module.c \
 	gck-modules.c \
 	gck-object.c \
-	gck-object-attributes.c \
+	gck-object-cache.c \
 	gck-password.c \
 	gck-session.c \
 	gck-slot.c \
diff --git a/gck/gck-enumerator.c b/gck/gck-enumerator.c
index 0d37e7b..4e60f71 100644
--- a/gck/gck-enumerator.c
+++ b/gck/gck-enumerator.c
@@ -86,7 +86,7 @@ struct _GckEnumeratorState {
 	/* The type of objects to create */
 	GType object_type;
 	gpointer object_class;
-	GckObjectAttributesIface *object_iface;
+	GckObjectCacheIface *object_iface;
 
 	/* state_slots */
 	GList *slots;
@@ -511,15 +511,15 @@ state_results (GckEnumeratorState *args,
 		}
 
 		/* If no request for attributes, just go forward */
-		if (args->object_iface == NULL || args->object_iface->n_attribute_types == 0) {
+		if (args->object_iface == NULL || args->object_iface->n_default_types == 0) {
 			g_queue_push_tail (args->results, result);
 			continue;
 		}
 
 		gck_builder_init (&builder);
 
-		for (i = 0; i < args->object_iface->n_attribute_types; ++i)
-			gck_builder_add_empty (&builder, args->object_iface->attribute_types[i]);
+		for (i = 0; i < args->object_iface->n_default_types; ++i)
+			gck_builder_add_empty (&builder, args->object_iface->default_types[i]);
 
 		/* Ask for attribute sizes */
 		template = _gck_builder_prepare_in (&builder, &n_template);
@@ -1046,7 +1046,7 @@ check_out_enumerator_state (GckEnumerator *self)
 			state->object_class = g_type_class_peek (state->object_type);
 			g_assert (state->object_class == self->pv->object_class);
 			state->object_iface = g_type_interface_peek (state->object_class,
-			                                             GCK_TYPE_OBJECT_ATTRIBUTES);
+			                                             GCK_TYPE_OBJECT_CACHE);
 			g_type_class_ref (state->object_type);
 		}
 
diff --git a/gck/gck-object-cache.c b/gck/gck-object-cache.c
new file mode 100644
index 0000000..38b912e
--- /dev/null
+++ b/gck/gck-object-cache.c
@@ -0,0 +1,352 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gck-object-cache.c - the GObject PKCS#11 wrapper library
+
+   Copyright (C) 2011 Collabora Ltd.
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stefw collabora co uk>
+*/
+
+#include "config.h"
+
+#include "gck.h"
+#include "gck-private.h"
+
+#include <string.h>
+
+/**
+ * SECTION:gck-object-cache
+ * @title: GckObjectCache
+ * @short_description: An interface which holds attributes for a PKCS\#11 object
+ *
+ * #GckObjectCache is an interface implemented by derived classes of
+ * #GckObject to indicate which attributes they'd like an enumerator to retrieve.
+ * These attributes are then cached on the object and can be retrieved through
+ * the #GckObjectCache:attributes property.
+ */
+
+/**
+ * GckObjectCacheIface:
+ * @interface: parent interface
+ * @default_types: (array length=n_default_types): attribute types that an
+ *                   enumerator should retrieve
+ * @n_default_types: number of attribute types to be retrieved
+ *
+ * Interface for #GckObjectCache. If the @default_types field is set by
+ * a implementing class, then the a #GckEnumerator which has been setup using
+ * gck_enumerator_set_object_type()
+ */
+
+typedef GckObjectCacheIface GckObjectCacheInterface;
+G_DEFINE_INTERFACE (GckObjectCache, gck_object_cache, GCK_TYPE_OBJECT);
+
+static void
+gck_object_cache_default_init (GckObjectCacheIface *iface)
+{
+	static volatile gsize initialized = 0;
+	if (g_once_init_enter (&initialized)) {
+
+		/**
+		 * GckObjectCache:attributes:
+		 *
+		 * The attributes cached on this object.
+		 */
+		g_object_interface_install_property (iface,
+		         g_param_spec_boxed ("attributes", "Attributes", "PKCS#11 Attributes",
+		                             GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+		g_once_init_leave (&initialized, 1);
+	}
+}
+
+/**
+ * gck_object_cache_get_attributes:
+ * @object: an object with attributes
+ *
+ * Gets the attributes cached on this object.
+ *
+ * Returns: (transfer full) (allow-none): the attributes
+ */
+GckAttributes *
+gck_object_cache_get_attributes (GckObjectCache *object)
+{
+	GckAttributes *attributes = NULL;
+	g_return_val_if_fail (GCK_IS_OBJECT_CACHE (object), NULL);
+	g_object_get (object, "attributes", &attributes, NULL);
+	return attributes;
+}
+
+void
+gck_object_cache_set_attributes (GckObjectCache *object,
+                                 GckAttributes *attributes)
+{
+	g_return_if_fail (GCK_IS_OBJECT_CACHE (object));
+
+	gck_attributes_ref_sink (attributes);
+	g_object_set (object, "attributes", attributes, NULL);
+	gck_attributes_unref (attributes);
+}
+
+/**
+ * gck_object_cache_add_attributes:
+ * @object: an object with attributes
+ * @attributes: the attributes to cache
+ *
+ * Adds the attributes to the set cached on this object.
+ */
+void
+gck_object_cache_add_attributes (GckObjectCache *object,
+                                 GckAttributes *attributes)
+{
+	GckObjectCacheIface *iface;
+
+	g_return_if_fail (GCK_IS_OBJECT_CACHE (object));
+	g_return_if_fail (attributes != NULL);
+
+	iface = GCK_OBJECT_CACHE_GET_INTERFACE (object);
+	g_return_if_fail (iface->add_attributes != NULL);
+
+	gck_attributes_ref_sink (attributes);
+	(iface->add_attributes) (object, attributes);
+	gck_attributes_unref (attributes);
+}
+
+gboolean
+gck_object_cache_update (GckObjectCache *object,
+                         const gulong *attr_types,
+                         gint n_attr_types,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+	GckObjectCacheIface *iface;
+	GckAttributes *attrs;
+
+	g_return_val_if_fail (GCK_IS_OBJECT_CACHE (object), FALSE);
+	g_return_val_if_fail (attr_types != NULL || n_attr_types == 0, FALSE);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	iface = GCK_OBJECT_CACHE_GET_INTERFACE (object);
+
+	if (attr_types == NULL) {
+		attr_types = iface->default_types;
+		n_attr_types = iface->n_default_types;
+
+		if (attr_types == NULL || n_attr_types == 0) {
+			g_warning ("no attribute types passed to gck_object_cache_update() "
+			           "and no default types on object.");
+			return FALSE;
+		}
+	}
+
+	attrs = gck_object_get_full (GCK_OBJECT (object),
+	                             attr_types, n_attr_types,
+	                             cancellable, error);
+
+	if (attrs != NULL) {
+		gck_object_cache_add_attributes (object, attrs);
+		gck_attributes_unref (attrs);
+	}
+
+	return attrs != NULL;
+}
+
+static void
+on_cache_object_get (GObject *source,
+                     GAsyncResult *result,
+                     gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	GckAttributes *attrs;
+	GError *error = NULL;
+
+	attrs = gck_object_get_finish (GCK_OBJECT (source), result, &error);
+	if (error == NULL) {
+		gck_object_cache_add_attributes (GCK_OBJECT_CACHE (source), attrs);
+		gck_attributes_unref (attrs);
+	} else {
+		g_simple_async_result_take_error (res, error);
+	}
+
+	g_simple_async_result_complete (res);
+	g_object_unref (res);
+}
+void
+gck_object_cache_update_async (GckObjectCache *object,
+                               const gulong *attr_types,
+                               gint n_attr_types,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+	GckObjectCacheIface *iface;
+	GSimpleAsyncResult *res;
+
+	g_return_if_fail (GCK_IS_OBJECT_CACHE (object));
+	g_return_if_fail (attr_types != NULL || n_attr_types == 0);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	iface = GCK_OBJECT_CACHE_GET_INTERFACE (object);
+
+	if (attr_types == NULL) {
+		attr_types = iface->default_types;
+		n_attr_types = iface->n_default_types;
+
+		if (attr_types == NULL || n_attr_types == 0) {
+			g_warning ("no attribute types passed to gck_object_cache_update_async() "
+			           "and no default types on object.");
+			return;
+		}
+	}
+
+	res = g_simple_async_result_new (G_OBJECT (object), callback, user_data,
+	                                 gck_object_cache_update_async);
+
+	gck_object_get_async (GCK_OBJECT (object), attr_types, n_attr_types,
+	                      cancellable, on_cache_object_get, g_object_ref (res));
+
+	g_object_unref (res);
+}
+
+gboolean
+gck_object_cache_update_finish (GckObjectCache *object,
+                                GAsyncResult *result,
+                                GError **error)
+{
+	g_return_val_if_fail (GCK_IS_OBJECT_CACHE (object), FALSE);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (object),
+	                      gck_object_cache_update_async), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+check_have_attributes (GckAttributes *attrs,
+                       const gulong *attr_types,
+                       gint n_attr_types)
+{
+	gint i;
+
+	if (attrs == NULL)
+		return FALSE;
+
+	for (i = 0; i < n_attr_types; i++) {
+		if (!gck_attributes_find (attrs, attr_types[i]))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+GckAttributes *
+gck_object_cache_lookup (GckObject *object,
+                         const gulong *attr_types,
+                         gint n_attr_types,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+	GckAttributes *attrs;
+	GckObjectCache *cache;
+
+	g_return_val_if_fail (GCK_IS_OBJECT (object), NULL);
+	g_return_val_if_fail (attr_types != NULL || n_attr_types == 0, NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	if (GCK_IS_OBJECT_CACHE (object)) {
+		cache = GCK_OBJECT_CACHE (object);
+		attrs = gck_object_cache_get_attributes (cache);
+		if (check_have_attributes (attrs, attr_types, n_attr_types))
+			return attrs;
+		gck_attributes_unref (attrs);
+
+		if (!gck_object_cache_update (cache, attr_types, n_attr_types,
+		                              cancellable, error))
+			return NULL;
+
+		return gck_object_cache_get_attributes (cache);
+
+	} else {
+		return gck_object_get_full (object, attr_types, n_attr_types,
+		                            cancellable, error);
+	}
+}
+
+void
+gck_object_cache_lookup_async (GckObject *object,
+                               const gulong *attr_types,
+                               gint n_attr_types,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+	GckAttributes *attrs;
+	GckObjectCache *cache;
+	gboolean have;
+
+	g_return_if_fail (GCK_IS_OBJECT (object));
+	g_return_if_fail (attr_types != NULL || n_attr_types == 0);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	if (GCK_IS_OBJECT_CACHE (object)) {
+		cache = GCK_OBJECT_CACHE (object);
+		attrs = gck_object_cache_get_attributes (cache);
+		have = check_have_attributes (attrs, attr_types, n_attr_types);
+		gck_attributes_unref (attrs);
+
+		if (have) {
+			res = g_simple_async_result_new (G_OBJECT (cache), callback, user_data,
+			                                 gck_object_cache_lookup_async);
+			g_simple_async_result_complete_in_idle (res);
+			g_object_unref (res);
+		} else {
+			gck_object_cache_update_async (cache, attr_types, n_attr_types,
+			                               cancellable, callback, user_data);
+		}
+	} else {
+		gck_object_get_async (object, attr_types, n_attr_types, cancellable,
+		                      callback, user_data);
+	}
+}
+
+GckAttributes *
+gck_object_cache_lookup_finish (GckObject *object,
+                                GAsyncResult *result,
+                                GError **error)
+{
+	GckObjectCache *cache;
+
+	g_return_val_if_fail (GCK_IS_OBJECT (object), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	if (GCK_IS_OBJECT_CACHE (object)) {
+		cache = GCK_OBJECT_CACHE (object);
+		if (!g_simple_async_result_is_valid (result, G_OBJECT (object),
+		                                     gck_object_cache_lookup_async))
+			if (!gck_object_cache_update_finish (cache, result, error))
+				return NULL;
+		return gck_object_cache_get_attributes (cache);
+	} else {
+
+		return gck_object_get_finish (object, result, error);
+	}
+}
diff --git a/gck/gck.h b/gck/gck.h
index c4a5bbf..c0f67dd 100644
--- a/gck/gck.h
+++ b/gck/gck.h
@@ -386,7 +386,7 @@ typedef struct _GckSlot GckSlot;
 typedef struct _GckModule GckModule;
 typedef struct _GckSession GckSession;
 typedef struct _GckObject GckObject;
-typedef struct _GckObjectAttributes GckObjectAttributes;
+typedef struct _GckObjectCache GckObjectCache;
 typedef struct _GckEnumerator GckEnumerator;
 typedef struct _GckUriData GckUriData;
 
@@ -1392,29 +1392,69 @@ GckAttributes*      gck_object_get_template_finish          (GckObject *self,
  * OBJECT ATTRIBUTES
  */
 
-#define GCK_TYPE_OBJECT_ATTRIBUTES                    (gck_object_attributes_get_type ())
-#define GCK_OBJECT_ATTRIBUTES(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_OBJECT_ATTRIBUTES, GckObjectAttributes))
-#define GCK_IS_OBJECT_ATTRIBUTES(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_OBJECT_ATTRIBUTES))
-#define GCK_OBJECT_ATTRIBUTES_GET_INTERFACE(inst)     (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GCK_TYPE_OBJECT_ATTRIBUTES, GckObjectAttributesIface))
+#define GCK_TYPE_OBJECT_CACHE                    (gck_object_cache_get_type ())
+#define GCK_OBJECT_CACHE(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_OBJECT_CACHE, GckObjectCache))
+#define GCK_IS_OBJECT_CACHE(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_OBJECT_CACHE))
+#define GCK_OBJECT_CACHE_GET_INTERFACE(inst)     (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GCK_TYPE_OBJECT_CACHE, GckObjectCacheIface))
 
-typedef struct _GckObjectAttributesIface GckObjectAttributesIface;
+typedef struct _GckObjectCacheIface GckObjectCacheIface;
 
-struct _GckObjectAttributesIface {
+struct _GckObjectCacheIface {
 	GTypeInterface interface;
 
-	const gulong *attribute_types;
-	gint n_attribute_types;
+	const gulong *  default_types;
+	gint            n_default_types;
+
+	void            (* add_attributes)                 (GckObjectCache *object,
+	                                                    GckAttributes *attributes);
 
 	/*< private >*/
 	gpointer reserved[6];
 };
 
-GType               gck_object_attributes_get_type          (void) G_GNUC_CONST;
-
-GckAttributes *     gck_object_attributes_get_attributes    (GckObjectAttributes *object);
-
-void                gck_object_attributes_set_attributes    (GckObjectAttributes *object,
-                                                             GckAttributes *attributes);
+GType               gck_object_cache_get_type              (void) G_GNUC_CONST;
+
+GckAttributes *     gck_object_cache_get_attributes        (GckObjectCache *object);
+
+void                gck_object_cache_set_attributes        (GckObjectCache *object,
+                                                            GckAttributes *attributes);
+
+void                gck_object_cache_add_attributes        (GckObjectCache *object,
+                                                            GckAttributes *attributes);
+
+gboolean            gck_object_cache_update                (GckObjectCache *object,
+                                                            const gulong *attr_types,
+                                                            gint n_attr_types,
+                                                            GCancellable *cancellable,
+                                                            GError **error);
+
+void                gck_object_cache_update_async          (GckObjectCache *object,
+                                                            const gulong *attr_types,
+                                                            gint n_attr_types,
+                                                            GCancellable *cancellable,
+                                                            GAsyncReadyCallback callback,
+                                                            gpointer user_data);
+
+gboolean            gck_object_cache_update_finish         (GckObjectCache *object,
+                                                            GAsyncResult *result,
+                                                            GError **error);
+
+GckAttributes *     gck_object_cache_lookup                (GckObject *object,
+                                                            const gulong *attr_types,
+                                                            gint n_attr_types,
+                                                            GCancellable *cancellable,
+                                                            GError **error);
+
+void                gck_object_cache_lookup_async          (GckObject *object,
+                                                            const gulong *attr_types,
+                                                            gint n_attr_types,
+                                                            GCancellable *cancellable,
+                                                            GAsyncReadyCallback callback,
+                                                            gpointer user_data);
+
+GckAttributes *     gck_object_cache_lookup_finish         (GckObject *object,
+                                                            GAsyncResult *result,
+                                                            GError **error);
 
 /* ------------------------------------------------------------------------
  * PASSWORD
diff --git a/gck/gck.symbols b/gck/gck.symbols
index 9cd3f94..6258dee 100644
--- a/gck/gck.symbols
+++ b/gck/gck.symbols
@@ -131,9 +131,16 @@ gck_modules_object_for_uri
 gck_modules_objects_for_uri
 gck_modules_token_for_uri
 gck_modules_tokens_for_uri
-gck_object_attributes_get_attributes
-gck_object_attributes_get_type
-gck_object_attributes_set_attributes
+gck_object_cache_add_attributes
+gck_object_cache_get_attributes
+gck_object_cache_get_type
+gck_object_cache_lookup
+gck_object_cache_lookup_async
+gck_object_cache_lookup_finish
+gck_object_cache_set_attributes
+gck_object_cache_update
+gck_object_cache_update_async
+gck_object_cache_update_finish
 gck_object_destroy
 gck_object_destroy_async
 gck_object_destroy_finish
diff --git a/gck/tests/test-gck-enumerator.c b/gck/tests/test-gck-enumerator.c
index 7c3a429..1ed1ab5 100644
--- a/gck/tests/test-gck-enumerator.c
+++ b/gck/tests/test-gck-enumerator.c
@@ -404,15 +404,15 @@ typedef struct {
 } MockObjectClass;
 
 GType mock_object_get_type (void) G_GNUC_CONST;
-static void mock_object_attributes_init (GckObjectAttributesIface *iface);
+static void mock_object_cache_init (GckObjectCacheIface *iface);
 
 #define MOCK_TYPE_OBJECT     (mock_object_get_type())
 #define MOCK_OBJECT(obj)     (G_TYPE_CHECK_INSTANCE_CAST((obj), MOCK_TYPE_OBJECT, MockObject))
 #define MOCK_IS_OBJECT(obj)  (G_TYPE_CHECK_INSTANCE_TYPE((obj), MOCK_TYPE_OBJECT))
 
 G_DEFINE_TYPE_WITH_CODE (MockObject, mock_object, GCK_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (GCK_TYPE_OBJECT_ATTRIBUTES,
-                                                mock_object_attributes_init);
+                         G_IMPLEMENT_INTERFACE (GCK_TYPE_OBJECT_CACHE,
+                                                mock_object_cache_init);
 );
 
 static void
@@ -480,10 +480,25 @@ mock_object_class_init (MockObjectClass *klass)
 }
 
 static void
-mock_object_attributes_init (GckObjectAttributesIface *iface)
+mock_object_add_attributes (GckObjectCache *object,
+                            GckAttributes *attrs)
 {
-	iface->attribute_types = mock_attribute_types;
-	iface->n_attribute_types = G_N_ELEMENTS (mock_attribute_types);
+	GckBuilder builder = GCK_BUILDER_INIT;
+	MockObject *self = MOCK_OBJECT (object);
+
+	gck_builder_add_all (&builder, self->attrs);
+	gck_builder_set_all (&builder, attrs);
+
+	gck_attributes_unref (self->attrs);
+	self->attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
+}
+
+static void
+mock_object_cache_init (GckObjectCacheIface *iface)
+{
+	iface->default_types = mock_attribute_types;
+	iface->n_default_types = G_N_ELEMENTS (mock_attribute_types);
+	iface->add_attributes = mock_object_add_attributes;
 }
 
 static void
diff --git a/gcr/gcr-key-mechanisms.c b/gcr/gcr-key-mechanisms.c
index 8728323..b21ccbb 100644
--- a/gcr/gcr-key-mechanisms.c
+++ b/gcr/gcr-key-mechanisms.c
@@ -97,8 +97,8 @@ _gcr_key_mechanisms_check (GckObject *key,
 	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), GCK_INVALID);
 	g_return_val_if_fail (error == NULL || *error == NULL, GCK_INVALID);
 
-	if (GCK_IS_OBJECT_ATTRIBUTES (key)) {
-		attrs = gck_object_attributes_get_attributes (GCK_OBJECT_ATTRIBUTES (key));
+	if (GCK_IS_OBJECT_CACHE (key)) {
+		attrs = gck_object_cache_get_attributes (GCK_OBJECT_CACHE (key));
 		if (!check_have_attributes (attrs, attr_types, G_N_ELEMENTS (attr_types))) {
 			gck_attributes_unref (attrs);
 			attrs = NULL;
@@ -143,7 +143,7 @@ on_check_get_attributes (GObject *source,
 	CheckClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
 
-	closure->attrs = gck_object_get_finish (GCK_OBJECT (source), result, &error);
+	closure->attrs = gck_object_cache_lookup_finish (GCK_OBJECT (source), result, &error);
 	if (error != NULL)
 		g_simple_async_result_take_error (res, error);
 
@@ -163,7 +163,6 @@ _gcr_key_mechanisms_check_async (GckObject *key,
 	gulong attr_types[] = { action_attr_type };
 	CheckClosure *closure;
 	GSimpleAsyncResult *res;
-	GckAttributes *attrs;
 
 	g_return_if_fail (GCK_IS_OBJECT (key));
 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
@@ -176,20 +175,8 @@ _gcr_key_mechanisms_check_async (GckObject *key,
 	closure->action_attr_type = action_attr_type;
 	g_simple_async_result_set_op_res_gpointer (res, closure, check_closure_free);
 
-	if (GCK_IS_OBJECT_ATTRIBUTES (key)) {
-		attrs = gck_object_attributes_get_attributes (GCK_OBJECT_ATTRIBUTES (key));
-		if (check_have_attributes (attrs, attr_types, G_N_ELEMENTS (attr_types))) {
-			g_simple_async_result_set_op_res_gpointer (res, attrs, gck_attributes_unref);
-			g_simple_async_result_complete_in_idle (res);
-			g_object_unref (res);
-			return;
-		}
-
-		gck_attributes_unref (attrs);
-	}
-
-	gck_object_get_async (key, attr_types, G_N_ELEMENTS (attr_types),
-	                      cancellable, on_check_get_attributes, g_object_ref (res));
+	gck_object_cache_lookup_async (key, attr_types, G_N_ELEMENTS (attr_types),
+	                               cancellable, on_check_get_attributes, g_object_ref (res));
 
 	g_object_unref (res);
 
diff --git a/gcr/gcr-key-renderer.c b/gcr/gcr-key-renderer.c
index 333c719..0bfb2c7 100644
--- a/gcr/gcr-key-renderer.c
+++ b/gcr/gcr-key-renderer.c
@@ -24,10 +24,14 @@
 #include "gcr-fingerprint.h"
 #include "gcr-icons.h"
 #include "gcr-renderer.h"
+#include "gcr-subject-public-key.h"
 #include "gcr-viewer.h"
 
 #include "gck/gck.h"
 
+#include "egg/egg-asn1x.h"
+#include "egg/egg-bytes.h"
+
 #include <gdk/gdk.h>
 #include <glib/gi18n-lib.h>
 
@@ -47,14 +51,18 @@
 enum {
 	PROP_0,
 	PROP_LABEL,
-	PROP_ATTRIBUTES
+	PROP_ATTRIBUTES,
+	PROP_OBJECT
 };
 
 struct _GcrKeyRendererPrivate {
 	guint key_size;
 	gchar *label;
 	GckAttributes *attributes;
+	GckObject *object;
 	GIcon *icon;
+	gulong notify_sig;
+	EggBytes *spk;
 };
 
 static void gcr_key_renderer_renderer_iface (GcrRendererIface *iface);
@@ -82,6 +90,32 @@ calculate_label (GcrKeyRenderer *self)
 	return g_strdup (_("Key"));
 }
 
+static GckAttributes *
+calculate_attrs (GcrKeyRenderer *self)
+{
+	if (self->pv->attributes)
+		return gck_attributes_ref (self->pv->attributes);
+
+	if (GCK_IS_OBJECT_CACHE (self->pv->object))
+		return gck_object_cache_get_attributes (GCK_OBJECT_CACHE (self->pv->object));
+
+	return NULL;
+}
+
+static guchar *
+calculate_fingerprint (GcrKeyRenderer *self,
+                       GckAttributes *attrs,
+                       GChecksumType algorithm,
+                       gsize *n_fingerprint)
+{
+	if (self->pv->spk)
+		return gcr_fingerprint_from_subject_public_key_info (egg_bytes_get_data (self->pv->spk),
+		                                                     egg_bytes_get_size (self->pv->spk),
+		                                                     algorithm, n_fingerprint);
+
+	return gcr_fingerprint_from_attributes (attrs, algorithm, n_fingerprint);
+}
+
 static gint
 calculate_rsa_key_size (GckAttributes *attrs)
 {
@@ -129,9 +163,61 @@ calculate_key_size (GckAttributes *attrs, gulong key_type)
 		return -1;
 }
 
-/* -----------------------------------------------------------------------------
- * OBJECT
- */
+static void
+on_subject_public_key (GObject *source,
+                       GAsyncResult *result,
+                       gpointer user_data)
+{
+	GcrKeyRenderer *self = GCR_KEY_RENDERER (user_data);
+	GError *error = NULL;
+	GNode *node;
+
+	node = _gcr_subject_public_key_load_finish (result, &error);
+	if (error != NULL) {
+		g_message ("couldn't load key information: %s", error->message);
+		g_clear_error (&error);
+
+	} else {
+		if (self->pv->spk)
+			egg_bytes_unref (self->pv->spk);
+		self->pv->spk = NULL;
+
+		self->pv->spk = egg_asn1x_encode (node, NULL);
+		if (self->pv->spk == NULL)
+			g_warning ("invalid subjectPublicKey loaded: %s",
+			           egg_asn1x_message (node));
+		egg_asn1x_destroy (node);
+
+		gcr_renderer_emit_data_changed (GCR_RENDERER (self));
+	}
+
+	g_object_unref (self);
+}
+
+static void
+update_subject_public_key (GcrKeyRenderer *self)
+{
+	if (self->pv->spk)
+		egg_bytes_unref (self->pv->spk);
+	self->pv->spk = NULL;
+
+	if (!self->pv->object)
+		return;
+
+	_gcr_subject_public_key_load_async (self->pv->object, NULL,
+	                                    on_subject_public_key,
+	                                    g_object_ref (self));
+}
+
+static void
+on_object_cache_attributes (GObject *obj,
+                            GParamSpec *spec,
+                            gpointer user_data)
+{
+	GcrKeyRenderer *self = GCR_KEY_RENDERER (user_data);
+	update_subject_public_key (self);
+	gcr_renderer_emit_data_changed (GCR_RENDERER (self));
+}
 
 static void
 gcr_key_renderer_init (GcrKeyRenderer *self)
@@ -143,6 +229,18 @@ gcr_key_renderer_init (GcrKeyRenderer *self)
 static void
 gcr_key_renderer_dispose (GObject *obj)
 {
+	GcrKeyRenderer *self = GCR_KEY_RENDERER (obj);
+
+	if (self->pv->spk)
+		egg_bytes_unref (self->pv->spk);
+	self->pv->spk = NULL;
+
+	if (self->pv->object && self->pv->notify_sig) {
+		g_signal_handler_disconnect (self->pv->object, self->pv->notify_sig);
+		self->pv->notify_sig = 0;
+	}
+	g_clear_object (&self->pv->object);
+
 	G_OBJECT_CLASS (gcr_key_renderer_parent_class)->dispose (obj);
 }
 
@@ -183,6 +281,16 @@ gcr_key_renderer_set_property (GObject *obj, guint prop_id, const GValue *value,
 		self->pv->attributes = g_value_dup_boxed (value);
 		gcr_renderer_emit_data_changed (GCR_RENDERER (self));
 		break;
+	case PROP_OBJECT:
+		g_return_if_fail (!self->pv->object);
+		self->pv->object = g_value_dup_object (value);
+		if (self->pv->object && GCK_IS_OBJECT_CACHE (self->pv->object))
+			self->pv->notify_sig = g_signal_connect (self->pv->object,
+			                                         "notify::attributes",
+			                                         G_CALLBACK (on_object_cache_attributes),
+			                                         self);
+		on_object_cache_attributes (G_OBJECT (self->pv->object), NULL, self);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -200,7 +308,10 @@ gcr_key_renderer_get_property (GObject *obj, guint prop_id, GValue *value,
 		g_value_take_string (value, calculate_label (self));
 		break;
 	case PROP_ATTRIBUTES:
-		g_value_set_boxed (value, self->pv->attributes);
+		g_value_take_boxed (value, calculate_attrs (self));
+		break;
+	case PROP_OBJECT:
+		g_value_set_object (value, self->pv->object);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -225,6 +336,10 @@ gcr_key_renderer_class_init (GcrKeyRendererClass *klass)
 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
 	g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
 
+	g_object_class_install_property (gobject_class, PROP_OBJECT,
+	            g_param_spec_object ("object", "Object", "Key Object", GCK_TYPE_OBJECT,
+	                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
 	/* Register this as a view which can be loaded */
 	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PRIVATE_KEY);
 	gcr_renderer_register (GCR_TYPE_KEY_RENDERER, gck_builder_end (&builder));
@@ -236,6 +351,7 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 	GcrKeyRenderer *self;
 	GcrDisplayView *view;
 	const gchar *text = "";
+	GckAttributes *attrs;
 	gpointer fingerprint;
 	gsize n_fingerprint;
 	gchar *display;
@@ -256,15 +372,17 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 
 	_gcr_display_view_begin (view, renderer);
 
-	if (!self->pv->attributes) {
+	attrs = calculate_attrs (self);
+	if (attrs == NULL) {
 		_gcr_display_view_end (view, renderer);
 		return;
 	}
 
-	if (!gck_attributes_find_ulong (self->pv->attributes, CKA_CLASS, &klass) ||
-	    !gck_attributes_find_ulong (self->pv->attributes, CKA_KEY_TYPE, &key_type)) {
+	if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &klass) ||
+	    !gck_attributes_find_ulong (attrs, CKA_KEY_TYPE, &key_type)) {
 		g_warning ("private key does not have the CKA_CLASS and CKA_KEY_TYPE attributes");
 		_gcr_display_view_end (view, renderer);
+		gck_attributes_unref (attrs);
 		return;
 	}
 
@@ -292,7 +410,7 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 
 	_gcr_display_view_append_content (view, renderer, text, NULL);
 
-	size = calculate_key_size (self->pv->attributes, key_type);
+	size = calculate_key_size (attrs, key_type);
 	if (size >= 0) {
 		display = g_strdup_printf (ngettext ("%d bit", "%d bits", size), size);
 		_gcr_display_view_append_content (view, renderer, _("Strength"), display);
@@ -301,7 +419,6 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 
 	_gcr_display_view_start_details (view, renderer);
 
-
 	if (key_type == CKK_RSA)
 		text = _("RSA");
 	else if (key_type == CKK_DSA)
@@ -310,7 +427,7 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 		text = _("Unknown");
 	_gcr_display_view_append_value (view, renderer, _("Algorithm"), text, FALSE);
 
-	size = calculate_key_size (self->pv->attributes, key_type);
+	size = calculate_key_size (attrs, key_type);
 	if (size < 0)
 		display = g_strdup (_("Unknown"));
 	else
@@ -321,20 +438,19 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 	/* Fingerprints */
 	_gcr_display_view_append_heading (view, renderer, _("Fingerprints"));
 
-	fingerprint = gcr_fingerprint_from_attributes (self->pv->attributes,
-	                                               G_CHECKSUM_SHA1, &n_fingerprint);
+	fingerprint = calculate_fingerprint (self, attrs, G_CHECKSUM_SHA1, &n_fingerprint);
 	if (fingerprint) {
 		_gcr_display_view_append_hex (view, renderer, _("SHA1"), fingerprint, n_fingerprint);
 		g_free (fingerprint);
 	}
-	fingerprint = gcr_fingerprint_from_attributes (self->pv->attributes,
-	                                               G_CHECKSUM_SHA256, &n_fingerprint);
+	fingerprint = calculate_fingerprint (self, attrs, G_CHECKSUM_SHA256, &n_fingerprint);
 	if (fingerprint) {
 		_gcr_display_view_append_hex (view, renderer, _("SHA256"), fingerprint, n_fingerprint);
 		g_free (fingerprint);
 	}
 
 	_gcr_display_view_end (view, renderer);
+	gck_attributes_unref (attrs);
 }
 
 static void
diff --git a/gcr/gcr-subject-public-key.c b/gcr/gcr-subject-public-key.c
index a3293f1..0e238fc 100644
--- a/gcr/gcr-subject-public-key.c
+++ b/gcr/gcr-subject-public-key.c
@@ -65,6 +65,7 @@ load_object_basics (GckObject *object,
                     gulong *type,
                     GError **lerror)
 {
+	gulong attr_types[] = { CKA_CLASS, CKA_KEY_TYPE, CKA_CERTIFICATE_TYPE };
 	GckAttributes *attrs;
 	GError *error = NULL;
 
@@ -76,8 +77,8 @@ load_object_basics (GckObject *object,
 		return TRUE;
 	}
 
-	attrs = gck_object_get (object, cancellable, &error,
-	                        CKA_CLASS, CKA_KEY_TYPE, CKA_CERTIFICATE_TYPE, GCK_INVALID);
+	attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
+	                                 cancellable, &error);
 	if (error != NULL) {
 		_gcr_debug ("couldn't load: %s", error->message);
 		g_propagate_error (lerror, error);
@@ -107,6 +108,7 @@ load_x509_attributes (GckObject *object,
                       GCancellable *cancellable,
                       GError **lerror)
 {
+	gulong attr_types[] = { CKA_VALUE };
 	GckAttributes *attrs;
 	GError *error = NULL;
 
@@ -115,8 +117,8 @@ load_x509_attributes (GckObject *object,
 		return TRUE;
 	}
 
-	attrs = gck_object_get (object, cancellable, &error,
-	                        CKA_VALUE, GCK_INVALID);
+	attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
+	                                 cancellable, &error);
 	if (error != NULL) {
 		_gcr_debug ("couldn't load: %s", error->message);
 		g_propagate_error (lerror, error);
@@ -148,6 +150,7 @@ load_rsa_attributes (GckObject *object,
                      GCancellable *cancellable,
                      GError **lerror)
 {
+	gulong attr_types[] = { CKA_MODULUS, CKA_PUBLIC_EXPONENT };
 	GckAttributes *attrs;
 	GError *error = NULL;
 
@@ -156,8 +159,8 @@ load_rsa_attributes (GckObject *object,
 		return TRUE;
 	}
 
-	attrs = gck_object_get (object, cancellable, &error,
-	                        CKA_MODULUS, CKA_PUBLIC_EXPONENT, GCK_INVALID);
+	attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
+	                                 cancellable, &error);
 	if (error != NULL) {
 		_gcr_debug ("couldn't load rsa attributes: %s", error->message);
 		g_propagate_error (lerror, error);
@@ -176,26 +179,37 @@ lookup_public_key (GckObject *object,
                    GError **lerror)
 {
 	GckBuilder builder = GCK_BUILDER_INIT;
+	gulong attr_types[] = { CKA_ID };
+	GckAttributes *attrs;
 	GError *error = NULL;
 	GckSession *session;
 	GckObject *result;
+	const GckAttribute *id;
 	GList *objects;
-	guchar *id;
-	gsize n_id;
 
-	id = gck_object_get_data (object, CKA_ID, cancellable, &n_id, &error);
+	attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
+	                                 cancellable, &error);
 	if (error != NULL) {
 		_gcr_debug ("couldn't load private key id: %s", error->message);
 		g_propagate_error (lerror, error);
 		return NULL;
 	}
 
+	id = gck_attributes_find (attrs, CKA_ID);
+	if (id == NULL || gck_attribute_is_invalid (id)) {
+		gck_attributes_unref (attrs);
+		_gcr_debug ("couldn't load private key id");
+		g_set_error (lerror, GCK_ERROR, CKR_ATTRIBUTE_TYPE_INVALID,
+		             gck_message_from_rv (CKR_ATTRIBUTE_TYPE_INVALID));
+		return NULL;
+	}
+
 	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
-	gck_builder_take_data (&builder, CKA_ID, id, n_id);
-	session = gck_object_get_session (object);
+	gck_builder_add_owned (&builder, id);
+	gck_attributes_unref (attrs);
 
+	session = gck_object_get_session (object);
 	objects = gck_session_find_objects (session, gck_builder_end (&builder), cancellable, &error);
-
 	g_object_unref (session);
 
 	if (error != NULL) {
@@ -238,6 +252,7 @@ load_dsa_attributes (GckObject *object,
                      GCancellable *cancellable,
                      GError **lerror)
 {
+	gulong attr_types[] = { CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_VALUE };
 	GError *error = NULL;
 	GckAttributes *loaded;
 	GckObject *publi;
@@ -259,9 +274,8 @@ load_dsa_attributes (GckObject *object,
 	if (!publi)
 		return FALSE;
 
-	loaded = gck_object_get (publi, cancellable, &error,
-	                         CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_VALUE,
-	                         GCK_INVALID);
+	loaded = gck_object_cache_lookup (publi, attr_types, G_N_ELEMENTS (attr_types),
+	                                  cancellable, &error);
 	g_object_unref (publi);
 
 	if (error != NULL) {
@@ -373,12 +387,12 @@ static void
 lookup_attributes (GckObject *object,
                    GckBuilder *builder)
 {
-	GckObjectAttributes *oakey;
+	GckObjectCache *oakey;
 	GckAttributes *attrs;
 
-	if (GCK_IS_OBJECT_ATTRIBUTES (object)) {
-		oakey = GCK_OBJECT_ATTRIBUTES (object);
-		attrs = gck_object_attributes_get_attributes (oakey);
+	if (GCK_IS_OBJECT_CACHE (object)) {
+		oakey = GCK_OBJECT_CACHE (object);
+		attrs = gck_object_cache_get_attributes (oakey);
 		if (attrs != NULL) {
 			gck_builder_add_all (builder, attrs);
 			gck_attributes_unref (attrs);
diff --git a/gcr/tests/test-subject-public-key.c b/gcr/tests/test-subject-public-key.c
index eaee3c7..bcd232c 100644
--- a/gcr/tests/test-subject-public-key.c
+++ b/gcr/tests/test-subject-public-key.c
@@ -419,9 +419,9 @@ typedef struct { GckObject parent; GckAttributes *attrs; } MockObject;
 typedef struct { GckObjectClass parent; } MockObjectClass;
 
 GType mock_object_get_type (void) G_GNUC_CONST;
-static void mock_object_attributes_init (GckObjectAttributesIface *iface);
+static void mock_object_cache_init (GckObjectCacheIface *iface);
 G_DEFINE_TYPE_WITH_CODE (MockObject, mock_object, GCK_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (GCK_TYPE_OBJECT_ATTRIBUTES, mock_object_attributes_init)
+                         G_IMPLEMENT_INTERFACE (GCK_TYPE_OBJECT_CACHE, mock_object_cache_init)
 );
 
 static void
@@ -462,17 +462,34 @@ static void
 mock_object_class_init (MockObjectClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
 	gobject_class->get_property = mock_object_get_property;
 	gobject_class->set_property = mock_object_set_property;
 	gobject_class->finalize = mock_object_finalize;
+
 	g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
 }
 
 static void
-mock_object_attributes_init (GckObjectAttributesIface *iface)
+mock_object_add_attributes (GckObjectCache *object,
+                            GckAttributes *attrs)
+{
+	GckBuilder builder = GCK_BUILDER_INIT;
+	MockObject *self = (MockObject *)object;
+
+	gck_builder_add_all (&builder, self->attrs);
+	gck_builder_set_all (&builder, attrs);
+
+	gck_attributes_unref (self->attrs);
+	self->attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
+}
+
+static void
+mock_object_cache_init (GckObjectCacheIface *iface)
 {
-	iface->attribute_types = NULL;
-	iface->n_attribute_types = 0;
+	iface->default_types = NULL;
+	iface->n_default_types = 0;
+	iface->add_attributes = mock_object_add_attributes;
 }
 
 static void



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