Commit f2e275f2 authored by Stef Walter's avatar Stef Walter Committed by Stef Walter
Browse files

Prompting and item deletion

parent b36268af
......@@ -317,3 +317,11 @@
fun:g_hash_table_remove
fun:g_variant_type_info_unref
}
{
g_rw_lock_reader_lock
Memcheck:Leak
...
fun:g_rw_lock_impl_new
fun:g_rw_lock_get_impl
fun:g_rw_lock_reader_lock
}
......@@ -364,3 +364,28 @@
fun:g_main_loop_run
fun:gdbus_shared_thread_func
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:g_source_new
fun:g_idle_source_new
fun:call_destroy_notify
fun:g_dbus_connection_signal_unsubscribe
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:g_source_set_callback
fun:call_destroy_notify
fun:g_dbus_connection_signal_unsubscribe
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:g_malloc0_n
fun:call_destroy_notify
fun:g_dbus_connection_signal_unsubscribe
}
......@@ -114,6 +114,17 @@ egg_test_wait_until (int timeout)
return (wait_until_impl) (timeout);
}
void
egg_test_wait_idle (void)
{
GMainContext *context;
g_assert (wait_until_impl != NULL);
context = g_main_context_get_thread_default ();
while (g_main_context_iteration (context, FALSE));
}
static GMainLoop *wait_loop = NULL;
static void
......
......@@ -59,6 +59,8 @@ void egg_test_wait_stop (void);
gboolean egg_test_wait_until (int timeout);
void egg_test_wait_idle (void);
gint egg_tests_run_with_loop (void);
#endif /* EGG_DH_H_ */
......@@ -17,6 +17,8 @@ BUILT_SOURCES = \
libgsecret_la_SOURCES = \
gsecret-value.h gsecret-value.c \
gsecret-item.h gsecret-item.c \
gsecret-password.h gsecret-password.c \
gsecret-prompt.h gsecret-prompt.c \
gsecret-service.h gsecret-service.c \
gsecret-util.c \
$(BUILT_SOURCES) \
......
......@@ -24,7 +24,6 @@ G_BEGIN_DECLS
#define GSECRET_IS_SERVICE_CLASS(class) (GSECRET_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_SERVICE))
#define GSECRET_SERVICE_GET_CLASS(inst) (GSECRET_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_SERVICE, GSecretServiceClass))
typedef struct _GSecretService GSecretService;
typedef struct _GSecretServiceClass GSecretServiceClass;
typedef struct _GSecretServicePrivate GSecretServicePrivate;
......
......@@ -38,96 +38,47 @@ gsecret_item_class_init (GSecretItemClass *klass)
}
static void
on_item_delete_ready (GObject *source, GAsyncResult *result, gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
GError *error = NULL;
GVariant *ret;
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
result, &error);
if (ret == NULL)
g_simple_async_result_take_error (res, error);
else
g_variant_unref (ret);
g_simple_async_result_complete (res);
g_object_unref (res);
}
void
gsecret_item_delete (GSecretItem *self, GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer user_data)
gsecret_item_delete (GSecretItem *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
const gchar *object_path;
gchar *collection_path;
GSimpleAsyncResult *res;
g_return_if_fail (GSECRET_IS_ITEM (self));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
res = g_simple_async_result_new (G_OBJECT (self), callback,
user_data, gsecret_item_delete);
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
collection_path = _gsecret_util_parent_path (object_path);
g_dbus_connection_call (g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
g_dbus_proxy_get_name (G_DBUS_PROXY (self)),
collection_path, GSECRET_COLLECTION_INTERFACE,
"Delete", NULL, NULL,
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
cancellable, on_item_delete_ready, res);
g_free (collection_path);
gsecret_service_delete_path (self->pv->service, object_path,
cancellable, callback, user_data);
}
gboolean
gsecret_item_delete_finish (GSecretItem *self, GAsyncResult *result,
gsecret_item_delete_finish (GSecretItem *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
g_return_val_if_fail (g_simple_async_result_is_valid (result,
G_OBJECT (self), gsecret_item_delete), FALSE);
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
error))
return FALSE;
return TRUE;
return gsecret_service_delete_path_finish (self->pv->service, result, error);
}
gboolean
gsecret_item_delete_sync (GSecretItem *self, GCancellable *cancellable,
gsecret_item_delete_sync (GSecretItem *self,
GCancellable *cancellable,
GError **error)
{
const gchar *object_path;
gchar *collection_path;
GVariant *ret;
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
collection_path = _gsecret_util_parent_path (object_path);
ret = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
g_dbus_proxy_get_name (G_DBUS_PROXY (self)),
collection_path, GSECRET_COLLECTION_INTERFACE,
"Delete", NULL, NULL,
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
cancellable, error);
g_free (collection_path);
if (ret != NULL) {
g_variant_unref (ret);
return TRUE;
}
return FALSE;
return gsecret_service_delete_path_sync (self->pv->service,
object_path, cancellable, error);
}
static void
......
......@@ -16,6 +16,7 @@
#include <gio/gio.h>
#include "gsecret-item.h"
#include "gsecret-service.h"
#include "gsecret-value.h"
G_BEGIN_DECLS
......@@ -27,7 +28,6 @@ G_BEGIN_DECLS
#define GSECRET_IS_ITEM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_ITEM))
#define GSECRET_ITEM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_ITEM, GSecretItemClass))
typedef struct _GSecretItem GSecretItem;
typedef struct _GSecretItemClass GSecretItemClass;
typedef struct _GSecretItemPrivate GSecretItemPrivate;
......
/* GSecret - GLib wrapper for Secret Service
*
* Copyright 2011 Collabora Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the licence or (at
* your option) any later version.
*
* See the included COPYING file for more information.
*/
#include "config.h"
#include "gsecret-password.h"
#include "gsecret-private.h"
#include "gsecret-value.h"
#include <egg/egg-secure-memory.h>
typedef struct {
GAsyncResult *result;
GMainContext *context;
GMainLoop *loop;
} SyncClosure;
static SyncClosure *
sync_closure_new (void)
{
SyncClosure *closure;
closure = g_new0 (SyncClosure, 1);
closure->context = g_main_context_new ();
closure->loop = g_main_loop_new (closure->context, FALSE);
return closure;
}
static void
sync_closure_free (gpointer data)
{
SyncClosure *closure = data;
g_clear_object (&closure->result);
g_main_loop_unref (closure->loop);
g_main_context_unref (closure->context);
}
static void
on_sync_result (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
SyncClosure *closure = user_data;
closure->result = g_object_ref (result);
g_main_loop_quit (closure->loop);
}
#if 0
typedef struct {
GVariant *properties;
gchar *collection_path;
GSecretValue *secret;
GCancellable *cancellable;
} StoreClosure;
static void
store_closure_free (gpointer data)
{
StoreClosure *closure = data;
g_variant_unref (closure->properties);
g_free (closure->collection_path);
gsecret_value_unref (closure->secret);
g_clear_object (closure->cancellable);
g_free (closure);
}
static void
on_create_item_reply (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
GError *error = NULL;
retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
if (error == NULL) {
g_variant_get (retval, "(&o&o)", &item_path, &prompt_path);
if (prompt_path xxx)
gsecret_prompt_perform (self, "", closure->cancellable,
on_store_prompt_complete, NULL);
if (g_strcmp0 (item_path, "/") != 0)
xxx complete!
}
g_object_unref (res);
}
static void
on_store_service_connected (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
StoreClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GSecretService *service;
GError *error = NULL;
GDBusProxy *proxy;
GVariant *params;
service = _gsecret_service_bare_connect_finish (result, &error);
if (error == NULL) {
params = g_variant_new ("(&a{sv}&(oayays)b)",
closure->properties,
_gsecret_service_encode_secret (service, closure->secret),
TRUE);
proxy = G_DBUS_PROXY (service);
g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
g_dbus_proxy_get_name (proxy),
closure->collection_path,
GSECRET_COLLECTION_INTERFACE,
"CreateItem", params, G_VARIANT_TYPE ("(oo)"),
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
closure->cancellable, on_create_item_reply,
g_object_ref (res));
} else {
g_simple_async_result_take_error (res, error);
g_simple_async_result_complete (res);
<arg name="item" type="o" direction="out"/>
<arg name="prompt" type="o" direction="out"/>
}
g_object_unref (res);
}
void
gsecret_password_store (const GSecretSchema *schema,
const gchar *collection_path,
const gchar *label,
const gchar *password,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...)
{
GSimpleAsyncResult *res;
GVariant *attributes;
StoreClosure *closure;
GVariantBuilder builder;
va_list va;
g_return_if_fail (schema != NULL);
g_return_if_fail (label != NULL);
g_return_if_fail (password != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
/* Build up the attributes */
va_start (va, user_data);
attributes = build_attributes (schema, va);
va_end (va);
g_return_if_fail (attributes != NULL);
/* Build up the various properties */
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Attributes", attributes);
g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Label", g_variant_new_string ("label"));
g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Schema", g_variant_new_string (schema->schema_name));
res = g_simple_async_result_new (NULL, callback, user_data,
gsecret_password_store_finish);
closure = g_new0 (StoreClosure, 1);
closure->properties = g_variant_ref_sink (g_variant_builder_end (&builder));
closure->collection_path = g_strdup (collection_path);
closure->secret = gsecret_value_new (password, -1, "text/plain");
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
g_simple_async_result_set_op_res_gpointer (res, closure, store_closure_free);
_gsecret_service_bare_connect_with_session (cancellable, on_store_service_connected,
g_object_ref (res));
g_object_unref (res);
}
#if 0
gboolean
gsecret_password_store_finish (GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
}
gboolean
gsecret_password_store_sync (const GSecretPasswordSchema *schema,
const gchar *collection,
const gchar *label,
const gchar *password,
GCancellable *cancellable,
GError **error,
const gchar *attribute_name,
...)
{
g_return_val_if_fail (schema != NULL, FALSE);
g_return_val_if_fail (display_name != NULL, FALSE);
g_return_val_if_fail (password != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
}
void
gsecret_password_lookup (const GSecretPasswordSchema *schema,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
const gchar *attribute_name,
...)
{
g_return_if_fail (schema != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
}
gchar *
gsecret_password_lookup_finish (GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
}
gchar *
gsecret_password_lookup_sync (const GSecretPasswordSchema *schema,
GCancellable *cancellable,
GError **error,
const gchar *attribute_name,
...)
{
g_return_val_if_fail (schema != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
}
#endif
#endif
typedef struct {
GCancellable *cancellable;
GHashTable *attributes;
gboolean deleted;
} DeleteClosure;
static void
delete_closure_free (gpointer data)
{
DeleteClosure *closure = data;
g_clear_object (&closure->cancellable);
g_hash_table_unref (closure->attributes);
g_slice_free (DeleteClosure, closure);
}
void
gsecret_password_delete (const GSecretSchema *schema,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...)
{
GHashTable *attributes;
va_list va;
g_return_if_fail (schema != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
va_start (va, user_data);
attributes = _gsecret_util_attributes_for_varargs (schema, va);
va_end (va);
gsecret_password_deletev (attributes, cancellable,
callback, user_data);
g_hash_table_unref (attributes);
}
static void
on_delete_complete (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GError *error = NULL;
closure->deleted = gsecret_service_delete_password_finish (GSECRET_SERVICE (source),
result, &error);
if (error != NULL)
g_simple_async_result_take_error (res, error);
g_simple_async_result_complete (res);
g_object_unref (res);
}
static void
on_delete_connect (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GSecretService *service;
GError *error = NULL;
service = _gsecret_service_bare_connect_finish (result, &error);
if (error == NULL) {
gsecret_service_delete_passwordv (service, closure->attributes,
closure->cancellable, on_delete_complete,
g_object_ref (res));
g_object_unref (service);
} else {
g_simple_async_result_take_error (res, error);
g_simple_async_result_complete (res);
}
g_object_unref (res);
}
void
gsecret_password_deletev (GHashTable *attributes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *res;
DeleteClosure *closure;
g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
res = g_simple_async_result_new (NULL, callback, user_data,
gsecret_password_deletev);
closure = g_slice_new0 (DeleteClosure);
closure->attributes = g_hash_table_ref (attributes);
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free);
_gsecret_service_bare_connect (NULL, FALSE, cancellable,
on_delete_connect,
g_object_ref (res));
g_object_unref (res);
}
gboolean
gsecret_password_delete_finish (GAsyncResult *result,
GError **error)
{
DeleteClosure *closure;
GSimpleAsyncResult *res;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
gsecret_password_deletev), FALSE);
res = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (res, error))
return FALSE;
closure = g_simple_async_result_get_op_res_gpointer (res);
return closure->deleted;
}
gboolean
gsecret_password_delete_sync (const GSecretSchema* schema,
GCancellable *cancellable,
GError **error,
...)
{
GHashTable *attributes;
gboolean result;
va_list va;
g_return_val_if_fail (schema != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
va_start (va, error);
attributes = _gsecret_util_attributes_for_varargs (schema, va);
va_end (va);
result = gsecret_password_deletev_sync (attributes, cancellable, error);
g_hash_table_unref (attributes);
return result;
}
gboolean
gsecret_password_deletev_sync (GHashTable *attributes,
GCancellable *cancellable,
GError **error)
{
SyncClosure *closure;
gboolean result;
g_return_val_if_fail (attributes != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
closure = sync_closure_new ();