[l10n] Updated Catalan translation
[platform/upstream/libsecret.git] / libsecret / secret-paths.c
1 /* libsecret - GLib wrapper for Secret Service
2  *
3  * Copyright 2011 Collabora Ltd.
4  * Copyright 2012 Red Hat Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published
8  * by the Free Software Foundation; either version 2.1 of the licence or (at
9  * your option) any later version.
10  *
11  * See the included COPYING file for more information.
12  *
13  * Author: Stef Walter <stefw@gnome.org>
14  */
15
16 #include "config.h"
17
18 #include "secret-dbus-generated.h"
19 #include "secret-paths.h"
20 #include "secret-private.h"
21 #include "secret-service.h"
22 #include "secret-types.h"
23 #include "secret-value.h"
24
25
26 /**
27  * SECTION:secret-paths
28  * @title: DBus Path Related Functions
29  * @short_description: Secret Service functions which operate on DBus object paths
30  *
31  * These are low level functions which operate on DBus object paths of
32  * collections or items, instead of the #SecretCollection or #SecretItem
33  * objects themselves.
34  *
35  * You can use these functions if you wish to manage access to the secret
36  * service using the DBus API directly, and only wish to use a few calls
37  * in libsecret.
38  *
39  * These functions have an unstable API and may change across versions. Use
40  * <literal>libsecret-unstable</literal> package to access them.
41  *
42  * Stability: Unstable
43  */
44
45 /**
46  * secret_collection_new_for_dbus_path:
47  * @service: (allow-none): a secret service object
48  * @collection_path: the D-Bus path of the collection
49  * @flags: options for the collection initialization
50  * @cancellable: optional cancellation object
51  * @callback: called when the operation completes
52  * @user_data: data to be passed to the callback
53  *
54  * Get a new collection proxy for a collection in the secret service.
55  *
56  * If @service is NULL, then secret_service_get() will be called to get
57  * the default #SecretService proxy.
58  *
59  * This method will return immediately and complete asynchronously.
60  */
61 void
62 secret_collection_new_for_dbus_path (SecretService *service,
63                                      const gchar *collection_path,
64                                      SecretCollectionFlags flags,
65                                      GCancellable *cancellable,
66                                      GAsyncReadyCallback callback,
67                                      gpointer user_data)
68 {
69         GDBusProxy *proxy;
70
71         g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
72         g_return_if_fail (collection_path != NULL);
73         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
74
75         proxy = G_DBUS_PROXY (service);
76
77         g_async_initable_new_async (secret_service_get_collection_gtype (service),
78                                     G_PRIORITY_DEFAULT, cancellable, callback, user_data,
79                                     "g-flags", G_DBUS_CALL_FLAGS_NONE,
80                                     "g-interface-info", _secret_gen_collection_interface_info (),
81                                     "g-name", g_dbus_proxy_get_name (proxy),
82                                     "g-connection", g_dbus_proxy_get_connection (proxy),
83                                     "g-object-path", collection_path,
84                                     "g-interface-name", SECRET_COLLECTION_INTERFACE,
85                                     "service", service,
86                                     "flags", flags,
87                                     NULL);
88 }
89
90 /**
91  * secret_collection_new_for_dbus_path_finish:
92  * @result: the asynchronous result passed to the callback
93  * @error: location to place an error on failure
94  *
95  * Finish asynchronous operation to get a new collection proxy for a
96  * collection in the secret service.
97  *
98  * Returns: (transfer full): the new collection, which should be unreferenced
99  *          with g_object_unref()
100  */
101 SecretCollection *
102 secret_collection_new_for_dbus_path_finish (GAsyncResult *result,
103                                             GError **error)
104 {
105         GObject *source_object;
106         GObject *object;
107
108         g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
109         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
110
111         source_object = g_async_result_get_source_object (result);
112         object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
113                                               result, error);
114         g_object_unref (source_object);
115
116         if (object == NULL)
117                 return NULL;
118
119         return SECRET_COLLECTION (object);
120 }
121
122 /**
123  * secret_collection_new_for_dbus_path_sync:
124  * @service: (allow-none): a secret service object
125  * @collection_path: the D-Bus path of the collection
126  * @flags: options for the collection initialization
127  * @cancellable: optional cancellation object
128  * @error: location to place an error on failure
129  *
130  * Get a new collection proxy for a collection in the secret service.
131  *
132  * If @service is NULL, then secret_service_get_sync() will be called to get
133  * the default #SecretService proxy.
134  *
135  * This method may block indefinitely and should not be used in user interface
136  * threads.
137  *
138  * Returns: (transfer full): the new collection, which should be unreferenced
139  *          with g_object_unref()
140  */
141 SecretCollection *
142 secret_collection_new_for_dbus_path_sync (SecretService *service,
143                                           const gchar *collection_path,
144                                           SecretCollectionFlags flags,
145                                           GCancellable *cancellable,
146                                           GError **error)
147 {
148         GDBusProxy *proxy;
149
150         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
151         g_return_val_if_fail (collection_path != NULL, NULL);
152         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
153         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
154
155         proxy = G_DBUS_PROXY (service);
156
157         return g_initable_new (secret_service_get_collection_gtype (service),
158                                cancellable, error,
159                                "g-flags", G_DBUS_CALL_FLAGS_NONE,
160                                "g-interface-info", _secret_gen_collection_interface_info (),
161                                "g-name", g_dbus_proxy_get_name (proxy),
162                                "g-connection", g_dbus_proxy_get_connection (proxy),
163                                "g-object-path", collection_path,
164                                "g-interface-name", SECRET_COLLECTION_INTERFACE,
165                                "service", service,
166                                "flags", flags,
167                                NULL);
168 }
169
170 /**
171  * secret_item_new_for_dbus_path:
172  * @service: (allow-none): a secret service object
173  * @item_path: the D-Bus path of the collection
174  * @flags: initialization flags for the new item
175  * @cancellable: optional cancellation object
176  * @callback: called when the operation completes
177  * @user_data: data to be passed to the callback
178  *
179  * Get a new item proxy for a secret item in the secret service.
180  *
181  * If @service is NULL, then secret_service_get() will be called to get
182  * the default #SecretService proxy.
183  *
184  * This method will return immediately and complete asynchronously.
185  */
186 void
187 secret_item_new_for_dbus_path (SecretService *service,
188                                const gchar *item_path,
189                                SecretItemFlags flags,
190                                GCancellable *cancellable,
191                                GAsyncReadyCallback callback,
192                                gpointer user_data)
193 {
194         GDBusProxy *proxy;
195
196         g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
197         g_return_if_fail (item_path != NULL);
198         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
199
200         proxy = G_DBUS_PROXY (service);
201
202         g_async_initable_new_async (secret_service_get_item_gtype (service),
203                                     G_PRIORITY_DEFAULT, cancellable, callback, user_data,
204                                     "g-flags", G_DBUS_CALL_FLAGS_NONE,
205                                     "g-interface-info", _secret_gen_item_interface_info (),
206                                     "g-name", g_dbus_proxy_get_name (proxy),
207                                     "g-connection", g_dbus_proxy_get_connection (proxy),
208                                     "g-object-path", item_path,
209                                     "g-interface-name", SECRET_ITEM_INTERFACE,
210                                     "service", service,
211                                     "flags", flags,
212                                     NULL);
213 }
214
215 /**
216  * secret_item_new_for_dbus_path_finish:
217  * @result: the asynchronous result passed to the callback
218  * @error: location to place an error on failure
219  *
220  * Finish asynchronous operation to get a new item proxy for an secret
221  * item in the secret service.
222  *
223  * Returns: (transfer full): the new item, which should be unreferenced
224  *          with g_object_unref()
225  */
226 SecretItem *
227 secret_item_new_for_dbus_path_finish (GAsyncResult *result,
228                                       GError **error)
229 {
230         GObject *object;
231         GObject *source_object;
232
233         source_object = g_async_result_get_source_object (result);
234         object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
235                                               result, error);
236         g_object_unref (source_object);
237
238         if (object == NULL)
239                 return NULL;
240
241         return SECRET_ITEM (object);
242 }
243
244 /**
245  * secret_item_new_dbus_path_sync:
246  * @service: (allow-none): a secret service object
247  * @item_path: the D-Bus path of the item
248  * @flags: initialization flags for the new item
249  * @cancellable: optional cancellation object
250  * @error: location to place an error on failure
251  *
252  * Get a new item proxy for a secret item in the secret service.
253  *
254  * If @service is NULL, then secret_service_get_sync() will be called to get
255  * the default #SecretService proxy.
256  *
257  * This method may block indefinitely and should not be used in user interface
258  * threads.
259  *
260  * Returns: (transfer full): the new item, which should be unreferenced
261  *          with g_object_unref()
262  */
263 SecretItem *
264 secret_item_new_for_dbus_path_sync (SecretService *service,
265                                     const gchar *item_path,
266                                     SecretItemFlags flags,
267                                     GCancellable *cancellable,
268                                     GError **error)
269 {
270         GDBusProxy *proxy;
271
272         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
273         g_return_val_if_fail (item_path != NULL, NULL);
274         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
275         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
276
277         proxy = G_DBUS_PROXY (service);
278
279         return g_initable_new (secret_service_get_item_gtype (service),
280                                cancellable, error,
281                                "g-flags", G_DBUS_CALL_FLAGS_NONE,
282                                "g-interface-info", _secret_gen_item_interface_info (),
283                                "g-name", g_dbus_proxy_get_name (proxy),
284                                "g-connection", g_dbus_proxy_get_connection (proxy),
285                                "g-object-path", item_path,
286                                "g-interface-name", SECRET_ITEM_INTERFACE,
287                                "service", service,
288                                "flags", flags,
289                                NULL);
290 }
291
292 static void
293 on_search_items_complete (GObject *source,
294                           GAsyncResult *result,
295                           gpointer user_data)
296 {
297         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
298         GError *error = NULL;
299         GVariant *response;
300
301         response = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
302         if (error != NULL) {
303                 g_simple_async_result_take_error (res, error);
304         } else {
305                 g_simple_async_result_set_op_res_gpointer (res, response,
306                                                            (GDestroyNotify)g_variant_unref);
307         }
308
309         g_simple_async_result_complete (res);
310         g_object_unref (res);
311 }
312
313 /**
314  * secret_collection_search_for_dbus_paths:
315  * @collection: the secret collection
316  * @schema: (allow-none): the schema for the attributes
317  * @attributes: (element-type utf8 utf8): search for items matching these attributes
318  * @cancellable: optional cancellation object
319  * @callback: called when the operation completes
320  * @user_data: data to pass to the callback
321  *
322  * Search for items in @collection matching the @attributes, and return their
323  * DBus object paths. Only the specified collection is searched. The @attributes
324  * should be a table of string keys and string values.
325  *
326  * This function returns immediately and completes asynchronously.
327  *
328  * When your callback is called use secret_collection_search_for_dbus_paths_finish()
329  * to get the results of this function. Only the DBus object paths of the
330  * items will be returned. If you would like #SecretItem objects to be returned
331  * instead, then use the secret_collection_search() function.
332  */
333 void
334 secret_collection_search_for_dbus_paths (SecretCollection *collection,
335                                          const SecretSchema *schema,
336                                          GHashTable *attributes,
337                                          GCancellable *cancellable,
338                                          GAsyncReadyCallback callback,
339                                          gpointer user_data)
340 {
341         GSimpleAsyncResult *async;
342         const gchar *schema_name = NULL;
343
344         g_return_if_fail (SECRET_IS_COLLECTION (collection));
345         g_return_if_fail (attributes != NULL);
346         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
347
348         /* Warnings raised already */
349         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
350                 return;
351
352         if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME))
353                 schema_name = schema->name;
354
355         async = g_simple_async_result_new (G_OBJECT (collection), callback, user_data,
356                                            secret_collection_search_for_dbus_paths);
357
358         g_dbus_proxy_call (G_DBUS_PROXY (collection), "SearchItems",
359                            g_variant_new ("(@a{ss})", _secret_attributes_to_variant (attributes, schema_name)),
360                            G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
361                            on_search_items_complete, g_object_ref (async));
362
363         g_object_unref (async);
364 }
365
366 /**
367  * secret_collection_search_for_dbus_paths_finish:
368  * @collection: the secret collection
369  * @result: asynchronous result passed to callback
370  * @error: location to place error on failure
371  *
372  * Complete asynchronous operation to search for items in a collection.
373  *
374  * DBus object paths of the items will be returned. If you would to have
375  * #SecretItem objects to be returned instead, then use the
376  * secret_collection_search() and secret_collection_search_finish() functions.
377  *
378  * Returns: (transfer full) (array zero-terminated=1): an array of DBus object
379  *          paths for matching items.
380  */
381 gchar **
382 secret_collection_search_for_dbus_paths_finish (SecretCollection *collection,
383                                                 GAsyncResult *result,
384                                                 GError **error)
385 {
386         GVariant *retval;
387         GSimpleAsyncResult *async;
388         gchar **paths = NULL;
389
390         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (collection),
391                               secret_collection_search_for_dbus_paths), FALSE);
392         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
393
394         async = G_SIMPLE_ASYNC_RESULT (result);
395         if (_secret_util_propagate_error (async, error))
396                 return FALSE;
397
398         retval= g_simple_async_result_get_op_res_gpointer (async);
399         g_variant_get (retval, "(^ao)", &paths);
400         return paths;
401 }
402
403 /**
404  * secret_collection_search_for_dbus_paths_sync:
405  * @collection: the secret collection
406  * @schema: (allow-none): the schema for the attributes
407  * @attributes: (element-type utf8 utf8): search for items matching these attributes
408  * @cancellable: optional cancellation object
409  * @error: location to place error on failure
410  *
411  * Search for items matching the @attributes in @collection, and return their
412  * DBus object paths. The @attributes should be a table of string keys and
413  * string values.
414  *
415  * This function may block indefinetely. Use the asynchronous version
416  * in user interface threads.
417  *
418  * DBus object paths of the items will be returned. If you would to have
419  * #SecretItem objects to be returned instead, then use the
420  * secret_collection_search_sync() function.
421  *
422  * Returns: (transfer full) (array zero-terminated=1): an array of DBus object
423  *          paths for matching items.
424  */
425 gchar **
426 secret_collection_search_for_dbus_paths_sync (SecretCollection *collection,
427                                               const SecretSchema *schema,
428                                               GHashTable *attributes,
429                                               GCancellable *cancellable,
430                                               GError **error)
431 {
432         SecretSync *sync;
433         gchar **paths;
434
435         g_return_val_if_fail (SECRET_IS_COLLECTION (collection), NULL);
436         g_return_val_if_fail (attributes != NULL, NULL);
437         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
438         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
439
440         sync = _secret_sync_new ();
441         g_main_context_push_thread_default (sync->context);
442
443         secret_collection_search_for_dbus_paths (collection, schema, attributes, cancellable,
444                                                  _secret_sync_on_result, sync);
445
446         g_main_loop_run (sync->loop);
447
448         paths = secret_collection_search_for_dbus_paths_finish (collection, sync->result, error);
449
450         g_main_context_pop_thread_default (sync->context);
451         _secret_sync_free (sync);
452
453         return paths;
454 }
455
456 /**
457  * secret_service_search_for_dbus_paths:
458  * @self: the secret service
459  * @schema: (allow-none): the schema for the attributes
460  * @attributes: (element-type utf8 utf8): search for items matching these attributes
461  * @cancellable: optional cancellation object
462  * @callback: called when the operation completes
463  * @user_data: data to pass to the callback
464  *
465  * Search for items matching the @attributes, and return their D-Bus object paths.
466  * All collections are searched. The @attributes should be a table of string keys
467  * and string values.
468  *
469  * This function returns immediately and completes asynchronously.
470  *
471  * When your callback is called use secret_service_search_for_dbus_paths_finish()
472  * to get the results of this function. Only the D-Bus object paths of the
473  * items will be returned. If you would like #SecretItem objects to be returned
474  * instead, then use the secret_service_search() function.
475  */
476 void
477 secret_service_search_for_dbus_paths (SecretService *self,
478                                       const SecretSchema *schema,
479                                       GHashTable *attributes,
480                                       GCancellable *cancellable,
481                                       GAsyncReadyCallback callback,
482                                       gpointer user_data)
483 {
484         const gchar *schema_name = NULL;
485
486         g_return_if_fail (SECRET_IS_SERVICE (self));
487         g_return_if_fail (attributes != NULL);
488         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
489
490         /* Warnings raised already */
491         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
492                 return;
493
494         if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME))
495                 schema_name = schema->name;
496
497         _secret_service_search_for_paths_variant (self, _secret_attributes_to_variant (attributes, schema_name),
498                                                   cancellable, callback, user_data);
499 }
500
501 void
502 _secret_service_search_for_paths_variant (SecretService *self,
503                                           GVariant *attributes,
504                                           GCancellable *cancellable,
505                                           GAsyncReadyCallback callback,
506                                           gpointer user_data)
507 {
508         GSimpleAsyncResult *res;
509
510         g_return_if_fail (SECRET_IS_SERVICE (self));
511         g_return_if_fail (attributes != NULL);
512         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
513
514         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
515                                          secret_service_search_for_dbus_paths);
516
517         g_dbus_proxy_call (G_DBUS_PROXY (self), "SearchItems",
518                            g_variant_new ("(@a{ss})", attributes),
519                            G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
520                            on_search_items_complete, g_object_ref (res));
521
522         g_object_unref (res);
523 }
524
525 /**
526  * secret_service_search_for_dbus_paths_finish:
527  * @self: the secret service
528  * @result: asynchronous result passed to callback
529  * @unlocked: (out) (transfer full) (array zero-terminated=1) (allow-none):
530  *            location to place an array of D-Bus object paths for matching
531  *            items which were locked.
532  * @locked: (out) (transfer full) (array zero-terminated=1) (allow-none):
533  *          location to place an array of D-Bus object paths for matching
534  *          items which were locked.
535  * @error: location to place error on failure
536  *
537  * Complete asynchronous operation to search for items, and return their
538  * D-Bus object paths.
539  *
540  * Matching items that are locked or unlocked, have their D-Bus paths placed
541  * in the @locked or @unlocked arrays respectively.
542  *
543  * D-Bus object paths of the items will be returned in the @unlocked or
544  * @locked arrays. If you would to have #SecretItem objects to be returned
545  * instead, then us the secret_service_search() and
546  * secret_service_search_finish() functions.
547  *
548  * Returns: whether the search was successful or not
549  */
550 gboolean
551 secret_service_search_for_dbus_paths_finish (SecretService *self,
552                                              GAsyncResult *result,
553                                              gchar ***unlocked,
554                                              gchar ***locked,
555                                              GError **error)
556 {
557         GVariant *response;
558         GSimpleAsyncResult *res;
559         gchar **dummy = NULL;
560
561         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
562                               secret_service_search_for_dbus_paths), FALSE);
563         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
564
565         res = G_SIMPLE_ASYNC_RESULT (result);
566         if (_secret_util_propagate_error (res, error))
567                 return FALSE;
568
569         if (unlocked || locked) {
570                 if (!unlocked)
571                         unlocked = &dummy;
572                 else if (!locked)
573                         locked = &dummy;
574                 response = g_simple_async_result_get_op_res_gpointer (res);
575                 g_variant_get (response, "(^ao^ao)", unlocked, locked);
576         }
577
578         g_strfreev (dummy);
579         return TRUE;
580 }
581
582 /**
583  * secret_service_search_for_dbus_paths_sync:
584  * @self: the secret service
585  * @schema: (allow-none): the schema for the attributes
586  * @attributes: (element-type utf8 utf8): search for items matching these attributes
587  * @cancellable: optional cancellation object
588  * @unlocked: (out) (transfer full) (array zero-terminated=1) (allow-none):
589  *            location to place an array of D-Bus object paths for matching
590  *            items which were locked.
591  * @locked: (out) (transfer full) (array zero-terminated=1) (allow-none):
592  *          location to place an array of D-Bus object paths for matching
593  *          items which were locked.
594  * @error: location to place error on failure
595  *
596  * Search for items matching the @attributes, and return their D-Bus object
597  * paths. All collections are searched. The @attributes should be a table of
598  * string keys and string values.
599  *
600  * This function may block indefinetely. Use the asynchronous version
601  * in user interface threads.
602  *
603  * Matching items that are locked or unlocked, have their D-Bus paths placed
604  * in the @locked or @unlocked arrays respectively.
605  *
606  * D-Bus object paths of the items will be returned in the @unlocked or
607  * @locked arrays. If you would to have #SecretItem objects to be returned
608  * instead, then use the secret_service_search_sync() function.
609  *
610  * Returns: whether the search was successful or not
611  */
612 gboolean
613 secret_service_search_for_dbus_paths_sync (SecretService *self,
614                                            const SecretSchema *schema,
615                                            GHashTable *attributes,
616                                            GCancellable *cancellable,
617                                            gchar ***unlocked,
618                                            gchar ***locked,
619                                            GError **error)
620 {
621         const gchar *schema_name = NULL;
622         gchar **dummy = NULL;
623         GVariant *response;
624
625         g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
626         g_return_val_if_fail (attributes != NULL, FALSE);
627         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
628         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
629
630         /* Warnings raised already */
631         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
632                 return FALSE;
633
634         if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME))
635                 schema_name = schema->name;
636
637         response = g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "SearchItems",
638                                            g_variant_new ("(@a{ss})",
639                                                           _secret_attributes_to_variant (attributes, schema_name)),
640                                            G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error);
641
642         if (response != NULL) {
643                 if (unlocked || locked) {
644                         if (!unlocked)
645                                 unlocked = &dummy;
646                         else if (!locked)
647                                 locked = &dummy;
648                         g_variant_get (response, "(^ao^ao)", unlocked, locked);
649                 }
650
651                 g_variant_unref (response);
652         }
653
654         g_strfreev (dummy);
655
656         return response != NULL;
657 }
658
659 typedef struct {
660         GCancellable *cancellable;
661         GVariant *in;
662         GVariant *out;
663         GHashTable *items;
664 } GetClosure;
665
666 static void
667 get_closure_free (gpointer data)
668 {
669         GetClosure *closure = data;
670         if (closure->in)
671                 g_variant_unref (closure->in);
672         if (closure->out)
673                 g_variant_unref (closure->out);
674         g_clear_object (&closure->cancellable);
675         g_slice_free (GetClosure, closure);
676 }
677
678 static void
679 on_get_secrets_complete (GObject *source,
680                          GAsyncResult *result,
681                          gpointer user_data)
682 {
683         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
684         GetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
685         GError *error = NULL;
686
687         closure->out = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
688         if (error != NULL) {
689                 g_simple_async_result_take_error (res, error);
690         }
691         g_simple_async_result_complete (res);
692
693         g_object_unref (res);
694 }
695
696 static void
697 on_get_secrets_session (GObject *source,
698                         GAsyncResult *result,
699                         gpointer user_data)
700 {
701         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
702         GetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
703         GError *error = NULL;
704         const gchar *session;
705
706         secret_service_ensure_session_finish (SECRET_SERVICE (source), result, &error);
707         if (error != NULL) {
708                 g_simple_async_result_take_error (res, error);
709                 g_simple_async_result_complete (res);
710         } else {
711                 session = secret_service_get_session_dbus_path (SECRET_SERVICE (source));
712                 g_dbus_proxy_call (G_DBUS_PROXY (source), "GetSecrets",
713                                    g_variant_new ("(@aoo)", closure->in, session),
714                                    G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
715                                    closure->cancellable, on_get_secrets_complete,
716                                    g_object_ref (res));
717         }
718
719         g_object_unref (res);
720 }
721
722 /**
723  * secret_service_get_secret_for_dbus_path:
724  * @self: the secret service
725  * @item_path: the D-Bus path to item to retrieve secret for
726  * @cancellable: optional cancellation object
727  * @callback: called when the operation completes
728  * @user_data: data to pass to the callback
729  *
730  * Get the secret value for an secret item stored in the service.
731  *
732  * The item is represented by its D-Bus object path. If you already have a
733  * #SecretItem proxy object, use use secret_item_get_secret() to more simply
734  * get its secret value.
735  *
736  * This function returns immediately and completes asynchronously.
737  */
738 void
739 secret_service_get_secret_for_dbus_path (SecretService *self,
740                                          const gchar *item_path,
741                                          GCancellable *cancellable,
742                                          GAsyncReadyCallback callback,
743                                          gpointer user_data)
744 {
745         GSimpleAsyncResult *res;
746         GetClosure *closure;
747
748         g_return_if_fail (SECRET_IS_SERVICE (self));
749         g_return_if_fail (item_path != NULL);
750         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
751
752         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
753                                          secret_service_get_secret_for_dbus_path);
754
755         closure = g_slice_new0 (GetClosure);
756         closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
757         closure->in = g_variant_ref_sink (g_variant_new_objv (&item_path, 1));
758         g_simple_async_result_set_op_res_gpointer (res, closure, get_closure_free);
759
760         secret_service_ensure_session (self, cancellable,
761                                        on_get_secrets_session,
762                                        g_object_ref (res));
763
764         g_object_unref (res);
765 }
766
767 /**
768  * secret_service_get_secret_for_dbus_path_finish:
769  * @self: the secret service
770  * @result: asynchronous result passed to callback
771  * @error: location to place an error on failure
772  *
773  * Complete asynchronous operation to get the secret value for an
774  * secret item stored in the service.
775  *
776  * Will return %NULL if the item is locked.
777  *
778  * Returns: (transfer full) (allow-none): the newly allocated secret value
779  *          for the item, which should be released with secret_value_unref()
780  */
781 SecretValue *
782 secret_service_get_secret_for_dbus_path_finish (SecretService *self,
783                                                 GAsyncResult *result,
784                                                 GError **error)
785 {
786         GSimpleAsyncResult *res;
787         GetClosure *closure;
788
789         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
790         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
791                               secret_service_get_secret_for_dbus_path), NULL);
792         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
793
794         res = G_SIMPLE_ASYNC_RESULT (result);
795         if (_secret_util_propagate_error (res, error))
796                 return NULL;
797
798         closure = g_simple_async_result_get_op_res_gpointer (res);
799         return _secret_service_decode_get_secrets_first (self, closure->out);
800 }
801
802 /**
803  * secret_service_get_secret_for_dbus_path_sync:
804  * @self: the secret service
805  * @item_path: the D-Bus path to item to retrieve secret for
806  * @cancellable: optional cancellation object
807  * @error: location to place an error on failure
808  *
809  * Get the secret value for an secret item stored in the service.
810  *
811  * The item is represented by its D-Bus object path. If you already have a
812  * #SecretItem proxy object, use use secret_item_load_secret_sync() to more simply
813  * get its secret value.
814  *
815  * This method may block indefinitely and should not be used in user interface
816  * threads.
817  *
818  * Will return %NULL if the item is locked.
819  *
820  * Returns: (transfer full) (allow-none): the newly allocated secret value
821  *          for the item, which should be released with secret_value_unref()
822  */
823 SecretValue *
824 secret_service_get_secret_for_dbus_path_sync (SecretService *self,
825                                               const gchar *item_path,
826                                               GCancellable *cancellable,
827                                               GError **error)
828 {
829         SecretSync *sync;
830         SecretValue *value;
831
832         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
833         g_return_val_if_fail (item_path != NULL, NULL);
834         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
835         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
836
837         sync = _secret_sync_new ();
838         g_main_context_push_thread_default (sync->context);
839
840         secret_service_get_secret_for_dbus_path (self, item_path, cancellable,
841                                                  _secret_sync_on_result, sync);
842
843         g_main_loop_run (sync->loop);
844
845         value = secret_service_get_secret_for_dbus_path_finish (self, sync->result, error);
846
847         g_main_context_pop_thread_default (sync->context);
848         _secret_sync_free (sync);
849
850         return value;
851 }
852
853 /**
854  * secret_service_get_secrets_for_dbus_paths:
855  * @self: the secret service
856  * @item_paths: the D-Bus paths to items to retrieve secrets for
857  * @cancellable: optional cancellation object
858  * @callback: called when the operation completes
859  * @user_data: data to pass to the callback
860  *
861  * Get the secret values for an secret items stored in the service.
862  *
863  * The items are represented by their D-Bus object paths. If you already have
864  * #SecretItem proxy objects, use use secret_item_load_secrets() to more simply
865  * get their secret values.
866  *
867  * This function returns immediately and completes asynchronously.
868  */
869 void
870 secret_service_get_secrets_for_dbus_paths (SecretService *self,
871                                            const gchar **item_paths,
872                                            GCancellable *cancellable,
873                                            GAsyncReadyCallback callback,
874                                            gpointer user_data)
875 {
876         GSimpleAsyncResult *res;
877         GetClosure *closure;
878
879         g_return_if_fail (SECRET_IS_SERVICE (self));
880         g_return_if_fail (item_paths != NULL);
881         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
882
883         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
884                                          secret_service_get_secret_for_dbus_path);
885
886         closure = g_slice_new0 (GetClosure);
887         closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
888         closure->in = g_variant_ref_sink (g_variant_new_objv (item_paths, -1));
889         g_simple_async_result_set_op_res_gpointer (res, closure, get_closure_free);
890
891         secret_service_ensure_session (self, cancellable,
892                                        on_get_secrets_session,
893                                        g_object_ref (res));
894
895         g_object_unref (res);
896 }
897
898 /**
899  * secret_service_get_secrets_for_dbus_paths_finish:
900  * @self: the secret service
901  * @result: asynchronous result passed to callback
902  * @error: location to place an error on failure
903  *
904  * Complete asynchronous operation to get the secret values for an
905  * secret items stored in the service.
906  *
907  * Items that are locked will not be included the results.
908  *
909  * Returns: (transfer full) (element-type utf8 SecretUnstable.Value): a newly
910  *          allocated hash table of item_path keys to #SecretValue
911  *          values.
912  */
913 GHashTable *
914 secret_service_get_secrets_for_dbus_paths_finish (SecretService *self,
915                                                   GAsyncResult *result,
916                                                   GError **error)
917 {
918         GSimpleAsyncResult *res;
919         GetClosure *closure;
920
921         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
922         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
923                               secret_service_get_secret_for_dbus_path), NULL);
924         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
925
926         res = G_SIMPLE_ASYNC_RESULT (result);
927         if (_secret_util_propagate_error (res, error))
928                 return NULL;
929
930         closure = g_simple_async_result_get_op_res_gpointer (res);
931         return _secret_service_decode_get_secrets_all (self, closure->out);
932 }
933
934 /**
935  * secret_service_get_secrets_for_dbus_paths_sync:
936  * @self: the secret service
937  * @item_paths: the D-Bus paths to items to retrieve secrets for
938  * @cancellable: optional cancellation object
939  * @error: location to place an error on failure
940  *
941  * Get the secret values for an secret items stored in the service.
942  *
943  * The items are represented by their D-Bus object paths. If you already have
944  * #SecretItem proxy objects, use use secret_item_load_secrets_sync() to more
945  * simply get their secret values.
946  *
947  * This method may block indefinitely and should not be used in user interface
948  * threads.
949  *
950  * Items that are locked will not be included the results.
951  *
952  * Returns: (transfer full) (element-type utf8 SecretUnstable.Value): a newly
953  *          allocated hash table of item_path keys to #SecretValue
954  *          values.
955  */
956 GHashTable *
957 secret_service_get_secrets_for_dbus_paths_sync (SecretService *self,
958                                                 const gchar **item_paths,
959                                                 GCancellable *cancellable,
960                                                 GError **error)
961 {
962         SecretSync *sync;
963         GHashTable *secrets;
964
965         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
966         g_return_val_if_fail (item_paths != NULL, NULL);
967         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
968         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
969
970         sync = _secret_sync_new ();
971         g_main_context_push_thread_default (sync->context);
972
973         secret_service_get_secrets_for_dbus_paths (self, item_paths, cancellable,
974                                                    _secret_sync_on_result, sync);
975
976         g_main_loop_run (sync->loop);
977
978         secrets = secret_service_get_secrets_for_dbus_paths_finish (self, sync->result, error);
979
980         g_main_context_pop_thread_default (sync->context);
981         _secret_sync_free (sync);
982
983         return secrets;
984 }
985
986
987 typedef struct {
988         GCancellable *cancellable;
989         SecretPrompt *prompt;
990         GPtrArray *xlocked;
991 } XlockClosure;
992
993 static void
994 xlock_closure_free (gpointer data)
995 {
996         XlockClosure *closure = data;
997         g_clear_object (&closure->cancellable);
998         g_clear_object (&closure->prompt);
999         if (closure->xlocked)
1000                 g_ptr_array_unref (closure->xlocked);
1001         g_slice_free (XlockClosure, closure);
1002 }
1003
1004 static void
1005 on_xlock_prompted (GObject *source,
1006                    GAsyncResult *result,
1007                    gpointer user_data)
1008 {
1009         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1010         XlockClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1011         SecretService *self = SECRET_SERVICE (source);
1012         GError *error = NULL;
1013         GVariantIter iter;
1014         GVariant *retval;
1015         gchar *path;
1016
1017         retval = secret_service_prompt_finish (self, result, &error);
1018         if (error != NULL)
1019                 g_simple_async_result_take_error (res, error);
1020
1021         if (retval != NULL) {
1022                 g_variant_iter_init (&iter, retval);
1023                 while (g_variant_iter_loop (&iter, "o", &path))
1024                         g_ptr_array_add (closure->xlocked, g_strdup (path));
1025                 g_variant_unref (retval);
1026         }
1027
1028         g_simple_async_result_complete (res);
1029         g_object_unref (res);
1030 }
1031
1032 static void
1033 on_xlock_called (GObject *source,
1034                  GAsyncResult *result,
1035                  gpointer user_data)
1036 {
1037         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1038         XlockClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1039         SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
1040         const gchar *prompt = NULL;
1041         gchar **xlocked = NULL;
1042         GError *error = NULL;
1043         GVariant *retval;
1044         guint i;
1045
1046         retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
1047         if (error != NULL) {
1048                 g_simple_async_result_take_error (res, error);
1049                 g_simple_async_result_complete (res);
1050
1051         } else {
1052                 g_variant_get (retval, "(^ao&o)", &xlocked, &prompt);
1053
1054                 if (_secret_util_empty_path (prompt)) {
1055                         for (i = 0; xlocked[i]; i++)
1056                                 g_ptr_array_add (closure->xlocked, g_strdup (xlocked[i]));
1057                         g_simple_async_result_complete (res);
1058
1059                 } else {
1060                         closure->prompt = _secret_prompt_instance (self, prompt);
1061                         secret_service_prompt (self, closure->prompt, G_VARIANT_TYPE ("ao"),
1062                                                closure->cancellable, on_xlock_prompted, g_object_ref (res));
1063                 }
1064
1065                 g_strfreev (xlocked);
1066                 g_variant_unref (retval);
1067         }
1068
1069         g_object_unref (self);
1070         g_object_unref (res);
1071 }
1072
1073 void
1074 _secret_service_xlock_paths_async (SecretService *self,
1075                                    const gchar *method,
1076                                    const gchar **paths,
1077                                    GCancellable *cancellable,
1078                                    GAsyncReadyCallback callback,
1079                                    gpointer user_data)
1080 {
1081         GSimpleAsyncResult *res;
1082         XlockClosure *closure;
1083
1084         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1085                                          _secret_service_xlock_paths_async);
1086         closure = g_slice_new0 (XlockClosure);
1087         closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
1088         closure->xlocked = g_ptr_array_new_with_free_func (g_free);
1089         g_simple_async_result_set_op_res_gpointer (res, closure, xlock_closure_free);
1090
1091         g_dbus_proxy_call (G_DBUS_PROXY (self), method,
1092                            g_variant_new ("(@ao)", g_variant_new_objv (paths, -1)),
1093                            G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
1094                            cancellable, on_xlock_called, g_object_ref (res));
1095
1096         g_object_unref (res);
1097 }
1098
1099 gint
1100 _secret_service_xlock_paths_finish (SecretService *self,
1101                                     GAsyncResult *result,
1102                                     gchar ***xlocked,
1103                                     GError **error)
1104 {
1105         GSimpleAsyncResult *res;
1106         XlockClosure *closure;
1107         gint count;
1108
1109         res = G_SIMPLE_ASYNC_RESULT (result);
1110         if (_secret_util_propagate_error (res, error))
1111                 return -1;
1112
1113         closure = g_simple_async_result_get_op_res_gpointer (res);
1114         count = closure->xlocked->len;
1115
1116         if (xlocked != NULL) {
1117                 g_ptr_array_add (closure->xlocked, NULL);
1118                 *xlocked = (gchar **)g_ptr_array_free (closure->xlocked, FALSE);
1119                 closure->xlocked = NULL;
1120         }
1121
1122         return count;
1123 }
1124
1125 /**
1126  * secret_service_lock_dbus_paths_sync:
1127  * @self: the secret service
1128  * @paths: the D-Bus object paths of the items or collections to lock
1129  * @cancellable: optional cancellation object
1130  * @locked: (out) (array zero-terminated=1) (transfer full) (allow-none):
1131  *          location to place array of D-Bus paths of items or collections
1132  *          that were locked
1133  * @error: location to place an error on failure
1134  *
1135  * Lock items or collections in the secret service.
1136  *
1137  * The items or collections are represented by their D-Bus object paths. If you
1138  * already have #SecretItem and #SecretCollection proxy objects, use use
1139  * secret_service_lock_sync() instead.
1140  *
1141  * The secret service may not be able to lock items individually, and may
1142  * lock an entire collection instead.
1143  *
1144  * This method may block indefinitely and should not be used in user
1145  * interface threads. The secret service may prompt the user.
1146  * secret_service_prompt() will be used to handle any prompts that show up.
1147  *
1148  * Returns: the number of items or collections that were locked
1149  */
1150 gint
1151 secret_service_lock_dbus_paths_sync (SecretService *self,
1152                                      const gchar **paths,
1153                                      GCancellable *cancellable,
1154                                      gchar ***locked,
1155                                      GError **error)
1156 {
1157         SecretSync *sync;
1158         gint count;
1159
1160         g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
1161         g_return_val_if_fail (paths != NULL, -1);
1162         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
1163         g_return_val_if_fail (error == NULL || *error == NULL, -1);
1164
1165         sync = _secret_sync_new ();
1166         g_main_context_push_thread_default (sync->context);
1167
1168         secret_service_lock_dbus_paths (self, paths, cancellable,
1169                                         _secret_sync_on_result, sync);
1170
1171         g_main_loop_run (sync->loop);
1172
1173         count = secret_service_lock_dbus_paths_finish (self, sync->result,
1174                                                        locked, error);
1175
1176         g_main_context_pop_thread_default (sync->context);
1177         _secret_sync_free (sync);
1178
1179         return count;
1180 }
1181
1182 /**
1183  * secret_service_lock_dbus_paths:
1184  * @self: the secret service
1185  * @paths: the D-Bus paths for items or collections to lock
1186  * @cancellable: optional cancellation object
1187  * @callback: called when the operation completes
1188  * @user_data: data to pass to the callback
1189  *
1190  * Lock items or collections in the secret service.
1191  *
1192  * The items or collections are represented by their D-Bus object paths. If you
1193  * already have #SecretItem and #SecretCollection proxy objects, use use
1194  * secret_service_lock() instead.
1195  *
1196  * The secret service may not be able to lock items individually, and may
1197  * lock an entire collection instead.
1198  *
1199  * This method returns immediately and completes asynchronously. The secret
1200  * service may prompt the user. secret_service_prompt() will be used to handle
1201  * any prompts that show up.
1202  */
1203 void
1204 secret_service_lock_dbus_paths (SecretService *self,
1205                                 const gchar **paths,
1206                                 GCancellable *cancellable,
1207                                 GAsyncReadyCallback callback,
1208                                 gpointer user_data)
1209 {
1210         g_return_if_fail (SECRET_IS_SERVICE (self));
1211         g_return_if_fail (paths != NULL);
1212         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1213
1214         _secret_service_xlock_paths_async (self, "Lock", paths, cancellable,
1215                                            callback, user_data);
1216 }
1217
1218 /**
1219  * secret_service_lock_dbus_paths_finish:
1220  * @self: the secret service
1221  * @result: asynchronous result passed to the callback
1222  * @locked: (out) (array zero-terminated=1) (transfer full) (allow-none):
1223  *          location to place array of D-Bus paths of items or collections
1224  *          that were locked
1225  * @error: location to place an error on failure
1226  *
1227  * Complete asynchronous operation to lock items or collections in the secret
1228  * service.
1229  *
1230  * The secret service may not be able to lock items individually, and may
1231  * lock an entire collection instead.
1232  *
1233  * Returns: the number of items or collections that were locked
1234  */
1235 gint
1236 secret_service_lock_dbus_paths_finish (SecretService *self,
1237                                        GAsyncResult *result,
1238                                        gchar ***locked,
1239                                        GError **error)
1240 {
1241         g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
1242         g_return_val_if_fail (locked != NULL, -1);
1243         g_return_val_if_fail (error == NULL || *error == NULL, -1);
1244
1245         return _secret_service_xlock_paths_finish (self, result, locked, error);
1246 }
1247
1248 /**
1249  * secret_service_unlock_dbus_paths_sync:
1250  * @self: the secret service
1251  * @paths: the D-Bus object paths of the items or collections to unlock
1252  * @cancellable: optional cancellation object
1253  * @unlocked: (out) (array zero-terminated=1) (transfer full) (allow-none):
1254  *            location to place array of D-Bus paths of items or collections
1255  *            that were unlocked
1256  * @error: location to place an error on failure
1257  *
1258  * Unlock items or collections in the secret service.
1259  *
1260  * The items or collections are represented by their D-Bus object paths. If you
1261  * already have #SecretItem and #SecretCollection proxy objects, use use
1262  * secret_service_unlock_sync() instead.
1263  *
1264  * The secret service may not be able to unlock items individually, and may
1265  * unlock an entire collection instead.
1266  *
1267  * This method may block indefinitely and should not be used in user
1268  * interface threads. The secret service may prompt the user.
1269  * secret_service_prompt() will be used to handle any prompts that show up.
1270  *
1271  * Returns: the number of items or collections that were unlocked
1272  */
1273 gint
1274 secret_service_unlock_dbus_paths_sync (SecretService *self,
1275                                        const gchar **paths,
1276                                        GCancellable *cancellable,
1277                                        gchar ***unlocked,
1278                                        GError **error)
1279 {
1280         SecretSync *sync;
1281         gint count;
1282
1283         g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
1284         g_return_val_if_fail (paths != NULL, -1);
1285         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
1286         g_return_val_if_fail (error == NULL || *error == NULL, -1);
1287
1288         sync = _secret_sync_new ();
1289         g_main_context_push_thread_default (sync->context);
1290
1291         secret_service_unlock_dbus_paths (self, paths, cancellable,
1292                                           _secret_sync_on_result, sync);
1293
1294         g_main_loop_run (sync->loop);
1295
1296         count = secret_service_unlock_dbus_paths_finish (self, sync->result,
1297                                                          unlocked, error);
1298
1299         g_main_context_pop_thread_default (sync->context);
1300         _secret_sync_free (sync);
1301
1302         return count;
1303 }
1304
1305 /**
1306  * secret_service_unlock_dbus_paths:
1307  * @self: the secret service
1308  * @paths: the D-Bus paths for items or collections to unlock
1309  * @cancellable: optional cancellation object
1310  * @callback: called when the operation completes
1311  * @user_data: data to pass to the callback
1312  *
1313  * Unlock items or collections in the secret service.
1314  *
1315  * The items or collections are represented by their D-Bus object paths. If you
1316  * already have #SecretItem and #SecretCollection proxy objects, use use
1317  * secret_service_unlock() instead.
1318  *
1319  * The secret service may not be able to unlock items individually, and may
1320  * unlock an entire collection instead.
1321  *
1322  * This method returns immediately and completes asynchronously. The secret
1323  * service may prompt the user. secret_service_prompt() will be used to handle
1324  * any prompts that show up.
1325  */
1326 void
1327 secret_service_unlock_dbus_paths (SecretService *self,
1328                                   const gchar **paths,
1329                                   GCancellable *cancellable,
1330                                   GAsyncReadyCallback callback,
1331                                   gpointer user_data)
1332 {
1333         g_return_if_fail (SECRET_IS_SERVICE (self));
1334         g_return_if_fail (paths != NULL);
1335         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1336
1337         _secret_service_xlock_paths_async (self, "Unlock",
1338                                            paths, cancellable,
1339                                            callback, user_data);
1340 }
1341
1342 /**
1343  * secret_service_unlock_dbus_paths_finish:
1344  * @self: the secret service
1345  * @result: asynchronous result passed to the callback
1346  * @unlocked: (out) (array zero-terminated=1) (transfer full) (allow-none):
1347  *            location to place array of D-Bus paths of items or collections
1348  *            that were unlocked
1349  * @error: location to place an error on failure
1350  *
1351  * Complete asynchronous operation to unlock items or collections in the secret
1352  * service.
1353  *
1354  * The secret service may not be able to unlock items individually, and may
1355  * unlock an entire collection instead.
1356  *
1357  * Returns: the number of items or collections that were unlocked
1358  */
1359 gint
1360 secret_service_unlock_dbus_paths_finish (SecretService *self,
1361                                          GAsyncResult *result,
1362                                          gchar ***unlocked,
1363                                          GError **error)
1364 {
1365         g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
1366         g_return_val_if_fail (error == NULL || *error == NULL, -1);
1367
1368         return _secret_service_xlock_paths_finish (self, result,
1369                                                    unlocked, error);
1370 }
1371
1372 typedef struct {
1373         GCancellable *cancellable;
1374         SecretPrompt *prompt;
1375         gboolean deleted;
1376 } DeleteClosure;
1377
1378 static void
1379 delete_closure_free (gpointer data)
1380 {
1381         DeleteClosure *closure = data;
1382         g_clear_object (&closure->prompt);
1383         g_clear_object (&closure->cancellable);
1384         g_slice_free (DeleteClosure, closure);
1385 }
1386
1387 static void
1388 on_delete_prompted (GObject *source,
1389                     GAsyncResult *result,
1390                     gpointer user_data)
1391 {
1392         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1393         DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1394         GError *error = NULL;
1395         GVariant *retval;
1396
1397         retval = secret_service_prompt_finish (SECRET_SERVICE (source), result,
1398                                                &error);
1399
1400         if (error == NULL)
1401                 closure->deleted = TRUE;
1402         else
1403                 g_simple_async_result_take_error (res, error);
1404         if (retval != NULL)
1405                 g_variant_unref (retval);
1406         g_simple_async_result_complete (res);
1407         g_object_unref (res);
1408 }
1409
1410 static void
1411 on_delete_complete (GObject *source,
1412                     GAsyncResult *result,
1413                     gpointer user_data)
1414 {
1415         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1416         DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1417         SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
1418         const gchar *prompt_path;
1419         GError *error = NULL;
1420         GVariant *retval;
1421
1422         retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
1423         if (error == NULL) {
1424                 g_variant_get (retval, "(&o)", &prompt_path);
1425
1426                 if (_secret_util_empty_path (prompt_path)) {
1427                         closure->deleted = TRUE;
1428                         g_simple_async_result_complete (res);
1429
1430                 } else {
1431                         closure->prompt = _secret_prompt_instance (self, prompt_path);
1432
1433                         secret_service_prompt (self, closure->prompt, NULL,
1434                                                closure->cancellable,
1435                                                on_delete_prompted,
1436                                                g_object_ref (res));
1437                 }
1438
1439                 g_variant_unref (retval);
1440
1441         } else {
1442                 g_simple_async_result_take_error (res, error);
1443                 g_simple_async_result_complete (res);
1444         }
1445
1446         g_object_unref (self);
1447         g_object_unref (res);
1448 }
1449
1450 void
1451 _secret_service_delete_path (SecretService *self,
1452                              const gchar *object_path,
1453                              gboolean is_an_item,
1454                              GCancellable *cancellable,
1455                              GAsyncReadyCallback callback,
1456                              gpointer user_data)
1457 {
1458         GSimpleAsyncResult *res;
1459         DeleteClosure *closure;
1460
1461         g_return_if_fail (SECRET_IS_SERVICE (self));
1462         g_return_if_fail (object_path != NULL);
1463         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1464
1465         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1466                                          _secret_service_delete_path);
1467         closure = g_slice_new0 (DeleteClosure);
1468         closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1469         g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free);
1470
1471         g_dbus_connection_call (g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
1472                                 g_dbus_proxy_get_name (G_DBUS_PROXY (self)), object_path,
1473                                 is_an_item ? SECRET_ITEM_INTERFACE : SECRET_COLLECTION_INTERFACE,
1474                                 "Delete", g_variant_new ("()"), G_VARIANT_TYPE ("(o)"),
1475                                 G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
1476                                 cancellable, on_delete_complete, g_object_ref (res));
1477
1478         g_object_unref (res);
1479 }
1480
1481 gboolean
1482 _secret_service_delete_path_finish (SecretService *self,
1483                                     GAsyncResult *result,
1484                                     GError **error)
1485 {
1486         GSimpleAsyncResult *res;
1487         DeleteClosure *closure;
1488
1489         g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
1490         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1491         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1492                               _secret_service_delete_path), FALSE);
1493
1494         res = G_SIMPLE_ASYNC_RESULT (result);
1495         if (_secret_util_propagate_error (res, error))
1496                 return FALSE;
1497
1498         closure = g_simple_async_result_get_op_res_gpointer (res);
1499         return closure->deleted;
1500 }
1501
1502 /**
1503  * secret_service_delete_item_dbus_path:
1504  * @self: the secret service
1505  * @item_path: the D-Bus path of item to delete
1506  * @cancellable: optional cancellation object
1507  * @callback: called when the operation completes
1508  * @user_data: data to be passed to the callback
1509  *
1510  * Delete a secret item from the secret service.
1511  *
1512  * The item is represented by its D-Bus object path. If you already have a
1513  * #SecretItem proxy objects, use use secret_item_delete() instead.
1514  *
1515  * This method will return immediately and complete asynchronously.
1516  */
1517 void
1518 secret_service_delete_item_dbus_path (SecretService *self,
1519                                       const gchar *item_path,
1520                                       GCancellable *cancellable,
1521                                       GAsyncReadyCallback callback,
1522                                       gpointer user_data)
1523 {
1524         g_return_if_fail (SECRET_IS_SERVICE (self));
1525         g_return_if_fail (item_path != NULL);
1526         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1527
1528         _secret_service_delete_path (self, item_path, TRUE, cancellable, callback, user_data);
1529 }
1530
1531 /**
1532  * secret_service_delete_item_dbus_path_finish:
1533  * @self: the secret service
1534  * @result: the asynchronous result passed to the callback
1535  * @error: location to place an error on failure
1536  *
1537  * Complete an asynchronous operation to delete a secret item from the secret
1538  * service.
1539  *
1540  * Returns: whether the deletion was successful or not
1541  */
1542 gboolean
1543 secret_service_delete_item_dbus_path_finish (SecretService *self,
1544                                              GAsyncResult *result,
1545                                              GError **error)
1546 {
1547         g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
1548         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1549         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1550                               _secret_service_delete_path), FALSE);
1551
1552         return _secret_service_delete_path_finish (self, result, error);
1553 }
1554
1555 /**
1556  * secret_service_delete_item_dbus_path_sync:
1557  * @self: the secret service
1558  * @item_path: the D-Bus path of item to delete
1559  * @cancellable: optional cancellation object
1560  * @error: location to place an error on failure
1561  *
1562  * Delete a secret item from the secret service.
1563  *
1564  * The item is represented by its D-Bus object path. If you already have a
1565  * #SecretItem proxy objects, use use secret_item_delete_sync() instead.
1566  *
1567  * This method may block indefinitely and should not be used in user interface
1568  * threads.
1569  *
1570  * Returns: whether the deletion was successful or not
1571  */
1572 gboolean
1573 secret_service_delete_item_dbus_path_sync (SecretService *self,
1574                                            const gchar *item_path,
1575                                            GCancellable *cancellable,
1576                                            GError **error)
1577 {
1578         SecretSync *sync;
1579         gboolean result;
1580
1581         g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
1582         g_return_val_if_fail (item_path != NULL, FALSE);
1583         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1584         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1585
1586         sync = _secret_sync_new ();
1587         g_main_context_push_thread_default (sync->context);
1588
1589         secret_service_delete_item_dbus_path (self, item_path, cancellable,
1590                                               _secret_sync_on_result, sync);
1591
1592         g_main_loop_run (sync->loop);
1593
1594         result = secret_service_delete_item_dbus_path_finish (self, sync->result, error);
1595
1596         g_main_context_pop_thread_default (sync->context);
1597         _secret_sync_free (sync);
1598
1599         return result;
1600 }
1601
1602 typedef struct {
1603         GCancellable *cancellable;
1604         SecretPrompt *prompt;
1605         gchar *collection_path;
1606 } CollectionClosure;
1607
1608 static void
1609 collection_closure_free (gpointer data)
1610 {
1611         CollectionClosure *closure = data;
1612         g_clear_object (&closure->cancellable);
1613         g_clear_object (&closure->prompt);
1614         g_slice_free (CollectionClosure, closure);
1615 }
1616
1617 static void
1618 on_create_collection_prompt (GObject *source,
1619                              GAsyncResult *result,
1620                              gpointer user_data)
1621 {
1622         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1623         CollectionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1624         GError *error = NULL;
1625         GVariant *value;
1626
1627         value = secret_service_prompt_finish (SECRET_SERVICE (source), result, &error);
1628         if (error != NULL)
1629                 g_simple_async_result_take_error (res, error);
1630         if (value != NULL) {
1631                 closure->collection_path = g_variant_dup_string (value, NULL);
1632                 g_variant_unref (value);
1633         }
1634
1635         g_simple_async_result_complete (res);
1636         g_object_unref (res);
1637 }
1638
1639 static void
1640 on_create_collection_called (GObject *source,
1641                              GAsyncResult *result,
1642                              gpointer user_data)
1643 {
1644         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1645         CollectionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1646         SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
1647         const gchar *prompt_path = NULL;
1648         const gchar *collection_path = NULL;
1649         GError *error = NULL;
1650         GVariant *retval;
1651
1652         retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
1653         if (error == NULL) {
1654                 g_variant_get (retval, "(&o&o)", &collection_path, &prompt_path);
1655                 if (!_secret_util_empty_path (prompt_path)) {
1656                         closure->prompt = _secret_prompt_instance (self, prompt_path);
1657                         secret_service_prompt (self, closure->prompt, G_VARIANT_TYPE ("o"),
1658                                                closure->cancellable, on_create_collection_prompt,
1659                                                g_object_ref (res));
1660
1661                 } else {
1662                         closure->collection_path = g_strdup (collection_path);
1663                         g_simple_async_result_complete (res);
1664                 }
1665
1666                 g_variant_unref (retval);
1667
1668         } else {
1669                 g_simple_async_result_take_error (res, error);
1670                 g_simple_async_result_complete (res);
1671         }
1672
1673         g_object_unref (self);
1674         g_object_unref (res);
1675 }
1676
1677 /**
1678  * secret_service_create_collection_dbus_path:
1679  * @self: a secret service object
1680  * @properties: (element-type utf8 GLib.Variant): hash table of properties for
1681  *              the new collection
1682  * @alias: (allow-none): an alias to check for before creating the new
1683  *         collection, or to assign to the new collection
1684  * @flags: not currently used
1685  * @cancellable: optional cancellation object
1686  * @callback: called when the operation completes
1687  * @user_data: data to be passed to the callback
1688  *
1689  * Create a new collection in the secret service, and return its path.
1690  *
1691  * Using this method requires that you setup a correct hash table of D-Bus
1692  * properties for the new collection. You may prefer to use
1693  * secret_collection_create() which does handles this for you.
1694  *
1695  * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1696  * default collection to store items in). This allows other applications to
1697  * easily identify and share a collection. If a collection with the @alias
1698  * already exists, then instead of creating a new collection, the existing
1699  * collection will be returned. If no collection with this alias exists, then a
1700  * new collection will be created and this alias will be assigned to it.
1701  *
1702  * @properties is a set of properties for the new collection. The keys in the
1703  * hash table should be interface.property strings like
1704  * <literal>org.freedesktop.Secret.Collection.Label</literal>. The values
1705  * in the hash table should be #GVariant values of the properties.
1706  *
1707  * If you wish to have a
1708  *
1709  * This method will return immediately and complete asynchronously. The secret
1710  * service may prompt the user. secret_service_prompt() will be used to handle
1711  * any prompts that are required.
1712  */
1713 void
1714 secret_service_create_collection_dbus_path (SecretService *self,
1715                                             GHashTable *properties,
1716                                             const gchar *alias,
1717                                             SecretCollectionCreateFlags flags,
1718                                             GCancellable *cancellable,
1719                                             GAsyncReadyCallback callback,
1720                                             gpointer user_data)
1721 {
1722         GSimpleAsyncResult *res;
1723         CollectionClosure *closure;
1724         GVariant *params;
1725         GVariant *props;
1726         GDBusProxy *proxy;
1727
1728         g_return_if_fail (SECRET_IS_SERVICE (self));
1729         g_return_if_fail (properties != NULL);
1730         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1731
1732         if (alias == NULL)
1733                 alias = "";
1734
1735         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1736                                          secret_service_create_collection_dbus_path);
1737         closure = g_slice_new0 (CollectionClosure);
1738         closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1739         g_simple_async_result_set_op_res_gpointer (res, closure, collection_closure_free);
1740
1741         props = _secret_util_variant_for_properties (properties);
1742         params = g_variant_new ("(@a{sv}s)", props, alias);
1743         proxy = G_DBUS_PROXY (self);
1744
1745         g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
1746                                 g_dbus_proxy_get_name (proxy),
1747                                 g_dbus_proxy_get_object_path (proxy),
1748                                 SECRET_SERVICE_INTERFACE,
1749                                 "CreateCollection", params, G_VARIANT_TYPE ("(oo)"),
1750                                 G_DBUS_CALL_FLAGS_NONE, -1,
1751                                 closure->cancellable,
1752                                 on_create_collection_called,
1753                                 g_object_ref (res));
1754
1755         g_object_unref (res);
1756
1757 }
1758
1759 /**
1760  * secret_service_create_collection_dbus_path_finish:
1761  * @self: a secret service object
1762  * @result: the asynchronous result passed to the callback
1763  * @error: location to place an error on failure
1764  *
1765  * Finish asynchronous operation to create a new collection in the secret
1766  * service.
1767  *
1768  * Returns: (transfer full): a new string containing the D-Bus object path
1769  *          of the collection
1770  */
1771 gchar *
1772 secret_service_create_collection_dbus_path_finish (SecretService *self,
1773                                                    GAsyncResult *result,
1774                                                    GError **error)
1775 {
1776         GSimpleAsyncResult *res;
1777         CollectionClosure *closure;
1778         gchar *path;
1779
1780         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1781                               secret_service_create_collection_dbus_path), NULL);
1782         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1783
1784         res = G_SIMPLE_ASYNC_RESULT (result);
1785
1786         if (_secret_util_propagate_error (res, error))
1787                 return NULL;
1788
1789         closure = g_simple_async_result_get_op_res_gpointer (res);
1790         path = closure->collection_path;
1791         closure->collection_path = NULL;
1792         return path;
1793 }
1794
1795 /**
1796  * secret_service_create_collection_dbus_path_sync:
1797  * @self: a secret service object
1798  * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
1799  *              for the new collection
1800  * @alias: (allow-none): an alias to check for before creating the new
1801  *         collection, or to assign to the new collection
1802  * @flags: not currently used
1803  * @cancellable: optional cancellation object
1804  * @error: location to place an error on failure
1805  *
1806  * Create a new collection in the secret service and return its path.
1807  *
1808  * Using this method requires that you setup a correct hash table of D-Bus
1809  * properties for the new collection. You may prefer to use
1810  * secret_collection_create() which does handles this for you.
1811  *
1812  * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1813  * default collection to store items in). This allows other applications to
1814  * easily identify and share a collection. If a collection with the @alias
1815  * already exists, then instead of creating a new collection, the existing
1816  * collection will be returned. If no collection with this alias exists, then
1817  * a new collection will be created and this alias will be assigned to it.
1818  *
1819  * @properties is a set of properties for the new collection. The keys in the
1820  * hash table should be interface.property strings like
1821  * <literal>org.freedesktop.Secret.Collection.Label</literal>. The values
1822  * in the hash table should be #GVariant values of the properties.
1823  *
1824  * This method may block indefinitely and should not be used in user interface
1825  * threads. The secret service may prompt the user. secret_service_prompt()
1826  * will be used to handle any prompts that are required.
1827  *
1828  * Returns: (transfer full): a new string containing the D-Bus object path
1829  *          of the collection
1830  */
1831 gchar *
1832 secret_service_create_collection_dbus_path_sync (SecretService *self,
1833                                                  GHashTable *properties,
1834                                                  const gchar *alias,
1835                                                  SecretCollectionCreateFlags flags,
1836                                                  GCancellable *cancellable,
1837                                                  GError **error)
1838 {
1839         SecretSync *sync;
1840         gchar *path;
1841
1842         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
1843         g_return_val_if_fail (properties != NULL, NULL);
1844         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1845         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1846
1847         sync = _secret_sync_new ();
1848         g_main_context_push_thread_default (sync->context);
1849
1850         secret_service_create_collection_dbus_path (self, properties, alias, flags, cancellable,
1851                                                     _secret_sync_on_result, sync);
1852
1853         g_main_loop_run (sync->loop);
1854
1855         path = secret_service_create_collection_dbus_path_finish (self, sync->result, error);
1856
1857         g_main_context_pop_thread_default (sync->context);
1858         _secret_sync_free (sync);
1859
1860         return path;
1861 }
1862
1863 typedef struct {
1864         GCancellable *cancellable;
1865         GVariant *properties;
1866         SecretValue *value;
1867         gboolean replace;
1868         gchar *collection_path;
1869         SecretPrompt *prompt;
1870         gchar *item_path;
1871 } ItemClosure;
1872
1873 static void
1874 item_closure_free (gpointer data)
1875 {
1876         ItemClosure *closure = data;
1877         g_variant_unref (closure->properties);
1878         secret_value_unref (closure->value);
1879         g_clear_object (&closure->cancellable);
1880         g_free (closure->collection_path);
1881         g_clear_object (&closure->prompt);
1882         g_slice_free (ItemClosure, closure);
1883 }
1884
1885 static void
1886 on_create_item_prompt (GObject *source,
1887                        GAsyncResult *result,
1888                        gpointer user_data)
1889 {
1890         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1891         ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1892         GError *error = NULL;
1893         GVariant *value;
1894
1895         value = secret_service_prompt_finish (SECRET_SERVICE (source), result, &error);
1896         if (error != NULL)
1897                 g_simple_async_result_take_error (res, error);
1898         if (value != NULL) {
1899                 closure->item_path = g_variant_dup_string (value, NULL);
1900                 g_variant_unref (value);
1901         }
1902
1903         g_simple_async_result_complete (res);
1904         g_object_unref (res);
1905 }
1906
1907 static void
1908 on_create_item_called (GObject *source,
1909                        GAsyncResult *result,
1910                        gpointer user_data)
1911 {
1912         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1913         ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1914         SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
1915         const gchar *prompt_path = NULL;
1916         const gchar *item_path = NULL;
1917         GError *error = NULL;
1918         GVariant *retval;
1919
1920         retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
1921         if (error == NULL) {
1922                 g_variant_get (retval, "(&o&o)", &item_path, &prompt_path);
1923                 if (!_secret_util_empty_path (prompt_path)) {
1924                         closure->prompt = _secret_prompt_instance (self, prompt_path);
1925                         secret_service_prompt (self, closure->prompt, G_VARIANT_TYPE ("o"),
1926                                                closure->cancellable, on_create_item_prompt,
1927                                                g_object_ref (res));
1928
1929                 } else {
1930                         closure->item_path = g_strdup (item_path);
1931                         g_simple_async_result_complete (res);
1932                 }
1933
1934                 g_variant_unref (retval);
1935
1936         } else {
1937                 g_simple_async_result_take_error (res, error);
1938                 g_simple_async_result_complete (res);
1939         }
1940
1941         g_object_unref (self);
1942         g_object_unref (res);
1943 }
1944
1945 static void
1946 on_create_item_session (GObject *source,
1947                         GAsyncResult *result,
1948                         gpointer user_data)
1949 {
1950         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1951         ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1952         SecretService *self = SECRET_SERVICE (source);
1953         SecretSession *session;
1954         GVariant *params;
1955         GError *error = NULL;
1956         GDBusProxy *proxy;
1957
1958         secret_service_ensure_session_finish (self, result, &error);
1959         if (error == NULL) {
1960                 session = _secret_service_get_session (self);
1961                 params = g_variant_new ("(@a{sv}@(oayays)b)",
1962                                         closure->properties,
1963                                         _secret_session_encode_secret (session, closure->value),
1964                                         closure->replace);
1965
1966                 proxy = G_DBUS_PROXY (self);
1967                 g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
1968                                         g_dbus_proxy_get_name (proxy),
1969                                         closure->collection_path,
1970                                         SECRET_COLLECTION_INTERFACE,
1971                                         "CreateItem", params, G_VARIANT_TYPE ("(oo)"),
1972                                         G_DBUS_CALL_FLAGS_NONE, -1,
1973                                         closure->cancellable,
1974                                         on_create_item_called,
1975                                         g_object_ref (res));
1976         } else {
1977                 g_simple_async_result_take_error (res, error);
1978                 g_simple_async_result_complete (res);
1979         }
1980
1981         g_object_unref (res);
1982 }
1983
1984 /**
1985  * secret_service_create_item_dbus_path:
1986  * @self: a secret service object
1987  * @collection_path: the D-Bus object path of the collection in which to create item
1988  * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
1989  *              for the new collection
1990  * @value: the secret value to store in the item
1991  * @flags: flags for the creation of the new item
1992  * @cancellable: optional cancellation object
1993  * @callback: called when the operation completes
1994  * @user_data: data to be passed to the callback
1995  *
1996  * Create a new item in a secret service collection and return its D-Bus
1997  * object path.
1998  *
1999  * It is often easier to use secret_password_store() or secret_item_create()
2000  * rather than using this function. Using this method requires that you setup
2001  * a correct hash table of D-Bus @properties for the new collection.
2002  *
2003  * If the @flags contains %SECRET_ITEM_CREATE_REPLACE, then the secret
2004  * service will search for an item matching the @attributes, and update that item
2005  * instead of creating a new one.
2006  *
2007  * @properties is a set of properties for the new collection. The keys in the
2008  * hash table should be interface.property strings like
2009  * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
2010  * in the hash table should be #GVariant values of the properties.
2011  *
2012  * This method will return immediately and complete asynchronously. The secret
2013  * service may prompt the user. secret_service_prompt() will be used to handle
2014  * any prompts that are required.
2015  */
2016 void
2017 secret_service_create_item_dbus_path (SecretService *self,
2018                                       const gchar *collection_path,
2019                                       GHashTable *properties,
2020                                       SecretValue *value,
2021                                       SecretItemCreateFlags flags,
2022                                       GCancellable *cancellable,
2023                                       GAsyncReadyCallback callback,
2024                                       gpointer user_data)
2025 {
2026         GSimpleAsyncResult *res;
2027         ItemClosure *closure;
2028
2029         g_return_if_fail (SECRET_IS_SERVICE (self));
2030         g_return_if_fail (collection_path != NULL && g_variant_is_object_path (collection_path));
2031         g_return_if_fail (properties != NULL);
2032         g_return_if_fail (value != NULL);
2033         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2034
2035         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
2036                                          secret_service_create_item_dbus_path);
2037         closure = g_slice_new0 (ItemClosure);
2038         closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
2039         closure->properties = _secret_util_variant_for_properties (properties);
2040         g_variant_ref_sink (closure->properties);
2041         closure->replace = flags & SECRET_ITEM_CREATE_REPLACE;
2042         closure->value = secret_value_ref (value);
2043         closure->collection_path = g_strdup (collection_path);
2044         g_simple_async_result_set_op_res_gpointer (res, closure, item_closure_free);
2045
2046         secret_service_ensure_session (self, cancellable,
2047                                        on_create_item_session,
2048                                        g_object_ref (res));
2049
2050         g_object_unref (res);
2051 }
2052
2053 /**
2054  * secret_service_create_item_dbus_path_finish:
2055  * @self: a secret service object
2056  * @result: the asynchronous result passed to the callback
2057  * @error: location to place an error on failure
2058  *
2059  * Finish asynchronous operation to create a new item in the secret
2060  * service.
2061  *
2062  * Returns: (transfer full): a new string containing the D-Bus object path
2063  *          of the item
2064  */
2065 gchar *
2066 secret_service_create_item_dbus_path_finish (SecretService *self,
2067                                              GAsyncResult *result,
2068                                              GError **error)
2069 {
2070         GSimpleAsyncResult *res;
2071         ItemClosure *closure;
2072         gchar *path;
2073
2074         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
2075                               secret_service_create_item_dbus_path), NULL);
2076         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2077
2078         res = G_SIMPLE_ASYNC_RESULT (result);
2079
2080         if (_secret_util_propagate_error (res, error))
2081                 return NULL;
2082
2083         closure = g_simple_async_result_get_op_res_gpointer (res);
2084         path = closure->item_path;
2085         closure->item_path = NULL;
2086         return path;
2087 }
2088
2089 void
2090 _secret_service_create_item_dbus_path_finish_raw (GAsyncResult *result,
2091                                                   GError **error)
2092 {
2093         g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
2094 }
2095
2096 /**
2097  * secret_service_create_item_dbus_path_sync:
2098  * @self: a secret service object
2099  * @collection_path: the D-Bus path of the collection in which to create item
2100  * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
2101  *              for the new collection
2102  * @value: the secret value to store in the item
2103  * @flags: flags for the creation of the new item
2104  * @cancellable: optional cancellation object
2105  * @error: location to place an error on failure
2106  *
2107  * Create a new item in a secret service collection and return its D-Bus
2108  * object path.
2109  *
2110  * It is often easier to use secret_password_store_sync() or secret_item_create_sync()
2111  * rather than using this function. Using this method requires that you setup
2112  * a correct hash table of D-Bus @properties for the new collection.
2113  *
2114  * If the @flags contains %SECRET_ITEM_CREATE_REPLACE, then the secret
2115  * service will search for an item matching the @attributes, and update that item
2116  * instead of creating a new one.
2117  *
2118  * @properties is a set of properties for the new collection. The keys in the
2119  * hash table should be interface.property strings like
2120  * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
2121  * in the hash table should be #GVariant values of the properties.
2122  *
2123  * This method may block indefinitely and should not be used in user interface
2124  * threads. The secret service may prompt the user. secret_service_prompt()
2125  * will be used to handle any prompts that are required.
2126  *
2127  * Returns: (transfer full): a new string containing the D-Bus object path
2128  *          of the item
2129  */
2130 gchar *
2131 secret_service_create_item_dbus_path_sync (SecretService *self,
2132                                            const gchar *collection_path,
2133                                            GHashTable *properties,
2134                                            SecretValue *value,
2135                                            SecretItemCreateFlags flags,
2136                                            GCancellable *cancellable,
2137                                            GError **error)
2138 {
2139         SecretSync *sync;
2140         gchar *path;
2141
2142         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
2143         g_return_val_if_fail (collection_path != NULL && g_variant_is_object_path (collection_path), NULL);
2144         g_return_val_if_fail (properties != NULL, NULL);
2145         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2146         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2147
2148         sync = _secret_sync_new ();
2149         g_main_context_push_thread_default (sync->context);
2150
2151         secret_service_create_item_dbus_path (self, collection_path, properties, value, flags,
2152                                               cancellable, _secret_sync_on_result, sync);
2153
2154         g_main_loop_run (sync->loop);
2155
2156         path = secret_service_create_item_dbus_path_finish (self, sync->result, error);
2157
2158         g_main_context_pop_thread_default (sync->context);
2159         _secret_sync_free (sync);
2160
2161         return path;
2162 }
2163
2164 /**
2165  * secret_service_read_alias_dbus_path:
2166  * @self: a secret service object
2167  * @alias: the alias to lookup
2168  * @cancellable: (allow-none): optional cancellation object
2169  * @callback: called when the operation completes
2170  * @user_data: data to pass to the callback
2171  *
2172  * Lookup which collection is assigned to this alias. Aliases help determine
2173  * well known collections, such as 'default'. This method looks up the
2174  * dbus object path of the well known collection.
2175  *
2176  * This method will return immediately and complete asynchronously.
2177  */
2178 void
2179 secret_service_read_alias_dbus_path (SecretService *self,
2180                                      const gchar *alias,
2181                                      GCancellable *cancellable,
2182                                      GAsyncReadyCallback callback,
2183                                      gpointer user_data)
2184 {
2185         g_return_if_fail (SECRET_IS_SERVICE (self));
2186         g_return_if_fail (alias != NULL);
2187         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2188
2189         g_dbus_proxy_call (G_DBUS_PROXY (self), "ReadAlias",
2190                            g_variant_new ("(s)", alias),
2191                            G_DBUS_CALL_FLAGS_NONE, -1,
2192                            cancellable, callback, user_data);
2193 }
2194
2195 /**
2196  * secret_service_read_alias_dbus_path_finish:
2197  * @self: a secret service object
2198  * @result: asynchronous result passed to callback
2199  * @error: location to place error on failure
2200  *
2201  * Finish an asynchronous operation to lookup which collection is assigned
2202  * to an alias. This method returns the DBus object path of the collection
2203  *
2204  * Returns: (transfer full): the collection dbus object path, or %NULL if
2205  *          none assigned to the alias
2206  */
2207 gchar *
2208 secret_service_read_alias_dbus_path_finish (SecretService *self,
2209                                             GAsyncResult *result,
2210                                             GError **error)
2211 {
2212         gchar *collection_path;
2213         GVariant *retval;
2214
2215         retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, error);
2216
2217         _secret_util_strip_remote_error (error);
2218         if (retval == NULL)
2219                 return NULL;
2220
2221         g_variant_get (retval, "(o)", &collection_path);
2222         g_variant_unref (retval);
2223
2224         if (g_str_equal (collection_path, "/")) {
2225                 g_free (collection_path);
2226                 collection_path = NULL;
2227         }
2228
2229         return collection_path;
2230 }
2231
2232 /**
2233  * secret_service_read_alias_dbus_path_sync:
2234  * @self: a secret service object
2235  * @alias: the alias to lookup
2236  * @cancellable: (allow-none): optional cancellation object
2237  * @error: location to place error on failure
2238  *
2239  * Lookup which collection is assigned to this alias. Aliases help determine
2240  * well known collections, such as 'default'. This method returns the dbus
2241  * object path of the collection.
2242  *
2243  * This method may block and should not be used in user interface threads.
2244  *
2245  * Returns: (transfer full): the collection dbus object path, or %NULL if
2246  *          none assigned to the alias
2247  */
2248 gchar *
2249 secret_service_read_alias_dbus_path_sync (SecretService *self,
2250                                           const gchar *alias,
2251                                           GCancellable *cancellable,
2252                                           GError **error)
2253 {
2254         SecretSync *sync;
2255         gchar *collection_path;
2256
2257         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
2258         g_return_val_if_fail (alias != NULL, NULL);
2259         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2260         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2261
2262         sync = _secret_sync_new ();
2263         g_main_context_push_thread_default (sync->context);
2264
2265         secret_service_read_alias_dbus_path (self, alias, cancellable, _secret_sync_on_result, sync);
2266
2267         g_main_loop_run (sync->loop);
2268
2269         collection_path = secret_service_read_alias_dbus_path_finish (self, sync->result, error);
2270
2271         g_main_context_pop_thread_default (sync->context);
2272         _secret_sync_free (sync);
2273
2274         return collection_path;
2275 }
2276
2277 /**
2278  * secret_service_set_alias_to_dbus_path:
2279  * @self: a secret service object
2280  * @alias: the alias to assign the collection to
2281  * @collection_path: (allow-none): the dbus object path of the collection to assign to the alias
2282  * @cancellable: (allow-none): optional cancellation object
2283  * @callback: called when the operation completes
2284  * @user_data: data to pass to the callback
2285  *
2286  * Assign a collection to this alias. Aliases help determine
2287  * well known collections, such as 'default'. This method takes the dbus object
2288  * path of the collection to assign to the alias.
2289  *
2290  * This method will return immediately and complete asynchronously.
2291  */
2292 void
2293 secret_service_set_alias_to_dbus_path (SecretService *self,
2294                                        const gchar *alias,
2295                                        const gchar *collection_path,
2296                                        GCancellable *cancellable,
2297                                        GAsyncReadyCallback callback,
2298                                        gpointer user_data)
2299 {
2300         g_return_if_fail (SECRET_IS_SERVICE (self));
2301         g_return_if_fail (alias != NULL);
2302         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2303
2304         if (collection_path == NULL)
2305                 collection_path = "/";
2306         else
2307                 g_return_if_fail (g_variant_is_object_path (collection_path));
2308
2309         g_dbus_proxy_call (G_DBUS_PROXY (self), "SetAlias",
2310                            g_variant_new ("(so)", alias, collection_path),
2311                            G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
2312                            callback, user_data);
2313 }
2314
2315 /**
2316  * secret_service_set_alias_to_dbus_path_finish:
2317  * @self: a secret service object
2318  * @result: asynchronous result passed to callback
2319  * @error: location to place error on failure
2320  *
2321  * Finish an asynchronous operation to assign a collection to an alias.
2322  *
2323  * Returns: %TRUE if successful
2324  */
2325 gboolean
2326 secret_service_set_alias_to_dbus_path_finish (SecretService *self,
2327                                               GAsyncResult *result,
2328                                               GError **error)
2329 {
2330         GVariant *retval;
2331
2332         g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
2333         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2334
2335         retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, error);
2336
2337         _secret_util_strip_remote_error (error);
2338         if (retval == NULL)
2339                 return FALSE;
2340
2341         g_variant_unref (retval);
2342         return TRUE;
2343 }
2344
2345 /**
2346  * secret_service_set_alias_to_dbus_path_sync:
2347  * @self: a secret service object
2348  * @alias: the alias to assign the collection to
2349  * @collection_path: (allow-none): the dbus object path of the collection to assign to the alias
2350  * @cancellable: (allow-none): optional cancellation object
2351  * @error: location to place error on failure
2352  *
2353  * Assign a collection to this alias. Aliases help determine
2354  * well known collections, such as 'default'. This method takes the dbus object
2355  * path of the collection to assign to the alias.
2356  *
2357  * This method may block and should not be used in user interface threads.
2358  *
2359  * Returns: %TRUE if successful
2360  */
2361 gboolean
2362 secret_service_set_alias_to_dbus_path_sync (SecretService *self,
2363                                             const gchar *alias,
2364                                             const gchar *collection_path,
2365                                             GCancellable *cancellable,
2366                                             GError **error)
2367 {
2368         SecretSync *sync;
2369         gboolean ret;
2370
2371         g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
2372         g_return_val_if_fail (alias != NULL, FALSE);
2373         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
2374         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2375
2376         if (collection_path == NULL)
2377                 collection_path = "/";
2378         else
2379                 g_return_val_if_fail (g_variant_is_object_path (collection_path), FALSE);
2380
2381         sync = _secret_sync_new ();
2382         g_main_context_push_thread_default (sync->context);
2383
2384         secret_service_set_alias_to_dbus_path (self, alias, collection_path,
2385                                                cancellable, _secret_sync_on_result, sync);
2386
2387         g_main_loop_run (sync->loop);
2388
2389         ret = secret_service_set_alias_to_dbus_path_finish (self, sync->result, error);
2390
2391         g_main_context_pop_thread_default (sync->context);
2392         _secret_sync_free (sync);
2393
2394         return ret;
2395 }
2396
2397 GVariant *
2398 secret_service_prompt_at_dbus_path_sync (SecretService *self,
2399                                          const gchar *prompt_path,
2400                                          GCancellable *cancellable,
2401                                          const GVariantType *return_type,
2402                                          GError **error)
2403 {
2404         SecretPrompt *prompt;
2405         GVariant *retval;
2406
2407         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
2408         g_return_val_if_fail (prompt_path != NULL, NULL);
2409         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2410         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2411
2412         prompt = _secret_prompt_instance (self, prompt_path);
2413         retval = secret_service_prompt_sync (self, prompt, cancellable, return_type, error);
2414         g_object_unref (prompt);
2415
2416         return retval;
2417 }
2418
2419 /**
2420  * secret_service_prompt_at_dbus_path:
2421  * @self: the secret service
2422  * @prompt_path: the D-Bus object path of the prompt
2423  * @return_type: (allow-none): the variant type of the prompt result
2424  * @cancellable: optional cancellation object
2425  * @callback: called when the operation completes
2426  * @user_data: data to be passed to the callback
2427  *
2428  * Perform prompting for a #SecretPrompt.
2429  *
2430  * This function is called by other parts of this library to handle prompts
2431  * for the various actions that can require prompting.
2432  *
2433  * Override the #SecretServiceClass <literal>prompt_async</literal> virtual method
2434  * to change the behavior of the propmting. The default behavior is to simply
2435  * run secret_prompt_perform() on the prompt.
2436  */
2437 void
2438 secret_service_prompt_at_dbus_path (SecretService *self,
2439                                     const gchar *prompt_path,
2440                                     const GVariantType *return_type,
2441                                     GCancellable *cancellable,
2442                                     GAsyncReadyCallback callback,
2443                                     gpointer user_data)
2444 {
2445         SecretPrompt *prompt;
2446
2447         g_return_if_fail (SECRET_IS_SERVICE (self));
2448         g_return_if_fail (prompt_path != NULL);
2449         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2450
2451         prompt = _secret_prompt_instance (self, prompt_path);
2452         secret_service_prompt (self, prompt, return_type, cancellable, callback, user_data);
2453         g_object_unref (prompt);
2454 }
2455
2456 /**
2457  * secret_service_prompt_at_dbus_path_finish:
2458  * @self: the secret service
2459  * @result: the asynchronous result passed to the callback
2460  * @error: location to place an error on failure
2461  *
2462  * Complete asynchronous operation to perform prompting for a #SecretPrompt.
2463  *
2464  * Returns a variant result if the prompt was completed and not dismissed. The
2465  * type of result depends on the action the prompt is completing, and is defined
2466  * in the Secret Service DBus API specification.
2467  *
2468  * Returns: (transfer full): %NULL if the prompt was dismissed or an error occurred,
2469  *          a variant result if the prompt was successful
2470  */
2471 GVariant *
2472 secret_service_prompt_at_dbus_path_finish (SecretService *self,
2473                                            GAsyncResult *result,
2474                                            GError **error)
2475 {
2476         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
2477         g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
2478         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2479
2480         return secret_service_prompt_finish (self, result, error);
2481 }