mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2024-12-22 12:48:51 +00:00
Prompting and item deletion
This commit is contained in:
parent
b36268afc1
commit
f2e275f25e
@ -317,3 +317,11 @@
|
|||||||
fun:g_hash_table_remove
|
fun:g_hash_table_remove
|
||||||
fun:g_variant_type_info_unref
|
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:g_main_loop_run
|
||||||
fun:gdbus_shared_thread_func
|
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);
|
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 GMainLoop *wait_loop = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -59,6 +59,8 @@ void egg_test_wait_stop (void);
|
|||||||
|
|
||||||
gboolean egg_test_wait_until (int timeout);
|
gboolean egg_test_wait_until (int timeout);
|
||||||
|
|
||||||
|
void egg_test_wait_idle (void);
|
||||||
|
|
||||||
gint egg_tests_run_with_loop (void);
|
gint egg_tests_run_with_loop (void);
|
||||||
|
|
||||||
#endif /* EGG_DH_H_ */
|
#endif /* EGG_DH_H_ */
|
||||||
|
@ -17,6 +17,8 @@ BUILT_SOURCES = \
|
|||||||
libgsecret_la_SOURCES = \
|
libgsecret_la_SOURCES = \
|
||||||
gsecret-value.h gsecret-value.c \
|
gsecret-value.h gsecret-value.c \
|
||||||
gsecret-item.h gsecret-item.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-service.h gsecret-service.c \
|
||||||
gsecret-util.c \
|
gsecret-util.c \
|
||||||
$(BUILT_SOURCES) \
|
$(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_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))
|
#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 _GSecretServiceClass GSecretServiceClass;
|
||||||
typedef struct _GSecretServicePrivate GSecretServicePrivate;
|
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
|
void
|
||||||
gsecret_item_delete (GSecretItem *self, GCancellable *cancellable,
|
gsecret_item_delete (GSecretItem *self,
|
||||||
GAsyncReadyCallback callback, gpointer user_data)
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
const gchar *object_path;
|
const gchar *object_path;
|
||||||
gchar *collection_path;
|
|
||||||
GSimpleAsyncResult *res;
|
|
||||||
|
|
||||||
g_return_if_fail (GSECRET_IS_ITEM (self));
|
g_return_if_fail (GSECRET_IS_ITEM (self));
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
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));
|
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
|
||||||
collection_path = _gsecret_util_parent_path (object_path);
|
gsecret_service_delete_path (self->pv->service, object_path,
|
||||||
|
cancellable, callback, user_data);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gsecret_item_delete_finish (GSecretItem *self, GAsyncResult *result,
|
gsecret_item_delete_finish (GSecretItem *self,
|
||||||
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
|
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 (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),
|
return gsecret_service_delete_path_finish (self->pv->service, result, error);
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gsecret_item_delete_sync (GSecretItem *self, GCancellable *cancellable,
|
gsecret_item_delete_sync (GSecretItem *self,
|
||||||
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
const gchar *object_path;
|
const gchar *object_path;
|
||||||
gchar *collection_path;
|
|
||||||
GVariant *ret;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
|
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 (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
|
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
|
||||||
collection_path = _gsecret_util_parent_path (object_path);
|
return gsecret_service_delete_path_sync (self->pv->service,
|
||||||
|
object_path, cancellable, error);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
#include "gsecret-item.h"
|
#include "gsecret-item.h"
|
||||||
|
#include "gsecret-service.h"
|
||||||
#include "gsecret-value.h"
|
#include "gsecret-value.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
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_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))
|
#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 _GSecretItemClass GSecretItemClass;
|
||||||
typedef struct _GSecretItemPrivate GSecretItemPrivate;
|
typedef struct _GSecretItemPrivate GSecretItemPrivate;
|
||||||
|
|
||||||
|
440
library/gsecret-password.c
Normal file
440
library/gsecret-password.c
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
/* 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 ();
|
||||||
|
g_main_context_push_thread_default (closure->context);
|
||||||
|
|
||||||
|
gsecret_password_deletev (attributes, cancellable,
|
||||||
|
on_sync_result, closure);
|
||||||
|
|
||||||
|
g_main_loop_run (closure->loop);
|
||||||
|
|
||||||
|
result = gsecret_password_delete_finish (closure->result, error);
|
||||||
|
|
||||||
|
g_main_context_pop_thread_default (closure->context);
|
||||||
|
sync_closure_free (closure);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_password_free (gpointer password)
|
||||||
|
{
|
||||||
|
if (password == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
egg_secure_strfree (password);
|
||||||
|
}
|
||||||
|
|
87
library/gsecret-password.h
Normal file
87
library/gsecret-password.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GSECRET_PASSWORD_H__
|
||||||
|
#define __GSECRET_PASSWORD_H__
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#include "gsecret-types.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
void gsecret_password_store (const GSecretSchema *schema,
|
||||||
|
const gchar *collection_path,
|
||||||
|
const gchar *label,
|
||||||
|
const gchar *password,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
gboolean gsecret_password_store_finish (GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gsecret_password_store_sync (const GSecretSchema *schema,
|
||||||
|
const gchar *collection,
|
||||||
|
const gchar *display_name,
|
||||||
|
const gchar *password,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
void gsecret_password_lookup (const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
gchar * gsecret_password_lookup_finish (GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gchar * gsecret_password_lookup_sync (const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void gsecret_password_delete (const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
void gsecret_password_deletev (GHashTable *attributes,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean gsecret_password_delete_finish (GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gsecret_password_delete_sync (const GSecretSchema* schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
gboolean gsecret_password_deletev_sync (GHashTable *attributes,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gsecret_password_free (gpointer password);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __G_SERVICE_H___ */
|
@ -30,22 +30,44 @@ typedef struct {
|
|||||||
|
|
||||||
#define GSECRET_SERVICE_BUS_NAME "org.freedesktop.Secret.Service"
|
#define GSECRET_SERVICE_BUS_NAME "org.freedesktop.Secret.Service"
|
||||||
|
|
||||||
|
#define GSECRET_ITEM_INTERFACE "org.freedesktop.Secret.Item"
|
||||||
|
#define GSECRET_COLLECTION_INTERFACE "org.freedesktop.Secret.Collection"
|
||||||
|
#define GSECRET_PROMPT_INTERFACE "org.freedesktop.Secret.Prompt"
|
||||||
#define GSECRET_SERVICE_INTERFACE "org.freedesktop.Secret.Service"
|
#define GSECRET_SERVICE_INTERFACE "org.freedesktop.Secret.Service"
|
||||||
|
|
||||||
#define GSECRET_COLLECTION_INTERFACE "org.freedesktop.Secret.Collection"
|
#define GSECRET_PROMPT_SIGNAL_COMPLETED "Completed"
|
||||||
|
|
||||||
GSecretParams * _gsecret_params_new (GCancellable *cancellable,
|
GSecretParams * _gsecret_params_new (GCancellable *cancellable,
|
||||||
GVariant *in);
|
GVariant *in);
|
||||||
|
|
||||||
void _gsecret_params_free (gpointer data);
|
void _gsecret_params_free (gpointer data);
|
||||||
|
|
||||||
|
GSecretPrompt * _gsecret_prompt_instance (GDBusConnection *connection,
|
||||||
|
const gchar *object_path);
|
||||||
|
|
||||||
gchar * _gsecret_util_parent_path (const gchar *path);
|
gchar * _gsecret_util_parent_path (const gchar *path);
|
||||||
|
|
||||||
|
gboolean _gsecret_util_empty_path (const gchar *path);
|
||||||
|
|
||||||
GVariant * _gsecret_util_variant_for_attributes (GHashTable *attributes);
|
GVariant * _gsecret_util_variant_for_attributes (GHashTable *attributes);
|
||||||
|
|
||||||
|
GHashTable * _gsecret_util_attributes_for_varargs (const GSecretSchema *schema,
|
||||||
|
va_list va);
|
||||||
|
|
||||||
|
void _gsecret_service_set_default_bus_name (const gchar *bus_name);
|
||||||
|
|
||||||
GSecretService * _gsecret_service_bare_instance (GDBusConnection *connection,
|
GSecretService * _gsecret_service_bare_instance (GDBusConnection *connection,
|
||||||
const gchar *bus_name);
|
const gchar *bus_name);
|
||||||
|
|
||||||
|
void _gsecret_service_bare_connect (const gchar *bus_name,
|
||||||
|
gboolean ensure_session,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GSecretService * _gsecret_service_bare_connect_finish (GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
GVariant * _gsecret_service_encode_secret (GSecretService *self,
|
GVariant * _gsecret_service_encode_secret (GSecretService *self,
|
||||||
GSecretValue *value);
|
GSecretValue *value);
|
||||||
|
|
||||||
|
433
library/gsecret-prompt.c
Normal file
433
library/gsecret-prompt.c
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
/* GSecret - GLib wrapper for Secret Prompt
|
||||||
|
*
|
||||||
|
* 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-dbus-generated.h"
|
||||||
|
#include "gsecret-private.h"
|
||||||
|
#include "gsecret-prompt.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n-lib.h>
|
||||||
|
|
||||||
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
struct _GSecretPromptPrivate {
|
||||||
|
gint prompted;
|
||||||
|
GVariant *last_result;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GSecretPrompt, gsecret_prompt, G_TYPE_DBUS_PROXY);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsecret_prompt_init (GSecretPrompt *self)
|
||||||
|
{
|
||||||
|
self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GSECRET_TYPE_PROMPT,
|
||||||
|
GSecretPromptPrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsecret_prompt_finalize (GObject *obj)
|
||||||
|
{
|
||||||
|
GSecretPrompt *self = GSECRET_PROMPT (obj);
|
||||||
|
|
||||||
|
if (self->pv->last_result)
|
||||||
|
g_variant_unref (self->pv->last_result);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsecret_prompt_parent_class)->finalize (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsecret_prompt_class_init (GSecretPromptClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gsecret_prompt_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (GSecretPromptPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GMainLoop *loop;
|
||||||
|
GAsyncResult *result;
|
||||||
|
} RunClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_prompt_run_complete (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
RunClosure *closure = user_data;
|
||||||
|
closure->result = g_object_ref (result);
|
||||||
|
g_main_loop_quit (closure->loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSecretPrompt *
|
||||||
|
gsecret_prompt_instance (GSecretService *service,
|
||||||
|
const gchar *prompt_path)
|
||||||
|
{
|
||||||
|
GDBusProxy *proxy;
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (service), NULL);
|
||||||
|
g_return_val_if_fail (prompt_path != NULL, NULL);
|
||||||
|
|
||||||
|
proxy = G_DBUS_PROXY (service);
|
||||||
|
prompt = g_initable_new (GSECRET_TYPE_PROMPT, NULL, &error,
|
||||||
|
"g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||||
|
"g-interface-info", _gsecret_gen_prompt_interface_info (),
|
||||||
|
"g-name", g_dbus_proxy_get_name (proxy),
|
||||||
|
"g-connection", g_dbus_proxy_get_connection (proxy),
|
||||||
|
"g-object-path", prompt_path,
|
||||||
|
"g-interface-name", GSECRET_PROMPT_INTERFACE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("couldn't create GSecretPrompt object: %s", error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_prompt_run (GSecretPrompt *self,
|
||||||
|
gulong window_id,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GMainContext *context;
|
||||||
|
RunClosure *closure;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_PROMPT (self), FALSE);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
context = g_main_context_get_thread_default ();
|
||||||
|
|
||||||
|
closure = g_new0 (RunClosure, 1);
|
||||||
|
closure->loop = g_main_loop_new (context, FALSE);
|
||||||
|
|
||||||
|
gsecret_prompt_perform (self, window_id, cancellable,
|
||||||
|
on_prompt_run_complete, closure);
|
||||||
|
|
||||||
|
g_main_loop_run (closure->loop);
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_finish (self, closure->result, error);
|
||||||
|
|
||||||
|
g_main_loop_unref (closure->loop);
|
||||||
|
g_object_unref (closure->result);
|
||||||
|
g_free (closure);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_prompt_perform_sync (GSecretPrompt *self,
|
||||||
|
gulong window_id,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GMainContext *context;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_PROMPT (self), FALSE);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
context = g_main_context_new ();
|
||||||
|
g_main_context_push_thread_default (context);
|
||||||
|
|
||||||
|
ret = gsecret_prompt_run (self, window_id, cancellable, error);
|
||||||
|
|
||||||
|
/* Needed to prevent memory leaks */
|
||||||
|
while (g_main_context_iteration (context, FALSE));
|
||||||
|
|
||||||
|
g_main_context_pop_thread_default (context);
|
||||||
|
g_main_context_unref (context);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GCancellable *call_cancellable;
|
||||||
|
GCancellable *async_cancellable;
|
||||||
|
gulong cancelled_sig;
|
||||||
|
gboolean prompting;
|
||||||
|
gboolean dismissed;
|
||||||
|
gboolean vanished;
|
||||||
|
gboolean completed;
|
||||||
|
guint signal;
|
||||||
|
guint watch;
|
||||||
|
} PerformClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
perform_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
PerformClosure *closure = data;
|
||||||
|
g_object_unref (closure->call_cancellable);
|
||||||
|
g_clear_object (&closure->async_cancellable);
|
||||||
|
g_object_unref (closure->connection);
|
||||||
|
g_assert (closure->signal == 0);
|
||||||
|
g_assert (closure->watch == 0);
|
||||||
|
g_slice_free (PerformClosure, closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
perform_prompt_complete (GSimpleAsyncResult *res,
|
||||||
|
gboolean dismissed)
|
||||||
|
{
|
||||||
|
PerformClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
|
||||||
|
closure->dismissed = dismissed;
|
||||||
|
if (closure->completed)
|
||||||
|
return;
|
||||||
|
closure->completed = TRUE;
|
||||||
|
|
||||||
|
if (closure->signal)
|
||||||
|
g_dbus_connection_signal_unsubscribe (closure->connection, closure->signal);
|
||||||
|
closure->signal = 0;
|
||||||
|
|
||||||
|
if (closure->watch)
|
||||||
|
g_bus_unwatch_name (closure->watch);
|
||||||
|
closure->watch = 0;
|
||||||
|
|
||||||
|
if (closure->cancelled_sig)
|
||||||
|
g_signal_handler_disconnect (closure->async_cancellable, closure->cancelled_sig);
|
||||||
|
closure->cancelled_sig = 0;
|
||||||
|
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_prompt_completed (GDBusConnection *connection,
|
||||||
|
const gchar *sender_name,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *signal_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
GSecretPrompt *self = GSECRET_PROMPT (g_async_result_get_source_object (user_data));
|
||||||
|
PerformClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
gboolean dismissed;
|
||||||
|
|
||||||
|
closure->prompting = FALSE;
|
||||||
|
|
||||||
|
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(bv)"))) {
|
||||||
|
g_warning ("GSecretPrompt received invalid %s signal of type %s",
|
||||||
|
signal_name, g_variant_get_type_string (parameters));
|
||||||
|
perform_prompt_complete (res, TRUE);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_return_if_fail (self->pv->last_result == NULL);
|
||||||
|
g_variant_get (parameters, "(bv)", &dismissed, &self->pv->last_result);
|
||||||
|
perform_prompt_complete (res, dismissed);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_prompt_prompted (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
PerformClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GSecretPrompt *self = GSECRET_PROMPT (source);
|
||||||
|
GError *error = NULL;
|
||||||
|
GVariant *retval;
|
||||||
|
|
||||||
|
retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, &error);
|
||||||
|
|
||||||
|
if (retval)
|
||||||
|
g_variant_unref (retval);
|
||||||
|
if (closure->vanished)
|
||||||
|
g_clear_error (&error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
perform_prompt_complete (res, TRUE);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_atomic_int_inc (&self->pv->prompted);
|
||||||
|
|
||||||
|
/* And now we wait for the signal */
|
||||||
|
closure->prompting = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_prompt_vanished (GDBusConnection *connection,
|
||||||
|
const gchar *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
PerformClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
closure->vanished = TRUE;
|
||||||
|
g_cancellable_cancel (closure->call_cancellable);
|
||||||
|
perform_prompt_complete (res, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_prompt_dismissed (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
PerformClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GSecretPrompt *self = GSECRET_PROMPT (source);
|
||||||
|
GError *error = NULL;
|
||||||
|
GVariant *retval;
|
||||||
|
|
||||||
|
retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, &error);
|
||||||
|
|
||||||
|
if (retval)
|
||||||
|
g_variant_unref (retval);
|
||||||
|
if (closure->vanished)
|
||||||
|
g_clear_error (&error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
perform_prompt_complete (res, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_prompt_cancelled (GCancellable *cancellable,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
PerformClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GSecretPrompt *self = GSECRET_PROMPT (g_async_result_get_source_object (user_data));
|
||||||
|
|
||||||
|
/* Instead of cancelling our dbus calls, we cancel the prompt itself via this dbus call */
|
||||||
|
|
||||||
|
g_dbus_proxy_call (G_DBUS_PROXY (self), "Dismiss", g_variant_new ("()"),
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
||||||
|
closure->call_cancellable,
|
||||||
|
on_prompt_dismissed, g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_prompt_perform (GSecretPrompt *self,
|
||||||
|
gulong window_id,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
PerformClosure *closure;
|
||||||
|
const gchar *owner_name;
|
||||||
|
const gchar *object_path;
|
||||||
|
GDBusProxy *proxy;
|
||||||
|
gchar *window;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_IS_PROMPT (self));
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
if (g_atomic_int_get (&self->pv->prompted)) {
|
||||||
|
g_warning ("The prompt object has already had its prompt called.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy = G_DBUS_PROXY (self);
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
gsecret_prompt_perform);
|
||||||
|
closure = g_slice_new0 (PerformClosure);
|
||||||
|
closure->connection = g_object_ref (g_dbus_proxy_get_connection (proxy));
|
||||||
|
closure->call_cancellable = g_cancellable_new ();
|
||||||
|
closure->async_cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, closure, perform_closure_free);
|
||||||
|
|
||||||
|
if (window_id == 0)
|
||||||
|
window = g_strdup ("");
|
||||||
|
else
|
||||||
|
window = g_strdup_printf ("%lu", window_id);
|
||||||
|
|
||||||
|
owner_name = g_dbus_proxy_get_name_owner (proxy);
|
||||||
|
object_path = g_dbus_proxy_get_object_path (proxy);
|
||||||
|
|
||||||
|
closure->signal = g_dbus_connection_signal_subscribe (closure->connection, owner_name,
|
||||||
|
GSECRET_PROMPT_INTERFACE,
|
||||||
|
GSECRET_PROMPT_SIGNAL_COMPLETED,
|
||||||
|
object_path, NULL,
|
||||||
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||||
|
on_prompt_completed,
|
||||||
|
g_object_ref (res),
|
||||||
|
g_object_unref);
|
||||||
|
|
||||||
|
closure->watch = g_bus_watch_name_on_connection (closure->connection, owner_name,
|
||||||
|
G_BUS_NAME_WATCHER_FLAGS_NONE, NULL,
|
||||||
|
on_prompt_vanished,
|
||||||
|
g_object_ref (res),
|
||||||
|
g_object_unref);
|
||||||
|
|
||||||
|
if (closure->async_cancellable) {
|
||||||
|
closure->cancelled_sig = g_cancellable_connect (closure->async_cancellable,
|
||||||
|
G_CALLBACK (on_prompt_cancelled),
|
||||||
|
res, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dbus_proxy_call (proxy, "Prompt", g_variant_new ("(s)", window),
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
||||||
|
closure->call_cancellable, on_prompt_prompted, g_object_ref (res));
|
||||||
|
|
||||||
|
g_free (window);
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_prompt_perform_finish (GSecretPrompt *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
PerformClosure *closure;
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_PROMPT (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_prompt_perform), 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->dismissed;
|
||||||
|
}
|
||||||
|
|
||||||
|
GVariant *
|
||||||
|
gsecret_prompt_get_result_value (GSecretPrompt *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSECRET_IS_PROMPT (self), NULL);
|
||||||
|
|
||||||
|
if (self->pv->last_result)
|
||||||
|
return g_variant_ref (self->pv->last_result);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gsecret-types.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GSECRET_TYPE_PROMPT (gsecret_prompt_get_type ())
|
#define GSECRET_TYPE_PROMPT (gsecret_prompt_get_type ())
|
||||||
@ -24,13 +26,13 @@ G_BEGIN_DECLS
|
|||||||
#define GSECRET_IS_PROMPT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_PROMPT))
|
#define GSECRET_IS_PROMPT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_PROMPT))
|
||||||
#define GSECRET_PROMPT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_PROMPT, GSecretPromptClass))
|
#define GSECRET_PROMPT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_PROMPT, GSecretPromptClass))
|
||||||
|
|
||||||
typedef struct _GSecretPrompt GSecretPrompt;
|
|
||||||
typedef struct _GSecretPromptClass GSecretPromptClass;
|
typedef struct _GSecretPromptClass GSecretPromptClass;
|
||||||
typedef struct _GSecretPromptPrivate GSecretPromptPrivate;
|
typedef struct _GSecretPromptPrivate GSecretPromptPrivate;
|
||||||
|
|
||||||
struct _GSecretPromptClass {
|
struct _GSecretPromptClass {
|
||||||
GDBusProxyClass parent_class;
|
GDBusProxyClass parent_class;
|
||||||
padding;
|
|
||||||
|
gpointer padding[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GSecretPrompt {
|
struct _GSecretPrompt {
|
||||||
@ -38,19 +40,32 @@ struct _GSecretPrompt {
|
|||||||
GSecretPromptPrivate *pv;
|
GSecretPromptPrivate *pv;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gsecret_service_get_type (void) G_GNUC_CONST;
|
GType gsecret_prompt_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
GSecretService* gsecret_collection_xxx_new (void);
|
GSecretPrompt * gsecret_prompt_instance (GSecretService *service,
|
||||||
|
const gchar *prompt_path);
|
||||||
|
|
||||||
GSecretPrompt* gsecret_prompt_instance (GDBusConnection *connection,
|
gboolean gsecret_prompt_run (GSecretPrompt *self,
|
||||||
const gchar *object_path,
|
gulong window_id,
|
||||||
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
GSecretPrompt* gsecret_prompt_instance_sync (GDBusConnection *connection,
|
gboolean gsecret_prompt_perform_sync (GSecretPrompt *self,
|
||||||
const gchar *object_path);
|
gulong window_id,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
gsecret_prompt_perform
|
void gsecret_prompt_perform (GSecretPrompt *self,
|
||||||
gsecret_prompt_dismiss
|
gulong window_id,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean gsecret_prompt_perform_finish (GSecretPrompt *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GVariant * gsecret_prompt_get_result_value (GSecretPrompt *self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "gsecret-dbus-generated.h"
|
#include "gsecret-dbus-generated.h"
|
||||||
|
#include "gsecret-item.h"
|
||||||
#include "gsecret-private.h"
|
#include "gsecret-private.h"
|
||||||
#include "gsecret-service.h"
|
#include "gsecret-service.h"
|
||||||
#include "gsecret-types.h"
|
#include "gsecret-types.h"
|
||||||
@ -36,6 +37,8 @@ EGG_SECURE_GLIB_DEFINITIONS ();
|
|||||||
|
|
||||||
EGG_SECURE_DECLARE (secret_service);
|
EGG_SECURE_DECLARE (secret_service);
|
||||||
|
|
||||||
|
static const gchar *default_bus_name = GSECRET_SERVICE_BUS_NAME;
|
||||||
|
|
||||||
#define ALGORITHMS_AES "dh-ietf1024-sha256-aes128-cbc-pkcs7"
|
#define ALGORITHMS_AES "dh-ietf1024-sha256-aes128-cbc-pkcs7"
|
||||||
#define ALGORITHMS_PLAIN "plain"
|
#define ALGORITHMS_PLAIN "plain"
|
||||||
|
|
||||||
@ -60,6 +63,45 @@ static gpointer service_instance = NULL;
|
|||||||
|
|
||||||
G_DEFINE_TYPE (GSecretService, gsecret_service, G_TYPE_DBUS_PROXY);
|
G_DEFINE_TYPE (GSecretService, gsecret_service, G_TYPE_DBUS_PROXY);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsecret_session_free (gpointer data)
|
gsecret_session_free (gpointer data)
|
||||||
{
|
{
|
||||||
@ -95,6 +137,65 @@ gsecret_service_finalize (GObject *obj)
|
|||||||
G_OBJECT_CLASS (gsecret_service_parent_class)->finalize (obj);
|
G_OBJECT_CLASS (gsecret_service_parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsecret_service_real_prompt_sync (GSecretService *self,
|
||||||
|
GSecretPrompt *prompt,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return gsecret_prompt_perform_sync (prompt, 0, cancellable, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_real_prompt_completed (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_finish (GSECRET_PROMPT (source), result, &error);
|
||||||
|
g_simple_async_result_set_op_res_gboolean (res, ret);
|
||||||
|
if (error != NULL)
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsecret_service_real_prompt_async (GSecretService *self,
|
||||||
|
GSecretPrompt *prompt,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
gsecret_service_real_prompt_async);
|
||||||
|
|
||||||
|
gsecret_prompt_perform (prompt, 0, cancellable,
|
||||||
|
on_real_prompt_completed,
|
||||||
|
g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsecret_service_real_prompt_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
|
||||||
|
if (g_simple_async_result_propagate_error (res, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return g_simple_async_result_get_op_res_gboolean (res);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsecret_service_class_init (GSecretServiceClass *klass)
|
gsecret_service_class_init (GSecretServiceClass *klass)
|
||||||
{
|
{
|
||||||
@ -102,9 +203,20 @@ gsecret_service_class_init (GSecretServiceClass *klass)
|
|||||||
|
|
||||||
object_class->finalize = gsecret_service_finalize;
|
object_class->finalize = gsecret_service_finalize;
|
||||||
|
|
||||||
|
klass->prompt_sync = gsecret_service_real_prompt_sync;
|
||||||
|
klass->prompt_async = gsecret_service_real_prompt_async;
|
||||||
|
klass->prompt_finish = gsecret_service_real_prompt_finish;
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GSecretServicePrivate));
|
g_type_class_add_private (klass, sizeof (GSecretServicePrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gsecret_service_set_default_bus_name (const gchar *bus_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (bus_name != NULL);
|
||||||
|
default_bus_name = bus_name;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_service_instance_gone (gpointer user_data,
|
on_service_instance_gone (gpointer user_data,
|
||||||
GObject *where_the_object_was)
|
GObject *where_the_object_was)
|
||||||
@ -138,7 +250,7 @@ _gsecret_service_bare_instance (GDBusConnection *connection,
|
|||||||
|
|
||||||
/* Alternate bus name is only used for testing */
|
/* Alternate bus name is only used for testing */
|
||||||
if (bus_name == NULL)
|
if (bus_name == NULL)
|
||||||
bus_name = GSECRET_SERVICE_BUS_NAME;
|
bus_name = default_bus_name;
|
||||||
|
|
||||||
service = g_initable_new (GSECRET_TYPE_SERVICE, NULL, &error,
|
service = g_initable_new (GSECRET_TYPE_SERVICE, NULL, &error,
|
||||||
"g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
"g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||||
@ -172,6 +284,115 @@ _gsecret_service_bare_instance (GDBusConnection *connection,
|
|||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GSecretService *service;
|
||||||
|
gboolean ensure_session;
|
||||||
|
gchar *bus_name;
|
||||||
|
} ConnectClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
connect_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
ConnectClosure *closure = data;
|
||||||
|
g_clear_object (&closure->cancellable);
|
||||||
|
g_clear_object (&closure->service);
|
||||||
|
g_slice_free (ConnectClosure, closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_connect_ensure (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
gsecret_service_ensure_session_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_connect_bus (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
ConnectClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
connection = g_bus_get_finish (result, &error);
|
||||||
|
if (error == NULL) {
|
||||||
|
closure->service = _gsecret_service_bare_instance (connection, closure->bus_name);
|
||||||
|
if (closure->ensure_session)
|
||||||
|
gsecret_service_ensure_session (closure->service, closure->cancellable,
|
||||||
|
on_connect_ensure, g_object_ref (res));
|
||||||
|
|
||||||
|
else
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
|
||||||
|
g_object_unref (connection);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gsecret_service_bare_connect (const gchar *bus_name,
|
||||||
|
gboolean ensure_session,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
ConnectClosure *closure;
|
||||||
|
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
if (bus_name == NULL)
|
||||||
|
bus_name = default_bus_name;
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (NULL, callback, user_data,
|
||||||
|
_gsecret_service_bare_connect);
|
||||||
|
closure = g_slice_new0 (ConnectClosure);
|
||||||
|
closure->bus_name = g_strdup (bus_name);
|
||||||
|
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
|
closure->ensure_session = ensure_session;
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, closure, connect_closure_free);
|
||||||
|
|
||||||
|
g_bus_get (G_BUS_TYPE_SESSION, cancellable, on_connect_bus, g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSecretService *
|
||||||
|
_gsecret_service_bare_connect_finish (GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ConnectClosure *closure;
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
|
||||||
|
_gsecret_service_bare_connect), NULL);
|
||||||
|
|
||||||
|
res = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
if (g_simple_async_result_propagate_error (res, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
return g_object_ref (closure->service);
|
||||||
|
}
|
||||||
|
|
||||||
const gchar *
|
const gchar *
|
||||||
gsecret_service_get_session_algorithms (GSecretService *self)
|
gsecret_service_get_session_algorithms (GSecretService *self)
|
||||||
{
|
{
|
||||||
@ -1271,3 +1492,490 @@ gsecret_service_get_secrets_for_paths_sync (GSecretService *self,
|
|||||||
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_service_prompt_sync (GSecretService *self,
|
||||||
|
GSecretPrompt *prompt,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSecretServiceClass *klass;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE);
|
||||||
|
g_return_val_if_fail (GSECRET_IS_PROMPT (prompt), FALSE);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
klass = GSECRET_SERVICE_GET_CLASS (self);
|
||||||
|
g_return_val_if_fail (klass->prompt_sync != NULL, FALSE);
|
||||||
|
|
||||||
|
return (klass->prompt_sync) (self, prompt, cancellable, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_prompt_path (GSecretService *self,
|
||||||
|
const gchar *prompt_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
||||||
|
g_return_if_fail (prompt_path != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (self, prompt_path);
|
||||||
|
|
||||||
|
gsecret_service_prompt (self, prompt, cancellable, callback, user_data);
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_prompt (GSecretService *self,
|
||||||
|
GSecretPrompt *prompt,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSecretServiceClass *klass;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
||||||
|
g_return_if_fail (GSECRET_IS_PROMPT (prompt));
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
klass = GSECRET_SERVICE_GET_CLASS (self);
|
||||||
|
g_return_if_fail (klass->prompt_async != NULL);
|
||||||
|
|
||||||
|
(klass->prompt_async) (self, prompt, cancellable, callback, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_service_prompt_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSecretServiceClass *klass;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE);
|
||||||
|
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
klass = GSECRET_SERVICE_GET_CLASS (self);
|
||||||
|
g_return_val_if_fail (klass->prompt_finish != NULL, FALSE);
|
||||||
|
|
||||||
|
return (klass->prompt_finish) (self, result, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_store_password (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
const gchar *collection_path,
|
||||||
|
const gchar *label,
|
||||||
|
const gchar *password,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_service_store_password_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_store_password_sync (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
const gchar *collection,
|
||||||
|
const gchar *display_name,
|
||||||
|
const gchar *password,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_lookup_password (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *
|
||||||
|
gsecret_service_lookup_password_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *
|
||||||
|
gsecret_service_lookup_password_sync (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GCancellable *cancellable;
|
||||||
|
gboolean deleted;
|
||||||
|
} DeleteClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
delete_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
DeleteClosure *closure = data;
|
||||||
|
g_clear_object (&closure->cancellable);
|
||||||
|
g_slice_free (DeleteClosure, closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_delete_prompted (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;
|
||||||
|
|
||||||
|
gsecret_service_prompt_finish (GSECRET_SERVICE (source), result, &error);
|
||||||
|
|
||||||
|
if (error == NULL)
|
||||||
|
closure->deleted = TRUE;
|
||||||
|
else
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
GSecretService *self = GSECRET_SERVICE (g_async_result_get_source_object (user_data));
|
||||||
|
const gchar *prompt_path;
|
||||||
|
GError *error = NULL;
|
||||||
|
GVariant *retval;
|
||||||
|
|
||||||
|
retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
|
||||||
|
if (error == NULL) {
|
||||||
|
g_variant_get (retval, "(&o)", &prompt_path);
|
||||||
|
|
||||||
|
if (_gsecret_util_empty_path (prompt_path)) {
|
||||||
|
closure->deleted = TRUE;
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
gsecret_service_prompt_path (self, prompt_path,
|
||||||
|
closure->cancellable,
|
||||||
|
on_delete_prompted,
|
||||||
|
g_object_ref (res));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_unref (retval);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (self);
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_delete_path (GSecretService *self,
|
||||||
|
const gchar *item_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
DeleteClosure *closure;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
||||||
|
g_return_if_fail (item_path != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
gsecret_service_delete_path);
|
||||||
|
closure = g_slice_new0 (DeleteClosure);
|
||||||
|
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free);
|
||||||
|
|
||||||
|
g_dbus_connection_call (g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
|
||||||
|
g_dbus_proxy_get_name (G_DBUS_PROXY (self)),
|
||||||
|
item_path, GSECRET_ITEM_INTERFACE,
|
||||||
|
"Delete", g_variant_new ("()"), G_VARIANT_TYPE ("(o)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
||||||
|
cancellable, on_delete_complete, g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_service_delete_path_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
DeleteClosure *closure;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (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_service_delete_path), 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_service_delete_path_sync (GSecretService *self,
|
||||||
|
const gchar *item_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
SyncClosure *closure;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE);
|
||||||
|
g_return_val_if_fail (item_path != 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 ();
|
||||||
|
g_main_context_push_thread_default (closure->context);
|
||||||
|
|
||||||
|
gsecret_service_delete_path (self, item_path, cancellable, on_sync_result, closure);
|
||||||
|
|
||||||
|
g_main_loop_run (closure->loop);
|
||||||
|
|
||||||
|
result = gsecret_service_delete_path_finish (self, closure->result, error);
|
||||||
|
|
||||||
|
g_main_context_pop_thread_default (closure->context);
|
||||||
|
sync_closure_free (closure);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_delete_password_complete (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
GSecretService *self = GSECRET_SERVICE (g_async_result_get_source_object (user_data));
|
||||||
|
DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
closure->deleted = gsecret_service_delete_path_finish (self, result, &error);
|
||||||
|
if (error != NULL)
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
|
||||||
|
g_object_unref (self);
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_search_delete_password (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 *self = GSECRET_SERVICE (g_async_result_get_source_object (user_data));
|
||||||
|
const gchar *path = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar **locked;
|
||||||
|
gchar **unlocked;
|
||||||
|
|
||||||
|
gsecret_service_search_for_paths_finish (self, result, &unlocked, &locked, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Choose the first path */
|
||||||
|
if (unlocked && unlocked[0])
|
||||||
|
path = unlocked[0];
|
||||||
|
else if (locked && locked[0])
|
||||||
|
path = locked[0];
|
||||||
|
|
||||||
|
/* Nothing to delete? */
|
||||||
|
if (path == NULL) {
|
||||||
|
closure->deleted = FALSE;
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
|
||||||
|
/* Delete the first path */
|
||||||
|
} else {
|
||||||
|
closure->deleted = TRUE;
|
||||||
|
gsecret_service_delete_path (self, path,
|
||||||
|
closure->cancellable,
|
||||||
|
on_delete_password_complete,
|
||||||
|
g_object_ref (res));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (locked);
|
||||||
|
g_strfreev (unlocked);
|
||||||
|
g_object_unref (self);
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_delete_password (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
GHashTable *attributes;
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_SERVICE (self));
|
||||||
|
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_service_delete_passwordv (self, attributes, cancellable,
|
||||||
|
callback, user_data);
|
||||||
|
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_delete_passwordv (GSecretService *self,
|
||||||
|
GHashTable *attributes,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
DeleteClosure *closure;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_SERVICE (self));
|
||||||
|
g_return_if_fail (attributes != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
gsecret_service_delete_password);
|
||||||
|
closure = g_slice_new0 (DeleteClosure);
|
||||||
|
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free);
|
||||||
|
|
||||||
|
gsecret_service_search_for_paths (self, attributes, cancellable,
|
||||||
|
on_search_delete_password, g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_service_delete_password_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
DeleteClosure *closure;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (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_service_delete_password), 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_service_delete_password_sync (GSecretService *self,
|
||||||
|
const GSecretSchema* schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
GHashTable *attributes;
|
||||||
|
gboolean result;
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), 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_service_delete_passwordv_sync (self, attributes, cancellable, error);
|
||||||
|
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsecret_service_delete_passwordv_sync (GSecretService *self,
|
||||||
|
GHashTable *attributes,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
SyncClosure *closure;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), 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 ();
|
||||||
|
g_main_context_push_thread_default (closure->context);
|
||||||
|
|
||||||
|
gsecret_service_delete_passwordv (self, attributes, cancellable,
|
||||||
|
on_sync_result, closure);
|
||||||
|
|
||||||
|
g_main_loop_run (closure->loop);
|
||||||
|
|
||||||
|
result = gsecret_service_delete_password_finish (self, closure->result, error);
|
||||||
|
|
||||||
|
g_main_context_pop_thread_default (closure->context);
|
||||||
|
sync_closure_free (closure);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gsecret-prompt.h"
|
||||||
|
#include "gsecret-types.h"
|
||||||
#include "gsecret-value.h"
|
#include "gsecret-value.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@ -26,19 +28,26 @@ G_BEGIN_DECLS
|
|||||||
#define GSECRET_IS_SERVICE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_SERVICE))
|
#define GSECRET_IS_SERVICE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_SERVICE))
|
||||||
#define GSECRET_SERVICE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_SERVICE, GSecretServiceClass))
|
#define GSECRET_SERVICE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_SERVICE, GSecretServiceClass))
|
||||||
|
|
||||||
typedef struct _GSecretService GSecretService;
|
|
||||||
typedef struct _GSecretServiceClass GSecretServiceClass;
|
typedef struct _GSecretServiceClass GSecretServiceClass;
|
||||||
typedef struct _GSecretServicePrivate GSecretServicePrivate;
|
typedef struct _GSecretServicePrivate GSecretServicePrivate;
|
||||||
|
|
||||||
struct _GSecretServiceClass {
|
struct _GSecretServiceClass {
|
||||||
GDBusProxyClass parent_class;
|
GDBusProxyClass parent_class;
|
||||||
|
|
||||||
GType collection_type;
|
gboolean (*prompt_sync) (GSecretService *self,
|
||||||
GType item_type;
|
GSecretPrompt *prompt,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
#if 0
|
void (*prompt_async) (GSecretService *self,
|
||||||
padding;
|
GSecretPrompt *prompt,
|
||||||
#endif
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean (*prompt_finish) (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GSecretService {
|
struct _GSecretService {
|
||||||
@ -186,34 +195,132 @@ void gsecret_service_unlock (GSecretService *se
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
gboolean gsecret_service_
|
gint gsecret_service_unlock_paths_sync (GSecretService *self,
|
||||||
GList **unlocked,
|
const gchar **paths,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
gchar ***unlocked,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gsecret_service_unlock_paths (GSecretService *self,
|
||||||
|
const gchar **paths,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gint gsecret_service_unlock_paths_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gchar ***unlocked,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gsecret_service_prompt_sync (GSecretService *self,
|
||||||
GSecretPrompt *prompt,
|
GSecretPrompt *prompt,
|
||||||
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean gsecret_service_unlock (GSecretService *self,
|
void gsecret_service_prompt (GSecretService *self,
|
||||||
GList *objects,
|
|
||||||
GList **unlocked,
|
|
||||||
GSecretPrompt *prompt,
|
GSecretPrompt *prompt,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
void gsecret_service_prompt_path (GSecretService *self,
|
||||||
|
const gchar *prompt_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean gsecret_service_prompt_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean gsecret_service_unlock_for_paths (GSecretService *self,
|
#if 0
|
||||||
GList *objects,
|
void gsecret_service_store_password (GSecretService *self,
|
||||||
GList **unlocked,
|
const GSecretSchema *schema,
|
||||||
GSecretPrompt *prompt,
|
const gchar *collection_path,
|
||||||
|
const gchar *label,
|
||||||
|
const gchar *password,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
gboolean gsecret_service_store_password_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
GHashTable* gsecret_service_get_secrets (GList *items,
|
void gsecret_service_store_password_sync (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
const gchar *collection,
|
||||||
|
const gchar *display_name,
|
||||||
|
const gchar *password,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
void gsecret_service_lookup_password (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
gchar * gsecret_service_lookup_password_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
GHashTable* gsecret_service_get_secrets_for_paths (GList *items,
|
gchar * gsecret_service_lookup_password_sync (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void gsecret_service_delete_path (GSecretService *self,
|
||||||
|
const gchar *item_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean gsecret_service_delete_path_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gsecret_collection_create_collection
|
gboolean gsecret_service_delete_path_sync (GSecretService *self,
|
||||||
|
const gchar *item_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
GList* gsecret_service_get_collections
|
void gsecret_service_delete_password (GSecretService *self,
|
||||||
|
const GSecretSchema *schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
void gsecret_service_delete_passwordv (GSecretService *self,
|
||||||
|
GHashTable *attributes,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean gsecret_service_delete_password_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gsecret_service_delete_password_sync (GSecretService *self,
|
||||||
|
const GSecretSchema* schema,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
gboolean gsecret_service_delete_passwordv_sync (GSecretService *self,
|
||||||
|
GHashTable *attributes,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
#if 0
|
||||||
GSecretCollection* gsecret_service_read_alias (GSecretService *self,
|
GSecretCollection* gsecret_service_read_alias (GSecretService *self,
|
||||||
const gchar *alias,
|
const gchar *alias,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
@ -25,6 +25,36 @@ typedef enum {
|
|||||||
GSECRET_ERROR_PROTOCOL = 1,
|
GSECRET_ERROR_PROTOCOL = 1,
|
||||||
} GSecretError;
|
} GSecretError;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSECRET_ATTRIBUTE_BOOLEAN,
|
||||||
|
GSECRET_ATTRIBUTE_STRING,
|
||||||
|
GSECRET_ATTRIBUTE_INTEGER
|
||||||
|
} GSecretSchemaType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const gchar *schema_name;
|
||||||
|
struct {
|
||||||
|
const gchar* name;
|
||||||
|
GSecretSchemaType type;
|
||||||
|
} attributes[32];
|
||||||
|
|
||||||
|
/* <private> */
|
||||||
|
gpointer reserved1;
|
||||||
|
gpointer reserved2;
|
||||||
|
gpointer reserved3;
|
||||||
|
gpointer reserved4;
|
||||||
|
gpointer reserved5;
|
||||||
|
gpointer reserved6;
|
||||||
|
gpointer reserved7;
|
||||||
|
gpointer reserved8;
|
||||||
|
} GSecretSchema;
|
||||||
|
|
||||||
|
typedef struct _GSecretCollection GSecretCollection;
|
||||||
|
typedef struct _GSecretItem GSecretItem;
|
||||||
|
typedef struct _GSecretPrompt GSecretPrompt;
|
||||||
|
typedef struct _GSecretService GSecretService;
|
||||||
|
typedef struct _GSecretValue GSecretValue;
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_SERVICE_H___ */
|
#endif /* __G_SERVICE_H___ */
|
||||||
|
@ -72,6 +72,13 @@ _gsecret_util_parent_path (const gchar *path)
|
|||||||
return g_strndup (path, pos - path);
|
return g_strndup (path, pos - path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_gsecret_util_empty_path (const gchar *path)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (path != NULL, TRUE);
|
||||||
|
return (g_str_equal (path, "") || g_str_equal (path, "/"));
|
||||||
|
}
|
||||||
|
|
||||||
GVariant *
|
GVariant *
|
||||||
_gsecret_util_variant_for_attributes (GHashTable *attributes)
|
_gsecret_util_variant_for_attributes (GHashTable *attributes)
|
||||||
{
|
{
|
||||||
@ -91,3 +98,71 @@ _gsecret_util_variant_for_attributes (GHashTable *attributes)
|
|||||||
return g_variant_builder_end (&builder);
|
return g_variant_builder_end (&builder);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GHashTable *
|
||||||
|
_gsecret_util_attributes_for_varargs (const GSecretSchema *schema,
|
||||||
|
va_list args)
|
||||||
|
{
|
||||||
|
const gchar *attribute_name;
|
||||||
|
GSecretSchemaType type;
|
||||||
|
GHashTable *attributes;
|
||||||
|
const gchar *string;
|
||||||
|
gboolean type_found;
|
||||||
|
gchar *value = NULL;
|
||||||
|
gboolean boolean;
|
||||||
|
gint integer;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
attribute_name = va_arg (args, const gchar *);
|
||||||
|
if (attribute_name == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
type_found = FALSE;
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (schema->attributes); ++i) {
|
||||||
|
if (!schema->attributes[i].name)
|
||||||
|
break;
|
||||||
|
if (g_str_equal (schema->attributes[i].name, attribute_name)) {
|
||||||
|
type_found = TRUE;
|
||||||
|
type = schema->attributes[i].type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type_found) {
|
||||||
|
g_warning ("The attribute '%s' was not found in the password schema.", attribute_name);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case GSECRET_ATTRIBUTE_BOOLEAN:
|
||||||
|
boolean = va_arg (args, gboolean);
|
||||||
|
value = g_strdup (boolean ? "true" : "false");
|
||||||
|
break;
|
||||||
|
case GSECRET_ATTRIBUTE_STRING:
|
||||||
|
string = va_arg (args, gchar *);
|
||||||
|
if (!g_utf8_validate (string, -1, NULL)) {
|
||||||
|
g_warning ("The value for attribute '%s' was not a valid utf-8 string.", attribute_name);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
value = g_strdup (string);
|
||||||
|
break;
|
||||||
|
case GSECRET_ATTRIBUTE_INTEGER:
|
||||||
|
integer = va_arg (args, gint);
|
||||||
|
value = g_strdup_printf ("%d", integer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_warning ("The password attribute '%s' has an invalid type in the password schema.", attribute_name);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_insert (attributes, g_strdup (attribute_name), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gsecret-types.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GSECRET_TYPE_VALUE (gsecret_service_get_type ())
|
#define GSECRET_TYPE_VALUE (gsecret_service_get_type ())
|
||||||
|
|
||||||
typedef struct _GSecretValue GSecretValue;
|
|
||||||
|
|
||||||
GType gsecret_value_get_type (void) G_GNUC_CONST;
|
GType gsecret_value_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
GSecretValue* gsecret_value_new (const gchar *secret,
|
GSecretValue* gsecret_value_new (const gchar *secret,
|
||||||
|
@ -68,109 +68,93 @@
|
|||||||
|
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<node name="/org/freedesktop/Secrets/collection/xxxx">
|
<interface name="org.freedesktop.Secret.Collection">
|
||||||
|
|
||||||
<interface name="org.freedesktop.Secret.Collection">
|
<property name="Items" type="ao" access="read"/>
|
||||||
|
<property name="Label" type="s" access="readwrite"/>
|
||||||
|
<property name="Locked" type="b" access="read"/>
|
||||||
|
<property name="Created" type="t" access="read"/>
|
||||||
|
<property name="Modified" type="t" access="read"/>
|
||||||
|
|
||||||
<property name="Items" type="ao" access="read"/>
|
<method name="Delete">
|
||||||
<property name="Label" type="s" access="readwrite"/>
|
<arg name="prompt" type="o" direction="out"/>
|
||||||
<property name="Locked" type="b" access="read"/>
|
</method>
|
||||||
<property name="Created" type="t" access="read"/>
|
|
||||||
<property name="Modified" type="t" access="read"/>
|
|
||||||
|
|
||||||
<method name="Delete">
|
<method name="SearchItems">
|
||||||
<arg name="prompt" type="o" direction="out"/>
|
<arg name="attributes" type="a{ss}" direction="in"/>
|
||||||
</method>
|
<arg name="results" type="ao" direction="out"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="SearchItems">
|
<method name="CreateItem">
|
||||||
<arg name="attributes" type="a{ss}" direction="in"/>
|
<arg name="properties" type="a{sv}" direction="in"/>
|
||||||
<arg name="results" type="ao" direction="out"/>
|
<arg name="secret" type="(oayays)" direction="in"/>
|
||||||
</method>
|
<arg name="replace" type="b" direction="in"/>
|
||||||
|
<arg name="item" type="o" direction="out"/>
|
||||||
|
<arg name="prompt" type="o" direction="out"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="CreateItem">
|
<signal name="ItemCreated">
|
||||||
<arg name="properties" type="a{sv}" direction="in"/>
|
<arg name="item" type="o"/>
|
||||||
<arg name="secret" type="(oayays)" direction="in"/>
|
</signal>
|
||||||
<arg name="replace" type="b" direction="in"/>
|
|
||||||
<arg name="item" type="o" direction="out"/>
|
|
||||||
<arg name="prompt" type="o" direction="out"/>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<signal name="ItemCreated">
|
<signal name="ItemDeleted">
|
||||||
<arg name="item" type="o"/>
|
<arg name="item" type="o"/>
|
||||||
</signal>
|
</signal>
|
||||||
|
|
||||||
<signal name="ItemDeleted">
|
<signal name="ItemChanged">
|
||||||
<arg name="item" type="o"/>
|
<arg name="item" type="o"/>
|
||||||
</signal>
|
</signal>
|
||||||
|
|
||||||
<signal name="ItemChanged">
|
</interface>
|
||||||
<arg name="item" type="o"/>
|
|
||||||
</signal>
|
|
||||||
|
|
||||||
</interface>
|
<interface name="org.freedesktop.Secret.Item">
|
||||||
|
|
||||||
<node name="/org/freedesktop/Secret/collection/xxxx/iiii">
|
<property name="Locked" type="b" access="read"/>
|
||||||
|
|
||||||
<interface name="org.freedesktop.Secret.Item">
|
<property name="Attributes" type="a{ss}" access="readwrite"/>
|
||||||
|
|
||||||
<property name="Locked" type="b" access="read"/>
|
<property name="Label" type="s" access="readwrite"/>
|
||||||
|
|
||||||
<property name="Attributes" type="a{ss}" access="readwrite"/>
|
<property name="Created" type="t" access="read"/>
|
||||||
|
|
||||||
<property name="Label" type="s" access="readwrite"/>
|
<property name="Modified" type="t" access="read"/>
|
||||||
|
|
||||||
<property name="Created" type="t" access="read"/>
|
<method name="Delete">
|
||||||
|
<arg name="Prompt" type="o" direction="out"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
<property name="Modified" type="t" access="read"/>
|
<method name="GetSecret">
|
||||||
|
<arg name="session" type="o" direction="in"/>
|
||||||
|
<arg name="secret" type="(oayays)" direction="out"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="Delete">
|
<method name="SetSecret">
|
||||||
<arg name="Prompt" type="o" direction="out"/>
|
<arg name="secret" type="(oayays)" direction="in"/>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<method name="GetSecret">
|
</interface>
|
||||||
<arg name="session" type="o" direction="in"/>
|
|
||||||
<arg name="secret" type="(oayays)" direction="out"/>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="SetSecret">
|
|
||||||
<arg name="secret" type="(oayays)" direction="in"/>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
</interface>
|
<interface name="org.freedesktop.Secret.Session">
|
||||||
|
|
||||||
</node>
|
<method name="Close">
|
||||||
|
</method>
|
||||||
|
|
||||||
</node>
|
</interface>
|
||||||
|
|
||||||
<node name="/org/freedesktop/Secret/session/ssss">
|
<interface name="org.freedesktop.Secret.Prompt">
|
||||||
|
|
||||||
<interface name="org.freedesktop.Secret.Session">
|
<method name="Prompt">
|
||||||
|
<arg name="window_id" type="s" direction="in"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="Close">
|
<method name="Dismiss">
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
</node>
|
|
||||||
|
|
||||||
<node name="/org/freedesktop/Secret/prompts/pppp">
|
|
||||||
|
|
||||||
<interface name="org.freedesktop.Secret.Prompt">
|
|
||||||
|
|
||||||
<method name="Prompt">
|
|
||||||
<arg name="window-id" type="s" direction="in"/>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="Dismiss">
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<signal name="Completed">
|
|
||||||
<arg name="dismissed" type="b"/>
|
|
||||||
<arg name="result" type="v"/>
|
|
||||||
</signal>
|
|
||||||
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
</node>
|
|
||||||
|
|
||||||
|
<signal name="Completed">
|
||||||
|
<arg name="dismissed" type="b"/>
|
||||||
|
<arg name="result" type="v"/>
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
s
|
||||||
</node>
|
</node>
|
||||||
|
@ -11,8 +11,10 @@ LDADD = \
|
|||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
TEST_PROGS = \
|
TEST_PROGS = \
|
||||||
|
test-prompt \
|
||||||
test-service \
|
test-service \
|
||||||
test-session \
|
test-session \
|
||||||
|
test-password \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
check_PROGRAMS = \
|
check_PROGRAMS = \
|
||||||
|
17
library/tests/mock-service-delete.py
Normal file
17
library/tests/mock-service-delete.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import dbus
|
||||||
|
import mock
|
||||||
|
import sys
|
||||||
|
|
||||||
|
service = mock.SecretService()
|
||||||
|
service.add_standard_objects()
|
||||||
|
|
||||||
|
collection = mock.SecretCollection(service, "to_delete", locked=False)
|
||||||
|
mock.SecretItem(collection, "item", attributes={ "number": "1", "string": "one", "even": "false" }, secret="uno")
|
||||||
|
mock.SecretItem(collection, "confirm", attributes={ "number": "2", "string": "two", "even": "true" }, secret="dos", confirm=True)
|
||||||
|
|
||||||
|
collection = mock.SecretCollection(service, "two_delete", locked=True)
|
||||||
|
mock.SecretItem(collection, "locked", attributes={ "number": "3", "string": "three", "even": "false" }, secret="tres")
|
||||||
|
|
||||||
|
service.listen()
|
42
library/tests/mock-service-prompt.py
Normal file
42
library/tests/mock-service-prompt.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import dbus
|
||||||
|
import mock
|
||||||
|
import sys
|
||||||
|
|
||||||
|
class ErrorPrompt(mock.SecretPrompt):
|
||||||
|
def __init__(self, service, sender, prompt_name):
|
||||||
|
mock.SecretPrompt.__init__(self, service, sender, prompt_name)
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Prompt')
|
||||||
|
def Prompt(self, window_id):
|
||||||
|
raise mock.NotSupported("This should cause prompting to fail")
|
||||||
|
|
||||||
|
class VanishPrompt(mock.SecretPrompt):
|
||||||
|
def __init__(self, service, sender, prompt_name):
|
||||||
|
mock.SecretPrompt.__init__(self, service, sender, prompt_name)
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Prompt')
|
||||||
|
def Prompt(self, window_id):
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
class WindowPrompt(mock.SecretPrompt):
|
||||||
|
def __init__(self, service, sender, prompt_name):
|
||||||
|
mock.SecretPrompt.__init__(self, service, sender, prompt_name)
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Prompt')
|
||||||
|
def Prompt(self, window_id):
|
||||||
|
self.result = dbus.String(window_id, variant_level=1)
|
||||||
|
mock.SecretPrompt.Prompt(self, window_id)
|
||||||
|
|
||||||
|
service = mock.SecretService()
|
||||||
|
service.add_standard_objects()
|
||||||
|
|
||||||
|
mock.SecretPrompt(service, None, "simple")
|
||||||
|
mock.SecretPrompt(service, None, "delay", delay=0.5)
|
||||||
|
mock.SecretPrompt(service, None, "result", result=dbus.String("Special Result", variant_level=1))
|
||||||
|
ErrorPrompt(service, None, "error")
|
||||||
|
VanishPrompt(service, None, "vanish")
|
||||||
|
WindowPrompt(service, None, "window")
|
||||||
|
|
||||||
|
service.listen()
|
@ -11,9 +11,10 @@
|
|||||||
# See the included COPYING file for more information.
|
# See the included COPYING file for more information.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import getopt
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import getopt
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import aes
|
import aes
|
||||||
@ -90,6 +91,48 @@ class AesAlgorithm():
|
|||||||
"".join([chr(i) for i in ciph]))
|
"".join([chr(i) for i in ciph]))
|
||||||
|
|
||||||
|
|
||||||
|
class SecretPrompt(dbus.service.Object):
|
||||||
|
def __init__(self, service, sender, prompt_name=None, delay=0,
|
||||||
|
dismiss=False, result=dbus.String("", variant_level=1),
|
||||||
|
action=None):
|
||||||
|
self.sender = sender
|
||||||
|
self.service = service
|
||||||
|
self.delay = 0
|
||||||
|
self.dismiss = False
|
||||||
|
self.result = result
|
||||||
|
self.action = action
|
||||||
|
self.completed = False
|
||||||
|
if prompt_name:
|
||||||
|
self.path = "/org/freedesktop/secrets/prompts/%s" % prompt_name
|
||||||
|
else:
|
||||||
|
self.path = "/org/freedesktop/secrets/prompts/p%d" % next_identifier()
|
||||||
|
dbus.service.Object.__init__(self, service.bus_name, self.path)
|
||||||
|
service.add_prompt(self)
|
||||||
|
assert self.path not in objects
|
||||||
|
objects[self.path] = self
|
||||||
|
|
||||||
|
def _complete(self):
|
||||||
|
if self.completed:
|
||||||
|
return
|
||||||
|
self.completed = True
|
||||||
|
self.Completed(self.dismiss, self.result)
|
||||||
|
self.remove_from_connection()
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Prompt')
|
||||||
|
def Prompt(self, window_id):
|
||||||
|
if self.action:
|
||||||
|
self.action()
|
||||||
|
gobject.timeout_add(self.delay * 1000, self._complete)
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Prompt')
|
||||||
|
def Dismiss(self):
|
||||||
|
self._complete()
|
||||||
|
|
||||||
|
@dbus.service.signal(dbus_interface='org.freedesktop.Secret.Prompt', signature='bv')
|
||||||
|
def Completed(self, dismiss, result):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SecretSession(dbus.service.Object):
|
class SecretSession(dbus.service.Object):
|
||||||
def __init__(self, service, sender, algorithm, key):
|
def __init__(self, service, sender, algorithm, key):
|
||||||
self.sender = sender
|
self.sender = sender
|
||||||
@ -116,7 +159,7 @@ class SecretSession(dbus.service.Object):
|
|||||||
|
|
||||||
class SecretItem(dbus.service.Object):
|
class SecretItem(dbus.service.Object):
|
||||||
def __init__(self, collection, identifier, label="Item", attributes={ },
|
def __init__(self, collection, identifier, label="Item", attributes={ },
|
||||||
secret="", content_type="text/plain"):
|
secret="", confirm=False, content_type="text/plain"):
|
||||||
self.collection = collection
|
self.collection = collection
|
||||||
self.identifier = identifier
|
self.identifier = identifier
|
||||||
self.label = label
|
self.label = label
|
||||||
@ -125,6 +168,7 @@ class SecretItem(dbus.service.Object):
|
|||||||
self.content_type = content_type
|
self.content_type = content_type
|
||||||
self.locked = collection.locked
|
self.locked = collection.locked
|
||||||
self.path = "%s/%s" % (collection.path, identifier)
|
self.path = "%s/%s" % (collection.path, identifier)
|
||||||
|
self.confirm = confirm
|
||||||
dbus.service.Object.__init__(self, collection.service.bus_name, self.path)
|
dbus.service.Object.__init__(self, collection.service.bus_name, self.path)
|
||||||
collection.items[identifier] = self
|
collection.items[identifier] = self
|
||||||
objects[self.path] = self
|
objects[self.path] = self
|
||||||
@ -135,6 +179,10 @@ class SecretItem(dbus.service.Object):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def perform_delete(self):
|
||||||
|
del self.collection.items[self.identifier]
|
||||||
|
del objects[self.path]
|
||||||
|
|
||||||
@dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender')
|
@dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender')
|
||||||
def GetSecret(self, session_path, sender=None):
|
def GetSecret(self, session_path, sender=None):
|
||||||
session = objects.get(session_path, None)
|
session = objects.get(session_path, None)
|
||||||
@ -144,6 +192,16 @@ class SecretItem(dbus.service.Object):
|
|||||||
raise IsLocked("secret is locked: %s" % self.path)
|
raise IsLocked("secret is locked: %s" % self.path)
|
||||||
return session.encode_secret(self.secret, self.content_type)
|
return session.encode_secret(self.secret, self.content_type)
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender')
|
||||||
|
def Delete(self, sender=None):
|
||||||
|
if self.confirm:
|
||||||
|
prompt = SecretPrompt(self.collection.service, sender,
|
||||||
|
dismiss=False, action=self.perform_delete)
|
||||||
|
return dbus.ObjectPath(prompt.path)
|
||||||
|
else:
|
||||||
|
self.perform_delete()
|
||||||
|
return dbus.ObjectPath("/")
|
||||||
|
|
||||||
|
|
||||||
class SecretCollection(dbus.service.Object):
|
class SecretCollection(dbus.service.Object):
|
||||||
def __init__(self, service, identifier, label="Collection", locked=False):
|
def __init__(self, service, identifier, label="Collection", locked=False):
|
||||||
@ -179,6 +237,7 @@ class SecretService(dbus.service.Object):
|
|||||||
self.bus_name = dbus.service.BusName(name, allow_replacement=True, replace_existing=True)
|
self.bus_name = dbus.service.BusName(name, allow_replacement=True, replace_existing=True)
|
||||||
dbus.service.Object.__init__(self, self.bus_name, '/org/freedesktop/secrets')
|
dbus.service.Object.__init__(self, self.bus_name, '/org/freedesktop/secrets')
|
||||||
self.sessions = { }
|
self.sessions = { }
|
||||||
|
self.prompts = { }
|
||||||
self.collections = { }
|
self.collections = { }
|
||||||
|
|
||||||
def on_name_owner_changed(owned, old_owner, new_owner):
|
def on_name_owner_changed(owned, old_owner, new_owner):
|
||||||
@ -213,6 +272,14 @@ class SecretService(dbus.service.Object):
|
|||||||
def remove_session(self, session):
|
def remove_session(self, session):
|
||||||
self.sessions[session.sender].remove(session)
|
self.sessions[session.sender].remove(session)
|
||||||
|
|
||||||
|
def add_prompt(self, prompt):
|
||||||
|
if prompt.sender not in self.prompts:
|
||||||
|
self.prompts[prompt.sender] = []
|
||||||
|
self.prompts[prompt.sender].append(prompt)
|
||||||
|
|
||||||
|
def remove_prompt (self, prompt):
|
||||||
|
self.prompts[prompt.sender].remove(prompt)
|
||||||
|
|
||||||
def find_item(self, object):
|
def find_item(self, object):
|
||||||
if object.startswith(COLLECTION_PREFIX):
|
if object.startswith(COLLECTION_PREFIX):
|
||||||
parts = object[len(COLLECTION_PREFIX):].split("/", 1)
|
parts = object[len(COLLECTION_PREFIX):].split("/", 1)
|
||||||
@ -254,6 +321,7 @@ class SecretService(dbus.service.Object):
|
|||||||
results[item_path] = item.GetSecret(session_path, sender)
|
results[item_path] = item.GetSecret(session_path, sender)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def parse_options(args):
|
def parse_options(args):
|
||||||
global bus_name
|
global bus_name
|
||||||
try:
|
try:
|
||||||
|
137
library/tests/test-password.c
Normal file
137
library/tests/test-password.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
|
*
|
||||||
|
* Copyright 2012 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Author: Stef Walter <stefw@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gsecret-password.h"
|
||||||
|
#include "gsecret-private.h"
|
||||||
|
|
||||||
|
#include "egg/egg-testing.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static gchar *MOCK_NAME = "org.mock.Service";
|
||||||
|
|
||||||
|
static const GSecretSchema DELETE_SCHEMA = {
|
||||||
|
"org.mock.schema.Delete",
|
||||||
|
{
|
||||||
|
{ "number", GSECRET_ATTRIBUTE_INTEGER },
|
||||||
|
{ "string", GSECRET_ATTRIBUTE_STRING },
|
||||||
|
{ "even", GSECRET_ATTRIBUTE_BOOLEAN },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GPid pid;
|
||||||
|
} Test;
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup (Test *test,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *mock_script = data;
|
||||||
|
gchar *argv[] = {
|
||||||
|
"python", (gchar *)mock_script,
|
||||||
|
"--name", MOCK_NAME,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
_gsecret_service_set_default_bus_name (MOCK_NAME);
|
||||||
|
|
||||||
|
g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_usleep (200 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
teardown (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
g_assert (test->pid);
|
||||||
|
if (kill (test->pid, SIGTERM) < 0)
|
||||||
|
g_error ("kill() failed: %s", g_strerror (errno));
|
||||||
|
g_spawn_close_pid (test->pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_complete_get_result (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GAsyncResult **ret = user_data;
|
||||||
|
g_assert (ret != NULL);
|
||||||
|
g_assert (*ret == NULL);
|
||||||
|
*ret = g_object_ref (result);
|
||||||
|
egg_test_wait_stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_sync (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gsecret_password_delete_sync (&DELETE_SCHEMA, NULL, &error,
|
||||||
|
"even", FALSE,
|
||||||
|
"string", "one",
|
||||||
|
"number", 1,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_async (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
gsecret_password_delete (&DELETE_SCHEMA, NULL,
|
||||||
|
on_complete_get_result, &result,
|
||||||
|
"even", FALSE,
|
||||||
|
"string", "one",
|
||||||
|
"number", 1,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_password_delete_finish (result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_object_unref (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
g_set_prgname ("test-password");
|
||||||
|
g_type_init ();
|
||||||
|
|
||||||
|
g_test_add ("/password/delete-sync", Test, "mock-service-delete.py", setup, test_delete_sync, teardown);
|
||||||
|
g_test_add ("/password/delete-async", Test, "mock-service-delete.py", setup, test_delete_async, teardown);
|
||||||
|
|
||||||
|
return egg_tests_run_with_loop ();
|
||||||
|
}
|
429
library/tests/test-prompt.c
Normal file
429
library/tests/test-prompt.c
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
/* GSecret - GLib wrapper for Secret Service
|
||||||
|
*
|
||||||
|
* Copyright 2011 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Author: Stef Walter <stefw@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gsecret-item.h"
|
||||||
|
#include "gsecret-service.h"
|
||||||
|
#include "gsecret-private.h"
|
||||||
|
#include "gsecret-prompt.h"
|
||||||
|
|
||||||
|
#include "egg/egg-testing.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static gchar *MOCK_NAME = "org.mock.Service";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GPid pid;
|
||||||
|
GDBusConnection *connection;
|
||||||
|
GSecretService *service;
|
||||||
|
} Test;
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup (Test *test,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *mock_script = data;
|
||||||
|
gchar *argv[] = {
|
||||||
|
"python", (gchar *)mock_script,
|
||||||
|
"--name", MOCK_NAME,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
_gsecret_service_set_default_bus_name (MOCK_NAME);
|
||||||
|
|
||||||
|
g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_usleep (200 * 1000);
|
||||||
|
|
||||||
|
test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
test->service = _gsecret_service_bare_instance (test->connection, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
teardown (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_object_unref (test->service);
|
||||||
|
egg_assert_not_object (test->service);
|
||||||
|
|
||||||
|
g_assert (test->pid);
|
||||||
|
if (kill (test->pid, SIGTERM) < 0) {
|
||||||
|
if (errno != ESRCH)
|
||||||
|
g_error ("kill() failed: %s", g_strerror (errno));
|
||||||
|
}
|
||||||
|
g_spawn_close_pid (test->pid);
|
||||||
|
|
||||||
|
g_dbus_connection_flush_sync (test->connection, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_object_unref (test->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_async_result (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GAsyncResult **ret = user_data;
|
||||||
|
g_assert (ret != NULL);
|
||||||
|
g_assert (*ret == NULL);
|
||||||
|
*ret = g_object_ref (result);
|
||||||
|
egg_test_wait_stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_idle_increment (gpointer user_data)
|
||||||
|
{
|
||||||
|
guint *value = user_data;
|
||||||
|
++(*value);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_perform_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
guint value = 0;
|
||||||
|
guint increment_id;
|
||||||
|
|
||||||
|
/* Verify that main loop does not run during this call */
|
||||||
|
increment_id = g_idle_add (on_idle_increment, &value);
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_sync (prompt, 0, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_assert_cmpuint (value, ==, 0);
|
||||||
|
g_source_remove (increment_id);
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_perform_run (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
guint value = 0;
|
||||||
|
guint increment_id;
|
||||||
|
|
||||||
|
/* Verify that main loop does run during this call */
|
||||||
|
increment_id = g_idle_add (on_idle_increment, &value);
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
|
||||||
|
|
||||||
|
ret = gsecret_prompt_run (prompt, 0, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret);
|
||||||
|
|
||||||
|
g_assert_cmpuint (value, >, 0);
|
||||||
|
g_source_remove (increment_id);
|
||||||
|
|
||||||
|
/* Make sure everything completes */
|
||||||
|
egg_test_wait_idle ();
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_perform_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
|
||||||
|
|
||||||
|
gsecret_prompt_perform (prompt, 0, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_finish (prompt, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
/* Make sure everything completes */
|
||||||
|
egg_test_wait_idle ();
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_perform_cancel (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/delay");
|
||||||
|
|
||||||
|
cancellable = g_cancellable_new ();
|
||||||
|
gsecret_prompt_perform (prompt, 0, cancellable, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
g_cancellable_cancel (cancellable);
|
||||||
|
g_object_unref (cancellable);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_finish (prompt, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
/* Make sure everything completes */
|
||||||
|
egg_test_wait_idle ();
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_perform_fail (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/error");
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_sync (prompt, 0, NULL, &error);
|
||||||
|
g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED);
|
||||||
|
g_assert (ret == FALSE);
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_perform_vanish (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/vanish");
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_sync (prompt, 0, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == FALSE);
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_prompt_result (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
GVariant *result;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/result");
|
||||||
|
|
||||||
|
result = gsecret_prompt_get_result_value (prompt);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_sync (prompt, 0, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
result = gsecret_prompt_get_result_value (prompt);
|
||||||
|
g_assert (result != NULL);
|
||||||
|
g_assert_cmpstr (g_variant_get_type_string (result), ==, "s");
|
||||||
|
g_assert_cmpstr (g_variant_get_string (result, NULL), ==, "Special Result");
|
||||||
|
g_variant_unref (result);
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_prompt_window_id (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
GVariant *result;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/window");
|
||||||
|
|
||||||
|
ret = gsecret_prompt_perform_sync (prompt, 555, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
result = gsecret_prompt_get_result_value (prompt);
|
||||||
|
g_assert (result != NULL);
|
||||||
|
g_assert_cmpstr (g_variant_get_type_string (result), ==, "s");
|
||||||
|
g_assert_cmpstr (g_variant_get_string (result, NULL), ==, "555");
|
||||||
|
g_variant_unref (result);
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_service_sync (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
|
||||||
|
|
||||||
|
ret = gsecret_service_prompt_sync (test->service, prompt, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_service_async (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
|
||||||
|
|
||||||
|
gsecret_service_prompt (test->service, prompt, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_service_prompt_finish (test->service, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
/* Make sure everything completes */
|
||||||
|
egg_test_wait_idle ();
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_service_fail (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GSecretPrompt *prompt;
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/error");
|
||||||
|
|
||||||
|
gsecret_service_prompt (test->service, prompt, NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_service_prompt_finish (test->service, result, &error);
|
||||||
|
g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED);
|
||||||
|
g_assert (ret == FALSE);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
/* Make sure everything completes */
|
||||||
|
egg_test_wait_idle ();
|
||||||
|
|
||||||
|
g_object_unref (prompt);
|
||||||
|
egg_assert_not_object (prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_service_path (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
gsecret_service_prompt_path (test->service, "/org/freedesktop/secrets/prompts/simple",
|
||||||
|
NULL, on_async_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_service_prompt_finish (test->service, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
/* Make sure everything completes */
|
||||||
|
egg_test_wait_idle ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
g_set_prgname ("test-prompt");
|
||||||
|
g_type_init ();
|
||||||
|
|
||||||
|
g_test_add ("/prompt/run", Test, "mock-service-prompt.py", setup, test_perform_run, teardown);
|
||||||
|
g_test_add ("/prompt/perform-sync", Test, "mock-service-prompt.py", setup, test_perform_sync, teardown);
|
||||||
|
g_test_add ("/prompt/perform-async", Test, "mock-service-prompt.py", setup, test_perform_async, teardown);
|
||||||
|
g_test_add ("/prompt/perform-cancel", Test, "mock-service-prompt.py", setup, test_perform_cancel, teardown);
|
||||||
|
g_test_add ("/prompt/perform-fail", Test, "mock-service-prompt.py", setup, test_perform_fail, teardown);
|
||||||
|
g_test_add ("/prompt/perform-vanish", Test, "mock-service-prompt.py", setup, test_perform_vanish, teardown);
|
||||||
|
g_test_add ("/prompt/result", Test, "mock-service-prompt.py", setup, test_prompt_result, teardown);
|
||||||
|
g_test_add ("/prompt/window-id", Test, "mock-service-prompt.py", setup, test_prompt_window_id, teardown);
|
||||||
|
|
||||||
|
g_test_add ("/prompt/service-sync", Test, "mock-service-prompt.py", setup, test_service_sync, teardown);
|
||||||
|
g_test_add ("/prompt/service-async", Test, "mock-service-prompt.py", setup, test_service_async, teardown);
|
||||||
|
g_test_add ("/prompt/service-path", Test, "mock-service-prompt.py", setup, test_service_path, teardown);
|
||||||
|
g_test_add ("/prompt/service-fail", Test, "mock-service-prompt.py", setup, test_service_fail, teardown);
|
||||||
|
|
||||||
|
return egg_tests_run_with_loop ();
|
||||||
|
}
|
@ -25,6 +25,15 @@
|
|||||||
|
|
||||||
static gchar *MOCK_NAME = "org.mock.Service";
|
static gchar *MOCK_NAME = "org.mock.Service";
|
||||||
|
|
||||||
|
static const GSecretSchema DELETE_SCHEMA = {
|
||||||
|
"org.mock.schema.Delete",
|
||||||
|
{
|
||||||
|
{ "number", GSECRET_ATTRIBUTE_INTEGER },
|
||||||
|
{ "string", GSECRET_ATTRIBUTE_STRING },
|
||||||
|
{ "even", GSECRET_ATTRIBUTE_BOOLEAN },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GPid pid;
|
GPid pid;
|
||||||
GDBusConnection *connection;
|
GDBusConnection *connection;
|
||||||
@ -32,8 +41,8 @@ typedef struct {
|
|||||||
} Test;
|
} Test;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setup (Test *test,
|
setup_mock (Test *test,
|
||||||
gconstpointer data)
|
gconstpointer data)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
const gchar *mock_script = data;
|
const gchar *mock_script = data;
|
||||||
@ -43,29 +52,49 @@ setup (Test *test,
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_gsecret_service_set_default_bus_name (MOCK_NAME);
|
||||||
|
|
||||||
g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error);
|
g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_usleep (200 * 1000);
|
g_usleep (200 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup (Test *test,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
setup_mock (test, data);
|
||||||
|
|
||||||
test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
|
|
||||||
test->service = _gsecret_service_bare_instance (test->connection, MOCK_NAME);
|
test->service = _gsecret_service_bare_instance (test->connection, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
teardown_mock (Test *test,
|
||||||
|
gconstpointer unused)
|
||||||
|
{
|
||||||
|
g_assert (test->pid);
|
||||||
|
if (kill (test->pid, SIGTERM) < 0)
|
||||||
|
g_error ("kill() failed: %s", g_strerror (errno));
|
||||||
|
g_spawn_close_pid (test->pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
teardown (Test *test,
|
teardown (Test *test,
|
||||||
gconstpointer unused)
|
gconstpointer unused)
|
||||||
{
|
{
|
||||||
|
egg_test_wait_idle ();
|
||||||
|
|
||||||
g_object_unref (test->service);
|
g_object_unref (test->service);
|
||||||
egg_assert_not_object (test->service);
|
egg_assert_not_object (test->service);
|
||||||
|
|
||||||
g_clear_object (&test->connection);
|
g_clear_object (&test->connection);
|
||||||
|
|
||||||
g_assert (test->pid);
|
teardown_mock (test, unused);
|
||||||
if (kill (test->pid, SIGTERM) < 0)
|
|
||||||
g_error ("kill() failed: %s", g_strerror (errno));
|
|
||||||
g_spawn_close_pid (test->pid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -116,6 +145,60 @@ test_instance (void)
|
|||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_connect_sync (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GSecretService *service;
|
||||||
|
const gchar *path;
|
||||||
|
|
||||||
|
/* Passing false, not session */
|
||||||
|
_gsecret_service_bare_connect (MOCK_NAME, FALSE, NULL, on_complete_get_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
service = _gsecret_service_bare_connect_finish (result, &error);
|
||||||
|
g_assert (GSECRET_IS_SERVICE (service));
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
path = gsecret_service_get_session_path (service);
|
||||||
|
g_assert (path == NULL);
|
||||||
|
|
||||||
|
g_object_unref (service);
|
||||||
|
egg_assert_not_object (service);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_connect_ensure_sync (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
GSecretService *service;
|
||||||
|
const gchar *path;
|
||||||
|
|
||||||
|
/* Passing true, ensures session is established */
|
||||||
|
_gsecret_service_bare_connect (MOCK_NAME, TRUE, NULL, on_complete_get_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
service = _gsecret_service_bare_connect_finish (result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (GSECRET_IS_SERVICE (service));
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
path = gsecret_service_get_session_path (service);
|
||||||
|
g_assert (path != NULL);
|
||||||
|
|
||||||
|
g_object_unref (service);
|
||||||
|
egg_assert_not_object (service);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_search_paths (Test *test,
|
test_search_paths (Test *test,
|
||||||
gconstpointer used)
|
gconstpointer used)
|
||||||
@ -405,6 +488,111 @@ test_secrets_for_paths_async (Test *test,
|
|||||||
g_hash_table_unref (values);
|
g_hash_table_unref (values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_for_path_sync (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
|
||||||
|
{
|
||||||
|
const gchar *path_item_one = "/org/freedesktop/secrets/collection/to_delete/item";
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gsecret_service_delete_path_sync (test->service, path_item_one, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_for_path_sync_prompt (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
|
||||||
|
{
|
||||||
|
const gchar *path_item_one = "/org/freedesktop/secrets/collection/to_delete/confirm";
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gsecret_service_delete_path_sync (test->service, path_item_one, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_password_sync (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gsecret_service_delete_password_sync (test->service, &DELETE_SCHEMA, NULL, &error,
|
||||||
|
"even", FALSE,
|
||||||
|
"string", "one",
|
||||||
|
"number", 1,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_password_async (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
gsecret_service_delete_password (test->service, &DELETE_SCHEMA, NULL,
|
||||||
|
on_complete_get_result, &result,
|
||||||
|
"even", FALSE,
|
||||||
|
"string", "one",
|
||||||
|
"number", 1,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert (result == NULL);
|
||||||
|
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
ret = gsecret_service_delete_password_finish (test->service, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_object_unref (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_password_locked (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gsecret_service_delete_password_sync (test->service, &DELETE_SCHEMA, NULL, &error,
|
||||||
|
"even", FALSE,
|
||||||
|
"string", "three",
|
||||||
|
"number", 3,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_delete_password_no_match (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
/* Won't match anything */
|
||||||
|
ret = gsecret_service_delete_password_sync (test->service, &DELETE_SCHEMA, NULL, &error,
|
||||||
|
"even", TRUE,
|
||||||
|
"string", "one",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (ret == FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -413,14 +601,26 @@ main (int argc, char **argv)
|
|||||||
g_type_init ();
|
g_type_init ();
|
||||||
|
|
||||||
g_test_add_func ("/service/instance", test_instance);
|
g_test_add_func ("/service/instance", test_instance);
|
||||||
|
|
||||||
|
g_test_add ("/service/connect-sync", Test, "mock-service-normal.py", setup_mock, test_connect_sync, teardown_mock);
|
||||||
|
g_test_add ("/service/connect-ensure-sync", Test, "mock-service-normal.py", setup_mock, test_connect_ensure_sync, teardown_mock);
|
||||||
|
|
||||||
g_test_add ("/service/search-for-paths", Test, "mock-service-normal.py", setup, test_search_paths, teardown);
|
g_test_add ("/service/search-for-paths", Test, "mock-service-normal.py", setup, test_search_paths, teardown);
|
||||||
g_test_add ("/service/search-for-paths-async", Test, "mock-service-normal.py", setup, test_search_paths_async, teardown);
|
g_test_add ("/service/search-for-paths-async", Test, "mock-service-normal.py", setup, test_search_paths_async, teardown);
|
||||||
g_test_add ("/service/search-for-paths-nulls", Test, "mock-service-normal.py", setup, test_search_paths_nulls, teardown);
|
g_test_add ("/service/search-for-paths-nulls", Test, "mock-service-normal.py", setup, test_search_paths_nulls, teardown);
|
||||||
|
|
||||||
g_test_add ("/service/secret-for-path", Test, "mock-service-normal.py", setup, test_secret_for_path, teardown);
|
g_test_add ("/service/secret-for-path", Test, "mock-service-normal.py", setup, test_secret_for_path, teardown);
|
||||||
g_test_add ("/service/secret-for-path-plain", Test, "mock-service-only-plain.py", setup, test_secret_for_path, teardown);
|
g_test_add ("/service/secret-for-path-plain", Test, "mock-service-only-plain.py", setup, test_secret_for_path, teardown);
|
||||||
g_test_add ("/service/secret-for-path-async", Test, "mock-service-normal.py", setup, test_secret_for_path_async, teardown);
|
g_test_add ("/service/secret-for-path-async", Test, "mock-service-normal.py", setup, test_secret_for_path_async, teardown);
|
||||||
g_test_add ("/service/secrets-for-paths", Test, "mock-service-normal.py", setup, test_secrets_for_paths, teardown);
|
g_test_add ("/service/secrets-for-paths", Test, "mock-service-normal.py", setup, test_secrets_for_paths, teardown);
|
||||||
g_test_add ("/service/secrets-for-paths-async", Test, "mock-service-normal.py", setup, test_secrets_for_paths_async, teardown);
|
g_test_add ("/service/secrets-for-paths-async", Test, "mock-service-normal.py", setup, test_secrets_for_paths_async, teardown);
|
||||||
|
|
||||||
|
g_test_add ("/service/delete-for-path", Test, "mock-service-delete.py", setup, test_delete_for_path_sync, teardown);
|
||||||
|
g_test_add ("/service/delete-for-path-with-prompt", Test, "mock-service-delete.py", setup, test_delete_for_path_sync_prompt, teardown);
|
||||||
|
g_test_add ("/service/delete-password-sync", Test, "mock-service-delete.py", setup, test_delete_password_sync, teardown);
|
||||||
|
g_test_add ("/service/delete-password-async", Test, "mock-service-delete.py", setup, test_delete_password_async, teardown);
|
||||||
|
g_test_add ("/service/delete-password-locked", Test, "mock-service-delete.py", setup, test_delete_password_locked, teardown);
|
||||||
|
g_test_add ("/service/delete-password-no-match", Test, "mock-service-delete.py", setup, test_delete_password_no_match, teardown);
|
||||||
|
|
||||||
return egg_tests_run_with_loop ();
|
return egg_tests_run_with_loop ();
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@ setup (Test *test,
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_gsecret_service_set_default_bus_name (MOCK_NAME);
|
||||||
|
|
||||||
g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error);
|
g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_usleep (200 * 1000);
|
g_usleep (200 * 1000);
|
||||||
@ -51,7 +53,7 @@ setup (Test *test,
|
|||||||
test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
|
|
||||||
test->service = _gsecret_service_bare_instance (test->connection, MOCK_NAME);
|
test->service = _gsecret_service_bare_instance (test->connection, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user