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