Make use of G_DEFINE_QUARK()
[platform/upstream/evolution-data-server.git] / libedataserver / e-client.c
1 /*
2  * e-client.c
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
16  *
17  *
18  * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <glib/gi18n-lib.h>
27 #include <gio/gio.h>
28
29 #include <libedataserver/e-data-server-util.h>
30
31 #include "e-gdbus-marshallers.h"
32
33 #include "e-client.h"
34 #include "e-client-private.h"
35
36 #define E_CLIENT_GET_PRIVATE(obj) \
37         (G_TYPE_INSTANCE_GET_PRIVATE \
38         ((obj), E_TYPE_CLIENT, EClientPrivate))
39
40 struct _EClientPrivate {
41         GRecMutex prop_mutex;
42
43         ESource *source;
44         gchar *uri;
45         gboolean online;
46         gboolean readonly;
47         gboolean opened;
48         gboolean capabilities_retrieved;
49         GSList *capabilities;
50
51         GHashTable *backend_property_cache;
52
53         GRecMutex ops_mutex;
54         guint32 last_opid;
55         GHashTable *ops; /* opid to GCancellable */
56 };
57
58 enum {
59         PROP_0,
60         PROP_SOURCE,
61         PROP_CAPABILITIES,
62         PROP_READONLY,
63         PROP_ONLINE,
64         PROP_OPENED
65 };
66
67 enum {
68         OPENED,
69         BACKEND_ERROR,
70         BACKEND_DIED,
71         BACKEND_PROPERTY_CHANGED,
72         LAST_SIGNAL
73 };
74
75 static guint signals[LAST_SIGNAL];
76
77 G_DEFINE_ABSTRACT_TYPE (EClient, e_client, G_TYPE_OBJECT)
78
79 /*
80  * Well-known client backend properties, which are common for each #EClient:
81  * @CLIENT_BACKEND_PROPERTY_OPENED: Is set to "TRUE" or "FALSE" depending
82  *   whether the backend is fully opened.
83  * @CLIENT_BACKEND_PROPERTY_OPENING: Is set to "TRUE" or "FALSE" depending
84  *   whether the backend is processing its opening phase.
85  * @CLIENT_BACKEND_PROPERTY_ONLINE: Is set to "TRUE" or "FALSE" depending
86  *   on the backend's loaded state. See also e_client_is_online().
87  * @CLIENT_BACKEND_PROPERTY_READONLY: Is set to "TRUE" or "FALSE" depending
88  *   on the backend's readonly state. See also e_client_is_readonly().
89  * @CLIENT_BACKEND_PROPERTY_CACHE_DIR: Local folder with cached data used
90  *   by the backend.
91  * @CLIENT_BACKEND_PROPERTY_CAPABILITIES: Retrieves comma-separated list
92  *   of capabilities supported by the backend. Preferred method of retreiving
93  *   and working with capabilities is e_client_get_capabilities() and
94  *   e_client_check_capability().
95  */
96
97 G_DEFINE_QUARK (e-client-error-quark, e_client_error)
98
99 /**
100  * e_client_error_to_string:
101  *
102  * FIXME: Document me.
103  *
104  * Since: 3.2
105  **/
106 const gchar *
107 e_client_error_to_string (EClientError code)
108 {
109         switch (code) {
110         case E_CLIENT_ERROR_INVALID_ARG:
111                 return _("Invalid argument");
112         case E_CLIENT_ERROR_BUSY:
113                 return _("Backend is busy");
114         case E_CLIENT_ERROR_SOURCE_NOT_LOADED:
115                 return _("Source not loaded");
116         case E_CLIENT_ERROR_SOURCE_ALREADY_LOADED:
117                 return _("Source already loaded");
118         case E_CLIENT_ERROR_AUTHENTICATION_FAILED:
119                 return _("Authentication failed");
120         case E_CLIENT_ERROR_AUTHENTICATION_REQUIRED:
121                 return _("Authentication required");
122         case E_CLIENT_ERROR_REPOSITORY_OFFLINE:
123                 return _("Repository offline");
124         case E_CLIENT_ERROR_OFFLINE_UNAVAILABLE:
125                 /* Translators: This means that the EClient does not support offline mode, or
126                  * it's not set to by a user, thus it is unavailable while user is not connected. */
127                 return _("Offline unavailable");
128         case E_CLIENT_ERROR_PERMISSION_DENIED:
129                 return _("Permission denied");
130         case E_CLIENT_ERROR_CANCELLED:
131                 return _("Cancelled");
132         case E_CLIENT_ERROR_COULD_NOT_CANCEL:
133                 return _("Could not cancel");
134         case E_CLIENT_ERROR_NOT_SUPPORTED:
135                 return _("Not supported");
136         case E_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD:
137                 return _("Unsupported authentication method");
138         case E_CLIENT_ERROR_TLS_NOT_AVAILABLE:
139                 return _("TLS not available");
140         case E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED:
141                 return _("Search size limit exceeded");
142         case E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED:
143                 return _("Search time limit exceeded");
144         case E_CLIENT_ERROR_INVALID_QUERY:
145                 return _("Invalid query");
146         case E_CLIENT_ERROR_QUERY_REFUSED:
147                 return _("Query refused");
148         case E_CLIENT_ERROR_DBUS_ERROR:
149                 return _("D-Bus error");
150         case E_CLIENT_ERROR_OTHER_ERROR:
151                 return _("Other error");
152         case E_CLIENT_ERROR_NOT_OPENED:
153                 return _("Backend is not opened yet");
154         }
155
156         return _("Unknown error");
157 }
158
159 /**
160  * e_client_error_create:
161  * @code: an #EClientError code to create
162  * @custom_msg: custom message to use for the error; can be %NULL
163  *
164  * Returns: a new #GError containing an E_CLIENT_ERROR of the given
165  * @code. If the @custom_msg is NULL, then the error message is
166  * the one returned from e_client_error_to_string() for the @code,
167  * otherwise the given message is used.
168  *
169  * Returned pointer should be freed with g_error_free().
170  *
171  * Since: 3.2
172  **/
173 GError *
174 e_client_error_create (EClientError code,
175                        const gchar *custom_msg)
176 {
177         return g_error_new_literal (E_CLIENT_ERROR, code, custom_msg ? custom_msg : e_client_error_to_string (code));
178 }
179
180 static void client_set_source (EClient *client, ESource *source);
181
182 static void
183 e_client_init (EClient *client)
184 {
185         client->priv = E_CLIENT_GET_PRIVATE (client);
186
187         client->priv->readonly = TRUE;
188
189         g_rec_mutex_init (&client->priv->prop_mutex);
190         client->priv->backend_property_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
191
192         g_rec_mutex_init (&client->priv->ops_mutex);
193         client->priv->last_opid = 0;
194         client->priv->ops = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
195 }
196
197 static void
198 client_dispose (GObject *object)
199 {
200         EClient *client;
201
202         client = E_CLIENT (object);
203
204         e_client_cancel_all (client);
205
206         /* Chain up to parent's dispose() method. */
207         G_OBJECT_CLASS (e_client_parent_class)->dispose (object);
208 }
209
210 static void
211 client_finalize (GObject *object)
212 {
213         EClient *client;
214         EClientPrivate *priv;
215
216         client = E_CLIENT (object);
217
218         priv = client->priv;
219
220         g_rec_mutex_lock (&priv->prop_mutex);
221
222         if (priv->source) {
223                 g_object_unref (priv->source);
224                 priv->source = NULL;
225         }
226
227         if (priv->uri) {
228                 g_free (priv->uri);
229                 priv->uri = NULL;
230         }
231
232         if (priv->capabilities) {
233                 g_slist_foreach (priv->capabilities, (GFunc) g_free, NULL);
234                 g_slist_free (priv->capabilities);
235                 priv->capabilities = NULL;
236         }
237
238         if (priv->backend_property_cache) {
239                 g_hash_table_destroy (priv->backend_property_cache);
240                 priv->backend_property_cache = NULL;
241         }
242
243         if (priv->ops) {
244                 g_hash_table_destroy (priv->ops);
245                 priv->ops = NULL;
246         }
247
248         g_rec_mutex_unlock (&priv->prop_mutex);
249         g_rec_mutex_clear (&priv->prop_mutex);
250         g_rec_mutex_clear (&priv->ops_mutex);
251
252         /* Chain up to parent's finalize() method. */
253         G_OBJECT_CLASS (e_client_parent_class)->finalize (object);
254 }
255
256 static void
257 client_set_property (GObject *object,
258                      guint property_id,
259                      const GValue *value,
260                      GParamSpec *pspec)
261 {
262         switch (property_id) {
263                 case PROP_SOURCE:
264                         client_set_source (E_CLIENT (object), g_value_get_object (value));
265                         return;
266
267                 case PROP_ONLINE:
268                         e_client_set_online (E_CLIENT (object), g_value_get_boolean (value));
269                         return;
270         }
271
272         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
273 }
274
275 static void
276 client_get_property (GObject *object,
277                      guint property_id,
278                      GValue *value,
279                      GParamSpec *pspec)
280 {
281         switch (property_id) {
282                 case PROP_SOURCE:
283                         g_value_set_object (value, e_client_get_source (E_CLIENT (object)));
284                         return;
285
286                 case PROP_CAPABILITIES:
287                         g_value_set_pointer (value, (gpointer) e_client_get_capabilities (E_CLIENT (object)));
288                         return;
289
290                 case PROP_READONLY:
291                         g_value_set_boolean (value, e_client_is_readonly (E_CLIENT (object)));
292                         return;
293
294                 case PROP_ONLINE:
295                         g_value_set_boolean (value, e_client_is_online (E_CLIENT (object)));
296                         return;
297
298                 case PROP_OPENED:
299                         g_value_set_boolean (value, e_client_is_opened (E_CLIENT (object)));
300                         return;
301         }
302
303         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
304 }
305
306 static void
307 client_remove_thread (GSimpleAsyncResult *simple,
308                       GObject *object,
309                       GCancellable *cancellable)
310 {
311         GError *error = NULL;
312
313         e_client_remove_sync (E_CLIENT (object), cancellable, &error);
314
315         if (error != NULL)
316                 g_simple_async_result_take_error (simple, error);
317 }
318
319 static void
320 client_remove (EClient *client,
321                GCancellable *cancellable,
322                GAsyncReadyCallback callback,
323                gpointer user_data)
324 {
325         GSimpleAsyncResult *simple;
326
327         simple = g_simple_async_result_new (
328                 G_OBJECT (client), callback, user_data, client_remove);
329
330         g_simple_async_result_set_check_cancellable (simple, cancellable);
331
332         g_simple_async_result_run_in_thread (
333                 simple, client_remove_thread,
334                 G_PRIORITY_DEFAULT, cancellable);
335
336         g_object_unref (simple);
337 }
338
339 static gboolean
340 client_remove_finish (EClient *client,
341                       GAsyncResult *result,
342                       GError **error)
343 {
344         GSimpleAsyncResult *simple;
345
346         g_return_val_if_fail (
347                 g_simple_async_result_is_valid (
348                 result, G_OBJECT (client), client_remove), FALSE);
349
350         simple = G_SIMPLE_ASYNC_RESULT (result);
351
352         /* Assume success unless a GError is set. */
353         return !g_simple_async_result_propagate_error (simple, error);
354 }
355
356 static gboolean
357 client_remove_sync (EClient *client,
358                     GCancellable *cancellable,
359                     GError **error)
360 {
361         ESource *source;
362
363         source = e_client_get_source (client);
364
365         return e_source_remove_sync (source, cancellable, error);
366 }
367
368 static void
369 e_client_class_init (EClientClass *class)
370 {
371         GObjectClass *object_class;
372
373         g_type_class_add_private (class, sizeof (EClientPrivate));
374
375         object_class = G_OBJECT_CLASS (class);
376         object_class->set_property = client_set_property;
377         object_class->get_property = client_get_property;
378         object_class->dispose = client_dispose;
379         object_class->finalize = client_finalize;
380
381         class->remove = client_remove;
382         class->remove_finish = client_remove_finish;
383         class->remove_sync = client_remove_sync;
384
385         g_object_class_install_property (
386                 object_class,
387                 PROP_SOURCE,
388                 g_param_spec_object (
389                         "source",
390                         NULL,
391                         NULL,
392                         E_TYPE_SOURCE,
393                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
394
395         g_object_class_install_property (
396                 object_class,
397                 PROP_CAPABILITIES,
398                 g_param_spec_pointer (
399                         "capabilities",
400                         NULL,
401                         NULL,
402                         G_PARAM_READABLE));
403
404         g_object_class_install_property (
405                 object_class,
406                 PROP_READONLY,
407                 g_param_spec_boolean (
408                         "readonly",
409                         NULL,
410                         NULL,
411                         FALSE,
412                         G_PARAM_READABLE));
413
414         g_object_class_install_property (
415                 object_class,
416                 PROP_ONLINE,
417                 g_param_spec_boolean (
418                         "online",
419                         NULL,
420                         NULL,
421                         FALSE,
422                         G_PARAM_READWRITE));
423
424         g_object_class_install_property (
425                 object_class,
426                 PROP_OPENED,
427                 g_param_spec_boolean (
428                         "opened",
429                         NULL,
430                         NULL,
431                         FALSE,
432                         G_PARAM_READABLE));
433
434         signals[OPENED] = g_signal_new (
435                 "opened",
436                 G_OBJECT_CLASS_TYPE (class),
437                 G_SIGNAL_RUN_LAST,
438                 G_STRUCT_OFFSET (EClientClass, opened),
439                 NULL, NULL,
440                 g_cclosure_marshal_VOID__BOXED,
441                 G_TYPE_NONE, 1,
442                 G_TYPE_ERROR);
443
444         signals[BACKEND_ERROR] = g_signal_new (
445                 "backend-error",
446                 G_OBJECT_CLASS_TYPE (class),
447                 G_SIGNAL_RUN_FIRST,
448                 G_STRUCT_OFFSET (EClientClass, backend_error),
449                 NULL, NULL,
450                 g_cclosure_marshal_VOID__STRING,
451                 G_TYPE_NONE, 1,
452                 G_TYPE_STRING);
453
454         signals[BACKEND_DIED] = g_signal_new (
455                 "backend-died",
456                 G_OBJECT_CLASS_TYPE (class),
457                 G_SIGNAL_RUN_LAST,
458                 G_STRUCT_OFFSET (EClientClass, backend_died),
459                 NULL, NULL,
460                 g_cclosure_marshal_VOID__VOID,
461                 G_TYPE_NONE, 0);
462
463         signals[BACKEND_PROPERTY_CHANGED] = g_signal_new (
464                 "backend-property-changed",
465                 G_OBJECT_CLASS_TYPE (class),
466                 G_SIGNAL_RUN_LAST,
467                 G_STRUCT_OFFSET (EClientClass, backend_property_changed),
468                 NULL, NULL,
469                 e_gdbus_marshallers_VOID__STRING_STRING,
470                 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
471 }
472
473 static void
474 client_set_source (EClient *client,
475                    ESource *source)
476 {
477         g_return_if_fail (E_IS_CLIENT (client));
478         g_return_if_fail (E_IS_SOURCE (source));
479
480         g_object_ref (source);
481
482         if (client->priv->source)
483                 g_object_unref (client->priv->source);
484
485         client->priv->source = source;
486 }
487
488 /**
489  * e_client_get_source:
490  * @client: an #EClient
491  *
492  * Get the #ESource that this client has assigned.
493  *
494  * Returns: (transfer none): The source.
495  *
496  * Since: 3.2
497  **/
498 ESource *
499 e_client_get_source (EClient *client)
500 {
501         g_return_val_if_fail (E_IS_CLIENT (client), NULL);
502
503         return client->priv->source;
504 }
505
506 static void
507 client_ensure_capabilities (EClient *client)
508 {
509         gchar *capabilities;
510
511         g_return_if_fail (E_IS_CLIENT (client));
512
513         if (client->priv->capabilities_retrieved || client->priv->capabilities)
514                 return;
515
516         g_rec_mutex_lock (&client->priv->prop_mutex);
517
518         capabilities = NULL;
519         e_client_retrieve_capabilities_sync (client, &capabilities, NULL, NULL);
520         /* e_client_set_capabilities is called inside the previous function */
521         g_free (capabilities);
522
523         client->priv->capabilities_retrieved = TRUE;
524
525         g_rec_mutex_unlock (&client->priv->prop_mutex);
526 }
527
528 /**
529  * e_client_get_capabilities:
530  * @client: an #EClient
531  *
532  * Get list of strings with capabilities advertised by a backend.
533  * This list, together with inner strings, is owned by the @client.
534  * To check for individual capabilities use e_client_check_capability().
535  *
536  * Returns: (element-type utf8) (transfer none): #GSList of const strings
537  *          of capabilities
538  *
539  * Since: 3.2
540  **/
541 const GSList *
542 e_client_get_capabilities (EClient *client)
543 {
544         g_return_val_if_fail (E_IS_CLIENT (client), NULL);
545
546         client_ensure_capabilities (client);
547
548         return client->priv->capabilities;
549 }
550
551 /**
552  * e_client_check_capability:
553  * @client: an #EClient
554  * @capability: a capability
555  *
556  * Check if backend supports particular capability.
557  * To get all capabilities use e_client_get_capabilities().
558  *
559  * Returns: #GSList of const strings of capabilities
560  *
561  * Since: 3.2
562  **/
563 gboolean
564 e_client_check_capability (EClient *client,
565                            const gchar *capability)
566 {
567         GSList *iter;
568
569         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
570         g_return_val_if_fail (capability, FALSE);
571
572         g_rec_mutex_lock (&client->priv->prop_mutex);
573
574         client_ensure_capabilities (client);
575
576         for (iter = client->priv->capabilities; iter; iter = g_slist_next (iter)) {
577                 const gchar *cap = iter->data;
578
579                 if (cap && g_ascii_strcasecmp (cap, capability) == 0) {
580                         g_rec_mutex_unlock (&client->priv->prop_mutex);
581                         return TRUE;
582                 }
583         }
584
585         g_rec_mutex_unlock (&client->priv->prop_mutex);
586
587         return FALSE;
588 }
589
590 /**
591  * e_client_check_refresh_supported:
592  * @client: A client.
593  *
594  * Checks whether a client supports explicit refreshing
595  * (see e_client_refresh()).
596  *
597  * Returns: TRUE if the client supports refreshing, FALSE otherwise.
598  *
599  * Since: 3.2
600  **/
601 gboolean
602 e_client_check_refresh_supported (EClient *client)
603 {
604         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
605
606         return e_client_check_capability (client, "refresh-supported");
607 }
608
609 /* capabilities - comma-separated list of capabilities; can be NULL to unset */
610 void
611 e_client_set_capabilities (EClient *client,
612                            const gchar *capabilities)
613 {
614         g_return_if_fail (E_IS_CLIENT (client));
615
616         g_rec_mutex_lock (&client->priv->prop_mutex);
617
618         if (!capabilities)
619                 client->priv->capabilities_retrieved = FALSE;
620
621         g_slist_foreach (client->priv->capabilities, (GFunc) g_free, NULL);
622         g_slist_free (client->priv->capabilities);
623         client->priv->capabilities = e_client_util_parse_comma_strings (capabilities);
624
625         g_rec_mutex_unlock (&client->priv->prop_mutex);
626
627         g_object_notify (G_OBJECT (client), "capabilities");
628 }
629
630 /**
631  * e_client_is_readonly:
632  * @client: an #EClient
633  *
634  * Check if this @client is read-only.
635  *
636  * Returns: %TRUE if this @client is read-only, otherwise %FALSE.
637  *
638  * Since: 3.2
639  **/
640 gboolean
641 e_client_is_readonly (EClient *client)
642 {
643         g_return_val_if_fail (E_IS_CLIENT (client), TRUE);
644
645         return client->priv->readonly;
646 }
647
648 void
649 e_client_set_readonly (EClient *client,
650                        gboolean readonly)
651 {
652         g_return_if_fail (E_IS_CLIENT (client));
653
654         g_rec_mutex_lock (&client->priv->prop_mutex);
655         if (client->priv->readonly == readonly) {
656                 g_rec_mutex_unlock (&client->priv->prop_mutex);
657                 return;
658         }
659
660         client->priv->readonly = readonly;
661
662         g_rec_mutex_unlock (&client->priv->prop_mutex);
663
664         g_object_notify (G_OBJECT (client), "readonly");
665 }
666
667 /**
668  * e_client_is_online:
669  * @client: an #EClient
670  *
671  * Check if this @client is connected.
672  *
673  * Returns: %TRUE if this @client is connected, otherwise %FALSE.
674  *
675  * Since: 3.2
676  **/
677 gboolean
678 e_client_is_online (EClient *client)
679 {
680         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
681
682         return client->priv->online;
683 }
684
685 void
686 e_client_set_online (EClient *client,
687                      gboolean is_online)
688 {
689         g_return_if_fail (E_IS_CLIENT (client));
690
691         /* newly connected/disconnected => make sure capabilities will be correct */
692         e_client_set_capabilities (client, NULL);
693
694         g_rec_mutex_lock (&client->priv->prop_mutex);
695         if (client->priv->online == is_online) {
696                 g_rec_mutex_unlock (&client->priv->prop_mutex);
697                 return;
698         }
699
700         client->priv->online = is_online;
701
702         g_rec_mutex_unlock (&client->priv->prop_mutex);
703
704         g_object_notify (G_OBJECT (client), "online");
705 }
706
707 /**
708  * e_client_is_opened:
709  * @client: an #EClient
710  *
711  * Check if this @client is fully opened. This includes
712  * everything from e_client_open() call up to the authentication,
713  * if required by a backend. Client cannot do any other operation
714  * during the opening phase except of authenticate or cancel it.
715  * Every other operation results in an %E_CLIENT_ERROR_BUSY error.
716  *
717  * Returns: %TRUE if this @client is fully opened, otherwise %FALSE.
718  *
719  * Since: 3.2.
720  **/
721 gboolean
722 e_client_is_opened (EClient *client)
723 {
724         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
725
726         return client->priv->opened;
727 }
728
729 /*
730  * client_cancel_op:
731  * @client: an #EClient
732  * @opid: asynchronous operation ID
733  *
734  * Cancels particular asynchronous operation. The @opid is returned from
735  * an e_client_register_op(). The function does nothing if the asynchronous
736  * operation doesn't exist any more.
737  *
738  * Since: 3.2
739  */
740 static void
741 client_cancel_op (EClient *client,
742                   guint32 opid)
743 {
744         GCancellable *cancellable;
745
746         g_return_if_fail (E_IS_CLIENT (client));
747         g_return_if_fail (client->priv->ops != NULL);
748
749         g_rec_mutex_lock (&client->priv->ops_mutex);
750
751         cancellable = g_hash_table_lookup (client->priv->ops, GINT_TO_POINTER (opid));
752         if (cancellable)
753                 g_cancellable_cancel (cancellable);
754
755         g_rec_mutex_unlock (&client->priv->ops_mutex);
756 }
757
758 static void
759 gather_opids_cb (gpointer opid,
760                  gpointer cancellable,
761                  gpointer ids_list)
762 {
763         GSList **ids = ids_list;
764
765         g_return_if_fail (ids_list != NULL);
766
767         *ids = g_slist_prepend (*ids, opid);
768 }
769
770 static void
771 cancel_op_cb (gpointer opid,
772               gpointer client)
773 {
774         client_cancel_op (client, GPOINTER_TO_INT (opid));
775 }
776
777 /**
778  * e_client_cancel_all:
779  * @client: an #EClient
780  *
781  * Cancels all pending operations started on @client.
782  *
783  * Since: 3.2
784  **/
785 void
786 e_client_cancel_all (EClient *client)
787 {
788         GSList *opids = NULL;
789
790         g_return_if_fail (E_IS_CLIENT (client));
791         g_return_if_fail (client->priv->ops != NULL);
792
793         g_rec_mutex_lock (&client->priv->ops_mutex);
794
795         g_hash_table_foreach (client->priv->ops, gather_opids_cb, &opids);
796
797         g_slist_foreach (opids, cancel_op_cb, client);
798         g_slist_free (opids);
799
800         g_rec_mutex_unlock (&client->priv->ops_mutex);
801 }
802
803 guint32
804 e_client_register_op (EClient *client,
805                       GCancellable *cancellable)
806 {
807         guint32 opid;
808
809         g_return_val_if_fail (E_IS_CLIENT (client), 0);
810         g_return_val_if_fail (client->priv->ops != NULL, 0);
811         g_return_val_if_fail (cancellable != NULL, 0);
812
813         g_rec_mutex_lock (&client->priv->ops_mutex);
814
815         client->priv->last_opid++;
816         if (!client->priv->last_opid)
817                 client->priv->last_opid++;
818
819         while (g_hash_table_lookup (client->priv->ops, GINT_TO_POINTER (client->priv->last_opid)))
820                 client->priv->last_opid++;
821
822         g_return_val_if_fail (client->priv->last_opid != 0, 0);
823
824         opid = client->priv->last_opid;
825         g_hash_table_insert (client->priv->ops, GINT_TO_POINTER (opid), g_object_ref (cancellable));
826
827         g_rec_mutex_unlock (&client->priv->ops_mutex);
828
829         return opid;
830 }
831
832 void
833 e_client_unregister_op (EClient *client,
834                         guint32 opid)
835 {
836         g_return_if_fail (E_IS_CLIENT (client));
837         g_return_if_fail (client->priv->ops != NULL);
838
839         g_rec_mutex_lock (&client->priv->ops_mutex);
840         g_hash_table_remove (client->priv->ops, GINT_TO_POINTER (opid));
841         g_rec_mutex_unlock (&client->priv->ops_mutex);
842 }
843
844 void
845 e_client_emit_opened (EClient *client,
846                       const GError *dbus_error)
847 {
848         GError *local_error = NULL;
849
850         g_return_if_fail (E_IS_CLIENT (client));
851
852         client->priv->opened = dbus_error == NULL;
853
854         if (dbus_error) {
855                 local_error = g_error_copy (dbus_error);
856                 e_client_unwrap_dbus_error (client, local_error, &local_error);
857         }
858
859         g_object_notify (G_OBJECT (client), "opened");
860         g_signal_emit (client, signals[OPENED], 0, local_error);
861
862         if (local_error)
863                 g_error_free (local_error);
864 }
865
866 void
867 e_client_emit_backend_error (EClient *client,
868                              const gchar *error_msg)
869 {
870         g_return_if_fail (E_IS_CLIENT (client));
871         g_return_if_fail (error_msg != NULL);
872
873         g_signal_emit (client, signals[BACKEND_ERROR], 0, error_msg);
874 }
875
876 void
877 e_client_emit_backend_died (EClient *client)
878 {
879         g_return_if_fail (E_IS_CLIENT (client));
880
881         g_signal_emit (client, signals[BACKEND_DIED], 0);
882 }
883
884 void
885 e_client_emit_backend_property_changed (EClient *client,
886                                         const gchar *prop_name,
887                                         const gchar *prop_value)
888 {
889         g_return_if_fail (E_IS_CLIENT (client));
890         g_return_if_fail (prop_name != NULL);
891         g_return_if_fail (*prop_name);
892         g_return_if_fail (prop_value != NULL);
893
894         e_client_update_backend_property_cache (client, prop_name, prop_value);
895
896         g_signal_emit (client, signals[BACKEND_PROPERTY_CHANGED], 0, prop_name, prop_value);
897 }
898
899 void
900 e_client_update_backend_property_cache (EClient *client,
901                                         const gchar *prop_name,
902                                         const gchar *prop_value)
903 {
904         g_return_if_fail (E_IS_CLIENT (client));
905         g_return_if_fail (prop_name != NULL);
906         g_return_if_fail (*prop_name);
907         g_return_if_fail (prop_value != NULL);
908
909         g_rec_mutex_lock (&client->priv->prop_mutex);
910
911         if (client->priv->backend_property_cache)
912                 g_hash_table_insert (client->priv->backend_property_cache, g_strdup (prop_name), g_strdup (prop_value));
913
914         g_rec_mutex_unlock (&client->priv->prop_mutex);
915 }
916
917 gchar *
918 e_client_get_backend_property_from_cache (EClient *client,
919                                           const gchar *prop_name)
920 {
921         gchar *prop_value = NULL;
922
923         g_return_val_if_fail (E_IS_CLIENT (client), NULL);
924         g_return_val_if_fail (prop_name != NULL, NULL);
925         g_return_val_if_fail (*prop_name, NULL);
926
927         g_rec_mutex_lock (&client->priv->prop_mutex);
928
929         if (client->priv->backend_property_cache)
930                 prop_value = g_strdup (g_hash_table_lookup (client->priv->backend_property_cache, prop_name));
931
932         g_rec_mutex_unlock (&client->priv->prop_mutex);
933
934         return prop_value;
935 }
936
937 /**
938  * e_client_retrieve_capabilities:
939  * @client: an #EClient
940  * @cancellable: a #GCancellable; can be %NULL
941  * @callback: callback to call when a result is ready
942  * @user_data: user data for the @callback
943  *
944  * Initiates retrieval of capabilities on the @client. This is usually
945  * required only once, after the @client is opened. The returned value
946  * is cached and any subsequent call of e_client_get_capabilities() and
947  * e_client_check_capability() is using the cached value.
948  * The call is finished by e_client_retrieve_capabilities_finish()
949  * from the @callback.
950  *
951  * Since: 3.2
952  **/
953 void
954 e_client_retrieve_capabilities (EClient *client,
955                                 GCancellable *cancellable,
956                                 GAsyncReadyCallback callback,
957                                 gpointer user_data)
958 {
959         EClientClass *class;
960
961         g_return_if_fail (E_IS_CLIENT (client));
962         g_return_if_fail (callback != NULL);
963
964         class = E_CLIENT_GET_CLASS (client);
965         g_return_if_fail (class != NULL);
966         g_return_if_fail (class->retrieve_capabilities != NULL);
967
968         class->retrieve_capabilities (client, cancellable, callback, user_data);
969 }
970
971 /**
972  * e_client_retrieve_capabilities_finish:
973  * @client: an #EClient
974  * @result: a #GAsyncResult
975  * @capabilities: (out): Comma-separated list of capabilities of the @client
976  * @error: (out): a #GError to set an error, if any
977  *
978  * Finishes previous call of e_client_retrieve_capabilities().
979  * Returned value of @capabilities should be freed with g_free(),
980  * when no longer needed.
981  *
982  * Returns: %TRUE if successful, %FALSE otherwise.
983  *
984  * Since: 3.2
985  **/
986 gboolean
987 e_client_retrieve_capabilities_finish (EClient *client,
988                                        GAsyncResult *result,
989                                        gchar **capabilities,
990                                        GError **error)
991 {
992         EClientClass *class;
993         gboolean res;
994
995         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
996         g_return_val_if_fail (capabilities != NULL, FALSE);
997
998         class = E_CLIENT_GET_CLASS (client);
999         g_return_val_if_fail (class != NULL, FALSE);
1000         g_return_val_if_fail (class->retrieve_capabilities_finish != NULL, FALSE);
1001
1002         *capabilities = NULL;
1003         res = class->retrieve_capabilities_finish (client, result, capabilities, error);
1004
1005         e_client_set_capabilities (client, res ? *capabilities : NULL);
1006
1007         if (error && *error)
1008                 e_client_unwrap_dbus_error (client, *error, error);
1009
1010         return res;
1011 }
1012
1013 /**
1014  * e_client_retrieve_capabilities_sync:
1015  * @client: an #EClient
1016  * @capabilities: (out): Comma-separated list of capabilities of the @client
1017  * @cancellable: a #GCancellable; can be %NULL
1018  * @error: (out): a #GError to set an error, if any
1019  *
1020  * Initiates retrieval of capabilities on the @client. This is usually
1021  * required only once, after the @client is opened. The returned value
1022  * is cached and any subsequent call of e_client_get_capabilities() and
1023  * e_client_check_capability() is using the cached value. Returned value
1024  * of @capabilities should be freed with g_free(), when no longer needed.
1025  *
1026  * Returns: %TRUE if successful, %FALSE otherwise.
1027  *
1028  * Since: 3.2
1029  **/
1030 gboolean
1031 e_client_retrieve_capabilities_sync (EClient *client,
1032                                      gchar **capabilities,
1033                                      GCancellable *cancellable,
1034                                      GError **error)
1035 {
1036         EClientClass *class;
1037         gboolean res = FALSE;
1038
1039         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1040         g_return_val_if_fail (capabilities != NULL, FALSE);
1041
1042         class = E_CLIENT_GET_CLASS (client);
1043         g_return_val_if_fail (class != NULL, FALSE);
1044         g_return_val_if_fail (class->retrieve_capabilities_sync != NULL, FALSE);
1045
1046         *capabilities = NULL;
1047         res = class->retrieve_capabilities_sync (client, capabilities, cancellable, error);
1048
1049         e_client_set_capabilities (client, res ? *capabilities : NULL);
1050
1051         if (error && *error)
1052                 e_client_unwrap_dbus_error (client, *error, error);
1053
1054         return res;
1055 }
1056
1057 /**
1058  * e_client_get_backend_property:
1059  * @client: an #EClient
1060  * @prop_name: property name, whose value to retrieve; cannot be %NULL
1061  * @cancellable: a #GCancellable; can be %NULL
1062  * @callback: callback to call when a result is ready
1063  * @user_data: user data for the @callback
1064  *
1065  * Queries @client's backend for a property of name @prop_name.
1066  * The call is finished by e_client_get_backend_property_finish()
1067  * from the @callback.
1068  *
1069  * Since: 3.2
1070  **/
1071 void
1072 e_client_get_backend_property (EClient *client,
1073                                const gchar *prop_name,
1074                                GCancellable *cancellable,
1075                                GAsyncReadyCallback callback,
1076                                gpointer user_data)
1077 {
1078         EClientClass *class;
1079
1080         g_return_if_fail (callback != NULL);
1081         g_return_if_fail (E_IS_CLIENT (client));
1082         g_return_if_fail (prop_name != NULL);
1083
1084         class = E_CLIENT_GET_CLASS (client);
1085         g_return_if_fail (class != NULL);
1086         g_return_if_fail (class->get_backend_property != NULL);
1087
1088         class->get_backend_property (client, prop_name, cancellable, callback, user_data);
1089 }
1090
1091 /**
1092  * e_client_get_backend_property_finish:
1093  * @client: an #EClient
1094  * @result: a #GAsyncResult
1095  * @prop_value: (out): Retrieved backend property value; cannot be %NULL
1096  * @error: (out): a #GError to set an error, if any
1097  *
1098  * Finishes previous call of e_client_get_backend_property().
1099  *
1100  * Returns: %TRUE if successful, %FALSE otherwise.
1101  *
1102  * Since: 3.2
1103  **/
1104 gboolean
1105 e_client_get_backend_property_finish (EClient *client,
1106                                       GAsyncResult *result,
1107                                       gchar **prop_value,
1108                                       GError **error)
1109 {
1110         EClientClass *class;
1111         gboolean res;
1112
1113         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1114         g_return_val_if_fail (prop_value != NULL, FALSE);
1115
1116         class = E_CLIENT_GET_CLASS (client);
1117         g_return_val_if_fail (class != NULL, FALSE);
1118         g_return_val_if_fail (class->get_backend_property_finish != NULL, FALSE);
1119
1120         res = class->get_backend_property_finish (client, result, prop_value, error);
1121
1122         if (error && *error)
1123                 e_client_unwrap_dbus_error (client, *error, error);
1124
1125         return res;
1126 }
1127
1128 /**
1129  * e_client_get_backend_property_sync:
1130  * @client: an #EClient
1131  * @prop_name: property name, whose value to retrieve; cannot be %NULL
1132  * @prop_value: (out): Retrieved backend property value; cannot be %NULL
1133  * @cancellable: a #GCancellable; can be %NULL
1134  * @error: (out): a #GError to set an error, if any
1135  *
1136  * Queries @client's backend for a property of name @prop_name.
1137  *
1138  * Returns: %TRUE if successful, %FALSE otherwise.
1139  *
1140  * Since: 3.2
1141  **/
1142 gboolean
1143 e_client_get_backend_property_sync (EClient *client,
1144                                     const gchar *prop_name,
1145                                     gchar **prop_value,
1146                                     GCancellable *cancellable,
1147                                     GError **error)
1148 {
1149         EClientClass *class;
1150         gboolean res;
1151
1152         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1153         g_return_val_if_fail (prop_name != NULL, FALSE);
1154         g_return_val_if_fail (prop_value != NULL, FALSE);
1155
1156         class = E_CLIENT_GET_CLASS (client);
1157         g_return_val_if_fail (class != NULL, FALSE);
1158         g_return_val_if_fail (class->get_backend_property_sync != NULL, FALSE);
1159
1160         res = class->get_backend_property_sync (client, prop_name, prop_value, cancellable, error);
1161
1162         if (error && *error)
1163                 e_client_unwrap_dbus_error (client, *error, error);
1164
1165         return res;
1166 }
1167
1168 /**
1169  * e_client_set_backend_property:
1170  * @client: an #EClient
1171  * @prop_name: property name, whose value to change; cannot be %NULL
1172  * @prop_value: property value, to set; cannot be %NULL
1173  * @cancellable: a #GCancellable; can be %NULL
1174  * @callback: callback to call when a result is ready
1175  * @user_data: user data for the @callback
1176  *
1177  * Sets @client's backend property of name @prop_name
1178  * to value @prop_value. The call is finished
1179  * by e_client_set_backend_property_finish() from the @callback.
1180  *
1181  * Since: 3.2
1182  **/
1183 void
1184 e_client_set_backend_property (EClient *client,
1185                                const gchar *prop_name,
1186                                const gchar *prop_value,
1187                                GCancellable *cancellable,
1188                                GAsyncReadyCallback callback,
1189                                gpointer user_data)
1190 {
1191         EClientClass *class;
1192
1193         g_return_if_fail (callback != NULL);
1194         g_return_if_fail (E_IS_CLIENT (client));
1195         g_return_if_fail (prop_name != NULL);
1196         g_return_if_fail (prop_value != NULL);
1197
1198         class = E_CLIENT_GET_CLASS (client);
1199         g_return_if_fail (class != NULL);
1200         g_return_if_fail (class->set_backend_property != NULL);
1201
1202         class->set_backend_property (client, prop_name, prop_value, cancellable, callback, user_data);
1203 }
1204
1205 /**
1206  * e_client_set_backend_property_finish:
1207  * @client: an #EClient
1208  * @result: a #GAsyncResult
1209  * @error: (out): a #GError to set an error, if any
1210  *
1211  * Finishes previous call of e_client_set_backend_property().
1212  *
1213  * Returns: %TRUE if successful, %FALSE otherwise.
1214  *
1215  * Since: 3.2
1216  **/
1217 gboolean
1218 e_client_set_backend_property_finish (EClient *client,
1219                                       GAsyncResult *result,
1220                                       GError **error)
1221 {
1222         EClientClass *class;
1223         gboolean res;
1224
1225         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1226
1227         class = E_CLIENT_GET_CLASS (client);
1228         g_return_val_if_fail (class != NULL, FALSE);
1229         g_return_val_if_fail (class->set_backend_property_finish != NULL, FALSE);
1230
1231         res = class->set_backend_property_finish (client, result, error);
1232
1233         if (error && *error)
1234                 e_client_unwrap_dbus_error (client, *error, error);
1235
1236         return res;
1237 }
1238
1239 /**
1240  * e_client_set_backend_property_sync:
1241  * @client: an #EClient
1242  * @prop_name: property name, whose value to change; cannot be %NULL
1243  * @prop_value: property value, to set; cannot be %NULL
1244  * @cancellable: a #GCancellable; can be %NULL
1245  * @error: (out): a #GError to set an error, if any
1246  *
1247  * Sets @client's backend property of name @prop_name
1248  * to value @prop_value.
1249  *
1250  * Returns: %TRUE if successful, %FALSE otherwise.
1251  *
1252  * Since: 3.2
1253  **/
1254 gboolean
1255 e_client_set_backend_property_sync (EClient *client,
1256                                     const gchar *prop_name,
1257                                     const gchar *prop_value,
1258                                     GCancellable *cancellable,
1259                                     GError **error)
1260 {
1261         EClientClass *class;
1262         gboolean res;
1263
1264         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1265         g_return_val_if_fail (prop_name != NULL, FALSE);
1266         g_return_val_if_fail (prop_value != NULL, FALSE);
1267
1268         class = E_CLIENT_GET_CLASS (client);
1269         g_return_val_if_fail (class != NULL, FALSE);
1270         g_return_val_if_fail (class->set_backend_property_sync != NULL, FALSE);
1271
1272         res = class->set_backend_property_sync (client, prop_name, prop_value, cancellable, error);
1273
1274         if (error && *error)
1275                 e_client_unwrap_dbus_error (client, *error, error);
1276
1277         return res;
1278 }
1279
1280 /**
1281  * e_client_open:
1282  * @client: an #EClient
1283  * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
1284  * @cancellable: a #GCancellable; can be %NULL
1285  * @callback: callback to call when a result is ready
1286  * @user_data: user data for the @callback
1287  *
1288  * Opens the @client, making it ready for queries and other operations.
1289  * The call is finished by e_client_open_finish() from the @callback.
1290  *
1291  * Since: 3.2
1292  **/
1293 void
1294 e_client_open (EClient *client,
1295                gboolean only_if_exists,
1296                GCancellable *cancellable,
1297                GAsyncReadyCallback callback,
1298                gpointer user_data)
1299 {
1300         EClientClass *class;
1301
1302         g_return_if_fail (callback != NULL);
1303         g_return_if_fail (E_IS_CLIENT (client));
1304
1305         class = E_CLIENT_GET_CLASS (client);
1306         g_return_if_fail (class != NULL);
1307         g_return_if_fail (class->open != NULL);
1308
1309         class->open (client, only_if_exists, cancellable, callback, user_data);
1310 }
1311
1312 /**
1313  * e_client_open_finish:
1314  * @client: an #EClient
1315  * @result: a #GAsyncResult
1316  * @error: (out): a #GError to set an error, if any
1317  *
1318  * Finishes previous call of e_client_open().
1319  *
1320  * Returns: %TRUE if successful, %FALSE otherwise.
1321  *
1322  * Since: 3.2
1323  **/
1324 gboolean
1325 e_client_open_finish (EClient *client,
1326                       GAsyncResult *result,
1327                       GError **error)
1328 {
1329         EClientClass *class;
1330         gboolean res;
1331
1332         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1333
1334         class = E_CLIENT_GET_CLASS (client);
1335         g_return_val_if_fail (class != NULL, FALSE);
1336         g_return_val_if_fail (class->open_finish != NULL, FALSE);
1337
1338         res = class->open_finish (client, result, error);
1339
1340         if (error && *error)
1341                 e_client_unwrap_dbus_error (client, *error, error);
1342
1343         return res;
1344 }
1345
1346 /**
1347  * e_client_open_sync:
1348  * @client: an #EClient
1349  * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
1350  * @cancellable: a #GCancellable; can be %NULL
1351  * @error: (out): a #GError to set an error, if any
1352  *
1353  * Opens the @client, making it ready for queries and other operations.
1354  *
1355  * Returns: %TRUE if successful, %FALSE otherwise.
1356  *
1357  * Since: 3.2
1358  **/
1359 gboolean
1360 e_client_open_sync (EClient *client,
1361                     gboolean only_if_exists,
1362                     GCancellable *cancellable,
1363                     GError **error)
1364 {
1365         EClientClass *class;
1366         gboolean res;
1367
1368         class = E_CLIENT_GET_CLASS (client);
1369         g_return_val_if_fail (class != NULL, FALSE);
1370         g_return_val_if_fail (class->open_sync != NULL, FALSE);
1371
1372         res = class->open_sync (client, only_if_exists, cancellable, error);
1373
1374         if (error && *error)
1375                 e_client_unwrap_dbus_error (client, *error, error);
1376
1377         return res;
1378 }
1379
1380 /**
1381  * e_client_remove:
1382  * @client: an #EClient
1383  * @cancellable: a #GCancellable; can be %NULL
1384  * @callback: callback to call when a result is ready
1385  * @user_data: user data for the @callback
1386  *
1387  * Removes the backing data for this #EClient. For example, with the file
1388  * backend this deletes the database file. You cannot get it back!
1389  * The call is finished by e_client_remove_finish() from the @callback.
1390  *
1391  * Since: 3.2
1392  *
1393  * Deprecated: 3.6: Use e_source_remove() instead.
1394  **/
1395 void
1396 e_client_remove (EClient *client,
1397                  GCancellable *cancellable,
1398                  GAsyncReadyCallback callback,
1399                  gpointer user_data)
1400 {
1401         EClientClass *class;
1402
1403         g_return_if_fail (E_IS_CLIENT (client));
1404         g_return_if_fail (callback != NULL);
1405
1406         class = E_CLIENT_GET_CLASS (client);
1407         g_return_if_fail (class != NULL);
1408         g_return_if_fail (class->remove != NULL);
1409
1410         class->remove (client, cancellable, callback, user_data);
1411 }
1412
1413 /**
1414  * e_client_remove_finish:
1415  * @client: an #EClient
1416  * @result: a #GAsyncResult
1417  * @error: (out): a #GError to set an error, if any
1418  *
1419  * Finishes previous call of e_client_remove().
1420  *
1421  * Returns: %TRUE if successful, %FALSE otherwise.
1422  *
1423  * Since: 3.2
1424  *
1425  * Deprecated: 3.6: Use e_source_remove_finish() instead.
1426  **/
1427 gboolean
1428 e_client_remove_finish (EClient *client,
1429                         GAsyncResult *result,
1430                         GError **error)
1431 {
1432         EClientClass *class;
1433         gboolean res;
1434
1435         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1436
1437         class = E_CLIENT_GET_CLASS (client);
1438         g_return_val_if_fail (class != NULL, FALSE);
1439         g_return_val_if_fail (class->remove_finish != NULL, FALSE);
1440
1441         res = class->remove_finish (client, result, error);
1442
1443         if (error && *error)
1444                 e_client_unwrap_dbus_error (client, *error, error);
1445
1446         return res;
1447 }
1448
1449 /**
1450  * e_client_remove_sync:
1451  * @client: an #EClient
1452  * @cancellable: a #GCancellable; can be %NULL
1453  * @error: (out): a #GError to set an error, if any
1454  *
1455  * Removes the backing data for this #EClient. For example, with the file
1456  * backend this deletes the database file. You cannot get it back!
1457  *
1458  * Returns: %TRUE if successful, %FALSE otherwise.
1459  *
1460  * Since: 3.2
1461  *
1462  * Deprecated: 3.6: Use e_source_remove_sync() instead.
1463  **/
1464 gboolean
1465 e_client_remove_sync (EClient *client,
1466                       GCancellable *cancellable,
1467                       GError **error)
1468 {
1469         EClientClass *class;
1470         gboolean res;
1471
1472         class = E_CLIENT_GET_CLASS (client);
1473         g_return_val_if_fail (class != NULL, FALSE);
1474         g_return_val_if_fail (class->remove_sync != NULL, FALSE);
1475
1476         res = class->remove_sync (client, cancellable, error);
1477
1478         if (error && *error)
1479                 e_client_unwrap_dbus_error (client, *error, error);
1480
1481         return res;
1482 }
1483
1484 /**
1485  * e_client_refresh:
1486  * @client: an #EClient
1487  * @cancellable: a #GCancellable; can be %NULL
1488  * @callback: callback to call when a result is ready
1489  * @user_data: user data for the @callback
1490  *
1491  * Initiates refresh on the @client. Finishing the method doesn't mean
1492  * that the refresh is done, backend only notifies whether it started
1493  * refreshing or not. Use e_client_check_refresh_supported() to check
1494  * whether the backend supports this method.
1495  * The call is finished by e_client_refresh_finish() from the @callback.
1496  *
1497  * Since: 3.2
1498  **/
1499 void
1500 e_client_refresh (EClient *client,
1501                   GCancellable *cancellable,
1502                   GAsyncReadyCallback callback,
1503                   gpointer user_data)
1504 {
1505         EClientClass *class;
1506
1507         g_return_if_fail (E_IS_CLIENT (client));
1508         g_return_if_fail (callback != NULL);
1509
1510         class = E_CLIENT_GET_CLASS (client);
1511         g_return_if_fail (class != NULL);
1512         g_return_if_fail (class->refresh != NULL);
1513
1514         class->refresh (client, cancellable, callback, user_data);
1515 }
1516
1517 /**
1518  * e_client_refresh_finish:
1519  * @client: an #EClient
1520  * @result: a #GAsyncResult
1521  * @error: (out): a #GError to set an error, if any
1522  *
1523  * Finishes previous call of e_client_refresh().
1524  *
1525  * Returns: %TRUE if successful, %FALSE otherwise.
1526  *
1527  * Since: 3.2
1528  **/
1529 gboolean
1530 e_client_refresh_finish (EClient *client,
1531                          GAsyncResult *result,
1532                          GError **error)
1533 {
1534         EClientClass *class;
1535         gboolean res;
1536
1537         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
1538
1539         class = E_CLIENT_GET_CLASS (client);
1540         g_return_val_if_fail (class != NULL, FALSE);
1541         g_return_val_if_fail (class->refresh_finish != NULL, FALSE);
1542
1543         res = class->refresh_finish (client, result, error);
1544
1545         if (error && *error)
1546                 e_client_unwrap_dbus_error (client, *error, error);
1547
1548         return res;
1549 }
1550
1551 /**
1552  * e_client_refresh_sync:
1553  * @client: an #EClient
1554  * @cancellable: a #GCancellable; can be %NULL
1555  * @error: (out): a #GError to set an error, if any
1556  *
1557  * Initiates refresh on the @client. Finishing the method doesn't mean
1558  * that the refresh is done, backend only notifies whether it started
1559  * refreshing or not. Use e_client_check_refresh_supported() to check
1560  * whether the backend supports this method.
1561  *
1562  * Returns: %TRUE if successful, %FALSE otherwise.
1563  *
1564  * Since: 3.2
1565  **/
1566 gboolean
1567 e_client_refresh_sync (EClient *client,
1568                        GCancellable *cancellable,
1569                        GError **error)
1570 {
1571         EClientClass *class;
1572         gboolean res;
1573
1574         class = E_CLIENT_GET_CLASS (client);
1575         g_return_val_if_fail (class != NULL, FALSE);
1576         g_return_val_if_fail (class->refresh_sync != NULL, FALSE);
1577
1578         res = class->refresh_sync (client, cancellable, error);
1579
1580         if (error && *error)
1581                 e_client_unwrap_dbus_error (client, *error, error);
1582
1583         return res;
1584 }
1585
1586 /**
1587  * e_client_util_slist_to_strv:
1588  * @strings: (element-type utf8): a #GSList of strings (const gchar *)
1589  *
1590  * Convert a list of strings into a %NULL-terminated array of strings.
1591  *
1592  * Returns: (transfer full): Newly allocated %NULL-terminated array of strings.
1593  * The returned pointer should be freed with g_strfreev().
1594  *
1595  * Note: Paired function for this is e_client_util_strv_to_slist().
1596  *
1597  * Since: 3.2
1598  *
1599  * Deprecated: 3.8: Use e_util_slist_to_strv() instead.
1600  **/
1601 gchar **
1602 e_client_util_slist_to_strv (const GSList *strings)
1603 {
1604         return e_util_slist_to_strv (strings);
1605 }
1606
1607 /**
1608  * e_client_util_strv_to_slist:
1609  * @strv: a %NULL-terminated array of strings (const gchar *)
1610  *
1611  * Convert a %NULL-terminated array of strings to a list of strings.
1612  *
1613  * Returns: (transfer full) (element-type utf8): Newly allocated #GSList of
1614  * newly allocated strings. The returned pointer should be freed with
1615  * e_client_util_free_string_slist().
1616  *
1617  * Note: Paired function for this is e_client_util_slist_to_strv().
1618  *
1619  * Since: 3.2
1620  *
1621  * Deprecated: 3.8: Use e_util_strv_to_slist() instead.
1622  **/
1623 GSList *
1624 e_client_util_strv_to_slist (const gchar * const *strv)
1625 {
1626         return e_util_strv_to_slist (strv);
1627 }
1628
1629 /**
1630  * e_client_util_copy_string_slist:
1631  * @copy_to: (element-type utf8) (allow-none): Where to copy; may be %NULL
1632  * @strings: (element-type utf8): #GSList of strings to be copied
1633  *
1634  * Copies the #GSList of strings to the end of @copy_to.
1635  *
1636  * Returns: (transfer full) (element-type utf8): New head of @copy_to.
1637  * The returned pointer can be freed with e_client_util_free_string_slist().
1638  *
1639  * Since: 3.2
1640  *
1641  * Deprecated: 3.8: Use e_util_copy_string_slist() instead.
1642  **/
1643 GSList *
1644 e_client_util_copy_string_slist (GSList *copy_to,
1645                                  const GSList *strings)
1646 {
1647         return e_util_copy_string_slist (copy_to, strings);
1648 }
1649
1650 /**
1651  * e_client_util_copy_object_slist:
1652  * @copy_to: (element-type GObject) (allow-none): Where to copy; may be %NULL
1653  * @objects: (element-type GObject): #GSList of #GObject<!-- -->s to be copied
1654  *
1655  * Copies a #GSList of #GObject<!-- -->s to the end of @copy_to.
1656  *
1657  * Returns: (transfer full) (element-type GObject): New head of @copy_to.
1658  * The returned pointer can be freed with e_client_util_free_object_slist().
1659  *
1660  * Since: 3.2
1661  *
1662  * Deprecated: 3.8: Use e_util_copy_object_slist() instead.
1663  **/
1664 GSList *
1665 e_client_util_copy_object_slist (GSList *copy_to,
1666                                  const GSList *objects)
1667 {
1668         return e_util_copy_object_slist (copy_to, objects);
1669 }
1670
1671 /**
1672  * e_client_util_free_string_slist:
1673  * @strings: (element-type utf8): a #GSList of strings (gchar *)
1674  *
1675  * Frees memory previously allocated by e_client_util_strv_to_slist().
1676  *
1677  * Since: 3.2
1678  *
1679  * Deprecated: 3.8: Use g_slist_free_full() instead.
1680  **/
1681 void
1682 e_client_util_free_string_slist (GSList *strings)
1683 {
1684         e_util_free_string_slist (strings);
1685 }
1686
1687 /**
1688  * e_client_util_free_object_slist:
1689  * @objects: (element-type GObject): a #GSList of #GObject<!-- -->s
1690  *
1691  * Calls g_object_unref() on each member of @objects and then frees @objects
1692  * itself.
1693  *
1694  * Since: 3.2
1695  *
1696  * Deprecated: 3.8: Use g_slist_free_full() instead.
1697  **/
1698 void
1699 e_client_util_free_object_slist (GSList *objects)
1700 {
1701         e_util_free_object_slist (objects);
1702 }
1703
1704 /**
1705  * e_client_util_parse_comma_strings:
1706  * @strings: string of comma-separated values
1707  *
1708  * Parses comma-separated list of values into #GSList.
1709  *
1710  * Returns: (transfer full) (element-type utf8): Newly allocated #GSList of
1711  * newly allocated strings corresponding to values parsed from @strings.
1712  * Free the returned pointer with e_client_util_free_string_slist().
1713  *
1714  * Since: 3.2
1715  **/
1716 GSList *
1717 e_client_util_parse_comma_strings (const gchar *strings)
1718 {
1719         GSList *strs_slist = NULL;
1720         gchar **strs_strv = NULL;
1721         gint ii;
1722
1723         if (!strings || !*strings)
1724                 return NULL;
1725
1726         strs_strv = g_strsplit (strings, ",", -1);
1727         g_return_val_if_fail (strs_strv != NULL, NULL);
1728
1729         for (ii = 0; strs_strv && strs_strv[ii]; ii++) {
1730                 gchar *str = g_strstrip (strs_strv[ii]);
1731
1732                 if (str && *str)
1733                         strs_slist = g_slist_prepend (strs_slist, g_strdup (str));
1734         }
1735
1736         g_strfreev (strs_strv);
1737
1738         return g_slist_reverse (strs_slist);
1739 }
1740
1741 void
1742 e_client_finish_async_without_dbus (EClient *client,
1743                                     GCancellable *cancellable,
1744                                     GAsyncReadyCallback callback,
1745                                     gpointer user_data,
1746                                     gpointer source_tag,
1747                                     gpointer op_res,
1748                                     GDestroyNotify destroy_op_res)
1749 {
1750         GCancellable *use_cancellable;
1751         GSimpleAsyncResult *simple;
1752         guint32 opid;
1753
1754         g_return_if_fail (E_IS_CLIENT (client));
1755         g_return_if_fail (callback != NULL);
1756         g_return_if_fail (source_tag != NULL);
1757
1758         use_cancellable = cancellable;
1759         if (!use_cancellable)
1760                 use_cancellable = g_cancellable_new ();
1761
1762         opid = e_client_register_op (client, use_cancellable);
1763         g_return_if_fail (opid > 0);
1764
1765         simple = g_simple_async_result_new (
1766                 G_OBJECT (client), callback, user_data, source_tag);
1767
1768         g_simple_async_result_set_check_cancellable (simple, cancellable);
1769
1770         g_simple_async_result_set_op_res_gpointer (
1771                 simple, op_res, destroy_op_res);
1772
1773         g_simple_async_result_complete_in_idle (simple);
1774
1775         g_object_unref (simple);
1776
1777         if (use_cancellable != cancellable)
1778                 g_object_unref (use_cancellable);
1779 }
1780
1781 GDBusProxy *
1782 e_client_get_dbus_proxy (EClient *client)
1783 {
1784         EClientClass *class;
1785
1786         g_return_val_if_fail (E_IS_CLIENT (client), NULL);
1787
1788         class = E_CLIENT_GET_CLASS (client);
1789         g_return_val_if_fail (class != NULL, NULL);
1790         g_return_val_if_fail (class->get_dbus_proxy != NULL, NULL);
1791
1792         return class->get_dbus_proxy (client);
1793 }
1794
1795 /**
1796  * e_client_unwrap_dbus_error:
1797  * @client: an #EClient
1798  * @dbus_error: a #GError returned bu D-Bus
1799  * @out_error: a #GError variable where to store the result
1800  *
1801  * Unwraps D-Bus error to local error. @dbus_error is automatically freed.
1802  * @dbus_erorr and @out_error can point to the same variable.
1803  *
1804  * Since: 3.2
1805  **/
1806 void
1807 e_client_unwrap_dbus_error (EClient *client,
1808                             GError *dbus_error,
1809                             GError **out_error)
1810 {
1811         EClientClass *class;
1812
1813         g_return_if_fail (E_IS_CLIENT (client));
1814
1815         class = E_CLIENT_GET_CLASS (client);
1816         g_return_if_fail (class != NULL);
1817         g_return_if_fail (class->unwrap_dbus_error != NULL);
1818
1819         if (!dbus_error || !out_error) {
1820                 if (dbus_error)
1821                         g_error_free (dbus_error);
1822         } else {
1823                 class->unwrap_dbus_error (client, dbus_error, out_error);
1824         }
1825 }
1826
1827 /**
1828  * e_client_util_unwrap_dbus_error:
1829  * @dbus_error: DBus #GError to unwrap
1830  * @client_error: (out): Resulting #GError; can be %NULL
1831  * @known_errors: List of known errors against which try to match
1832  * @known_errors_count: How many items are stored in @known_errors
1833  * @known_errors_domain: Error domain for @known_errors
1834  * @fail_when_none_matched: Whether to fail when none of @known_errors matches
1835  *
1836  * The function takes a @dbus_error and tries to find a match in @known_errors
1837  * for it, if it is a G_IO_ERROR, G_IO_ERROR_DBUS_ERROR. If it is anything else
1838  * then the @dbus_error is moved to @client_error.
1839  *
1840  * The @fail_when_none_matched influences behaviour. If it's %TRUE, and none of
1841  * @known_errors matches, or this is not a G_IO_ERROR_DBUS_ERROR, then %FALSE
1842  * is returned and the @client_error is left without change. Otherwise, the
1843  * @fail_when_none_matched is %FALSE, the error is always processed and will
1844  * result in E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR if none of @known_error
1845  * matches.
1846  *
1847  * Returns: Whether was @dbus_error processed into @client_error.
1848  *
1849  * Note: The @dbus_error is automatically freed if returned %TRUE.
1850  *
1851  * Since: 3.2
1852  **/
1853 gboolean
1854 e_client_util_unwrap_dbus_error (GError *dbus_error,
1855                                  GError **client_error,
1856                                  const EClientErrorsList *known_errors,
1857                                  guint known_errors_count,
1858                                  GQuark known_errors_domain,
1859                                  gboolean fail_when_none_matched)
1860 {
1861         if (!client_error) {
1862                 if (dbus_error)
1863                         g_error_free (dbus_error);
1864                 return TRUE;
1865         }
1866
1867         if (!dbus_error) {
1868                 *client_error = NULL;
1869                 return TRUE;
1870         }
1871
1872         if (dbus_error->domain == known_errors_domain) {
1873                 *client_error = dbus_error;
1874                 return TRUE;
1875         }
1876
1877         if (known_errors) {
1878                 if (g_error_matches (dbus_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) {
1879                         gchar *name;
1880                         gint ii;
1881
1882                         name = g_dbus_error_get_remote_error (dbus_error);
1883
1884                         for (ii = 0; ii < known_errors_count; ii++) {
1885                                 if (g_ascii_strcasecmp (known_errors[ii].name, name) == 0) {
1886                                         g_free (name);
1887
1888                                         g_dbus_error_strip_remote_error (dbus_error);
1889                                         *client_error = g_error_new_literal (known_errors_domain, known_errors[ii].err_code, dbus_error->message);
1890                                         g_error_free (dbus_error);
1891                                         return TRUE;
1892                                 }
1893                         }
1894
1895                         g_free (name);
1896                 }
1897         }
1898
1899         if (fail_when_none_matched)
1900                 return FALSE;
1901
1902         if (g_error_matches (dbus_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) {
1903                 g_dbus_error_strip_remote_error (dbus_error);
1904                 *client_error = g_error_new_literal (E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, dbus_error->message);
1905                 g_error_free (dbus_error);
1906         } else {
1907                 g_dbus_error_strip_remote_error (dbus_error);
1908                 *client_error = dbus_error;
1909         }
1910
1911         return TRUE;
1912 }
1913
1914 typedef struct _EClientAsyncOpData
1915 {
1916         EClient *client;
1917         guint32 opid;
1918
1919         gpointer source_tag;
1920         gchar *res_op_data; /* optional string to set on a GAsyncResult object as "res-op-data" user data */
1921         GAsyncReadyCallback callback;
1922         gpointer user_data;
1923
1924         gboolean result; /* result of the finish function call */
1925
1926         /* only one can be non-NULL, and the type is telling which 'out' value is valid */
1927         EClientProxyFinishVoidFunc finish_void;
1928         EClientProxyFinishBooleanFunc finish_boolean;
1929         EClientProxyFinishStringFunc finish_string;
1930         EClientProxyFinishStrvFunc finish_strv;
1931         EClientProxyFinishUintFunc finish_uint;
1932
1933         union {
1934                 gboolean val_boolean;
1935                 gchar *val_string;
1936                 gchar **val_strv;
1937                 guint val_uint;
1938         } out;
1939 } EClientAsyncOpData;
1940
1941 static void
1942 async_data_free (EClientAsyncOpData *async_data)
1943 {
1944         g_return_if_fail (async_data != NULL);
1945         g_return_if_fail (async_data->client != NULL);
1946
1947         e_client_unregister_op (async_data->client, async_data->opid);
1948
1949         if (async_data->finish_string)
1950                 g_free (async_data->out.val_string);
1951         else if (async_data->finish_strv)
1952                 g_strfreev (async_data->out.val_strv);
1953
1954         g_object_unref (async_data->client);
1955         g_free (async_data->res_op_data);
1956         g_free (async_data);
1957 }
1958
1959 static gboolean
1960 complete_async_op_in_idle_cb (gpointer user_data)
1961 {
1962         GSimpleAsyncResult *simple = user_data;
1963         gint run_main_depth;
1964
1965         g_return_val_if_fail (simple != NULL, FALSE);
1966
1967         run_main_depth = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (simple), "run-main-depth"));
1968         if (run_main_depth < 1)
1969                 run_main_depth = 1;
1970
1971         /* do not receive in higher level than was initially run */
1972         if (g_main_depth () > run_main_depth) {
1973                 return TRUE;
1974         }
1975
1976         g_simple_async_result_complete (simple);
1977         g_object_unref (simple);
1978
1979         return FALSE;
1980 }
1981
1982 static void
1983 finish_async_op (EClientAsyncOpData *async_data,
1984                  const GError *error,
1985                  gboolean in_idle)
1986 {
1987         GSimpleAsyncResult *simple;
1988
1989         g_return_if_fail (async_data != NULL);
1990         g_return_if_fail (async_data->source_tag != NULL);
1991         g_return_if_fail (async_data->client != NULL);
1992
1993         simple = g_simple_async_result_new (G_OBJECT (async_data->client), async_data->callback, async_data->user_data, async_data->source_tag);
1994         g_simple_async_result_set_op_res_gpointer (simple, async_data, (GDestroyNotify) async_data_free);
1995
1996         if (async_data->res_op_data)
1997                 g_object_set_data_full (G_OBJECT (simple), "res-op-data", g_strdup (async_data->res_op_data), g_free);
1998
1999         if (error != NULL)
2000                 g_simple_async_result_set_from_error (simple, error);
2001
2002         if (in_idle) {
2003                 g_object_set_data (G_OBJECT (simple), "run-main-depth", GINT_TO_POINTER (g_main_depth ()));
2004                 g_idle_add (complete_async_op_in_idle_cb, simple);
2005         } else {
2006                 g_simple_async_result_complete (simple);
2007                 g_object_unref (simple);
2008         }
2009 }
2010
2011 static void
2012 async_result_ready_cb (GObject *source_object,
2013                        GAsyncResult *result,
2014                        gpointer user_data)
2015 {
2016         GError *error = NULL;
2017         EClientAsyncOpData *async_data;
2018         EClient *client;
2019
2020         g_return_if_fail (result != NULL);
2021         g_return_if_fail (source_object != NULL);
2022
2023         async_data = user_data;
2024         g_return_if_fail (async_data != NULL);
2025         g_return_if_fail (async_data->client != NULL);
2026
2027         client = async_data->client;
2028         g_return_if_fail (e_client_get_dbus_proxy (client) == G_DBUS_PROXY (source_object));
2029
2030         if (async_data->finish_void)
2031                 async_data->result = async_data->finish_void (G_DBUS_PROXY (source_object), result, &error);
2032         else if (async_data->finish_boolean)
2033                 async_data->result = async_data->finish_boolean (G_DBUS_PROXY (source_object), result, &async_data->out.val_boolean, &error);
2034         else if (async_data->finish_string)
2035                 async_data->result = async_data->finish_string (G_DBUS_PROXY (source_object), result, &async_data->out.val_string, &error);
2036         else if (async_data->finish_strv)
2037                 async_data->result = async_data->finish_strv (G_DBUS_PROXY (source_object), result, &async_data->out.val_strv, &error);
2038         else if (async_data->finish_uint)
2039                 async_data->result = async_data->finish_uint (G_DBUS_PROXY (source_object), result, &async_data->out.val_uint, &error);
2040         else
2041                 g_warning ("%s: Do not know how to finish async operation", G_STRFUNC);
2042
2043         finish_async_op (async_data, error, FALSE);
2044
2045         if (error != NULL)
2046                 g_error_free (error);
2047 }
2048
2049 static EClientAsyncOpData *
2050 prepare_async_data (EClient *client,
2051                     GCancellable *cancellable,
2052                     GAsyncReadyCallback callback,
2053                     gpointer user_data,
2054                     gpointer source_tag,
2055                     gboolean error_report_only,
2056                     EClientProxyFinishVoidFunc finish_void,
2057                     EClientProxyFinishBooleanFunc finish_boolean,
2058                     EClientProxyFinishStringFunc finish_string,
2059                     EClientProxyFinishStrvFunc finish_strv,
2060                     EClientProxyFinishUintFunc finish_uint,
2061                     GDBusProxy **proxy,
2062                     GCancellable **out_cancellable)
2063 {
2064         EClientAsyncOpData *async_data;
2065         GCancellable *use_cancellable;
2066         guint32 opid;
2067
2068         g_return_val_if_fail (client != NULL, NULL);
2069         g_return_val_if_fail (callback != NULL, NULL);
2070         g_return_val_if_fail (source_tag != NULL, NULL);
2071
2072         if (!error_report_only) {
2073                 g_return_val_if_fail (proxy != NULL, NULL);
2074                 g_return_val_if_fail (out_cancellable != NULL, NULL);
2075                 g_return_val_if_fail (finish_void || finish_boolean || finish_string || finish_strv || finish_uint, NULL);
2076
2077                 if (finish_void) {
2078                         g_return_val_if_fail (finish_boolean == NULL, NULL);
2079                         g_return_val_if_fail (finish_string == NULL, NULL);
2080                         g_return_val_if_fail (finish_strv == NULL, NULL);
2081                         g_return_val_if_fail (finish_uint == NULL, NULL);
2082                 }
2083
2084                 if (finish_boolean) {
2085                         g_return_val_if_fail (finish_void == NULL, NULL);
2086                         g_return_val_if_fail (finish_string == NULL, NULL);
2087                         g_return_val_if_fail (finish_strv == NULL, NULL);
2088                         g_return_val_if_fail (finish_uint == NULL, NULL);
2089                 }
2090
2091                 if (finish_string) {
2092                         g_return_val_if_fail (finish_void == NULL, NULL);
2093                         g_return_val_if_fail (finish_boolean == NULL, NULL);
2094                         g_return_val_if_fail (finish_strv == NULL, NULL);
2095                         g_return_val_if_fail (finish_uint == NULL, NULL);
2096                 }
2097
2098                 if (finish_strv) {
2099                         g_return_val_if_fail (finish_void == NULL, NULL);
2100                         g_return_val_if_fail (finish_boolean == NULL, NULL);
2101                         g_return_val_if_fail (finish_string == NULL, NULL);
2102                         g_return_val_if_fail (finish_uint == NULL, NULL);
2103                 }
2104
2105                 if (finish_uint) {
2106                         g_return_val_if_fail (finish_void == NULL, NULL);
2107                         g_return_val_if_fail (finish_boolean == NULL, NULL);
2108                         g_return_val_if_fail (finish_string == NULL, NULL);
2109                         g_return_val_if_fail (finish_strv == NULL, NULL);
2110                 }
2111
2112                 *proxy = e_client_get_dbus_proxy (client);
2113                 if (!*proxy)
2114                         return NULL;
2115         }
2116
2117         use_cancellable = cancellable;
2118         if (!use_cancellable)
2119                 use_cancellable = g_cancellable_new ();
2120
2121         opid = e_client_register_op (client, use_cancellable);
2122         async_data = g_new0 (EClientAsyncOpData, 1);
2123         async_data->client = g_object_ref (client);
2124         async_data->opid = opid;
2125         async_data->source_tag = source_tag;
2126         async_data->callback = callback;
2127         async_data->user_data = user_data;
2128         async_data->finish_void = finish_void;
2129         async_data->finish_boolean = finish_boolean;
2130         async_data->finish_string = finish_string;
2131         async_data->finish_strv = finish_strv;
2132         async_data->finish_uint = finish_uint;
2133
2134         /* EClient from e_client_register_op() took ownership of the use_cancellable */
2135         if (use_cancellable != cancellable)
2136                 g_object_unref (use_cancellable);
2137
2138         if (out_cancellable)
2139                 *out_cancellable = use_cancellable;
2140
2141         return async_data;
2142 }
2143
2144 void
2145 e_client_proxy_return_async_error (EClient *client,
2146                                    const GError *error,
2147                                    GAsyncReadyCallback callback,
2148                                    gpointer user_data,
2149                                    gpointer source_tag)
2150 {
2151         EClientAsyncOpData *async_data;
2152
2153         g_return_if_fail (E_IS_CLIENT (client));
2154         g_return_if_fail (error != NULL);
2155         g_return_if_fail (callback != NULL);
2156
2157         async_data = prepare_async_data (client, NULL, callback, user_data, source_tag, TRUE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2158         g_return_if_fail (async_data != NULL);
2159
2160         finish_async_op (async_data, error, TRUE);
2161 }
2162
2163 void
2164 e_client_proxy_call_void (EClient *client,
2165                           GCancellable *cancellable,
2166                           GAsyncReadyCallback callback,
2167                           gpointer user_data,
2168                           gpointer source_tag,
2169                           void (*func) (GDBusProxy *proxy,
2170                                         GCancellable *cancellable,
2171                                         GAsyncReadyCallback callback,
2172                                         gpointer user_data),
2173                           EClientProxyFinishVoidFunc finish_void,
2174                           EClientProxyFinishBooleanFunc finish_boolean,
2175                           EClientProxyFinishStringFunc finish_string,
2176                           EClientProxyFinishStrvFunc finish_strv,
2177                           EClientProxyFinishUintFunc finish_uint)
2178 {
2179         EClientAsyncOpData *async_data;
2180         GDBusProxy *proxy = NULL;
2181
2182         g_return_if_fail (E_IS_CLIENT (client));
2183         g_return_if_fail (callback != NULL);
2184         g_return_if_fail (source_tag != NULL);
2185         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2186
2187         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2188         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2189
2190         func (proxy, cancellable, async_result_ready_cb, async_data);
2191 }
2192
2193 void
2194 e_client_proxy_call_boolean (EClient *client,
2195                              gboolean in_boolean,
2196                              GCancellable *cancellable,
2197                              GAsyncReadyCallback callback,
2198                              gpointer user_data,
2199                              gpointer source_tag,
2200                              void (*func) (GDBusProxy *proxy,
2201                                            gboolean in_boolean,
2202                                            GCancellable *cancellable,
2203                                            GAsyncReadyCallback callback,
2204                                            gpointer user_data),
2205                              EClientProxyFinishVoidFunc finish_void,
2206                              EClientProxyFinishBooleanFunc finish_boolean,
2207                              EClientProxyFinishStringFunc finish_string,
2208                              EClientProxyFinishStrvFunc finish_strv,
2209                              EClientProxyFinishUintFunc finish_uint)
2210 {
2211         EClientAsyncOpData *async_data;
2212         GDBusProxy *proxy = NULL;
2213
2214         g_return_if_fail (E_IS_CLIENT (client));
2215         g_return_if_fail (callback != NULL);
2216         g_return_if_fail (source_tag != NULL);
2217         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2218
2219         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2220         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2221
2222         func (proxy, in_boolean, cancellable, async_result_ready_cb, async_data);
2223 }
2224
2225 void
2226 e_client_proxy_call_string (EClient *client,
2227                             const gchar *in_string,
2228                             GCancellable *cancellable,
2229                             GAsyncReadyCallback callback,
2230                             gpointer user_data,
2231                             gpointer source_tag,
2232                             void (*func) (GDBusProxy *proxy,
2233                                           const gchar *in_string,
2234                                           GCancellable *cancellable,
2235                                           GAsyncReadyCallback callback,
2236                                           gpointer user_data),
2237                             EClientProxyFinishVoidFunc finish_void,
2238                             EClientProxyFinishBooleanFunc finish_boolean,
2239                             EClientProxyFinishStringFunc finish_string,
2240                             EClientProxyFinishStrvFunc finish_strv,
2241                             EClientProxyFinishUintFunc finish_uint)
2242 {
2243         EClientAsyncOpData *async_data;
2244         GDBusProxy *proxy = NULL;
2245
2246         g_return_if_fail (E_IS_CLIENT (client));
2247         g_return_if_fail (callback != NULL);
2248         g_return_if_fail (source_tag != NULL);
2249         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2250         e_client_return_async_if_fail (in_string != NULL, client, callback, user_data, source_tag);
2251
2252         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2253         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2254
2255         func (proxy, in_string, cancellable, async_result_ready_cb, async_data);
2256 }
2257
2258 void
2259 e_client_proxy_call_string_with_res_op_data (EClient *client,
2260                                              const gchar *in_string,
2261                                              GCancellable *cancellable,
2262                                              GAsyncReadyCallback callback,
2263                                              gpointer user_data,
2264                                              gpointer source_tag,
2265                                              const gchar *res_op_data,
2266                                              void (*func) (GDBusProxy *proxy,
2267                                                            const gchar *in_string,
2268                                                            GCancellable *cancellable,
2269                                                            GAsyncReadyCallback callback,
2270                                                            gpointer user_data),
2271                                              EClientProxyFinishVoidFunc finish_void,
2272                                              EClientProxyFinishBooleanFunc finish_boolean,
2273                                              EClientProxyFinishStringFunc finish_string,
2274                                              EClientProxyFinishStrvFunc finish_strv,
2275                                              EClientProxyFinishUintFunc finish_uint)
2276 {
2277         EClientAsyncOpData *async_data;
2278         GDBusProxy *proxy = NULL;
2279
2280         g_return_if_fail (E_IS_CLIENT (client));
2281         g_return_if_fail (callback != NULL);
2282         g_return_if_fail (source_tag != NULL);
2283         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2284         e_client_return_async_if_fail (in_string != NULL, client, callback, user_data, source_tag);
2285
2286         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2287         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2288
2289         async_data->res_op_data = g_strdup (res_op_data);
2290
2291         func (proxy, in_string, cancellable, async_result_ready_cb, async_data);
2292 }
2293
2294 void
2295 e_client_proxy_call_strv (EClient *client,
2296                           const gchar * const *in_strv,
2297                           GCancellable *cancellable,
2298                           GAsyncReadyCallback callback,
2299                           gpointer user_data,
2300                           gpointer source_tag,
2301                           void (*func) (GDBusProxy *proxy,
2302                                         const gchar * const * in_strv,
2303                                         GCancellable *cancellable,
2304                                         GAsyncReadyCallback callback,
2305                                         gpointer user_data),
2306                           EClientProxyFinishVoidFunc finish_void,
2307                           EClientProxyFinishBooleanFunc finish_boolean,
2308                           EClientProxyFinishStringFunc finish_string,
2309                           EClientProxyFinishStrvFunc finish_strv,
2310                           EClientProxyFinishUintFunc finish_uint)
2311 {
2312         EClientAsyncOpData *async_data;
2313         GDBusProxy *proxy = NULL;
2314
2315         g_return_if_fail (E_IS_CLIENT (client));
2316         g_return_if_fail (callback != NULL);
2317         g_return_if_fail (source_tag != NULL);
2318         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2319         e_client_return_async_if_fail (in_strv != NULL, client, callback, user_data, source_tag);
2320
2321         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2322         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2323
2324         func (proxy, in_strv, cancellable, async_result_ready_cb, async_data);
2325 }
2326
2327 void
2328 e_client_proxy_call_uint (EClient *client,
2329                           guint in_uint,
2330                           GCancellable *cancellable,
2331                           GAsyncReadyCallback callback,
2332                           gpointer user_data,
2333                           gpointer source_tag,
2334                           void (*func) (GDBusProxy *proxy,
2335                                         guint in_uint,
2336                                         GCancellable *cancellable,
2337                                         GAsyncReadyCallback callback,
2338                                         gpointer user_data),
2339                           EClientProxyFinishVoidFunc finish_void,
2340                           EClientProxyFinishBooleanFunc finish_boolean,
2341                           EClientProxyFinishStringFunc finish_string,
2342                           EClientProxyFinishStrvFunc finish_strv,
2343                           EClientProxyFinishUintFunc finish_uint)
2344 {
2345         EClientAsyncOpData *async_data;
2346         GDBusProxy *proxy = NULL;
2347
2348         g_return_if_fail (E_IS_CLIENT (client));
2349         g_return_if_fail (callback != NULL);
2350         g_return_if_fail (source_tag != NULL);
2351         e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
2352
2353         async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
2354         e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
2355
2356         func (proxy, in_uint, cancellable, async_result_ready_cb, async_data);
2357 }
2358
2359 gboolean
2360 e_client_proxy_call_finish_void (EClient *client,
2361                                  GAsyncResult *result,
2362                                  GError **error,
2363                                  gpointer source_tag)
2364 {
2365         GSimpleAsyncResult *simple;
2366         GError *local_error = NULL;
2367         EClientAsyncOpData *async_data;
2368
2369         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2370         g_return_val_if_fail (result != NULL, FALSE);
2371         g_return_val_if_fail (source_tag != NULL, FALSE);
2372         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2373
2374         simple = G_SIMPLE_ASYNC_RESULT (result);
2375
2376         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2377                 e_client_unwrap_dbus_error (client, local_error, error);
2378                 return FALSE;
2379         }
2380
2381         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2382         g_return_val_if_fail (async_data != NULL, FALSE);
2383
2384         return async_data->result;
2385 }
2386
2387 gboolean
2388 e_client_proxy_call_finish_boolean (EClient *client,
2389                                     GAsyncResult *result,
2390                                     gboolean *out_boolean,
2391                                     GError **error,
2392                                     gpointer source_tag)
2393 {
2394         GSimpleAsyncResult *simple;
2395         GError *local_error = NULL;
2396         EClientAsyncOpData *async_data;
2397
2398         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2399         g_return_val_if_fail (result != NULL, FALSE);
2400         g_return_val_if_fail (source_tag != NULL, FALSE);
2401         g_return_val_if_fail (out_boolean != NULL, FALSE);
2402         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2403
2404         simple = G_SIMPLE_ASYNC_RESULT (result);
2405
2406         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2407                 e_client_unwrap_dbus_error (client, local_error, error);
2408                 return FALSE;
2409         }
2410
2411         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2412         g_return_val_if_fail (async_data != NULL, FALSE);
2413
2414         *out_boolean = async_data->out.val_boolean;
2415
2416         return async_data->result;
2417 }
2418
2419 gboolean
2420 e_client_proxy_call_finish_string (EClient *client,
2421                                    GAsyncResult *result,
2422                                    gchar **out_string,
2423                                    GError **error,
2424                                    gpointer source_tag)
2425 {
2426         GSimpleAsyncResult *simple;
2427         GError *local_error = NULL;
2428         EClientAsyncOpData *async_data;
2429
2430         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2431         g_return_val_if_fail (result != NULL, FALSE);
2432         g_return_val_if_fail (source_tag != NULL, FALSE);
2433         g_return_val_if_fail (out_string != NULL, FALSE);
2434         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2435
2436         simple = G_SIMPLE_ASYNC_RESULT (result);
2437
2438         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2439                 e_client_unwrap_dbus_error (client, local_error, error);
2440                 return FALSE;
2441         }
2442
2443         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2444         g_return_val_if_fail (async_data != NULL, FALSE);
2445
2446         *out_string = async_data->out.val_string;
2447         async_data->out.val_string = NULL;
2448
2449         return async_data->result;
2450 }
2451
2452 gboolean
2453 e_client_proxy_call_finish_strv (EClient *client,
2454                                  GAsyncResult *result,
2455                                  gchar ***out_strv,
2456                                  GError **error,
2457                                  gpointer source_tag)
2458 {
2459         GSimpleAsyncResult *simple;
2460         GError *local_error = NULL;
2461         EClientAsyncOpData *async_data;
2462
2463         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2464         g_return_val_if_fail (result != NULL, FALSE);
2465         g_return_val_if_fail (source_tag != NULL, FALSE);
2466         g_return_val_if_fail (out_strv != NULL, FALSE);
2467         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2468
2469         simple = G_SIMPLE_ASYNC_RESULT (result);
2470
2471         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2472                 e_client_unwrap_dbus_error (client, local_error, error);
2473                 return FALSE;
2474         }
2475
2476         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2477         g_return_val_if_fail (async_data != NULL, FALSE);
2478
2479         *out_strv = async_data->out.val_strv;
2480         async_data->out.val_strv = NULL;
2481
2482         return async_data->result;
2483 }
2484
2485 gboolean
2486 e_client_proxy_call_finish_uint (EClient *client,
2487                                  GAsyncResult *result,
2488                                  guint *out_uint,
2489                                  GError **error,
2490                                  gpointer source_tag)
2491 {
2492         GSimpleAsyncResult *simple;
2493         GError *local_error = NULL;
2494         EClientAsyncOpData *async_data;
2495
2496         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
2497         g_return_val_if_fail (result != NULL, FALSE);
2498         g_return_val_if_fail (source_tag != NULL, FALSE);
2499         g_return_val_if_fail (out_uint != NULL, FALSE);
2500         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
2501
2502         simple = G_SIMPLE_ASYNC_RESULT (result);
2503
2504         if (g_simple_async_result_propagate_error (simple, &local_error)) {
2505                 e_client_unwrap_dbus_error (client, local_error, error);
2506                 return FALSE;
2507         }
2508
2509         async_data = g_simple_async_result_get_op_res_gpointer (simple);
2510         g_return_val_if_fail (async_data != NULL, FALSE);
2511
2512         *out_uint = async_data->out.val_uint;
2513
2514         return async_data->result;
2515 }
2516
2517 #define SYNC_CALL_TEMPLATE(_out_test,_the_call)                 \
2518         GDBusProxy *proxy;                                      \
2519         GCancellable *use_cancellable;                          \
2520         guint32 opid;                                           \
2521         gboolean result;                                        \
2522         GError *local_error = NULL;                             \
2523                                                                 \
2524         g_return_val_if_fail (E_IS_CLIENT (client), FALSE);     \
2525         g_return_val_if_fail (func != NULL, FALSE);             \
2526         g_return_val_if_fail (_out_test != NULL, FALSE);        \
2527                                                                 \
2528         proxy = e_client_get_dbus_proxy (client);               \
2529         g_return_val_if_fail (proxy != NULL, FALSE);            \
2530                                                                 \
2531         use_cancellable = cancellable;                          \
2532         if (!use_cancellable)                                   \
2533                 use_cancellable = g_cancellable_new ();         \
2534                                                                 \
2535         g_object_ref (client);                                  \
2536         opid = e_client_register_op (client, use_cancellable);  \
2537                                                                 \
2538         result = func _the_call;                                \
2539                                                                 \
2540         e_client_unregister_op (client, opid);                  \
2541         g_object_unref (client);                                \
2542                                                                 \
2543         if (use_cancellable != cancellable)                     \
2544                 g_object_unref (use_cancellable);               \
2545                                                                 \
2546         e_client_unwrap_dbus_error (client, local_error, error);\
2547                                                                 \
2548         return result;
2549
2550 gboolean
2551 e_client_proxy_call_sync_void__void (EClient *client,
2552                                      GCancellable *cancellable,
2553                                      GError **error,
2554                                      gboolean (*func) (GDBusProxy *proxy,
2555                                                        GCancellable *cancellable,
2556                                                        GError **error))
2557 {
2558         SYNC_CALL_TEMPLATE (client, (proxy, use_cancellable, &local_error))
2559 }
2560
2561 gboolean
2562 e_client_proxy_call_sync_void__boolean (EClient *client,
2563                                         gboolean *out_boolean,
2564                                         GCancellable *cancellable,
2565                                         GError **error,
2566                                         gboolean (*func) (GDBusProxy *proxy,
2567                                                           gboolean *out_boolean,
2568                                                           GCancellable *cancellable,
2569                                                           GError **error))
2570 {
2571         SYNC_CALL_TEMPLATE (out_boolean, (proxy, out_boolean, use_cancellable, &local_error))
2572 }
2573
2574 gboolean
2575 e_client_proxy_call_sync_void__string (EClient *client,
2576                                        gchar **out_string,
2577                                        GCancellable *cancellable,
2578                                        GError **error,
2579                                        gboolean (*func) (GDBusProxy *proxy,
2580                                                          gchar **out_string,
2581                                                          GCancellable *cancellable,
2582                                                          GError **error))
2583 {
2584         SYNC_CALL_TEMPLATE (out_string, (proxy, out_string, use_cancellable, &local_error))
2585 }
2586
2587 gboolean
2588 e_client_proxy_call_sync_void__strv (EClient *client,
2589                                      gchar ***out_strv,
2590                                      GCancellable *cancellable,
2591                                      GError **error,
2592                                      gboolean (*func) (GDBusProxy *proxy,
2593                                                        gchar ***out_strv,
2594                                                        GCancellable *cancellable,
2595                                                        GError **error))
2596 {
2597         SYNC_CALL_TEMPLATE (out_strv, (proxy, out_strv, use_cancellable, &local_error))
2598 }
2599
2600 gboolean
2601 e_client_proxy_call_sync_void__uint (EClient *client,
2602                                      guint *out_uint,
2603                                      GCancellable *cancellable,
2604                                      GError **error,
2605                                      gboolean (*func) (GDBusProxy *proxy,
2606                                                        guint *out_uint,
2607                                                        GCancellable *cancellable,
2608                                                        GError **error))
2609 {
2610         SYNC_CALL_TEMPLATE (out_uint, (proxy, out_uint, use_cancellable, &local_error))
2611 }
2612
2613 gboolean
2614 e_client_proxy_call_sync_boolean__void (EClient *client,
2615                                         gboolean in_boolean,
2616                                         GCancellable *cancellable,
2617                                         GError **error,
2618                                         gboolean (*func) (GDBusProxy *proxy,
2619                                                           gboolean in_boolean,
2620                                                           GCancellable *cancellable,
2621                                                           GError **error))
2622 {
2623         SYNC_CALL_TEMPLATE (client, (proxy, in_boolean, use_cancellable, &local_error))
2624 }
2625
2626 gboolean
2627 e_client_proxy_call_sync_boolean__boolean (EClient *client,
2628                                            gboolean in_boolean,
2629                                            gboolean *out_boolean,
2630                                            GCancellable *cancellable,
2631                                            GError **error,
2632                                            gboolean (*func) (GDBusProxy *proxy,
2633                                                              gboolean in_boolean,
2634                                                              gboolean *out_boolean,
2635                                                              GCancellable *cancellable,
2636                                                              GError **error))
2637 {
2638         SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_boolean, out_boolean, use_cancellable, &local_error))
2639 }
2640
2641 gboolean
2642 e_client_proxy_call_sync_boolean__string (EClient *client,
2643                                           gboolean in_boolean,
2644                                           gchar **out_string,
2645                                           GCancellable *cancellable,
2646                                           GError **error,
2647                                           gboolean (*func) (GDBusProxy *proxy,
2648                                                             gboolean in_boolean,
2649                                                             gchar **out_string,
2650                                                             GCancellable *cancellable,
2651                                                             GError **error))
2652 {
2653         SYNC_CALL_TEMPLATE (out_string, (proxy, in_boolean, out_string, use_cancellable, &local_error))
2654 }
2655
2656 gboolean
2657 e_client_proxy_call_sync_boolean__strv (EClient *client,
2658                                         gboolean in_boolean,
2659                                         gchar ***out_strv,
2660                                         GCancellable *cancellable,
2661                                         GError **error,
2662                                         gboolean (*func) (GDBusProxy *proxy,
2663                                                           gboolean in_boolean,
2664                                                           gchar ***out_strv,
2665                                                           GCancellable *cancellable,
2666                                                           GError **error))
2667 {
2668         SYNC_CALL_TEMPLATE (out_strv, (proxy, in_boolean, out_strv, use_cancellable, &local_error))
2669 }
2670
2671 gboolean
2672 e_client_proxy_call_sync_boolean__uint (EClient *client,
2673                                         gboolean in_boolean,
2674                                         guint *out_uint,
2675                                         GCancellable *cancellable,
2676                                         GError **error,
2677                                         gboolean (*func) (GDBusProxy *proxy,
2678                                                           gboolean in_boolean,
2679                                                           guint *out_uint,
2680                                                           GCancellable *cancellable,
2681                                                           GError **error))
2682 {
2683         SYNC_CALL_TEMPLATE (out_uint, (proxy, in_boolean, out_uint, use_cancellable, &local_error))
2684 }
2685
2686 gboolean
2687 e_client_proxy_call_sync_string__void (EClient *client,
2688                                        const gchar *in_string,
2689                                        GCancellable *cancellable,
2690                                        GError **error,
2691                                        gboolean (*func) (GDBusProxy *proxy,
2692                                                          const gchar *in_string,
2693                                                          GCancellable *cancellable,
2694                                                          GError **error))
2695 {
2696         SYNC_CALL_TEMPLATE (client, (proxy, in_string, use_cancellable, &local_error))
2697 }
2698
2699 gboolean
2700 e_client_proxy_call_sync_string__boolean (EClient *client,
2701                                           const gchar *in_string,
2702                                           gboolean *out_boolean,
2703                                           GCancellable *cancellable,
2704                                           GError **error,
2705                                           gboolean (*func) (GDBusProxy *proxy,
2706                                                             const gchar *in_string,
2707                                                             gboolean *out_boolean,
2708                                                             GCancellable *cancellable,
2709                                                             GError **error))
2710 {
2711         SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_string, out_boolean, use_cancellable, &local_error))
2712 }
2713
2714 gboolean
2715 e_client_proxy_call_sync_string__string (EClient *client,
2716                                          const gchar *in_string,
2717                                          gchar **out_string,
2718                                          GCancellable *cancellable,
2719                                          GError **error,
2720                                          gboolean (*func) (GDBusProxy *proxy,
2721                                                            const gchar *in_string,
2722                                                            gchar **out_string,
2723                                                            GCancellable *cancellable,
2724                                                            GError **error))
2725 {
2726         SYNC_CALL_TEMPLATE (out_string, (proxy, in_string, out_string, use_cancellable, &local_error))
2727 }
2728
2729 gboolean
2730 e_client_proxy_call_sync_string__strv (EClient *client,
2731                                        const gchar *in_string,
2732                                        gchar ***out_strv,
2733                                        GCancellable *cancellable,
2734                                        GError **error,
2735                                        gboolean (*func) (GDBusProxy *proxy,
2736                                                          const gchar *in_string,
2737                                                          gchar ***out_strv,
2738                                                          GCancellable *cancellable,
2739                                                          GError **error))
2740 {
2741         SYNC_CALL_TEMPLATE (out_strv, (proxy, in_string, out_strv, use_cancellable, &local_error))
2742 }
2743
2744 gboolean
2745 e_client_proxy_call_sync_string__uint (EClient *client,
2746                                        const gchar *in_string,
2747                                        guint *out_uint,
2748                                        GCancellable *cancellable,
2749                                        GError **error,
2750                                        gboolean (*func) (GDBusProxy *proxy,
2751                                                          const gchar *in_string,
2752                                                          guint *out_uint,
2753                                                          GCancellable *cancellable,
2754                                                          GError **error))
2755 {
2756         SYNC_CALL_TEMPLATE (out_uint, (proxy, in_string, out_uint, use_cancellable, &local_error))
2757 }
2758
2759 gboolean
2760 e_client_proxy_call_sync_strv__void (EClient *client,
2761                                      const gchar * const *in_strv,
2762                                      GCancellable *cancellable,
2763                                      GError **error,
2764                                      gboolean (*func) (GDBusProxy *proxy,
2765                                                        const gchar * const *in_strv,
2766                                                        GCancellable *cancellable,
2767                                                        GError **error))
2768 {
2769         SYNC_CALL_TEMPLATE (client, (proxy, in_strv, use_cancellable, &local_error))
2770 }
2771
2772 gboolean
2773 e_client_proxy_call_sync_strv__boolean (EClient *client,
2774                                         const gchar * const *in_strv,
2775                                         gboolean *out_boolean,
2776                                         GCancellable *cancellable,
2777                                         GError **error,
2778                                         gboolean (*func) (GDBusProxy *proxy,
2779                                                           const gchar * const *in_strv,
2780                                                           gboolean *out_boolean,
2781                                                           GCancellable *cancellable,
2782                                                           GError **error))
2783 {
2784         SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_strv, out_boolean, use_cancellable, &local_error))
2785 }
2786
2787 gboolean
2788 e_client_proxy_call_sync_strv__string (EClient *client,
2789                                        const gchar * const *in_strv,
2790                                        gchar **out_string,
2791                                        GCancellable *cancellable,
2792                                        GError **error,
2793                                        gboolean (*func) (GDBusProxy *proxy,
2794                                                          const gchar * const *in_strv,
2795                                                          gchar **out_string,
2796                                                          GCancellable *cancellable,
2797                                                          GError **error))
2798 {
2799         SYNC_CALL_TEMPLATE (out_string, (proxy, in_strv, out_string, use_cancellable, &local_error))
2800 }
2801
2802 gboolean
2803 e_client_proxy_call_sync_strv__strv (EClient *client,
2804                                      const gchar * const *in_strv,
2805                                      gchar ***out_strv,
2806                                      GCancellable *cancellable,
2807                                      GError **error,
2808                                      gboolean (*func) (GDBusProxy *proxy,
2809                                                        const gchar * const *in_strv,
2810                                                        gchar ***out_strv,
2811                                                        GCancellable *cancellable,
2812                                                        GError **error))
2813 {
2814         SYNC_CALL_TEMPLATE (out_strv, (proxy, in_strv, out_strv, use_cancellable, &local_error))
2815 }
2816
2817 gboolean
2818 e_client_proxy_call_sync_strv__uint (EClient *client,
2819                                      const gchar * const *in_strv,
2820                                      guint *out_uint,
2821                                      GCancellable *cancellable,
2822                                      GError **error,
2823                                      gboolean (*func) (GDBusProxy *proxy,
2824                                                        const gchar * const *in_strv,
2825                                                        guint *out_uint,
2826                                                        GCancellable *cancellable,
2827                                                        GError **error))
2828 {
2829         SYNC_CALL_TEMPLATE (out_uint, (proxy, in_strv, out_uint, use_cancellable, &local_error))
2830 }
2831
2832 gboolean
2833 e_client_proxy_call_sync_uint__void (EClient *client,
2834                                      guint in_uint,
2835                                      GCancellable *cancellable,
2836                                      GError **error,
2837                                      gboolean (*func) (GDBusProxy *proxy,
2838                                                        guint in_uint,
2839                                                        GCancellable *cancellable,
2840                                                        GError **error))
2841 {
2842         SYNC_CALL_TEMPLATE (client, (proxy, in_uint, use_cancellable, &local_error))
2843 }
2844
2845 gboolean
2846 e_client_proxy_call_sync_uint__boolean (EClient *client,
2847                                         guint in_uint,
2848                                         gboolean *out_boolean,
2849                                         GCancellable *cancellable,
2850                                         GError **error,
2851                                         gboolean (*func) (GDBusProxy *proxy,
2852                                                           guint in_uint,
2853                                                           gboolean *out_boolean,
2854                                                           GCancellable *cancellable,
2855                                                           GError **error))
2856 {
2857         SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_uint, out_boolean, use_cancellable, &local_error))
2858 }
2859
2860 gboolean
2861 e_client_proxy_call_sync_uint__string (EClient *client,
2862                                        guint in_uint,
2863                                        gchar **out_string,
2864                                        GCancellable *cancellable,
2865                                        GError **error,
2866                                        gboolean (*func) (GDBusProxy *proxy,
2867                                                          guint in_uint,
2868                                                          gchar **out_string,
2869                                                          GCancellable *cancellable,
2870                                                          GError **error))
2871 {
2872         SYNC_CALL_TEMPLATE (out_string, (proxy, in_uint, out_string, use_cancellable, &local_error))
2873 }
2874
2875 gboolean
2876 e_client_proxy_call_sync_uint__strv (EClient *client,
2877                                      guint in_uint,
2878                                      gchar ***out_strv,
2879                                      GCancellable *cancellable,
2880                                      GError **error,
2881                                      gboolean (*func) (GDBusProxy *proxy,
2882                                                        guint in_uint,
2883                                                        gchar ***out_strv,
2884                                                        GCancellable *cancellable,
2885                                                        GError **error))
2886 {
2887         SYNC_CALL_TEMPLATE (out_strv, (proxy, in_uint, out_strv, use_cancellable, &local_error))
2888 }
2889
2890 gboolean
2891 e_client_proxy_call_sync_uint__uint (EClient *client,
2892                                      guint in_uint,
2893                                      guint *out_uint,
2894                                      GCancellable *cancellable,
2895                                      GError **error,
2896                                      gboolean (*func) (GDBusProxy *proxy,
2897                                                        guint in_uint,
2898                                                        guint *out_uint,
2899                                                        GCancellable *cancellable,
2900                                                        GError **error))
2901 {
2902         SYNC_CALL_TEMPLATE (out_uint, (proxy, in_uint, out_uint, use_cancellable, &local_error))
2903 }
2904
2905 #undef SYNC_CALL_TEMPLATE