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