dfe968e0c29d8c06d0e8a4a56c6c8cb32196f8d2
[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_CLASS (service)->collection_gtype,
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_CLASS (service)->collection_gtype,
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_CLASS (service)->item_gtype,
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_CLASS (service)->item_gtype,
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, G_VARIANT_TYPE ("ao"), &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, closure->cancellable,
1062                                                 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                                                NULL, &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,
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,
1628                                               G_VARIANT_TYPE ("o"), &error);
1629         if (error != NULL)
1630                 g_simple_async_result_take_error (res, error);
1631         if (value != NULL) {
1632                 closure->collection_path = g_variant_dup_string (value, NULL);
1633                 g_variant_unref (value);
1634         }
1635
1636         g_simple_async_result_complete (res);
1637         g_object_unref (res);
1638 }
1639
1640 static void
1641 on_create_collection_called (GObject *source,
1642                              GAsyncResult *result,
1643                              gpointer user_data)
1644 {
1645         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1646         CollectionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1647         SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
1648         const gchar *prompt_path = NULL;
1649         const gchar *collection_path = NULL;
1650         GError *error = NULL;
1651         GVariant *retval;
1652
1653         retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
1654         if (error == NULL) {
1655                 g_variant_get (retval, "(&o&o)", &collection_path, &prompt_path);
1656                 if (!_secret_util_empty_path (prompt_path)) {
1657                         closure->prompt = _secret_prompt_instance (self, prompt_path);
1658                         secret_service_prompt (self, closure->prompt,
1659                                                closure->cancellable, on_create_collection_prompt,
1660                                                g_object_ref (res));
1661
1662                 } else {
1663                         closure->collection_path = g_strdup (collection_path);
1664                         g_simple_async_result_complete (res);
1665                 }
1666
1667                 g_variant_unref (retval);
1668
1669         } else {
1670                 g_simple_async_result_take_error (res, error);
1671                 g_simple_async_result_complete (res);
1672         }
1673
1674         g_object_unref (self);
1675         g_object_unref (res);
1676 }
1677
1678 /**
1679  * secret_service_create_collection_dbus_path:
1680  * @self: a secret service object
1681  * @properties: (element-type utf8 GLib.Variant): hash table of properties for
1682  *              the new collection
1683  * @alias: (allow-none): an alias to check for before creating the new
1684  *         collection, or to assign to the new collection
1685  * @flags: not currently used
1686  * @cancellable: optional cancellation object
1687  * @callback: called when the operation completes
1688  * @user_data: data to be passed to the callback
1689  *
1690  * Create a new collection in the secret service, and return its path.
1691  *
1692  * Using this method requires that you setup a correct hash table of D-Bus
1693  * properties for the new collection. You may prefer to use
1694  * secret_collection_create() which does handles this for you.
1695  *
1696  * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1697  * default collection to store items in). This allows other applications to
1698  * easily identify and share a collection. If a collection with the @alias
1699  * already exists, then instead of creating a new collection, the existing
1700  * collection will be returned. If no collection with this alias exists, then a
1701  * new collection will be created and this alias will be assigned to it.
1702  *
1703  * @properties is a set of properties for the new collection. The keys in the
1704  * hash table should be interface.property strings like
1705  * <literal>org.freedesktop.Secret.Collection.Label</literal>. The values
1706  * in the hash table should be #GVariant values of the properties.
1707  *
1708  * If you wish to have a
1709  *
1710  * This method will return immediately and complete asynchronously. The secret
1711  * service may prompt the user. secret_service_prompt() will be used to handle
1712  * any prompts that are required.
1713  */
1714 void
1715 secret_service_create_collection_dbus_path (SecretService *self,
1716                                             GHashTable *properties,
1717                                             const gchar *alias,
1718                                             SecretCollectionCreateFlags flags,
1719                                             GCancellable *cancellable,
1720                                             GAsyncReadyCallback callback,
1721                                             gpointer user_data)
1722 {
1723         GSimpleAsyncResult *res;
1724         CollectionClosure *closure;
1725         GVariant *params;
1726         GVariant *props;
1727         GDBusProxy *proxy;
1728
1729         g_return_if_fail (SECRET_IS_SERVICE (self));
1730         g_return_if_fail (properties != NULL);
1731         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1732
1733         if (alias == NULL)
1734                 alias = "";
1735
1736         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1737                                          secret_service_create_collection_dbus_path);
1738         closure = g_slice_new0 (CollectionClosure);
1739         closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1740         g_simple_async_result_set_op_res_gpointer (res, closure, collection_closure_free);
1741
1742         props = _secret_util_variant_for_properties (properties);
1743         params = g_variant_new ("(@a{sv}s)", props, alias);
1744         proxy = G_DBUS_PROXY (self);
1745
1746         g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
1747                                 g_dbus_proxy_get_name (proxy),
1748                                 g_dbus_proxy_get_object_path (proxy),
1749                                 SECRET_SERVICE_INTERFACE,
1750                                 "CreateCollection", params, G_VARIANT_TYPE ("(oo)"),
1751                                 G_DBUS_CALL_FLAGS_NONE, -1,
1752                                 closure->cancellable,
1753                                 on_create_collection_called,
1754                                 g_object_ref (res));
1755
1756         g_object_unref (res);
1757
1758 }
1759
1760 /**
1761  * secret_service_create_collection_dbus_path_finish:
1762  * @self: a secret service object
1763  * @result: the asynchronous result passed to the callback
1764  * @error: location to place an error on failure
1765  *
1766  * Finish asynchronous operation to create a new collection in the secret
1767  * service.
1768  *
1769  * Returns: (transfer full): a new string containing the D-Bus object path
1770  *          of the collection
1771  */
1772 gchar *
1773 secret_service_create_collection_dbus_path_finish (SecretService *self,
1774                                                    GAsyncResult *result,
1775                                                    GError **error)
1776 {
1777         GSimpleAsyncResult *res;
1778         CollectionClosure *closure;
1779         gchar *path;
1780
1781         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1782                               secret_service_create_collection_dbus_path), NULL);
1783         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1784
1785         res = G_SIMPLE_ASYNC_RESULT (result);
1786
1787         if (_secret_util_propagate_error (res, error))
1788                 return NULL;
1789
1790         closure = g_simple_async_result_get_op_res_gpointer (res);
1791         path = closure->collection_path;
1792         closure->collection_path = NULL;
1793         return path;
1794 }
1795
1796 /**
1797  * secret_service_create_collection_dbus_path_sync:
1798  * @self: a secret service object
1799  * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
1800  *              for the new collection
1801  * @alias: (allow-none): an alias to check for before creating the new
1802  *         collection, or to assign to the new collection
1803  * @flags: not currently used
1804  * @cancellable: optional cancellation object
1805  * @error: location to place an error on failure
1806  *
1807  * Create a new collection in the secret service and return its path.
1808  *
1809  * Using this method requires that you setup a correct hash table of D-Bus
1810  * properties for the new collection. You may prefer to use
1811  * secret_collection_create() which does handles this for you.
1812  *
1813  * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1814  * default collection to store items in). This allows other applications to
1815  * easily identify and share a collection. If a collection with the @alias
1816  * already exists, then instead of creating a new collection, the existing
1817  * collection will be returned. If no collection with this alias exists, then
1818  * a new collection will be created and this alias will be assigned to it.
1819  *
1820  * @properties is a set of properties for the new collection. The keys in the
1821  * hash table should be interface.property strings like
1822  * <literal>org.freedesktop.Secret.Collection.Label</literal>. The values
1823  * in the hash table should be #GVariant values of the properties.
1824  *
1825  * This method may block indefinitely and should not be used in user interface
1826  * threads. The secret service may prompt the user. secret_service_prompt()
1827  * will be used to handle any prompts that are required.
1828  *
1829  * Returns: (transfer full): a new string containing the D-Bus object path
1830  *          of the collection
1831  */
1832 gchar *
1833 secret_service_create_collection_dbus_path_sync (SecretService *self,
1834                                                  GHashTable *properties,
1835                                                  const gchar *alias,
1836                                                  SecretCollectionCreateFlags flags,
1837                                                  GCancellable *cancellable,
1838                                                  GError **error)
1839 {
1840         SecretSync *sync;
1841         gchar *path;
1842
1843         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
1844         g_return_val_if_fail (properties != NULL, NULL);
1845         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1846         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1847
1848         sync = _secret_sync_new ();
1849         g_main_context_push_thread_default (sync->context);
1850
1851         secret_service_create_collection_dbus_path (self, properties, alias, flags, cancellable,
1852                                                     _secret_sync_on_result, sync);
1853
1854         g_main_loop_run (sync->loop);
1855
1856         path = secret_service_create_collection_dbus_path_finish (self, sync->result, error);
1857
1858         g_main_context_pop_thread_default (sync->context);
1859         _secret_sync_free (sync);
1860
1861         return path;
1862 }
1863
1864 typedef struct {
1865         GCancellable *cancellable;
1866         GVariant *properties;
1867         SecretValue *value;
1868         gboolean replace;
1869         gchar *collection_path;
1870         SecretPrompt *prompt;
1871         gchar *item_path;
1872 } ItemClosure;
1873
1874 static void
1875 item_closure_free (gpointer data)
1876 {
1877         ItemClosure *closure = data;
1878         g_variant_unref (closure->properties);
1879         secret_value_unref (closure->value);
1880         g_clear_object (&closure->cancellable);
1881         g_free (closure->collection_path);
1882         g_clear_object (&closure->prompt);
1883         g_slice_free (ItemClosure, closure);
1884 }
1885
1886 static void
1887 on_create_item_prompt (GObject *source,
1888                        GAsyncResult *result,
1889                        gpointer user_data)
1890 {
1891         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1892         ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1893         GError *error = NULL;
1894         GVariant *value;
1895
1896         value = secret_service_prompt_finish (SECRET_SERVICE (source), result,
1897                                               G_VARIANT_TYPE ("o"), &error);
1898         if (error != NULL)
1899                 g_simple_async_result_take_error (res, error);
1900         if (value != NULL) {
1901                 closure->item_path = g_variant_dup_string (value, NULL);
1902                 g_variant_unref (value);
1903         }
1904
1905         g_simple_async_result_complete (res);
1906         g_object_unref (res);
1907 }
1908
1909 static void
1910 on_create_item_called (GObject *source,
1911                        GAsyncResult *result,
1912                        gpointer user_data)
1913 {
1914         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1915         ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1916         SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
1917         const gchar *prompt_path = NULL;
1918         const gchar *item_path = NULL;
1919         GError *error = NULL;
1920         GVariant *retval;
1921
1922         retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
1923         if (error == NULL) {
1924                 g_variant_get (retval, "(&o&o)", &item_path, &prompt_path);
1925                 if (!_secret_util_empty_path (prompt_path)) {
1926                         closure->prompt = _secret_prompt_instance (self, prompt_path);
1927                         secret_service_prompt (self, closure->prompt,
1928                                                closure->cancellable, on_create_item_prompt,
1929                                                g_object_ref (res));
1930
1931                 } else {
1932                         closure->item_path = g_strdup (item_path);
1933                         g_simple_async_result_complete (res);
1934                 }
1935
1936                 g_variant_unref (retval);
1937
1938         } else {
1939                 g_simple_async_result_take_error (res, error);
1940                 g_simple_async_result_complete (res);
1941         }
1942
1943         g_object_unref (self);
1944         g_object_unref (res);
1945 }
1946
1947 static void
1948 on_create_item_session (GObject *source,
1949                         GAsyncResult *result,
1950                         gpointer user_data)
1951 {
1952         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1953         ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1954         SecretService *self = SECRET_SERVICE (source);
1955         SecretSession *session;
1956         GVariant *params;
1957         GError *error = NULL;
1958         GDBusProxy *proxy;
1959
1960         secret_service_ensure_session_finish (self, result, &error);
1961         if (error == NULL) {
1962                 session = _secret_service_get_session (self);
1963                 params = g_variant_new ("(@a{sv}@(oayays)b)",
1964                                         closure->properties,
1965                                         _secret_session_encode_secret (session, closure->value),
1966                                         closure->replace);
1967
1968                 proxy = G_DBUS_PROXY (self);
1969                 g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
1970                                         g_dbus_proxy_get_name (proxy),
1971                                         closure->collection_path,
1972                                         SECRET_COLLECTION_INTERFACE,
1973                                         "CreateItem", params, G_VARIANT_TYPE ("(oo)"),
1974                                         G_DBUS_CALL_FLAGS_NONE, -1,
1975                                         closure->cancellable,
1976                                         on_create_item_called,
1977                                         g_object_ref (res));
1978         } else {
1979                 g_simple_async_result_take_error (res, error);
1980                 g_simple_async_result_complete (res);
1981         }
1982
1983         g_object_unref (res);
1984 }
1985
1986 /**
1987  * secret_service_create_item_dbus_path:
1988  * @self: a secret service object
1989  * @collection_path: the D-Bus object path of the collection in which to create item
1990  * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
1991  *              for the new collection
1992  * @value: the secret value to store in the item
1993  * @flags: flags for the creation of the new item
1994  * @cancellable: optional cancellation object
1995  * @callback: called when the operation completes
1996  * @user_data: data to be passed to the callback
1997  *
1998  * Create a new item in a secret service collection and return its D-Bus
1999  * object path.
2000  *
2001  * It is often easier to use secret_password_store() or secret_item_create()
2002  * rather than using this function. Using this method requires that you setup
2003  * a correct hash table of D-Bus @properties for the new collection.
2004  *
2005  * If the @flags contains %SECRET_ITEM_CREATE_REPLACE, then the secret
2006  * service will search for an item matching the @attributes, and update that item
2007  * instead of creating a new one.
2008  *
2009  * @properties is a set of properties for the new collection. The keys in the
2010  * hash table should be interface.property strings like
2011  * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
2012  * in the hash table should be #GVariant values of the properties.
2013  *
2014  * This method will return immediately and complete asynchronously. The secret
2015  * service may prompt the user. secret_service_prompt() will be used to handle
2016  * any prompts that are required.
2017  */
2018 void
2019 secret_service_create_item_dbus_path (SecretService *self,
2020                                       const gchar *collection_path,
2021                                       GHashTable *properties,
2022                                       SecretValue *value,
2023                                       SecretItemCreateFlags flags,
2024                                       GCancellable *cancellable,
2025                                       GAsyncReadyCallback callback,
2026                                       gpointer user_data)
2027 {
2028         GSimpleAsyncResult *res;
2029         ItemClosure *closure;
2030
2031         g_return_if_fail (SECRET_IS_SERVICE (self));
2032         g_return_if_fail (collection_path != NULL && g_variant_is_object_path (collection_path));
2033         g_return_if_fail (properties != NULL);
2034         g_return_if_fail (value != NULL);
2035         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2036
2037         res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
2038                                          secret_service_create_item_dbus_path);
2039         closure = g_slice_new0 (ItemClosure);
2040         closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
2041         closure->properties = _secret_util_variant_for_properties (properties);
2042         g_variant_ref_sink (closure->properties);
2043         closure->replace = flags & SECRET_ITEM_CREATE_REPLACE;
2044         closure->value = secret_value_ref (value);
2045         closure->collection_path = g_strdup (collection_path);
2046         g_simple_async_result_set_op_res_gpointer (res, closure, item_closure_free);
2047
2048         secret_service_ensure_session (self, cancellable,
2049                                        on_create_item_session,
2050                                        g_object_ref (res));
2051
2052         g_object_unref (res);
2053 }
2054
2055 /**
2056  * secret_service_create_item_dbus_path_finish:
2057  * @self: a secret service object
2058  * @result: the asynchronous result passed to the callback
2059  * @error: location to place an error on failure
2060  *
2061  * Finish asynchronous operation to create a new item in the secret
2062  * service.
2063  *
2064  * Returns: (transfer full): a new string containing the D-Bus object path
2065  *          of the item
2066  */
2067 gchar *
2068 secret_service_create_item_dbus_path_finish (SecretService *self,
2069                                              GAsyncResult *result,
2070                                              GError **error)
2071 {
2072         GSimpleAsyncResult *res;
2073         ItemClosure *closure;
2074         gchar *path;
2075
2076         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
2077                               secret_service_create_item_dbus_path), NULL);
2078         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2079
2080         res = G_SIMPLE_ASYNC_RESULT (result);
2081
2082         if (_secret_util_propagate_error (res, error))
2083                 return NULL;
2084
2085         closure = g_simple_async_result_get_op_res_gpointer (res);
2086         path = closure->item_path;
2087         closure->item_path = NULL;
2088         return path;
2089 }
2090
2091 /**
2092  * secret_service_create_item_dbus_path_sync:
2093  * @self: a secret service object
2094  * @collection_path: the D-Bus path of the collection in which to create item
2095  * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
2096  *              for the new collection
2097  * @value: the secret value to store in the item
2098  * @flags: flags for the creation of the new item
2099  * @cancellable: optional cancellation object
2100  * @error: location to place an error on failure
2101  *
2102  * Create a new item in a secret service collection and return its D-Bus
2103  * object path.
2104  *
2105  * It is often easier to use secret_password_store_sync() or secret_item_create_sync()
2106  * rather than using this function. Using this method requires that you setup
2107  * a correct hash table of D-Bus @properties for the new collection.
2108  *
2109  * If the @flags contains %SECRET_ITEM_CREATE_REPLACE, then the secret
2110  * service will search for an item matching the @attributes, and update that item
2111  * instead of creating a new one.
2112  *
2113  * @properties is a set of properties for the new collection. The keys in the
2114  * hash table should be interface.property strings like
2115  * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
2116  * in the hash table should be #GVariant values of the properties.
2117  *
2118  * This method may block indefinitely and should not be used in user interface
2119  * threads. The secret service may prompt the user. secret_service_prompt()
2120  * will be used to handle any prompts that are required.
2121  *
2122  * Returns: (transfer full): a new string containing the D-Bus object path
2123  *          of the item
2124  */
2125 gchar *
2126 secret_service_create_item_dbus_path_sync (SecretService *self,
2127                                            const gchar *collection_path,
2128                                            GHashTable *properties,
2129                                            SecretValue *value,
2130                                            SecretItemCreateFlags flags,
2131                                            GCancellable *cancellable,
2132                                            GError **error)
2133 {
2134         SecretSync *sync;
2135         gchar *path;
2136
2137         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
2138         g_return_val_if_fail (collection_path != NULL && g_variant_is_object_path (collection_path), NULL);
2139         g_return_val_if_fail (properties != NULL, NULL);
2140         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2141         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2142
2143         sync = _secret_sync_new ();
2144         g_main_context_push_thread_default (sync->context);
2145
2146         secret_service_create_item_dbus_path (self, collection_path, properties, value, flags,
2147                                               cancellable, _secret_sync_on_result, sync);
2148
2149         g_main_loop_run (sync->loop);
2150
2151         path = secret_service_create_item_dbus_path_finish (self, sync->result, error);
2152
2153         g_main_context_pop_thread_default (sync->context);
2154         _secret_sync_free (sync);
2155
2156         return path;
2157 }
2158
2159 /**
2160  * secret_service_read_alias_dbus_path:
2161  * @self: a secret service object
2162  * @alias: the alias to lookup
2163  * @cancellable: (allow-none): optional cancellation object
2164  * @callback: called when the operation completes
2165  * @user_data: data to pass to the callback
2166  *
2167  * Lookup which collection is assigned to this alias. Aliases help determine
2168  * well known collections, such as 'default'. This method looks up the
2169  * dbus object path of the well known collection.
2170  *
2171  * This method will return immediately and complete asynchronously.
2172  */
2173 void
2174 secret_service_read_alias_dbus_path (SecretService *self,
2175                                      const gchar *alias,
2176                                      GCancellable *cancellable,
2177                                      GAsyncReadyCallback callback,
2178                                      gpointer user_data)
2179 {
2180         g_return_if_fail (SECRET_IS_SERVICE (self));
2181         g_return_if_fail (alias != NULL);
2182         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2183
2184         g_dbus_proxy_call (G_DBUS_PROXY (self), "ReadAlias",
2185                            g_variant_new ("(s)", alias),
2186                            G_DBUS_CALL_FLAGS_NONE, -1,
2187                            cancellable, callback, user_data);
2188 }
2189
2190 /**
2191  * secret_service_read_alias_dbus_path_finish:
2192  * @self: a secret service object
2193  * @result: asynchronous result passed to callback
2194  * @error: location to place error on failure
2195  *
2196  * Finish an asynchronous operation to lookup which collection is assigned
2197  * to an alias. This method returns the DBus object path of the collection
2198  *
2199  * Returns: (transfer full): the collection dbus object path, or %NULL if
2200  *          none assigned to the alias
2201  */
2202 gchar *
2203 secret_service_read_alias_dbus_path_finish (SecretService *self,
2204                                             GAsyncResult *result,
2205                                             GError **error)
2206 {
2207         gchar *collection_path;
2208         GVariant *retval;
2209
2210         retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, error);
2211
2212         _secret_util_strip_remote_error (error);
2213         if (retval == NULL)
2214                 return NULL;
2215
2216         g_variant_get (retval, "(o)", &collection_path);
2217         g_variant_unref (retval);
2218
2219         if (g_str_equal (collection_path, "/")) {
2220                 g_free (collection_path);
2221                 collection_path = NULL;
2222         }
2223
2224         return collection_path;
2225 }
2226
2227 /**
2228  * secret_service_read_alias_dbus_path_sync:
2229  * @self: a secret service object
2230  * @alias: the alias to lookup
2231  * @cancellable: (allow-none): optional cancellation object
2232  * @error: location to place error on failure
2233  *
2234  * Lookup which collection is assigned to this alias. Aliases help determine
2235  * well known collections, such as 'default'. This method returns the dbus
2236  * object path of the collection.
2237  *
2238  * This method may block and should not be used in user interface threads.
2239  *
2240  * Returns: (transfer full): the collection dbus object path, or %NULL if
2241  *          none assigned to the alias
2242  */
2243 gchar *
2244 secret_service_read_alias_dbus_path_sync (SecretService *self,
2245                                           const gchar *alias,
2246                                           GCancellable *cancellable,
2247                                           GError **error)
2248 {
2249         SecretSync *sync;
2250         gchar *collection_path;
2251
2252         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
2253         g_return_val_if_fail (alias != NULL, NULL);
2254         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2255         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2256
2257         sync = _secret_sync_new ();
2258         g_main_context_push_thread_default (sync->context);
2259
2260         secret_service_read_alias_dbus_path (self, alias, cancellable, _secret_sync_on_result, sync);
2261
2262         g_main_loop_run (sync->loop);
2263
2264         collection_path = secret_service_read_alias_dbus_path_finish (self, sync->result, error);
2265
2266         g_main_context_pop_thread_default (sync->context);
2267         _secret_sync_free (sync);
2268
2269         return collection_path;
2270 }
2271
2272 /**
2273  * secret_service_set_alias_to_dbus_path:
2274  * @self: a secret service object
2275  * @alias: the alias to assign the collection to
2276  * @collection_path: (allow-none): the dbus object path of the collection to assign to the alias
2277  * @cancellable: (allow-none): optional cancellation object
2278  * @callback: called when the operation completes
2279  * @user_data: data to pass to the callback
2280  *
2281  * Assign a collection to this alias. Aliases help determine
2282  * well known collections, such as 'default'. This method takes the dbus object
2283  * path of the collection to assign to the alias.
2284  *
2285  * This method will return immediately and complete asynchronously.
2286  */
2287 void
2288 secret_service_set_alias_to_dbus_path (SecretService *self,
2289                                        const gchar *alias,
2290                                        const gchar *collection_path,
2291                                        GCancellable *cancellable,
2292                                        GAsyncReadyCallback callback,
2293                                        gpointer user_data)
2294 {
2295         g_return_if_fail (SECRET_IS_SERVICE (self));
2296         g_return_if_fail (alias != NULL);
2297         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2298
2299         if (collection_path == NULL)
2300                 collection_path = "/";
2301         else
2302                 g_return_if_fail (g_variant_is_object_path (collection_path));
2303
2304         g_dbus_proxy_call (G_DBUS_PROXY (self), "SetAlias",
2305                            g_variant_new ("(so)", alias, collection_path),
2306                            G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
2307                            callback, user_data);
2308 }
2309
2310 /**
2311  * secret_service_set_alias_to_dbus_path_finish:
2312  * @self: a secret service object
2313  * @result: asynchronous result passed to callback
2314  * @error: location to place error on failure
2315  *
2316  * Finish an asynchronous operation to assign a collection to an alias.
2317  *
2318  * Returns: %TRUE if successful
2319  */
2320 gboolean
2321 secret_service_set_alias_to_dbus_path_finish (SecretService *self,
2322                                               GAsyncResult *result,
2323                                               GError **error)
2324 {
2325         GVariant *retval;
2326
2327         g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
2328         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2329
2330         retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, error);
2331
2332         _secret_util_strip_remote_error (error);
2333         if (retval == NULL)
2334                 return FALSE;
2335
2336         g_variant_unref (retval);
2337         return TRUE;
2338 }
2339
2340 /**
2341  * secret_service_set_alias_to_dbus_path_sync:
2342  * @self: a secret service object
2343  * @alias: the alias to assign the collection to
2344  * @collection_path: (allow-none): the dbus object path of the collection to assign to the alias
2345  * @cancellable: (allow-none): optional cancellation object
2346  * @error: location to place error on failure
2347  *
2348  * Assign a collection to this alias. Aliases help determine
2349  * well known collections, such as 'default'. This method takes the dbus object
2350  * path of the collection to assign to the alias.
2351  *
2352  * This method may block and should not be used in user interface threads.
2353  *
2354  * Returns: %TRUE if successful
2355  */
2356 gboolean
2357 secret_service_set_alias_to_dbus_path_sync (SecretService *self,
2358                                             const gchar *alias,
2359                                             const gchar *collection_path,
2360                                             GCancellable *cancellable,
2361                                             GError **error)
2362 {
2363         SecretSync *sync;
2364         gboolean ret;
2365
2366         g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
2367         g_return_val_if_fail (alias != NULL, FALSE);
2368         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
2369         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2370
2371         if (collection_path == NULL)
2372                 collection_path = "/";
2373         else
2374                 g_return_val_if_fail (g_variant_is_object_path (collection_path), FALSE);
2375
2376         sync = _secret_sync_new ();
2377         g_main_context_push_thread_default (sync->context);
2378
2379         secret_service_set_alias_to_dbus_path (self, alias, collection_path,
2380                                                cancellable, _secret_sync_on_result, sync);
2381
2382         g_main_loop_run (sync->loop);
2383
2384         ret = secret_service_set_alias_to_dbus_path_finish (self, sync->result, error);
2385
2386         g_main_context_pop_thread_default (sync->context);
2387         _secret_sync_free (sync);
2388
2389         return ret;
2390 }
2391
2392 GVariant *
2393 secret_service_prompt_at_dbus_path_sync (SecretService *self,
2394                                          const gchar *prompt_path,
2395                                          GCancellable *cancellable,
2396                                          const GVariantType *return_type,
2397                                          GError **error)
2398 {
2399         SecretPrompt *prompt;
2400         GVariant *retval;
2401
2402         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
2403         g_return_val_if_fail (prompt_path != NULL, NULL);
2404         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2405         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2406
2407         prompt = _secret_prompt_instance (self, prompt_path);
2408         retval = secret_service_prompt_sync (self, prompt, cancellable, return_type, error);
2409         g_object_unref (prompt);
2410
2411         return retval;
2412 }
2413
2414 /**
2415  * secret_service_prompt_at_dbus_path:
2416  * @self: the secret service
2417  * @prompt_path: the D-Bus object path of the prompt
2418  * @cancellable: optional cancellation object
2419  * @callback: called when the operation completes
2420  * @user_data: data to be passed to the callback
2421  *
2422  * Perform prompting for a #SecretPrompt.
2423  *
2424  * This function is called by other parts of this library to handle prompts
2425  * for the various actions that can require prompting.
2426  *
2427  * Override the #SecretServiceClass <literal>prompt_async</literal> virtual method
2428  * to change the behavior of the propmting. The default behavior is to simply
2429  * run secret_prompt_perform() on the prompt.
2430  */
2431 void
2432 secret_service_prompt_at_dbus_path (SecretService *self,
2433                                     const gchar *prompt_path,
2434                                     GCancellable *cancellable,
2435                                     GAsyncReadyCallback callback,
2436                                     gpointer user_data)
2437 {
2438         SecretPrompt *prompt;
2439
2440         g_return_if_fail (SECRET_IS_SERVICE (self));
2441         g_return_if_fail (prompt_path != NULL);
2442         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2443
2444         prompt = _secret_prompt_instance (self, prompt_path);
2445         secret_service_prompt (self, prompt, cancellable, callback, user_data);
2446         g_object_unref (prompt);
2447 }
2448
2449 /**
2450  * secret_service_prompt_at_dbus_path_finish:
2451  * @self: the secret service
2452  * @result: the asynchronous result passed to the callback
2453  * @return_type: the variant type of the prompt result
2454  * @error: location to place an error on failure
2455  *
2456  * Complete asynchronous operation to perform prompting for a #SecretPrompt.
2457  *
2458  * Returns a variant result if the prompt was completed and not dismissed. The
2459  * type of result depends on the action the prompt is completing, and is defined
2460  * in the Secret Service DBus API specification.
2461  *
2462  * Returns: (transfer full): %NULL if the prompt was dismissed or an error occurred,
2463  *          a variant result if the prompt was successful
2464  */
2465 GVariant *
2466 secret_service_prompt_at_dbus_path_finish (SecretService *self,
2467                                            GAsyncResult *result,
2468                                            const GVariantType *return_type,
2469                                            GError **error)
2470 {
2471         g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
2472         g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
2473         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2474
2475         return secret_service_prompt_finish (self, result, return_type, error);
2476 }