LCOV - code coverage report
Current view: top level - libsecret - secret-methods.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 593 713 83.2 %
Date: 2024-02-08 14:44:34 Functions: 50 56 89.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 343 746 46.0 %

           Branch data     Line data    Source code
       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-collection.h"
      19                 :            : #include "secret-dbus-generated.h"
      20                 :            : #include "secret-item.h"
      21                 :            : #include "secret-paths.h"
      22                 :            : #include "secret-private.h"
      23                 :            : #include "secret-service.h"
      24                 :            : #include "secret-types.h"
      25                 :            : #include "secret-value.h"
      26                 :            : 
      27                 :            : #include <glib/gi18n-lib.h>
      28                 :            : 
      29                 :            : /**
      30                 :            :  * SecretSearchFlags:
      31                 :            :  * @SECRET_SEARCH_NONE: no flags
      32                 :            :  * @SECRET_SEARCH_ALL: all the items matching the search will be returned, instead of just the first one
      33                 :            :  * @SECRET_SEARCH_UNLOCK: unlock locked items while searching
      34                 :            :  * @SECRET_SEARCH_LOAD_SECRETS: while searching load secrets for items that are not locked
      35                 :            :  *
      36                 :            :  * Various flags to be used with [method@Service.search] and [method@Service.search_sync].
      37                 :            :  */
      38                 :            : 
      39                 :            : typedef struct {
      40                 :            :         SecretService *service;
      41                 :            :         GHashTable *items;
      42                 :            :         gchar **unlocked;
      43                 :            :         gchar **locked;
      44                 :            :         guint loading;
      45                 :            :         SecretSearchFlags flags;
      46                 :            :         GVariant *attributes;
      47                 :            : } SearchClosure;
      48                 :            : 
      49                 :            : static void
      50                 :          8 : search_closure_free (gpointer data)
      51                 :            : {
      52                 :          8 :         SearchClosure *closure = data;
      53         [ +  - ]:          8 :         g_clear_object (&closure->service);
      54                 :          8 :         g_hash_table_unref (closure->items);
      55                 :          8 :         g_variant_unref (closure->attributes);
      56                 :          8 :         g_strfreev (closure->unlocked);
      57                 :          8 :         g_strfreev (closure->locked);
      58                 :          8 :         g_free (closure);
      59                 :          8 : }
      60                 :            : 
      61                 :            : static void
      62                 :         10 : search_closure_take_item (SearchClosure *closure,
      63                 :            :                           SecretItem *item)
      64                 :            : {
      65                 :         10 :         const gchar *path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
      66                 :         10 :         g_hash_table_insert (closure->items, (gpointer)path, item);
      67                 :         10 : }
      68                 :            : 
      69                 :            : static GList *
      70                 :         16 : search_closure_build_items (SearchClosure *closure,
      71                 :            :                             gchar **paths)
      72                 :            : {
      73                 :         16 :         GList *results = NULL;
      74                 :            :         SecretItem *item;
      75                 :            :         guint i;
      76                 :            : 
      77         [ +  + ]:         27 :         for (i = 0; paths[i]; i++) {
      78                 :         11 :                 item = g_hash_table_lookup (closure->items, paths[i]);
      79         [ +  + ]:         11 :                 if (item != NULL)
      80                 :         10 :                         results = g_list_prepend (results, g_object_ref (item));
      81                 :            :         }
      82                 :            : 
      83                 :         16 :         return g_list_reverse (results);
      84                 :            : }
      85                 :            : 
      86                 :            : static void
      87                 :          1 : on_search_secrets (GObject *source,
      88                 :            :                    GAsyncResult *result,
      89                 :            :                    gpointer user_data)
      90                 :            : {
      91                 :          1 :         GTask *task = G_TASK (user_data);
      92                 :            : 
      93                 :            :         /* Note that we ignore any unlock failure */
      94                 :          1 :         secret_item_load_secrets_finish (result, NULL);
      95                 :          1 :         g_task_return_boolean (task, TRUE);
      96                 :            : 
      97         [ +  - ]:          1 :         g_clear_object (&task);
      98                 :          1 : }
      99                 :            : 
     100                 :            : static void
     101                 :          8 : secret_search_load_or_complete (GTask *task,
     102                 :            :                                 SearchClosure *search)
     103                 :            : {
     104                 :          8 :         GCancellable *cancellable = g_task_get_cancellable (task);
     105                 :            :         GList *items;
     106                 :            : 
     107                 :            :         /* If loading secrets ... locked items automatically ignored */
     108         [ +  + ]:          8 :         if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
     109                 :          1 :                 items = g_hash_table_get_values (search->items);
     110                 :          1 :                 secret_item_load_secrets (items, cancellable,
     111                 :            :                                           on_search_secrets, g_object_ref (task));
     112                 :          1 :                 g_list_free (items);
     113                 :            : 
     114                 :            :         /* No additional options, just complete */
     115                 :            :         } else {
     116                 :          7 :                 g_task_return_boolean (task, TRUE);
     117                 :            :         }
     118                 :          8 : }
     119                 :            : 
     120                 :            : static void
     121                 :         10 : on_search_loaded (GObject *source,
     122                 :            :                   GAsyncResult *result,
     123                 :            :                   gpointer user_data)
     124                 :            : {
     125                 :         10 :         GTask *task = G_TASK (user_data);
     126                 :         10 :         SearchClosure *closure = g_task_get_task_data (task);
     127                 :         10 :         GError *error = NULL;
     128                 :            :         SecretItem *item;
     129                 :            : 
     130                 :         10 :         closure->loading--;
     131                 :            : 
     132                 :         10 :         item = secret_item_new_for_dbus_path_finish (result, &error);
     133         [ -  + ]:         10 :         if (error != NULL) {
     134                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
     135         [ #  # ]:          0 :                 g_clear_object (&task);
     136                 :          0 :                 return;
     137                 :            :         }
     138                 :            : 
     139         [ +  - ]:         10 :         if (item != NULL)
     140                 :         10 :                 search_closure_take_item (closure, item);
     141                 :            : 
     142                 :            :         /* We're done loading, lets go to the next step */
     143         [ +  + ]:         10 :         if (closure->loading == 0)
     144                 :          7 :                 secret_search_load_or_complete (task, closure);
     145                 :            : 
     146         [ +  - ]:         10 :         g_clear_object (&task);
     147                 :            : }
     148                 :            : 
     149                 :            : static void
     150                 :         10 : search_load_item_async (SecretService *self,
     151                 :            :                         GTask *task,
     152                 :            :                         SearchClosure *closure,
     153                 :            :                         const gchar *path)
     154                 :            : {
     155                 :         10 :         GCancellable *cancellable = g_task_get_cancellable (task);
     156                 :            :         SecretItem *item;
     157                 :            : 
     158                 :         10 :         item = _secret_service_find_item_instance (self, path);
     159         [ +  - ]:         10 :         if (item == NULL) {
     160                 :         10 :                 secret_item_new_for_dbus_path (self, path, SECRET_ITEM_NONE, cancellable,
     161                 :            :                                                on_search_loaded, g_object_ref (task));
     162                 :         10 :                 closure->loading++;
     163                 :            :         } else {
     164                 :          0 :                 search_closure_take_item (closure, item);
     165                 :            :         }
     166                 :         10 : }
     167                 :            : 
     168                 :            : static void
     169                 :          8 : load_items (SearchClosure *closure,
     170                 :            :             GTask *task)
     171                 :            : {
     172                 :          8 :         SecretService *self = closure->service;
     173                 :          8 :         gint want = 1;
     174                 :          8 :         gint count = 0;
     175                 :            :         gint i;
     176                 :            : 
     177         [ +  + ]:          8 :         if (closure->flags & SECRET_SEARCH_ALL)
     178                 :          7 :                 want = G_MAXINT;
     179                 :            : 
     180   [ +  +  +  + ]:         14 :         for (i = 0; count < want && closure->unlocked[i] != NULL; i++, count++)
     181                 :          6 :                 search_load_item_async (self, task, closure, closure->unlocked[i]);
     182   [ +  +  +  + ]:         12 :         for (i = 0; count < want && closure->locked[i] != NULL; i++, count++)
     183                 :          4 :                 search_load_item_async (self, task, closure, closure->locked[i]);
     184                 :            : 
     185                 :            :         /* No items loading, complete operation now */
     186         [ +  + ]:          8 :         if (closure->loading == 0)
     187                 :          1 :                 secret_search_load_or_complete (task, closure);
     188                 :          8 : }
     189                 :            : 
     190                 :            : static void
     191                 :          1 : on_unlock_paths (GObject *source,
     192                 :            :                  GAsyncResult *result,
     193                 :            :                  gpointer user_data)
     194                 :            : {
     195                 :          1 :         GTask *task = G_TASK (user_data);
     196                 :          1 :         SearchClosure *closure = g_task_get_task_data (task);
     197                 :          1 :         SecretService *self = closure->service;
     198                 :            : 
     199                 :            :         /* Note that we ignore any unlock failure */
     200                 :          1 :         secret_service_unlock_dbus_paths_finish (self, result, NULL, NULL);
     201                 :            : 
     202                 :          1 :         load_items (closure, task);
     203         [ +  - ]:          1 :         g_clear_object (&task);
     204                 :          1 : }
     205                 :            : 
     206                 :            : static void
     207                 :          8 : on_search_paths (GObject *source,
     208                 :            :                  GAsyncResult *result,
     209                 :            :                  gpointer user_data)
     210                 :            : {
     211                 :          8 :         GTask *task = G_TASK (user_data);
     212                 :          8 :         SearchClosure *closure = g_task_get_task_data (task);
     213                 :          8 :         SecretService *self = closure->service;
     214                 :          8 :         GError *error = NULL;
     215                 :            : 
     216                 :          8 :         secret_service_search_for_dbus_paths_finish (self, result, &closure->unlocked,
     217                 :            :                                                      &closure->locked, &error);
     218         [ +  - ]:          8 :         if (error == NULL) {
     219                 :            :                 /* If unlocking then unlock all the locked items */
     220         [ +  + ]:          8 :                 if (closure->flags & SECRET_SEARCH_UNLOCK) {
     221                 :          1 :                         GCancellable *cancellable = g_task_get_cancellable (task);
     222                 :          1 :                         const gchar **const_locked = (const gchar**) closure->locked;
     223                 :            : 
     224                 :          1 :                         secret_service_unlock_dbus_paths (self, const_locked, cancellable,
     225                 :            :                                                           on_unlock_paths,
     226                 :            :                                                           g_steal_pointer (&task));
     227                 :            :                 } else {
     228                 :          7 :                         load_items (closure, task);
     229                 :            :                 }
     230                 :            :         } else {
     231                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
     232                 :            :         }
     233                 :            : 
     234         [ +  + ]:          8 :         g_clear_object (&task);
     235                 :          8 : }
     236                 :            : 
     237                 :            : static void
     238                 :          0 : on_search_service (GObject *source,
     239                 :            :                    GAsyncResult *result,
     240                 :            :                    gpointer user_data)
     241                 :            : {
     242                 :          0 :         GTask *task = G_TASK (user_data);
     243                 :          0 :         SearchClosure *search = g_task_get_task_data (task);
     244                 :          0 :         GCancellable *cancellable = g_task_get_cancellable (task);
     245                 :          0 :         GError *error = NULL;
     246                 :            : 
     247                 :          0 :         search->service = secret_service_get_finish (result, &error);
     248         [ #  # ]:          0 :         if (error == NULL) {
     249                 :          0 :                 _secret_service_search_for_paths_variant (search->service, search->attributes,
     250                 :            :                                                           cancellable, on_search_paths,
     251                 :            :                                                           g_steal_pointer (&task));
     252                 :            : 
     253                 :            :         } else {
     254                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
     255                 :            :         }
     256                 :            : 
     257         [ #  # ]:          0 :         g_clear_object (&task);
     258                 :          0 : }
     259                 :            : 
     260                 :            : /**
     261                 :            :  * secret_service_search:
     262                 :            :  * @service: (nullable): the secret service
     263                 :            :  * @schema: (nullable): the schema for the attributes
     264                 :            :  * @attributes: (element-type utf8 utf8): search for items matching these attributes
     265                 :            :  * @flags: search option flags
     266                 :            :  * @cancellable: (nullable): optional cancellation object
     267                 :            :  * @callback: called when the operation completes
     268                 :            :  * @user_data: data to pass to the callback
     269                 :            :  *
     270                 :            :  * Search for items matching the @attributes.
     271                 :            :  *
     272                 :            :  * All collections are searched. The @attributes should be a table of string
     273                 :            :  * keys and string values.
     274                 :            :  *
     275                 :            :  * If @service is %NULL, then [func@Service.get] will be called to get
     276                 :            :  * the default [class@Service] proxy.
     277                 :            :  *
     278                 :            :  * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
     279                 :            :  * search will be returned. Otherwise only the first item will be returned.
     280                 :            :  * This is almost always the unlocked item that was most recently stored.
     281                 :            :  *
     282                 :            :  * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
     283                 :            :  * if necessary. In either case, locked and unlocked items will match the
     284                 :            :  * search and be returned. If the unlock fails, the search does not fail.
     285                 :            :  *
     286                 :            :  * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
     287                 :            :  * their secret values loaded and available via [method@Item.get_secret].
     288                 :            :  *
     289                 :            :  * This function returns immediately and completes asynchronously.
     290                 :            :  */
     291                 :            : void
     292                 :          8 : secret_service_search (SecretService *service,
     293                 :            :                        const SecretSchema *schema,
     294                 :            :                        GHashTable *attributes,
     295                 :            :                        SecretSearchFlags flags,
     296                 :            :                        GCancellable *cancellable,
     297                 :            :                        GAsyncReadyCallback callback,
     298                 :            :                        gpointer user_data)
     299                 :            : {
     300                 :            :         GTask *task;
     301                 :            :         SearchClosure *closure;
     302                 :          8 :         const gchar *schema_name = NULL;
     303                 :            : 
     304   [ +  -  -  +  :          8 :         g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
          +  -  +  -  -  
                      + ]
     305         [ -  + ]:          8 :         g_return_if_fail (attributes != NULL);
     306   [ -  +  -  -  :          8 :         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
          -  -  -  -  -  
                      - ]
     307                 :            : 
     308                 :            :         /* Warnings raised already */
     309   [ +  -  -  + ]:          8 :         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
     310                 :          0 :                 return;
     311                 :            : 
     312   [ +  -  +  + ]:          8 :         if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME))
     313                 :          7 :                 schema_name = schema->name;
     314                 :            : 
     315                 :          8 :         task = g_task_new (service, cancellable, callback, user_data);
     316         [ +  - ]:          8 :         g_task_set_source_tag (task, secret_service_search);
     317                 :          8 :         closure = g_new0 (SearchClosure, 1);
     318                 :          8 :         closure->items = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
     319                 :          8 :         closure->flags = flags;
     320                 :          8 :         closure->attributes = _secret_attributes_to_variant (attributes, schema_name);
     321                 :          8 :         g_variant_ref_sink (closure->attributes);
     322                 :          8 :         g_task_set_task_data (task, closure, search_closure_free);
     323                 :            : 
     324         [ +  - ]:          8 :         if (service) {
     325                 :          8 :                 closure->service = g_object_ref (service);
     326                 :          8 :                 _secret_service_search_for_paths_variant (closure->service, closure->attributes,
     327                 :            :                                                           cancellable, on_search_paths,
     328                 :            :                                                           g_steal_pointer (&task));
     329                 :            : 
     330                 :            :         } else {
     331                 :          0 :                 secret_service_get (SECRET_SERVICE_NONE, cancellable,
     332                 :            :                                     on_search_service, g_steal_pointer (&task));
     333                 :            :         }
     334                 :            : 
     335         [ -  + ]:          8 :         g_clear_object (&task);
     336                 :            : }
     337                 :            : 
     338                 :            : /**
     339                 :            :  * secret_service_search_finish:
     340                 :            :  * @service: (nullable): the secret service
     341                 :            :  * @result: asynchronous result passed to callback
     342                 :            :  * @error: location to place error on failure
     343                 :            :  *
     344                 :            :  * Complete asynchronous operation to search for items.
     345                 :            :  *
     346                 :            :  * Returns: (transfer full) (element-type Secret.Item):
     347                 :            :  *   a list of items that matched the search
     348                 :            :  */
     349                 :            : GList *
     350                 :          8 : secret_service_search_finish (SecretService *service,
     351                 :            :                               GAsyncResult *result,
     352                 :            :                               GError **error)
     353                 :            : {
     354                 :            :         SearchClosure *closure;
     355                 :          8 :         GList *items = NULL;
     356                 :            : 
     357   [ +  -  -  +  :          8 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
          +  -  +  -  -  
                      + ]
     358   [ +  -  -  + ]:          8 :         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     359         [ -  + ]:          8 :         g_return_val_if_fail (g_task_is_valid (result, service), NULL);
     360                 :            : 
     361         [ -  + ]:          8 :         if (!g_task_propagate_boolean (G_TASK (result), error)) {
     362                 :          0 :                 _secret_util_strip_remote_error (error);
     363                 :          0 :                 return NULL;
     364                 :            :         }
     365                 :            : 
     366                 :          8 :         closure = g_task_get_task_data (G_TASK (result));
     367         [ +  - ]:          8 :         if (closure->unlocked)
     368                 :          8 :                 items = search_closure_build_items (closure, closure->unlocked);
     369         [ +  - ]:          8 :         if (closure->locked)
     370                 :          8 :                 items = g_list_concat (items, search_closure_build_items (closure, closure->locked));
     371                 :          8 :         return items;
     372                 :            : }
     373                 :            : 
     374                 :            : static gboolean
     375                 :          8 : service_load_items_sync (SecretService *service,
     376                 :            :                          GCancellable *cancellable,
     377                 :            :                          gchar **paths,
     378                 :            :                          GList **items,
     379                 :            :                          gint want,
     380                 :            :                          gint *have,
     381                 :            :                          GError **error)
     382                 :            : {
     383                 :            :         SecretItem *item;
     384                 :            :         guint i;
     385                 :            : 
     386   [ +  +  +  + ]:         15 :         for (i = 0; *have < want && paths[i] != NULL; i++) {
     387                 :          7 :                 item = _secret_service_find_item_instance (service, paths[i]);
     388         [ +  - ]:          7 :                 if (item == NULL)
     389                 :          7 :                         item = secret_item_new_for_dbus_path_sync (service, paths[i], SECRET_ITEM_NONE,
     390                 :            :                                                                    cancellable, error);
     391         [ -  + ]:          7 :                 if (item == NULL) {
     392                 :          0 :                         return FALSE;
     393                 :            : 
     394                 :            :                 } else {
     395                 :          7 :                         *items = g_list_prepend (*items, item);
     396                 :          7 :                         (*have)++;
     397                 :            :                 }
     398                 :            :         }
     399                 :            : 
     400                 :          8 :         return TRUE;
     401                 :            : }
     402                 :            : 
     403                 :            : /**
     404                 :            :  * secret_service_search_sync:
     405                 :            :  * @service: (nullable): the secret service
     406                 :            :  * @schema: (nullable): the schema for the attributes
     407                 :            :  * @attributes: (element-type utf8 utf8): search for items matching these attributes
     408                 :            :  * @flags: search option flags
     409                 :            :  * @cancellable: (nullable): optional cancellation object
     410                 :            :  * @error: location to place error on failure
     411                 :            :  *
     412                 :            :  * Search for items matching the @attributes.
     413                 :            :  *
     414                 :            :  * All collections are searched. The @attributes should be a table of string
     415                 :            :  * keys and string values.
     416                 :            :  *
     417                 :            :  * If @service is %NULL, then [func@Service.get_sync] will be called to get
     418                 :            :  * the default [class@Service] proxy.
     419                 :            :  *
     420                 :            :  * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
     421                 :            :  * search will be returned. Otherwise only the first item will be returned.
     422                 :            :  * This is almost always the unlocked item that was most recently stored.
     423                 :            :  *
     424                 :            :  * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
     425                 :            :  * if necessary. In either case, locked and unlocked items will match the
     426                 :            :  * search and be returned. If the unlock fails, the search does not fail.
     427                 :            :  *
     428                 :            :  * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items' secret
     429                 :            :  * values will be loaded for any unlocked items. Loaded item secret values
     430                 :            :  * are available via [method@Item.get_secret]. If the load of a secret values
     431                 :            :  * fail, then the
     432                 :            :  *
     433                 :            :  * This function may block indefinitely. Use the asynchronous version
     434                 :            :  * in user interface threads.
     435                 :            :  *
     436                 :            :  * Returns: (transfer full) (element-type Secret.Item):
     437                 :            :  *   a list of items that matched the search
     438                 :            :  */
     439                 :            : GList *
     440                 :          4 : secret_service_search_sync (SecretService *service,
     441                 :            :                             const SecretSchema *schema,
     442                 :            :                             GHashTable *attributes,
     443                 :            :                             SecretSearchFlags flags,
     444                 :            :                             GCancellable *cancellable,
     445                 :            :                             GError **error)
     446                 :            : {
     447                 :          4 :         gchar **unlocked_paths = NULL;
     448                 :          4 :         gchar **locked_paths = NULL;
     449                 :          4 :         GList *items = NULL;
     450                 :          4 :         GList *locked = NULL;
     451                 :          4 :         GList *unlocked = NULL;
     452                 :            :         gboolean ret;
     453                 :            :         gint want;
     454                 :            :         gint have;
     455                 :            : 
     456   [ +  -  -  +  :          4 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
          +  -  +  -  -  
                      + ]
     457   [ -  +  -  -  :          4 :         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
          -  -  -  -  -  
                      - ]
     458   [ +  -  -  + ]:          4 :         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     459                 :            : 
     460                 :            :         /* Warnings raised already */
     461   [ +  -  -  + ]:          4 :         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
     462                 :          0 :                 return NULL;
     463                 :            : 
     464         [ -  + ]:          4 :         if (service == NULL) {
     465                 :          0 :                 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
     466         [ #  # ]:          0 :                 if (service == NULL)
     467                 :          0 :                         return NULL;
     468                 :            :         } else {
     469                 :          4 :                 g_object_ref (service);
     470                 :            :         }
     471                 :            : 
     472         [ -  + ]:          4 :         if (!secret_service_search_for_dbus_paths_sync (service, schema, attributes, cancellable,
     473                 :            :                                                         &unlocked_paths, &locked_paths, error)) {
     474                 :          0 :                 g_object_unref (service);
     475                 :          0 :                 return NULL;
     476                 :            :         }
     477                 :            : 
     478         [ +  + ]:          4 :         if (flags & SECRET_SEARCH_UNLOCK)
     479                 :          1 :                 secret_service_unlock_dbus_paths_sync (service, (const gchar**) locked_paths,
     480                 :            :                                                        cancellable, NULL, NULL);
     481                 :            : 
     482                 :          4 :         ret = TRUE;
     483                 :            : 
     484                 :          4 :         want = 1;
     485         [ +  + ]:          4 :         if (flags & SECRET_SEARCH_ALL)
     486                 :          3 :                 want = G_MAXINT;
     487                 :          4 :         have = 0;
     488                 :            : 
     489                 :            :         /* Remember, we're adding to the list backwards */
     490                 :            : 
     491         [ +  - ]:          4 :         if (unlocked_paths) {
     492                 :          4 :                 ret = service_load_items_sync (service, cancellable, unlocked_paths,
     493                 :            :                                                &unlocked, want, &have, error);
     494                 :            :         }
     495                 :            : 
     496   [ +  -  +  - ]:          4 :         if (ret && locked_paths) {
     497                 :          4 :                 ret = service_load_items_sync (service, cancellable, locked_paths,
     498                 :            :                                                &locked, want, &have, error);
     499                 :            :         }
     500                 :            : 
     501                 :          4 :         g_strfreev (unlocked_paths);
     502                 :          4 :         g_strfreev (locked_paths);
     503                 :            : 
     504         [ -  + ]:          4 :         if (!ret) {
     505                 :          0 :                 g_list_free_full (unlocked, g_object_unref);
     506                 :          0 :                 g_list_free_full (locked, g_object_unref);
     507                 :          0 :                 g_object_unref (service);
     508                 :          0 :                 return NULL;
     509                 :            :         }
     510                 :            : 
     511                 :            :         /* The lists are backwards at this point ... */
     512                 :          4 :         items = g_list_concat (items, g_list_copy (locked));
     513                 :          4 :         items = g_list_concat (items, g_list_copy (unlocked));
     514                 :          4 :         items = g_list_reverse (items);
     515                 :            : 
     516         [ +  + ]:          4 :         if (flags & SECRET_SEARCH_LOAD_SECRETS)
     517                 :          1 :                 secret_item_load_secrets_sync (items, NULL, NULL);
     518                 :            : 
     519                 :          4 :         g_list_free (locked);
     520                 :          4 :         g_list_free (unlocked);
     521                 :          4 :         g_object_unref (service);
     522                 :          4 :         return items;
     523                 :            : }
     524                 :            : 
     525                 :            : SecretValue *
     526                 :         23 : _secret_service_decode_get_secrets_first (SecretService *self,
     527                 :            :                                           GVariant *out)
     528                 :            : {
     529                 :            :         SecretSession *session;
     530                 :         23 :         SecretValue *value = NULL;
     531                 :            :         GVariantIter *iter;
     532                 :            :         GVariant *variant;
     533                 :            :         const gchar *path;
     534                 :            : 
     535                 :         23 :         g_variant_get (out, "(a{o(oayays)})", &iter);
     536         [ +  - ]:         23 :         while (g_variant_iter_next (iter, "{&o@(oayays)}", &path, &variant)) {
     537                 :         23 :                 session = _secret_service_get_session (self);
     538                 :         23 :                 value = _secret_session_decode_secret (session, variant);
     539                 :         23 :                 g_variant_unref (variant);
     540                 :         23 :                 break;
     541                 :            :         }
     542                 :         23 :         g_variant_iter_free (iter);
     543                 :         23 :         return value;
     544                 :            : }
     545                 :            : 
     546                 :            : GHashTable *
     547                 :          8 : _secret_service_decode_get_secrets_all (SecretService *self,
     548                 :            :                                         GVariant *out)
     549                 :            : {
     550                 :            :         SecretSession *session;
     551                 :            :         GVariantIter *iter;
     552                 :            :         GVariant *variant;
     553                 :            :         GHashTable *values;
     554                 :            :         SecretValue *value;
     555                 :            :         gchar *path;
     556                 :            : 
     557                 :          8 :         session = _secret_service_get_session (self);
     558                 :          8 :         values = g_hash_table_new_full (g_str_hash, g_str_equal,
     559                 :            :                                         g_free, secret_value_unref);
     560                 :          8 :         g_variant_get (out, "(a{o(oayays)})", &iter);
     561         [ +  + ]:         20 :         while (g_variant_iter_loop (iter, "{o@(oayays)}", &path, &variant)) {
     562                 :         12 :                 value = _secret_session_decode_secret (session, variant);
     563   [ +  -  +  - ]:         12 :                 if (value && path)
     564                 :         24 :                         g_hash_table_insert (values, g_strdup (path), value);
     565                 :            :         }
     566                 :          8 :         g_variant_iter_free (iter);
     567                 :          8 :         return values;
     568                 :            : }
     569                 :            : 
     570                 :            : typedef struct {
     571                 :            :         GPtrArray *paths;
     572                 :            :         GHashTable *objects;
     573                 :            :         gchar **xlocked;
     574                 :            :         gboolean locking;
     575                 :            : } XlockClosure;
     576                 :            : 
     577                 :            : static void
     578                 :          5 : xlock_closure_free (gpointer data)
     579                 :            : {
     580                 :          5 :         XlockClosure *closure = data;
     581                 :          5 :         g_ptr_array_free (closure->paths, TRUE);
     582                 :          5 :         g_strfreev (closure->xlocked);
     583                 :          5 :         g_hash_table_unref (closure->objects);
     584                 :          5 :         g_free (closure);
     585                 :          5 : }
     586                 :            : 
     587                 :            : static void
     588                 :          5 : on_xlock_paths (GObject *source,
     589                 :            :                 GAsyncResult *result,
     590                 :            :                 gpointer user_data)
     591                 :            : {
     592                 :          5 :         SecretService *service = SECRET_SERVICE (source);
     593                 :          5 :         GTask *task = G_TASK (user_data);
     594                 :          5 :         XlockClosure *xlock = g_task_get_task_data (task);
     595                 :            :         GVariant *lockval;
     596                 :            :         GDBusProxy *object;
     597                 :          5 :         GError *error = NULL;
     598                 :            :         gint count;
     599                 :            :         gint i;
     600                 :            : 
     601                 :          5 :         count = _secret_service_xlock_paths_finish (service, result,
     602                 :            :                                                     &xlock->xlocked, &error);
     603                 :            : 
     604         [ +  - ]:          5 :         if (error == NULL) {
     605                 :            :                 /*
     606                 :            :                  * After a lock or unlock we want the Locked property to immediately
     607                 :            :                  * reflect the new state, and not have to wait for a PropertiesChanged
     608                 :            :                  * signal to be processed later.
     609                 :            :                  */
     610                 :            : 
     611                 :          5 :                 lockval = g_variant_ref_sink (g_variant_new_boolean (xlock->locking));
     612         [ +  + ]:         10 :                 for (i = 0; xlock->xlocked[i] != NULL; i++) {
     613                 :          5 :                         object =  g_hash_table_lookup (xlock->objects, xlock->xlocked[i]);
     614         [ +  - ]:          5 :                         if (object != NULL)
     615                 :          5 :                                 g_dbus_proxy_set_cached_property (object, "Locked", lockval);
     616                 :            :                 }
     617                 :          5 :                 g_variant_unref (lockval);
     618                 :          5 :                 g_task_return_int (task, count);
     619                 :            : 
     620                 :            :         } else {
     621                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
     622                 :            :         }
     623                 :            : 
     624         [ +  - ]:          5 :         g_clear_object (&task);
     625                 :          5 : }
     626                 :            : 
     627                 :            : static void
     628                 :          0 : on_xlock_service (GObject *source,
     629                 :            :                   GAsyncResult *result,
     630                 :            :                   gpointer user_data)
     631                 :            : {
     632                 :          0 :         GTask *task = G_TASK (user_data);
     633                 :          0 :         XlockClosure *xlock = g_task_get_task_data (task);
     634                 :          0 :         GCancellable *cancellable = g_task_get_cancellable (task);
     635                 :          0 :         GError *error = NULL;
     636                 :            :         SecretService *service;
     637                 :            : 
     638                 :          0 :         service = secret_service_get_finish (result, &error);
     639         [ #  # ]:          0 :         if (error == NULL) {
     640                 :          0 :                 _secret_service_xlock_paths_async (service, xlock->locking ? "Lock" : "Unlock",
     641         [ #  # ]:          0 :                                                    (const gchar **)xlock->paths->pdata,
     642                 :            :                                                    cancellable, on_xlock_paths,
     643                 :            :                                                    g_steal_pointer (&task));
     644                 :          0 :                 g_object_unref (service);
     645                 :            : 
     646                 :            :         } else {
     647                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
     648                 :            :         }
     649                 :            : 
     650         [ #  # ]:          0 :         g_clear_object (&task);
     651                 :          0 : }
     652                 :            : 
     653                 :            : static void
     654                 :          5 : service_xlock_async (SecretService *service,
     655                 :            :                      gboolean locking,
     656                 :            :                      GList *objects,
     657                 :            :                      GCancellable *cancellable,
     658                 :            :                      GAsyncReadyCallback callback,
     659                 :            :                      gpointer user_data)
     660                 :            : {
     661                 :            :         GTask *task;
     662                 :            :         XlockClosure *xlock;
     663                 :            :         const gchar *path;
     664                 :            :         GList *l;
     665                 :            : 
     666                 :          5 :         task = g_task_new (service, cancellable, callback, user_data);
     667         [ +  - ]:          5 :         g_task_set_source_tag (task, service_xlock_async);
     668                 :          5 :         xlock = g_new0 (XlockClosure, 1);
     669                 :          5 :         xlock->objects = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
     670                 :          5 :         xlock->locking = locking;
     671                 :          5 :         xlock->paths = g_ptr_array_new ();
     672                 :            : 
     673   [ +  -  +  + ]:         10 :         for (l = objects; l != NULL; l = g_list_next (l)) {
     674                 :          5 :                 path = g_dbus_proxy_get_object_path (l->data);
     675                 :          5 :                 g_ptr_array_add (xlock->paths, (gpointer)path);
     676                 :         10 :                 g_hash_table_insert (xlock->objects, g_strdup (path), g_object_ref (l->data));
     677                 :            :         }
     678                 :          5 :         g_ptr_array_add (xlock->paths, NULL);
     679                 :            : 
     680                 :          5 :         g_task_set_task_data (task, xlock, xlock_closure_free);
     681                 :            : 
     682         [ -  + ]:          5 :         if (service == NULL) {
     683                 :          0 :                 secret_service_get (SECRET_SERVICE_NONE, cancellable,
     684                 :            :                                     on_xlock_service, g_steal_pointer (&task));
     685                 :            :         } else {
     686                 :         10 :                 _secret_service_xlock_paths_async (service, xlock->locking ? "Lock" : "Unlock",
     687         [ +  + ]:          5 :                                                    (const gchar **)xlock->paths->pdata,
     688                 :            :                                                    cancellable, on_xlock_paths,
     689                 :            :                                                    g_steal_pointer (&task));
     690                 :            :         }
     691                 :            : 
     692         [ -  + ]:          5 :         g_clear_object (&task);
     693                 :          5 : }
     694                 :            : 
     695                 :            : static gint
     696                 :          5 : service_xlock_finish (SecretService *service,
     697                 :            :                       GAsyncResult *result,
     698                 :            :                       GList **xlocked,
     699                 :            :                       GError **error)
     700                 :            : {
     701                 :            :         XlockClosure *xlock;
     702                 :            :         GDBusProxy *object;
     703                 :            :         gint count;
     704                 :            :         gint i;
     705                 :            : 
     706         [ -  + ]:          5 :         g_return_val_if_fail (g_task_is_valid (result, service), -1);
     707                 :            : 
     708                 :          5 :         count = g_task_propagate_int (G_TASK (result), error);
     709         [ -  + ]:          5 :         if (count == -1) {
     710                 :          0 :                 _secret_util_strip_remote_error (error);
     711                 :          0 :                 return -1;
     712                 :            :         }
     713                 :            : 
     714                 :          5 :         xlock = g_task_get_task_data (G_TASK (result));
     715         [ +  + ]:          5 :         if (xlocked) {
     716                 :          2 :                 *xlocked = NULL;
     717         [ +  + ]:          4 :                 for (i = 0; xlock->xlocked[i] != NULL; i++) {
     718                 :          2 :                         object = g_hash_table_lookup (xlock->objects, xlock->xlocked[i]);
     719         [ +  - ]:          2 :                         if (object != NULL)
     720                 :          2 :                                 *xlocked = g_list_prepend (*xlocked, g_object_ref (object));
     721                 :            :                 }
     722                 :            :         }
     723                 :            : 
     724                 :          5 :         return count;
     725                 :            : }
     726                 :            : 
     727                 :            : /**
     728                 :            :  * secret_service_lock:
     729                 :            :  * @service: (nullable): the secret service
     730                 :            :  * @objects: (element-type Gio.DBusProxy): the items or collections to lock
     731                 :            :  * @cancellable: (nullable): optional cancellation object
     732                 :            :  * @callback: called when the operation completes
     733                 :            :  * @user_data: data to pass to the callback
     734                 :            :  *
     735                 :            :  * Lock items or collections in the secret service.
     736                 :            :  *
     737                 :            :  * The secret service may not be able to lock items individually, and may
     738                 :            :  * lock an entire collection instead.
     739                 :            :  *
     740                 :            :  * If @service is %NULL, then [func@Service.get] will be called to get
     741                 :            :  * the default [class@Service] proxy.
     742                 :            :  *
     743                 :            :  * This method returns immediately and completes asynchronously. The secret
     744                 :            :  * service may prompt the user. [method@Service.prompt] will be used to handle
     745                 :            :  * any prompts that show up.
     746                 :            :  */
     747                 :            : void
     748                 :          2 : secret_service_lock (SecretService *service,
     749                 :            :                      GList *objects,
     750                 :            :                      GCancellable *cancellable,
     751                 :            :                      GAsyncReadyCallback callback,
     752                 :            :                      gpointer user_data)
     753                 :            : {
     754   [ +  -  -  +  :          2 :         g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
          +  -  +  -  -  
                      + ]
     755   [ -  +  -  -  :          2 :         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
          -  -  -  -  -  
                      - ]
     756                 :            : 
     757                 :          2 :         service_xlock_async (service, TRUE, objects, cancellable, callback, user_data);
     758                 :            : }
     759                 :            : 
     760                 :            : /**
     761                 :            :  * secret_service_lock_finish:
     762                 :            :  * @service: (nullable): the secret service
     763                 :            :  * @result: asynchronous result passed to the callback
     764                 :            :  * @locked: (out) (element-type Gio.DBusProxy) (transfer full) (nullable) (optional):
     765                 :            :  *   location to place list of items or collections that were locked
     766                 :            :  * @error: location to place an error on failure
     767                 :            :  *
     768                 :            :  * Complete asynchronous operation to lock items or collections in the secret
     769                 :            :  * service.
     770                 :            :  *
     771                 :            :  * The secret service may not be able to lock items individually, and may
     772                 :            :  * lock an entire collection instead.
     773                 :            :  *
     774                 :            :  * Returns: the number of items or collections that were locked
     775                 :            :  */
     776                 :            : gint
     777                 :          2 : secret_service_lock_finish (SecretService *service,
     778                 :            :                             GAsyncResult *result,
     779                 :            :                             GList **locked,
     780                 :            :                             GError **error)
     781                 :            : {
     782   [ +  -  -  +  :          2 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), -1);
          +  -  +  -  -  
                      + ]
     783   [ +  -  -  + ]:          2 :         g_return_val_if_fail (error == NULL || *error == NULL, -1);
     784                 :            : 
     785                 :          2 :         return service_xlock_finish (service, result, locked, error);
     786                 :            : }
     787                 :            : 
     788                 :            : /**
     789                 :            :  * secret_service_lock_sync:
     790                 :            :  * @service: (nullable): the secret service
     791                 :            :  * @objects: (element-type Gio.DBusProxy): the items or collections to lock
     792                 :            :  * @cancellable: (nullable): optional cancellation object
     793                 :            :  * @locked: (out) (element-type Gio.DBusProxy) (transfer full) (nullable) (optional):
     794                 :            :  *   location to place list of items or collections that were locked
     795                 :            :  * @error: location to place an error on failure
     796                 :            :  *
     797                 :            :  * Lock items or collections in the secret service.
     798                 :            :  *
     799                 :            :  * The secret service may not be able to lock items individually, and may
     800                 :            :  * lock an entire collection instead.
     801                 :            :  *
     802                 :            :  * If @service is %NULL, then [func@Service.get_sync] will be called to get
     803                 :            :  * the default [class@Service] proxy.
     804                 :            :  *
     805                 :            :  * This method may block indefinitely and should not be used in user
     806                 :            :  * interface threads. The secret service may prompt the user.
     807                 :            :  * [method@Service.prompt] will be used to handle any prompts that show up.
     808                 :            :  *
     809                 :            :  * Returns: the number of items or collections that were locked
     810                 :            :  */
     811                 :            : gint
     812                 :          1 : secret_service_lock_sync (SecretService *service,
     813                 :            :                           GList *objects,
     814                 :            :                           GCancellable *cancellable,
     815                 :            :                           GList **locked,
     816                 :            :                           GError **error)
     817                 :            : {
     818                 :            :         SecretSync *sync;
     819                 :            :         gint count;
     820                 :            : 
     821   [ +  -  -  +  :          1 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), -1);
          +  -  +  -  -  
                      + ]
     822   [ -  +  -  -  :          1 :         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
          -  -  -  -  -  
                      - ]
     823   [ +  -  -  + ]:          1 :         g_return_val_if_fail (error == NULL || *error == NULL, -1);
     824                 :            : 
     825                 :          1 :         sync = _secret_sync_new ();
     826                 :          1 :         g_main_context_push_thread_default (sync->context);
     827                 :            : 
     828                 :          1 :         secret_service_lock (service, objects, cancellable,
     829                 :            :                              _secret_sync_on_result, sync);
     830                 :            : 
     831                 :          1 :         g_main_loop_run (sync->loop);
     832                 :            : 
     833                 :          1 :         count = secret_service_lock_finish (service, sync->result, locked, error);
     834                 :            : 
     835                 :          1 :         g_main_context_pop_thread_default (sync->context);
     836                 :          1 :         _secret_sync_free (sync);
     837                 :            : 
     838                 :          1 :         return count;
     839                 :            : }
     840                 :            : 
     841                 :            : /**
     842                 :            :  * secret_service_unlock:
     843                 :            :  * @service: (nullable): the secret service
     844                 :            :  * @objects: (element-type Gio.DBusProxy): the items or collections to unlock
     845                 :            :  * @cancellable: (nullable): optional cancellation object
     846                 :            :  * @callback: called when the operation completes
     847                 :            :  * @user_data: data to pass to the callback
     848                 :            :  *
     849                 :            :  * Unlock items or collections in the secret service.
     850                 :            :  *
     851                 :            :  * The secret service may not be able to unlock items individually, and may
     852                 :            :  * unlock an entire collection instead.
     853                 :            :  *
     854                 :            :  * If @service is %NULL, then [func@Service.get] will be called to get
     855                 :            :  * the default [class@Service] proxy.
     856                 :            :  *
     857                 :            :  * This method may block indefinitely and should not be used in user
     858                 :            :  * interface threads. The secret service may prompt the user.
     859                 :            :  * [method@Service.prompt] will be used to handle any prompts that show up.
     860                 :            :  */
     861                 :            : void
     862                 :          3 : secret_service_unlock (SecretService *service,
     863                 :            :                        GList *objects,
     864                 :            :                        GCancellable *cancellable,
     865                 :            :                        GAsyncReadyCallback callback,
     866                 :            :                        gpointer user_data)
     867                 :            : {
     868   [ +  -  -  +  :          3 :         g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
          +  -  +  -  -  
                      + ]
     869   [ -  +  -  -  :          3 :         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
          -  -  -  -  -  
                      - ]
     870                 :            : 
     871                 :          3 :         service_xlock_async (service, FALSE, objects, cancellable, callback, user_data);
     872                 :            : }
     873                 :            : 
     874                 :            : /**
     875                 :            :  * secret_service_unlock_finish:
     876                 :            :  * @service: (nullable): the secret service
     877                 :            :  * @result: asynchronous result passed to the callback
     878                 :            :  * @unlocked: (out) (element-type Gio.DBusProxy) (transfer full) (nullable) (optional):
     879                 :            :  *   location to place list of items or collections that were unlocked
     880                 :            :  * @error: location to place an error on failure
     881                 :            :  *
     882                 :            :  * Complete asynchronous operation to unlock items or collections in the secret
     883                 :            :  * service.
     884                 :            :  *
     885                 :            :  * The secret service may not be able to unlock items individually, and may
     886                 :            :  * unlock an entire collection instead.
     887                 :            :  *
     888                 :            :  * Returns: the number of items or collections that were unlocked
     889                 :            :  */
     890                 :            : gint
     891                 :          3 : secret_service_unlock_finish (SecretService *service,
     892                 :            :                               GAsyncResult *result,
     893                 :            :                               GList **unlocked,
     894                 :            :                               GError **error)
     895                 :            : {
     896   [ +  -  -  +  :          3 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), -1);
          +  -  +  -  -  
                      + ]
     897   [ +  +  -  + ]:          3 :         g_return_val_if_fail (error == NULL || *error == NULL, -1);
     898                 :            : 
     899                 :          3 :         return service_xlock_finish (service, result, unlocked, error);
     900                 :            : }
     901                 :            : 
     902                 :            : /**
     903                 :            :  * secret_service_unlock_sync:
     904                 :            :  * @service: (nullable): the secret service
     905                 :            :  * @objects: (element-type Gio.DBusProxy): the items or collections to unlock
     906                 :            :  * @cancellable: (nullable): optional cancellation object
     907                 :            :  * @unlocked: (out) (element-type Gio.DBusProxy) (transfer full) (nullable) (optional):
     908                 :            :  *   location to place list of items or collections that were unlocked
     909                 :            :  * @error: location to place an error on failure
     910                 :            :  *
     911                 :            :  * Unlock items or collections in the secret service.
     912                 :            :  *
     913                 :            :  * The secret service may not be able to unlock items individually, and may
     914                 :            :  * unlock an entire collection instead.
     915                 :            :  *
     916                 :            :  * If @service is %NULL, then [func@Service.get_sync] will be called to get
     917                 :            :  * the default [class@Service] proxy.
     918                 :            :  *
     919                 :            :  * This method may block indefinitely and should not be used in user
     920                 :            :  * interface threads. The secret service may prompt the user.
     921                 :            :  * [method@Service.prompt] will be used to handle any prompts that show up.
     922                 :            :  *
     923                 :            :  * Returns: the number of items or collections that were unlocked
     924                 :            :  */
     925                 :            : gint
     926                 :          2 : secret_service_unlock_sync (SecretService *service,
     927                 :            :                             GList *objects,
     928                 :            :                             GCancellable *cancellable,
     929                 :            :                             GList **unlocked,
     930                 :            :                             GError **error)
     931                 :            : {
     932                 :            :         SecretSync *sync;
     933                 :            :         gint count;
     934                 :            : 
     935   [ +  -  -  +  :          2 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), -1);
          +  -  +  -  -  
                      + ]
     936   [ -  +  -  -  :          2 :         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
          -  -  -  -  -  
                      - ]
     937   [ +  +  -  + ]:          2 :         g_return_val_if_fail (error == NULL || *error == NULL, -1);
     938                 :            : 
     939                 :          2 :         sync = _secret_sync_new ();
     940                 :          2 :         g_main_context_push_thread_default (sync->context);
     941                 :            : 
     942                 :          2 :         secret_service_unlock (service, objects, cancellable,
     943                 :            :                                _secret_sync_on_result, sync);
     944                 :            : 
     945                 :          2 :         g_main_loop_run (sync->loop);
     946                 :            : 
     947                 :          2 :         count = secret_service_unlock_finish (service, sync->result, unlocked, error);
     948                 :            : 
     949                 :          2 :         g_main_context_pop_thread_default (sync->context);
     950                 :          2 :         _secret_sync_free (sync);
     951                 :            : 
     952                 :          2 :         return count;
     953                 :            : }
     954                 :            : 
     955                 :            : typedef struct {
     956                 :            :         gchar *collection_path;
     957                 :            :         SecretValue *value;
     958                 :            :         GHashTable *properties;
     959                 :            :         gboolean created_collection;
     960                 :            :         gboolean unlocked_collection;
     961                 :            : } StoreClosure;
     962                 :            : 
     963                 :            : static void
     964                 :         12 : store_closure_free (gpointer data)
     965                 :            : {
     966                 :         12 :         StoreClosure *store = data;
     967                 :         12 :         g_free (store->collection_path);
     968                 :         12 :         secret_value_unref (store->value);
     969                 :         12 :         g_hash_table_unref (store->properties);
     970                 :         12 :         g_free (store);
     971                 :         12 : }
     972                 :            : 
     973                 :            : static void
     974                 :            : on_store_create (GObject *source,
     975                 :            :                  GAsyncResult *result,
     976                 :            :                  gpointer user_data);
     977                 :            : 
     978                 :            : static void
     979                 :          1 : on_store_keyring (GObject *source,
     980                 :            :                   GAsyncResult *result,
     981                 :            :                   gpointer user_data)
     982                 :            : {
     983                 :          1 :         SecretService *service = SECRET_SERVICE (source);
     984                 :          1 :         GTask *task = G_TASK (user_data);
     985                 :          1 :         StoreClosure *store = g_task_get_task_data (task);
     986                 :          1 :         GCancellable *cancellable = g_task_get_cancellable (task);
     987                 :          1 :         GError *error = NULL;
     988                 :            :         gchar *path;
     989                 :            : 
     990                 :          1 :         path = secret_service_create_collection_dbus_path_finish (service, result, &error);
     991         [ +  - ]:          1 :         if (error == NULL) {
     992                 :          1 :                 store->created_collection = TRUE;
     993                 :          1 :                 secret_service_create_item_dbus_path (service, store->collection_path,
     994                 :            :                                                       store->properties, store->value,
     995                 :            :                                                       SECRET_ITEM_CREATE_REPLACE,
     996                 :            :                                                       cancellable,
     997                 :            :                                                       on_store_create,
     998                 :            :                                                       g_steal_pointer (&task));
     999                 :            :         } else {
    1000                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1001                 :            :         }
    1002                 :            : 
    1003                 :          1 :         g_free (path);
    1004         [ -  + ]:          1 :         g_clear_object (&task);
    1005                 :          1 : }
    1006                 :            : 
    1007                 :            : static void
    1008                 :          1 : on_store_unlock (GObject *source,
    1009                 :            :                  GAsyncResult *result,
    1010                 :            :                  gpointer user_data)
    1011                 :            : {
    1012                 :          1 :         SecretService *service = SECRET_SERVICE (source);
    1013                 :          1 :         GTask *task = G_TASK (user_data);
    1014                 :          1 :         StoreClosure *store = g_task_get_task_data (task);
    1015                 :          1 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1016                 :          1 :         GError *error = NULL;
    1017                 :            : 
    1018                 :          1 :         secret_service_unlock_dbus_paths_finish (service, result, NULL, &error);
    1019         [ +  - ]:          1 :         if (error == NULL) {
    1020                 :          1 :                 store->unlocked_collection = TRUE;
    1021                 :          1 :                 secret_service_create_item_dbus_path (service, store->collection_path,
    1022                 :            :                                                       store->properties, store->value,
    1023                 :            :                                                       SECRET_ITEM_CREATE_REPLACE,
    1024                 :            :                                                       cancellable,
    1025                 :            :                                                       on_store_create,
    1026                 :            :                                                       g_steal_pointer (&task));
    1027                 :            :         } else {
    1028                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1029                 :            :         }
    1030                 :            : 
    1031         [ -  + ]:          1 :         g_clear_object (&task);
    1032                 :          1 : }
    1033                 :            : 
    1034                 :            : static void
    1035                 :         14 : on_store_create (GObject *source,
    1036                 :            :                  GAsyncResult *result,
    1037                 :            :                  gpointer user_data)
    1038                 :            : {
    1039                 :         14 :         SecretService *service = SECRET_SERVICE (source);
    1040                 :         14 :         GTask *task = G_TASK (user_data);
    1041                 :         14 :         StoreClosure *store = g_task_get_task_data (task);
    1042                 :         14 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1043                 :         14 :         GError *error = NULL;
    1044                 :            :         GHashTable *properties;
    1045                 :            : 
    1046                 :         14 :         _secret_service_create_item_dbus_path_finish_raw (result, &error);
    1047                 :            : 
    1048                 :            :         /*
    1049                 :            :          * This happens when the collection doesn't exist. If the collection is
    1050                 :            :          * the default alias, we should try and create it
    1051                 :            :          */
    1052                 :            : 
    1053   [ +  +  +  - ]:         27 :         if (!store->created_collection &&
    1054         [ +  + ]:         26 :             (g_error_matches (error, SECRET_ERROR, SECRET_ERROR_NO_SUCH_OBJECT) ||
    1055         [ -  + ]:         25 :              g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) ||
    1056         [ +  - ]:         13 :              g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_OBJECT)) &&
    1057                 :          1 :             g_strcmp0 (store->collection_path, SECRET_ALIAS_PREFIX "default") == 0) {
    1058                 :          1 :                 properties = _secret_collection_properties_new (_("Default keyring"));
    1059                 :          1 :                 secret_service_create_collection_dbus_path (service, properties, "default",
    1060                 :            :                                                             SECRET_COLLECTION_CREATE_NONE,
    1061                 :            :                                                             cancellable,
    1062                 :            :                                                             on_store_keyring,
    1063                 :            :                                                             g_steal_pointer (&task));
    1064                 :          1 :                 g_hash_table_unref (properties);
    1065                 :          1 :                 g_error_free (error);
    1066         [ -  + ]:          1 :                 g_clear_object (&task);
    1067                 :          2 :                 return;
    1068                 :            :         }
    1069                 :            : 
    1070   [ +  +  +  + ]:         25 :         if (!store->unlocked_collection &&
    1071                 :         12 :                    g_error_matches (error, SECRET_ERROR, SECRET_ERROR_IS_LOCKED)) {
    1072                 :          1 :                 const gchar *paths[2] = { store->collection_path, NULL };
    1073                 :          1 :                 secret_service_unlock_dbus_paths (service, paths, cancellable,
    1074                 :            :                                                   on_store_unlock, g_steal_pointer (&task));
    1075                 :          1 :                 g_error_free (error);
    1076         [ -  + ]:          1 :                 g_clear_object (&task);
    1077                 :          1 :                 return;
    1078                 :            :         }
    1079                 :            : 
    1080         [ -  + ]:         12 :         if (error != NULL)
    1081                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1082                 :            :         else
    1083                 :         12 :                 g_task_return_boolean (task, TRUE);
    1084                 :            : 
    1085         [ +  - ]:         12 :         g_clear_object (&task);
    1086                 :            : }
    1087                 :            : 
    1088                 :            : static void
    1089                 :          0 : on_store_service (GObject *source,
    1090                 :            :                   GAsyncResult *result,
    1091                 :            :                   gpointer user_data)
    1092                 :            : {
    1093                 :          0 :         GTask *task = G_TASK (user_data);
    1094                 :          0 :         StoreClosure *store = g_task_get_task_data (task);
    1095                 :          0 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1096                 :            :         SecretService *service;
    1097                 :          0 :         GError *error = NULL;
    1098                 :            : 
    1099                 :          0 :         service = secret_service_get_finish (result, &error);
    1100         [ #  # ]:          0 :         if (error == NULL) {
    1101                 :          0 :                 secret_service_create_item_dbus_path (service, store->collection_path,
    1102                 :            :                                                       store->properties, store->value,
    1103                 :            :                                                       SECRET_ITEM_CREATE_REPLACE,
    1104                 :            :                                                       cancellable,
    1105                 :            :                                                       on_store_create,
    1106                 :            :                                                       g_steal_pointer (&task));
    1107                 :          0 :                 g_object_unref (service);
    1108                 :            : 
    1109                 :            :         } else {
    1110                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1111                 :            :         }
    1112                 :            : 
    1113         [ #  # ]:          0 :         g_clear_object (&task);
    1114                 :          0 : }
    1115                 :            : 
    1116                 :            : /**
    1117                 :            :  * secret_service_store:
    1118                 :            :  * @service: (nullable): the secret service
    1119                 :            :  * @schema: (nullable): the schema to use to check attributes
    1120                 :            :  * @attributes: (element-type utf8 utf8): the attribute keys and values
    1121                 :            :  * @collection: (nullable): a collection alias, or D-Bus object path of the
    1122                 :            :  *   collection where to store the secret
    1123                 :            :  * @label: label for the secret
    1124                 :            :  * @value: the secret value
    1125                 :            :  * @cancellable: (nullable): optional cancellation object
    1126                 :            :  * @callback: called when the operation completes
    1127                 :            :  * @user_data: data to be passed to the callback
    1128                 :            :  *
    1129                 :            :  * Store a secret value in the secret service.
    1130                 :            :  *
    1131                 :            :  * The @attributes should be a set of key and value string pairs.
    1132                 :            :  *
    1133                 :            :  * If the attributes match a secret item already stored in the collection, then
    1134                 :            :  * the item will be updated with these new values.
    1135                 :            :  *
    1136                 :            :  * If @service is %NULL, then [func@Service.get] will be called to get
    1137                 :            :  * the default [class@Service] proxy.
    1138                 :            :  *
    1139                 :            :  * If @collection is not specified, then the default collection will be
    1140                 :            :  * used. Use [const@COLLECTION_SESSION] to store the password in the session
    1141                 :            :  * collection, which doesn't get stored across login sessions.
    1142                 :            :  *
    1143                 :            :  * This method will return immediately and complete asynchronously.
    1144                 :            :  */
    1145                 :            : void
    1146                 :         12 : secret_service_store (SecretService *service,
    1147                 :            :                       const SecretSchema *schema,
    1148                 :            :                       GHashTable *attributes,
    1149                 :            :                       const gchar *collection,
    1150                 :            :                       const gchar *label,
    1151                 :            :                       SecretValue *value,
    1152                 :            :                       GCancellable *cancellable,
    1153                 :            :                       GAsyncReadyCallback callback,
    1154                 :            :                       gpointer user_data)
    1155                 :            : {
    1156                 :            :         GTask *task;
    1157                 :            :         StoreClosure *store;
    1158                 :            :         const gchar *schema_name;
    1159                 :            :         GVariant *propval;
    1160                 :            : 
    1161   [ +  -  -  +  :         12 :         g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
          +  -  +  -  -  
                      + ]
    1162         [ -  + ]:         12 :         g_return_if_fail (attributes != NULL);
    1163         [ -  + ]:         12 :         g_return_if_fail (label != NULL);
    1164         [ -  + ]:         12 :         g_return_if_fail (value != NULL);
    1165   [ -  +  -  -  :         12 :         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
          -  -  -  -  -  
                      - ]
    1166                 :            : 
    1167                 :            :         /* Warnings raised already */
    1168   [ +  -  -  + ]:         12 :         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
    1169                 :          0 :                 return;
    1170                 :            : 
    1171                 :         12 :         task = g_task_new (service, cancellable, callback, user_data);
    1172         [ +  - ]:         12 :         g_task_set_source_tag (task, secret_service_store);
    1173                 :         12 :         store = g_new0 (StoreClosure, 1);
    1174                 :         12 :         store->collection_path = _secret_util_collection_to_path (collection);
    1175                 :         12 :         store->value = secret_value_ref (value);
    1176                 :         12 :         store->properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
    1177                 :            :                                                    (GDestroyNotify)g_variant_unref);
    1178                 :            : 
    1179                 :         12 :         propval = g_variant_new_string (label);
    1180                 :         12 :         g_hash_table_insert (store->properties,
    1181                 :            :                              SECRET_ITEM_INTERFACE ".Label",
    1182                 :         12 :                              g_variant_ref_sink (propval));
    1183                 :            : 
    1184                 :            :         /* Always store the schema name in the attributes */
    1185         [ +  - ]:         12 :         schema_name = (schema == NULL) ? NULL : schema->name;
    1186                 :         12 :         propval = _secret_attributes_to_variant (attributes, schema_name);
    1187                 :         12 :         g_hash_table_insert (store->properties,
    1188                 :            :                              SECRET_ITEM_INTERFACE ".Attributes",
    1189                 :         12 :                              g_variant_ref_sink (propval));
    1190                 :            : 
    1191                 :         12 :         g_task_set_task_data (task, store, store_closure_free);
    1192                 :            : 
    1193         [ -  + ]:         12 :         if (service == NULL) {
    1194                 :          0 :                 secret_service_get (SECRET_SERVICE_OPEN_SESSION, cancellable,
    1195                 :            :                                     on_store_service, g_steal_pointer (&task));
    1196                 :            : 
    1197                 :            :         } else {
    1198                 :         12 :                 secret_service_create_item_dbus_path (service, store->collection_path,
    1199                 :            :                                                       store->properties, store->value,
    1200                 :            :                                                       SECRET_ITEM_CREATE_REPLACE,
    1201                 :            :                                                       cancellable,
    1202                 :            :                                                       on_store_create,
    1203                 :            :                                                       g_steal_pointer (&task));
    1204                 :            :         }
    1205                 :            : 
    1206         [ -  + ]:         12 :         g_clear_object (&task);
    1207                 :            : }
    1208                 :            : 
    1209                 :            : /**
    1210                 :            :  * secret_service_store_finish:
    1211                 :            :  * @service: (nullable): the secret service
    1212                 :            :  * @result: the asynchronous result passed to the callback
    1213                 :            :  * @error: location to place an error on failure
    1214                 :            :  *
    1215                 :            :  * Finish asynchronous operation to store a secret value in the secret service.
    1216                 :            :  *
    1217                 :            :  * Returns: whether the storage was successful or not
    1218                 :            :  */
    1219                 :            : gboolean
    1220                 :         12 : secret_service_store_finish (SecretService *service,
    1221                 :            :                              GAsyncResult *result,
    1222                 :            :                              GError **error)
    1223                 :            : {
    1224   [ +  -  -  +  :         12 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), FALSE);
          +  -  +  -  -  
                      + ]
    1225         [ -  + ]:         12 :         g_return_val_if_fail (g_task_is_valid (result, service), FALSE);
    1226   [ +  -  -  + ]:         12 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1227                 :            : 
    1228         [ -  + ]:         12 :         if (!g_task_propagate_boolean (G_TASK (result), error)) {
    1229                 :          0 :                 _secret_util_strip_remote_error (error);
    1230                 :          0 :                 return FALSE;
    1231                 :            :         }
    1232                 :            : 
    1233                 :         12 :         return TRUE;
    1234                 :            : }
    1235                 :            : 
    1236                 :            : /**
    1237                 :            :  * secret_service_store_sync:
    1238                 :            :  * @service: (nullable): the secret service
    1239                 :            :  * @schema: (nullable): the schema for the attributes
    1240                 :            :  * @attributes: (element-type utf8 utf8): the attribute keys and values
    1241                 :            :  * @collection: (nullable): a collection alias, or D-Bus object path of the
    1242                 :            :  *   collection where to store the secret
    1243                 :            :  * @label: label for the secret
    1244                 :            :  * @value: the secret value
    1245                 :            :  * @cancellable: (nullable): optional cancellation object
    1246                 :            :  * @error: location to place an error on failure
    1247                 :            :  *
    1248                 :            :  * Store a secret value in the secret service.
    1249                 :            :  *
    1250                 :            :  * The @attributes should be a set of key and value string pairs.
    1251                 :            :  *
    1252                 :            :  * If the attributes match a secret item already stored in the collection, then
    1253                 :            :  * the item will be updated with these new values.
    1254                 :            :  *
    1255                 :            :  * If @collection is %NULL, then the default collection will be
    1256                 :            :  * used. Use [const@COLLECTION_SESSION] to store the password in the session
    1257                 :            :  * collection, which doesn't get stored across login sessions.
    1258                 :            :  *
    1259                 :            :  * If @service is %NULL, then [func@Service.get_sync] will be called to get
    1260                 :            :  * the default [class@Service] proxy.
    1261                 :            :  *
    1262                 :            :  * This method may block indefinitely and should not be used in user interface
    1263                 :            :  * threads.
    1264                 :            :  *
    1265                 :            :  * Returns: whether the storage was successful or not
    1266                 :            :  */
    1267                 :            : gboolean
    1268                 :          4 : secret_service_store_sync (SecretService *service,
    1269                 :            :                            const SecretSchema *schema,
    1270                 :            :                            GHashTable *attributes,
    1271                 :            :                            const gchar *collection,
    1272                 :            :                            const gchar *label,
    1273                 :            :                            SecretValue *value,
    1274                 :            :                            GCancellable *cancellable,
    1275                 :            :                            GError **error)
    1276                 :            : {
    1277                 :            :         SecretSync *sync;
    1278                 :            :         gboolean ret;
    1279                 :            : 
    1280   [ +  -  -  +  :          4 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), FALSE);
          +  -  +  -  -  
                      + ]
    1281         [ -  + ]:          4 :         g_return_val_if_fail (attributes != NULL, FALSE);
    1282         [ -  + ]:          4 :         g_return_val_if_fail (label != NULL, FALSE);
    1283         [ -  + ]:          4 :         g_return_val_if_fail (value != NULL, FALSE);
    1284   [ -  +  -  -  :          4 :         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
          -  -  -  -  -  
                      - ]
    1285   [ +  -  -  + ]:          4 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1286                 :            : 
    1287                 :            :         /* Warnings raised already */
    1288   [ +  -  -  + ]:          4 :         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
    1289                 :          0 :                 return FALSE;
    1290                 :            : 
    1291                 :          4 :         sync = _secret_sync_new ();
    1292                 :          4 :         g_main_context_push_thread_default (sync->context);
    1293                 :            : 
    1294                 :          4 :         secret_service_store (service, schema, attributes, collection,
    1295                 :            :                               label, value, cancellable, _secret_sync_on_result, sync);
    1296                 :            : 
    1297                 :          4 :         g_main_loop_run (sync->loop);
    1298                 :            : 
    1299                 :          4 :         ret = secret_service_store_finish (service, sync->result, error);
    1300                 :            : 
    1301                 :          4 :         g_main_context_pop_thread_default (sync->context);
    1302                 :          4 :         _secret_sync_free (sync);
    1303                 :            : 
    1304                 :          4 :         return ret;
    1305                 :            : }
    1306                 :            : 
    1307                 :            : static void
    1308                 :         17 : on_lookup_get_secret (GObject *source,
    1309                 :            :                       GAsyncResult *result,
    1310                 :            :                       gpointer user_data)
    1311                 :            : {
    1312                 :         17 :         GTask *task = G_TASK (user_data);
    1313                 :         17 :         SecretService *self = SECRET_SERVICE (source);
    1314                 :            :         SecretValue *value;
    1315                 :         17 :         GError *error = NULL;
    1316                 :            : 
    1317                 :         17 :         value = secret_service_get_secret_for_dbus_path_finish (self, result, &error);
    1318         [ -  + ]:         17 :         if (error != NULL)
    1319                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1320                 :            :         else
    1321                 :         17 :                 g_task_return_pointer (task, value, secret_value_unref);
    1322                 :            : 
    1323         [ +  - ]:         17 :         g_clear_object (&task);
    1324                 :         17 : }
    1325                 :            : 
    1326                 :            : static void
    1327                 :          3 : on_lookup_unlocked (GObject *source,
    1328                 :            :                     GAsyncResult *result,
    1329                 :            :                     gpointer user_data)
    1330                 :            : {
    1331                 :          3 :         SecretService *self = SECRET_SERVICE (source);
    1332                 :          3 :         GTask *task = G_TASK (user_data);
    1333                 :          3 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1334                 :          3 :         GError *error = NULL;
    1335                 :          3 :         gchar **unlocked = NULL;
    1336                 :            : 
    1337                 :          3 :         secret_service_unlock_dbus_paths_finish (self, result, &unlocked, &error);
    1338         [ -  + ]:          3 :         if (error != NULL) {
    1339                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1340                 :            : 
    1341   [ +  -  +  - ]:          3 :         } else if (unlocked && unlocked[0]) {
    1342                 :          3 :                 secret_service_get_secret_for_dbus_path (self, unlocked[0],
    1343                 :            :                                                          cancellable,
    1344                 :            :                                                          on_lookup_get_secret,
    1345                 :            :                                                          g_steal_pointer (&task));
    1346                 :            : 
    1347                 :            :         } else {
    1348                 :          0 :                 g_task_return_pointer (task, NULL, NULL);
    1349                 :            :         }
    1350                 :            : 
    1351                 :          3 :         g_strfreev (unlocked);
    1352         [ -  + ]:          3 :         g_clear_object (&task);
    1353                 :          3 : }
    1354                 :            : 
    1355                 :            : static void
    1356                 :         25 : on_lookup_searched (GObject *source,
    1357                 :            :                     GAsyncResult *result,
    1358                 :            :                     gpointer user_data)
    1359                 :            : {
    1360                 :         25 :         SecretService *self = SECRET_SERVICE (source);
    1361                 :         25 :         GTask *task = G_TASK (user_data);
    1362                 :         25 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1363                 :         25 :         GError *error = NULL;
    1364                 :         25 :         gchar **unlocked = NULL;
    1365                 :         25 :         gchar **locked = NULL;
    1366                 :            : 
    1367                 :         25 :         secret_service_search_for_dbus_paths_finish (self, result, &unlocked, &locked, &error);
    1368         [ -  + ]:         25 :         if (error != NULL) {
    1369                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1370                 :            : 
    1371   [ +  -  +  + ]:         25 :         } else if (unlocked && unlocked[0]) {
    1372                 :         14 :                 secret_service_get_secret_for_dbus_path (self, unlocked[0],
    1373                 :            :                                                          cancellable,
    1374                 :            :                                                          on_lookup_get_secret,
    1375                 :            :                                                          g_steal_pointer (&task));
    1376                 :            : 
    1377   [ +  -  +  + ]:         14 :         } else if (locked && locked[0]) {
    1378                 :          3 :                 const gchar *paths[] = { locked[0], NULL };
    1379                 :          3 :                 secret_service_unlock_dbus_paths (self, paths,
    1380                 :            :                                                   cancellable,
    1381                 :            :                                                   on_lookup_unlocked,
    1382                 :            :                                                   g_steal_pointer (&task));
    1383                 :            : 
    1384                 :            :         } else {
    1385                 :          8 :                 g_task_return_pointer (task, NULL, NULL);
    1386                 :            :         }
    1387                 :            : 
    1388                 :         25 :         g_strfreev (unlocked);
    1389                 :         25 :         g_strfreev (locked);
    1390         [ +  + ]:         25 :         g_clear_object (&task);
    1391                 :         25 : }
    1392                 :            : 
    1393                 :            : static void
    1394                 :          0 : on_lookup_service (GObject *source,
    1395                 :            :                    GAsyncResult *result,
    1396                 :            :                    gpointer user_data)
    1397                 :            : {
    1398                 :          0 :         GTask *task = G_TASK (user_data);
    1399                 :          0 :         GVariant *attributes = g_task_get_task_data (task);
    1400                 :          0 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1401                 :            :         SecretService *service;
    1402                 :          0 :         GError *error = NULL;
    1403                 :            : 
    1404                 :          0 :         service = secret_service_get_finish (result, &error);
    1405         [ #  # ]:          0 :         if (error == NULL) {
    1406                 :          0 :                 _secret_service_search_for_paths_variant (service, attributes,
    1407                 :            :                                                           cancellable,
    1408                 :            :                                                           on_lookup_searched,
    1409                 :            :                                                           g_steal_pointer (&task));
    1410                 :          0 :                 g_object_unref (service);
    1411                 :            : 
    1412                 :            :         } else {
    1413                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1414                 :            :         }
    1415                 :            : 
    1416         [ #  # ]:          0 :         g_clear_object (&task);
    1417                 :          0 : }
    1418                 :            : 
    1419                 :            : /**
    1420                 :            :  * secret_service_lookup:
    1421                 :            :  * @service: (nullable): the secret service
    1422                 :            :  * @schema: (nullable): the schema for the attributes
    1423                 :            :  * @attributes: (element-type utf8 utf8): the attribute keys and values
    1424                 :            :  * @cancellable: (nullable): optional cancellation object
    1425                 :            :  * @callback: called when the operation completes
    1426                 :            :  * @user_data: data to be passed to the callback
    1427                 :            :  *
    1428                 :            :  * Lookup a secret value in the secret service.
    1429                 :            :  *
    1430                 :            :  * The @attributes should be a set of key and value string pairs.
    1431                 :            :  *
    1432                 :            :  * If @service is %NULL, then [func@Service.get] will be called to get
    1433                 :            :  * the default [class@Service] proxy.
    1434                 :            :  *
    1435                 :            :  * This method will return immediately and complete asynchronously.
    1436                 :            :  */
    1437                 :            : void
    1438                 :         25 : secret_service_lookup (SecretService *service,
    1439                 :            :                        const SecretSchema *schema,
    1440                 :            :                        GHashTable *attributes,
    1441                 :            :                        GCancellable *cancellable,
    1442                 :            :                        GAsyncReadyCallback callback,
    1443                 :            :                        gpointer user_data)
    1444                 :            : {
    1445                 :         25 :         const gchar *schema_name = NULL;
    1446                 :            :         GTask *task;
    1447                 :            :         GVariant *attributes_v;
    1448                 :            : 
    1449   [ +  -  -  +  :         25 :         g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
          +  -  +  -  -  
                      + ]
    1450         [ -  + ]:         25 :         g_return_if_fail (attributes != NULL);
    1451   [ -  +  -  -  :         25 :         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
          -  -  -  -  -  
                      - ]
    1452                 :            : 
    1453                 :            :         /* Warnings raised already */
    1454   [ +  -  -  + ]:         25 :         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
    1455                 :          0 :                 return;
    1456                 :            : 
    1457   [ +  -  +  + ]:         25 :         if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME))
    1458                 :         23 :                 schema_name = schema->name;
    1459                 :            : 
    1460                 :         25 :         task = g_task_new (service, cancellable, callback, user_data);
    1461         [ +  - ]:         25 :         g_task_set_source_tag (task, secret_service_lookup);
    1462                 :            : 
    1463                 :         25 :         attributes_v = _secret_attributes_to_variant (attributes, schema_name);
    1464                 :         25 :         g_variant_ref_sink (attributes_v);
    1465                 :         25 :         g_task_set_task_data (task, attributes_v, (GDestroyNotify) g_variant_unref);
    1466                 :            : 
    1467         [ -  + ]:         25 :         if (service == NULL) {
    1468                 :          0 :                 secret_service_get (SECRET_SERVICE_OPEN_SESSION, cancellable,
    1469                 :            :                                     on_lookup_service, g_steal_pointer (&task));
    1470                 :            :         } else {
    1471                 :         25 :                 _secret_service_search_for_paths_variant (service, attributes_v,
    1472                 :            :                                                           cancellable,
    1473                 :            :                                                           on_lookup_searched,
    1474                 :            :                                                           g_steal_pointer (&task));
    1475                 :            :         }
    1476                 :            : 
    1477         [ -  + ]:         25 :         g_clear_object (&task);
    1478                 :            : }
    1479                 :            : 
    1480                 :            : /**
    1481                 :            :  * secret_service_lookup_finish:
    1482                 :            :  * @service: (nullable): the secret service
    1483                 :            :  * @result: the asynchronous result passed to the callback
    1484                 :            :  * @error: location to place an error on failure
    1485                 :            :  *
    1486                 :            :  * Finish asynchronous operation to lookup a secret value in the secret service.
    1487                 :            :  *
    1488                 :            :  * If no secret is found then %NULL is returned.
    1489                 :            :  *
    1490                 :            :  * Returns: (transfer full): a newly allocated [struct@Value], which should be
    1491                 :            :  *   released with [method@Value.unref], or %NULL if no secret found
    1492                 :            :  */
    1493                 :            : SecretValue *
    1494                 :         25 : secret_service_lookup_finish (SecretService *service,
    1495                 :            :                               GAsyncResult *result,
    1496                 :            :                               GError **error)
    1497                 :            : {
    1498                 :            :         SecretValue *value;
    1499                 :            : 
    1500   [ +  -  -  +  :         25 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
          +  -  +  -  -  
                      + ]
    1501   [ +  -  -  + ]:         25 :         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
    1502         [ -  + ]:         25 :         g_return_val_if_fail (g_task_is_valid (result, service), NULL);
    1503                 :            : 
    1504                 :         25 :         value = g_task_propagate_pointer (G_TASK (result), error);
    1505         [ +  + ]:         25 :         if (!value) {
    1506                 :          8 :                 _secret_util_strip_remote_error (error);
    1507                 :          8 :                 return NULL;
    1508                 :            :         }
    1509                 :            : 
    1510                 :         17 :         return value;
    1511                 :            : }
    1512                 :            : 
    1513                 :            : /**
    1514                 :            :  * secret_service_lookup_sync:
    1515                 :            :  * @service: (nullable): the secret service
    1516                 :            :  * @schema: (nullable): the schema for the attributes
    1517                 :            :  * @attributes: (element-type utf8 utf8): the attribute keys and values
    1518                 :            :  * @cancellable: (nullable): optional cancellation object
    1519                 :            :  * @error: location to place an error on failure
    1520                 :            :  *
    1521                 :            :  * Lookup a secret value in the secret service.
    1522                 :            :  *
    1523                 :            :  * The @attributes should be a set of key and value string pairs.
    1524                 :            :  *
    1525                 :            :  * If @service is %NULL, then [func@Service.get_sync] will be called to get
    1526                 :            :  * the default [class@Service] proxy.
    1527                 :            :  *
    1528                 :            :  * This method may block indefinitely and should not be used in user interface
    1529                 :            :  * threads.
    1530                 :            :  *
    1531                 :            :  * Returns: (transfer full): a newly allocated [struct@Value], which should be
    1532                 :            :  *   released with [method@Value.unref], or %NULL if no secret found
    1533                 :            :  */
    1534                 :            : SecretValue *
    1535                 :          5 : secret_service_lookup_sync (SecretService *service,
    1536                 :            :                             const SecretSchema *schema,
    1537                 :            :                             GHashTable *attributes,
    1538                 :            :                             GCancellable *cancellable,
    1539                 :            :                             GError **error)
    1540                 :            : {
    1541                 :            :         SecretSync *sync;
    1542                 :            :         SecretValue *value;
    1543                 :            : 
    1544   [ +  -  -  +  :          5 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
          +  -  +  -  -  
                      + ]
    1545         [ -  + ]:          5 :         g_return_val_if_fail (attributes != NULL, NULL);
    1546   [ -  +  -  -  :          5 :         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
          -  -  -  -  -  
                      - ]
    1547                 :            : 
    1548                 :            :         /* Warnings raised already */
    1549   [ +  -  -  + ]:          5 :         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
    1550                 :          0 :                 return NULL;
    1551                 :            : 
    1552                 :          5 :         sync = _secret_sync_new ();
    1553                 :          5 :         g_main_context_push_thread_default (sync->context);
    1554                 :            : 
    1555                 :          5 :         secret_service_lookup (service, schema, attributes, cancellable,
    1556                 :            :                                _secret_sync_on_result, sync);
    1557                 :            : 
    1558                 :          5 :         g_main_loop_run (sync->loop);
    1559                 :            : 
    1560                 :          5 :         value = secret_service_lookup_finish (service, sync->result, error);
    1561                 :            : 
    1562                 :          5 :         g_main_context_pop_thread_default (sync->context);
    1563                 :          5 :         _secret_sync_free (sync);
    1564                 :            : 
    1565                 :          5 :         return value;
    1566                 :            : }
    1567                 :            : 
    1568                 :            : typedef struct {
    1569                 :            :         SecretService *service;
    1570                 :            :         GVariant *attributes;
    1571                 :            :         gint deleted;
    1572                 :            :         gint deleting;
    1573                 :            : } DeleteClosure;
    1574                 :            : 
    1575                 :            : static void
    1576                 :         14 : delete_closure_free (gpointer data)
    1577                 :            : {
    1578                 :         14 :         DeleteClosure *closure = data;
    1579         [ +  - ]:         14 :         if (closure->service)
    1580                 :         14 :                 g_object_unref (closure->service);
    1581                 :         14 :         g_variant_unref (closure->attributes);
    1582                 :         14 :         g_free (closure);
    1583                 :         14 : }
    1584                 :            : 
    1585                 :            : static void
    1586                 :          8 : on_delete_password_complete (GObject *source,
    1587                 :            :                              GAsyncResult *result,
    1588                 :            :                              gpointer user_data)
    1589                 :            : {
    1590                 :          8 :         SecretService *service = SECRET_SERVICE (source);
    1591                 :          8 :         GTask *task = G_TASK (user_data);
    1592                 :          8 :         DeleteClosure *closure = g_task_get_task_data (task);
    1593                 :          8 :         GError *error = NULL;
    1594                 :            :         gboolean deleted;
    1595                 :            : 
    1596                 :          8 :         closure->deleting--;
    1597                 :            : 
    1598                 :          8 :         deleted = _secret_service_delete_path_finish (service, result, &error);
    1599         [ -  + ]:          8 :         if (error != NULL)
    1600                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1601         [ +  - ]:          8 :         if (deleted)
    1602                 :          8 :                 closure->deleted++;
    1603                 :            : 
    1604         [ +  - ]:          8 :         if (closure->deleting <= 0)
    1605                 :          8 :                 g_task_return_boolean (task, TRUE);
    1606                 :            : 
    1607         [ +  - ]:          8 :         g_clear_object (&task);
    1608                 :          8 : }
    1609                 :            : 
    1610                 :            : static void
    1611                 :         14 : on_delete_searched (GObject *source,
    1612                 :            :                     GAsyncResult *result,
    1613                 :            :                     gpointer user_data)
    1614                 :            : {
    1615                 :         14 :         SecretService *service = SECRET_SERVICE (source);
    1616                 :         14 :         GTask *task = G_TASK (user_data);
    1617                 :         14 :         DeleteClosure *closure = g_task_get_task_data (task);
    1618                 :         14 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1619                 :         14 :         GError *error = NULL;
    1620                 :         14 :         gchar **unlocked = NULL;
    1621                 :            :         gint i;
    1622                 :            : 
    1623                 :         14 :         secret_service_search_for_dbus_paths_finish (service, result, &unlocked, NULL, &error);
    1624         [ +  - ]:         14 :         if (error == NULL) {
    1625         [ +  + ]:         22 :                 for (i = 0; unlocked[i] != NULL; i++) {
    1626                 :          8 :                         _secret_service_delete_path (closure->service, unlocked[i], TRUE,
    1627                 :            :                                                      cancellable,
    1628                 :            :                                                      on_delete_password_complete,
    1629                 :            :                                                      g_object_ref (task));
    1630                 :          8 :                         closure->deleting++;
    1631                 :            :                 }
    1632                 :            : 
    1633         [ +  + ]:         14 :                 if (closure->deleting == 0)
    1634                 :          6 :                         g_task_return_boolean (task, FALSE);
    1635                 :            :         } else {
    1636                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1637                 :            :         }
    1638                 :            : 
    1639                 :         14 :         g_strfreev (unlocked);
    1640         [ +  - ]:         14 :         g_clear_object (&task);
    1641                 :         14 : }
    1642                 :            : 
    1643                 :            : static void
    1644                 :          0 : on_delete_service (GObject *source,
    1645                 :            :                    GAsyncResult *result,
    1646                 :            :                    gpointer user_data)
    1647                 :            : {
    1648                 :          0 :         GTask *task = G_TASK (user_data);
    1649                 :          0 :         DeleteClosure *closure = g_task_get_task_data (task);
    1650                 :          0 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1651                 :          0 :         GError *error = NULL;
    1652                 :            : 
    1653                 :          0 :         closure->service = secret_service_get_finish (result, &error);
    1654         [ #  # ]:          0 :         if (error == NULL) {
    1655                 :          0 :                 _secret_service_search_for_paths_variant (closure->service, closure->attributes,
    1656                 :            :                                                           cancellable,
    1657                 :            :                                                           on_delete_searched, g_steal_pointer (&task));
    1658                 :            : 
    1659                 :            :         } else {
    1660                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1661                 :            :         }
    1662                 :            : 
    1663         [ #  # ]:          0 :         g_clear_object (&task);
    1664                 :          0 : }
    1665                 :            : 
    1666                 :            : /**
    1667                 :            :  * secret_service_clear:
    1668                 :            :  * @service: (nullable): the secret service
    1669                 :            :  * @schema: (nullable): the schema for the attributes
    1670                 :            :  * @attributes: (element-type utf8 utf8): the attribute keys and values
    1671                 :            :  * @cancellable: (nullable): optional cancellation object
    1672                 :            :  * @callback: called when the operation completes
    1673                 :            :  * @user_data: data to be passed to the callback
    1674                 :            :  *
    1675                 :            :  * Remove unlocked items which match the attributes from the secret service.
    1676                 :            :  *
    1677                 :            :  * The @attributes should be a set of key and value string pairs.
    1678                 :            :  *
    1679                 :            :  * If @service is %NULL, then [func@Service.get] will be called to get
    1680                 :            :  * the default [class@Service] proxy.
    1681                 :            :  *
    1682                 :            :  * This method will return immediately and complete asynchronously.
    1683                 :            :  */
    1684                 :            : void
    1685                 :         14 : secret_service_clear (SecretService *service,
    1686                 :            :                       const SecretSchema *schema,
    1687                 :            :                       GHashTable *attributes,
    1688                 :            :                       GCancellable *cancellable,
    1689                 :            :                       GAsyncReadyCallback callback,
    1690                 :            :                       gpointer user_data)
    1691                 :            : {
    1692                 :         14 :         const gchar *schema_name = NULL;
    1693                 :            :         GTask *task;
    1694                 :            :         DeleteClosure *closure;
    1695                 :            : 
    1696   [ +  -  -  + ]:         14 :         g_return_if_fail (service == NULL || SECRET_SERVICE (service));
    1697         [ -  + ]:         14 :         g_return_if_fail (attributes != NULL);
    1698   [ -  +  -  -  :         14 :         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
          -  -  -  -  -  
                      - ]
    1699                 :            : 
    1700                 :            :         /* Warnings raised already */
    1701   [ +  -  -  + ]:         14 :         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
    1702                 :          0 :                 return;
    1703                 :            : 
    1704   [ +  -  +  + ]:         14 :         if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME))
    1705                 :         12 :                 schema_name = schema->name;
    1706                 :            : 
    1707                 :         14 :         task = g_task_new (service, cancellable, callback, user_data);
    1708         [ +  - ]:         14 :         g_task_set_source_tag (task, secret_service_clear);
    1709                 :         14 :         closure = g_new0 (DeleteClosure, 1);
    1710                 :         14 :         closure->attributes = _secret_attributes_to_variant (attributes, schema_name);
    1711                 :         14 :         g_variant_ref_sink (closure->attributes);
    1712                 :         14 :         g_task_set_task_data (task, closure, delete_closure_free);
    1713                 :            : 
    1714                 :            :         /* A double check to make sure we don't delete everything, should have been checked earlier */
    1715         [ -  + ]:         14 :         g_assert (g_variant_n_children (closure->attributes) > 0);
    1716                 :            : 
    1717         [ -  + ]:         14 :         if (service == NULL) {
    1718                 :          0 :                 secret_service_get (SECRET_SERVICE_NONE, cancellable,
    1719                 :            :                                     on_delete_service, g_steal_pointer (&task));
    1720                 :            :         } else {
    1721                 :         14 :                 closure->service = g_object_ref (service);
    1722                 :         14 :                 _secret_service_search_for_paths_variant (closure->service, closure->attributes,
    1723                 :            :                                                           cancellable,
    1724                 :            :                                                           on_delete_searched, g_steal_pointer (&task));
    1725                 :            :         }
    1726                 :            : 
    1727         [ -  + ]:         14 :         g_clear_object (&task);
    1728                 :            : }
    1729                 :            : 
    1730                 :            : /**
    1731                 :            :  * secret_service_clear_finish:
    1732                 :            :  * @service: (nullable): the secret service
    1733                 :            :  * @result: the asynchronous result passed to the callback
    1734                 :            :  * @error: location to place an error on failure
    1735                 :            :  *
    1736                 :            :  * Finish asynchronous operation to remove items from the secret
    1737                 :            :  * service.
    1738                 :            :  *
    1739                 :            :  * Returns: whether items were removed or not
    1740                 :            :  */
    1741                 :            : gboolean
    1742                 :         14 : secret_service_clear_finish (SecretService *service,
    1743                 :            :                              GAsyncResult *result,
    1744                 :            :                              GError **error)
    1745                 :            : {
    1746   [ +  -  -  +  :         14 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), FALSE);
          +  -  +  -  -  
                      + ]
    1747   [ +  -  -  + ]:         14 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1748         [ -  + ]:         14 :         g_return_val_if_fail (g_task_is_valid (result, service), FALSE);
    1749                 :            : 
    1750         [ +  + ]:         14 :         if (!g_task_propagate_boolean (G_TASK (result), error)) {
    1751                 :          6 :                 _secret_util_strip_remote_error (error);
    1752                 :          6 :                 return FALSE;
    1753                 :            :         }
    1754                 :            : 
    1755                 :          8 :         return TRUE;
    1756                 :            : }
    1757                 :            : 
    1758                 :            : /**
    1759                 :            :  * secret_service_clear_sync:
    1760                 :            :  * @service: (nullable): the secret service
    1761                 :            :  * @schema: (nullable): the schema for the attributes
    1762                 :            :  * @attributes: (element-type utf8 utf8): the attribute keys and values
    1763                 :            :  * @cancellable: (nullable): optional cancellation object
    1764                 :            :  * @error: location to place an error on failure
    1765                 :            :  *
    1766                 :            :  * Remove unlocked items which match the attributes from the secret service.
    1767                 :            :  *
    1768                 :            :  * The @attributes should be a set of key and value string pairs.
    1769                 :            :  *
    1770                 :            :  * If @service is %NULL, then [func@Service.get_sync] will be called to get
    1771                 :            :  * the default [class@Service] proxy.
    1772                 :            :  *
    1773                 :            :  * This method may block indefinitely and should not be used in user interface
    1774                 :            :  * threads.
    1775                 :            :  *
    1776                 :            :  * Returns: whether items were removed or not
    1777                 :            :  */
    1778                 :            : gboolean
    1779                 :          5 : secret_service_clear_sync (SecretService *service,
    1780                 :            :                            const SecretSchema *schema,
    1781                 :            :                            GHashTable *attributes,
    1782                 :            :                            GCancellable *cancellable,
    1783                 :            :                            GError **error)
    1784                 :            : {
    1785                 :            :         SecretSync *sync;
    1786                 :            :         gboolean result;
    1787                 :            : 
    1788   [ +  -  -  +  :          5 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), FALSE);
          +  -  +  -  -  
                      + ]
    1789   [ -  +  -  -  :          5 :         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
          -  -  -  -  -  
                      - ]
    1790   [ +  -  -  + ]:          5 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1791                 :            : 
    1792                 :            :         /* Warnings raised already */
    1793   [ +  -  -  + ]:          5 :         if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
    1794                 :          0 :                 return FALSE;
    1795                 :            : 
    1796                 :          5 :         sync = _secret_sync_new ();
    1797                 :          5 :         g_main_context_push_thread_default (sync->context);
    1798                 :            : 
    1799                 :          5 :         secret_service_clear (service, schema, attributes, cancellable,
    1800                 :            :                               _secret_sync_on_result, sync);
    1801                 :            : 
    1802                 :          5 :         g_main_loop_run (sync->loop);
    1803                 :            : 
    1804                 :          5 :         result = secret_service_clear_finish (service, sync->result, error);
    1805                 :            : 
    1806                 :          5 :         g_main_context_pop_thread_default (sync->context);
    1807                 :          5 :         _secret_sync_free (sync);
    1808                 :            : 
    1809                 :          5 :         return result;
    1810                 :            : }
    1811                 :            : 
    1812                 :            : typedef struct {
    1813                 :            :         gchar *alias;
    1814                 :            :         gchar *collection_path;
    1815                 :            : } SetClosure;
    1816                 :            : 
    1817                 :            : static void
    1818                 :          2 : set_closure_free (gpointer data)
    1819                 :            : {
    1820                 :          2 :         SetClosure *set = data;
    1821                 :          2 :         g_free (set->alias);
    1822                 :          2 :         g_free (set->collection_path);
    1823                 :          2 :         g_free (set);
    1824                 :          2 : }
    1825                 :            : 
    1826                 :            : static void
    1827                 :          2 : on_set_alias_done (GObject *source,
    1828                 :            :                    GAsyncResult *result,
    1829                 :            :                    gpointer user_data)
    1830                 :            : {
    1831                 :          2 :         GTask *task = G_TASK (user_data);
    1832                 :          2 :         SecretService *service = SECRET_SERVICE (source);
    1833                 :          2 :         GError *error = NULL;
    1834                 :            : 
    1835         [ +  - ]:          2 :         if (secret_service_set_alias_to_dbus_path_finish (service, result, &error)) {
    1836                 :          2 :                 g_task_return_boolean (task, TRUE);
    1837                 :            :         } else {
    1838                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1839                 :            :         }
    1840                 :            : 
    1841         [ +  - ]:          2 :         g_clear_object (&task);
    1842                 :          2 : }
    1843                 :            : 
    1844                 :            : static void
    1845                 :          0 : on_set_alias_service (GObject *source,
    1846                 :            :                       GAsyncResult *result,
    1847                 :            :                       gpointer user_data)
    1848                 :            : {
    1849                 :          0 :         GTask *task = G_TASK (user_data);
    1850                 :          0 :         SetClosure *set = g_task_get_task_data (task);
    1851                 :          0 :         GCancellable *cancellable = g_task_get_cancellable (task);
    1852                 :            :         SecretService *service;
    1853                 :          0 :         GError *error = NULL;
    1854                 :            : 
    1855                 :          0 :         service = secret_service_get_finish (result, &error);
    1856         [ #  # ]:          0 :         if (error == NULL) {
    1857                 :          0 :                 secret_service_set_alias_to_dbus_path (service, set->alias,
    1858                 :          0 :                                                        set->collection_path,
    1859                 :            :                                                        cancellable,
    1860                 :            :                                                        on_set_alias_done,
    1861                 :            :                                                        g_steal_pointer (&task));
    1862                 :          0 :                 g_object_unref (service);
    1863                 :            : 
    1864                 :            :         } else {
    1865                 :          0 :                 g_task_return_error (task, g_steal_pointer (&error));
    1866                 :            :         }
    1867                 :            : 
    1868         [ #  # ]:          0 :         g_clear_object (&task);
    1869                 :          0 : }
    1870                 :            : 
    1871                 :            : /**
    1872                 :            :  * secret_service_set_alias:
    1873                 :            :  * @service: (nullable): a secret service object
    1874                 :            :  * @alias: the alias to assign the collection to
    1875                 :            :  * @collection: (nullable): the collection to assign to the alias
    1876                 :            :  * @cancellable: (nullable): optional cancellation object
    1877                 :            :  * @callback: called when the operation completes
    1878                 :            :  * @user_data: data to pass to the callback
    1879                 :            :  *
    1880                 :            :  * Assign a collection to this alias.
    1881                 :            :  *
    1882                 :            :  * Aliases help determine well known collections, such as 'default'.
    1883                 :            :  *
    1884                 :            :  * If @service is %NULL, then [func@Service.get] will be called to get
    1885                 :            :  * the default [class@Service] proxy.
    1886                 :            :  *
    1887                 :            :  * This method will return immediately and complete asynchronously.
    1888                 :            :  */
    1889                 :            : void
    1890                 :          2 : secret_service_set_alias (SecretService *service,
    1891                 :            :                           const gchar *alias,
    1892                 :            :                           SecretCollection *collection,
    1893                 :            :                           GCancellable *cancellable,
    1894                 :            :                           GAsyncReadyCallback callback,
    1895                 :            :                           gpointer user_data)
    1896                 :            : {
    1897                 :            :         GTask *task;
    1898                 :            :         SetClosure *set;
    1899                 :            :         const gchar *path;
    1900                 :            : 
    1901   [ +  -  -  +  :          2 :         g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
          +  -  +  -  -  
                      + ]
    1902         [ -  + ]:          2 :         g_return_if_fail (alias != NULL);
    1903   [ +  +  -  +  :          2 :         g_return_if_fail (collection == NULL || SECRET_IS_COLLECTION (collection));
          +  -  +  -  -  
                      + ]
    1904   [ -  +  -  -  :          2 :         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
          -  -  -  -  -  
                      - ]
    1905                 :            : 
    1906                 :          2 :         task = g_task_new (service, cancellable, callback, user_data);
    1907         [ +  - ]:          2 :         g_task_set_source_tag (task, secret_service_set_alias);
    1908                 :          2 :         set = g_new0 (SetClosure, 1);
    1909                 :          2 :         set->alias = g_strdup (alias);
    1910                 :            : 
    1911         [ +  + ]:          2 :         if (collection) {
    1912                 :          1 :                 path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection));
    1913         [ -  + ]:          1 :                 g_return_if_fail (path != NULL);
    1914                 :            :         } else {
    1915                 :          1 :                 path = NULL;
    1916                 :            :         }
    1917                 :            : 
    1918                 :          2 :         set->collection_path = g_strdup (path);
    1919                 :          2 :         g_task_set_task_data (task, set, set_closure_free);
    1920                 :            : 
    1921         [ -  + ]:          2 :         if (service == NULL) {
    1922                 :          0 :                 secret_service_get (SECRET_SERVICE_NONE, cancellable,
    1923                 :            :                                     on_set_alias_service, g_steal_pointer (&task));
    1924                 :            :         } else {
    1925                 :          2 :                 secret_service_set_alias_to_dbus_path (service, set->alias,
    1926                 :          2 :                                                        set->collection_path,
    1927                 :            :                                                        cancellable,
    1928                 :            :                                                        on_set_alias_done,
    1929                 :            :                                                        g_steal_pointer (&task));
    1930                 :            :         }
    1931                 :            : 
    1932         [ -  + ]:          2 :         g_clear_object (&task);
    1933                 :            : }
    1934                 :            : 
    1935                 :            : /**
    1936                 :            :  * secret_service_set_alias_finish:
    1937                 :            :  * @service: (nullable): a secret service object
    1938                 :            :  * @result: asynchronous result passed to callback
    1939                 :            :  * @error: location to place error on failure
    1940                 :            :  *
    1941                 :            :  * Finish an asynchronous operation to assign a collection to an alias.
    1942                 :            :  *
    1943                 :            :  * Returns: %TRUE if successful
    1944                 :            :  */
    1945                 :            : gboolean
    1946                 :          2 : secret_service_set_alias_finish (SecretService *service,
    1947                 :            :                                  GAsyncResult *result,
    1948                 :            :                                  GError **error)
    1949                 :            : {
    1950   [ +  -  -  +  :          2 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), FALSE);
          +  -  +  -  -  
                      + ]
    1951         [ -  + ]:          2 :         g_return_val_if_fail (g_task_is_valid (result, service), FALSE);
    1952   [ +  -  -  + ]:          2 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1953                 :            : 
    1954         [ -  + ]:          2 :         if (!g_task_propagate_boolean (G_TASK (result), error)) {
    1955                 :          0 :                 _secret_util_strip_remote_error (error);
    1956                 :          0 :                 return FALSE;
    1957                 :            :         }
    1958                 :            : 
    1959                 :          2 :         return TRUE;
    1960                 :            : }
    1961                 :            : 
    1962                 :            : /**
    1963                 :            :  * secret_service_set_alias_sync:
    1964                 :            :  * @service: (nullable): a secret service object
    1965                 :            :  * @alias: the alias to assign the collection to
    1966                 :            :  * @collection: (nullable): the collection to assign to the alias
    1967                 :            :  * @cancellable: (nullable): optional cancellation object
    1968                 :            :  * @error: location to place error on failure
    1969                 :            :  *
    1970                 :            :  * Assign a collection to this alias. Aliases help determine
    1971                 :            :  * well known collections, such as 'default'.
    1972                 :            :  *
    1973                 :            :  * If @service is %NULL, then [func@Service.get_sync] will be called to get
    1974                 :            :  * the default [class@Service] proxy.
    1975                 :            :  *
    1976                 :            :  * This method may block and should not be used in user interface threads.
    1977                 :            :  *
    1978                 :            :  * Returns: %TRUE if successful
    1979                 :            :  */
    1980                 :            : gboolean
    1981                 :          2 : secret_service_set_alias_sync (SecretService *service,
    1982                 :            :                                const gchar *alias,
    1983                 :            :                                SecretCollection *collection,
    1984                 :            :                                GCancellable *cancellable,
    1985                 :            :                                GError **error)
    1986                 :            : {
    1987                 :            :         SecretSync *sync;
    1988                 :            :         gboolean ret;
    1989                 :            : 
    1990   [ +  -  -  +  :          2 :         g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), FALSE);
          +  -  +  -  -  
                      + ]
    1991         [ -  + ]:          2 :         g_return_val_if_fail (alias != NULL, FALSE);
    1992   [ -  +  -  -  :          2 :         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
          -  -  -  -  -  
                      - ]
    1993   [ +  -  -  + ]:          2 :         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    1994                 :            : 
    1995                 :          2 :         sync = _secret_sync_new ();
    1996                 :          2 :         g_main_context_push_thread_default (sync->context);
    1997                 :            : 
    1998                 :          2 :         secret_service_set_alias (service, alias, collection, cancellable,
    1999                 :            :                                   _secret_sync_on_result, sync);
    2000                 :            : 
    2001                 :          2 :         g_main_loop_run (sync->loop);
    2002                 :            : 
    2003                 :          2 :         ret = secret_service_set_alias_finish (service, sync->result, error);
    2004                 :            : 
    2005                 :          2 :         g_main_context_pop_thread_default (sync->context);
    2006                 :          2 :         _secret_sync_free (sync);
    2007                 :            : 
    2008                 :          2 :         return ret;
    2009                 :            : }

Generated by: LCOV version 1.14