1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4 * Copyright (C) 2006 OpenedHand Ltd
5 * Copyright (C) 2009 Intel Corporation
7 * This library is free software; you can redistribute it and/or modify it under
8 * the terms of version 2.1 of the GNU Lesser General Public License as
9 * published by the Free Software Foundation.
11 * This library is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author: Ross Burton <ross@linux.intel.com>
25 #include <glib/gi18n.h>
28 /* Private D-Bus classes. */
29 #include <e-dbus-address-book.h>
31 #include <libebook-contacts/libebook-contacts.h>
33 #include "e-data-book-factory.h"
34 #include "e-data-book.h"
35 #include "e-data-book-view.h"
36 #include "e-book-backend.h"
37 #include "e-book-backend-sexp.h"
39 #define E_DATA_BOOK_GET_PRIVATE(obj) \
40 (G_TYPE_INSTANCE_GET_PRIVATE \
41 ((obj), E_TYPE_DATA_BOOK, EDataBookPrivate))
43 struct _EDataBookPrivate {
44 GDBusConnection *connection;
45 EDBusAddressBook *dbus_interface;
46 EBookBackend *backend;
49 GRecMutex pending_ops_lock;
50 GHashTable *pending_ops; /* opid -> OperationData */
52 /* Operations are queued while an
53 * open operation is in progress. */
66 static EOperationPool *ops_pool = NULL;
77 OP_GET_BACKEND_PROPERTY,
83 volatile gint ref_count;
86 guint32 id; /* operation id */
87 EDataBook *book; /* book */
88 GCancellable *cancellable;
89 GDBusMethodInvocation *invocation;
95 /* OP_REMOVE_CONTACTS */
98 /* OP_MODIFY_CONTACTS */
101 /* OP_GET_CONTACTS */
102 /* OP_GET_CONTACTS_UIDS */
104 /* OP_GET_BACKEND_PROPERTY */
105 const gchar *prop_name;
112 /* Forward Declarations */
113 static void e_data_book_initable_init (GInitableIface *interface);
115 G_DEFINE_TYPE_WITH_CODE (
119 G_IMPLEMENT_INTERFACE (
121 e_data_book_initable_init))
124 construct_bookview_path (void)
126 static volatile gint counter = 1;
128 g_atomic_int_inc (&counter);
130 return g_strdup_printf (
131 "/org/gnome/evolution/dataserver/AddressBookView/%d/%d",
136 op_sender_vanished_cb (GDBusConnection *connection,
138 GCancellable *cancellable)
140 g_cancellable_cancel (cancellable);
143 static OperationData *
144 op_ref (OperationData *data)
146 g_return_val_if_fail (data != NULL, data);
147 g_return_val_if_fail (data->ref_count > 0, data);
149 g_atomic_int_inc (&data->ref_count);
154 static OperationData *
155 op_new (OperationID op,
157 GDBusMethodInvocation *invocation)
161 data = g_slice_new0 (OperationData);
164 data->id = e_operation_pool_reserve_opid (ops_pool);
165 data->book = g_object_ref (book);
166 data->cancellable = g_cancellable_new ();
168 /* This is optional so we can fake client requests. */
169 if (invocation != NULL) {
170 GDBusConnection *connection;
173 data->invocation = g_object_ref (invocation);
175 connection = e_data_book_get_connection (book);
176 sender = g_dbus_method_invocation_get_sender (invocation);
178 data->watcher_id = g_bus_watch_name_on_connection (
180 G_BUS_NAME_WATCHER_FLAGS_NONE,
181 (GBusNameAppearedCallback) NULL,
182 (GBusNameVanishedCallback) op_sender_vanished_cb,
183 g_object_ref (data->cancellable),
184 (GDestroyNotify) g_object_unref);
187 g_rec_mutex_lock (&book->priv->pending_ops_lock);
188 g_hash_table_insert (
189 book->priv->pending_ops,
190 GUINT_TO_POINTER (data->id),
192 g_rec_mutex_unlock (&book->priv->pending_ops_lock);
198 op_unref (OperationData *data)
200 g_return_if_fail (data != NULL);
201 g_return_if_fail (data->ref_count > 0);
203 if (g_atomic_int_dec_and_test (&data->ref_count)) {
207 g_free (data->d.uid);
209 case OP_REMOVE_CONTACTS:
212 (GDestroyNotify) g_free);
214 case OP_ADD_CONTACTS:
215 case OP_MODIFY_CONTACTS:
218 (GDestroyNotify) g_free);
221 case OP_GET_CONTACTS:
222 case OP_GET_CONTACTS_UIDS:
223 g_free (data->d.query);
229 g_object_unref (data->book);
230 g_object_unref (data->cancellable);
232 if (data->invocation != NULL)
233 g_object_unref (data->invocation);
235 if (data->watcher_id > 0)
236 g_bus_unwatch_name (data->watcher_id);
238 g_slice_free (OperationData, data);
243 op_dispatch (EDataBook *book,
246 g_mutex_lock (&book->priv->open_lock);
248 /* If an open operation is currently in progress, queue this
249 * operation to be dispatched when the open operation finishes. */
250 if (book->priv->open_opid > 0) {
251 g_queue_push_tail (&book->priv->open_queue, data);
253 if (data->op == OP_OPEN)
254 book->priv->open_opid = data->id;
255 e_operation_pool_push (ops_pool, data);
258 g_mutex_unlock (&book->priv->open_lock);
261 static OperationData *
262 op_claim (EDataBook *book,
267 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
269 e_operation_pool_release_opid (ops_pool, opid);
271 g_rec_mutex_lock (&book->priv->pending_ops_lock);
272 data = g_hash_table_lookup (
273 book->priv->pending_ops,
274 GUINT_TO_POINTER (opid));
276 /* Steal the hash table's reference. */
278 book->priv->pending_ops,
279 GUINT_TO_POINTER (opid));
281 g_rec_mutex_unlock (&book->priv->pending_ops_lock);
287 op_complete (EDataBook *book,
290 g_return_if_fail (E_IS_DATA_BOOK (book));
292 e_operation_pool_release_opid (ops_pool, opid);
294 g_rec_mutex_lock (&book->priv->pending_ops_lock);
295 g_hash_table_remove (
296 book->priv->pending_ops,
297 GUINT_TO_POINTER (opid));
298 g_rec_mutex_unlock (&book->priv->pending_ops_lock);
302 data_book_convert_to_client_error (GError *error)
304 g_return_if_fail (error != NULL);
306 if (error->domain != E_DATA_BOOK_ERROR)
309 switch (error->code) {
310 case E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE:
311 error->domain = E_CLIENT_ERROR;
312 error->code = E_CLIENT_ERROR_REPOSITORY_OFFLINE;
315 case E_DATA_BOOK_STATUS_PERMISSION_DENIED:
316 error->domain = E_CLIENT_ERROR;
317 error->code = E_CLIENT_ERROR_PERMISSION_DENIED;
320 case E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND:
321 error->domain = E_BOOK_CLIENT_ERROR;
322 error->code = E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND;
325 case E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS:
326 error->domain = E_BOOK_CLIENT_ERROR;
327 error->code = E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS;
330 case E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED:
331 error->domain = E_CLIENT_ERROR;
332 error->code = E_CLIENT_ERROR_AUTHENTICATION_FAILED;
335 case E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD:
336 error->domain = E_CLIENT_ERROR;
337 error->code = E_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD;
340 case E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE:
341 error->domain = E_CLIENT_ERROR;
342 error->code = E_CLIENT_ERROR_TLS_NOT_AVAILABLE;
345 case E_DATA_BOOK_STATUS_NO_SUCH_BOOK:
346 error->domain = E_BOOK_CLIENT_ERROR;
347 error->code = E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK;
350 case E_DATA_BOOK_STATUS_BOOK_REMOVED:
351 error->domain = E_BOOK_CLIENT_ERROR;
352 error->code = E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE;
355 case E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE:
356 error->domain = E_CLIENT_ERROR;
357 error->code = E_CLIENT_ERROR_OFFLINE_UNAVAILABLE;
360 case E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED:
361 error->domain = E_CLIENT_ERROR;
362 error->code = E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED;
365 case E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED:
366 error->domain = E_CLIENT_ERROR;
367 error->code = E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED;
370 case E_DATA_BOOK_STATUS_INVALID_QUERY:
371 error->domain = E_CLIENT_ERROR;
372 error->code = E_CLIENT_ERROR_INVALID_QUERY;
375 case E_DATA_BOOK_STATUS_QUERY_REFUSED:
376 error->domain = E_CLIENT_ERROR;
377 error->code = E_CLIENT_ERROR_QUERY_REFUSED;
380 case E_DATA_BOOK_STATUS_COULD_NOT_CANCEL:
381 error->domain = E_CLIENT_ERROR;
382 error->code = E_CLIENT_ERROR_COULD_NOT_CANCEL;
385 case E_DATA_BOOK_STATUS_NO_SPACE:
386 error->domain = E_BOOK_CLIENT_ERROR;
387 error->code = E_BOOK_CLIENT_ERROR_NO_SPACE;
390 case E_DATA_BOOK_STATUS_INVALID_ARG:
391 error->domain = E_CLIENT_ERROR;
392 error->code = E_CLIENT_ERROR_INVALID_ARG;
395 case E_DATA_BOOK_STATUS_NOT_SUPPORTED:
396 error->domain = E_CLIENT_ERROR;
397 error->code = E_CLIENT_ERROR_NOT_SUPPORTED;
400 case E_DATA_BOOK_STATUS_NOT_OPENED:
401 error->domain = E_CLIENT_ERROR;
402 error->code = E_CLIENT_ERROR_NOT_OPENED;
405 case E_DATA_BOOK_STATUS_OUT_OF_SYNC:
406 error->domain = E_CLIENT_ERROR;
407 error->code = E_CLIENT_ERROR_OUT_OF_SYNC;
410 case E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD:
411 case E_DATA_BOOK_STATUS_OTHER_ERROR:
412 case E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION:
413 error->domain = E_CLIENT_ERROR;
414 error->code = E_CLIENT_ERROR_OTHER_ERROR;
418 g_warn_if_reached ();
423 operation_thread (gpointer data,
426 OperationData *op = data;
427 EBookBackend *backend;
431 backend = e_data_book_get_backend (op->book);
435 e_book_backend_open (
436 backend, op->book, op->id,
437 op->cancellable, FALSE);
440 case OP_ADD_CONTACTS:
441 e_book_backend_create_contacts (
442 backend, op->book, op->id,
443 op->cancellable, op->d.vcards);
447 e_book_backend_get_contact (
448 backend, op->book, op->id,
449 op->cancellable, op->d.uid);
452 case OP_GET_CONTACTS:
453 e_book_backend_get_contact_list (
454 backend, op->book, op->id,
455 op->cancellable, op->d.query);
458 case OP_GET_CONTACTS_UIDS:
459 e_book_backend_get_contact_list_uids (
460 backend, op->book, op->id,
461 op->cancellable, op->d.query);
464 case OP_MODIFY_CONTACTS:
465 e_book_backend_modify_contacts (
466 backend, op->book, op->id,
467 op->cancellable, op->d.vcards);
470 case OP_REMOVE_CONTACTS:
471 e_book_backend_remove_contacts (
472 backend, op->book, op->id,
473 op->cancellable, op->d.ids);
477 e_book_backend_refresh (
478 backend, op->book, op->id, op->cancellable);
481 case OP_GET_BACKEND_PROPERTY:
482 e_book_backend_get_backend_property (
483 backend, op->book, op->id,
484 op->cancellable, op->d.prop_name);
490 EBookBackendSExp *card_sexp;
491 GDBusConnection *connection;
493 GError *error = NULL;
495 card_sexp = e_book_backend_sexp_new (op->d.query);
497 g_dbus_method_invocation_return_error_literal (
500 E_CLIENT_ERROR_INVALID_QUERY,
503 op_complete (op->book, op->id);
507 object_path = construct_bookview_path ();
508 connection = e_data_book_get_connection (op->book);
510 view = e_data_book_view_new (
512 connection, object_path, &error);
514 g_object_unref (card_sexp);
518 ((view != NULL) && (error == NULL)) ||
519 ((view == NULL) && (error != NULL)));
522 /* Translators: This is prefix to a detailed error message */
523 g_prefix_error (&error, "%s", _("Invalid query: "));
524 data_book_convert_to_client_error (error);
525 g_dbus_method_invocation_take_error (
526 op->invocation, error);
528 op_complete (op->book, op->id);
529 g_free (object_path);
533 e_book_backend_add_view (backend, view);
535 e_dbus_address_book_complete_get_view (
536 op->book->priv->dbus_interface,
540 op_complete (op->book, op->id);
541 g_free (object_path);
546 /* close just cancels all pending ops and frees data book */
547 e_book_backend_remove_client (backend, op->book);
549 g_rec_mutex_lock (&op->book->priv->pending_ops_lock);
551 g_hash_table_iter_init (&iter, op->book->priv->pending_ops);
552 while (g_hash_table_iter_next (&iter, NULL, &value)) {
553 OperationData *cancel_op = value;
554 g_cancellable_cancel (cancel_op->cancellable);
557 g_rec_mutex_unlock (&op->book->priv->pending_ops_lock);
559 e_dbus_address_book_complete_close (
560 op->book->priv->dbus_interface,
563 op_complete (op->book, op->id);
571 * e_data_book_status_to_string:
576 e_data_book_status_to_string (EDataBookStatus status)
579 static struct _statuses {
580 EDataBookStatus status;
583 { E_DATA_BOOK_STATUS_SUCCESS, N_("Success") },
584 { E_DATA_BOOK_STATUS_BUSY, N_("Backend is busy") },
585 { E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, N_("Repository offline") },
586 { E_DATA_BOOK_STATUS_PERMISSION_DENIED, N_("Permission denied") },
587 { E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, N_("Contact not found") },
588 { E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS, N_("Contact ID already exists") },
589 { E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED, N_("Authentication Failed") },
590 { E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED, N_("Authentication Required") },
591 { E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD, N_("Unsupported field") },
592 { E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD, N_("Unsupported authentication method") },
593 { E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE, N_("TLS not available") },
594 { E_DATA_BOOK_STATUS_NO_SUCH_BOOK, N_("Address book does not exist") },
595 { E_DATA_BOOK_STATUS_BOOK_REMOVED, N_("Book removed") },
596 { E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE, N_("Not available in offline mode") },
597 { E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED, N_("Search size limit exceeded") },
598 { E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED, N_("Search time limit exceeded") },
599 { E_DATA_BOOK_STATUS_INVALID_QUERY, N_("Invalid query") },
600 { E_DATA_BOOK_STATUS_QUERY_REFUSED, N_("Query refused") },
601 { E_DATA_BOOK_STATUS_COULD_NOT_CANCEL, N_("Could not cancel") },
602 /* { E_DATA_BOOK_STATUS_OTHER_ERROR, N_("Other error") }, */
603 { E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION, N_("Invalid server version") },
604 { E_DATA_BOOK_STATUS_NO_SPACE, N_("No space") },
605 { E_DATA_BOOK_STATUS_INVALID_ARG, N_("Invalid argument") },
606 /* Translators: The string for NOT_SUPPORTED error */
607 { E_DATA_BOOK_STATUS_NOT_SUPPORTED, N_("Not supported") },
608 { E_DATA_BOOK_STATUS_NOT_OPENED, N_("Backend is not opened yet") },
609 { E_DATA_BOOK_STATUS_OUT_OF_SYNC, N_("Object is out of sync") }
612 for (i = 0; i < G_N_ELEMENTS (statuses); i++) {
613 if (statuses[i].status == status)
614 return _(statuses[i].msg);
617 return _("Other error");
620 /* Create the EDataBook error quark */
622 e_data_book_error_quark (void)
624 #define ERR_PREFIX "org.gnome.evolution.dataserver.AddressBook."
626 static const GDBusErrorEntry entries[] = {
627 { E_DATA_BOOK_STATUS_SUCCESS, ERR_PREFIX "Success" },
628 { E_DATA_BOOK_STATUS_BUSY, ERR_PREFIX "Busy" },
629 { E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, ERR_PREFIX "RepositoryOffline" },
630 { E_DATA_BOOK_STATUS_PERMISSION_DENIED, ERR_PREFIX "PermissionDenied" },
631 { E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, ERR_PREFIX "ContactNotFound" },
632 { E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS, ERR_PREFIX "ContactIDAlreadyExists" },
633 { E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED, ERR_PREFIX "AuthenticationFailed" },
634 { E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED, ERR_PREFIX "AuthenticationRequired" },
635 { E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD, ERR_PREFIX "UnsupportedField" },
636 { E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD, ERR_PREFIX "UnsupportedAuthenticationMethod" },
637 { E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE, ERR_PREFIX "TLSNotAvailable" },
638 { E_DATA_BOOK_STATUS_NO_SUCH_BOOK, ERR_PREFIX "NoSuchBook" },
639 { E_DATA_BOOK_STATUS_BOOK_REMOVED, ERR_PREFIX "BookRemoved" },
640 { E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE, ERR_PREFIX "OfflineUnavailable" },
641 { E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED, ERR_PREFIX "SearchSizeLimitExceeded" },
642 { E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED, ERR_PREFIX "SearchTimeLimitExceeded" },
643 { E_DATA_BOOK_STATUS_INVALID_QUERY, ERR_PREFIX "InvalidQuery" },
644 { E_DATA_BOOK_STATUS_QUERY_REFUSED, ERR_PREFIX "QueryRefused" },
645 { E_DATA_BOOK_STATUS_COULD_NOT_CANCEL, ERR_PREFIX "CouldNotCancel" },
646 { E_DATA_BOOK_STATUS_OTHER_ERROR, ERR_PREFIX "OtherError" },
647 { E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION, ERR_PREFIX "InvalidServerVersion" },
648 { E_DATA_BOOK_STATUS_NO_SPACE, ERR_PREFIX "NoSpace" },
649 { E_DATA_BOOK_STATUS_INVALID_ARG, ERR_PREFIX "InvalidArg" },
650 { E_DATA_BOOK_STATUS_NOT_SUPPORTED, ERR_PREFIX "NotSupported" },
651 { E_DATA_BOOK_STATUS_NOT_OPENED, ERR_PREFIX "NotOpened" },
652 { E_DATA_BOOK_STATUS_OUT_OF_SYNC, ERR_PREFIX "OutOfSync" }
657 static volatile gsize quark_volatile = 0;
659 g_dbus_error_register_error_domain ("e-data-book-error", &quark_volatile, entries, G_N_ELEMENTS (entries));
661 return (GQuark) quark_volatile;
665 * e_data_book_create_error:
670 e_data_book_create_error (EDataBookStatus status,
671 const gchar *custom_msg)
673 if (status == E_DATA_BOOK_STATUS_SUCCESS)
676 return g_error_new_literal (E_DATA_BOOK_ERROR, status, custom_msg ? custom_msg : e_data_book_status_to_string (status));
680 * e_data_book_create_error_fmt:
685 e_data_book_create_error_fmt (EDataBookStatus status,
686 const gchar *custom_msg_fmt,
694 return e_data_book_create_error (status, NULL);
696 va_start (ap, custom_msg_fmt);
697 custom_msg = g_strdup_vprintf (custom_msg_fmt, ap);
700 error = e_data_book_create_error (status, custom_msg);
708 * e_data_book_string_slist_to_comma_string:
710 * Takes a list of strings and converts it to a comma-separated string of
711 * values; free returned pointer with g_free()
716 e_data_book_string_slist_to_comma_string (const GSList *strings)
722 tmp = g_string_new ("");
723 for (l = strings; l != NULL; l = l->next) {
724 const gchar *str = l->data;
729 if (strchr (str, ',')) {
730 g_warning ("%s: String cannot contain comma; skipping value '%s'\n", G_STRFUNC, str);
735 g_string_append_c (tmp, ',');
736 g_string_append (tmp, str);
739 res = e_util_utf8_make_valid (tmp->str);
741 g_string_free (tmp, TRUE);
747 data_book_handle_open_cb (EDBusAddressBook *interface,
748 GDBusMethodInvocation *invocation,
753 op = op_new (OP_OPEN, book, invocation);
755 op_dispatch (book, op);
761 data_book_handle_refresh_cb (EDBusAddressBook *interface,
762 GDBusMethodInvocation *invocation,
767 op = op_new (OP_REFRESH, book, invocation);
769 op_dispatch (book, op);
775 data_book_handle_get_contact_cb (EDBusAddressBook *interface,
776 GDBusMethodInvocation *invocation,
782 op = op_new (OP_GET_CONTACT, book, invocation);
783 op->d.uid = g_strdup (in_uid);
785 op_dispatch (book, op);
791 data_book_handle_get_contact_list_cb (EDBusAddressBook *interface,
792 GDBusMethodInvocation *invocation,
793 const gchar *in_query,
798 op = op_new (OP_GET_CONTACTS, book, invocation);
799 op->d.query = g_strdup (in_query);
801 op_dispatch (book, op);
807 data_book_handle_get_contact_list_uids_cb (EDBusAddressBook *interface,
808 GDBusMethodInvocation *invocation,
809 const gchar *in_query,
814 op = op_new (OP_GET_CONTACTS_UIDS, book, invocation);
815 op->d.query = g_strdup (in_query);
817 op_dispatch (book, op);
823 data_book_handle_create_contacts_cb (EDBusAddressBook *interface,
824 GDBusMethodInvocation *invocation,
825 const gchar * const *in_vcards,
830 op = op_new (OP_ADD_CONTACTS, book, invocation);
831 op->d.vcards = e_util_strv_to_slist (in_vcards);
833 op_dispatch (book, op);
839 data_book_handle_modify_contacts_cb (EDBusAddressBook *interface,
840 GDBusMethodInvocation *invocation,
841 const gchar * const *in_vcards,
846 op = op_new (OP_MODIFY_CONTACTS, book, invocation);
847 op->d.vcards = e_util_strv_to_slist (in_vcards);
849 op_dispatch (book, op);
855 data_book_handle_remove_contacts_cb (EDBusAddressBook *interface,
856 GDBusMethodInvocation *invocation,
857 const gchar * const *in_uids,
862 op = op_new (OP_REMOVE_CONTACTS, book, invocation);
864 /* Allow an empty array to be removed */
865 for (; in_uids && *in_uids; in_uids++) {
866 op->d.ids = g_slist_prepend (op->d.ids, g_strdup (*in_uids));
869 op_dispatch (book, op);
875 data_book_handle_get_view_cb (EDBusAddressBook *interface,
876 GDBusMethodInvocation *invocation,
877 const gchar *in_query,
882 op = op_new (OP_GET_VIEW, book, invocation);
883 op->d.query = g_strdup (in_query);
885 /* This operation is never queued. */
886 e_operation_pool_push (ops_pool, op);
892 data_book_handle_close_cb (EDBusAddressBook *interface,
893 GDBusMethodInvocation *invocation,
898 op = op_new (OP_CLOSE, book, invocation);
899 /* unref here makes sure the book is freed in a separate thread */
900 g_object_unref (book);
902 /* This operation is never queued. */
903 e_operation_pool_push (ops_pool, op);
909 e_data_book_respond_open (EDataBook *book,
916 g_return_if_fail (E_IS_DATA_BOOK (book));
918 data = op_claim (book, opid);
919 g_return_if_fail (data != NULL);
921 /* Translators: This is prefix to a detailed error message */
922 g_prefix_error (&error, "%s", _("Cannot open book: "));
924 /* This function is deprecated, but it's the only way to
925 * set EBookBackend's internal 'opened' flag. We should
926 * be the only ones calling this. */
928 copy = g_error_copy (error);
929 e_book_backend_notify_opened (book->priv->backend, copy);
932 e_dbus_address_book_complete_open (
933 book->priv->dbus_interface,
936 data_book_convert_to_client_error (error);
937 g_dbus_method_invocation_take_error (
938 data->invocation, error);
943 /* Dispatch any pending operations. */
945 g_mutex_lock (&book->priv->open_lock);
947 if (opid == book->priv->open_opid) {
950 book->priv->open_opid = 0;
952 while (!g_queue_is_empty (&book->priv->open_queue)) {
953 op = g_queue_pop_head (&book->priv->open_queue);
954 e_operation_pool_push (ops_pool, op);
958 g_mutex_unlock (&book->priv->open_lock);
962 * e_data_book_respond_refresh:
963 * @book: An addressbook client interface.
964 * @error: Operation error, if any, automatically freed if passed it.
966 * Notifies listeners of the completion of the refresh method call.
971 e_data_book_respond_refresh (EDataBook *book,
977 g_return_if_fail (E_IS_DATA_BOOK (book));
979 data = op_claim (book, opid);
980 g_return_if_fail (data != NULL);
982 /* Translators: This is prefix to a detailed error message */
983 g_prefix_error (&error, "%s", _("Cannot refresh address book: "));
986 e_dbus_address_book_complete_refresh (
987 book->priv->dbus_interface,
990 data_book_convert_to_client_error (error);
991 g_dbus_method_invocation_take_error (
992 data->invocation, error);
999 * e_data_book_respond_get_backend_property:
1001 * FIXME: Document me.
1006 e_data_book_respond_get_backend_property (EDataBook *book,
1009 const gchar *prop_value)
1011 OperationData *data;
1013 g_return_if_fail (E_IS_DATA_BOOK (book));
1015 data = op_claim (book, opid);
1016 g_return_if_fail (data != NULL);
1018 if (error == NULL) {
1019 e_data_book_report_backend_property_changed (
1020 book, data->d.prop_name, prop_value);
1022 /* This should never happen, since all backend property
1023 * requests now originate from our constructed() method. */
1024 g_warning ("%s: %s", G_STRFUNC, error->message);
1025 g_error_free (error);
1032 * e_data_book_respond_set_backend_property:
1034 * FIXME: Document me.
1038 * Deprecated: 3.8: This function no longer does anything.
1041 e_data_book_respond_set_backend_property (EDataBook *book,
1049 e_data_book_respond_get_contact (EDataBook *book,
1054 OperationData *data;
1056 g_return_if_fail (E_IS_DATA_BOOK (book));
1058 data = op_claim (book, opid);
1059 g_return_if_fail (data != NULL);
1061 /* Translators: This is prefix to a detailed error message */
1062 g_prefix_error (&error, "%s", _("Cannot get contact: "));
1064 if (error == NULL) {
1067 utf8_vcard = e_util_utf8_make_valid (vcard);
1069 e_dbus_address_book_complete_get_contact (
1070 book->priv->dbus_interface,
1074 g_free (utf8_vcard);
1076 data_book_convert_to_client_error (error);
1077 g_dbus_method_invocation_take_error (
1078 data->invocation, error);
1085 e_data_book_respond_get_contact_list (EDataBook *book,
1088 const GSList *cards)
1090 OperationData *data;
1092 g_return_if_fail (E_IS_DATA_BOOK (book));
1094 data = op_claim (book, opid);
1095 g_return_if_fail (data != NULL);
1097 /* Translators: This is prefix to a detailed error message */
1098 g_prefix_error (&error, "%s", _("Cannot get contact list: "));
1100 if (error == NULL) {
1105 length = g_slist_length ((GSList *) cards);
1106 strv = g_new0 (gchar *, length + 1);
1108 while (cards != NULL) {
1109 strv[ii++] = e_util_utf8_make_valid (cards->data);
1110 cards = g_slist_next ((GSList *) cards);
1113 e_dbus_address_book_complete_get_contact_list (
1114 book->priv->dbus_interface,
1116 (const gchar * const *) strv);
1120 data_book_convert_to_client_error (error);
1121 g_dbus_method_invocation_take_error (
1122 data->invocation, error);
1129 * e_data_book_respond_get_contact_list_uids:
1131 * FIXME: Document me.
1136 e_data_book_respond_get_contact_list_uids (EDataBook *book,
1141 OperationData *data;
1143 g_return_if_fail (E_IS_DATA_BOOK (book));
1145 data = op_claim (book, opid);
1146 g_return_if_fail (data != NULL);
1148 /* Translators: This is prefix to a detailed error message */
1149 g_prefix_error (&error, "%s", _("Cannot get contact list uids: "));
1151 if (error == NULL) {
1156 length = g_slist_length ((GSList *) uids);
1157 strv = g_new0 (gchar *, length + 1);
1159 while (uids != NULL) {
1160 strv[ii++] = e_util_utf8_make_valid (uids->data);
1161 uids = g_slist_next ((GSList *) uids);
1164 e_dbus_address_book_complete_get_contact_list_uids (
1165 book->priv->dbus_interface,
1167 (const gchar * const *) strv);
1171 data_book_convert_to_client_error (error);
1172 g_dbus_method_invocation_take_error (
1173 data->invocation, error);
1180 * e_data_book_respond_create_contacts:
1182 * FIXME: Document me!
1187 e_data_book_respond_create_contacts (EDataBook *book,
1190 const GSList *contacts)
1192 OperationData *data;
1194 g_return_if_fail (E_IS_DATA_BOOK (book));
1196 data = op_claim (book, opid);
1197 g_return_if_fail (data != NULL);
1199 /* Translators: This is prefix to a detailed error message */
1200 g_prefix_error (&error, "%s", _("Cannot add contact: "));
1202 if (error == NULL) {
1203 EBookBackend *backend;
1208 backend = e_data_book_get_backend (book);
1210 length = g_slist_length ((GSList *) contacts);
1211 strv = g_new0 (gchar *, length + 1);
1213 while (contacts != NULL) {
1214 EContact *contact = E_CONTACT (contacts->data);
1217 uid = e_contact_get_const (contact, E_CONTACT_UID);
1218 strv[ii++] = e_util_utf8_make_valid (uid);
1220 e_book_backend_notify_update (backend, contact);
1222 contacts = g_slist_next ((GSList *) contacts);
1225 e_dbus_address_book_complete_create_contacts (
1226 book->priv->dbus_interface,
1228 (const gchar * const *) strv);
1230 e_book_backend_notify_complete (backend);
1234 data_book_convert_to_client_error (error);
1235 g_dbus_method_invocation_take_error (
1236 data->invocation, error);
1243 * e_data_book_respond_modify_contacts:
1245 * FIXME: Document me!
1250 e_data_book_respond_modify_contacts (EDataBook *book,
1253 const GSList *contacts)
1255 OperationData *data;
1257 g_return_if_fail (E_IS_DATA_BOOK (book));
1259 data = op_claim (book, opid);
1260 g_return_if_fail (data != NULL);
1262 /* Translators: This is prefix to a detailed error message */
1263 g_prefix_error (&error, "%s", _("Cannot modify contacts: "));
1265 if (error == NULL) {
1266 EBookBackend *backend;
1268 backend = e_data_book_get_backend (book);
1270 e_dbus_address_book_complete_modify_contacts (
1271 book->priv->dbus_interface,
1274 while (contacts != NULL) {
1275 EContact *contact = E_CONTACT (contacts->data);
1276 e_book_backend_notify_update (backend, contact);
1277 contacts = g_slist_next ((GSList *) contacts);
1280 e_book_backend_notify_complete (backend);
1282 data_book_convert_to_client_error (error);
1283 g_dbus_method_invocation_take_error (
1284 data->invocation, error);
1291 e_data_book_respond_remove_contacts (EDataBook *book,
1296 OperationData *data;
1298 g_return_if_fail (E_IS_DATA_BOOK (book));
1300 data = op_claim (book, opid);
1301 g_return_if_fail (data != NULL);
1303 /* Translators: This is prefix to a detailed error message */
1304 g_prefix_error (&error, "%s", _("Cannot remove contacts: "));
1306 if (error == NULL) {
1307 EBookBackend *backend;
1309 backend = e_data_book_get_backend (book);
1311 e_dbus_address_book_complete_remove_contacts (
1312 book->priv->dbus_interface,
1315 while (ids != NULL) {
1316 e_book_backend_notify_remove (backend, ids->data);
1317 ids = g_slist_next ((GSList *) ids);
1320 e_book_backend_notify_complete (backend);
1322 data_book_convert_to_client_error (error);
1323 g_dbus_method_invocation_take_error (
1324 data->invocation, error);
1331 * e_data_book_report_error:
1333 * FIXME: Document me.
1338 e_data_book_report_error (EDataBook *book,
1339 const gchar *message)
1341 g_return_if_fail (E_IS_DATA_BOOK (book));
1342 g_return_if_fail (message != NULL);
1344 e_dbus_address_book_emit_error (book->priv->dbus_interface, message);
1348 * e_data_book_report_readonly:
1350 * FIXME: Document me.
1354 * Deprecated: 3.8: Use e_book_backend_set_writable() instead.
1357 e_data_book_report_readonly (EDataBook *book,
1360 g_return_if_fail (E_IS_DATA_BOOK (book));
1362 e_book_backend_set_writable (book->priv->backend, !readonly);
1366 * e_data_book_report_online:
1368 * FIXME: Document me.
1372 * Deprecated: 3.8: Use e_backend_set_online() instead.
1375 e_data_book_report_online (EDataBook *book,
1378 g_return_if_fail (E_IS_DATA_BOOK (book));
1380 e_backend_set_online (E_BACKEND (book->priv->backend), is_online);
1384 * e_data_book_report_opened:
1386 * Reports to associated client that opening phase of the book is finished.
1387 * error being NULL means successfully, otherwise reports an error which
1388 * happened during opening phase. By opening phase is meant a process
1389 * including successfull authentication to the server/storage.
1393 * Deprecated: 3.8: This function no longer does anything.
1396 e_data_book_report_opened (EDataBook *book,
1397 const GError *error)
1403 * e_data_book_report_backend_property_changed:
1405 * FIXME: Document me.
1410 e_data_book_report_backend_property_changed (EDataBook *book,
1411 const gchar *prop_name,
1412 const gchar *prop_value)
1414 EDBusAddressBook *dbus_interface;
1417 g_return_if_fail (E_IS_DATA_BOOK (book));
1418 g_return_if_fail (prop_name != NULL);
1420 if (prop_value == NULL)
1423 dbus_interface = book->priv->dbus_interface;
1425 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
1426 strv = g_strsplit (prop_value, ",", -1);
1427 e_dbus_address_book_set_capabilities (
1428 dbus_interface, (const gchar * const *) strv);
1432 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_REVISION))
1433 e_dbus_address_book_set_revision (dbus_interface, prop_value);
1435 if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
1436 strv = g_strsplit (prop_value, ",", -1);
1437 e_dbus_address_book_set_required_fields (
1438 dbus_interface, (const gchar * const *) strv);
1442 if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
1443 strv = g_strsplit (prop_value, ",", -1);
1444 e_dbus_address_book_set_supported_fields (
1445 dbus_interface, (const gchar * const *) strv);
1449 /* Disregard anything else. */
1453 data_book_set_backend (EDataBook *book,
1454 EBookBackend *backend)
1456 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
1457 g_return_if_fail (book->priv->backend == NULL);
1459 book->priv->backend = g_object_ref (backend);
1463 data_book_set_connection (EDataBook *book,
1464 GDBusConnection *connection)
1466 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1467 g_return_if_fail (book->priv->connection == NULL);
1469 book->priv->connection = g_object_ref (connection);
1473 data_book_set_object_path (EDataBook *book,
1474 const gchar *object_path)
1476 g_return_if_fail (object_path != NULL);
1477 g_return_if_fail (book->priv->object_path == NULL);
1479 book->priv->object_path = g_strdup (object_path);
1483 data_book_set_property (GObject *object,
1485 const GValue *value,
1488 switch (property_id) {
1490 data_book_set_backend (
1491 E_DATA_BOOK (object),
1492 g_value_get_object (value));
1495 case PROP_CONNECTION:
1496 data_book_set_connection (
1497 E_DATA_BOOK (object),
1498 g_value_get_object (value));
1501 case PROP_OBJECT_PATH:
1502 data_book_set_object_path (
1503 E_DATA_BOOK (object),
1504 g_value_get_string (value));
1508 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1512 data_book_get_property (GObject *object,
1517 switch (property_id) {
1519 g_value_set_object (
1521 e_data_book_get_backend (
1522 E_DATA_BOOK (object)));
1525 case PROP_CONNECTION:
1526 g_value_set_object (
1528 e_data_book_get_connection (
1529 E_DATA_BOOK (object)));
1532 case PROP_OBJECT_PATH:
1533 g_value_set_string (
1535 e_data_book_get_object_path (
1536 E_DATA_BOOK (object)));
1540 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1544 data_book_dispose (GObject *object)
1546 EDataBookPrivate *priv;
1548 priv = E_DATA_BOOK_GET_PRIVATE (object);
1550 if (priv->connection != NULL) {
1551 g_object_unref (priv->connection);
1552 priv->connection = NULL;
1555 if (priv->backend != NULL) {
1556 g_object_unref (priv->backend);
1557 priv->backend = NULL;
1560 /* Chain up to parent's dispose() metnod. */
1561 G_OBJECT_CLASS (e_data_book_parent_class)->dispose (object);
1565 data_book_finalize (GObject *object)
1567 EDataBookPrivate *priv;
1569 priv = E_DATA_BOOK_GET_PRIVATE (object);
1571 g_free (priv->object_path);
1573 if (priv->pending_ops) {
1574 g_hash_table_destroy (priv->pending_ops);
1575 priv->pending_ops = NULL;
1578 g_rec_mutex_clear (&priv->pending_ops_lock);
1580 if (priv->dbus_interface) {
1581 g_object_unref (priv->dbus_interface);
1582 priv->dbus_interface = NULL;
1585 g_mutex_clear (&priv->open_lock);
1587 /* This should be empty now, else we leak memory. */
1588 g_warn_if_fail (g_queue_is_empty (&priv->open_queue));
1590 /* Chain up to parent's finalize() method. */
1591 G_OBJECT_CLASS (e_data_book_parent_class)->finalize (object);
1595 data_book_constructed (GObject *object)
1597 EDataBook *book = E_DATA_BOOK (object);
1600 /* Chain up to parent's constructed() method. */
1601 G_OBJECT_CLASS (e_data_book_parent_class)->constructed (object);
1603 g_object_bind_property (
1604 book->priv->backend, "cache-dir",
1605 book->priv->dbus_interface, "cache-dir",
1606 G_BINDING_SYNC_CREATE);
1608 g_object_bind_property (
1609 book->priv->backend, "online",
1610 book->priv->dbus_interface, "online",
1611 G_BINDING_SYNC_CREATE);
1613 g_object_bind_property (
1614 book->priv->backend, "writable",
1615 book->priv->dbus_interface, "writable",
1616 G_BINDING_SYNC_CREATE);
1618 /* XXX Initialize the rest of the properties by faking client
1619 * requests. At present it's the only way to fish values
1620 * from EBookBackend's antiquated API. */
1622 op = op_new (OP_GET_BACKEND_PROPERTY, book, NULL);
1623 op->d.prop_name = CLIENT_BACKEND_PROPERTY_CAPABILITIES;
1624 e_book_backend_get_backend_property (
1625 book->priv->backend, book, op->id,
1626 op->cancellable, op->d.prop_name);
1629 op = op_new (OP_GET_BACKEND_PROPERTY, book, NULL);
1630 op->d.prop_name = CLIENT_BACKEND_PROPERTY_REVISION;
1631 e_book_backend_get_backend_property (
1632 book->priv->backend, book, op->id,
1633 op->cancellable, op->d.prop_name);
1636 op = op_new (OP_GET_BACKEND_PROPERTY, book, NULL);
1637 op->d.prop_name = BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
1638 e_book_backend_get_backend_property (
1639 book->priv->backend, book, op->id,
1640 op->cancellable, op->d.prop_name);
1643 op = op_new (OP_GET_BACKEND_PROPERTY, book, NULL);
1644 op->d.prop_name = BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
1645 e_book_backend_get_backend_property (
1646 book->priv->backend, book, op->id,
1647 op->cancellable, op->d.prop_name);
1652 data_book_initable_init (GInitable *initable,
1653 GCancellable *cancellable,
1658 book = E_DATA_BOOK (initable);
1660 return g_dbus_interface_skeleton_export (
1661 G_DBUS_INTERFACE_SKELETON (book->priv->dbus_interface),
1662 book->priv->connection,
1663 book->priv->object_path,
1668 e_data_book_class_init (EDataBookClass *class)
1670 GObjectClass *object_class;
1672 g_type_class_add_private (class, sizeof (EDataBookPrivate));
1674 object_class = G_OBJECT_CLASS (class);
1675 object_class->set_property = data_book_set_property;
1676 object_class->get_property = data_book_get_property;
1677 object_class->dispose = data_book_dispose;
1678 object_class->finalize = data_book_finalize;
1679 object_class->constructed = data_book_constructed;
1681 g_object_class_install_property (
1684 g_param_spec_object (
1687 "The backend driving this connection",
1688 E_TYPE_BOOK_BACKEND,
1690 G_PARAM_CONSTRUCT_ONLY |
1691 G_PARAM_STATIC_STRINGS));
1693 g_object_class_install_property (
1696 g_param_spec_object (
1699 "The GDBusConnection on which to "
1700 "export the address book interface",
1701 G_TYPE_DBUS_CONNECTION,
1703 G_PARAM_CONSTRUCT_ONLY |
1704 G_PARAM_STATIC_STRINGS));
1706 g_object_class_install_property (
1709 g_param_spec_string (
1712 "The object path at which to "
1713 "export the address book interface",
1716 G_PARAM_CONSTRUCT_ONLY |
1717 G_PARAM_STATIC_STRINGS));
1720 ops_pool = e_operation_pool_new (10, operation_thread, NULL);
1724 e_data_book_initable_init (GInitableIface *interface)
1726 interface->init = data_book_initable_init;
1730 e_data_book_init (EDataBook *ebook)
1732 EDBusAddressBook *dbus_interface;
1734 ebook->priv = E_DATA_BOOK_GET_PRIVATE (ebook);
1736 dbus_interface = e_dbus_address_book_skeleton_new ();
1737 ebook->priv->dbus_interface = dbus_interface;
1739 ebook->priv->pending_ops = g_hash_table_new_full (
1740 (GHashFunc) g_direct_hash,
1741 (GEqualFunc) g_direct_equal,
1742 (GDestroyNotify) NULL,
1743 (GDestroyNotify) op_unref);
1744 g_rec_mutex_init (&ebook->priv->pending_ops_lock);
1746 g_mutex_init (&ebook->priv->open_lock);
1749 dbus_interface, "handle-open",
1750 G_CALLBACK (data_book_handle_open_cb), ebook);
1752 dbus_interface, "handle-refresh",
1753 G_CALLBACK (data_book_handle_refresh_cb), ebook);
1755 dbus_interface, "handle-get-contact",
1756 G_CALLBACK (data_book_handle_get_contact_cb), ebook);
1758 dbus_interface, "handle-get-contact-list",
1759 G_CALLBACK (data_book_handle_get_contact_list_cb), ebook);
1761 dbus_interface, "handle-get-contact-list-uids",
1762 G_CALLBACK (data_book_handle_get_contact_list_uids_cb), ebook);
1764 dbus_interface, "handle-create-contacts",
1765 G_CALLBACK (data_book_handle_create_contacts_cb), ebook);
1767 dbus_interface, "handle-modify-contacts",
1768 G_CALLBACK (data_book_handle_modify_contacts_cb), ebook);
1770 dbus_interface, "handle-remove-contacts",
1771 G_CALLBACK (data_book_handle_remove_contacts_cb), ebook);
1773 dbus_interface, "handle-get-view",
1774 G_CALLBACK (data_book_handle_get_view_cb), ebook);
1776 dbus_interface, "handle-close",
1777 G_CALLBACK (data_book_handle_close_cb), ebook);
1782 * @backend: an #EBookBackend
1783 * @connection: a #GDBusConnection
1784 * @object_path: object path for the D-Bus interface
1785 * @error: return location for a #GError, or %NULL
1787 * Creates a new #EDataBook and exports the AddressBook D-Bus interface
1788 * on @connection at @object_path. The #EDataBook handles incoming remote
1789 * method invocations and forwards them to the @backend. If the AddressBook
1790 * interface fails to export, the function sets @error and returns %NULL.
1792 * Returns: an #EDataBook, or %NULL on error
1795 e_data_book_new (EBookBackend *backend,
1796 GDBusConnection *connection,
1797 const gchar *object_path,
1800 g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), NULL);
1801 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1802 g_return_val_if_fail (object_path != NULL, NULL);
1804 return g_initable_new (
1805 E_TYPE_DATA_BOOK, NULL, error,
1807 "connection", connection,
1808 "object-path", object_path,
1813 * e_data_book_get_backend:
1814 * @book: an #EDataBook
1816 * Returns the #EBookBackend to which incoming remote method invocations
1817 * are being forwarded.
1819 * Returns: the #EBookBackend
1822 e_data_book_get_backend (EDataBook *book)
1824 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
1826 return book->priv->backend;
1830 * e_data_book_get_connection:
1831 * @book: an #EDataBook
1833 * Returns the #GDBusConnection on which the AddressBook D-Bus interface
1836 * Returns: the #GDBusConnection
1841 e_data_book_get_connection (EDataBook *book)
1843 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
1845 return book->priv->connection;
1849 * e_data_book_get_object_path:
1850 * @book: an #EDataBook
1852 * Returns the object path at which the AddressBook D-Bus interface is
1855 * Returns: the object path
1860 e_data_book_get_object_path (EDataBook *book)
1862 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
1864 return book->priv->object_path;