static void
state_create_object (GcrImporter *self, gboolean async)
{
	GP11Attributes *attrs;
	GP11Object *object;
	GError *error = NULL;
	
	/* No more objects */
	if (g_queue_is_empty (&self->pv->queue)) {
		next_state (self, state_complete);
		
	} else {
		
		/* Pop first one off the list */
		attrs = g_queue_pop_head (&self->pv->queue);
		g_assert (attrs);
		
		gp11_attributes_add_boolean (attrs, CKA_TOKEN, CK_TRUE);
		
		if (async) {
			gp11_session_create_object_async (self->pv->session, attrs, self->pv->cancel, 
			                                  on_create_object, self);
		} else {
			object = gp11_session_create_object_full (self->pv->session, attrs, self->pv->cancel, &error);
			complete_create_object (self, object, error);
		}
	
		gp11_attributes_unref (attrs);
	}
}
static DBusMessage*
service_method_create_collection (GkdSecretService *self, DBusMessage *message)
{
	DBusMessageIter iter, array;
	GP11Attributes *attrs;
	GkdSecretCreate *create;
	ServiceClient *client;
	DBusMessage *reply;
	const gchar *path;
	const char *caller;
	const gchar *coll;

	/* Parse the incoming message */
	if (!dbus_message_has_signature (message, "a{sv}"))
		return NULL;
	if (!dbus_message_iter_init (message, &iter))
		g_return_val_if_reached (NULL);
	attrs = gp11_attributes_new ();
	dbus_message_iter_recurse (&iter, &array);
	if (!gkd_secret_property_parse_all (&array, attrs)) {
		gp11_attributes_unref (attrs);
		return dbus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS,
		                                      "Invalid properties");
	}

	gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);

	/* Create the prompt object, for the password */
	caller = dbus_message_get_sender (message);
	create = gkd_secret_create_new (self, caller, attrs);
	gp11_attributes_unref (attrs);

	path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (create));
	client = g_hash_table_lookup (self->clients, caller);
	g_return_val_if_fail (client, NULL);
	g_hash_table_replace (client->prompts, (gpointer)path, create);

	coll = "/";
	reply = dbus_message_new_method_return (message);
	dbus_message_append_args (reply,
	                          DBUS_TYPE_OBJECT_PATH, &coll,
	                          DBUS_TYPE_OBJECT_PATH, &path,
	                          DBUS_TYPE_INVALID);

	return reply;
}
static DBusMessage*
service_method_create_with_master_password (GkdSecretService *self, DBusMessage *message)
{
	DBusError derr = DBUS_ERROR_INIT;
	DBusMessageIter iter, array;
	DBusMessage *reply = NULL;
	GkdSecretSecret *secret = NULL;
	GP11Attributes *attrs = NULL;
	gchar *path;

	/* Parse the incoming message */
	if (!dbus_message_has_signature (message, "a{sv}(oayay)"))
		return NULL;
	if (!dbus_message_iter_init (message, &iter))
		g_return_val_if_reached (NULL);
	attrs = gp11_attributes_new ();
	dbus_message_iter_recurse (&iter, &array);
	if (!gkd_secret_property_parse_all (&array, attrs)) {
		gp11_attributes_unref (attrs);
		return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS,
		                               "Invalid properties argument");
	}
	dbus_message_iter_next (&iter);
	secret = gkd_secret_secret_parse (self, message, &iter, &derr);
	if (secret == NULL) {
		gp11_attributes_unref (attrs);
		return gkd_secret_error_to_reply (message, &derr);
	}

	gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
	path = gkd_secret_create_with_secret (attrs, secret, &derr);
	gp11_attributes_unref (attrs);
	gkd_secret_secret_free (secret);

	if (path == NULL)
		return gkd_secret_error_to_reply (message, &derr);

	reply = dbus_message_new_method_return (message);
	dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
	g_free (path);

	return reply;
}
static void 
on_open_session(GP11Slot *slot, GAsyncResult *result, SeahorsePkcs11Refresher *self) 
{
	GError *err = NULL;
	GP11Attributes *attrs;
	
	g_return_if_fail (SEAHORSE_IS_PKCS11_REFRESHER (self));
	
	self->session = gp11_slot_open_session_finish (slot, result, &err);
	if (!self->session) {
		seahorse_pkcs11_mark_complete (SEAHORSE_OPERATION (self), err);
		return;
	}
	
	/* Step 2. Load all the objects that we want */
	attrs = gp11_attributes_new ();
	gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
	gp11_attributes_add_ulong (attrs, CKA_CLASS, CKO_CERTIFICATE);
	gp11_session_find_objects_async (self->session, attrs, self->cancellable, 
	                                 (GAsyncReadyCallback)on_find_objects, self);
	gp11_attributes_unref (attrs);
}