static void
test_expose_transaction (Test* test, gconstpointer unused)
{
	CK_OBJECT_HANDLE handle;
	GkmManager *manager;
	GkmObject *check, *object;
	GkmTransaction *transaction;

	manager = gkm_session_get_manager (test->session);
	object = mock_module_object_new (test->session);

	handle = gkm_object_get_handle (object);
	transaction = gkm_transaction_new ();

	/* Should be hidden */
	gkm_object_expose (object, FALSE);
	check = gkm_manager_find_by_handle (manager, handle);
	g_assert (check == NULL);

	/* Now it should have a handle, and be visible */
	gkm_object_expose_full (object, transaction, TRUE);
	check = gkm_manager_find_by_handle (manager, handle);
	g_assert (check == object);

	gkm_transaction_fail (transaction, CKR_GENERAL_ERROR);
	gkm_transaction_complete (transaction);

	/* Now should be invisible */
	check = gkm_manager_find_by_handle (manager, handle);
	g_assert (check == NULL);

	g_object_unref (transaction);
}
static void
gkm_object_dispose (GObject *obj)
{
	GkmObject *self = GKM_OBJECT (obj);
	GkmObjectTransient *transient;

	if (self->pv->manager) {
		if (self->pv->exposed)
			gkm_object_expose (self, FALSE);
		g_return_if_fail (!self->pv->exposed);
		g_object_remove_weak_pointer (G_OBJECT (self->pv->manager),
		                              (gpointer*)&(self->pv->manager));
		self->pv->manager = NULL;
	}

	g_object_set (self, "store", NULL, NULL);
	g_assert (self->pv->store == NULL);

	if (self->pv->transient) {
		transient = self->pv->transient;
		if (transient->timer)
			gkm_timer_cancel (transient->timer);
		transient->timer = NULL;
	}

	G_OBJECT_CLASS (gkm_object_parent_class)->dispose (obj);
}
static void
file_load (EggFileTracker *tracker,
           const gchar *path,
           GkmSshModule *self)
{
	GkmSshPrivateKey *key;
	gchar *private_path;
	GError *error = NULL;
	gchar *unique;

	g_return_if_fail (path);
	g_return_if_fail (GKM_IS_SSH_MODULE (self));

	private_path = private_path_for_public (path);
	if (!private_path || !g_file_test (private_path, G_FILE_TEST_IS_REGULAR)) {
		g_message ("no private key present for public key: %s", path);
		g_free (private_path);
		return;
	}

	/* Create a key if necessary */
	key = g_hash_table_lookup (self->keys_by_path, path);
	if (key == NULL) {
		unique = g_strdup_printf ("ssh-store:%s", private_path);
		key = gkm_ssh_private_key_new (GKM_MODULE (self), unique);
		g_free (unique);

		g_hash_table_replace (self->keys_by_path, g_strdup (path), key);
	}

	/* Parse the data into the key */
	if (!gkm_ssh_private_key_parse (key, path, private_path, &error)) {
		if (error) {
			g_message ("couldn't parse data: %s: %s", path, egg_error_message (error));
			g_clear_error (&error);
		}
		gkm_object_expose (GKM_OBJECT (key), FALSE);

	/* When successful register with the object manager */
	} else {
		gkm_object_expose (GKM_OBJECT (key), TRUE);
	}

	g_free (private_path);
}
static gboolean
complete_expose (GkmTransaction *transaction, GObject *obj, gpointer user_data)
{
	GkmObject *self = GKM_OBJECT (obj);
	gboolean expose = GPOINTER_TO_UINT (user_data);

	if (gkm_transaction_get_failed (transaction))
		gkm_object_expose (self, !expose);

	return TRUE;
}
static void
gkm_xdg_trust_expose_object (GkmObject *base, gboolean expose)
{
	GHashTableIter iter;
	gpointer value;

	GKM_OBJECT_CLASS (gkm_xdg_trust_parent_class)->expose_object (base, expose);

	g_hash_table_iter_init (&iter, GKM_XDG_TRUST (base)->pv->assertions);
	while (g_hash_table_iter_next (&iter, NULL, &value))
		gkm_object_expose (value, expose);
}
static void
test_expose (Test* test, gconstpointer unused)
{
	CK_OBJECT_HANDLE handle;
	GkmManager *manager;
	GkmObject *check, *object;

	manager = gkm_session_get_manager (test->session);
	object = mock_module_object_new (test->session);

	handle = gkm_object_get_handle (object);
	gkm_object_expose (object, TRUE);

	/* Now it should have a handle, and be visible */
	check = gkm_manager_find_by_handle (manager, handle);
	g_assert (check == object);

	gkm_object_expose (object, FALSE);

	/* Now should be invisible */
	check = gkm_manager_find_by_handle (manager, handle);
	g_assert (check == NULL);
}
static void
add_assertion_to_trust (GkmXdgTrust *self, GkmAssertion *assertion,
                        GkmTransaction *transaction)
{
	GBytes *key;

	key = lookup_or_create_assertion_key (assertion);
	g_assert (key != NULL);

	g_hash_table_insert (self->pv->assertions, g_bytes_ref (key), g_object_ref (assertion));
	gkm_object_expose (GKM_OBJECT (assertion), gkm_object_is_exposed (GKM_OBJECT (self)));

	if (transaction != NULL)
		gkm_transaction_add (transaction, self, complete_add_assertion, g_object_ref (assertion));
}
void
gkm_object_expose_full (GkmObject *self, GkmTransaction *transaction, gboolean expose)
{
	if (!expose && !self)
		return;

	g_return_if_fail (GKM_IS_OBJECT (self));
	g_return_if_fail (!transaction || !gkm_transaction_get_failed (transaction));

	if (self->pv->exposed != expose) {
		if (transaction)
			gkm_transaction_add (transaction, self, complete_expose, GUINT_TO_POINTER (expose));
		gkm_object_expose (self, expose);
	}
}
static GkmCertificate*
add_certificate_for_data (GkmRootsModule *self, const guchar *data,
                          gsize n_data, const gchar *path)
{
	GkmCertificate *cert;
	GkmManager *manager;
	gchar *hash, *unique;

	g_assert (GKM_IS_ROOTS_MODULE (self));
	g_assert (data);
	g_assert (path);

	manager = gkm_module_get_manager (GKM_MODULE (self));
	g_return_val_if_fail (manager, NULL);

	/* Hash the certificate */
	hash = g_compute_checksum_for_data (G_CHECKSUM_MD5, data, n_data);
	unique = g_strdup_printf ("%s:%s", path, hash);
	g_free (hash);

	/* Try and find a certificate */
	cert = GKM_CERTIFICATE (gkm_manager_find_one_by_string_property (manager, "unique", unique));
	if (cert != NULL) {
		g_free (unique);
		return cert;
	}

	/* Create a new certificate object */
	cert = GKM_CERTIFICATE (gkm_roots_certificate_new (GKM_MODULE (self), unique, path));
	g_free (unique);

	if (!gkm_serializable_load (GKM_SERIALIZABLE (cert), NULL, data, n_data)) {
		g_message ("couldn't parse certificate(s): %s", path);
		g_object_unref (cert);
		return NULL;
	}

	/* Make the certificate show up */
	gkm_object_expose (GKM_OBJECT (cert), TRUE);

	/* And add to our wonderful table */
	g_hash_table_insert (self->certificates, cert, cert);
	return cert;
}
static void
take_object_ownership (GkmMate2Storage *self, const gchar *identifier, GkmObject *object)
{
    gchar *str;

    g_assert (GKM_IS_MATE2_STORAGE (self));
    g_assert (GKM_IS_OBJECT (object));

    g_assert (g_hash_table_lookup (self->identifier_to_object, identifier) == NULL);
    g_assert (g_hash_table_lookup (self->object_to_identifier, object) == NULL);

    str = g_strdup (identifier);
    object = g_object_ref (object);

    g_hash_table_replace (self->identifier_to_object, str, object);
    g_hash_table_replace (self->object_to_identifier, object, str);;

    g_object_set (object, "store", self, NULL);
    gkm_object_expose (object, TRUE);
}
static void
remove_assertion_from_trust (GkmXdgTrust *self, GkmAssertion *assertion,
                             GkmTransaction *transaction)
{
	GByteArray *key;

	key = lookup_assertion_key (assertion);
	g_assert (key);

	gkm_object_expose (GKM_OBJECT (assertion), FALSE);

	if (transaction == NULL) {
		if (!g_hash_table_remove (self->pv->assertions, key))
			g_return_if_reached ();
	} else {
		if (!g_hash_table_steal (self->pv->assertions, key))
			g_return_if_reached ();
		gkm_transaction_add (transaction, self, complete_remove_assertion, assertion);
	}
}
static void
add_transient_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object)
{
	g_assert (GKM_IS_MODULE (self));
	g_assert (GKM_IS_OBJECT (object));

	/* Must not already be associated with a session or manager */
	g_return_if_fail (gkm_object_get_manager (object) == self->pv->token_manager);
	g_return_if_fail (g_hash_table_lookup (self->pv->transient_objects, object) == NULL);

	g_hash_table_insert (self->pv->transient_objects, object, g_object_ref (object));
	g_object_set (object, "store", self->pv->transient_store, NULL);
	gkm_object_expose (object, TRUE);

	if (transaction) {
		gkm_transaction_add (transaction, self,
		                     (GkmTransactionFunc)complete_transient_add,
		                     g_object_ref (object));
	}
}
static void
remove_transient_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object)
{
	g_assert (GKM_IS_MODULE (self));
	g_assert (GKM_IS_OBJECT (object));

	g_object_ref (object);

	gkm_object_expose (object, FALSE);
	if (!g_hash_table_remove (self->pv->transient_objects, object))
		g_return_if_reached ();
	g_object_set (object, "store", NULL, NULL);

	if (transaction) {
		gkm_transaction_add (transaction, self,
		                     (GkmTransactionFunc)complete_transient_remove,
		                     g_object_ref (object));
	}

	g_object_unref (object);
}
static void
gkm_roots_certificate_expose_object (GkmObject *obj, gboolean expose)
{
	GKM_OBJECT_CLASS (gkm_roots_certificate_parent_class)->expose_object (obj, expose);
	gkm_object_expose (GKM_OBJECT (GKM_ROOTS_CERTIFICATE (obj)->trust), expose);
}
static void
gkm_ssh_private_key_expose (GkmObject *base, gboolean expose)
{
	GKM_OBJECT_CLASS (gkm_ssh_private_key_parent_class)->expose_object (base, expose);
	gkm_object_expose (GKM_OBJECT (GKM_SSH_PRIVATE_KEY (base)->pubkey), expose);
}