LCOV - code coverage report
Current view: top level - src/libvalent/contacts - valent-contact-cache.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 93.8 % 178 167
Test Date: 2024-06-18 15:52:56 Functions: 100.0 % 19 19
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 50.8 % 118 60

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-3.0-or-later
       2                 :             : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
       3                 :             : 
       4                 :             : #define G_LOG_DOMAIN "valent-contact-cache"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <libvalent-core.h>
       9                 :             : 
      10                 :             : #include "valent-contact-cache-private.h"
      11                 :             : #include "valent-contact-store.h"
      12                 :             : #include "valent-eds.h"
      13                 :             : 
      14                 :             : 
      15                 :             : /**
      16                 :             :  * ValentContactCache:
      17                 :             :  *
      18                 :             :  * An implementation of [class@Valent.ContactStore].
      19                 :             :  *
      20                 :             :  * `ValentContactCache` is a simple implementation of [class@Valent.ContactStore]
      21                 :             :  * for local contact store, used as a fallback when Evolution Data Server is not
      22                 :             :  * available.
      23                 :             :  *
      24                 :             :  * Since: 1.0
      25                 :             :  */
      26                 :             : 
      27                 :             : struct _ValentContactCache
      28                 :             : {
      29                 :             :   ValentContactStore  parent_instance;
      30                 :             : 
      31                 :             :   EBookCache         *cache;
      32                 :             :   char               *path;
      33                 :             : };
      34                 :             : 
      35   [ +  +  +  - ]:         194 : G_DEFINE_FINAL_TYPE (ValentContactCache, valent_contact_cache, VALENT_TYPE_CONTACT_STORE)
      36                 :             : 
      37                 :             : 
      38                 :             : enum {
      39                 :             :   PROP_0,
      40                 :             :   PROP_PATH,
      41                 :             :   N_PROPERTIES
      42                 :             : };
      43                 :             : 
      44                 :             : static GParamSpec *properties[N_PROPERTIES] = { NULL, };
      45                 :             : 
      46                 :             : static inline void
      47                 :          14 : object_slist_free (gpointer slist)
      48                 :             : {
      49                 :          14 :   g_slist_free_full (slist, g_object_unref);
      50                 :          14 : }
      51                 :             : 
      52                 :             : static inline void
      53                 :           1 : string_slist_free (gpointer slist)
      54                 :             : {
      55                 :           1 :   g_slist_free_full (slist, g_free);
      56                 :           1 : }
      57                 :             : 
      58                 :             : /*
      59                 :             :  * ValentContactStore
      60                 :             :  */
      61                 :             : static void
      62                 :          14 : valent_contact_cache_add_task (GTask        *task,
      63                 :             :                                gpointer      source_object,
      64                 :             :                                gpointer      task_data,
      65                 :             :                                GCancellable *cancellable)
      66                 :             : {
      67                 :          14 :   ValentContactCache *self = VALENT_CONTACT_CACHE (source_object);
      68                 :          14 :   ValentContactStore *store = VALENT_CONTACT_STORE (source_object);
      69                 :          14 :   GSList *contacts = task_data;
      70                 :          14 :   GError *error = NULL;
      71                 :             : 
      72         [ +  - ]:          14 :   if (g_task_return_error_if_cancelled (task))
      73                 :           0 :     return;
      74                 :             : 
      75                 :          14 :   valent_object_lock (VALENT_OBJECT (self));
      76                 :          14 :   e_book_cache_put_contacts (self->cache,
      77                 :             :                              contacts,
      78                 :             :                              NULL,
      79                 :             :                              NULL,
      80                 :             :                              E_CACHE_IS_OFFLINE,
      81                 :             :                              cancellable,
      82                 :             :                              &error);
      83                 :          14 :   valent_object_unlock (VALENT_OBJECT (self));
      84                 :             : 
      85         [ -  + ]:          14 :   if (error != NULL)
      86                 :           0 :     return g_task_return_error (task, error);
      87                 :             : 
      88         [ +  + ]:          35 :   for (const GSList *iter = contacts; iter; iter = iter->next)
      89                 :          21 :     valent_contact_store_contact_added (store, E_CONTACT (iter->data));
      90                 :             : 
      91                 :          14 :   g_task_return_boolean (task, TRUE);
      92                 :             : }
      93                 :             : 
      94                 :             : static void
      95                 :          14 : valent_contact_cache_add_contacts (ValentContactStore  *store,
      96                 :             :                                    GSList              *contacts,
      97                 :             :                                    GCancellable        *cancellable,
      98                 :             :                                    GAsyncReadyCallback  callback,
      99                 :             :                                    gpointer             user_data)
     100                 :             : {
     101                 :          28 :   g_autoptr (GTask) task = NULL;
     102                 :          14 :   GSList *additions = NULL;
     103                 :             : 
     104         [ +  - ]:          14 :   g_assert (VALENT_IS_CONTACT_STORE (store));
     105         [ -  + ]:          14 :   g_assert (contacts != NULL);
     106   [ +  +  +  -  :          14 :   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  +  -  - ]
     107                 :             : 
     108         [ +  + ]:          35 :   for (const GSList *iter = contacts; iter; iter = iter->next)
     109                 :          21 :     additions = g_slist_append (additions, g_object_ref (iter->data));
     110                 :             : 
     111                 :          14 :   task = g_task_new (store, cancellable, callback, user_data);
     112         [ +  - ]:          14 :   g_task_set_source_tag (task, valent_contact_cache_add_contacts);
     113                 :          14 :   g_task_set_task_data (task, additions, object_slist_free);
     114         [ +  - ]:          14 :   g_task_run_in_thread (task, valent_contact_cache_add_task);
     115                 :          14 : }
     116                 :             : 
     117                 :             : static void
     118                 :           1 : valent_contact_cache_remove_task (GTask        *task,
     119                 :             :                                   gpointer      source_object,
     120                 :             :                                   gpointer      task_data,
     121                 :             :                                   GCancellable *cancellable)
     122                 :             : {
     123                 :           1 :   ValentContactCache *self = VALENT_CONTACT_CACHE (source_object);
     124                 :           1 :   ValentContactStore *store = VALENT_CONTACT_STORE (source_object);
     125                 :           1 :   GSList *uids = task_data;
     126                 :           1 :   GError *error = NULL;
     127                 :             : 
     128         [ +  - ]:           1 :   if (g_task_return_error_if_cancelled (task))
     129                 :           0 :     return;
     130                 :             : 
     131                 :           1 :   valent_object_lock (VALENT_OBJECT (self));
     132                 :           1 :   e_book_cache_remove_contacts (self->cache,
     133                 :             :                                 uids,
     134                 :             :                                 0,
     135                 :             :                                 E_CACHE_IS_OFFLINE,
     136                 :             :                                 cancellable,
     137                 :             :                                 &error);
     138                 :           1 :   valent_object_unlock (VALENT_OBJECT (self));
     139                 :             : 
     140         [ -  + ]:           1 :   if (error != NULL)
     141                 :           0 :     return g_task_return_error (task, error);
     142                 :             : 
     143         [ +  + ]:           2 :   for (const GSList *iter = uids; iter; iter = iter->next)
     144                 :           1 :     valent_contact_store_contact_removed (store, (char *)iter->data);
     145                 :             : 
     146                 :           1 :   g_task_return_boolean (task, TRUE);
     147                 :             : }
     148                 :             : 
     149                 :             : static void
     150                 :           1 : valent_contact_cache_remove_contacts (ValentContactStore  *store,
     151                 :             :                                       GSList              *uids,
     152                 :             :                                       GCancellable        *cancellable,
     153                 :             :                                       GAsyncReadyCallback  callback,
     154                 :             :                                       gpointer             user_data)
     155                 :             : {
     156                 :           2 :   g_autoptr (GTask) task = NULL;
     157                 :           1 :   GSList *removals = NULL;
     158                 :             : 
     159         [ +  - ]:           1 :   g_assert (VALENT_IS_CONTACT_STORE (store));
     160         [ -  + ]:           1 :   g_assert (uids != NULL);
     161   [ -  +  -  -  :           1 :   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  -  -  - ]
     162                 :             : 
     163         [ +  + ]:           2 :   for (const GSList *iter = uids; iter; iter = iter->next)
     164         [ -  + ]:           2 :     removals = g_slist_append (removals, g_strdup (iter->data));
     165                 :             : 
     166                 :           1 :   task = g_task_new (store, cancellable, callback, user_data);
     167         [ +  - ]:           1 :   g_task_set_source_tag (task, valent_contact_cache_remove_contacts);
     168                 :           1 :   g_task_set_task_data (task, removals, string_slist_free);
     169         [ +  - ]:           1 :   g_task_run_in_thread (task, valent_contact_cache_remove_task);
     170                 :           1 : }
     171                 :             : 
     172                 :             : static void
     173                 :           2 : valent_contact_cache_get_contact_task (GTask        *task,
     174                 :             :                                        gpointer      source_object,
     175                 :             :                                        gpointer      task_data,
     176                 :             :                                        GCancellable *cancellable)
     177                 :             : {
     178                 :           2 :   ValentContactCache *self = VALENT_CONTACT_CACHE (source_object);
     179                 :           2 :   const char *uid = task_data;
     180                 :           2 :   EContact *contact = NULL;
     181                 :           2 :   GError *error = NULL;
     182                 :             : 
     183         [ +  - ]:           2 :   if (g_task_return_error_if_cancelled (task))
     184                 :           1 :     return;
     185                 :             : 
     186                 :           2 :   valent_object_lock (VALENT_OBJECT (self));
     187                 :           2 :   e_book_cache_get_contact (self->cache,
     188                 :             :                             uid,
     189                 :             :                             FALSE,
     190                 :             :                             &contact,
     191                 :             :                             cancellable,
     192                 :             :                             &error);
     193                 :           2 :   valent_object_unlock (VALENT_OBJECT (self));
     194                 :             : 
     195         [ +  + ]:           2 :   if (error != NULL)
     196                 :           1 :     return g_task_return_error (task, error);
     197                 :             : 
     198                 :           1 :   g_task_return_pointer (task, contact, g_object_unref);
     199                 :             : }
     200                 :             : 
     201                 :             : static void
     202                 :           2 : valent_contact_cache_get_contact (ValentContactStore  *store,
     203                 :             :                                   const char          *uid,
     204                 :             :                                   GCancellable        *cancellable,
     205                 :             :                                   GAsyncReadyCallback  callback,
     206                 :             :                                   gpointer             user_data)
     207                 :             : {
     208                 :           4 :   g_autoptr (GTask) task = NULL;
     209                 :             : 
     210         [ +  - ]:           2 :   g_assert (VALENT_IS_CONTACT_STORE (store));
     211         [ -  + ]:           2 :   g_assert (uid != NULL);
     212   [ -  +  -  -  :           2 :   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  -  -  - ]
     213                 :             : 
     214                 :           2 :   task = g_task_new (store, cancellable, callback, user_data);
     215         [ +  - ]:           2 :   g_task_set_source_tag (task, valent_contact_cache_get_contact);
     216         [ -  + ]:           4 :   g_task_set_task_data (task, g_strdup (uid), g_free);
     217         [ +  - ]:           2 :   g_task_run_in_thread (task, valent_contact_cache_get_contact_task);
     218                 :           2 : }
     219                 :             : 
     220                 :             : static void
     221                 :          12 : valent_contact_cache_query_task (GTask        *task,
     222                 :             :                                  gpointer      source_object,
     223                 :             :                                  gpointer      task_data,
     224                 :             :                                  GCancellable *cancellable)
     225                 :             : {
     226                 :          12 :   ValentContactCache *self = VALENT_CONTACT_CACHE (source_object);
     227                 :          12 :   const char *query = task_data;
     228                 :          12 :   GSList *results = NULL;
     229                 :          12 :   GSList *contacts = NULL;
     230                 :          12 :   GError *error = NULL;
     231                 :             : 
     232         [ +  - ]:          12 :   if (g_task_return_error_if_cancelled (task))
     233                 :           0 :     return;
     234                 :             : 
     235                 :          12 :   valent_object_lock (VALENT_OBJECT (self));
     236                 :          12 :   e_book_cache_search (self->cache,
     237                 :             :                        query,
     238                 :             :                        FALSE,
     239                 :             :                        &results,
     240                 :             :                        cancellable,
     241                 :             :                        &error);
     242                 :          12 :   valent_object_unlock (VALENT_OBJECT (self));
     243                 :             : 
     244         [ -  + ]:          12 :   if (error != NULL)
     245                 :           0 :     return g_task_return_error (task, error);
     246                 :             : 
     247         [ +  + ]:          28 :   for (const GSList *iter = results; iter; iter = iter->next)
     248                 :             :     {
     249                 :          16 :       EBookCacheSearchData *result = iter->data;
     250                 :          16 :       EContact *contact;
     251                 :             : 
     252                 :          16 :       contact = e_contact_new_from_vcard (result->vcard);
     253                 :          16 :       contacts = g_slist_prepend (contacts, contact);
     254                 :             :     }
     255                 :          12 :   g_slist_free_full (results, e_book_cache_search_data_free);
     256                 :             : 
     257                 :          12 :   g_task_return_pointer (task, contacts, object_slist_free);
     258                 :             : }
     259                 :             : 
     260                 :             : static void
     261                 :          12 : valent_contact_cache_query (ValentContactStore  *store,
     262                 :             :                             const char          *query,
     263                 :             :                             GCancellable        *cancellable,
     264                 :             :                             GAsyncReadyCallback  callback,
     265                 :             :                             gpointer             user_data)
     266                 :             : {
     267                 :          24 :   g_autoptr (GTask) task = NULL;
     268                 :             : 
     269         [ +  - ]:          12 :   g_assert (VALENT_IS_CONTACT_STORE (store));
     270         [ -  + ]:          12 :   g_assert (query != NULL);
     271   [ +  +  +  -  :          12 :   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  +  -  - ]
     272                 :             : 
     273                 :          12 :   task = g_task_new (store, cancellable, callback, user_data);
     274         [ +  - ]:          12 :   g_task_set_source_tag (task, valent_contact_cache_query);
     275         [ -  + ]:          24 :   g_task_set_task_data (task, g_strdup (query), g_free);
     276         [ +  - ]:          12 :   g_task_run_in_thread (task, valent_contact_cache_query_task);
     277                 :          12 : }
     278                 :             : 
     279                 :             : /*
     280                 :             :  * GObject
     281                 :             :  */
     282                 :             : static void
     283                 :          17 : valent_contact_cache_constructed (GObject *object)
     284                 :             : {
     285                 :          17 :   ValentContactCache *self = VALENT_CONTACT_CACHE (object);
     286                 :          17 :   ValentContactStore *store = VALENT_CONTACT_STORE (object);
     287                 :          17 :   ESource *source;
     288                 :          34 :   g_autoptr (GError) error = NULL;
     289                 :             : 
     290                 :          17 :   source = valent_contact_store_get_source (store);
     291                 :             : 
     292                 :             :   /* This will usually be the path for the contacts plugin, since the device ID
     293                 :             :    * is used as the ESource UID. */
     294         [ +  - ]:          17 :   if (self->path == NULL)
     295                 :             :     {
     296                 :          34 :       g_autoptr (ValentContext) context = NULL;
     297         [ +  - ]:          17 :       g_autoptr (GFile) contacts_db = NULL;
     298                 :             : 
     299                 :          17 :       context = valent_context_new (NULL, "contacts", e_source_get_uid (source));
     300                 :          17 :       contacts_db = valent_context_get_cache_file (context, "contacts.db");
     301         [ +  - ]:          17 :       self->path = g_file_get_path (contacts_db);
     302                 :             :     }
     303                 :             : 
     304                 :          17 :   valent_object_lock (VALENT_OBJECT (self));
     305                 :          17 :   self->cache = e_book_cache_new (self->path, source, NULL, &error);
     306                 :          17 :   valent_object_unlock (VALENT_OBJECT (self));
     307                 :             : 
     308         [ -  + ]:          17 :   if (error != NULL)
     309                 :           0 :     g_critical ("%s(): %s", G_STRFUNC, error->message);
     310                 :             : 
     311         [ -  + ]:          17 :   G_OBJECT_CLASS (valent_contact_cache_parent_class)->constructed (object);
     312                 :          17 : }
     313                 :             : 
     314                 :             : static void
     315                 :           8 : valent_contact_cache_finalize (GObject *object)
     316                 :             : {
     317                 :           8 :   ValentContactCache *self = VALENT_CONTACT_CACHE (object);
     318                 :             : 
     319                 :           8 :   valent_object_lock (VALENT_OBJECT (self));
     320         [ +  - ]:           8 :   g_clear_object (&self->cache);
     321         [ +  - ]:           8 :   g_clear_pointer (&self->path, g_free);
     322                 :           8 :   valent_object_unlock (VALENT_OBJECT (self));
     323                 :             : 
     324                 :           8 :   G_OBJECT_CLASS (valent_contact_cache_parent_class)->finalize (object);
     325                 :           8 : }
     326                 :             : 
     327                 :             : static void
     328                 :           1 : valent_contact_cache_get_property (GObject    *object,
     329                 :             :                                    guint       prop_id,
     330                 :             :                                    GValue     *value,
     331                 :             :                                    GParamSpec *pspec)
     332                 :             : {
     333                 :           1 :   ValentContactCache *self = VALENT_CONTACT_CACHE (object);
     334                 :             : 
     335         [ +  - ]:           1 :   switch (prop_id)
     336                 :             :     {
     337                 :           1 :     case PROP_PATH:
     338                 :           1 :       g_value_set_string (value, self->path);
     339                 :           1 :       break;
     340                 :             : 
     341                 :           0 :     default:
     342                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     343                 :             :     }
     344                 :           1 : }
     345                 :             : 
     346                 :             : static void
     347                 :          17 : valent_contact_cache_set_property (GObject      *object,
     348                 :             :                                    guint         prop_id,
     349                 :             :                                    const GValue *value,
     350                 :             :                                    GParamSpec   *pspec)
     351                 :             : {
     352                 :          17 :   ValentContactCache *self = VALENT_CONTACT_CACHE (object);
     353                 :             : 
     354         [ +  - ]:          17 :   switch (prop_id)
     355                 :             :     {
     356                 :          17 :     case PROP_PATH:
     357                 :          17 :       self->path = g_value_dup_string (value);
     358                 :          17 :       break;
     359                 :             : 
     360                 :           0 :     default:
     361                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     362                 :             :     }
     363                 :          17 : }
     364                 :             : 
     365                 :             : static void
     366                 :           7 : valent_contact_cache_class_init (ValentContactCacheClass *klass)
     367                 :             : {
     368                 :           7 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     369                 :           7 :   ValentContactStoreClass *store_class = VALENT_CONTACT_STORE_CLASS (klass);
     370                 :             : 
     371                 :           7 :   object_class->constructed = valent_contact_cache_constructed;
     372                 :           7 :   object_class->finalize = valent_contact_cache_finalize;
     373                 :           7 :   object_class->get_property = valent_contact_cache_get_property;
     374                 :           7 :   object_class->set_property = valent_contact_cache_set_property;
     375                 :             : 
     376                 :           7 :   store_class->add_contacts = valent_contact_cache_add_contacts;
     377                 :           7 :   store_class->remove_contacts = valent_contact_cache_remove_contacts;
     378                 :           7 :   store_class->query = valent_contact_cache_query;
     379                 :           7 :   store_class->get_contact = valent_contact_cache_get_contact;
     380                 :             : 
     381                 :             :   /**
     382                 :             :    * ValentContactCache:path:
     383                 :             :    *
     384                 :             :    * The path to the database file.
     385                 :             :    *
     386                 :             :    * Since: 1.0
     387                 :             :    */
     388                 :          14 :   properties [PROP_PATH] =
     389                 :           7 :     g_param_spec_string ("path", NULL, NULL,
     390                 :             :                          NULL,
     391                 :             :                          (G_PARAM_READWRITE |
     392                 :             :                           G_PARAM_CONSTRUCT_ONLY |
     393                 :             :                           G_PARAM_EXPLICIT_NOTIFY |
     394                 :             :                           G_PARAM_STATIC_STRINGS));
     395                 :             : 
     396                 :           7 :   g_object_class_install_properties (object_class, N_PROPERTIES, properties);
     397                 :           7 : }
     398                 :             : 
     399                 :             : static void
     400                 :          17 : valent_contact_cache_init (ValentContactCache *self)
     401                 :             : {
     402                 :          17 : }
     403                 :             : 
        

Generated by: LCOV version 2.0-1