[gnome-keyring] gcr: Rework how we get supplemental information for the import



commit 0b191e5c7c4fba2a7b5ea9a862c5c91380427d70
Author: Stef Walter <stefw collabora co uk>
Date:   Wed Oct 5 10:17:34 2011 +0200

    gcr: Rework how we get supplemental information for the import

 docs/reference/gcr/Makefile.am      |    2 +
 docs/reference/gcr/gcr-sections.txt |   14 ++++-
 gcr/gcr-base.symbols                |    3 +-
 gcr/gcr-fingerprint.c               |    4 +-
 gcr/gcr-import-interaction.c        |   99 +++++++++++++++++----------
 gcr/gcr-import-interaction.h        |   13 +++-
 gcr/gcr-pkcs11-import-dialog.c      |  132 ++++++++---------------------------
 gcr/gcr-pkcs11-import-dialog.h      |    9 ++-
 gcr/gcr-pkcs11-import-interaction.c |   86 ++++++++++++++---------
 gcr/gcr-pkcs11-importer.c           |   84 ++++++++++++++++++----
 10 files changed, 248 insertions(+), 198 deletions(-)
---
diff --git a/docs/reference/gcr/Makefile.am b/docs/reference/gcr/Makefile.am
index 7ad4c12..f7554f4 100644
--- a/docs/reference/gcr/Makefile.am
+++ b/docs/reference/gcr/Makefile.am
@@ -77,6 +77,8 @@ IGNORE_HFILES= \
 	gcr-menu-button.h \
 	gcr-openpgp.h \
 	gcr-pkcs11-importer.h \
+	gcr-pkcs11-import-interaction.h \
+	gcr-pkcs11-import-dialog.h \
 	gcr-pkcs11-renderer.h \
 	gcr-record.h \
 	gcr-single-collection.h \
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt
index 63372f9..31558e4 100644
--- a/docs/reference/gcr/gcr-sections.txt
+++ b/docs/reference/gcr/gcr-sections.txt
@@ -92,6 +92,8 @@ GcrGeneralNameType
 <FILE>gcr-importer</FILE>
 GcrImporter
 GcrImporterIface
+gcr_importer_get_interaction
+gcr_importer_set_interaction
 gcr_importer_import
 gcr_importer_import_async
 gcr_importer_import_finish
@@ -100,13 +102,23 @@ gcr_importer_register_well_known
 gcr_importer_create_for_parsed
 gcr_importer_queue_for_parsed
 gcr_importer_queue_and_filter_for_parsed
+gcr_import_interaction_supplement_prep
+gcr_import_interaction_supplement
+gcr_import_interaction_supplement_async
+gcr_import_interaction_supplement_finish
 <SUBSECTION Standard>
 GCR_IMPORTER
 GCR_IS_IMPORTER
 GCR_TYPE_IMPORTER
 gcr_importer_get_type
 GCR_IMPORTER_GET_INTERFACE
-<SUBSECTION Private>
+GCR_IMPORT_INTERACTION
+GCR_IMPORT_INTERACTION_GET_INTERFACE
+GCR_IS_IMPORT_INTERACTION
+GCR_TYPE_IMPORT_INTERACTION
+GcrImportInteraction
+GcrImportInteractionIface
+gcr_import_interaction_get_type
 </SECTION>
 
 <SECTION>
diff --git a/gcr/gcr-base.symbols b/gcr/gcr-base.symbols
index 8c251a4..0d48bd1 100644
--- a/gcr/gcr-base.symbols
+++ b/gcr/gcr-base.symbols
@@ -74,12 +74,11 @@ gcr_importer_set_interaction
 gcr_importer_set_parser
 gcr_importer_set_prompt_behavior
 gcr_importer_set_slot
-gcr_import_interaction_get_importer
 gcr_import_interaction_get_type
-gcr_import_interaction_set_importer
 gcr_import_interaction_supplement
 gcr_import_interaction_supplement_async
 gcr_import_interaction_supplement_finish
+gcr_import_interaction_supplement_prep
 gcr_parsed_get_attributes
 gcr_parsed_get_data
 gcr_parsed_get_description
diff --git a/gcr/gcr-fingerprint.c b/gcr/gcr-fingerprint.c
index 9b43dca..39d9319 100644
--- a/gcr/gcr-fingerprint.c
+++ b/gcr/gcr-fingerprint.c
@@ -354,8 +354,8 @@ gcr_fingerprint_from_attributes (GckAttributes *attrs,
 }
 
 /**
- * gcr_fingerprint_from_attributes:
- * @attrs: attributes for key or certificate
+ * gcr_fingerprint_from_certificate_public_key:
+ * @certificate: the certificate
  * @checksum_type: the type of fingerprint to create
  * @n_fingerprint: the length of fingerprint returned
  *
diff --git a/gcr/gcr-import-interaction.c b/gcr/gcr-import-interaction.c
index aee2048..19d0bc0 100644
--- a/gcr/gcr-import-interaction.c
+++ b/gcr/gcr-import-interaction.c
@@ -74,77 +74,90 @@ gcr_import_interaction_default_init (GcrImportInteractionIface *iface)
 	static volatile gsize initialized = 0;
 
 	if (g_once_init_enter (&initialized)) {
-
-		/**
-		 * GcrImportInteraction:importer:
-		 *
-		 * The importer being imported to
-		 */
-		g_object_interface_install_property (iface,
-		         g_param_spec_object ("importer", "Importer", "The imported imported to",
-		                              GCR_TYPE_IMPORTER, G_PARAM_READWRITE));
-
 		g_once_init_leave (&initialized, 1);
 	}
 }
 
 /**
- * gcr_import_interaction_get_importer:
+ * gcr_import_interaction_supplement_prep:
  * @interaction: the interaction
+ * @attributes: attributes to supplement
  *
- * Get the importer that's using this interaction.
+ * Prepare for supplementing the given attributes before import. This means
+ * prompting the user for things like labels and the like. The attributes
+ * will contain attributes for values that the importer needs, either empty
+ * or prefilled with suggested values.
  *
- * Returns: (transfer full):
+ * This method does not prompt the user, but rather just prepares the
+ * interaction that these are the attributes that are needed.
  */
-GcrImporter *
-gcr_import_interaction_get_importer (GcrImportInteraction *interaction)
+void
+gcr_import_interaction_supplement_prep (GcrImportInteraction *interaction,
+                                        GckAttributes *attributes)
 {
-	GcrImporter *importer = NULL;
-
-	g_return_val_if_fail (GCR_IS_IMPORT_INTERACTION (interaction), NULL);
-
-	g_object_get (interaction, "importer", &importer, NULL);
+	GcrImportInteractionIface *iface;
 
-	if (importer != NULL)
-		g_object_unref (importer);
+	g_return_if_fail (GCR_IS_IMPORT_INTERACTION (interaction));
+	g_return_if_fail (attributes != NULL);
 
-	return importer;
+	iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
+	if (iface->supplement != NULL)
+		(iface->supplement_prep) (interaction, attributes);
 }
 
 /**
- * gcr_import_interaction_set_importer:
+ * gcr_import_interaction_supplement:
  * @interaction: the interaction
- * @importer: (allow-none): the importer or %NULL
+ * @attributes: supplemented attributes
+ * @cancellable: optional cancellable object
+ * @error: location to store error on failure
+ *
+ * Supplement attributes before import. This means prompting the user for
+ * things like labels and the like. The needed attributes will have been passed
+ * to gcr_import_interaction_supplement_prep().
  *
- * Set the importer that's using this interaction.
+ * This method prompts the user and fills in the attributes. If the user or
+ * cancellable cancels the operation the error should be set with %G_IO_ERROR_CANCELLED.
+ *
+ * Returns: %G_TLS_INTERACTION_HANDLED if successful or %G_TLS_INTERACTION_FAILED
  */
-void
-gcr_import_interaction_set_importer (GcrImportInteraction *interaction,
-                                     GcrImporter *importer)
-{
-	g_return_if_fail (GCR_IS_IMPORT_INTERACTION (interaction));
-	g_object_set (interaction, "importer", importer, NULL);
-}
-
 GTlsInteractionResult
 gcr_import_interaction_supplement (GcrImportInteraction *interaction,
+                                   GckAttributes *attributes,
                                    GCancellable *cancellable,
                                    GError **error)
 {
 	GcrImportInteractionIface *iface;
 
 	g_return_val_if_fail (GCR_IS_IMPORT_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
+	g_return_val_if_fail (attributes != NULL, G_TLS_INTERACTION_UNHANDLED);
 	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
 	g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_INTERACTION_UNHANDLED);
 
 	iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
 	g_return_val_if_fail (iface->supplement != NULL, G_TLS_INTERACTION_UNHANDLED);
 
-	return (iface->supplement) (interaction, cancellable, error);
+	return (iface->supplement) (interaction, attributes, cancellable, error);
 }
 
+
+/**
+ * gcr_import_interaction_supplement_async:
+ * @interaction: the interaction
+ * @attributes: supplemented attributes
+ * @cancellable: optional cancellable object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Asynchronously supplement attributes before import. This means prompting the
+ * user for things like labels and the like. The needed attributes will have
+ * been passed to gcr_import_interaction_supplement_prep().
+ *
+ * This method prompts the user and fills in the attributes.
+ */
 void
 gcr_import_interaction_supplement_async (GcrImportInteraction *interaction,
+                                         GckAttributes *attributes,
                                          GCancellable *cancellable,
                                          GAsyncReadyCallback callback,
                                          gpointer user_data)
@@ -152,14 +165,28 @@ gcr_import_interaction_supplement_async (GcrImportInteraction *interaction,
 	GcrImportInteractionIface *iface;
 
 	g_return_if_fail (GCR_IS_IMPORT_INTERACTION (interaction));
+	g_return_if_fail (attributes != NULL);
 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
 	iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
 	g_return_if_fail (iface->supplement != NULL);
 
-	(iface->supplement_async) (interaction, cancellable, callback, user_data);
+	(iface->supplement_async) (interaction, attributes, cancellable, callback, user_data);
 }
 
+/**
+ * gcr_import_interaction_supplement_finish:
+ * @interaction: the interaction
+ * @result: the asynchronous result
+ * @error: location to place an error on failure
+ *
+ * Complete operation to asynchronously supplement attributes before import.
+ *
+ * If the user or cancellable cancels the operation the error should be set
+ * with %G_IO_ERROR_CANCELLED.
+ *
+ * Returns: %G_TLS_INTERACTION_HANDLED if successful or %G_TLS_INTERACTION_FAILED
+ */
 GTlsInteractionResult
 gcr_import_interaction_supplement_finish (GcrImportInteraction *interaction,
                                           GAsyncResult *result,
diff --git a/gcr/gcr-import-interaction.h b/gcr/gcr-import-interaction.h
index 79f5970..2793d13 100644
--- a/gcr/gcr-import-interaction.h
+++ b/gcr/gcr-import-interaction.h
@@ -47,11 +47,16 @@ typedef struct _GcrImportInteractionIface GcrImportInteractionIface;
 struct _GcrImportInteractionIface {
 	GTypeInterface parent;
 
+	void                    (*supplement_prep)   (GcrImportInteraction *interaction,
+	                                              GckAttributes *attributes);
+
 	GTlsInteractionResult   (*supplement)        (GcrImportInteraction *interaction,
+	                                              GckAttributes *attributes,
 	                                              GCancellable *cancellable,
 	                                              GError **error);
 
 	void                    (*supplement_async)  (GcrImportInteraction *interaction,
+	                                              GckAttributes *attributes,
 	                                              GCancellable *cancellable,
 	                                              GAsyncReadyCallback callback,
 	                                              gpointer user_data);
@@ -66,16 +71,16 @@ struct _GcrImportInteractionIface {
 
 GType                  gcr_import_interaction_get_type             (void);
 
-GcrImporter *          gcr_import_interaction_get_importer         (GcrImportInteraction *interaction);
-
-void                   gcr_import_interaction_set_importer         (GcrImportInteraction *interaction,
-                                                                    GcrImporter *importer);
+void                   gcr_import_interaction_supplement_prep      (GcrImportInteraction *interaction,
+                                                                    GckAttributes *attributes);
 
 GTlsInteractionResult  gcr_import_interaction_supplement           (GcrImportInteraction *interaction,
+                                                                    GckAttributes *attributes,
                                                                     GCancellable *cancellable,
                                                                     GError **error);
 
 void                   gcr_import_interaction_supplement_async     (GcrImportInteraction *interaction,
+                                                                    GckAttributes *attributes,
                                                                     GCancellable *cancellable,
                                                                     GAsyncReadyCallback callback,
                                                                     gpointer user_data);
diff --git a/gcr/gcr-pkcs11-import-dialog.c b/gcr/gcr-pkcs11-import-dialog.c
index dce5ae1..e33d624 100644
--- a/gcr/gcr-pkcs11-import-dialog.c
+++ b/gcr/gcr-pkcs11-import-dialog.c
@@ -44,7 +44,6 @@ enum {
 
 struct _GcrPkcs11ImportDialog {
 	GtkDialog parent;
-	GcrImporter *importer;
 	GtkBuilder *builder;
 	GtkWidget *password_area;
 	GtkLabel *token_label;
@@ -70,18 +69,6 @@ on_label_changed (GtkEditable *editable,
 	self->label_changed = TRUE;
 }
 
-static GList *
-pkcs11_importer_get_queued (GcrImporter *importer)
-{
-	GList *queued = NULL;
-
-	/* TODO: This is ugly */
-
-	g_object_get (importer, "queued", &queued, NULL);
-
-	return queued;
-}
-
 static void
 _gcr_pkcs11_import_dialog_constructed (GObject *obj)
 {
@@ -90,9 +77,6 @@ _gcr_pkcs11_import_dialog_constructed (GObject *obj)
 	GtkEntryBuffer *buffer;
 	GtkWidget *widget;
 	GtkBox *contents;
-	GList *queued, *l;
-	gchar *label = NULL;
-	gchar *value;
 
 	G_OBJECT_CLASS (_gcr_pkcs11_import_dialog_parent_class)->constructed (obj);
 
@@ -125,27 +109,6 @@ _gcr_pkcs11_import_dialog_constructed (GObject *obj)
 	g_signal_connect (self->label_entry, "changed", G_CALLBACK (on_label_changed), self);
 	gtk_entry_set_activates_default (self->label_entry, TRUE);
 
-	queued = pkcs11_importer_get_queued (self->importer);
-	for (l = queued; l != NULL; l = g_list_next (l)) {
-		if (!gck_attributes_find_string (l->data, CKA_LABEL, &value))
-			value = NULL;
-		if (l == queued) {
-			label = value;
-			value = NULL;
-		} else if (g_strcmp0 (label, value) != 0) {
-			g_free (label);
-			label = NULL;
-		}
-		g_free (value);
-	}
-	g_list_free (queued);
-
-	if (label == NULL)
-		gtk_entry_set_placeholder_text (self->label_entry, _("Automatically chosen"));
-	else
-		gtk_entry_set_text (self->label_entry, label);
-	g_free (label);
-
 	/* Add our various buttons */
 	gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
 	gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_OK, GTK_RESPONSE_OK);
@@ -166,94 +129,65 @@ _gcr_pkcs11_import_dialog_finalize (GObject *obj)
 	GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
 
 	g_object_unref (self->builder);
-	g_clear_object (&self->importer);
 
 	G_OBJECT_CLASS (_gcr_pkcs11_import_dialog_parent_class)->finalize (obj);
 }
 
 static void
-_gcr_pkcs11_import_dialog_set_property (GObject *obj,
-                                        guint prop_id,
-                                        const GValue *value,
-                                        GParamSpec *pspec)
-{
-	GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
-
-	switch (prop_id) {
-	case PROP_IMPORTER:
-		g_return_if_fail (self->importer == NULL);
-		self->importer = g_value_dup_object (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-_gcr_pkcs11_import_dialog_get_property (GObject *obj,
-                                        guint prop_id,
-                                        GValue *value,
-                                        GParamSpec *pspec)
-{
-	GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
-
-	switch (prop_id) {
-	case PROP_IMPORTER:
-		g_value_set_object (value, self->importer);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
-}
-
-static void
 _gcr_pkcs11_import_dialog_class_init (GcrPkcs11ImportDialogClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
 	gobject_class->constructed = _gcr_pkcs11_import_dialog_constructed;
 	gobject_class->finalize = _gcr_pkcs11_import_dialog_finalize;
-	gobject_class->set_property = _gcr_pkcs11_import_dialog_set_property;
-	gobject_class->get_property = _gcr_pkcs11_import_dialog_get_property;
-
-	g_object_class_install_property (gobject_class, PROP_IMPORTER,
-	           g_param_spec_object ("importer", "Importer", "The PKCS#11 importer",
-	                                GCR_TYPE_IMPORTER,
-	                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 GcrPkcs11ImportDialog *
-_gcr_pkcs11_import_dialog_new (GcrImporter *importer,
-                               GtkWindow *parent)
+_gcr_pkcs11_import_dialog_new (GtkWindow *parent)
 {
 	GcrPkcs11ImportDialog *dialog;
 
-	g_return_val_if_fail (GCR_IS_IMPORTER (importer), NULL);
 	g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
 
 	dialog = g_object_new (GCR_TYPE_PKCS11_IMPORT_DIALOG,
-	                       "importer", importer,
 	                       "transient-for", parent,
 	                       NULL);
 
 	return g_object_ref_sink (dialog);
 }
 
-static void
-update_importer_labels (GcrPkcs11ImportDialog *self)
+void
+_gcr_pkcs11_import_dialog_get_supplements (GcrPkcs11ImportDialog *self,
+                                           GckAttributes *attributes)
 {
 	const gchar *label;
-	GList *queued, *l;
+
+	g_return_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self));
+	g_return_if_fail (attributes != NULL);
 
 	label = gtk_entry_get_text (self->label_entry);
-	if (self->label_changed && label != NULL && label[0]) {
-		queued = pkcs11_importer_get_queued (self->importer);
-		for (l = queued; l != NULL; l = g_list_next (l))
-			gck_attributes_set_string (l->data, CKA_LABEL, label);
-		g_list_free (queued);
-	}
+	if (self->label_changed && label != NULL && label[0])
+		gck_attributes_set_string (attributes, CKA_LABEL, label);
+}
+
+void
+_gcr_pkcs11_import_dialog_set_supplements (GcrPkcs11ImportDialog *self,
+                                           GckAttributes *attributes)
+{
+	gchar *label;
+
+	g_return_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self));
+	g_return_if_fail (attributes != NULL);
+
+	if (!gck_attributes_find_string (attributes, CKA_LABEL, &label))
+		label = NULL;
+
+	if (label == NULL)
+		gtk_entry_set_placeholder_text (self->label_entry, _("Automatically chosen"));
+	gtk_entry_set_text (self->label_entry, label == NULL ? "" : label);
+	g_free (label);
+
+	self->label_changed = FALSE;
 }
 
 gboolean
@@ -264,7 +198,6 @@ _gcr_pkcs11_import_dialog_run (GcrPkcs11ImportDialog *self)
 	g_return_val_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self), FALSE);
 
 	if (gtk_dialog_run (GTK_DIALOG (self)) == GTK_RESPONSE_OK) {
-		update_importer_labels (self);
 		ret = TRUE;
 	}
 
@@ -296,12 +229,7 @@ _gcr_pkcs11_import_dialog_run_finish (GcrPkcs11ImportDialog *self,
 
 	gtk_widget_hide (GTK_WIDGET (self));
 
-	if (response == GTK_RESPONSE_OK) {
-		update_importer_labels (self);
-		return TRUE;
-	}
-
-	return FALSE;
+	return (response == GTK_RESPONSE_OK) ? TRUE : FALSE;
 }
 
 GTlsInteractionResult
diff --git a/gcr/gcr-pkcs11-import-dialog.h b/gcr/gcr-pkcs11-import-dialog.h
index 7c20769..38a1dd4 100644
--- a/gcr/gcr-pkcs11-import-dialog.h
+++ b/gcr/gcr-pkcs11-import-dialog.h
@@ -39,8 +39,13 @@ typedef struct _GcrPkcs11ImportDialog GcrPkcs11ImportDialog;
 
 GType                   _gcr_pkcs11_import_dialog_get_type          (void) G_GNUC_CONST;
 
-GcrPkcs11ImportDialog * _gcr_pkcs11_import_dialog_new               (GcrImporter *importer,
-                                                                     GtkWindow *parent);
+GcrPkcs11ImportDialog * _gcr_pkcs11_import_dialog_new               (GtkWindow *parent);
+
+void                    _gcr_pkcs11_import_dialog_get_supplements   (GcrPkcs11ImportDialog *self,
+                                                                     GckAttributes *attributes);
+
+void                    _gcr_pkcs11_import_dialog_set_supplements   (GcrPkcs11ImportDialog *self,
+                                                                     GckAttributes *attributes);
 
 gboolean                _gcr_pkcs11_import_dialog_run               (GcrPkcs11ImportDialog *self);
 
diff --git a/gcr/gcr-pkcs11-import-interaction.c b/gcr/gcr-pkcs11-import-interaction.c
index 3be7c94..ee592e1 100644
--- a/gcr/gcr-pkcs11-import-interaction.c
+++ b/gcr/gcr-pkcs11-import-interaction.c
@@ -33,7 +33,6 @@
 
 enum {
 	PROP_0,
-	PROP_IMPORTER,
 	PROP_PARENT_WINDOW
 };
 
@@ -41,8 +40,7 @@ typedef struct _GcrPkcs11ImportInteractionClass GcrPkcs11ImportInteractionClass;
 
 struct _GcrPkcs11ImportInteraction {
 	GTlsInteraction parent;
-	GcrImporter *importer;
-	gboolean dialog_shown;
+	gboolean supplemented;
 	GtkWindow *parent_window;
 	GcrPkcs11ImportDialog *dialog;
 };
@@ -59,7 +57,7 @@ G_DEFINE_TYPE_WITH_CODE(GcrPkcs11ImportInteraction, _gcr_pkcs11_import_interacti
 static void
 _gcr_pkcs11_import_interaction_init (GcrPkcs11ImportInteraction *self)
 {
-
+	self->dialog = _gcr_pkcs11_import_dialog_new (self->parent_window);
 }
 
 static void
@@ -81,17 +79,9 @@ _gcr_pkcs11_import_interaction_set_property (GObject *obj,
 	GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (obj);
 
 	switch (prop_id) {
-	case PROP_IMPORTER:
-		g_clear_object (&self->dialog);
-		g_clear_object (&self->importer);
-		self->importer = g_value_dup_object (value);
-		self->dialog_shown = FALSE;
-		if (self->importer != NULL)
-			self->dialog = _gcr_pkcs11_import_dialog_new (self->importer, self->parent_window);
-		break;
 	case PROP_PARENT_WINDOW:
-		g_clear_object (&self->parent_window);
-		self->parent_window = g_value_dup_object (value);
+		gtk_window_set_transient_for (GTK_WINDOW (self->dialog),
+		                              g_value_get_object (value));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -108,11 +98,8 @@ _gcr_pkcs11_import_interaction_get_property (GObject *obj,
 	GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (obj);
 
 	switch (prop_id) {
-	case PROP_IMPORTER:
-		g_value_set_object (value, self->importer);
-		break;
 	case PROP_PARENT_WINDOW:
-		g_value_set_object (value, self->parent_window);
+		g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (self->dialog)));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -130,12 +117,23 @@ _gcr_pkcs11_import_interaction_ask_password (GTlsInteraction *interaction,
 
 	g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
 
-	self->dialog_shown = TRUE;
+	self->supplemented = TRUE;
 	return _gcr_pkcs11_import_dialog_run_ask_password (self->dialog, password, cancellable, error);
 }
 
+static void
+_gcr_pkcs11_import_interaction_supplement_prep (GcrImportInteraction *interaction,
+                                                GckAttributes *attributes)
+{
+	GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (interaction);
+
+	self->supplemented = FALSE;
+	_gcr_pkcs11_import_dialog_set_supplements (self->dialog, attributes);
+}
+
 static GTlsInteractionResult
 _gcr_pkcs11_import_interaction_supplement (GcrImportInteraction *interaction,
+                                           GckAttributes *attributes,
                                            GCancellable *cancellable,
                                            GError **error)
 {
@@ -143,11 +141,12 @@ _gcr_pkcs11_import_interaction_supplement (GcrImportInteraction *interaction,
 
 	g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
 
-	if (self->dialog_shown)
+	if (self->supplemented)
 		return G_TLS_INTERACTION_HANDLED;
 
-	self->dialog_shown = TRUE;
+	self->supplemented = TRUE;
 	if (_gcr_pkcs11_import_dialog_run (self->dialog)) {
+		_gcr_pkcs11_import_dialog_get_supplements (self->dialog, attributes);
 		return G_TLS_INTERACTION_HANDLED;
 
 	} else {
@@ -157,7 +156,18 @@ _gcr_pkcs11_import_interaction_supplement (GcrImportInteraction *interaction,
 }
 
 static void
+on_dialog_run_async (GObject *source,
+                     GAsyncResult *result,
+                     gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	g_simple_async_result_complete (res);
+	g_object_unref (res);
+}
+
+static void
 _gcr_pkcs11_import_interaction_supplement_async (GcrImportInteraction *interaction,
+                                                 GckAttributes *attributes,
                                                  GCancellable *cancellable,
                                                  GAsyncReadyCallback callback,
                                                  gpointer user_data)
@@ -167,17 +177,22 @@ _gcr_pkcs11_import_interaction_supplement_async (GcrImportInteraction *interacti
 
 	g_return_if_fail (self->dialog != NULL);
 
+	res = g_simple_async_result_new (G_OBJECT (interaction), callback, user_data,
+	                                 _gcr_pkcs11_import_interaction_supplement_async);
+
 	/* If dialog was already shown, then short circuit */
-	if (self->dialog_shown) {
-		res = g_simple_async_result_new (G_OBJECT (interaction), callback, user_data,
-		                                 _gcr_pkcs11_import_interaction_supplement_async);
+	if (self->supplemented) {
 		g_simple_async_result_complete_in_idle (res);
-		g_object_unref (res);
 
 	} else {
-		self->dialog_shown = TRUE;
-		_gcr_pkcs11_import_dialog_run_async (self->dialog, cancellable, callback, user_data);
+		self->supplemented = TRUE;
+		g_simple_async_result_set_op_res_gpointer (res, gck_attributes_ref (attributes),
+		                                           (GDestroyNotify)gck_attributes_unref);
+		_gcr_pkcs11_import_dialog_run_async (self->dialog, cancellable,
+		                                     on_dialog_run_async, g_object_ref (res));
 	}
+
+	g_object_unref (res);
 }
 
 static GTlsInteractionResult
@@ -186,17 +201,21 @@ _gcr_pkcs11_import_interaction_supplement_finish (GcrImportInteraction *interact
                                                   GError **error)
 {
 	GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (interaction);
+	GckAttributes *attributes;
 
 	g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
+	                      _gcr_pkcs11_import_interaction_supplement_async), G_TLS_INTERACTION_UNHANDLED);
 
-	/* If it was short circuited without a dialog */
-	if (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
-	                                    _gcr_pkcs11_import_interaction_supplement_async)) {
-		return G_TLS_INTERACTION_HANDLED;
+	attributes = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
 
-	} else if (_gcr_pkcs11_import_dialog_run_finish (self->dialog, result)) {
+	/* Didn't show the dialog */
+	if (attributes == NULL)
 		return G_TLS_INTERACTION_HANDLED;
 
+	if (_gcr_pkcs11_import_dialog_run_finish (self->dialog, result)) {
+		_gcr_pkcs11_import_dialog_get_supplements (self->dialog, attributes);
+		return G_TLS_INTERACTION_HANDLED;
 	} else {
 		g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, _("The user cancelled the operation"));
 		return G_TLS_INTERACTION_FAILED;
@@ -206,6 +225,7 @@ _gcr_pkcs11_import_interaction_supplement_finish (GcrImportInteraction *interact
 static void
 _gcr_pkcs11_import_interaction_iface_init (GcrImportInteractionIface *iface)
 {
+	iface->supplement_prep = _gcr_pkcs11_import_interaction_supplement_prep;
 	iface->supplement = _gcr_pkcs11_import_interaction_supplement;
 	iface->supplement_async = _gcr_pkcs11_import_interaction_supplement_async;
 	iface->supplement_finish = _gcr_pkcs11_import_interaction_supplement_finish;
@@ -223,8 +243,6 @@ _gcr_pkcs11_import_interaction_class_init (GcrPkcs11ImportInteractionClass *klas
 
 	interaction_class->ask_password = _gcr_pkcs11_import_interaction_ask_password;
 
-	g_object_class_override_property (gobject_class, PROP_IMPORTER, "importer");
-
 	g_object_class_install_property (gobject_class, PROP_PARENT_WINDOW,
 	              g_param_spec_object ("parent-window", "Parent Window", "Prompt Parent Window",
 	                                   GTK_TYPE_WINDOW, G_PARAM_READWRITE));
diff --git a/gcr/gcr-pkcs11-importer.c b/gcr/gcr-pkcs11-importer.c
index 371f76b..15ea88f 100644
--- a/gcr/gcr-pkcs11-importer.c
+++ b/gcr/gcr-pkcs11-importer.c
@@ -74,6 +74,7 @@ typedef struct  {
 	GCancellable *cancellable;
 	gboolean prompted;
 	gboolean async;
+	GckAttributes *supplement;
 } GcrImporterData;
 
 /* State forward declarations */
@@ -132,13 +133,6 @@ static void
 state_complete (GSimpleAsyncResult *res,
                 gboolean async)
 {
-	GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
-	GcrPkcs11Importer *self = data->importer;
-
-	/* Disconnect from the interaction */
-	if (data->importer->interaction && GCR_IS_IMPORT_INTERACTION (self->interaction))
-		gcr_import_interaction_set_importer (GCR_IMPORT_INTERACTION (self->interaction), NULL);
-
 	g_simple_async_result_complete (res);
 }
 
@@ -237,6 +231,20 @@ typedef struct {
 } CertificateKeyPair;
 
 static void
+supplement_with_attributes (GckAttributes *attrs,
+                            GckAttributes *supplements)
+{
+	GckAttribute *supplement;
+	gint i;
+
+	for (i = 0; i < gck_attributes_count (supplements); i++) {
+		supplement = gck_attributes_at (supplements, i);
+		if (!gck_attribute_is_invalid (supplement) && supplement->length != 0)
+			gck_attributes_add (attrs, supplement);
+	}
+}
+
+static void
 supplement_id_for_data (GckAttributes *attrs,
                         guchar *nonce,
                         gsize n_once,
@@ -263,11 +271,13 @@ supplement_id_for_data (GckAttributes *attrs,
 }
 
 static void
-supplement_attributes (GcrPkcs11Importer *self)
+supplement_attributes (GcrPkcs11Importer *self,
+                       GckAttributes *supplements)
 {
 	GHashTable *pairs;
 	GHashTable *paired;
 	CertificateKeyPair *pair;
+	gboolean supplemented = FALSE;
 	GckAttributes *attrs;
 	gulong klass;
 	guchar *finger;
@@ -343,14 +353,21 @@ supplement_attributes (GcrPkcs11Importer *self)
 			 * Generate a CKA_ID based on the fingerprint and nonce,
 			 * and do the same CKA_ID for both private key and certificate.
 			 */
+
+			supplement_with_attributes (pair->private_key, supplements);
 			supplement_id_for_data (pair->private_key, nonce, sizeof (nonce),
 			                        fingerprint, strlen (fingerprint));
 			g_queue_push_tail (queue, pair->private_key);
 			g_hash_table_insert (paired, pair->private_key, "present");
+
+			supplement_with_attributes (pair->private_key, supplements);
 			supplement_id_for_data (pair->certificate, nonce, sizeof (nonce),
 			                        fingerprint, strlen (fingerprint));
 			g_queue_push_tail (queue, pair->certificate);
 			g_hash_table_insert (paired, pair->certificate, "present");
+
+			/* Used the suplements for the pairs, don't use for unpaired stuff */
+			supplemented = TRUE;
 		}
 	}
 
@@ -358,6 +375,9 @@ supplement_attributes (GcrPkcs11Importer *self)
 	for (l = self->queue->head; l != NULL; l = g_list_next (l)) {
 		attrs = l->data;
 		if (!g_hash_table_lookup (paired, attrs)) {
+			if (!supplemented)
+				supplement_with_attributes (attrs, supplements);
+
 			/*
 			 * Generate a CKA_ID based on the location of attrs in,
 			 * memory, since this together with the nonce should
@@ -365,6 +385,7 @@ supplement_attributes (GcrPkcs11Importer *self)
 			 */
 			supplement_id_for_data (attrs, nonce, sizeof (nonce),
 			                        &attrs, sizeof (gpointer));
+
 			g_queue_push_tail (queue, l->data);
 		}
 	}
@@ -384,7 +405,7 @@ complete_supplement (GSimpleAsyncResult *res,
 	GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
 
 	if (error == NULL) {
-		supplement_attributes (data->importer);
+		supplement_attributes (data->importer, data->supplement);
 		next_state (res, state_create_object);
 	} else {
 		g_simple_async_result_take_error (res, error);
@@ -421,16 +442,51 @@ state_supplement (GSimpleAsyncResult *res,
 
 	} else if (async) {
 		gcr_import_interaction_supplement_async (GCR_IMPORT_INTERACTION (self->interaction),
-		                                         data->cancellable, on_supplement_done,
-		                                         g_object_ref (res));
+		                                         data->supplement, data->cancellable,
+		                                         on_supplement_done, g_object_ref (res));
 
 	} else {
 		gcr_import_interaction_supplement (GCR_IMPORT_INTERACTION (self->interaction),
-		                                   data->cancellable, &error);
+		                                   data->supplement, data->cancellable, &error);
 		complete_supplement (res, error);
 	}
 }
 
+static void
+supplement_prep (GSimpleAsyncResult *res)
+{
+	GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
+	GcrPkcs11Importer *self = data->importer;
+	GckAttribute *the_label = NULL;
+	GckAttribute *attr;
+	gboolean first = TRUE;
+	GList *l;
+
+	if (data->supplement)
+		gck_attributes_unref (data->supplement);
+	data->supplement = gck_attributes_new ();
+
+	/* Do we have a consistent label across all objects? */
+	for (l = self->queue->head; l != NULL; l = g_list_next (l)) {
+		attr = gck_attributes_find (l->data, CKA_LABEL);
+		if (first)
+			the_label = attr;
+		else if (!gck_attribute_equal (the_label, attr))
+			the_label = NULL;
+		first = FALSE;
+	}
+
+	/* If consistent label, set that in supplement data */
+	if (the_label != NULL)
+		gck_attributes_add (data->supplement, the_label);
+	else
+		gck_attributes_add_empty (data->supplement, CKA_LABEL);
+
+	if (GCR_IS_IMPORT_INTERACTION (self->interaction))
+		gcr_import_interaction_supplement_prep (GCR_IMPORT_INTERACTION (self->interaction),
+		                                        data->supplement);
+}
+
 /* ---------------------------------------------------------------------------------
  * OPEN SESSION
  */
@@ -770,9 +826,7 @@ _gcr_pkcs11_importer_import_async (GcrImporter *importer,
 	data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 	g_simple_async_result_set_op_res_gpointer (res, data, gcr_importer_data_free);
 
-	if (GCR_IS_IMPORT_INTERACTION (self->interaction))
-		gcr_import_interaction_set_importer (GCR_IMPORT_INTERACTION (self->interaction),
-		                                     GCR_IMPORTER (self));
+	supplement_prep (res);
 	gck_slot_set_interaction (self->slot, self->interaction);
 
 	next_state (res, state_open_session);



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