[evolution-data-server/wip/mcrha/libical-glib] Change libebook and libedata-book APIs



commit cc642781e42c02c975f6bd516fba751726bc1e74
Author: Milan Crha <mcrha redhat com>
Date:   Thu Apr 25 14:54:04 2019 +0200

    Change libebook and libedata-book APIs
    
    Namely:
     * Split EBookBackend into EBookBackend and EBookBackendSync
       - It includes also some API changes to avoid unnecessary conversions
         of strings into EContact, or GSList into GQueue and then back to GSList.
    
     * Replace EDataBookStatus with EClientError and EBookClientError
       - The EDataBookStatus had been only an "error wrapper" on the backend side,
         which had been transformed into an EClientError or EBookClientError before
         being passed through D-Bus. Better to avoid it and use the client errors
         directly.
    
     * Change API to be able to pass flags into create/modify/remove operations

 CMakeLists.txt                                     |   8 +-
 .../evolution-data-server-docs.sgml.in             |   4 +-
 po/POTFILES.in                                     |   2 +-
 .../backends/carddav/e-book-backend-carddav.c      |  35 +-
 .../file/e-book-backend-file-migrate-bdb.c         |  15 +-
 .../backends/file/e-book-backend-file.c            | 214 +++---
 .../backends/file/e-book-backend-file.h            |   4 +-
 .../backends/google/e-book-backend-google.c        |  77 +--
 .../backends/ldap/e-book-backend-ldap.c            | 339 +++++-----
 src/addressbook/libebook-contacts/CMakeLists.txt   |   7 +-
 .../libebook-contacts/e-book-contacts-enums.h      | 148 +++++
 .../libebook-contacts/e-book-contacts-types.c      |  73 ---
 .../libebook-contacts/e-book-contacts-types.h      | 312 ---------
 .../libebook-contacts/e-book-contacts-utils.c      | 168 +++++
 .../libebook-contacts/e-book-contacts-utils.h      | 175 +++++
 .../e-source-backend-summary-setup.h               |   2 +-
 .../libebook-contacts/libebook-contacts.h          |   5 +-
 src/addressbook/libebook/e-book-client.c           | 173 +++--
 src/addressbook/libebook/e-book-client.h           |  22 +-
 src/addressbook/libebook/e-book-view.c             |  17 +-
 src/addressbook/libebook/e-book.c                  |  58 +-
 src/addressbook/libedata-book/CMakeLists.txt       |  14 +-
 .../libedata-book/e-book-backend-sync.c            | 585 +++++++++++++++++
 .../libedata-book/e-book-backend-sync.h            | 194 ++++++
 src/addressbook/libedata-book/e-book-backend.c     | 726 +++------------------
 src/addressbook/libedata-book/e-book-backend.h     |  96 +--
 src/addressbook/libedata-book/e-book-cache.c       | 196 +++++-
 src/addressbook/libedata-book/e-book-cache.h       |  26 +-
 .../libedata-book/e-book-meta-backend.c            | 242 +++----
 .../libedata-book/e-book-meta-backend.h            |  10 +-
 src/addressbook/libedata-book/e-data-book.c        | 360 ++--------
 src/addressbook/libedata-book/e-data-book.h        |  32 +-
 src/addressbook/libedata-book/libedata-book.h      |   3 +-
 .../backends/contacts/e-cal-backend-contacts.c     |   1 -
 src/calendar/backends/file/e-cal-backend-file.c    |   6 +-
 .../backends/weather/e-cal-backend-weather.c       |   1 -
 src/calendar/libedata-cal/e-cal-backend-sync.c     |  10 +-
 src/calendar/libedata-cal/e-cal-backend-sync.h     |   2 -
 src/calendar/libedata-cal/e-cal-backend.c          |   2 +-
 src/calendar/libedata-cal/e-cal-backend.h          |   3 +-
 src/calendar/libedata-cal/e-cal-meta-backend.c     |   1 -
 src/examples/cursor/cursor-data.c                  |   2 +-
 src/libedataserver/e-client.c                      |  16 +-
 .../org.gnome.evolution.dataserver.AddressBook.xml |   3 +
 tests/book-migration/setup-migration-test.c        |   2 +-
 tests/book-migration/test-migration.c              |   4 +-
 tests/libebook/client/client-test-utils.c          |   4 +-
 .../client/test-book-client-add-and-get-async.c    |   2 +-
 .../libebook/client/test-book-client-add-contact.c |   2 +-
 .../client/test-book-client-cursor-operations.c    |  15 +-
 .../client/test-book-client-custom-summary.c       |   2 +-
 .../libebook/client/test-book-client-e164-param.c  |   2 +-
 .../client/test-book-client-get-revision.c         |   2 +-
 .../client/test-book-client-modify-contact.c       |   4 +-
 .../client/test-book-client-photo-is-uri.c         |   8 +-
 .../client/test-book-client-preserve-uid.c         |   4 +-
 .../test-book-client-remove-contact-by-uid.c       |   4 +-
 .../client/test-book-client-remove-contact.c       |   6 +-
 .../client/test-book-client-remove-contacts.c      |   4 +-
 tests/libebook/client/test-book-client-self.c      |   2 +-
 .../libebook/client/test-book-client-write-write.c |   2 +-
 .../test-book-cache-cursor-calculate.c             |  12 +-
 tests/libedata-book/test-book-cache-offline.c      |  89 ++-
 tests/libedata-book/test-book-cache-utils.c        |   4 +-
 tests/libedata-book/test-book-meta-backend.c       | 275 ++++----
 65 files changed, 2544 insertions(+), 2294 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8f4eafcd8..efa2f8016 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,7 +40,7 @@ set(PROJECT_DISTCONFIGURE_PARAMS
 # D-Bus versioning
 # ******************************
 # Actual name can be modified with DBUS_SERVICES_PREFIX option
-set(ADDRESS_BOOK_DBUS_SERVICE_NAME     "org.gnome.evolution.dataserver.AddressBook9")
+set(ADDRESS_BOOK_DBUS_SERVICE_NAME     "org.gnome.evolution.dataserver.AddressBook10")
 set(CALENDAR_DBUS_SERVICE_NAME         "org.gnome.evolution.dataserver.Calendar8")
 set(SOURCES_DBUS_SERVICE_NAME          "org.gnome.evolution.dataserver.Sources5")
 set(USER_PROMPTER_DBUS_SERVICE_NAME    "org.gnome.evolution.dataserver.UserPrompter0")
@@ -64,15 +64,15 @@ set(LIBEDATASERVERUI_CURRENT 2)
 set(LIBEDATASERVERUI_REVISION 0)
 set(LIBEDATASERVERUI_AGE 0)
 
-set(LIBEBOOK_CURRENT 19)
+set(LIBEBOOK_CURRENT 20)
 set(LIBEBOOK_REVISION 1)
 set(LIBEBOOK_AGE 3)
 
-set(LIBEBOOK_CONTACTS_CURRENT 2)
+set(LIBEBOOK_CONTACTS_CURRENT 3)
 set(LIBEBOOK_CONTACTS_REVISION 0)
 set(LIBEBOOK_CONTACTS_AGE 0)
 
-set(LIBEDATABOOK_CURRENT 25)
+set(LIBEDATABOOK_CURRENT 26)
 set(LIBEDATABOOK_REVISION 0)
 set(LIBEDATABOOK_AGE 0)
 
diff --git a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in 
b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
index f3834222c..1f9d0318a 100644
--- a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
+++ b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
@@ -195,6 +195,7 @@
     <chapter>
       <title>Addressbook Backend Classes</title>
       <xi:include href="xml/e-book-backend.xml"/>
+      <xi:include href="xml/e-book-backend-sync.xml"/>
       <xi:include href="xml/e-book-backend-factory.xml"/>
       <xi:include href="xml/e-book-backend-sexp.xml"/>
       <xi:include href="xml/e-book-cache.xml"/>
@@ -282,7 +283,8 @@
 
     <chapter>
       <title>Addressbook related utilities</title>
-      <xi:include href="xml/e-book-contacts-types.xml"/>
+      <xi:include href="xml/e-book-contacts-enums.xml"/>
+      <xi:include href="xml/e-book-contacts-utils.xml"/>
       <xi:include href="xml/e-destination.xml"/>
       <xi:include href="xml/e-address-western.xml"/>
       <xi:include href="xml/e-name-western.xml"/>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0e1a75036..98382fb63 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,7 +7,7 @@ src/addressbook/backends/file/e-book-backend-file-migrate-bdb.c
 src/addressbook/backends/google/e-book-backend-google.c
 src/addressbook/backends/google/e-book-google-utils.c
 src/addressbook/backends/ldap/e-book-backend-ldap.c
-src/addressbook/libebook-contacts/e-book-contacts-types.c
+src/addressbook/libebook-contacts/e-book-contacts-utils.c
 src/addressbook/libebook-contacts/e-contact.c
 src/addressbook/libebook-contacts/e-phone-number.c
 src/addressbook/libebook/e-book.c
diff --git a/src/addressbook/backends/carddav/e-book-backend-carddav.c 
b/src/addressbook/backends/carddav/e-book-backend-carddav.c
index cfd44e701..e0ba6b5f8 100644
--- a/src/addressbook/backends/carddav/e-book-backend-carddav.c
+++ b/src/addressbook/backends/carddav/e-book-backend-carddav.c
@@ -32,8 +32,9 @@
 
 #define E_WEBDAV_X_ETAG "X-EVOLUTION-WEBDAV-ETAG"
 
-#define EDB_ERROR(_code) e_data_book_create_error (_code, NULL)
-#define EDB_ERROR_EX(_code, _msg) e_data_book_create_error (_code, _msg)
+#define EC_ERROR(_code) e_client_error_create (_code, NULL)
+#define EC_ERROR_EX(_code, _msg) e_client_error_create (_code, _msg)
+#define EBC_ERROR(_code) e_book_client_error_create (_code, NULL)
 
 struct _EBookBackendCardDAVPrivate {
        /* The main WebDAV session  */
@@ -566,6 +567,7 @@ ebb_carddav_search_changes_cb (EBookCache *book_cache,
                               const gchar *revision,
                               const gchar *object,
                               const gchar *extra,
+                              guint32 custom_flags,
                               EOfflineState offline_state,
                               gpointer user_data)
 {
@@ -610,19 +612,19 @@ ebb_carddav_check_credentials_error (EBookBackendCardDAV *bbdav,
        g_return_if_fail (E_IS_BOOK_BACKEND_CARDDAV (bbdav));
 
        if (g_error_matches (op_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) && webdav) {
-               op_error->domain = E_DATA_BOOK_ERROR;
-               op_error->code = E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE;
+               op_error->domain = E_CLIENT_ERROR;
+               op_error->code = E_CLIENT_ERROR_TLS_NOT_AVAILABLE;
        } else if (g_error_matches (op_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) ||
                   g_error_matches (op_error, SOUP_HTTP_ERROR, SOUP_STATUS_FORBIDDEN)) {
-               op_error->domain = E_DATA_BOOK_ERROR;
-               op_error->code = E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED;
+               op_error->domain = E_CLIENT_ERROR;
+               op_error->code = E_CLIENT_ERROR_AUTHENTICATION_REQUIRED;
 
                if (webdav) {
                        ENamedParameters *credentials;
 
                        credentials = e_soup_session_dup_credentials (E_SOUP_SESSION (webdav));
                        if (credentials && e_named_parameters_count (credentials) > 0)
-                               op_error->code = E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED;
+                               op_error->code = E_CLIENT_ERROR_AUTHENTICATION_FAILED;
 
                        e_named_parameters_free (credentials);
                }
@@ -982,7 +984,7 @@ ebb_carddav_load_contact_sync (EBookMetaBackend *meta_backend,
                                g_free (last_sync_tag);
                                g_free (new_sync_tag);
 
-                               g_propagate_error (error, EDB_ERROR (E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND));
+                               g_propagate_error (error, EBC_ERROR (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND));
 
                                return FALSE;
                        }
@@ -1033,11 +1035,11 @@ ebb_carddav_load_contact_sync (EBookMetaBackend *meta_backend,
                        success = FALSE;
 
                        if (!href)
-                               g_propagate_error (&local_error, EDB_ERROR_EX 
(E_DATA_BOOK_STATUS_OTHER_ERROR, _("Server didn’t return object’s href")));
+                               g_propagate_error (&local_error, EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, 
_("Server didn’t return object’s href")));
                        else if (!etag)
-                               g_propagate_error (&local_error, EDB_ERROR_EX 
(E_DATA_BOOK_STATUS_OTHER_ERROR, _("Server didn’t return object’s ETag")));
+                               g_propagate_error (&local_error, EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, 
_("Server didn’t return object’s ETag")));
                        else
-                               g_propagate_error (&local_error, EDB_ERROR_EX 
(E_DATA_BOOK_STATUS_OTHER_ERROR, _("Received object is not a valid vCard")));
+                               g_propagate_error (&local_error, EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, 
_("Received object is not a valid vCard")));
                } else if (out_extra) {
                        *out_extra = g_strdup (href);
                }
@@ -1064,6 +1066,7 @@ ebb_carddav_save_contact_sync (EBookMetaBackend *meta_backend,
                               EConflictResolution conflict_resolution,
                               /* const */ EContact *contact,
                               const gchar *extra,
+                              guint32 opflags,
                               gchar **out_new_uid,
                               gchar **out_new_extra,
                               GCancellable *cancellable,
@@ -1146,10 +1149,11 @@ ebb_carddav_save_contact_sync (EBookMetaBackend *meta_backend,
                g_free (new_etag);
        } else if (uid && vcard_string) {
                success = FALSE;
-               g_propagate_error (error, EDB_ERROR_EX (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Missing 
information about vCard URL, local cache is possibly incomplete or broken. Remove it, please.")));
+               g_propagate_error (error, EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR,
+                       _("Missing information about vCard URL, local cache is possibly incomplete or broken. 
Remove it, please.")));
        } else {
                success = FALSE;
-               g_propagate_error (error, EDB_ERROR_EX (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Object to save is 
not a valid vCard")));
+               g_propagate_error (error, EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, _("Object to save is not a 
valid vCard")));
        }
 
        g_free (vcard_string);
@@ -1173,6 +1177,7 @@ ebb_carddav_remove_contact_sync (EBookMetaBackend *meta_backend,
                                 const gchar *uid,
                                 const gchar *extra,
                                 const gchar *object,
+                                guint32 opflags,
                                 GCancellable *cancellable,
                                 GError **error)
 {
@@ -1190,13 +1195,13 @@ ebb_carddav_remove_contact_sync (EBookMetaBackend *meta_backend,
        bbdav = E_BOOK_BACKEND_CARDDAV (meta_backend);
 
        if (!extra || !*extra) {
-               g_propagate_error (error, EDB_ERROR (E_DATA_BOOK_STATUS_INVALID_ARG));
+               g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_INVALID_ARG));
                return FALSE;
        }
 
        contact = e_contact_new_from_vcard (object);
        if (!contact) {
-               g_propagate_error (error, EDB_ERROR (E_DATA_BOOK_STATUS_INVALID_ARG));
+               g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_INVALID_ARG));
                return FALSE;
        }
 
diff --git a/src/addressbook/backends/file/e-book-backend-file-migrate-bdb.c 
b/src/addressbook/backends/file/e-book-backend-file-migrate-bdb.c
index 38b7a13f0..c9e9503e4 100644
--- a/src/addressbook/backends/file/e-book-backend-file-migrate-bdb.c
+++ b/src/addressbook/backends/file/e-book-backend-file-migrate-bdb.c
@@ -46,8 +46,9 @@
 #define E_BOOK_BACKEND_FILE_VERSION_NAME          "PAS-DB-VERSION"
 #define E_BOOK_BACKEND_FILE_LAST_BDB_VERSION      "0.2"
 
-#define EDB_ERROR(_code)          e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, NULL)
-#define EDB_ERROR_EX(_code, _msg) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, _msg)
+#define EC_ERROR(_code)          e_client_error_create (_code, NULL)
+#define EC_ERROR_EX(_code, _msg) e_client_error_create (_code, _msg)
+#define EBC_ERROR(_code)         e_book_client_error_create (_code, NULL)
 
 G_LOCK_DEFINE_STATIC (db_env);
 static DB_ENV *db_env = NULL;
@@ -132,16 +133,16 @@ db_error_to_gerror (const gint db_error,
        case 0:
                return;
        case DB_NOTFOUND:
-               g_propagate_error (perror, EDB_ERROR (CONTACT_NOT_FOUND));
+               g_propagate_error (perror, EBC_ERROR (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND));
                return;
        case EACCES:
-               g_propagate_error (perror, EDB_ERROR (PERMISSION_DENIED));
+               g_propagate_error (perror, EC_ERROR (E_CLIENT_ERROR_PERMISSION_DENIED));
                return;
        default:
                g_propagate_error (
                        perror,
-                       e_data_book_create_error_fmt (
-                               E_DATA_BOOK_STATUS_OTHER_ERROR,
+                       e_client_error_create_fmt (
+                               E_CLIENT_ERROR_OTHER_ERROR,
                                "db error 0x%x (%s)", db_error,
                                db_strerror (db_error) ?
                                        db_strerror (db_error) :
@@ -510,7 +511,7 @@ e_book_backend_file_migrate_bdb (EBookSqlite *sqlitedb,
 
        /* Try another upgrade */
        if (!e_book_backend_file_maybe_upgrade_db (db)) {
-               g_propagate_error (error, EDB_ERROR_EX (OTHER_ERROR, "e_book_backend_file_maybe_upgrade_db 
failed"));
+               g_propagate_error (error, EC_ERROR_EX (E_CLIENT_ERROR_OTHER_ERROR, 
"e_book_backend_file_maybe_upgrade_db failed"));
                goto close_db;
        }
 
diff --git a/src/addressbook/backends/file/e-book-backend-file.c 
b/src/addressbook/backends/file/e-book-backend-file.c
index a40d0146c..0a44e900a 100644
--- a/src/addressbook/backends/file/e-book-backend-file.c
+++ b/src/addressbook/backends/file/e-book-backend-file.c
@@ -70,7 +70,7 @@ static void   e_book_backend_file_initable_init
 G_DEFINE_TYPE_WITH_CODE (
        EBookBackendFile,
        e_book_backend_file,
-       E_TYPE_BOOK_BACKEND,
+       E_TYPE_BOOK_BACKEND_SYNC,
        G_IMPLEMENT_INTERFACE (
                G_TYPE_INITABLE,
                e_book_backend_file_initable_init))
@@ -698,7 +698,7 @@ e_book_backend_file_bump_revision (EBookBackendFile *bf,
                bf->priv->revision = new_revision;
 
                e_book_backend_notify_property_changed (E_BOOK_BACKEND (bf),
-                                                       BOOK_BACKEND_PROPERTY_REVISION,
+                                                       E_BOOK_BACKEND_PROPERTY_REVISION,
                                                        bf->priv->revision);
        } else {
                g_free (new_revision);
@@ -797,12 +797,11 @@ cursors_contact_removed (EBookBackendFile *bf,
 static gboolean
 do_create (EBookBackendFile *bf,
            const gchar * const *vcards,
-           GQueue *out_contacts,
+           GSList **out_contacts,
            GCancellable *cancellable,
            GError **error)
 {
        PhotoModifiedStatus status = STATUS_NORMAL;
-       GQueue queue = G_QUEUE_INIT;
        guint ii, length;
        GError *local_error = NULL;
 
@@ -831,7 +830,7 @@ do_create (EBookBackendFile *bf,
                if (status != STATUS_ERROR) {
 
                        /* Contact was added successfully. */
-                       g_queue_push_tail (&queue, contact);
+                       *out_contacts = g_slist_prepend (*out_contacts, contact);
                } else {
                        /* Contact could not be transformed */
                        g_warning (
@@ -846,16 +845,10 @@ do_create (EBookBackendFile *bf,
        }
 
        if (status != STATUS_ERROR) {
-               GList *tail, *link;
-               GSList *slist = NULL, *l;
-
-               /* EBookSqlite uses GSList. */
-               tail = g_queue_peek_tail_link (&queue);
-               for (link = tail; link != NULL; link = g_list_previous (link))
-                       slist = g_slist_prepend (slist, link->data);
+               GSList *link;
 
                if (!e_book_sqlite_add_contacts (bf->priv->sqlitedb,
-                                                slist, NULL, FALSE,
+                                                *out_contacts, NULL, FALSE,
                                                 cancellable,
                                                 &local_error)) {
 
@@ -876,19 +869,11 @@ do_create (EBookBackendFile *bf,
                }
 
                /* After adding any contacts, notify any cursors that the new contacts are added */
-               for (l = slist; l; l = l->next) {
-                       cursors_contact_added (bf, E_CONTACT (l->data));
+               for (link = *out_contacts; link; link = g_slist_next (link)) {
+                       cursors_contact_added (bf, link->data);
                }
-
-               g_slist_free (slist);
        }
 
-       if (status != STATUS_ERROR && out_contacts != NULL)
-               e_queue_transfer (&queue, out_contacts);
-
-       while (!g_queue_is_empty (&queue))
-               g_object_unref (g_queue_pop_head (&queue));
-
        return (status != STATUS_ERROR);
 }
 
@@ -1111,10 +1096,10 @@ book_backend_file_get_backend_property (EBookBackend *backend,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return g_strdup ("local,do-initial-query,bulk-adds,bulk-modifies,bulk-removes,contact-lists");
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                return g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                GString *fields;
                gint ii;
 
@@ -1130,7 +1115,7 @@ book_backend_file_get_backend_property (EBookBackend *backend,
 
                return g_string_free (fields, FALSE);
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REVISION)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REVISION)) {
                gchar *prop_value;
 
                g_rw_lock_reader_lock (&(bf->priv->lock));
@@ -1146,7 +1131,7 @@ book_backend_file_get_backend_property (EBookBackend *backend,
 }
 
 static gboolean
-book_backend_file_open_sync (EBookBackend *backend,
+book_backend_file_open_sync (EBookBackendSync *backend,
                              GCancellable *cancellable,
                              GError **error)
 {
@@ -1169,7 +1154,7 @@ book_backend_file_open_sync (EBookBackend *backend,
                e_book_backend_file_load_revision (bf);
                e_book_backend_notify_property_changed (
                        E_BOOK_BACKEND (backend),
-                       BOOK_BACKEND_PROPERTY_REVISION,
+                       E_BOOK_BACKEND_PROPERTY_REVISION,
                        bf->priv->revision);
        }
        g_rw_lock_writer_unlock (&(bf->priv->lock));
@@ -1181,15 +1166,20 @@ book_backend_file_open_sync (EBookBackend *backend,
 }
 
 static gboolean
-book_backend_file_create_contacts_sync (EBookBackend *backend,
-                                        const gchar * const *vcards,
-                                        GQueue *out_contacts,
-                                        GCancellable *cancellable,
-                                        GError **error)
+book_backend_file_create_contacts_sync (EBookBackendSync *backend,
+                                       const gchar * const *vcards,
+                                       guint32 opflags,
+                                       GSList **out_contacts,
+                                       GCancellable *cancellable,
+                                       GError **error)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
        gboolean success = FALSE;
 
+       g_return_val_if_fail (out_contacts != NULL, FALSE);
+
+       *out_contacts = NULL;
+
        g_rw_lock_writer_lock (&(bf->priv->lock));
        if (!e_book_sqlite_lock (bf->priv->sqlitedb,
                                 EBSQL_LOCK_WRITE,
@@ -1200,6 +1190,13 @@ book_backend_file_create_contacts_sync (EBookBackend *backend,
 
        success = do_create (bf, vcards, out_contacts, cancellable, error);
 
+       if (success) {
+               *out_contacts = g_slist_reverse (*out_contacts);
+       } else {
+               g_slist_free_full (*out_contacts, g_object_unref);
+               *out_contacts = NULL;
+       }
+
        if (success)
                success = e_book_backend_file_bump_revision (bf, error);
 
@@ -1232,18 +1229,18 @@ book_backend_file_create_contacts_sync (EBookBackend *backend,
 }
 
 static gboolean
-book_backend_file_modify_contacts_sync (EBookBackend *backend,
-                                        const gchar * const *vcards,
-                                        GQueue *out_contacts,
-                                        GCancellable *cancellable,
-                                        GError **error)
+book_backend_file_modify_contacts_sync (EBookBackendSync *backend,
+                                       const gchar * const *vcards,
+                                       guint32 opflags,
+                                       GSList **out_contacts,
+                                       GCancellable *cancellable,
+                                       GError **error)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
        GSList           *ids = NULL;
        GError           *local_error = NULL;
        PhotoModifiedStatus status = STATUS_NORMAL;
-       GQueue old_contact_queue = G_QUEUE_INIT;
-       GQueue mod_contact_queue = G_QUEUE_INIT;
+       GSList *old_contacts = NULL;
        guint ii, length;
 
        length = g_strv_length ((gchar **) vcards);
@@ -1325,42 +1322,33 @@ book_backend_file_modify_contacts_sync (EBookBackend *backend,
                /* update the revision (modified time of contact) */
                set_revision (bf, mod_contact);
 
-               g_queue_push_tail (&old_contact_queue, old_contact);
-               g_queue_push_tail (&mod_contact_queue, mod_contact);
+               old_contacts = g_slist_prepend (old_contacts, old_contact);
+               *out_contacts = g_slist_prepend (*out_contacts, mod_contact);
 
                ids = g_slist_prepend (ids, id);
        }
 
        if (status != STATUS_ERROR) {
-               GList *old_link;
-               GList *mod_link;
-               GSList *slist = NULL;
+               GSList *old_link, *mod_link;
 
                /* Delete old photo file uris if need be (this will compare the new contact
                 * with the current copy in the BDB to extract the uris to delete) */
-               old_link = g_queue_peek_head_link (&old_contact_queue);
-               mod_link = g_queue_peek_head_link (&mod_contact_queue);
+               old_link = old_contacts;
+               mod_link = *out_contacts;
 
                while (old_link != NULL && mod_link != NULL) {
                        maybe_delete_unused_uris (
                                bf,
                                E_CONTACT (old_link->data),
                                E_CONTACT (mod_link->data));
-                       old_link = g_list_next (old_link);
-                       mod_link = g_list_next (mod_link);
-               }
-
-               /* EBookSqlite uses GSList. */
-               mod_link = g_queue_peek_tail_link (&mod_contact_queue);
-               while (mod_link != NULL) {
-                       slist = g_slist_prepend (slist, mod_link->data);
-                       mod_link = g_list_previous (mod_link);
+                       old_link = g_slist_next (old_link);
+                       mod_link = g_slist_next (mod_link);
                }
 
                /* Update summary as well */
                e_book_sqlite_add_contacts (
                        bf->priv->sqlitedb,
-                       slist, NULL, TRUE,
+                       *out_contacts, NULL, TRUE,
                        cancellable, &local_error);
 
                if (local_error != NULL) {
@@ -1372,8 +1360,6 @@ book_backend_file_modify_contacts_sync (EBookBackend *backend,
 
                        status = STATUS_ERROR;
                }
-
-               g_slist_free (slist);
        }
 
        /* Bump the revision atomically in the same transaction */
@@ -1409,43 +1395,42 @@ book_backend_file_modify_contacts_sync (EBookBackend *backend,
                }
        }
 
-       if (status != STATUS_ERROR)
-               e_queue_transfer (&mod_contact_queue, out_contacts);
+       if (status != STATUS_ERROR) {
+               *out_contacts = g_slist_reverse (*out_contacts);
+       } else {
+               g_slist_free_full (*out_contacts, g_object_unref);
+               *out_contacts = NULL;
+       }
 
        /* Now that we've modified the contact(s),
         * notify cursors of the changes. */
        if (status != STATUS_ERROR) {
-               GList *l;
+               GSList *link;
 
-               for (l = g_queue_peek_head_link (&old_contact_queue);
-                    l; l = l->next) {
-                       cursors_contact_removed (bf, E_CONTACT (l->data));
+               for (link = old_contacts; link; link = g_slist_next (link)) {
+                       cursors_contact_removed (bf, E_CONTACT (link->data));
                }
 
-               for (l = g_queue_peek_head_link (&mod_contact_queue);
-                    l; l = l->next) {
-                       cursors_contact_added (bf, E_CONTACT (l->data));
+               for (link = *out_contacts; link; link = g_slist_next (*out_contacts)) {
+                       cursors_contact_added (bf, E_CONTACT (link->data));
                }
        }
 
        g_rw_lock_writer_unlock (&(bf->priv->lock));
 
-       while (!g_queue_is_empty (&old_contact_queue))
-               g_object_unref (g_queue_pop_head (&old_contact_queue));
-
-       while (!g_queue_is_empty (&mod_contact_queue))
-               g_object_unref (g_queue_pop_head (&mod_contact_queue));
-
-       g_slist_free_full (ids, (GDestroyNotify) g_free);
+       g_slist_free_full (old_contacts, g_object_unref);
+       g_slist_free_full (ids, g_free);
 
        return (status != STATUS_ERROR);
 }
 
 static gboolean
-book_backend_file_remove_contacts_sync (EBookBackend *backend,
-                                        const gchar * const *uids,
-                                        GCancellable *cancellable,
-                                        GError **error)
+book_backend_file_remove_contacts_sync (EBookBackendSync *backend,
+                                       const gchar * const *uids,
+                                       guint32 opflags,
+                                       GSList **out_removed_uids,
+                                       GCancellable *cancellable,
+                                       GError **error)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
        GSList           *removed_ids = NULL, *removed_contacts = NULL;
@@ -1454,6 +1439,8 @@ book_backend_file_remove_contacts_sync (EBookBackend *backend,
        gboolean success = TRUE;
        guint ii, length;
 
+       g_return_val_if_fail (out_removed_uids != NULL, FALSE);
+
        length = g_strv_length ((gchar **) uids);
 
        g_rw_lock_writer_lock (&(bf->priv->lock));
@@ -1540,16 +1527,17 @@ book_backend_file_remove_contacts_sync (EBookBackend *backend,
                }
        }
 
+       *out_removed_uids = removed_ids;
+
        g_rw_lock_writer_unlock (&(bf->priv->lock));
 
-       g_slist_free_full (removed_ids, (GDestroyNotify) g_free);
        g_slist_free_full (removed_contacts, (GDestroyNotify) g_object_unref);
 
        return success;
 }
 
 static EContact *
-book_backend_file_get_contact_sync (EBookBackend *backend,
+book_backend_file_get_contact_sync (EBookBackendSync *backend,
                                     const gchar *uid,
                                     GCancellable *cancellable,
                                     GError **error)
@@ -1583,9 +1571,9 @@ book_backend_file_get_contact_sync (EBookBackend *backend,
 }
 
 static gboolean
-book_backend_file_get_contact_list_sync (EBookBackend *backend,
+book_backend_file_get_contact_list_sync (EBookBackendSync *backend,
                                          const gchar *query,
-                                         GQueue *out_contacts,
+                                         GSList **out_contacts,
                                          GCancellable *cancellable,
                                          GError **error)
 {
@@ -1595,6 +1583,10 @@ book_backend_file_get_contact_list_sync (EBookBackend *backend,
        gboolean success = TRUE;
        GError *local_error = NULL;
 
+       g_return_val_if_fail (out_contacts != NULL, FALSE);
+
+       *out_contacts = NULL;
+
        d (printf ("book_backend_file_get_contact_list_sync (%s)\n", query));
 
        g_rw_lock_reader_lock (&(bf->priv->lock));
@@ -1656,29 +1648,31 @@ book_backend_file_get_contact_list_sync (EBookBackend *backend,
                EContact *contact;
 
                contact = e_contact_new_from_vcard (data->vcard);
-               g_queue_push_tail (out_contacts, contact);
+               link->data = contact;
+
+               e_book_sqlite_search_data_free (data);
        }
 
-       g_slist_free_full (
-               summary_list, (GDestroyNotify)
-               e_book_sqlite_search_data_free);
+       *out_contacts = summary_list;
 
        return success;
 }
 
 static gboolean
-book_backend_file_get_contact_list_uids_sync (EBookBackend *backend,
+book_backend_file_get_contact_list_uids_sync (EBookBackendSync *backend,
                                               const gchar *query,
-                                              GQueue *out_uids,
+                                              GSList **out_uids,
                                               GCancellable *cancellable,
                                               GError **error)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
-       GSList *uids = NULL;
-       GSList *link;
        gboolean success = TRUE;
        GError *local_error = NULL;
 
+       g_return_val_if_fail (out_uids != NULL, FALSE);
+
+       *out_uids = NULL;
+
        d (printf ("book_backend_file_get_contact_list_sync (%s)\n", query));
 
        g_rw_lock_reader_lock (&(bf->priv->lock));
@@ -1695,7 +1689,7 @@ book_backend_file_get_contact_list_uids_sync (EBookBackend *backend,
        success = e_book_sqlite_search_uids (
                bf->priv->sqlitedb,
                query,
-               &uids,
+               out_uids,
                cancellable,
                &local_error);
        e_book_sqlite_unlock (
@@ -1706,7 +1700,7 @@ book_backend_file_get_contact_list_uids_sync (EBookBackend *backend,
        g_rw_lock_reader_unlock (&(bf->priv->lock));
 
        if (!success) {
-               g_warn_if_fail (uids == NULL);
+               g_warn_if_fail (*out_uids == NULL);
 
                if (g_error_matches (local_error,
                                     E_BOOK_SQLITE_ERROR,
@@ -1734,12 +1728,6 @@ book_backend_file_get_contact_list_uids_sync (EBookBackend *backend,
                }
        }
 
-       /* Transfer UID strings to the GQueue. */
-       for (link = uids; link != NULL; link = g_slist_next (link))
-               g_queue_push_tail (out_uids, link->data);
-
-       g_slist_free (uids);
-
        return success;
 }
 
@@ -1825,16 +1813,6 @@ book_backend_file_configure_direct (EBookBackend *backend,
        priv->base_directory = g_strdup (config);
 }
 
-static void
-book_backend_file_sync (EBookBackend *backend)
-{
-       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
-
-       g_return_if_fail (bf != NULL);
-
-       /* FIXME: Tell sqlite to dump NOW ! */
-}
-
 static void
 book_backend_file_vcard_changed (EbSqlChangeType change_type,
                                  const gchar *uid,
@@ -2143,6 +2121,7 @@ e_book_backend_file_class_init (EBookBackendFileClass *class)
 {
        GObjectClass *object_class;
        EBookBackendClass *backend_class;
+       EBookBackendSyncClass *backend_sync_class;
 
        g_type_class_add_private (class, sizeof (EBookBackendFilePrivate));
 
@@ -2150,20 +2129,21 @@ e_book_backend_file_class_init (EBookBackendFileClass *class)
        object_class->dispose = book_backend_file_dispose;
        object_class->finalize = book_backend_file_finalize;
 
+       backend_sync_class = E_BOOK_BACKEND_SYNC_CLASS (class);
+       backend_sync_class->open_sync = book_backend_file_open_sync;
+       backend_sync_class->create_contacts_sync = book_backend_file_create_contacts_sync;
+       backend_sync_class->modify_contacts_sync = book_backend_file_modify_contacts_sync;
+       backend_sync_class->remove_contacts_sync = book_backend_file_remove_contacts_sync;
+       backend_sync_class->get_contact_sync = book_backend_file_get_contact_sync;
+       backend_sync_class->get_contact_list_sync = book_backend_file_get_contact_list_sync;
+       backend_sync_class->get_contact_list_uids_sync = book_backend_file_get_contact_list_uids_sync;
+
        backend_class = E_BOOK_BACKEND_CLASS (class);
        backend_class->get_backend_property = book_backend_file_get_backend_property;
-       backend_class->open_sync = book_backend_file_open_sync;
-       backend_class->create_contacts_sync = book_backend_file_create_contacts_sync;
-       backend_class->modify_contacts_sync = book_backend_file_modify_contacts_sync;
-       backend_class->remove_contacts_sync = book_backend_file_remove_contacts_sync;
-       backend_class->get_contact_sync = book_backend_file_get_contact_sync;
-       backend_class->get_contact_list_sync = book_backend_file_get_contact_list_sync;
-       backend_class->get_contact_list_uids_sync = book_backend_file_get_contact_list_uids_sync;
        backend_class->start_view = book_backend_file_start_view;
        backend_class->stop_view = book_backend_file_stop_view;
        backend_class->get_direct_book = book_backend_file_get_direct_book;
        backend_class->configure_direct = book_backend_file_configure_direct;
-       backend_class->sync = book_backend_file_sync;
        backend_class->set_locale = book_backend_file_set_locale;
        backend_class->dup_locale = book_backend_file_dup_locale;
        backend_class->create_cursor = book_backend_file_create_cursor;
diff --git a/src/addressbook/backends/file/e-book-backend-file.h 
b/src/addressbook/backends/file/e-book-backend-file.h
index 8af35fe61..16760d573 100644
--- a/src/addressbook/backends/file/e-book-backend-file.h
+++ b/src/addressbook/backends/file/e-book-backend-file.h
@@ -54,12 +54,12 @@ typedef struct _EBookBackendFileClass EBookBackendFileClass;
 typedef struct _EBookBackendFilePrivate EBookBackendFilePrivate;
 
 struct _EBookBackendFile {
-       EBookBackend parent;
+       EBookBackendSync parent;
        EBookBackendFilePrivate *priv;
 };
 
 struct _EBookBackendFileClass {
-       EBookBackendClass parent_class;
+       EBookBackendSyncClass parent_class;
 };
 
 GType          e_book_backend_file_get_type    (void);
diff --git a/src/addressbook/backends/google/e-book-backend-google.c 
b/src/addressbook/backends/google/e-book-backend-google.c
index 4d83428f6..0008303c2 100644
--- a/src/addressbook/backends/google/e-book-backend-google.c
+++ b/src/addressbook/backends/google/e-book-backend-google.c
@@ -86,58 +86,36 @@ ebb_google_data_book_error_from_gdata_error (GError **error,
        if (gdata_error->domain == GDATA_SERVICE_ERROR) {
                switch (gdata_error->code) {
                case GDATA_SERVICE_ERROR_UNAVAILABLE:
-                       g_set_error_literal (
-                               error, E_CLIENT_ERROR,
-                               E_CLIENT_ERROR_REPOSITORY_OFFLINE,
-                               e_client_error_to_string (
-                               E_CLIENT_ERROR_REPOSITORY_OFFLINE));
+                       g_propagate_error (error,
+                               e_client_error_create (E_CLIENT_ERROR_REPOSITORY_OFFLINE, NULL));
                        break;
                case GDATA_SERVICE_ERROR_PROTOCOL_ERROR:
-                       g_set_error_literal (
-                               error, E_CLIENT_ERROR,
-                               E_CLIENT_ERROR_INVALID_QUERY,
-                               gdata_error->message);
+                       g_propagate_error (error,
+                               e_client_error_create (E_CLIENT_ERROR_INVALID_QUERY, gdata_error->message));
                        break;
                case GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED:
-                       g_set_error_literal (
-                               error, E_BOOK_CLIENT_ERROR,
-                               E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS,
-                               e_book_client_error_to_string (
-                               E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS));
+                       g_propagate_error (error,
+                               e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS, 
NULL));
                        break;
                case GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED:
-                       g_set_error_literal (
-                               error, E_CLIENT_ERROR,
-                               E_CLIENT_ERROR_AUTHENTICATION_REQUIRED,
-                               e_client_error_to_string (
-                               E_CLIENT_ERROR_AUTHENTICATION_REQUIRED));
+                       g_propagate_error (error,
+                               e_client_error_create (E_CLIENT_ERROR_AUTHENTICATION_REQUIRED, NULL));
                        break;
                case GDATA_SERVICE_ERROR_NOT_FOUND:
-                       g_set_error_literal (
-                               error, E_BOOK_CLIENT_ERROR,
-                               E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND,
-                               e_book_client_error_to_string (
-                               E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND));
+                       g_propagate_error (error,
+                               e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, NULL));
                        break;
                case GDATA_SERVICE_ERROR_CONFLICT:
-                       g_set_error_literal (
-                               error, E_BOOK_CLIENT_ERROR,
-                               E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS,
-                               e_book_client_error_to_string (
-                               E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS));
+                       g_propagate_error (error,
+                               e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS, 
NULL));
                        break;
                case GDATA_SERVICE_ERROR_FORBIDDEN:
-                       g_set_error_literal (
-                               error, E_CLIENT_ERROR,
-                               E_CLIENT_ERROR_QUERY_REFUSED,
-                               e_client_error_to_string (
-                               E_CLIENT_ERROR_QUERY_REFUSED));
+                       g_propagate_error (error,
+                               e_client_error_create (E_CLIENT_ERROR_QUERY_REFUSED, NULL));
                        break;
                case GDATA_SERVICE_ERROR_BAD_QUERY_PARAMETER:
-                       g_set_error_literal (
-                               error, E_CLIENT_ERROR,
-                               E_CLIENT_ERROR_INVALID_QUERY,
-                               gdata_error->message);
+                       g_propagate_error (error,
+                               e_client_error_create (E_CLIENT_ERROR_INVALID_QUERY, gdata_error->message));
                        break;
                default:
                        use_fallback = TRUE;
@@ -149,11 +127,10 @@ ebb_google_data_book_error_from_gdata_error (GError **error,
        }
 
        /* Generic fallback */
-       if (use_fallback)
-               g_set_error_literal (
-                       error, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_OTHER_ERROR,
-                       gdata_error->message);
+       if (use_fallback) {
+               g_propagate_error (error,
+                       e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, gdata_error->message));
+       }
 }
 
 static gboolean
@@ -935,6 +912,7 @@ ebb_google_save_contact_sync (EBookMetaBackend *meta_backend,
                              EConflictResolution conflict_resolution,
                              /* const */ EContact *contact,
                              const gchar *extra,
+                             guint32 opflags,
                              gchar **out_new_uid,
                              gchar **out_new_extra,
                              GCancellable *cancellable,
@@ -1007,7 +985,7 @@ ebb_google_save_contact_sync (EBookMetaBackend *meta_backend,
 
        if (!entry) {
                g_rec_mutex_unlock (&bbgoogle->priv->conn_lock);
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Object 
to save is not a valid vCard")));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Object to 
save is not a valid vCard")));
                return FALSE;
        }
 
@@ -1063,7 +1041,7 @@ ebb_google_save_contact_sync (EBookMetaBackend *meta_backend,
        if (!new_contact) {
                g_object_unref (gdata_contact);
                e_contact_photo_free (photo);
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed 
to create contact from returned server data")));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Failed to 
create contact from returned server data")));
                return FALSE;
        }
 
@@ -1079,7 +1057,7 @@ ebb_google_save_contact_sync (EBookMetaBackend *meta_backend,
        uid = e_contact_get_const (new_contact, E_CONTACT_UID);
 
        if (!uid) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Server 
returned contact without UID")));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Server 
returned contact without UID")));
 
                g_object_unref (new_contact);
                g_free (*out_new_extra);
@@ -1104,6 +1082,7 @@ ebb_google_remove_contact_sync (EBookMetaBackend *meta_backend,
                                const gchar *uid,
                                const gchar *extra,
                                const gchar *object,
+                               guint32 opflags,
                                GCancellable *cancellable,
                                GError **error)
 {
@@ -1117,7 +1096,7 @@ ebb_google_remove_contact_sync (EBookMetaBackend *meta_backend,
 
        entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_CONTACTS_CONTACT, extra, -1, NULL));
        if (!entry) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_ARG, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_INVALID_ARG, NULL));
                return FALSE;
        }
 
@@ -1156,10 +1135,10 @@ ebb_google_get_backend_property (EBookBackend *book_backend,
                        e_book_meta_backend_get_capabilities (E_BOOK_META_BACKEND (book_backend)),
                        NULL);
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                return g_strdup ("");
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                return g_strjoin (",",
                        e_contact_field_name (E_CONTACT_UID),
                        e_contact_field_name (E_CONTACT_REV),
diff --git a/src/addressbook/backends/ldap/e-book-backend-ldap.c 
b/src/addressbook/backends/ldap/e-book-backend-ldap.c
index 0156a5caf..6168a7a07 100644
--- a/src/addressbook/backends/ldap/e-book-backend-ldap.c
+++ b/src/addressbook/backends/ldap/e-book-backend-ldap.c
@@ -104,18 +104,14 @@ static gchar *    e_book_backend_ldap_build_query (EBookBackendLDAP *bl,
 
 typedef struct LDAPOp LDAPOp;
 
-#define EDB_ERROR(_code) \
-       (e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, NULL))
-#define EDB_ERROR_EX(_code, _msg) \
-       (e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, _msg))
+#define EC_ERROR(_code) e_client_error_create (_code, NULL)
+#define EC_ERROR_EX(_code, _msg)  e_client_error_create (_code, _msg)
+#define EBC_ERROR(_code) e_book_client_error_create (_code, NULL)
+
 /* Translators: An error message shown to a user when trying to do an
  * operation on the LDAP address book which is not connected to the server */
-#define EDB_ERROR_NOT_CONNECTED() (e_data_book_create_error (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Not 
connected")))
-#define EDB_ERROR_MSG_TYPE(_msg_type) \
-       (e_data_book_create_error_fmt ( \
-       E_DATA_BOOK_STATUS_INVALID_ARG, \
-       "Incorrect msg type %d passed to %s", \
-       _msg_type, G_STRFUNC))
+#define EC_ERROR_NOT_CONNECTED() e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Not connected"))
+#define EC_ERROR_MSG_TYPE(_msg_type) e_client_error_create_fmt (E_CLIENT_ERROR_INVALID_ARG, "Incorrect msg 
type %d passed to %s", _msg_type, G_STRFUNC)
 
 G_DEFINE_TYPE (EBookBackendLDAP, e_book_backend_ldap, E_TYPE_BOOK_BACKEND)
 
@@ -619,7 +615,7 @@ check_schema_support (EBookBackendLDAP *bl)
        }
 
        lst = e_data_book_string_slist_to_comma_string (bl->priv->supported_fields);
-       e_book_backend_notify_property_changed (E_BOOK_BACKEND (bl), BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, 
lst);
+       e_book_backend_notify_property_changed (E_BOOK_BACKEND (bl), 
E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, lst);
        g_free (lst);
 }
 
@@ -810,7 +806,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                        ldap_unbind (blpriv->ldap);
                        blpriv->ldap = NULL;
                        g_rec_mutex_unlock (&eds_ldap_handler_lock);
-                       g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE));
+                       g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_TLS_NOT_AVAILABLE));
                        return FALSE;
                }
 
@@ -846,7 +842,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                                ldap_unbind (blpriv->ldap);
                                blpriv->ldap = NULL;
                                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-                               g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE));
+                               g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_TLS_NOT_AVAILABLE));
                                return FALSE;
                        } else if (enable_debug)
                                g_message ("TLS active");
@@ -876,10 +872,8 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                                blpriv->ldap = NULL;
                        }
                        g_rec_mutex_unlock (&eds_ldap_handler_lock);
-                       g_propagate_error (
-                               error, e_data_book_create_error (
-                               E_DATA_BOOK_STATUS_OTHER_ERROR,
-                               _("Failed to bind using either v3 or v2 binds")));
+                       g_propagate_error (error,
+                               e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Failed to bind using 
either v3 or v2 binds")));
                        return FALSE;
 
                } else if (ldap_error == LDAP_SERVER_DOWN) {
@@ -890,7 +884,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                                blpriv->ldap = NULL;
                        }
                        g_rec_mutex_unlock (&eds_ldap_handler_lock);
-                       g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+                       g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
                        return FALSE;
                } else if (ldap_error == LDAP_INVALID_CREDENTIALS) {
                        g_warning ("Invalid credentials while connecting (ldap_error 0x%02x)", ldap_error);
@@ -899,7 +893,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                                blpriv->ldap = NULL;
                        }
                        g_rec_mutex_unlock (&eds_ldap_handler_lock);
-                       g_propagate_error (error, EDB_ERROR (AUTHENTICATION_FAILED));
+                       g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_AUTHENTICATION_FAILED));
                        return FALSE;
                }
 
@@ -946,7 +940,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                                blpriv->ldap = NULL;
                        }
                        g_rec_mutex_unlock (&eds_ldap_handler_lock);
-                       g_propagate_error (error, EDB_ERROR (AUTHENTICATION_FAILED));
+                       g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_AUTHENTICATION_FAILED));
                        return FALSE;
                } else {
                        if (blpriv->ldap) {
@@ -972,7 +966,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                blpriv->ldap_rootdn ? blpriv->ldap_rootdn : "");
        blpriv->connected = FALSE;
 
-       g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+       g_propagate_error (error, EC_ERROR (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
 
        return FALSE;
 }
@@ -1136,24 +1130,24 @@ static GError *
 ldap_error_to_response (gint ldap_error)
 {
        if (ldap_error == LDAP_SUCCESS)
-               return EDB_ERROR (SUCCESS);
+               return NULL;
        else if (ldap_error == LDAP_INVALID_DN_SYNTAX)
-               return e_data_book_create_error (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Invalid DN syntax"));
+               return e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Invalid DN syntax"));
        else if (LDAP_NAME_ERROR (ldap_error))
-               return EDB_ERROR (CONTACT_NOT_FOUND);
+               return EBC_ERROR (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
        else if (ldap_error == LDAP_INSUFFICIENT_ACCESS)
-               return EDB_ERROR (PERMISSION_DENIED);
+               return EC_ERROR (E_CLIENT_ERROR_PERMISSION_DENIED);
        else if (ldap_error == LDAP_STRONG_AUTH_REQUIRED)
-               return EDB_ERROR (AUTHENTICATION_REQUIRED);
+               return EC_ERROR (E_CLIENT_ERROR_AUTHENTICATION_REQUIRED);
        else if (ldap_error == LDAP_SERVER_DOWN)
-               return EDB_ERROR (REPOSITORY_OFFLINE);
+               return EC_ERROR (E_CLIENT_ERROR_REPOSITORY_OFFLINE);
        else if (ldap_error == LDAP_ALREADY_EXISTS)
-               return EDB_ERROR (CONTACTID_ALREADY_EXISTS);
+               return EBC_ERROR (E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS);
        else if (ldap_error == LDAP_TYPE_OR_VALUE_EXISTS )
-               return EDB_ERROR (CONTACTID_ALREADY_EXISTS);
+               return EBC_ERROR (E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS);
        else
-               return e_data_book_create_error_fmt (
-                       E_DATA_BOOK_STATUS_OTHER_ERROR,
+               return e_client_error_create_fmt (
+                       E_CLIENT_ERROR_OTHER_ERROR,
                        _("LDAP error 0x%x (%s)"), ldap_error,
                        ldap_err2string (ldap_error) ?
                        ldap_err2string (ldap_error) :
@@ -1529,7 +1523,7 @@ create_contact_handler (LDAPOp *op,
                e_data_book_respond_create_contacts (
                        op->book,
                        op->opid,
-                       EDB_ERROR_NOT_CONNECTED (),
+                       EC_ERROR_NOT_CONNECTED (),
                        NULL);
                ldap_op_finished (op);
                return;
@@ -1540,7 +1534,7 @@ create_contact_handler (LDAPOp *op,
                e_data_book_respond_create_contacts (
                        op->book,
                        op->opid,
-                       EDB_ERROR_MSG_TYPE (ldap_msgtype (res)),
+                       EC_ERROR_MSG_TYPE (ldap_msgtype (res)),
                        NULL);
                ldap_op_finished (op);
                return;
@@ -1600,7 +1594,7 @@ remove_contact_handler (LDAPOp *op,
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_remove_contacts (op->book, op->opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+               e_data_book_respond_remove_contacts (op->book, op->opid, EC_ERROR_NOT_CONNECTED (), NULL);
                ldap_op_finished (op);
                return;
        }
@@ -1610,7 +1604,7 @@ remove_contact_handler (LDAPOp *op,
                e_data_book_respond_remove_contacts (
                        op->book,
                        op->opid,
-                       EDB_ERROR_MSG_TYPE (ldap_msgtype (res)),
+                       EC_ERROR_MSG_TYPE (ldap_msgtype (res)),
                        NULL);
                ldap_op_finished (op);
                return;
@@ -1689,7 +1683,7 @@ modify_contact_modify_handler (LDAPOp *op,
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
                e_data_book_respond_modify_contacts (op->book,
                                                     op->opid,
-                                                    EDB_ERROR_NOT_CONNECTED (),
+                                                    EC_ERROR_NOT_CONNECTED (),
                                                     NULL);
                ldap_op_finished (op);
                return;
@@ -1699,7 +1693,7 @@ modify_contact_modify_handler (LDAPOp *op,
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
                e_data_book_respond_modify_contacts (op->book,
                                                     op->opid,
-                                                    EDB_ERROR_MSG_TYPE (ldap_msgtype (res)),
+                                                    EC_ERROR_MSG_TYPE (ldap_msgtype (res)),
                                                     NULL);
                ldap_op_finished (op);
                return;
@@ -1744,7 +1738,7 @@ modify_contact_search_handler (LDAPOp *op,
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
                e_data_book_respond_modify_contacts (op->book, op->opid,
-                                                    EDB_ERROR_NOT_CONNECTED (), NULL);
+                                                    EC_ERROR_NOT_CONNECTED (), NULL);
                ldap_op_finished (op);
                return;
        }
@@ -1768,10 +1762,8 @@ modify_contact_search_handler (LDAPOp *op,
                if (!e) {
                        e_data_book_respond_modify_contacts (
                                op->book, op->opid,
-                               e_data_book_create_error_fmt (
-                                       E_DATA_BOOK_STATUS_OTHER_ERROR,
-                                       _("%s: NULL returned from ldap_first_entry"),
-                                       G_STRFUNC),
+                               e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR,
+                                       _("%s: NULL returned from ldap_first_entry"), G_STRFUNC),
                                NULL);
                        ldap_op_finished (op);
                        return;
@@ -1909,7 +1901,7 @@ modify_contact_rename_handler (LDAPOp *op,
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
                e_data_book_respond_modify_contacts (op->book,
                                                     op->opid,
-                                                    EDB_ERROR_NOT_CONNECTED (),
+                                                    EC_ERROR_NOT_CONNECTED (),
                                                     NULL);
                ldap_op_finished (op);
                return;
@@ -1921,7 +1913,7 @@ modify_contact_rename_handler (LDAPOp *op,
                if (LDAP_RES_RENAME != ldap_msgtype (res)) {
                        e_data_book_respond_modify_contacts (op->book,
                                                             op->opid,
-                                                            EDB_ERROR_MSG_TYPE (ldap_msgtype (res)),
+                                                            EC_ERROR_MSG_TYPE (ldap_msgtype (res)),
                                                             NULL);
                        ldap_op_finished (op);
                        return;
@@ -2040,7 +2032,7 @@ modify_contact_rename_handler (LDAPOp *op,
        } else {
                e_data_book_respond_modify_contacts (op->book,
                                                     op->opid,
-                                                    e_data_book_create_error_fmt 
(E_DATA_BOOK_STATUS_OTHER_ERROR,
+                                                    e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR,
                                                     _("%s: Unhandled result type %d returned"), G_STRFUNC, 
ldap_msgtype (res)),
                                                     NULL);
                ldap_op_finished (op);
@@ -2085,7 +2077,7 @@ get_contact_handler (LDAPOp *op,
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_get_contact (op->book, op->opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+               e_data_book_respond_get_contact (op->book, op->opid, EC_ERROR_NOT_CONNECTED (), NULL);
                ldap_op_finished (op);
                if (enable_debug)
                        printf ("get_contact_handler... ldap handler is NULL \n");
@@ -2100,7 +2092,6 @@ get_contact_handler (LDAPOp *op,
        if (msg_type == LDAP_RES_SEARCH_ENTRY) {
                LDAPMessage *e;
                EContact *contact;
-               gchar *vcard;
 
                g_rec_mutex_lock (&eds_ldap_handler_lock);
                if (bl->priv->ldap)
@@ -2112,8 +2103,8 @@ get_contact_handler (LDAPOp *op,
                if (!e) {
                        e_data_book_respond_get_contact (
                                op->book, op->opid,
-                               e_data_book_create_error_fmt (
-                                       E_DATA_BOOK_STATUS_OTHER_ERROR,
+                               e_client_error_create_fmt (
+                                       E_CLIENT_ERROR_OTHER_ERROR,
                                        _("%s: NULL returned from ldap_first_entry"),
                                        G_STRFUNC),
                                NULL);
@@ -2125,8 +2116,8 @@ get_contact_handler (LDAPOp *op,
                if (!contact) {
                        e_data_book_respond_get_contact (
                                op->book, op->opid,
-                               e_data_book_create_error_fmt (
-                                       E_DATA_BOOK_STATUS_OTHER_ERROR,
+                               e_client_error_create_fmt (
+                                       E_CLIENT_ERROR_OTHER_ERROR,
                                        _("%s: NULL returned from ldap_first_entry"),
                                        G_STRFUNC),
                                NULL);
@@ -2134,13 +2125,11 @@ get_contact_handler (LDAPOp *op,
                        return;
                }
 
-               vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
                e_data_book_respond_get_contact (
                        op->book,
                        op->opid,
-                       EDB_ERROR (SUCCESS),
-                       vcard);
-               g_free (vcard);
+                       NULL,
+                       contact);
                g_object_unref (contact);
                ldap_op_finished (op);
 
@@ -2187,7 +2176,7 @@ get_contact_handler (LDAPOp *op,
                e_data_book_respond_get_contact (
                        op->book,
                        op->opid,
-                       e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR,
+                       e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR,
                                                        _("%s: Unhandled result type %d returned"), 
G_STRFUNC, msg_type),
                        NULL);
                ldap_op_finished (op);
@@ -2227,7 +2216,7 @@ contact_list_handler (LDAPOp *op,
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_get_contact_list (op->book, op->opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+               e_data_book_respond_get_contact_list (op->book, op->opid, EC_ERROR_NOT_CONNECTED (), NULL);
                ldap_op_finished (op);
                if (enable_debug)
                        printf ("contact_list_handler ... ldap handler is NULL \n");
@@ -2246,18 +2235,18 @@ contact_list_handler (LDAPOp *op,
 
                while (NULL != e) {
                        EContact *contact;
-                       gchar *vcard;
 
                        contact = build_contact_from_entry (bl, e, NULL, NULL);
                        if (contact) {
-                               vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+                               if (enable_debug) {
+                                       gchar *vcard;
 
-                               if (enable_debug)
+                                       vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
                                        printf ("vcard = %s\n", vcard);
+                                       g_free (vcard);
+                               }
 
-                               contact_list_op->contacts = g_slist_append (contact_list_op->contacts, vcard);
-
-                               g_object_unref (contact);
+                               contact_list_op->contacts = g_slist_append (contact_list_op->contacts, 
contact);
                        }
 
                        g_rec_mutex_lock (&eds_ldap_handler_lock);
@@ -2297,19 +2286,19 @@ contact_list_handler (LDAPOp *op,
                        e_data_book_respond_get_contact_list (
                                op->book,
                                op->opid,
-                               EDB_ERROR (SEARCH_TIME_LIMIT_EXCEEDED),
+                               EC_ERROR (E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED),
                                contact_list_op->contacts);
                else if (ldap_error == LDAP_SIZELIMIT_EXCEEDED)
                        e_data_book_respond_get_contact_list (
                                op->book,
                                op->opid,
-                               EDB_ERROR (SEARCH_SIZE_LIMIT_EXCEEDED),
+                               EC_ERROR (E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED),
                                contact_list_op->contacts);
                else if (ldap_error == LDAP_SUCCESS)
                        e_data_book_respond_get_contact_list (
                                op->book,
                                op->opid,
-                               EDB_ERROR (SUCCESS),
+                               NULL,
                                contact_list_op->contacts);
                else
                        e_data_book_respond_get_contact_list (
@@ -2332,7 +2321,7 @@ contact_list_handler (LDAPOp *op,
                e_data_book_respond_get_contact_list (
                        op->book,
                        op->opid,
-                       e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR,
+                       e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR,
                        _("%s: Unhandled search result type %d returned"), G_STRFUNC, msg_type),
                        NULL);
                ldap_op_finished (op);
@@ -2344,8 +2333,7 @@ contact_list_dtor (LDAPOp *op)
 {
        LDAPGetContactListOp *contact_list_op = (LDAPGetContactListOp *) op;
 
-       g_slist_foreach (contact_list_op->contacts, (GFunc) g_free, NULL);
-       g_slist_free (contact_list_op->contacts);
+       g_slist_free_full (contact_list_op->contacts, g_object_unref);
 
        g_free (contact_list_op);
 }
@@ -2374,7 +2362,7 @@ contact_list_uids_handler (LDAPOp *op,
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_get_contact_list_uids (op->book, op->opid, EDB_ERROR_NOT_CONNECTED (), 
NULL);
+               e_data_book_respond_get_contact_list_uids (op->book, op->opid, EC_ERROR_NOT_CONNECTED (), 
NULL);
                ldap_op_finished (op);
                if (enable_debug)
                        printf ("contact_list_uids_handler ... ldap handler is NULL \n");
@@ -2440,17 +2428,17 @@ contact_list_uids_handler (LDAPOp *op,
                if (ldap_error == LDAP_TIMELIMIT_EXCEEDED)
                        e_data_book_respond_get_contact_list_uids (
                                op->book, op->opid,
-                               EDB_ERROR (SEARCH_TIME_LIMIT_EXCEEDED),
+                               EC_ERROR (E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED),
                                contact_list_uids_op->uids);
                else if (ldap_error == LDAP_SIZELIMIT_EXCEEDED)
                        e_data_book_respond_get_contact_list_uids (
                                op->book, op->opid,
-                               EDB_ERROR (SEARCH_SIZE_LIMIT_EXCEEDED),
+                               EC_ERROR (E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED),
                                contact_list_uids_op->uids);
                else if (ldap_error == LDAP_SUCCESS)
                        e_data_book_respond_get_contact_list_uids (
                                op->book, op->opid,
-                               EDB_ERROR (SUCCESS),
+                               NULL,
                                contact_list_uids_op->uids);
                else
                        e_data_book_respond_get_contact_list_uids (
@@ -2471,7 +2459,7 @@ contact_list_uids_handler (LDAPOp *op,
                g_warning ("unhandled search result type %d returned", msg_type);
                e_data_book_respond_get_contact_list_uids (
                        op->book, op->opid,
-                       e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR,
+                       e_client_error_create_fmt (E_CLIENT_ERROR_OTHER_ERROR,
                        _("%s: Unhandled search result type %d returned"), G_STRFUNC, msg_type),
                        NULL);
                ldap_op_finished (op);
@@ -4246,7 +4234,7 @@ ldap_search_handler (LDAPOp *op,
 
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
-               GError *edb_err = EDB_ERROR_NOT_CONNECTED ();
+               GError *edb_err = EC_ERROR_NOT_CONNECTED ();
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
                e_data_book_view_notify_complete (view, edb_err);
                ldap_op_finished (op);
@@ -4289,7 +4277,7 @@ ldap_search_handler (LDAPOp *op,
        } else if (msg_type == LDAP_RES_SEARCH_REFERENCE) {
                /* ignore references */
        } else if (msg_type == LDAP_RES_SEARCH_RESULT) {
-               GError *edb_err = NULL;
+               GError *ec_err = NULL;
                gchar *ldap_error_msg = NULL;
                gint ldap_error;
 
@@ -4312,23 +4300,19 @@ ldap_search_handler (LDAPOp *op,
                        ldap_memfree (ldap_error_msg);
 
                if ((ldap_error == LDAP_TIMELIMIT_EXCEEDED || ldap_error == LDAP_SIZELIMIT_EXCEEDED) && 
can_browse ((EBookBackend *) bl))
-                       /* do not complain when search limit exceeded for browseable LDAPs */
-                       edb_err = EDB_ERROR (SUCCESS);
+                       ;/* do not complain when search limit exceeded for browseable LDAPs */
                else if (ldap_error == LDAP_TIMELIMIT_EXCEEDED)
-                       edb_err = EDB_ERROR (SEARCH_TIME_LIMIT_EXCEEDED);
+                       ec_err = EC_ERROR (E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED);
                else if (ldap_error == LDAP_SIZELIMIT_EXCEEDED)
-                       edb_err = EDB_ERROR (SEARCH_SIZE_LIMIT_EXCEEDED);
-               else if (ldap_error == LDAP_SUCCESS)
-                       edb_err = EDB_ERROR (SUCCESS);
-               else
-                       edb_err = e_data_book_create_error_fmt (
-                               E_DATA_BOOK_STATUS_OTHER_ERROR,
+                       ec_err = EC_ERROR (E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED);
+               else if (ldap_error != LDAP_SUCCESS)
+                       ec_err = e_client_error_create_fmt (
+                               E_CLIENT_ERROR_OTHER_ERROR,
                                _("LDAP error 0x%x (%s)"), ldap_error,
                                ldap_err2string (ldap_error) ? ldap_err2string (ldap_error) : _("Unknown 
error"));
 
-               e_data_book_view_notify_complete (view, edb_err);
-               if (edb_err)
-                       g_error_free (edb_err);
+               e_data_book_view_notify_complete (view, ec_err);
+               g_clear_error (&ec_err);
 
                ldap_op_finished (op);
                if (enable_debug) {
@@ -4340,11 +4324,11 @@ ldap_search_handler (LDAPOp *op,
                }
        }
        else {
-               GError *edb_err = EDB_ERROR (INVALID_QUERY);
+               GError *ec_err = EC_ERROR (E_CLIENT_ERROR_INVALID_QUERY);
                g_warning ("unhandled search result type %d returned", msg_type);
-               e_data_book_view_notify_complete (view, edb_err);
+               e_data_book_view_notify_complete (view, ec_err);
                ldap_op_finished (op);
-               g_error_free (edb_err);
+               g_error_free (ec_err);
        }
 }
 
@@ -4392,7 +4376,7 @@ e_book_backend_ldap_search (EBookBackendLDAP *bl,
 
        if (!e_backend_get_online (E_BACKEND (bl)) || (bl->priv->marked_for_offline && bl->priv->cache)) {
                if (!(bl->priv->marked_for_offline && bl->priv->cache)) {
-                       GError *edb_err = EDB_ERROR (REPOSITORY_OFFLINE);
+                       GError *edb_err = EC_ERROR (E_CLIENT_ERROR_REPOSITORY_OFFLINE);
                        e_data_book_view_notify_complete (view, edb_err);
                        g_error_free (edb_err);
                        return;
@@ -4632,13 +4616,8 @@ generate_cache_dtor (LDAPOp *op)
 {
        LDAPGetContactListOp *contact_list_op = (LDAPGetContactListOp *) op;
        EBookBackendLDAP *ldap_backend = E_BOOK_BACKEND_LDAP (op->backend);
-       GSList *l;
-
-       for (l = contact_list_op->contacts; l; l = g_slist_next (l)) {
-               g_object_unref (l->data);
-       }
 
-       g_slist_free (contact_list_op->contacts);
+       g_slist_free_full (contact_list_op->contacts, g_object_unref);
        g_free (contact_list_op);
 
        g_rec_mutex_lock (&eds_ldap_handler_lock);
@@ -4741,24 +4720,28 @@ generate_cache (EBookBackendLDAP *book_backend_ldap)
        }
 }
 
-static gboolean
-book_backend_ldap_refresh_sync (EBookBackend *backend,
-                               GCancellable *cancellable,
-                               GError **error)
+static void
+book_backend_ldap_refresh (EBookBackend *backend,
+                          EDataBook *book,
+                          guint32 opid,
+                          GCancellable *cancellable)
 {
-       EBookBackendLDAP *ldap_backend = E_BOOK_BACKEND_LDAP (backend);
+       EBookBackendLDAP *ldap_backend;
 
-       g_return_val_if_fail (ldap_backend != NULL, FALSE);
-       g_return_val_if_fail (ldap_backend->priv != NULL, FALSE);
+       g_return_if_fail (E_IS_BOOK_BACKEND_LDAP (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
 
-       if (!ldap_backend->priv->cache || !ldap_backend->priv->marked_for_offline ||
-           ldap_backend->priv->generate_cache_in_progress)
-               return TRUE;
+       ldap_backend = E_BOOK_BACKEND_LDAP (backend);
+       g_return_if_fail (ldap_backend != NULL);
+       g_return_if_fail (ldap_backend->priv != NULL);
 
-       e_book_backend_cache_set_time (ldap_backend->priv->cache, "");
-       generate_cache (ldap_backend);
+       if (ldap_backend->priv->cache && ldap_backend->priv->marked_for_offline &&
+           !ldap_backend->priv->generate_cache_in_progress) {
+               e_book_backend_cache_set_time (ldap_backend->priv->cache, "");
+               generate_cache (ldap_backend);
+       }
 
-       return TRUE;
+       e_data_book_respond_refresh (book, opid, NULL);
 }
 
 static void
@@ -4913,7 +4896,7 @@ book_backend_ldap_get_backend_property (EBookBackend *backend,
                else
                        return g_strdup ("net,anon-access,contact-lists");
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                GSList *fields = NULL;
                gchar *prop_value;
 
@@ -4929,7 +4912,7 @@ book_backend_ldap_get_backend_property (EBookBackend *backend,
 
                return prop_value;
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
 
                return e_data_book_string_slist_to_comma_string (bl->priv->supported_fields);
@@ -4945,8 +4928,7 @@ static void
 book_backend_ldap_open (EBookBackend *backend,
                         EDataBook *book,
                         guint opid,
-                        GCancellable *cancellable,
-                        gboolean only_if_exists)
+                        GCancellable *cancellable)
 {
        EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
        ESourceAuthentication *auth_extension;
@@ -5024,7 +5006,7 @@ book_backend_ldap_open (EBookBackend *backend,
                e_book_backend_set_writable (backend, FALSE);
 
                if (!bl->priv->marked_for_offline)
-                       error = EDB_ERROR (OFFLINE_UNAVAILABLE);
+                       error = EC_ERROR (E_CLIENT_ERROR_OFFLINE_UNAVAILABLE);
 
                e_data_book_respond_open (book, opid, error);
                return;
@@ -5039,10 +5021,7 @@ book_backend_ldap_open (EBookBackend *backend,
        if (!auth_required)
                e_book_backend_ldap_connect (bl, &error);
 
-       if (g_error_matches (
-               error, E_DATA_BOOK_ERROR,
-               E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED)) {
-
+       if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_REQUIRED)) {
                g_clear_error (&error);
                auth_required = TRUE;
        }
@@ -5069,12 +5048,13 @@ book_backend_ldap_open (EBookBackend *backend,
 
 static void
 book_backend_ldap_create_contacts (EBookBackend *backend,
-                                   EDataBook *book,
-                                   guint32 opid,
-                                   GCancellable *cancellable,
-                                   const GSList *vcards)
+                                  EDataBook *book,
+                                  guint32 opid,
+                                  GCancellable *cancellable,
+                                  const gchar * const *vcards,
+                                  guint32 opflags)
 {
-       LDAPCreateOp *create_op = g_new0 (LDAPCreateOp, 1);
+       LDAPCreateOp *create_op;
        EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
        EDataBookView *book_view;
        gint create_contact_msgid;
@@ -5082,29 +5062,33 @@ book_backend_ldap_create_contacts (EBookBackend *backend,
        GPtrArray *mod_array;
        LDAPMod **ldap_mods;
        gchar *new_uid;
-       const gchar *vcard = (const gchar *) vcards->data;
+       const gchar *vcard;
        gboolean is_list;
 
+       g_return_if_fail (vcards != NULL);
+
+       vcard = vcards[0];
+
        /* We make the assumption that the vCard list we're passed is always exactly one element long, since 
we haven't specified "bulk-adds"
         * in our static capability list. This is because there is no clean way to roll back changes in case 
of an error. */
-       if (vcards->next != NULL) {
+       if (!vcards[0] || vcards[1]) {
                e_data_book_respond_create_contacts (
                        book, opid,
-                       EDB_ERROR_EX (NOT_SUPPORTED,
+                       EC_ERROR_EX (E_CLIENT_ERROR_NOT_SUPPORTED,
                        _("The backend does not support bulk additions")),
                        NULL);
                return;
        }
 
        if (!e_backend_get_online (E_BACKEND (backend))) {
-               e_data_book_respond_create_contacts (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
+               e_data_book_respond_create_contacts (book, opid, EC_ERROR 
(E_CLIENT_ERROR_REPOSITORY_OFFLINE), NULL);
                return;
        }
 
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_create_contacts (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+               e_data_book_respond_create_contacts (book, opid, EC_ERROR_NOT_CONNECTED (), NULL);
                return;
        }
        g_rec_mutex_unlock (&eds_ldap_handler_lock);
@@ -5114,6 +5098,7 @@ book_backend_ldap_create_contacts (EBookBackend *backend,
        if (enable_debug)
                printf ("Create Contact: vcard = %s\n", vcard);
 
+       create_op = g_new0 (LDAPCreateOp, 1);
        create_op->new_contact = e_contact_new_from_vcard (vcard);
 
        new_uid = create_dn_from_contact (create_op->new_contact, bl->priv->ldap_rootdn);
@@ -5212,25 +5197,30 @@ book_backend_ldap_modify_contacts (EBookBackend *backend,
                                    EDataBook *book,
                                    guint32 opid,
                                    GCancellable *cancellable,
-                                   const GSList *vcards)
+                                   const gchar * const *vcards,
+                                  guint32 opflags)
 {
-       LDAPModifyOp *modify_op = g_new0 (LDAPModifyOp, 1);
+       LDAPModifyOp *modify_op;
        EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
        gint ldap_error;
        gint modify_contact_msgid;
        EDataBookView *book_view;
-       gchar *vcard = vcards->data;
+       const gchar *vcard;
+
+       g_return_if_fail (vcards != NULL);
+
+       vcard = vcards[0];
 
        if (!e_backend_get_online (E_BACKEND (backend))) {
-               e_data_book_respond_modify_contacts (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
+               e_data_book_respond_modify_contacts (book, opid, EC_ERROR 
(E_CLIENT_ERROR_REPOSITORY_OFFLINE), NULL);
                return;
        }
 
        /* We make the assumption that the vCard list we're passed is always exactly one element long, since 
we haven't specified "bulk-modifies"
         * in our static capability list. This is because there is no clean way to roll back changes in case 
of an error. */
-       if (vcards->next != NULL) {
+       if (!vcards[0] || vcards[1]) {
                e_data_book_respond_modify_contacts (book, opid,
-                                                    EDB_ERROR_EX (NOT_SUPPORTED,
+                                                    EC_ERROR_EX (E_CLIENT_ERROR_NOT_SUPPORTED,
                                                     _("The backend does not support bulk modifications")),
                                                     NULL);
                return;
@@ -5239,8 +5229,7 @@ book_backend_ldap_modify_contacts (EBookBackend *backend,
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_modify_contacts (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
-               g_free (modify_op);
+               e_data_book_respond_modify_contacts (book, opid, EC_ERROR_NOT_CONNECTED (), NULL);
                return;
        }
        g_rec_mutex_unlock (&eds_ldap_handler_lock);
@@ -5249,6 +5238,7 @@ book_backend_ldap_modify_contacts (EBookBackend *backend,
 
        if (enable_debug)
                printf ("Modify Contact: vcard = %s\n", vcard);
+       modify_op = g_new0 (LDAPModifyOp, 1);
        modify_op->contact = e_contact_new_from_vcard (vcard);
        modify_op->id = e_contact_get_const (modify_op->contact, E_CONTACT_UID);
 
@@ -5290,25 +5280,26 @@ book_backend_ldap_remove_contacts (EBookBackend *backend,
                                    EDataBook *book,
                                    guint32 opid,
                                    GCancellable *cancellable,
-                                   const GSList *ids)
+                                   const gchar * const *uids,
+                                  guint32 opflags)
 {
-       LDAPRemoveOp *remove_op = g_new (LDAPRemoveOp, 1);
+       LDAPRemoveOp *remove_op;
        EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
        EDataBookView *book_view;
        gint remove_msgid;
        gint ldap_error;
 
+       g_return_if_fail (uids != NULL);
+
        if (!e_backend_get_online (E_BACKEND (backend))) {
-               e_data_book_respond_remove_contacts (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
-               g_free (remove_op);
+               e_data_book_respond_remove_contacts (book, opid, EC_ERROR 
(E_CLIENT_ERROR_REPOSITORY_OFFLINE), NULL);
                return;
        }
 
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_remove_contacts (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
-               g_free (remove_op);
+               e_data_book_respond_remove_contacts (book, opid, EC_ERROR_NOT_CONNECTED (), NULL);
                return;
        }
        g_rec_mutex_unlock (&eds_ldap_handler_lock);
@@ -5320,7 +5311,8 @@ book_backend_ldap_remove_contacts (EBookBackend *backend,
        ** capabilities, we should only get 1 length lists here, so
        ** the id we're deleting is the first and only id in the list.
        */
-       remove_op->id = g_strdup (ids->data);
+       remove_op = g_new (LDAPRemoveOp, 1);
+       remove_op->id = g_strdup (uids[0]);
 
        do {
                book_view_notify_status (bl, book_view, _("Removing contact from LDAP server..."));
@@ -5373,26 +5365,22 @@ book_backend_ldap_get_contact (EBookBackend *backend,
        if (!e_backend_get_online (E_BACKEND (backend))) {
                if (bl->priv->marked_for_offline && bl->priv->cache) {
                        EContact *contact = e_book_backend_cache_get_contact (bl->priv->cache, id);
-                       gchar *vcard_str;
 
                        if (!contact) {
-                               e_data_book_respond_get_contact (book, opid, EDB_ERROR (CONTACT_NOT_FOUND), 
NULL);
+                               e_data_book_respond_get_contact (book, opid, EBC_ERROR 
(E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND), NULL);
                                return;
                        }
 
-                       vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
                        e_data_book_respond_get_contact (
                                book,
                                opid,
-                               EDB_ERROR (SUCCESS),
-                               vcard_str);
-                       g_free (vcard_str);
+                               NULL,
+                               contact);
                        g_object_unref (contact);
                        return;
                }
 
-               e_data_book_respond_get_contact (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
+               e_data_book_respond_get_contact (book, opid, EC_ERROR (E_CLIENT_ERROR_REPOSITORY_OFFLINE), 
NULL);
                return;
        }
 
@@ -5404,7 +5392,7 @@ book_backend_ldap_get_contact (EBookBackend *backend,
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_get_contact (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+               e_data_book_respond_get_contact (book, opid, EC_ERROR_NOT_CONNECTED (), NULL);
                if (enable_debug)
                        printf ("e_book_backend_ldap_get_contact ... ldap handler is NULL\n");
                return;
@@ -5479,34 +5467,31 @@ book_backend_ldap_get_contact_list (EBookBackend *backend,
        if (!e_backend_get_online (E_BACKEND (backend))) {
                if (bl->priv->marked_for_offline && bl->priv->cache) {
                        GList *contacts;
-                       GSList *vcard_strings = NULL;
+                       GSList *contacts_slist = NULL;
                        GList *l;
 
                        contacts = e_book_backend_cache_get_contacts (bl->priv->cache, query);
 
                        for (l = contacts; l; l = g_list_next (l)) {
                                EContact *contact = l->data;
-                               vcard_strings = g_slist_prepend (
-                                       vcard_strings, e_vcard_to_string (E_VCARD (contact),
-                                       EVC_FORMAT_VCARD_30));
-                               g_object_unref (contact);
+                               contacts_slist = g_slist_prepend (contacts_slist, contact);
                        }
 
-                       g_list_free (contacts);
-                       e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (SUCCESS), vcard_strings);
-                       g_slist_foreach (vcard_strings, (GFunc) g_free, NULL);
-                       g_slist_free (vcard_strings);
+                       e_data_book_respond_get_contact_list (book, opid, NULL, contacts_slist);
+
+                       g_list_free_full (contacts, g_object_unref);
+                       g_slist_free (contacts_slist);
                        return;
                }
 
-               e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
+               e_data_book_respond_get_contact_list (book, opid, EC_ERROR 
(E_CLIENT_ERROR_REPOSITORY_OFFLINE), NULL);
                return;
        }
 
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_get_contact_list (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+               e_data_book_respond_get_contact_list (book, opid, EC_ERROR_NOT_CONNECTED (), NULL);
                if (enable_debug)
                        printf ("e_book_backend_ldap_get_contact_list... ldap handler is NULL\n");
                return;
@@ -5600,20 +5585,19 @@ book_backend_ldap_get_contact_list_uids (EBookBackend *backend,
                        }
 
                        g_list_free (contacts);
-                       e_data_book_respond_get_contact_list_uids (book, opid, EDB_ERROR (SUCCESS), uids);
-                       g_slist_foreach (uids, (GFunc) g_free, NULL);
-                       g_slist_free (uids);
+                       e_data_book_respond_get_contact_list_uids (book, opid, NULL, uids);
+                       g_slist_free_full (uids, g_free);
                        return;
                }
 
-               e_data_book_respond_get_contact_list_uids (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
+               e_data_book_respond_get_contact_list_uids (book, opid, EC_ERROR 
(E_CLIENT_ERROR_REPOSITORY_OFFLINE), NULL);
                return;
        }
 
        g_rec_mutex_lock (&eds_ldap_handler_lock);
        if (!bl->priv->ldap) {
                g_rec_mutex_unlock (&eds_ldap_handler_lock);
-               e_data_book_respond_get_contact_list_uids (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+               e_data_book_respond_get_contact_list_uids (book, opid, EC_ERROR_NOT_CONNECTED (), NULL);
                if (enable_debug)
                        printf ("e_book_backend_ldap_get_contact_list_uids... ldap handler is NULL\n");
                return;
@@ -5791,10 +5775,7 @@ book_backend_ldap_authenticate_sync (EBackend *backend,
                        if (local_error == NULL) {
                                return E_SOURCE_AUTHENTICATION_ACCEPTED;
 
-                       } else if (g_error_matches (
-                               local_error, E_DATA_BOOK_ERROR,
-                               E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED)) {
-
+                       } else if (g_error_matches (local_error, E_CLIENT_ERROR, 
E_CLIENT_ERROR_AUTHENTICATION_FAILED)) {
                                g_clear_error (&local_error);
                                return E_SOURCE_AUTHENTICATION_REJECTED;
 
@@ -5841,10 +5822,7 @@ book_backend_ldap_authenticate_sync (EBackend *backend,
                        if (local_error == NULL) {
                                return E_SOURCE_AUTHENTICATION_ACCEPTED;
 
-                       } else if (g_error_matches (
-                               local_error, E_DATA_BOOK_ERROR,
-                               E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED)) {
-
+                       } else if (g_error_matches (local_error, E_CLIENT_ERROR, 
E_CLIENT_ERROR_AUTHENTICATION_FAILED)) {
                                g_clear_error (&local_error);
                                return E_SOURCE_AUTHENTICATION_REJECTED;
 
@@ -5900,8 +5878,7 @@ exit:
 
                case LDAP_NOT_SUPPORTED:
                        g_propagate_error (
-                               error, EDB_ERROR (
-                               UNSUPPORTED_AUTHENTICATION_METHOD));
+                               error, EC_ERROR (E_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD));
                        result = E_SOURCE_AUTHENTICATION_ERROR;
                        break;
 
@@ -5949,7 +5926,7 @@ e_book_backend_ldap_class_init (EBookBackendLDAPClass *class)
        book_backend_class->get_contact_list_uids = book_backend_ldap_get_contact_list_uids;
        book_backend_class->start_view = book_backend_ldap_start_view;
        book_backend_class->stop_view = book_backend_ldap_stop_view;
-       book_backend_class->refresh_sync = book_backend_ldap_refresh_sync;
+       book_backend_class->refresh = book_backend_ldap_refresh;
 
        /* Register our ESource extension. */
        E_TYPE_SOURCE_LDAP;
diff --git a/src/addressbook/libebook-contacts/CMakeLists.txt 
b/src/addressbook/libebook-contacts/CMakeLists.txt
index e9e325973..02ca9d530 100644
--- a/src/addressbook/libebook-contacts/CMakeLists.txt
+++ b/src/addressbook/libebook-contacts/CMakeLists.txt
@@ -1,4 +1,4 @@
-glib_mkenums(e-book-contacts-enumtypes e-book-contacts-types.h E_BOOK_CONTACTS_ENUMTYPES_H)
+glib_mkenums(e-book-contacts-enumtypes e-book-contacts-enums.h E_BOOK_CONTACTS_ENUMTYPES_H)
 
 add_pkgconfig_file(libebook-contacts.pc.in libebook-contacts-${API_VERSION}.pc)
 
@@ -36,7 +36,7 @@ set(DEPENDENCIES
 
 set(SOURCES
        e-address-western.c
-       e-book-contacts-types.c
+       e-book-contacts-utils.c
        e-book-query.c
        e-contact.c
        e-name-western.c
@@ -51,7 +51,8 @@ set(SOURCES
 set(HEADERS
        libebook-contacts.h
        e-address-western.h
-       e-book-contacts-types.h
+       e-book-contacts-enums.h
+       e-book-contacts-utils.h
        e-book-query.h
        e-contact.h
        e-name-western.h
diff --git a/src/addressbook/libebook-contacts/e-book-contacts-enums.h 
b/src/addressbook/libebook-contacts/e-book-contacts-enums.h
new file mode 100644
index 000000000..06a3e18fc
--- /dev/null
+++ b/src/addressbook/libebook-contacts/e-book-contacts-enums.h
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Nat Friedman (nat ximian com)
+ *          Tristan Van Berkom <tristanvb openismus com>
+ */
+
+#if !defined (__LIBEBOOK_CONTACTS_H_INSIDE__) && !defined (LIBEBOOK_CONTACTS_COMPILATION)
+#error "Only <libebook-contacts/libebook-contacts.h> should be included directly."
+#endif
+
+#ifndef E_BOOK_CONTACTS_ENUMS_H
+#define E_BOOK_CONTACTS_ENUMS_H
+
+G_BEGIN_DECLS
+
+/**
+ * EBookClientViewFlags:
+ * @E_BOOK_CLIENT_VIEW_FLAGS_NONE:
+ *   Symbolic value for no flags
+ * @E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL:
+ *   If this flag is set then all contacts matching the view's query will
+ *   be sent as notifications when starting the view, otherwise only future
+ *   changes will be reported.  The default for a #EBookClientView is %TRUE.
+ *
+ * Flags that control the behaviour of an #EBookClientView.
+ *
+ * Since: 3.4
+ */
+typedef enum { /*< flags >*/
+       E_BOOK_CLIENT_VIEW_FLAGS_NONE = 0,
+       E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL = (1 << 0),
+} EBookClientViewFlags;
+
+/**
+ * EBookIndexType:
+ * @E_BOOK_INDEX_PREFIX: An index suitable for searching contacts with a prefix pattern
+ * @E_BOOK_INDEX_SUFFIX: An index suitable for searching contacts with a suffix pattern
+ * @E_BOOK_INDEX_PHONE: An index suitable for searching contacts for phone numbers.
+ * <note><para>Phone numbers must be convertible into FQTN according to E.164 to be
+ * stored in this index. The number "+9999999" for instance won't be stored because
+ * the country calling code "+999" currently is not assigned.</para></note>
+ * @E_BOOK_INDEX_SORT_KEY: Indicates that a given #EContactField should be usable as a sort key.
+ *
+ * The type of index defined by e_source_backend_summary_setup_set_indexed_fields()
+ */
+typedef enum {
+       E_BOOK_INDEX_PREFIX = 0,
+       E_BOOK_INDEX_SUFFIX,
+       E_BOOK_INDEX_PHONE,
+       E_BOOK_INDEX_SORT_KEY
+} EBookIndexType;
+
+/**
+ * EBookCursorSortType:
+ * @E_BOOK_CURSOR_SORT_ASCENDING: Sort results in ascending order
+ * @E_BOOK_CURSOR_SORT_DESCENDING: Sort results in descending order
+ *
+ * Specifies the sort order of an ordered query
+ *
+ * Since: 3.12
+ */
+typedef enum {
+       E_BOOK_CURSOR_SORT_ASCENDING = 0,
+       E_BOOK_CURSOR_SORT_DESCENDING
+} EBookCursorSortType;
+
+/**
+ * EBookCursorOrigin:
+ * @E_BOOK_CURSOR_ORIGIN_CURRENT:  The current cursor position
+ * @E_BOOK_CURSOR_ORIGIN_BEGIN:    The beginning of the cursor results.
+ * @E_BOOK_CURSOR_ORIGIN_END:      The ending of the cursor results.
+ *
+ * Specifies the start position to in the list of traversed contacts
+ * in calls to e_book_client_cursor_step().
+ *
+ * When an #EBookClientCursor is created, the current position implied by %E_BOOK_CURSOR_ORIGIN_CURRENT
+ * is the same as %E_BOOK_CURSOR_ORIGIN_BEGIN.
+ *
+ * Since: 3.12
+ */
+typedef enum {
+       E_BOOK_CURSOR_ORIGIN_CURRENT,
+       E_BOOK_CURSOR_ORIGIN_BEGIN,
+       E_BOOK_CURSOR_ORIGIN_END
+} EBookCursorOrigin;
+
+/**
+ * EBookCursorStepFlags:
+ * @E_BOOK_CURSOR_STEP_MOVE:  The cursor position should be modified while stepping
+ * @E_BOOK_CURSOR_STEP_FETCH: Traversed contacts should be listed and returned while stepping.
+ *
+ * Defines the behaviour of e_book_client_cursor_step().
+ *
+ * Since: 3.12
+ */
+typedef enum { /*< flags >*/
+       E_BOOK_CURSOR_STEP_MOVE = (1 << 0),
+       E_BOOK_CURSOR_STEP_FETCH = (1 << 1)
+} EBookCursorStepFlags;
+
+/**
+ * EBookOperationFlags:
+ * @E_BOOK_OPERATION_FLAG_NONE: no operation flags defined
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_FAIL: conflict resolution mode, to fail and do not
+ *    do any changes, when a conflict is detected
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_USE_NEWER: conflict resolution mode, to use newer
+ *    of the local and the server side data, when a conflict is detected
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_SERVER: conflict resolution mode, to use
+ *    the server data (and local changed), when a conflict is detected
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL: conflict resolution mode, to use
+ *    local data (and always overwrite server data), when a conflict is detected
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_WRITE_COPY: conflict resolution mode, to create
+ *    a copy of the data, when a conflict is detected
+ *
+ * Book operation flags, to specify behavior in certain situations. The conflict
+ * resolution mode flags cannot be combined together, where the @E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL
+ * is the default behavior (and it is used when no other conflict resolution flag is set).
+ * The flags can be ignored when the operation or the backend don't support it.
+ *
+ * Since: 3.36
+ **/
+typedef enum { /*< flags >*/
+       E_BOOK_OPERATION_FLAG_NONE                      = 0,
+       E_BOOK_OPERATION_FLAG_CONFLICT_FAIL             = (1 << 0),
+       E_BOOK_OPERATION_FLAG_CONFLICT_USE_NEWER        = (1 << 1),
+       E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_SERVER      = (1 << 2),
+       E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL       = 0,
+       E_BOOK_OPERATION_FLAG_CONFLICT_WRITE_COPY       = (1 << 3)
+} EBookOperationFlags;
+
+G_END_DECLS
+
+#endif /* E_BOOK_CONTACTS_ENUMS_H */
diff --git a/src/addressbook/libebook-contacts/e-book-contacts-utils.c 
b/src/addressbook/libebook-contacts/e-book-contacts-utils.c
new file mode 100644
index 000000000..fb03480f0
--- /dev/null
+++ b/src/addressbook/libebook-contacts/e-book-contacts-utils.c
@@ -0,0 +1,168 @@
+/*
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "libedataserver/libedataserver.h"
+
+#include "e-book-contacts-utils.h"
+
+G_DEFINE_QUARK (e-book-client-error-quark, e_book_client_error)
+
+/**
+ * e_book_client_error_to_string:
+ * @code: an #EBookClientError code
+ *
+ * Get localized human readable description of the given error code.
+ *
+ * Returns: Localized human readable description of the given error code
+ *
+ * Since: 3.2
+ **/
+const gchar *
+e_book_client_error_to_string (EBookClientError code)
+{
+       switch (code) {
+       case E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK:
+               return _("No such book");
+       case E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND:
+               return _("Contact not found");
+       case E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS:
+               return _("Contact ID already exists");
+       case E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE:
+               return _("No such source");
+       case E_BOOK_CLIENT_ERROR_NO_SPACE:
+               return _("No space");
+       }
+
+       return _("Unknown error");
+}
+
+/**
+ * e_book_client_error_create:
+ * @code: an #EBookClientError code to create
+ * @custom_msg: custom message to use for the error; can be %NULL
+ *
+ * Returns: a new #GError containing an E_BOOK_CLIENT_ERROR of the given
+ * @code. If the @custom_msg is NULL, then the error message is
+ * the one returned from e_book_client_error_to_string() for the @code,
+ * otherwise the given message is used.
+ *
+ * Returned pointer should be freed with g_error_free().
+ *
+ * Since: 3.2
+ **/
+GError *
+e_book_client_error_create (EBookClientError code,
+                            const gchar *custom_msg)
+{
+       return g_error_new_literal (E_BOOK_CLIENT_ERROR, code, custom_msg ? custom_msg : 
e_book_client_error_to_string (code));
+}
+
+/**
+ * e_book_client_error_create_fmt:
+ * @code: an #EBookClientError
+ * @format: (nullable): message format, or %NULL to use the default message for the @code
+ * @...: arguments for the format
+ *
+ * Similar as e_book_client_error_create(), only here, instead of custom_msg,
+ * is used a printf() format to create a custom message for the error.
+ *
+ * Returns: (transfer full): a newly allocated #GError, which should be
+ *   freed with g_error_free(), when no longer needed.
+ *   The #GError has set the custom message, or the default message for
+ *   @code, when @format is %NULL.
+ *
+ * Since: 3.36
+ **/
+GError *
+e_book_client_error_create_fmt (EBookClientError code,
+                               const gchar *format,
+                               ...)
+{
+       GError *error;
+       gchar *custom_msg;
+       va_list ap;
+
+       if (!format)
+               return e_book_client_error_create (code, NULL);
+
+       va_start (ap, format);
+       custom_msg = g_strdup_vprintf (format, ap);
+       va_end (ap);
+
+       error = e_book_client_error_create (code, custom_msg);
+
+       g_free (custom_msg);
+
+       return error;
+}
+
+/**
+ * e_book_util_operation_flags_to_conflict_resolution:
+ * @flags: bit-or of #EBookOperationFlags
+ *
+ * Decodes the #EConflictResolution from the bit-or of #EBookOperationFlags.
+ *
+ * Returns: an #EConflictResolution as stored in the @flags
+ *
+ * Since: 3.36
+ **/
+EConflictResolution
+e_book_util_operation_flags_to_conflict_resolution (guint32 flags)
+{
+       if ((flags & E_BOOK_OPERATION_FLAG_CONFLICT_FAIL) != 0)
+               return E_CONFLICT_RESOLUTION_FAIL;
+       else if ((flags & E_BOOK_OPERATION_FLAG_CONFLICT_USE_NEWER) != 0)
+               return E_CONFLICT_RESOLUTION_USE_NEWER;
+       else if ((flags & E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_SERVER) != 0)
+               return E_CONFLICT_RESOLUTION_KEEP_SERVER;
+       else if ((flags & E_BOOK_OPERATION_FLAG_CONFLICT_WRITE_COPY) != 0)
+               return E_CONFLICT_RESOLUTION_WRITE_COPY;
+
+       /* E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL is the default */
+       return E_CONFLICT_RESOLUTION_KEEP_LOCAL;
+}
+
+/**
+ * e_book_util_conflict_resolution_to_operation_flags:
+ * @conflict_resolution: an #EConflictResolution
+ *
+ * Encodes the #EConflictResolution into the bit-or of #EBookOperationFlags.
+ * The returned value can be bit-or-ed with other #EBookOperationFlags values.
+ *
+ * Returns: a bit-or of #EBookOperationFlags, corresponding to the @conflict_resolution
+ *
+ * Since: 3.36
+ **/
+guint32
+e_book_util_conflict_resolution_to_operation_flags (EConflictResolution conflict_resolution)
+{
+       switch (conflict_resolution) {
+       case E_CONFLICT_RESOLUTION_FAIL:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_FAIL;
+       case E_CONFLICT_RESOLUTION_USE_NEWER:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_USE_NEWER;
+       case E_CONFLICT_RESOLUTION_KEEP_SERVER:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_SERVER;
+       case E_CONFLICT_RESOLUTION_KEEP_LOCAL:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL;
+       case E_CONFLICT_RESOLUTION_WRITE_COPY:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_WRITE_COPY;
+       }
+
+       return E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL;
+}
diff --git a/src/addressbook/libebook-contacts/e-book-contacts-utils.h 
b/src/addressbook/libebook-contacts/e-book-contacts-utils.h
new file mode 100644
index 000000000..62781d490
--- /dev/null
+++ b/src/addressbook/libebook-contacts/e-book-contacts-utils.h
@@ -0,0 +1,175 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Nat Friedman (nat ximian com)
+ *          Tristan Van Berkom <tristanvb openismus com>
+ */
+
+#if !defined (__LIBEBOOK_CONTACTS_H_INSIDE__) && !defined (LIBEBOOK_CONTACTS_COMPILATION)
+#error "Only <libebook-contacts/libebook-contacts.h> should be included directly."
+#endif
+
+#ifndef E_BOOK_CONTACTS_UTILS_H
+#define E_BOOK_CONTACTS_UTILS_H
+
+#include <libedataserver/libedataserver.h>
+#include <libebook-contacts/e-book-contacts-enums.h>
+#include <libebook-contacts/e-contact.h>
+
+/**
+ * E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: (value "required-fields")
+ *
+ * Provides comma-separated list of required fields by the book backend.
+ * All of these attributes should be set, otherwise the backend will reject
+ * saving the contact.
+ *
+ * The e_contact_field_id() can be used to transform the field name
+ * into an #EContactField.
+ *
+ * Since: 3.2
+ **/
+#define E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS                "required-fields"
+
+/**
+ * E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: (value "supported-fields")
+ *
+ * Provides comma-separated list of supported fields by the book backend.
+ * Attributes other than those listed here can be discarded. This can be
+ * used to enable/show only supported elements in GUI.
+ *
+ * The e_contact_field_id() can be used to transform the field name
+ * into an #EContactField.
+ *
+ * Since: 3.2
+ **/
+#define E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS       "supported-fields"
+
+/**
+ * E_BOOK_BACKEND_PROPERTY_REVISION: (value "revision")
+ *
+ * The current overall revision string, this can be used as
+ * a quick check to see if data has changed at all since the
+ * last time the addressbook revision was observed.
+ *
+ * Since: 3.4
+ **/
+#define E_BOOK_BACKEND_PROPERTY_REVISION               "revision"
+
+/**
+ * E_BOOK_CLIENT_ERROR:
+ *
+ * Error domain for #EBookClient errors
+ *
+ * Since: 3.2
+ **/
+#define E_BOOK_CLIENT_ERROR e_book_client_error_quark ()
+
+G_BEGIN_DECLS
+
+/**
+ * EBookClientError:
+ * @E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK: Requested book did not exist
+ * @E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND: Contact referred to was not found
+ * @E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS: Tried to add a contact which already exists
+ * @E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE: Referred #ESource does not exist
+ * @E_BOOK_CLIENT_ERROR_NO_SPACE: Out of disk space
+ *
+ * Error codes returned by #EBookClient APIs, if an #EClientError was not available.
+ *
+ * Since: 3.2
+ **/
+typedef enum {
+       E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK,
+       E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND,
+       E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS,
+       E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE,
+       E_BOOK_CLIENT_ERROR_NO_SPACE
+} EBookClientError;
+
+GQuark         e_book_client_error_quark       (void) G_GNUC_CONST;
+const gchar *  e_book_client_error_to_string   (EBookClientError code);
+GError *       e_book_client_error_create      (EBookClientError code,
+                                                const gchar *custom_msg);
+GError *       e_book_client_error_create_fmt  (EBookClientError code,
+                                                const gchar *format,
+                                                ...) G_GNUC_PRINTF (2, 3);
+
+EConflictResolution
+               e_book_util_operation_flags_to_conflict_resolution
+                                               (guint32 flags); /* bit-or of EBookOperationFlags */
+guint32                e_book_util_conflict_resolution_to_operation_flags /* bit-or of EBookOperationFlags */
+                                               (EConflictResolution conflict_resolution);
+
+#ifndef EDS_DISABLE_DEPRECATED
+
+/**
+ * EBookViewStatus:
+ * @E_BOOK_VIEW_STATUS_OK: Ok
+ * @E_BOOK_VIEW_STATUS_TIME_LIMIT_EXCEEDED: Time limit exceeded
+ * @E_BOOK_VIEW_STATUS_SIZE_LIMIT_EXCEEDED: Size limit exceeded
+ * @E_BOOK_VIEW_ERROR_INVALID_QUERY: Invalid search expression
+ * @E_BOOK_VIEW_ERROR_QUERY_REFUSED: Search expression refused
+ * @E_BOOK_VIEW_ERROR_OTHER_ERROR: Another error occurred
+ *
+ * Status messages used in notifications in the deprecated #EBookView class
+ *
+ * Deprecated: 3.2: Use #EBookClientView instead.
+ */
+typedef enum {
+       E_BOOK_VIEW_STATUS_OK,
+       E_BOOK_VIEW_STATUS_TIME_LIMIT_EXCEEDED,
+       E_BOOK_VIEW_STATUS_SIZE_LIMIT_EXCEEDED,
+       E_BOOK_VIEW_ERROR_INVALID_QUERY,
+       E_BOOK_VIEW_ERROR_QUERY_REFUSED,
+       E_BOOK_VIEW_ERROR_OTHER_ERROR
+} EBookViewStatus;
+
+/**
+ * EBookChangeType:
+ * @E_BOOK_CHANGE_CARD_ADDED: A vCard was added
+ * @E_BOOK_CHANGE_CARD_DELETED: A vCard was deleted
+ * @E_BOOK_CHANGE_CARD_MODIFIED: A vCard was modified
+ *
+ * The type of change in an #EBookChange
+ *
+ * Deprecated: 3.2
+ */
+typedef enum {
+       E_BOOK_CHANGE_CARD_ADDED,
+       E_BOOK_CHANGE_CARD_DELETED,
+       E_BOOK_CHANGE_CARD_MODIFIED
+} EBookChangeType;
+
+/**
+ * EBookChange:
+ * @change_type: The #EBookChangeType
+ * @contact: The #EContact which changed
+ *
+ * This is a part of the deprecated #EBook API.
+ *
+ * Deprecated: 3.2
+ */
+typedef struct {
+       EBookChangeType  change_type;
+       EContact        *contact;
+} EBookChange;
+
+#endif /* EDS_DISABLE_DEPRECATED */
+
+G_END_DECLS
+
+#endif /* E_BOOK_CONTACTS_UTILS_H */
diff --git a/src/addressbook/libebook-contacts/e-source-backend-summary-setup.h 
b/src/addressbook/libebook-contacts/e-source-backend-summary-setup.h
index 0206859b7..c2192d966 100644
--- a/src/addressbook/libebook-contacts/e-source-backend-summary-setup.h
+++ b/src/addressbook/libebook-contacts/e-source-backend-summary-setup.h
@@ -28,7 +28,7 @@
 
 #include <libedataserver/libedataserver.h>
 #include <libebook-contacts/e-contact.h>
-#include <libebook-contacts/e-book-contacts-types.h>
+#include <libebook-contacts/e-book-contacts-enums.h>
 
 /* Standard GObject macros */
 #define E_TYPE_SOURCE_BACKEND_SUMMARY_SETUP \
diff --git a/src/addressbook/libebook-contacts/libebook-contacts.h 
b/src/addressbook/libebook-contacts/libebook-contacts.h
index 87c58eed2..04e1bdb5a 100644
--- a/src/addressbook/libebook-contacts/libebook-contacts.h
+++ b/src/addressbook/libebook-contacts/libebook-contacts.h
@@ -22,13 +22,14 @@
 
 #include <libedataserver/libedataserver.h>
 
-#include <libebook-contacts/e-book-contacts-types.h>
+#include <libebook-contacts/e-book-contacts-enums.h>
+#include <libebook-contacts/e-book-contacts-enumtypes.h>
+#include <libebook-contacts/e-book-contacts-utils.h>
 #include <libebook-contacts/e-book-query.h>
 #include <libebook-contacts/e-name-western.h>
 #include <libebook-contacts/e-address-western.h>
 #include <libebook-contacts/e-contact.h>
 #include <libebook-contacts/e-vcard.h>
-#include <libebook-contacts/e-book-contacts-enumtypes.h>
 #include <libebook-contacts/e-source-backend-summary-setup.h>
 #include <libebook-contacts/e-phone-number.h>
 
diff --git a/src/addressbook/libebook/e-book-client.c b/src/addressbook/libebook/e-book-client.c
index 2c0557c3c..fb58e7637 100644
--- a/src/addressbook/libebook/e-book-client.c
+++ b/src/addressbook/libebook/e-book-client.c
@@ -82,6 +82,7 @@ struct _AsyncContext {
        gchar *sexp;
        gchar *uid;
        GMainContext *context;
+       guint32 opflags;
 };
 
 struct _SignalClosure {
@@ -197,11 +198,11 @@ run_in_thread_closure_free (RunInThreadClosure *run_in_thread_closure)
 
 /*
  * Well-known book backend properties:
- * @BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: Retrieves comma-separated list
+ * @E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: Retrieves comma-separated list
  *   of required fields by the backend. Use e_client_util_parse_comma_strings()
  *   to parse returned string value into a #GSList. These fields are required
  *   to be filled in for all contacts.
- * @BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: Retrieves comma-separated list
+ * @E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: Retrieves comma-separated list
  *   of supported fields by the backend. Use e_client_util_parse_comma_strings()
  *   to parse returned string value into a #GSList. These fields can be
  *   stored for contacts.
@@ -561,7 +562,7 @@ book_client_dbus_proxy_property_changed (EClient *client,
        }
 
        if (g_str_equal (property_name, "required-fields")) {
-               backend_prop_name = BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
+               backend_prop_name = E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
        }
 
        if (g_str_equal (property_name, "revision")) {
@@ -569,7 +570,7 @@ book_client_dbus_proxy_property_changed (EClient *client,
        }
 
        if (g_str_equal (property_name, "supported-fields")) {
-               backend_prop_name = BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
+               backend_prop_name = E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
        }
 
        if (g_str_equal (property_name, "writable")) {
@@ -904,7 +905,7 @@ book_client_get_backend_property_sync (EClient *client,
                return TRUE;
        }
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                strv = e_dbus_address_book_dup_required_fields (dbus_proxy);
                if (strv != NULL)
                        *prop_value = g_strjoinv (",", strv);
@@ -914,7 +915,7 @@ book_client_get_backend_property_sync (EClient *client,
                return TRUE;
        }
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                strv = e_dbus_address_book_dup_supported_fields (dbus_proxy);
                if (strv != NULL)
                        *prop_value = g_strjoinv (",", strv);
@@ -2012,7 +2013,7 @@ e_book_client_get_self (ESourceRegistry *registry,
        uid = NULL;
        contact = make_me_card ();
        success = e_book_client_add_contact_sync (
-               book_client, contact, &uid, NULL, error);
+               book_client, contact, E_BOOK_OPERATION_FLAG_NONE, &uid, NULL, error);
        if (!success) {
                g_object_unref (book_client);
                g_object_unref (contact);
@@ -2120,6 +2121,7 @@ book_client_add_contact_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_add_contact_sync (
                E_BOOK_CLIENT (source_object),
                async_context->contact,
+               async_context->opflags,
                &async_context->uid,
                cancellable, &local_error)) {
 
@@ -2138,6 +2140,7 @@ book_client_add_contact_thread (GSimpleAsyncResult *simple,
  * e_book_client_add_contact:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2150,10 +2153,11 @@ book_client_add_contact_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_add_contact (EBookClient *client,
-                           EContact *contact,
-                           GCancellable *cancellable,
-                           GAsyncReadyCallback callback,
-                           gpointer user_data)
+                          EContact *contact,
+                          guint32 opflags,
+                          GCancellable *cancellable,
+                          GAsyncReadyCallback callback,
+                          gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2163,6 +2167,7 @@ e_book_client_add_contact (EBookClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->contact = g_object_ref (contact);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2231,6 +2236,7 @@ e_book_client_add_contact_finish (EBookClient *client,
  * e_book_client_add_contact_sync:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_added_uid: (out): UID of a newly added contact; can be %NULL
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
@@ -2248,10 +2254,11 @@ e_book_client_add_contact_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_add_contact_sync (EBookClient *client,
-                                EContact *contact,
-                                gchar **out_added_uid,
-                                GCancellable *cancellable,
-                                GError **error)
+                               EContact *contact,
+                               guint32 opflags,
+                               gchar **out_added_uid,
+                               GCancellable *cancellable,
+                               GError **error)
 {
        GSList link = { contact, NULL };
        GSList *uids = NULL;
@@ -2261,7 +2268,7 @@ e_book_client_add_contact_sync (EBookClient *client,
        g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
 
        success = e_book_client_add_contacts_sync (
-               client, &link, &uids, cancellable, error);
+               client, &link, opflags, &uids, cancellable, error);
 
        /* Sanity check. */
        g_return_val_if_fail (
@@ -2292,6 +2299,7 @@ book_client_add_contacts_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_add_contacts_sync (
                E_BOOK_CLIENT (source_object),
                async_context->object_list,
+               async_context->opflags,
                &async_context->string_list,
                cancellable, &local_error)) {
 
@@ -2310,6 +2318,7 @@ book_client_add_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_client_add_contacts:
  * @client: an #EBookClient
  * @contacts: (element-type EContact): a #GSList of #EContact objects to add
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2322,10 +2331,11 @@ book_client_add_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_add_contacts (EBookClient *client,
-                            GSList *contacts,
-                            GCancellable *cancellable,
-                            GAsyncReadyCallback callback,
-                            gpointer user_data)
+                           GSList *contacts,
+                           guint32 opflags,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2336,6 +2346,7 @@ e_book_client_add_contacts (EBookClient *client,
        async_context = g_slice_new0 (AsyncContext);
        async_context->object_list = g_slist_copy_deep (
                contacts, (GCopyFunc) g_object_ref, NULL);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2406,6 +2417,7 @@ e_book_client_add_contacts_finish (EBookClient *client,
  * e_book_client_add_contacts_sync:
  * @client: an #EBookClient
  * @contacts: (element-type EContact): a #GSList of #EContact objects to add
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_added_uids: (out) (element-type utf8) (allow-none): UIDs of newly
  *                  added contacts; can be %NULL
  * @cancellable: a #GCancellable; can be %NULL
@@ -2427,10 +2439,11 @@ e_book_client_add_contacts_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_add_contacts_sync (EBookClient *client,
-                                 GSList *contacts,
-                                 GSList **out_added_uids,
-                                 GCancellable *cancellable,
-                                 GError **error)
+                                GSList *contacts,
+                                guint32 opflags,
+                                GSList **out_added_uids,
+                                GCancellable *cancellable,
+                                GError **error)
 {
        GSList *link;
        gchar **strv;
@@ -2455,7 +2468,7 @@ e_book_client_add_contacts_sync (EBookClient *client,
 
        e_dbus_address_book_call_create_contacts_sync (
                client->priv->dbus_proxy,
-               (const gchar * const *) strv,
+               (const gchar * const *) strv, opflags,
                &uids, cancellable, &local_error);
 
        g_strfreev (strv);
@@ -2506,6 +2519,7 @@ book_client_modify_contact_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_modify_contact_sync (
                E_BOOK_CLIENT (source_object),
                async_context->contact,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -2523,6 +2537,7 @@ book_client_modify_contact_thread (GSimpleAsyncResult *simple,
  * e_book_client_modify_contact:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2535,10 +2550,11 @@ book_client_modify_contact_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_modify_contact (EBookClient *client,
-                              EContact *contact,
-                              GCancellable *cancellable,
-                              GAsyncReadyCallback callback,
-                              gpointer user_data)
+                             EContact *contact,
+                             guint32 opflags,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2548,6 +2564,7 @@ e_book_client_modify_contact (EBookClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->contact = g_object_ref (contact);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2599,6 +2616,7 @@ e_book_client_modify_contact_finish (EBookClient *client,
  * e_book_client_modify_contact_sync:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -2610,9 +2628,10 @@ e_book_client_modify_contact_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_modify_contact_sync (EBookClient *client,
-                                   EContact *contact,
-                                   GCancellable *cancellable,
-                                   GError **error)
+                                  EContact *contact,
+                                  guint32 opflags,
+                                  GCancellable *cancellable,
+                                  GError **error)
 {
        GSList link = { contact, NULL };
 
@@ -2620,7 +2639,7 @@ e_book_client_modify_contact_sync (EBookClient *client,
        g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
 
        return e_book_client_modify_contacts_sync (
-               client, &link, cancellable, error);
+               client, &link, opflags, cancellable, error);
 }
 
 /* Helper for e_book_client_modify_contacts() */
@@ -2637,6 +2656,7 @@ book_client_modify_contacts_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_modify_contacts_sync (
                E_BOOK_CLIENT (source_object),
                async_context->object_list,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -2654,6 +2674,7 @@ book_client_modify_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_client_modify_contacts:
  * @client: an #EBookClient
  * @contacts: (element-type EContact): a #GSList of #EContact objects
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2666,10 +2687,11 @@ book_client_modify_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_modify_contacts (EBookClient *client,
-                               GSList *contacts,
-                               GCancellable *cancellable,
-                               GAsyncReadyCallback callback,
-                               gpointer user_data)
+                              GSList *contacts,
+                              guint32 opflags,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2680,6 +2702,7 @@ e_book_client_modify_contacts (EBookClient *client,
        async_context = g_slice_new0 (AsyncContext);
        async_context->object_list = g_slist_copy_deep (
                contacts, (GCopyFunc) g_object_ref, NULL);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2731,6 +2754,7 @@ e_book_client_modify_contacts_finish (EBookClient *client,
  * e_book_client_modify_contacts_sync:
  * @client: an #EBookClient
  * @contacts: (element-type EContact): a #GSList of #EContact objects
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -2742,9 +2766,10 @@ e_book_client_modify_contacts_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_modify_contacts_sync (EBookClient *client,
-                                    GSList *contacts,
-                                    GCancellable *cancellable,
-                                    GError **error)
+                                   GSList *contacts,
+                                   guint32 opflags,
+                                   GCancellable *cancellable,
+                                   GError **error)
 {
        GSList *link;
        gchar **strv;
@@ -2768,7 +2793,7 @@ e_book_client_modify_contacts_sync (EBookClient *client,
 
        e_dbus_address_book_call_modify_contacts_sync (
                client->priv->dbus_proxy,
-               (const gchar * const *) strv,
+               (const gchar * const *) strv, opflags,
                cancellable, &local_error);
 
        g_strfreev (strv);
@@ -2796,6 +2821,7 @@ book_client_remove_contact_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_remove_contact_sync (
                E_BOOK_CLIENT (source_object),
                async_context->contact,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -2813,6 +2839,7 @@ book_client_remove_contact_thread (GSimpleAsyncResult *simple,
  * e_book_client_remove_contact:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2825,10 +2852,11 @@ book_client_remove_contact_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_remove_contact (EBookClient *client,
-                              /* const */ EContact *contact,
-                              GCancellable *cancellable,
-                              GAsyncReadyCallback callback,
-                              gpointer user_data)
+                             /* const */ EContact *contact,
+                             guint32 opflags,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2838,6 +2866,7 @@ e_book_client_remove_contact (EBookClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->contact = g_object_ref (contact);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2889,6 +2918,7 @@ e_book_client_remove_contact_finish (EBookClient *client,
  * e_book_client_remove_contact_sync:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -2900,9 +2930,10 @@ e_book_client_remove_contact_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_remove_contact_sync (EBookClient *client,
-                                   EContact *contact,
-                                   GCancellable *cancellable,
-                                   GError **error)
+                                  EContact *contact,
+                                  guint32 opflags,
+                                  GCancellable *cancellable,
+                                  GError **error)
 {
        const gchar *uid;
 
@@ -2913,7 +2944,7 @@ e_book_client_remove_contact_sync (EBookClient *client,
        g_return_val_if_fail (uid != NULL, FALSE);
 
        return e_book_client_remove_contact_by_uid_sync (
-               client, uid, cancellable, error);
+               client, uid, opflags, cancellable, error);
 }
 
 /* Helper for e_book_client_remove_contact_by_uid() */
@@ -2930,6 +2961,7 @@ book_client_remove_contact_by_uid_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_remove_contact_by_uid_sync (
                E_BOOK_CLIENT (source_object),
                async_context->uid,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -2947,6 +2979,7 @@ book_client_remove_contact_by_uid_thread (GSimpleAsyncResult *simple,
  * e_book_client_remove_contact_by_uid:
  * @client: an #EBookClient
  * @uid: a UID of a contact to remove
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2959,10 +2992,11 @@ book_client_remove_contact_by_uid_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_remove_contact_by_uid (EBookClient *client,
-                                     const gchar *uid,
-                                     GCancellable *cancellable,
-                                     GAsyncReadyCallback callback,
-                                     gpointer user_data)
+                                    const gchar *uid,
+                                    guint32 opflags,
+                                    GCancellable *cancellable,
+                                    GAsyncReadyCallback callback,
+                                    gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2972,6 +3006,7 @@ e_book_client_remove_contact_by_uid (EBookClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->uid = g_strdup (uid);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -3023,6 +3058,7 @@ e_book_client_remove_contact_by_uid_finish (EBookClient *client,
  * e_book_client_remove_contact_by_uid_sync:
  * @client: an #EBookClient
  * @uid: a UID of a contact to remove
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -3034,9 +3070,10 @@ e_book_client_remove_contact_by_uid_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_remove_contact_by_uid_sync (EBookClient *client,
-                                          const gchar *uid,
-                                          GCancellable *cancellable,
-                                          GError **error)
+                                         const gchar *uid,
+                                         guint32 opflags,
+                                         GCancellable *cancellable,
+                                         GError **error)
 {
        GSList link = { (gpointer) uid, NULL };
 
@@ -3044,7 +3081,7 @@ e_book_client_remove_contact_by_uid_sync (EBookClient *client,
        g_return_val_if_fail (uid != NULL, FALSE);
 
        return e_book_client_remove_contacts_sync (
-               client, &link, cancellable, error);
+               client, &link, opflags, cancellable, error);
 }
 
 /* Helper for e_book_client_remove_contacts() */
@@ -3061,6 +3098,7 @@ book_client_remove_contacts_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_remove_contacts_sync (
                E_BOOK_CLIENT (source_object),
                async_context->string_list,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -3078,6 +3116,7 @@ book_client_remove_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_client_remove_contacts:
  * @client: an #EBookClient
  * @uids: (element-type utf8): a #GSList of UIDs to remove
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -3093,10 +3132,11 @@ book_client_remove_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_remove_contacts (EBookClient *client,
-                               const GSList *uids,
-                               GCancellable *cancellable,
-                               GAsyncReadyCallback callback,
-                               gpointer user_data)
+                              const GSList *uids,
+                              guint32 opflags,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -3107,6 +3147,7 @@ e_book_client_remove_contacts (EBookClient *client,
        async_context = g_slice_new0 (AsyncContext);
        async_context->string_list = g_slist_copy_deep (
                (GSList *) uids, (GCopyFunc) g_strdup, NULL);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -3158,6 +3199,7 @@ e_book_client_remove_contacts_finish (EBookClient *client,
  * e_book_client_remove_contacts_sync:
  * @client: an #EBookClient
  * @uids: (element-type utf8): a #GSList of UIDs to remove
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -3172,9 +3214,10 @@ e_book_client_remove_contacts_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_remove_contacts_sync (EBookClient *client,
-                                    const GSList *uids,
-                                    GCancellable *cancellable,
-                                    GError **error)
+                                   const GSList *uids,
+                                   guint32 opflags,
+                                   GCancellable *cancellable,
+                                   GError **error)
 {
        gchar **strv;
        gint ii = 0;
@@ -3191,7 +3234,7 @@ e_book_client_remove_contacts_sync (EBookClient *client,
 
        e_dbus_address_book_call_remove_contacts_sync (
                client->priv->dbus_proxy,
-               (const gchar * const *) strv,
+               (const gchar * const *) strv, opflags,
                cancellable, &local_error);
 
        g_strfreev (strv);
diff --git a/src/addressbook/libebook/e-book-client.h b/src/addressbook/libebook/e-book-client.h
index 683c07aaa..eca77f109 100644
--- a/src/addressbook/libebook/e-book-client.h
+++ b/src/addressbook/libebook/e-book-client.h
@@ -118,6 +118,7 @@ gboolean    e_book_client_set_self          (EBookClient *client,
 gboolean       e_book_client_is_self           (EContact *contact);
 void           e_book_client_add_contact       (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -128,11 +129,13 @@ gboolean  e_book_client_add_contact_finish
                                                 GError **error);
 gboolean       e_book_client_add_contact_sync  (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 gchar **out_added_uid,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_add_contacts      (EBookClient *client,
                                                 GSList *contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -143,11 +146,13 @@ gboolean  e_book_client_add_contacts_finish
                                                 GError **error);
 gboolean       e_book_client_add_contacts_sync (EBookClient *client,
                                                 GSList *contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GSList **out_added_uids,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_modify_contact    (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -158,10 +163,12 @@ gboolean  e_book_client_modify_contact_finish
 gboolean       e_book_client_modify_contact_sync
                                                (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_modify_contacts   (EBookClient *client,
                                                 GSList *contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -172,10 +179,12 @@ gboolean  e_book_client_modify_contacts_finish
 gboolean       e_book_client_modify_contacts_sync
                                                (EBookClient *client,
                                                 GSList *contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_remove_contact    (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -186,11 +195,13 @@ gboolean  e_book_client_remove_contact_finish
 gboolean       e_book_client_remove_contact_sync
                                                (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_remove_contact_by_uid
                                                (EBookClient *client,
                                                 const gchar *uid,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -201,10 +212,12 @@ gboolean  e_book_client_remove_contact_by_uid_finish
 gboolean       e_book_client_remove_contact_by_uid_sync
                                                (EBookClient *client,
                                                 const gchar *uid,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_remove_contacts   (EBookClient *client,
                                                 const GSList *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -215,6 +228,7 @@ gboolean    e_book_client_remove_contacts_finish
 gboolean       e_book_client_remove_contacts_sync
                                                (EBookClient *client,
                                                 const GSList *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_get_contact       (EBookClient *client,
@@ -300,14 +314,6 @@ gboolean   e_book_client_get_cursor_sync   (EBookClient *client,
 const gchar *  e_book_client_get_locale        (EBookClient *client);
 
 #ifndef EDS_DISABLE_DEPRECATED
-/**
- * BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS: (value "supported-auth-methods")
- *
- * Since: 3.2
- *
- * Deprecated: 3.8: The property is no longer supported.
- **/
-#define BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS   "supported-auth-methods"
 
 EBookClient *  e_book_client_new               (ESource *source,
                                                 GError **error);
diff --git a/src/addressbook/libebook/e-book-view.c b/src/addressbook/libebook/e-book-view.c
index 2a1e4beac..6a9719e54 100644
--- a/src/addressbook/libebook/e-book-view.c
+++ b/src/addressbook/libebook/e-book-view.c
@@ -123,25 +123,26 @@ book_view_complete_cb (EBookClientView *client_view,
 
        if (error == NULL) {
                status = E_BOOK_VIEW_STATUS_OK;
-       } else switch (error->code) {
-               case E_DATA_BOOK_STATUS_SUCCESS:
-                       status = E_BOOK_VIEW_STATUS_OK;
-                       break;
-               case E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED:
+       } else if (error->domain == E_CLIENT_ERROR) {
+               switch (error->code) {
+               case E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED:
                        status = E_BOOK_VIEW_STATUS_TIME_LIMIT_EXCEEDED;
                        break;
-               case E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED:
+               case E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED:
                        status = E_BOOK_VIEW_STATUS_SIZE_LIMIT_EXCEEDED;
                        break;
-               case E_DATA_BOOK_STATUS_INVALID_QUERY:
+               case E_CLIENT_ERROR_INVALID_QUERY:
                        status = E_BOOK_VIEW_ERROR_INVALID_QUERY;
                        break;
-               case E_DATA_BOOK_STATUS_QUERY_REFUSED:
+               case E_CLIENT_ERROR_QUERY_REFUSED:
                        status = E_BOOK_VIEW_ERROR_QUERY_REFUSED;
                        break;
                default:
                        status = E_BOOK_VIEW_ERROR_OTHER_ERROR;
                        break;
+               }
+       } else {
+               status = E_BOOK_VIEW_ERROR_OTHER_ERROR;
        }
 
        message = (error != NULL) ? error->message : "";
diff --git a/src/addressbook/libebook/e-book.c b/src/addressbook/libebook/e-book.c
index 3396b57c0..fd7260d4b 100644
--- a/src/addressbook/libebook/e-book.c
+++ b/src/addressbook/libebook/e-book.c
@@ -46,10 +46,6 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_BOOK, EBookPrivate))
 
-#define CLIENT_BACKEND_PROPERTY_CAPABILITIES           "capabilities"
-#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS          "required-fields"
-#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS         "supported-fields"
-
 struct _EBookPrivate {
        EBookClient *client;
        gulong backend_died_handler_id;
@@ -324,7 +320,7 @@ e_book_add_contact (EBook *book,
        g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
 
        success = e_book_client_add_contact_sync (
-               book->priv->client, contact, &added_uid, NULL, error);
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, &added_uid, NULL, error);
 
        if (added_uid != NULL) {
                e_contact_set (contact, E_CONTACT_UID, added_uid);
@@ -394,7 +390,7 @@ e_book_async_add_contact (EBook *book,
        data->closure = closure;
 
        e_book_client_add_contact (
-               book->priv->client, contact, NULL,
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                add_contact_reply, data);
 
        return TRUE;
@@ -433,7 +429,7 @@ e_book_add_contact_async (EBook *book,
        data->closure = closure;
 
        e_book_client_add_contact (
-               book->priv->client, contact, NULL,
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                add_contact_reply, data);
 
        return TRUE;
@@ -461,7 +457,7 @@ e_book_commit_contact (EBook *book,
        g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
 
        return e_book_client_modify_contact_sync (
-               book->priv->client, contact, NULL, error);
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, error);
 }
 
 static void
@@ -522,7 +518,7 @@ e_book_async_commit_contact (EBook *book,
        data->closure = closure;
 
        e_book_client_modify_contact (
-               book->priv->client, contact, NULL,
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                modify_contacts_reply, data);
 
        return TRUE;
@@ -562,7 +558,7 @@ e_book_commit_contact_async (EBook *book,
        data->closure = closure;
 
        e_book_client_modify_contact (
-               book->priv->client, contact, NULL,
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                modify_contacts_reply, data);
 
        return TRUE;
@@ -583,7 +579,7 @@ e_book_commit_contact_async (EBook *book,
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
  * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
- * an #EBookClient object with #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
+ * an #EBookClient object with #E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
  **/
 gboolean
 e_book_get_required_fields (EBook *book,
@@ -600,7 +596,7 @@ e_book_get_required_fields (EBook *book,
 
        success = e_client_get_backend_property_sync (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
                &prop_value, NULL, error);
 
        if (success && fields != NULL) {
@@ -707,7 +703,7 @@ e_book_async_get_required_fields (EBook *book,
 
        e_client_get_backend_property (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
                NULL, get_required_fields_reply, data);
 
        return TRUE;
@@ -729,7 +725,7 @@ e_book_async_get_required_fields (EBook *book,
  * Deprecated: 3.2: Use e_client_get_backend_property() and
  *                  e_client_get_backend_property_finish() on an
  *                  #EBookClient object with
- *                  #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
+ *                  #E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
  **/
 gboolean
 e_book_get_required_fields_async (EBook *book,
@@ -747,7 +743,7 @@ e_book_get_required_fields_async (EBook *book,
 
        e_client_get_backend_property (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
                NULL, get_required_fields_reply, data);
 
        return TRUE;
@@ -768,7 +764,7 @@ e_book_get_required_fields_async (EBook *book,
  * Returns: %TRUE if successful, %FALSE otherwise
  *
  * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
- * an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
+ * an #EBookClient object with #E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
  **/
 gboolean
 e_book_get_supported_fields (EBook *book,
@@ -785,7 +781,7 @@ e_book_get_supported_fields (EBook *book,
 
        success = e_client_get_backend_property_sync (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
                &prop_value, NULL, error);
 
        if (success && fields != NULL) {
@@ -893,7 +889,7 @@ e_book_async_get_supported_fields (EBook *book,
 
        e_client_get_backend_property (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
                NULL, get_supported_fields_reply, data);
 
        return TRUE;
@@ -916,7 +912,7 @@ e_book_async_get_supported_fields (EBook *book,
  * Deprecated: 3.2: Use e_client_get_backend_property() and
  *                  e_client_get_backend_property_finish() on an
  *                  #EBookClient object with
- *                  #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
+ *                  #E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
  **/
 gboolean
 e_book_get_supported_fields_async (EBook *book,
@@ -934,7 +930,7 @@ e_book_get_supported_fields_async (EBook *book,
 
        e_client_get_backend_property (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
                NULL, get_supported_fields_reply, data);
 
        return TRUE;
@@ -1193,7 +1189,7 @@ e_book_remove_contact (EBook *book,
        g_return_val_if_fail (id != NULL, FALSE);
 
        return e_book_client_remove_contact_by_uid_sync (
-               book->priv->client, id, NULL, error);
+               book->priv->client, id, E_BOOK_OPERATION_FLAG_NONE, NULL, error);
 }
 
 static void
@@ -1257,7 +1253,7 @@ e_book_remove_contacts (EBook *book,
        slist = g_slist_reverse (slist);
 
        success = e_book_client_remove_contacts_sync (
-               book->priv->client, slist, NULL, error);
+               book->priv->client, slist, E_BOOK_OPERATION_FLAG_NONE, NULL, error);
 
        g_slist_free (slist);
 
@@ -1295,7 +1291,8 @@ e_book_async_remove_contact (EBook *book,
 
        e_book_client_remove_contact (
                E_BOOK_CLIENT (book->priv->client),
-               contact, NULL, remove_contact_reply, data);
+               contact, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contact_reply, data);
 
        return TRUE;
 }
@@ -1334,7 +1331,8 @@ e_book_remove_contact_async (EBook *book,
 
        e_book_client_remove_contact (
                E_BOOK_CLIENT (book->priv->client),
-               contact, NULL, remove_contact_reply, data);
+               contact, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contact_reply, data);
 
        return TRUE;
 }
@@ -1397,7 +1395,8 @@ e_book_async_remove_contact_by_id (EBook *book,
 
        e_book_client_remove_contact_by_uid (
                E_BOOK_CLIENT (book->priv->client),
-               id, NULL, remove_contact_by_id_reply, data);
+               id, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contact_by_id_reply, data);
 
        return TRUE;
 }
@@ -1436,7 +1435,8 @@ e_book_remove_contact_by_id_async (EBook *book,
 
        e_book_client_remove_contact_by_uid (
                E_BOOK_CLIENT (book->priv->client),
-               id, NULL, remove_contact_by_id_reply, data);
+               id, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contact_by_id_reply, data);
 
        return TRUE;
 }
@@ -1509,7 +1509,8 @@ e_book_async_remove_contacts (EBook *book,
 
        e_book_client_remove_contacts (
                E_BOOK_CLIENT (book->priv->client),
-               slist, NULL, remove_contacts_reply, data);
+               slist, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contacts_reply, data);
 
        g_slist_free (slist);
 
@@ -1560,7 +1561,8 @@ e_book_remove_contacts_async (EBook *book,
 
        e_book_client_remove_contacts (
                E_BOOK_CLIENT (book->priv->client),
-               slist, NULL, remove_contacts_reply, data);
+               slist, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contacts_reply, data);
 
        g_slist_free (slist);
 
diff --git a/src/addressbook/libedata-book/CMakeLists.txt b/src/addressbook/libedata-book/CMakeLists.txt
index 8972c9bd5..15ac13a77 100644
--- a/src/addressbook/libedata-book/CMakeLists.txt
+++ b/src/addressbook/libedata-book/CMakeLists.txt
@@ -9,12 +9,13 @@ set(DEPENDENCIES
 )
 
 set(SOURCES
+       e-book-backend.c
+       e-book-backend-cache.c
        e-book-backend-factory.c
        e-book-backend-sexp.c
-       e-book-backend-summary.c
-       e-book-backend-cache.c
        e-book-backend-sqlitedb.c
-       e-book-backend.c
+       e-book-backend-summary.c
+       e-book-backend-sync.c
        e-book-cache.c
        e-book-meta-backend.c
        e-book-sqlite.c
@@ -32,10 +33,13 @@ set(SOURCES
 
 set(HEADERS
        libedata-book.h
+       e-book-backend.h
+       e-book-backend-cache.h
        e-book-backend-factory.h
        e-book-backend-sexp.h
+       e-book-backend-sqlitedb.h
        e-book-backend-summary.h
-       e-book-backend.h
+       e-book-backend-sync.h
        e-book-cache.h
        e-book-meta-backend.h
        e-book-sqlite.h
@@ -46,8 +50,6 @@ set(HEADERS
        e-data-book-cursor-cache.h
        e-data-book-cursor-sqlite.h
        e-data-book-direct.h
-       e-book-backend-cache.h
-       e-book-backend-sqlitedb.h
        e-subprocess-book-factory.h
        e-system-locale-watcher.h
 )
diff --git a/src/addressbook/libedata-book/e-book-backend-sync.c 
b/src/addressbook/libedata-book/e-book-backend-sync.c
new file mode 100644
index 000000000..852ebaea1
--- /dev/null
+++ b/src/addressbook/libedata-book/e-book-backend-sync.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Nat Friedman (nat ximian com)
+ *          Tristan Van Berkom <tristanvb openismus com>
+ */
+
+/**
+ * SECTION: e-book-backend-sync
+ * @include: libedata-book/libedata-book.h
+ * @short_description: An abstract class for implementing synchronous addressbook backends
+ *
+ * This is a descendant of the #EBookBackend, providing synchronous variants
+ * of the main methods.
+ *
+ * Since: 3.36
+ **/
+
+#include "evolution-data-server-config.h"
+
+#include <glib.h>
+
+#include "e-data-book-view.h"
+#include "e-data-book.h"
+#include "e-book-backend.h"
+#include "e-book-backend-sync.h"
+
+struct _EBookBackendSyncPrivate {
+       guint dummy;
+};
+
+G_DEFINE_TYPE (EBookBackendSync, e_book_backend_sync, E_TYPE_BOOK_BACKEND)
+
+static void
+book_backend_sync_open (EBookBackend *backend,
+                       EDataBook *book,
+                       guint32 opid,
+                       GCancellable *cancellable)
+{
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
+
+       e_book_backend_sync_open (E_BOOK_BACKEND_SYNC (backend), cancellable, &error);
+
+       e_data_book_respond_open (book, opid, error);
+}
+
+static void
+book_backend_sync_refresh (EBookBackend *backend,
+                          EDataBook *book,
+                          guint32 opid,
+                          GCancellable *cancellable)
+{
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
+
+       e_book_backend_sync_refresh (E_BOOK_BACKEND_SYNC (backend), cancellable, &error);
+
+       e_data_book_respond_refresh (book, opid, error);
+}
+
+static void
+book_backend_sync_create_contacts (EBookBackend *backend,
+                                  EDataBook *book,
+                                  guint32 opid,
+                                  GCancellable *cancellable,
+                                  const gchar * const *vcards,
+                                  guint32 opflags)
+{
+       GSList *contacts = NULL;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
+
+       e_book_backend_sync_create_contacts (E_BOOK_BACKEND_SYNC (backend), vcards, opflags, &contacts, 
cancellable, &error);
+
+       e_data_book_respond_create_contacts (book, opid, error, contacts);
+
+       g_slist_free_full (contacts, g_object_unref);
+}
+
+static void
+book_backend_sync_modify_contacts (EBookBackend *backend,
+                                  EDataBook *book,
+                                  guint32 opid,
+                                  GCancellable *cancellable,
+                                  const gchar * const *vcards,
+                                  guint32 opflags)
+{
+       GSList *contacts = NULL;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
+
+       e_book_backend_sync_modify_contacts (E_BOOK_BACKEND_SYNC (backend), vcards, opflags, &contacts, 
cancellable, &error);
+
+       e_data_book_respond_modify_contacts (book, opid, error, contacts);
+
+       g_slist_free_full (contacts, g_object_unref);
+}
+
+static void
+book_backend_sync_remove_contacts (EBookBackend *backend,
+                                  EDataBook *book,
+                                  guint32 opid,
+                                  GCancellable *cancellable,
+                                  const gchar * const *uids,
+                                  guint32 opflags)
+{
+       GSList *removed_uids = NULL;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
+
+       e_book_backend_sync_remove_contacts (E_BOOK_BACKEND_SYNC (backend), uids, opflags, &removed_uids, 
cancellable, &error);
+
+       e_data_book_respond_remove_contacts (book, opid, error, removed_uids);
+
+       g_slist_free_full (removed_uids, g_free);
+}
+
+static void
+book_backend_sync_get_contact (EBookBackend *backend,
+                              EDataBook *book,
+                              guint32 opid,
+                              GCancellable *cancellable,
+                              const gchar *uid)
+{
+       EContact *contact;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
+
+       contact = e_book_backend_sync_get_contact (E_BOOK_BACKEND_SYNC (backend), uid, cancellable, &error);
+
+       e_data_book_respond_get_contact (book, opid, error, contact);
+
+       g_clear_object (&contact);
+}
+
+static void
+book_backend_sync_get_contact_list (EBookBackend *backend,
+                                   EDataBook *book,
+                                   guint32 opid,
+                                   GCancellable *cancellable,
+                                   const gchar *query)
+{
+       GSList *contacts = NULL;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
+
+       e_book_backend_sync_get_contact_list (E_BOOK_BACKEND_SYNC (backend), query, &contacts, cancellable, 
&error);
+
+       e_data_book_respond_get_contact_list (book, opid, error, contacts);
+
+       g_slist_free_full (contacts, g_object_unref);
+}
+
+static void
+book_backend_sync_get_contact_list_uids (EBookBackend *backend,
+                                        EDataBook *book,
+                                        guint32 opid,
+                                        GCancellable *cancellable,
+                                        const gchar *query)
+{
+       GSList *uids = NULL;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
+       g_return_if_fail (E_IS_DATA_BOOK (book));
+
+       e_book_backend_sync_get_contact_list_uids (E_BOOK_BACKEND_SYNC (backend), query, &uids, cancellable, 
&error);
+
+       e_data_book_respond_get_contact_list_uids (book, opid, error, uids);
+
+       g_slist_free_full (uids, g_free);
+}
+
+static gboolean
+book_backend_sync_get_contact_list_uids_sync (EBookBackendSync *backend,
+                                             const gchar *query,
+                                             GSList **out_uids,
+                                             GCancellable *cancellable,
+                                             GError **error)
+{
+       GSList *contacts = NULL;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+       g_return_val_if_fail (out_uids != NULL, FALSE);
+
+       *out_uids = NULL;
+
+       success = e_book_backend_sync_get_contact_list (backend, query, &contacts, cancellable, error);
+
+       if (success) {
+               GSList *link;
+
+               for (link = contacts; link; link = g_slist_next (link)) {
+                       EContact *contact = link->data;
+                       gchar *uid;
+
+                       uid = e_contact_get (contact, E_CONTACT_UID);
+                       *out_uids = g_slist_prepend (*out_uids, uid);
+               }
+       }
+
+       g_slist_free_full (contacts, g_object_unref);
+
+       return success;
+}
+
+static void
+e_book_backend_sync_class_init (EBookBackendSyncClass *klass)
+{
+       EBookBackendClass *book_backend_class;
+
+       g_type_class_add_private (klass, sizeof (EBookBackendSyncPrivate));
+
+       klass->get_contact_list_uids_sync = book_backend_sync_get_contact_list_uids_sync;
+
+       book_backend_class = E_BOOK_BACKEND_CLASS (klass);
+       book_backend_class->open = book_backend_sync_open;
+       book_backend_class->refresh = book_backend_sync_refresh;
+       book_backend_class->create_contacts = book_backend_sync_create_contacts;
+       book_backend_class->modify_contacts = book_backend_sync_modify_contacts;
+       book_backend_class->remove_contacts = book_backend_sync_remove_contacts;
+       book_backend_class->get_contact = book_backend_sync_get_contact;
+       book_backend_class->get_contact_list = book_backend_sync_get_contact_list;
+       book_backend_class->get_contact_list_uids = book_backend_sync_get_contact_list_uids;
+}
+
+static void
+e_book_backend_sync_init (EBookBackendSync *backend)
+{
+       backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, E_TYPE_BOOK_BACKEND_SYNC, 
EBookBackendSyncPrivate);
+}
+
+/**
+ * e_book_backend_sync_open:
+ * @backend: an #EBookBackendSync
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * "Opens" the @backend.  Opening a backend is something of an outdated
+ * concept, but the operation is hanging around for a little while longer.
+ * This usually involves some custom initialization logic, and testing of
+ * remote authentication if applicable.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_backend_sync_open (EBookBackendSync *backend,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+       EBookBackendSyncClass *klass;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+
+       klass = E_BOOK_BACKEND_SYNC_GET_CLASS (backend);
+       g_return_val_if_fail (klass != NULL, FALSE);
+
+       if (klass->open_sync)
+               return klass->open_sync (backend, cancellable, error);
+
+       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
+
+       return FALSE;
+}
+
+/**
+ * e_book_backend_sync_refresh:
+ * @backend: an #EBookBackendSync
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Initiates a refresh for @backend, if the @backend supports refreshing.
+ * The actual refresh operation completes on its own time.  This function
+ * merely initiates the operation.
+ *
+ * If an error occurs while initiating the refresh, the function will set
+ * @error and return %FALSE.  If the @backend does not support refreshing,
+ * the function will set an %E_CLIENT_ERROR_NOT_SUPPORTED error and return
+ * %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_backend_sync_refresh (EBookBackendSync *backend,
+                            GCancellable *cancellable,
+                            GError **error)
+{
+       EBookBackendSyncClass *klass;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+
+       klass = E_BOOK_BACKEND_SYNC_GET_CLASS (backend);
+       g_return_val_if_fail (klass != NULL, FALSE);
+
+       if (klass->refresh_sync)
+               return klass->refresh_sync (backend, cancellable, error);
+
+       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
+
+       return FALSE;
+}
+
+/**
+ * e_book_backend_sync_create_contacts:
+ * @backend: an #EBookBackendSync
+ * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
+ * @out_contacts: (out) (element-type EContact): a #GSList in which to deposit results
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates one or more new contacts from @vcards, and deposits an #EContact
+ * instance for each newly-created contact in @out_contacts.
+ *
+ * The returned #EContact instances are referenced for thread-safety and
+ * must be unreferenced with g_object_unref() when finished with them.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_backend_sync_create_contacts (EBookBackendSync *backend,
+                                    const gchar * const *vcards,
+                                    guint32 opflags,
+                                    GSList **out_contacts,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+       EBookBackendSyncClass *klass;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+
+       klass = E_BOOK_BACKEND_SYNC_GET_CLASS (backend);
+       g_return_val_if_fail (klass != NULL, FALSE);
+
+       if (klass->create_contacts_sync)
+               return klass->create_contacts_sync (backend, vcards, opflags, out_contacts, cancellable, 
error);
+
+       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
+
+       return FALSE;
+}
+
+/**
+ * e_book_backend_sync_modify_contacts:
+ * @backend: an #EBookBackendSync
+ * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
+ * @out_contacts: (out) (element-type EContact): a #GSList to deposit the modified contacts to
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Modifies one or more contacts according to @vcards.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_backend_sync_modify_contacts (EBookBackendSync *backend,
+                                    const gchar * const *vcards,
+                                    guint32 opflags,
+                                    GSList **out_contacts,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+       EBookBackendSyncClass *klass;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+
+       klass = E_BOOK_BACKEND_SYNC_GET_CLASS (backend);
+       g_return_val_if_fail (klass != NULL, FALSE);
+
+       if (klass->modify_contacts_sync)
+               return klass->modify_contacts_sync (backend, vcards, opflags, out_contacts, cancellable, 
error);
+
+       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
+
+       return FALSE;
+}
+
+/**
+ * e_book_backend_sync_remove_contacts:
+ * @backend: an #EBookBackendSync
+ * @uids: a %NULL-terminated array of contact ID strings
+ * @opflags: bit-or of #EBookOperationFlags
+ * @out_removed_uids: (out) (element-type utf8): a #GSList of removed UIDs
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Removes one or more contacts according to @uids.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_backend_sync_remove_contacts (EBookBackendSync *backend,
+                                    const gchar * const *uids,
+                                    guint32 opflags,
+                                    GSList **out_removed_uids,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+       EBookBackendSyncClass *klass;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+
+       klass = E_BOOK_BACKEND_SYNC_GET_CLASS (backend);
+       g_return_val_if_fail (klass != NULL, FALSE);
+
+       if (klass->remove_contacts_sync)
+               return klass->remove_contacts_sync (backend, uids, opflags, out_removed_uids, cancellable, 
error);
+
+       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
+
+       return FALSE;
+}
+
+/**
+ * e_book_backend_sync_get_contact:
+ * @backend: an #EBookBackendSync
+ * @uid: a contact ID
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains an #EContact for @uid.
+ *
+ * The returned #EContact is referenced for thread-safety and must be
+ * unreferenced with g_object_unref() when finished with it.
+ *
+ * If an error occurs, the function will set @error and return %NULL.
+ *
+ * Returns: (transfer full): an #EContact, or %NULL
+ *
+ * Since: 3.36
+ **/
+EContact *
+e_book_backend_sync_get_contact (EBookBackendSync *backend,
+                                const gchar *uid,
+                                GCancellable *cancellable,
+                                GError **error)
+{
+       EBookBackendSyncClass *klass;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+
+       klass = E_BOOK_BACKEND_SYNC_GET_CLASS (backend);
+       g_return_val_if_fail (klass != NULL, FALSE);
+
+       if (klass->get_contact_sync)
+               return klass->get_contact_sync (backend, uid, cancellable, error);
+
+       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
+
+       return FALSE;
+}
+
+/**
+ * e_book_backend_sync_get_contact_list:
+ * @backend: an #EBookBackendSync
+ * @query: a search query in S-expression format
+ * @out_contacts: (out) (element-type EContact): a #GSList in which to deposit results
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains a set of #EContact instances which satisfy the criteria specified
+ * in @query, and deposits them in @out_contacts.
+ *
+ * The returned #EContact instances are referenced for thread-safety and
+ * must be unreferenced with g_object_unref() when finished with them.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ * Note that an empty result set does not necessarily imply an error.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_backend_sync_get_contact_list (EBookBackendSync *backend,
+                                     const gchar *query,
+                                     GSList **out_contacts,
+                                     GCancellable *cancellable,
+                                     GError **error)
+{
+       EBookBackendSyncClass *klass;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+
+       klass = E_BOOK_BACKEND_SYNC_GET_CLASS (backend);
+       g_return_val_if_fail (klass != NULL, FALSE);
+
+       if (klass->get_contact_list_sync)
+               return klass->get_contact_list_sync (backend, query, out_contacts, cancellable, error);
+
+       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
+
+       return FALSE;
+}
+
+/**
+ * e_book_backend_sync_get_contact_list_uids:
+ * @backend: an #EBookBackendSync
+ * @query: a search query in S-expression format
+ * @out_uids: (out) (element-type utf8): a #GSList in which to deposit results
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains a set of ID strings for contacts which satisfy the criteria
+ * specified in @query, and deposits them in @out_uids.
+ *
+ * The returned ID strings must be freed with g_free() with finished
+ * with them.
+ *
+ * If an error occurs, the function will set @error and return %FALSE.
+ * Note that an empty result set does not necessarily imply an error.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_backend_sync_get_contact_list_uids (EBookBackendSync *backend,
+                                          const gchar *query,
+                                          GSList **out_uids,
+                                          GCancellable *cancellable,
+                                          GError **error)
+{
+       EBookBackendSyncClass *klass;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), FALSE);
+
+       klass = E_BOOK_BACKEND_SYNC_GET_CLASS (backend);
+       g_return_val_if_fail (klass != NULL, FALSE);
+
+       if (klass->get_contact_list_uids_sync)
+               return klass->get_contact_list_uids_sync (backend, query, out_uids, cancellable, error);
+
+       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
+
+       return FALSE;
+}
diff --git a/src/addressbook/libedata-book/e-book-backend-sync.h 
b/src/addressbook/libedata-book/e-book-backend-sync.h
new file mode 100644
index 000000000..51176c8be
--- /dev/null
+++ b/src/addressbook/libedata-book/e-book-backend-sync.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Nat Friedman (nat ximian com)
+ *          Tristan Van Berkom <tristanvb openismus com>
+ */
+
+#if !defined (__LIBEDATA_BOOK_H_INSIDE__) && !defined (LIBEDATA_BOOK_COMPILATION)
+#error "Only <libedata-book/libedata-book.h> should be included directly."
+#endif
+
+#ifndef E_BOOK_BACKEND_SYNC_H
+#define E_BOOK_BACKEND_SYNC_H
+
+#include <libebook-contacts/libebook-contacts.h>
+#include <libebackend/libebackend.h>
+
+#include <libedata-book/e-book-backend.h>
+#include <libedata-book/e-data-book.h>
+#include <libedata-book/e-data-book-cursor.h>
+#include <libedata-book/e-data-book-direct.h>
+#include <libedata-book/e-data-book-view.h>
+
+/* Standard GObject macros */
+#define E_TYPE_BOOK_BACKEND_SYNC \
+       (e_book_backend_sync_get_type ())
+#define E_BOOK_BACKEND_SYNC(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_BOOK_BACKEND_SYNC, EBookBackendSync))
+#define E_BOOK_BACKEND_SYNC_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_BOOK_BACKEND_SYNC, EBookBackendSyncClass))
+#define E_IS_BOOK_BACKEND_SYNC(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_BOOK_BACKEND_SYNC))
+#define E_IS_BOOK_BACKEND_SYNC_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_BOOK_BACKEND_SYNC))
+#define E_BOOK_BACKEND_SYNC_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_BOOK_BACKEND_SYNC, EBookBackendSyncClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EBookBackendSync EBookBackendSync;
+typedef struct _EBookBackendSyncClass EBookBackendSyncClass;
+typedef struct _EBookBackendSyncPrivate EBookBackendSyncPrivate;
+
+/**
+ * EBookBackendSync:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ */
+struct _EBookBackendSync {
+       /*< private >*/
+       EBookBackend parent;
+       EBookBackendSyncPrivate *priv;
+};
+
+/**
+ * EBookBackendSyncClass:
+ * @open_sync: Open the backend
+ * @refresh_sync: Refresh the backend
+ * @create_contacts_sync: Add and store the passed vcards
+ * @modify_contacts_sync: Modify the existing contacts using the passed vcards
+ * @remove_contacts_sync: Remove the contacts specified by the passed UIDs
+ * @get_contact_sync: Fetch a contact by UID
+ * @get_contact_list_sync: Fetch a list of contacts based on a search expression
+ * @get_contact_list_uids_sync: Fetch a list of contact UIDs based on a search expression (optional)
+ *
+ * Class structure for the #EBookBackendSync class.
+ *
+ * These virtual methods must be implemented when writing
+ * an addressbook backend.
+ */
+struct _EBookBackendSyncClass {
+       /*< private >*/
+       EBookBackendClass parent_class;
+
+       /*< public >*/
+
+       gboolean        (*open_sync)            (EBookBackendSync *backend,
+                                                GCancellable *cancellable,
+                                                GError **error);
+       gboolean        (*refresh_sync)         (EBookBackendSync *backend,
+                                                GCancellable *cancellable,
+                                                GError **error);
+       gboolean        (*create_contacts_sync) (EBookBackendSync *backend,
+                                                const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_contacts, /* EContact * */
+                                                GCancellable *cancellable,
+                                                GError **error);
+       gboolean        (*modify_contacts_sync) (EBookBackendSync *backend,
+                                                const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_contacts, /* EContact * */
+                                                GCancellable *cancellable,
+                                                GError **error);
+       gboolean        (*remove_contacts_sync) (EBookBackendSync *backend,
+                                                const gchar * const *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_removed_uids, /* gchar * */
+                                                GCancellable *cancellable,
+                                                GError **error);
+       EContact *      (*get_contact_sync)     (EBookBackendSync *backend,
+                                                const gchar *uid,
+                                                GCancellable *cancellable,
+                                                GError **error);
+       gboolean        (*get_contact_list_sync)
+                                               (EBookBackendSync *backend,
+                                                const gchar *query,
+                                                GSList **out_contacts,
+                                                GCancellable *cancellable,
+                                                GError **error);
+
+       /* This method is optional.  By default, it simply calls
+        * get_contact_list_sync() and extracts UID strings from
+        * the matched EContacts.  Backends may override this if
+        * they can implement it more efficiently. */
+       gboolean        (*get_contact_list_uids_sync)
+                                               (EBookBackendSync *backend,
+                                                const gchar *query,
+                                                GSList **out_uids,
+                                                GCancellable *cancellable,
+                                                GError **error);
+
+       /* Padding for future expansion */
+       gpointer reserved_padding[20];
+};
+
+GType          e_book_backend_sync_get_type    (void) G_GNUC_CONST;
+
+gboolean       e_book_backend_sync_open        (EBookBackendSync *backend,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_book_backend_sync_refresh     (EBookBackendSync *backend,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_book_backend_sync_create_contacts
+                                               (EBookBackendSync *backend,
+                                                const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_contacts, /* EContact * */
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_book_backend_sync_modify_contacts
+                                               (EBookBackendSync *backend,
+                                                const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_contacts, /* EContact * */
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_book_backend_sync_remove_contacts
+                                               (EBookBackendSync *backend,
+                                                const gchar * const *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_removed_uids, /* gchar * */
+                                                GCancellable *cancellable,
+                                                GError **error);
+EContact *     e_book_backend_sync_get_contact (EBookBackendSync *backend,
+                                                const gchar *uid,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_book_backend_sync_get_contact_list
+                                               (EBookBackendSync *backend,
+                                                const gchar *query,
+                                                GSList **out_contacts, /* EContact * */
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_book_backend_sync_get_contact_list_uids
+                                               (EBookBackendSync *backend,
+                                                const gchar *query,
+                                                GSList **out_uids, /* gchar * */
+                                                GCancellable *cancellable,
+                                                GError **error);
+
+G_END_DECLS
+
+#endif /* E_BOOK_BACKEND_SYNC_H */
diff --git a/src/addressbook/libedata-book/e-book-backend.c b/src/addressbook/libedata-book/e-book-backend.c
index 18577618b..35dbb873d 100644
--- a/src/addressbook/libedata-book/e-book-backend.c
+++ b/src/addressbook/libedata-book/e-book-backend.c
@@ -71,11 +71,6 @@ struct _EBookBackendPrivate {
 };
 
 struct _AsyncContext {
-
-       /* Indicates if we're using the old or new style API,
-        * as method results are stashed differently for each. */
-       gboolean old_style;
-
        /* Inputs */
        gchar *uid;
        gchar *query;
@@ -89,6 +84,8 @@ struct _AsyncContext {
         * so any leftover resources can be released. */
        GQueue *object_queue;
        GQueue *string_queue;
+
+       guint32 opflags; /* bit-or of EBookOperationFlags */
 };
 
 struct _DispatchNode {
@@ -668,41 +665,6 @@ book_backend_get_backend_property (EBookBackend *backend,
        return prop_value;
 }
 
-static gboolean
-book_backend_get_contact_list_uids_sync (EBookBackend *backend,
-                                         const gchar *query,
-                                         GQueue *out_uids,
-                                         GCancellable *cancellable,
-                                         GError **error)
-{
-       EBookBackendClass *class;
-       GQueue queue = G_QUEUE_INIT;
-       gboolean success;
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_val_if_fail (class != NULL, FALSE);
-       g_return_val_if_fail (class->get_contact_list_sync != NULL, FALSE);
-
-       success = class->get_contact_list_sync (
-               backend, query, &queue, cancellable, error);
-
-       if (success) {
-               while (!g_queue_is_empty (&queue)) {
-                       EContact *contact;
-                       gchar *uid;
-
-                       contact = g_queue_pop_head (&queue);
-                       uid = e_contact_get (contact, E_CONTACT_UID);
-                       g_queue_push_tail (out_uids, uid);
-                       g_object_unref (contact);
-               }
-       }
-
-       g_warn_if_fail (g_queue_is_empty (&queue));
-
-       return success;
-}
-
 static void
 book_backend_notify_update (EBookBackend *backend,
                             const EContact *contact)
@@ -752,7 +714,6 @@ e_book_backend_class_init (EBookBackendClass *class)
 
        class->use_serial_dispatch_queue = TRUE;
        class->get_backend_property = book_backend_get_backend_property;
-       class->get_contact_list_uids_sync = book_backend_get_contact_list_uids_sync;
        class->notify_update = book_backend_notify_update;
        class->shutdown = book_backend_shutdown;
 
@@ -1133,40 +1094,8 @@ e_book_backend_open_sync (EBookBackend *backend,
 /* Helper for e_book_backend_open() */
 static void
 book_backend_open_thread (GSimpleAsyncResult *simple,
-                          GObject *source_object,
-                          GCancellable *cancellable)
-{
-       EBookBackend *backend;
-       EBookBackendClass *class;
-
-       backend = E_BOOK_BACKEND (source_object);
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-       g_return_if_fail (class->open_sync != NULL);
-
-       if (!e_book_backend_is_opened (backend)) {
-               GError *error = NULL;
-
-               e_backend_ensure_online_state_updated (E_BACKEND (backend), cancellable);
-
-               class->open_sync (backend, cancellable, &error);
-
-               if (error != NULL)
-                       g_simple_async_result_take_error (simple, error);
-       }
-
-       /* XXX Once we get rid of the old-style API we can dispatch
-        *     methods using g_simple_async_result_run_in_thread(),
-        *     which completes the GSimpleAsyncResult for us. */
-       g_simple_async_result_complete_in_idle (simple);
-}
-
-/* Helper for e_book_backend_open() */
-static void
-book_backend_open_thread_old_style (GSimpleAsyncResult *simple,
-                                    GObject *source_object,
-                                    GCancellable *cancellable)
+                         GObject *source_object,
+                         GCancellable *cancellable)
 {
        EBookBackend *backend;
        EBookBackendClass *class;
@@ -1191,7 +1120,7 @@ book_backend_open_thread_old_style (GSimpleAsyncResult *simple,
 
                e_backend_ensure_online_state_updated (E_BACKEND (backend), cancellable);
 
-               class->open (backend, data_book, opid, cancellable, FALSE);
+               class->open (backend, data_book, opid, cancellable);
        }
 
        g_object_unref (data_book);
@@ -1234,24 +1163,14 @@ e_book_backend_open (EBookBackend *backend,
 
        g_simple_async_result_set_check_cancellable (simple, cancellable);
 
-       if (class->open_sync != NULL) {
+       if (class->open != NULL) {
                book_backend_push_operation (
                        backend, simple, cancellable, TRUE,
                        book_backend_open_thread);
                book_backend_dispatch_next_operation (backend);
 
-       } else if (class->open != NULL) {
-               book_backend_push_operation (
-                       backend, simple, cancellable, TRUE,
-                       book_backend_open_thread_old_style);
-               book_backend_dispatch_next_operation (backend);
-
        } else {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_SUPPORTED));
+               g_simple_async_result_take_error (simple, e_client_error_create 
(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                g_simple_async_result_complete_in_idle (simple);
        }
 
@@ -1344,45 +1263,8 @@ e_book_backend_refresh_sync (EBookBackend *backend,
 /* Helper for e_book_backend_refresh() */
 static void
 book_backend_refresh_thread (GSimpleAsyncResult *simple,
-                             GObject *source_object,
-                             GCancellable *cancellable)
-{
-       EBookBackend *backend;
-       EBookBackendClass *class;
-
-       backend = E_BOOK_BACKEND (source_object);
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-       g_return_if_fail (class->refresh_sync != NULL);
-
-       if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
-
-       } else {
-               GError *error = NULL;
-
-               class->refresh_sync (backend, cancellable, &error);
-
-               if (error != NULL)
-                       g_simple_async_result_take_error (simple, error);
-       }
-
-       /* XXX Once we get rid of the old-style API we can dispatch
-        *     methods using g_simple_async_result_run_in_thread(),
-        *     which completes the GSimpleAsyncResult for us. */
-       g_simple_async_result_complete_in_idle (simple);
-}
-
-/* Helper for e_book_backend_refresh() */
-static void
-book_backend_refresh_thread_old_style (GSimpleAsyncResult *simple,
-                                       GObject *source_object,
-                                       GCancellable *cancellable)
+                            GObject *source_object,
+                            GCancellable *cancellable)
 {
        EBookBackend *backend;
        EBookBackendClass *class;
@@ -1398,11 +1280,7 @@ book_backend_refresh_thread_old_style (GSimpleAsyncResult *simple,
        g_return_if_fail (data_book != NULL);
 
        if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
+               g_simple_async_result_take_error (simple, e_client_error_create (E_CLIENT_ERROR_NOT_OPENED, 
NULL));
                g_simple_async_result_complete_in_idle (simple);
 
        } else {
@@ -1453,24 +1331,14 @@ e_book_backend_refresh (EBookBackend *backend,
 
        g_simple_async_result_set_check_cancellable (simple, cancellable);
 
-       if (class->refresh_sync != NULL) {
+       if (class->refresh != NULL) {
                book_backend_push_operation (
                        backend, simple, cancellable, FALSE,
                        book_backend_refresh_thread);
                book_backend_dispatch_next_operation (backend);
 
-       } else if (class->refresh != NULL) {
-               book_backend_push_operation (
-                       backend, simple, cancellable, FALSE,
-                       book_backend_refresh_thread_old_style);
-               book_backend_dispatch_next_operation (backend);
-
        } else {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_SUPPORTED));
+               g_simple_async_result_take_error (simple, e_client_error_create 
(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                g_simple_async_result_complete_in_idle (simple);
        }
 
@@ -1518,6 +1386,7 @@ e_book_backend_refresh_finish (EBookBackend *backend,
  * e_book_backend_create_contacts_sync:
  * @backend: an #EBookBackend
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_contacts: a #GQueue in which to deposit results
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -1536,10 +1405,11 @@ e_book_backend_refresh_finish (EBookBackend *backend,
  **/
 gboolean
 e_book_backend_create_contacts_sync (EBookBackend *backend,
-                                     const gchar * const *vcards,
-                                     GQueue *out_contacts,
-                                     GCancellable *cancellable,
-                                     GError **error)
+                                    const gchar * const *vcards,
+                                    guint32 opflags,
+                                    GQueue *out_contacts,
+                                    GCancellable *cancellable,
+                                    GError **error)
 {
        EAsyncClosure *closure;
        GAsyncResult *result;
@@ -1552,7 +1422,7 @@ e_book_backend_create_contacts_sync (EBookBackend *backend,
        closure = e_async_closure_new ();
 
        e_book_backend_create_contacts (
-               backend, vcards, cancellable,
+               backend, vcards, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -1568,52 +1438,8 @@ e_book_backend_create_contacts_sync (EBookBackend *backend,
 /* Helper for e_book_backend_create_contacts() */
 static void
 book_backend_create_contacts_thread (GSimpleAsyncResult *simple,
-                                     GObject *source_object,
-                                     GCancellable *cancellable)
-{
-       EBookBackend *backend;
-       EBookBackendClass *class;
-       AsyncContext *async_context;
-
-       backend = E_BOOK_BACKEND (source_object);
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-       g_return_if_fail (class->create_contacts_sync != NULL);
-
-       async_context = g_simple_async_result_get_op_res_gpointer (simple);
-
-       if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
-
-       } else {
-               GError *error = NULL;
-
-               class->create_contacts_sync (
-                       backend,
-                       (const gchar * const *) async_context->strv,
-                       async_context->object_queue,
-                       cancellable, &error);
-
-               if (error != NULL)
-                       g_simple_async_result_take_error (simple, error);
-       }
-
-       /* XXX Once we get rid of the old-style API we can dispatch
-        *     methods using g_simple_async_result_run_in_thread(),
-        *     which completes the GSimpleAsyncResult for us. */
-       g_simple_async_result_complete_in_idle (simple);
-}
-
-/* Helper for e_book_backend_create_contacts() */
-static void
-book_backend_create_contacts_thread_old_style (GSimpleAsyncResult *simple,
-                                               GObject *source_object,
-                                               GCancellable *cancellable)
+                                    GObject *source_object,
+                                    GCancellable *cancellable)
 {
        EBookBackend *backend;
        EBookBackendClass *class;
@@ -1632,33 +1458,16 @@ book_backend_create_contacts_thread_old_style (GSimpleAsyncResult *simple,
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
        if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
+               g_simple_async_result_take_error (simple, e_client_error_create (E_CLIENT_ERROR_NOT_OPENED, 
NULL));
                g_simple_async_result_complete_in_idle (simple);
 
        } else {
-               GSList *list = NULL;
                guint32 opid;
-               guint ii;
-
-               /* This is so the finish function knows which method
-                * was invoked and can gather results appropriately. */
-               async_context->old_style = TRUE;
 
                opid = book_backend_stash_operation (backend, simple);
 
-               /* The AsyncContext retains ownership of the strings. */
-               for (ii = 0; async_context->strv[ii] != NULL; ii++)
-                       list = g_slist_prepend (list, async_context->strv[ii]);
-               list = g_slist_reverse (list);
-
                class->create_contacts (
-                       backend, data_book, opid, cancellable, list);
-
-               g_slist_free (list);
+                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv, 
async_context->opflags);
        }
 
        g_object_unref (data_book);
@@ -1668,6 +1477,7 @@ book_backend_create_contacts_thread_old_style (GSimpleAsyncResult *simple,
  * e_book_backend_create_contacts:
  * @backend: an #EBookBackend
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -1682,10 +1492,11 @@ book_backend_create_contacts_thread_old_style (GSimpleAsyncResult *simple,
  **/
 void
 e_book_backend_create_contacts (EBookBackend *backend,
-                                const gchar * const *vcards,
-                                GCancellable *cancellable,
-                                GAsyncReadyCallback callback,
-                                gpointer user_data)
+                               const gchar * const *vcards,
+                               guint32 opflags,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
 {
        EBookBackendClass *class;
        GSimpleAsyncResult *simple;
@@ -1699,6 +1510,7 @@ e_book_backend_create_contacts (EBookBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->strv = g_strdupv ((gchar **) vcards);
+       async_context->opflags = opflags;
        async_context->object_queue = &async_context->result_queue;
 
        simple = g_simple_async_result_new (
@@ -1710,24 +1522,14 @@ e_book_backend_create_contacts (EBookBackend *backend,
        g_simple_async_result_set_op_res_gpointer (
                simple, async_context, (GDestroyNotify) async_context_free);
 
-       if (class->create_contacts_sync != NULL) {
+       if (class->create_contacts != NULL) {
                book_backend_push_operation (
                        backend, simple, cancellable, FALSE,
                        book_backend_create_contacts_thread);
                book_backend_dispatch_next_operation (backend);
 
-       } else if (class->create_contacts != NULL) {
-               book_backend_push_operation (
-                       backend, simple, cancellable, FALSE,
-                       book_backend_create_contacts_thread_old_style);
-               book_backend_dispatch_next_operation (backend);
-
        } else {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_SUPPORTED));
+               g_simple_async_result_take_error (simple, e_client_error_create 
(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                g_simple_async_result_complete_in_idle (simple);
        }
 
@@ -1795,6 +1597,7 @@ e_book_backend_create_contacts_finish (EBookBackend *backend,
  * e_book_backend_modify_contacts_sync:
  * @backend: an #EBookBackend
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -1808,9 +1611,10 @@ e_book_backend_create_contacts_finish (EBookBackend *backend,
  **/
 gboolean
 e_book_backend_modify_contacts_sync (EBookBackend *backend,
-                                     const gchar * const *vcards,
-                                     GCancellable *cancellable,
-                                     GError **error)
+                                    const gchar * const *vcards,
+                                    guint32 opflags,
+                                    GCancellable *cancellable,
+                                    GError **error)
 {
        EAsyncClosure *closure;
        GAsyncResult *result;
@@ -1819,7 +1623,7 @@ e_book_backend_modify_contacts_sync (EBookBackend *backend,
        closure = e_async_closure_new ();
 
        e_book_backend_modify_contacts (
-               backend, vcards, cancellable,
+               backend, vcards, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -1835,52 +1639,8 @@ e_book_backend_modify_contacts_sync (EBookBackend *backend,
 /* Helper for e_book_backend_modify_contacts() */
 static void
 book_backend_modify_contacts_thread (GSimpleAsyncResult *simple,
-                                     GObject *source_object,
-                                     GCancellable *cancellable)
-{
-       EBookBackend *backend;
-       EBookBackendClass *class;
-       AsyncContext *async_context;
-
-       backend = E_BOOK_BACKEND (source_object);
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-       g_return_if_fail (class->modify_contacts_sync != NULL);
-
-       async_context = g_simple_async_result_get_op_res_gpointer (simple);
-
-       if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
-
-       } else {
-               GError *error = NULL;
-
-               class->modify_contacts_sync (
-                       backend,
-                       (const gchar * const *) async_context->strv,
-                       async_context->object_queue,
-                       cancellable, &error);
-
-               if (error != NULL)
-                       g_simple_async_result_take_error (simple, error);
-       }
-
-       /* XXX Once we get rid of the old-style API we can dispatch
-        *     methods using g_simple_async_result_run_in_thread(),
-        *     which completes the GSimpleAsyncResult for us. */
-       g_simple_async_result_complete_in_idle (simple);
-}
-
-/* Helper for e_book_backend_modify_contacts() */
-static void
-book_backend_modify_contacts_thread_old_style (GSimpleAsyncResult *simple,
-                                               GObject *source_object,
-                                               GCancellable *cancellable)
+                                    GObject *source_object,
+                                    GCancellable *cancellable)
 {
        EBookBackend *backend;
        EBookBackendClass *class;
@@ -1899,33 +1659,16 @@ book_backend_modify_contacts_thread_old_style (GSimpleAsyncResult *simple,
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
        if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
+               g_simple_async_result_take_error (simple, e_client_error_create (E_CLIENT_ERROR_NOT_OPENED, 
NULL));
                g_simple_async_result_complete_in_idle (simple);
 
        } else {
-               GSList *list = NULL;
                guint32 opid;
-               guint ii;
-
-               /* This is so the finish function knows which method
-                * was invoked and can gather results appropriately. */
-               async_context->old_style = TRUE;
 
                opid = book_backend_stash_operation (backend, simple);
 
-               /* The AsyncContext retains ownership of the strings. */
-               for (ii = 0; async_context->strv[ii] != NULL; ii++)
-                       list = g_slist_prepend (list, async_context->strv[ii]);
-               list = g_slist_reverse (list);
-
                class->modify_contacts (
-                       backend, data_book, opid, cancellable, list);
-
-               g_slist_free (list);
+                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv, 
async_context->opflags);
        }
 
        g_object_unref (data_book);
@@ -1935,6 +1678,7 @@ book_backend_modify_contacts_thread_old_style (GSimpleAsyncResult *simple,
  * e_book_backend_modify_contacts:
  * @backend: an #EBookBackend
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -1949,10 +1693,11 @@ book_backend_modify_contacts_thread_old_style (GSimpleAsyncResult *simple,
  **/
 void
 e_book_backend_modify_contacts (EBookBackend *backend,
-                                const gchar * const *vcards,
-                                GCancellable *cancellable,
-                                GAsyncReadyCallback callback,
-                                gpointer user_data)
+                               const gchar * const *vcards,
+                               guint32 opflags,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
 {
        EBookBackendClass *class;
        GSimpleAsyncResult *simple;
@@ -1966,6 +1711,7 @@ e_book_backend_modify_contacts (EBookBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->strv = g_strdupv ((gchar **) vcards);
+       async_context->opflags = opflags;
        async_context->object_queue = &async_context->result_queue;
 
        simple = g_simple_async_result_new (
@@ -1977,24 +1723,14 @@ e_book_backend_modify_contacts (EBookBackend *backend,
        g_simple_async_result_set_op_res_gpointer (
                simple, async_context, (GDestroyNotify) async_context_free);
 
-       if (class->modify_contacts_sync != NULL) {
+       if (class->modify_contacts != NULL) {
                book_backend_push_operation (
                        backend, simple, cancellable, FALSE,
                        book_backend_modify_contacts_thread);
                book_backend_dispatch_next_operation (backend);
 
-       } else if (class->modify_contacts != NULL) {
-               book_backend_push_operation (
-                       backend, simple, cancellable, FALSE,
-                       book_backend_modify_contacts_thread_old_style);
-               book_backend_dispatch_next_operation (backend);
-
        } else {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_SUPPORTED));
+               g_simple_async_result_take_error (simple, e_client_error_create 
(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                g_simple_async_result_complete_in_idle (simple);
        }
 
@@ -2053,6 +1789,7 @@ e_book_backend_modify_contacts_finish (EBookBackend *backend,
  * e_book_backend_remove_contacts_sync:
  * @backend: an #EBookBackend
  * @uids: a %NULL-terminated array of contact ID strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -2066,9 +1803,10 @@ e_book_backend_modify_contacts_finish (EBookBackend *backend,
  **/
 gboolean
 e_book_backend_remove_contacts_sync (EBookBackend *backend,
-                                     const gchar * const *uids,
-                                     GCancellable *cancellable,
-                                     GError **error)
+                                    const gchar * const *uids,
+                                    guint32 opflags,
+                                    GCancellable *cancellable,
+                                    GError **error)
 {
        EAsyncClosure *closure;
        GAsyncResult *result;
@@ -2080,7 +1818,7 @@ e_book_backend_remove_contacts_sync (EBookBackend *backend,
        closure = e_async_closure_new ();
 
        e_book_backend_remove_contacts (
-               backend, uids, cancellable,
+               backend, uids, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -2096,51 +1834,8 @@ e_book_backend_remove_contacts_sync (EBookBackend *backend,
 /* Helper for e_book_backend_remove_contacts() */
 static void
 book_backend_remove_contacts_thread (GSimpleAsyncResult *simple,
-                                     GObject *source_object,
-                                     GCancellable *cancellable)
-{
-       EBookBackend *backend;
-       EBookBackendClass *class;
-       AsyncContext *async_context;
-
-       backend = E_BOOK_BACKEND (source_object);
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-       g_return_if_fail (class->remove_contacts_sync != NULL);
-
-       async_context = g_simple_async_result_get_op_res_gpointer (simple);
-
-       if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
-
-       } else {
-               GError *error = NULL;
-
-               class->remove_contacts_sync (
-                       backend,
-                       (const gchar * const *) async_context->strv,
-                       cancellable, &error);
-
-               if (error != NULL)
-                       g_simple_async_result_take_error (simple, error);
-       }
-
-       /* XXX Once we get rid of the old-style API we can dispatch
-        *     methods using g_simple_async_result_run_in_thread(),
-        *     which completes the GSimpleAsyncResult for us. */
-       g_simple_async_result_complete_in_idle (simple);
-}
-
-/* Helper for e_book_backend_remove_contacts() */
-static void
-book_backend_remove_contacts_thread_old_style (GSimpleAsyncResult *simple,
-                                               GObject *source_object,
-                                               GCancellable *cancellable)
+                                    GObject *source_object,
+                                    GCancellable *cancellable)
 {
        EBookBackend *backend;
        EBookBackendClass *class;
@@ -2159,33 +1854,16 @@ book_backend_remove_contacts_thread_old_style (GSimpleAsyncResult *simple,
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
        if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
+               g_simple_async_result_take_error (simple, e_client_error_create (E_CLIENT_ERROR_NOT_OPENED, 
NULL));
                g_simple_async_result_complete_in_idle (simple);
 
        } else {
-               GSList *list = NULL;
                guint32 opid;
-               guint ii;
-
-               /* This is so the finish function knows which method
-                * was invoked and can gather results appropriately. */
-               async_context->old_style = TRUE;
 
                opid = book_backend_stash_operation (backend, simple);
 
-               /* The AsyncContext retains ownership of the strings. */
-               for (ii = 0; async_context->strv[ii] != NULL; ii++)
-                       list = g_slist_prepend (list, async_context->strv[ii]);
-               list = g_slist_reverse (list);
-
                class->remove_contacts (
-                       backend, data_book, opid, cancellable, list);
-
-               g_slist_free (list);
+                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv, 
async_context->opflags);
        }
 
        g_object_unref (data_book);
@@ -2195,6 +1873,7 @@ book_backend_remove_contacts_thread_old_style (GSimpleAsyncResult *simple,
  * e_book_backend_remove_contacts:
  * @backend: an #EBookBackend
  * @uids: (array zero-terminated=1): a %NULL-terminated array of contact ID strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -2209,10 +1888,11 @@ book_backend_remove_contacts_thread_old_style (GSimpleAsyncResult *simple,
  **/
 void
 e_book_backend_remove_contacts (EBookBackend *backend,
-                                const gchar * const *uids,
-                                GCancellable *cancellable,
-                                GAsyncReadyCallback callback,
-                                gpointer user_data)
+                               const gchar * const *uids,
+                               guint32 opflags,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
 {
        EBookBackendClass *class;
        GSimpleAsyncResult *simple;
@@ -2226,6 +1906,7 @@ e_book_backend_remove_contacts (EBookBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->strv = g_strdupv ((gchar **) uids);
+       async_context->opflags = opflags;
        async_context->string_queue = &async_context->result_queue;
 
        simple = g_simple_async_result_new (
@@ -2237,24 +1918,14 @@ e_book_backend_remove_contacts (EBookBackend *backend,
        g_simple_async_result_set_op_res_gpointer (
                simple, async_context, (GDestroyNotify) async_context_free);
 
-       if (class->remove_contacts_sync != NULL) {
+       if (class->remove_contacts != NULL) {
                book_backend_push_operation (
                        backend, simple, cancellable, FALSE,
                        book_backend_remove_contacts_thread);
                book_backend_dispatch_next_operation (backend);
 
-       } else if (class->remove_contacts != NULL) {
-               book_backend_push_operation (
-                       backend, simple, cancellable, FALSE,
-                       book_backend_remove_contacts_thread_old_style);
-               book_backend_dispatch_next_operation (backend);
-
        } else {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_SUPPORTED));
+               g_simple_async_result_take_error (simple, e_client_error_create 
(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                g_simple_async_result_complete_in_idle (simple);
        }
 
@@ -2357,51 +2028,8 @@ e_book_backend_get_contact_sync (EBookBackend *backend,
 /* Helper for e_book_backend_get_contact() */
 static void
 book_backend_get_contact_thread (GSimpleAsyncResult *simple,
-                                 GObject *source_object,
-                                 GCancellable *cancellable)
-{
-       EBookBackend *backend;
-       EBookBackendClass *class;
-       AsyncContext *async_context;
-
-       backend = E_BOOK_BACKEND (source_object);
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-       g_return_if_fail (class->get_contact_sync != NULL);
-
-       async_context = g_simple_async_result_get_op_res_gpointer (simple);
-
-       if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
-
-       } else {
-               GError *error = NULL;
-
-               async_context->contact = class->get_contact_sync (
-                       backend,
-                       async_context->uid,
-                       cancellable, &error);
-
-               if (error != NULL)
-                       g_simple_async_result_take_error (simple, error);
-       }
-
-       /* XXX Once we get rid of the old-style API we can dispatch
-        *     methods using g_simple_async_result_run_in_thread(),
-        *     which completes the GSimpleAsyncResult for us. */
-       g_simple_async_result_complete_in_idle (simple);
-}
-
-/* Helper for e_book_backend_get_contact() */
-static void
-book_backend_get_contact_thread_old_style (GSimpleAsyncResult *simple,
-                                           GObject *source_object,
-                                           GCancellable *cancellable)
+                                GObject *source_object,
+                                GCancellable *cancellable)
 {
        EBookBackend *backend;
        EBookBackendClass *class;
@@ -2420,20 +2048,12 @@ book_backend_get_contact_thread_old_style (GSimpleAsyncResult *simple,
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
        if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
+               g_simple_async_result_take_error (simple, e_client_error_create (E_CLIENT_ERROR_NOT_OPENED, 
NULL));
                g_simple_async_result_complete_in_idle (simple);
 
        } else {
                guint32 opid;
 
-               /* This is so the finish function knows which method
-                * was invoked and can gather results appropriately. */
-               async_context->old_style = TRUE;
-
                opid = book_backend_stash_operation (backend, simple);
 
                class->get_contact (
@@ -2490,24 +2110,14 @@ e_book_backend_get_contact (EBookBackend *backend,
        g_simple_async_result_set_op_res_gpointer (
                simple, async_context, (GDestroyNotify) async_context_free);
 
-       if (class->get_contact_sync != NULL) {
+       if (class->get_contact != NULL) {
                book_backend_push_operation (
                        backend, simple, cancellable, FALSE,
                        book_backend_get_contact_thread);
                book_backend_dispatch_next_operation (backend);
 
-       } else if (class->get_contact != NULL) {
-               book_backend_push_operation (
-                       backend, simple, cancellable, FALSE,
-                       book_backend_get_contact_thread_old_style);
-               book_backend_dispatch_next_operation (backend);
-
        } else {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_SUPPORTED));
+               g_simple_async_result_take_error (simple, e_client_error_create 
(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                g_simple_async_result_complete_in_idle (simple);
        }
 
@@ -2537,6 +2147,7 @@ e_book_backend_get_contact_finish (EBookBackend *backend,
                                    GError **error)
 {
        GSimpleAsyncResult *simple;
+       GQueue *queue;
        AsyncContext *async_context;
 
        g_return_val_if_fail (
@@ -2554,12 +2165,10 @@ e_book_backend_get_contact_finish (EBookBackend *backend,
 
        /* XXX e_data_book_respond_get_contact() stuffs the
         *     resulting EContact into the object queue. */
-       if (async_context->old_style) {
-               GQueue *queue = async_context->object_queue;
-               g_warn_if_fail (async_context->contact == NULL);
-               async_context->contact = g_queue_pop_head (queue);
-               g_warn_if_fail (g_queue_is_empty (queue));
-       }
+       queue = async_context->object_queue;
+       g_warn_if_fail (async_context->contact == NULL);
+       async_context->contact = g_queue_pop_head (queue);
+       g_warn_if_fail (g_queue_is_empty (queue));
 
        g_return_val_if_fail (E_IS_CONTACT (async_context->contact), NULL);
 
@@ -2621,52 +2230,8 @@ e_book_backend_get_contact_list_sync (EBookBackend *backend,
 /* Helper for e_book_backend_get_contact_list() */
 static void
 book_backend_get_contact_list_thread (GSimpleAsyncResult *simple,
-                                      GObject *source_object,
-                                      GCancellable *cancellable)
-{
-       EBookBackend *backend;
-       EBookBackendClass *class;
-       AsyncContext *async_context;
-
-       backend = E_BOOK_BACKEND (source_object);
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-       g_return_if_fail (class->get_contact_list_sync != NULL);
-
-       async_context = g_simple_async_result_get_op_res_gpointer (simple);
-
-       if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
-
-       } else {
-               GError *error = NULL;
-
-               class->get_contact_list_sync (
-                       backend,
-                       async_context->query,
-                       async_context->object_queue,
-                       cancellable, &error);
-
-               if (error != NULL)
-                       g_simple_async_result_take_error (simple, error);
-       }
-
-       /* XXX Once we get rid of the old-style API we can dispatch
-        *     methods using g_simple_async_result_run_in_thread(),
-        *     which completes the GSimpleAsyncResult for us. */
-       g_simple_async_result_complete_in_idle (simple);
-}
-
-/* Helper for e_book_backend_get_contact_list() */
-static void
-book_backend_get_contact_list_thread_old_style (GSimpleAsyncResult *simple,
-                                                GObject *source_object,
-                                                GCancellable *cancellable)
+                                     GObject *source_object,
+                                     GCancellable *cancellable)
 {
        EBookBackend *backend;
        EBookBackendClass *class;
@@ -2685,20 +2250,12 @@ book_backend_get_contact_list_thread_old_style (GSimpleAsyncResult *simple,
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
        if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
+               g_simple_async_result_take_error (simple, e_client_error_create (E_CLIENT_ERROR_NOT_OPENED, 
NULL));
                g_simple_async_result_complete_in_idle (simple);
 
        } else {
                guint32 opid;
 
-               /* This is so the finish function knows which method
-                * was invoked and can gather results appropriately. */
-               async_context->old_style = TRUE;
-
                opid = book_backend_stash_operation (backend, simple);
 
                class->get_contact_list (
@@ -2756,24 +2313,14 @@ e_book_backend_get_contact_list (EBookBackend *backend,
        g_simple_async_result_set_op_res_gpointer (
                simple, async_context, (GDestroyNotify) async_context_free);
 
-       if (class->get_contact_list_sync != NULL) {
+       if (class->get_contact_list != NULL) {
                book_backend_push_operation (
                        backend, simple, cancellable, FALSE,
                        book_backend_get_contact_list_thread);
                book_backend_dispatch_next_operation (backend);
 
-       } else if (class->get_contact_list != NULL) {
-               book_backend_push_operation (
-                       backend, simple, cancellable, FALSE,
-                       book_backend_get_contact_list_thread_old_style);
-               book_backend_dispatch_next_operation (backend);
-
        } else {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_SUPPORTED));
+               g_simple_async_result_take_error (simple, e_client_error_create 
(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                g_simple_async_result_complete_in_idle (simple);
        }
 
@@ -2883,52 +2430,8 @@ e_book_backend_get_contact_list_uids_sync (EBookBackend *backend,
 /* Helper for e_book_backend_get_contact_list_uids() */
 static void
 book_backend_get_contact_list_uids_thread (GSimpleAsyncResult *simple,
-                                           GObject *source_object,
-                                           GCancellable *cancellable)
-{
-       EBookBackend *backend;
-       EBookBackendClass *class;
-       AsyncContext *async_context;
-
-       backend = E_BOOK_BACKEND (source_object);
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-       g_return_if_fail (class->get_contact_list_uids_sync != NULL);
-
-       async_context = g_simple_async_result_get_op_res_gpointer (simple);
-
-       if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
-
-       } else {
-               GError *error = NULL;
-
-               class->get_contact_list_uids_sync (
-                       backend,
-                       async_context->query,
-                       async_context->string_queue,
-                       cancellable, &error);
-
-               if (error != NULL)
-                       g_simple_async_result_take_error (simple, error);
-       }
-
-       /* XXX Once we get rid of the old-style API we can dispatch
-        *     methods using g_simple_async_result_run_in_thread(),
-        *     which completes the GSimpleAsyncResult for us. */
-       g_simple_async_result_complete_in_idle (simple);
-}
-
-/* Helper for e_book_backend_get_contact_list_uids() */
-static void
-book_backend_get_contact_list_uids_thread_old_style (GSimpleAsyncResult *simple,
-                                                     GObject *source_object,
-                                                     GCancellable *cancellable)
+                                          GObject *source_object,
+                                          GCancellable *cancellable)
 {
        EBookBackend *backend;
        EBookBackendClass *class;
@@ -2947,20 +2450,12 @@ book_backend_get_contact_list_uids_thread_old_style (GSimpleAsyncResult *simple,
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
        if (!e_book_backend_is_opened (backend)) {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_OPENED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_OPENED));
+               g_simple_async_result_take_error (simple, e_client_error_create (E_CLIENT_ERROR_NOT_OPENED, 
NULL));
                g_simple_async_result_complete_in_idle (simple);
 
        } else {
                guint32 opid;
 
-               /* This is so the finish function knows which method
-                * was invoked and can gather results appropriately. */
-               async_context->old_style = TRUE;
-
                opid = book_backend_stash_operation (backend, simple);
 
                class->get_contact_list_uids (
@@ -3018,24 +2513,14 @@ e_book_backend_get_contact_list_uids (EBookBackend *backend,
        g_simple_async_result_set_op_res_gpointer (
                simple, async_context, (GDestroyNotify) async_context_free);
 
-       if (class->get_contact_list_uids_sync != NULL) {
+       if (class->get_contact_list_uids != NULL) {
                book_backend_push_operation (
                        backend, simple, cancellable, FALSE,
                        book_backend_get_contact_list_uids_thread);
                book_backend_dispatch_next_operation (backend);
 
-       } else if (class->get_contact_list_uids != NULL) {
-               book_backend_push_operation (
-                       backend, simple, cancellable, FALSE,
-                       book_backend_get_contact_list_uids_thread_old_style);
-               book_backend_dispatch_next_operation (backend);
-
        } else {
-               g_simple_async_result_set_error (
-                       simple, E_CLIENT_ERROR,
-                       E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "%s", e_client_error_to_string (
-                       E_CLIENT_ERROR_NOT_SUPPORTED));
+               g_simple_async_result_take_error (simple, e_client_error_create 
(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                g_simple_async_result_complete_in_idle (simple);
        }
 
@@ -3359,35 +2844,6 @@ e_book_backend_configure_direct (EBookBackend *backend,
                class->configure_direct (backend, config);
 }
 
-/**
- * e_book_backend_sync:
- * @backend: an #EBookBackend
- *
- * Write all pending data to disk.  This is only required under special
- * circumstances (for example before a live backup) and should not be used in
- * normal use.
- *
- * Since: 1.12
- */
-void
-e_book_backend_sync (EBookBackend *backend)
-{
-       EBookBackendClass *class;
-
-       g_return_if_fail (E_IS_BOOK_BACKEND (backend));
-
-       class = E_BOOK_BACKEND_GET_CLASS (backend);
-       g_return_if_fail (class != NULL);
-
-       if (class->sync) {
-               g_object_ref (backend);
-
-               class->sync (backend);
-
-               g_object_unref (backend);
-       }
-}
-
 /**
  * e_book_backend_set_locale:
  * @backend: an #EBookBackend
@@ -3701,7 +3157,7 @@ e_book_backend_create_cursor (EBookBackend *backend,
                        error,
                        E_CLIENT_ERROR,
                        E_CLIENT_ERROR_NOT_SUPPORTED,
-                       "Addressbook backend does not support cursors");
+                       _("Addressbook backend does not support cursors"));
        }
 
        return cursor;
diff --git a/src/addressbook/libedata-book/e-book-backend.h b/src/addressbook/libedata-book/e-book-backend.h
index d53cf5e81..ac32eb523 100644
--- a/src/addressbook/libedata-book/e-book-backend.h
+++ b/src/addressbook/libedata-book/e-book-backend.h
@@ -77,14 +77,14 @@ struct _EBookBackend {
  * @use_serial_dispatch_queue: Whether a serial dispatch queue should
  *                             be used for this backend or not. The default is %TRUE.
  * @get_backend_property: Fetch a property value by name from the backend
- * @open_sync: Open the backend
- * @refresh_sync: Refresh the backend
- * @create_contacts_sync: Add and store the passed vcards
- * @modify_contacts_sync: Modify the existing contacts using the passed vcards
- * @remove_contacts_sync: Remove the contacts specified by the passed UIDs
- * @get_contact_sync: Fetch a contact by UID
- * @get_contact_list_sync: Fetch a list of contacts based on a search expression
- * @get_contact_list_uids_sync: Fetch a list of contact UIDs based on a search expression (optional)
+ * @open: Open the backend
+ * @refresh: Refresh the backend
+ * @create_contacts: Add and store the passed vcards
+ * @modify_contacts: Modify the existing contacts using the passed vcards
+ * @remove_contacts: Remove the contacts specified by the passed UIDs
+ * @get_contact: Fetch a contact by UID
+ * @get_contact_list: Fetch a list of contacts based on a search expression
+ * @get_contact_list_uids: Fetch a list of contact UIDs based on a search expression
  * @start_view: Start up the specified view
  * @stop_view: Stop the specified view
  * @notify_update: Notify changes which might have occured for a given contact
@@ -93,21 +93,12 @@ struct _EBookBackend {
  * @configure_direct: For addressbook backends which support Direct Read Access, configure a
  *                    backend instantiated on the client side for Direct Read Access, using data
  *                    reported from the server via the @get_direct_book method.
- * @sync: Sync the backend's persistance
  * @set_locale: Store & remember the passed locale setting
  * @dup_locale: Return the currently set locale setting (must be a string duplicate, for thread safety).
  * @create_cursor: Create an #EDataBookCursor
  * @delete_cursor: Delete an #EDataBookCursor previously created by this backend
  * @closed: A signal notifying that the backend was closed
  * @shutdown: A signal notifying that the backend is being shut down
- * @open: Deprecated method
- * @refresh: Deprecated method
- * @create_contacts: Deprecated method
- * @remove_contacts: Deprecated method
- * @modify_contacts: Deprecated method
- * @get_contact: Deprecated method
- * @get_contact_list: Deprecated method
- * @get_contact_list_uids: Deprecated method
  *
  * Class structure for the #EBookBackend class.
  *
@@ -130,55 +121,10 @@ struct _EBookBackendClass {
        gchar *         (*get_backend_property) (EBookBackend *backend,
                                                 const gchar *prop_name);
 
-       gboolean        (*open_sync)            (EBookBackend *backend,
-                                                GCancellable *cancellable,
-                                                GError **error);
-       gboolean        (*refresh_sync)         (EBookBackend *backend,
-                                                GCancellable *cancellable,
-                                                GError **error);
-       gboolean        (*create_contacts_sync) (EBookBackend *backend,
-                                                const gchar * const *vcards,
-                                                GQueue *out_contacts,
-                                                GCancellable *cancellable,
-                                                GError **error);
-       gboolean        (*modify_contacts_sync) (EBookBackend *backend,
-                                                const gchar * const *vcards,
-                                                GQueue *out_contacts,
-                                                GCancellable *cancellable,
-                                                GError **error);
-       gboolean        (*remove_contacts_sync) (EBookBackend *backend,
-                                                const gchar * const *uids,
-                                                GCancellable *cancellable,
-                                                GError **error);
-       EContact *      (*get_contact_sync)     (EBookBackend *backend,
-                                                const gchar *uid,
-                                                GCancellable *cancellable,
-                                                GError **error);
-       gboolean        (*get_contact_list_sync)
-                                               (EBookBackend *backend,
-                                                const gchar *query,
-                                                GQueue *out_contacts,
-                                                GCancellable *cancellable,
-                                                GError **error);
-
-       /* This method is optional.  By default, it simply calls
-        * get_contact_list_sync() and extracts UID strings from
-        * the matched EContacts.  Backends may override this if
-        * they can implement it more efficiently. */
-       gboolean        (*get_contact_list_uids_sync)
-                                               (EBookBackend *backend,
-                                                const gchar *query,
-                                                GQueue *out_uids,
-                                                GCancellable *cancellable,
-                                                GError **error);
-
-       /* These methods are deprecated and will be removed once all
-        * known subclasses are converted to the new methods above. */
        void            (*open)                 (EBookBackend *backend,
                                                 EDataBook *book,
                                                 guint32 opid,
-                                                GCancellable *cancellable,
-                                                gboolean only_if_exists);
+                                                GCancellable *cancellable);
        void            (*refresh)              (EBookBackend *backend,
                                                 EDataBook *book,
                                                 guint32 opid,
@@ -187,17 +133,20 @@ struct _EBookBackendClass {
                                                 EDataBook *book,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const GSList *vcards);
-       void            (*remove_contacts)      (EBookBackend *backend,
+                                                const gchar * const *vcards,
+                                                guint32 opflags); /* bit-or of EBookOperationFlags */
+       void            (*modify_contacts)      (EBookBackend *backend,
                                                 EDataBook *book,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const GSList *id_list);
-       void            (*modify_contacts)      (EBookBackend *backend,
+                                                const gchar * const *vcards,
+                                                guint32 opflags); /* bit-or of EBookOperationFlags */
+       void            (*remove_contacts)      (EBookBackend *backend,
                                                 EDataBook *book,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const GSList *vcards);
+                                                const gchar * const *uids,
+                                                guint32 opflags); /* bit-or of EBookOperationFlags */
        void            (*get_contact)          (EBookBackend *backend,
                                                 EDataBook *book,
                                                 guint32 opid,
@@ -228,8 +177,6 @@ struct _EBookBackendClass {
        void            (*configure_direct)     (EBookBackend *backend,
                                                 const gchar *config);
 
-       void            (*sync)                 (EBookBackend *backend);
-
        gboolean        (*set_locale)           (EBookBackend *backend,
                                                 const gchar *locale,
                                                 GCancellable *cancellable,
@@ -249,6 +196,9 @@ struct _EBookBackendClass {
        void            (*closed)               (EBookBackend *backend,
                                                 const gchar *sender);
        void            (*shutdown)             (EBookBackend *backend);
+
+       /* Padding for future expansion */
+       gpointer reserved_padding[20];
 };
 
 GType          e_book_backend_get_type         (void) G_GNUC_CONST;
@@ -298,11 +248,13 @@ gboolean  e_book_backend_refresh_finish   (EBookBackend *backend,
 gboolean       e_book_backend_create_contacts_sync
                                                (EBookBackend *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GQueue *out_contacts,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_backend_create_contacts  (EBookBackend *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -314,10 +266,12 @@ gboolean  e_book_backend_create_contacts_finish
 gboolean       e_book_backend_modify_contacts_sync
                                                (EBookBackend *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_backend_modify_contacts  (EBookBackend *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -328,10 +282,12 @@ gboolean  e_book_backend_modify_contacts_finish
 gboolean       e_book_backend_remove_contacts_sync
                                                (EBookBackend *backend,
                                                 const gchar * const *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_backend_remove_contacts  (EBookBackend *backend,
                                                 const gchar * const *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
diff --git a/src/addressbook/libedata-book/e-book-cache.c b/src/addressbook/libedata-book/e-book-cache.c
index 694146b20..b10beb08c 100644
--- a/src/addressbook/libedata-book/e-book-cache.c
+++ b/src/addressbook/libedata-book/e-book-cache.c
@@ -96,6 +96,7 @@
 #define INDEX_FLAG(type)  (1 << E_BOOK_INDEX_##type)
 
 #define EBC_COLUMN_EXTRA       "bdata"
+#define EBC_COLUMN_CUSTOM_FLAGS        "custom_flags"
 
 typedef struct {
        EContactField field_id;         /* The EContact field */
@@ -3063,11 +3064,15 @@ ebc_generate_select (EBookCache *book_cache,
                g_string_append (string, "summary." E_CACHE_COLUMN_REVISION ",");
                g_string_append (string, "summary." E_CACHE_COLUMN_OBJECT ",");
                g_string_append (string, "summary." E_CACHE_COLUMN_STATE ",");
-               g_string_append (string, "summary." EBC_COLUMN_EXTRA " ");
+               g_string_append (string, "summary." EBC_COLUMN_EXTRA ",");
+               g_string_append (string, "summary." EBC_COLUMN_CUSTOM_FLAGS " ");
                break;
        case SEARCH_UID_AND_REV:
                callback = ebc_search_meta_contacts_cb;
-               g_string_append (string, "summary." E_CACHE_COLUMN_UID ", summary." E_CACHE_COLUMN_REVISION 
", summary." EBC_COLUMN_EXTRA " ");
+               g_string_append (string, "summary." E_CACHE_COLUMN_UID ",");
+               g_string_append (string, "summary." E_CACHE_COLUMN_REVISION ",");
+               g_string_append (string, "summary." EBC_COLUMN_EXTRA ",");
+               g_string_append (string, "summary." EBC_COLUMN_CUSTOM_FLAGS " ");
                break;
        case SEARCH_UID:
                callback = ebc_search_uids_cb;
@@ -3252,6 +3257,7 @@ struct EBCSearchData {
        gint revision_index;
        gint object_index;
        gint extra_index;
+       gint custom_flags_index;
        gint state_index;
 
        EBookCacheInternalSearchFunc func;
@@ -3270,6 +3276,7 @@ ebc_search_select_cb (ECache *cache,
 {
        struct EBCSearchData *sd = user_data;
        const gchar *object = NULL, *extra = NULL;
+       guint32 custom_flags = 0;
        EOfflineState offline_state = E_OFFLINE_STATE_UNKNOWN;
 
        g_return_val_if_fail (sd != NULL, FALSE);
@@ -3280,6 +3287,7 @@ ebc_search_select_cb (ECache *cache,
            sd->revision_index == -1 ||
            sd->object_index == -1 ||
            sd->extra_index == -1 ||
+           sd->custom_flags_index == -1 ||
            sd->state_index == -1) {
                gint ii;
 
@@ -3287,6 +3295,7 @@ ebc_search_select_cb (ECache *cache,
                     sd->revision_index == -1 ||
                     sd->object_index == -1 ||
                     sd->extra_index == -1 ||
+                    sd->custom_flags_index == -1 ||
                     sd->state_index == -1); ii++) {
                        const gchar *cname = column_names[ii];
 
@@ -3304,6 +3313,8 @@ ebc_search_select_cb (ECache *cache,
                                sd->object_index = ii;
                        } else if (sd->extra_index == -1 && g_ascii_strcasecmp (cname, EBC_COLUMN_EXTRA) == 
0) {
                                sd->extra_index = ii;
+                       } else if (sd->custom_flags_index == -1 && g_ascii_strcasecmp (cname, 
EBC_COLUMN_CUSTOM_FLAGS) == 0) {
+                               sd->custom_flags_index = ii;
                        } else if (sd->state_index == -1 && g_ascii_strcasecmp (cname, E_CACHE_COLUMN_STATE) 
== 0) {
                                sd->state_index = ii;
                        }
@@ -3323,6 +3334,12 @@ ebc_search_select_cb (ECache *cache,
                extra = column_values[sd->extra_index];
        }
 
+       if (sd->custom_flags_index != -2) {
+               g_return_val_if_fail (sd->custom_flags_index >= 0 && sd->custom_flags_index < ncols, FALSE);
+               if (column_values[sd->custom_flags_index])
+                       custom_flags = g_ascii_strtoull (column_values[sd->custom_flags_index], NULL, 10);
+       }
+
        if (sd->state_index != -2) {
                g_return_val_if_fail (sd->extra_index >= 0 && sd->extra_index < ncols, FALSE);
 
@@ -3334,7 +3351,7 @@ ebc_search_select_cb (ECache *cache,
 
        if (sd->user_func) {
                return sd->user_func (E_BOOK_CACHE (cache), column_values[sd->uid_index], 
column_values[sd->revision_index],
-                       object, extra, offline_state, sd->user_func_user_data);
+                       object, extra, custom_flags, offline_state, sd->user_func_user_data);
        }
 
        sd->func (cache, column_values[sd->uid_index], column_values[sd->revision_index], object, extra, 
sd->out_value);
@@ -3394,6 +3411,7 @@ ebc_do_search_query (EBookCache *book_cache,
                sd.revision_index = -1;
                sd.object_index = search_type == SEARCH_FULL ? -1 : -2;
                sd.extra_index = search_type == SEARCH_UID ? -2 : -1;
+               sd.custom_flags_index = search_type == SEARCH_UID ? -2 : -1;
                sd.state_index = search_type == SEARCH_FULL ? -1 : -2;
                sd.out_value = out_value;
                sd.user_func = func;
@@ -4196,6 +4214,26 @@ e_book_cache_get_strings (ECache *cache,
        return TRUE;
 }
 
+static gboolean
+e_book_cache_get_uint64_cb (ECache *cache,
+                           gint ncols,
+                           const gchar **column_names,
+                           const gchar **column_values,
+                           gpointer user_data)
+{
+       guint64 *pui64 = user_data;
+
+       g_return_val_if_fail (pui64 != NULL, FALSE);
+
+       if (ncols == 1) {
+               *pui64 = column_values[0] ? g_ascii_strtoull (column_values[0], NULL, 10) : 0;
+       } else {
+               *pui64 = 0;
+       }
+
+       return TRUE;
+}
+
 static gboolean
 e_book_cache_get_old_contacts_cb (ECache *cache,
                                  gint ncols,
@@ -4298,7 +4336,7 @@ e_book_cache_migrate (ECache *cache,
                                if (!contact)
                                        continue;
 
-                               success = e_book_cache_put_contact (book_cache, contact, data->extra, 
E_CACHE_IS_ONLINE, cancellable, error);
+                               success = e_book_cache_put_contact (book_cache, contact, data->extra, 0, 
E_CACHE_IS_ONLINE, cancellable, error);
                        }
                }
 
@@ -4366,6 +4404,7 @@ e_book_cache_populate_other_columns (EBookCache *book_cache,
                } G_STMT_END
 
        add_column (EBC_COLUMN_EXTRA, "TEXT", NULL);
+       add_column (EBC_COLUMN_CUSTOM_FLAGS, "INTEGER", NULL);
 
        use_default = !setup;
 
@@ -4796,7 +4835,8 @@ e_book_cache_ref_collator (EBookCache *book_cache)
  * e_book_cache_put_contact:
  * @book_cache: An #EBookCache
  * @contact: an #EContact to be added
- * @extra: extra data to store in association with this contact
+ * @extra: (nullable): extra data to store in association with this @contact
+ * @custom_flags: custom flags for the @contact, not interpreted by the @book_cache
  * @offline_flag: one of #ECacheOfflineFlag, whether putting this contact in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -4812,11 +4852,12 @@ gboolean
 e_book_cache_put_contact (EBookCache *book_cache,
                          EContact *contact,
                          const gchar *extra,
+                         guint32 custom_flags,
                          ECacheOfflineFlag offline_flag,
                          GCancellable *cancellable,
                          GError **error)
 {
-       GSList *contacts, *extras;
+       GSList *contacts, *extras, *custom_flags_lst;
        gboolean success;
 
        g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
@@ -4824,9 +4865,11 @@ e_book_cache_put_contact (EBookCache *book_cache,
 
        contacts = g_slist_append (NULL, contact);
        extras = g_slist_append (NULL, (gpointer) extra);
+       custom_flags_lst = g_slist_append (NULL, GUINT_TO_POINTER (custom_flags));
 
-       success = e_book_cache_put_contacts (book_cache, contacts, extras, offline_flag, cancellable, error);
+       success = e_book_cache_put_contacts (book_cache, contacts, extras, custom_flags_lst, offline_flag, 
cancellable, error);
 
+       g_slist_free (custom_flags_lst);
        g_slist_free (contacts);
        g_slist_free (extras);
 
@@ -4838,15 +4881,17 @@ e_book_cache_put_contact (EBookCache *book_cache,
  * @book_cache: An #EBookCache
  * @contacts: (element-type EContact): A list of contacts to add to @book_cache
  * @extras: (nullable) (element-type utf8): A list of extra data to store in association with the @contacts
+ * @custom_flags: (nullable) (element-type guint32): optional custom flags to use for the @contacts
  * @offline_flag: one of #ECacheOfflineFlag, whether putting these contacts in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Adds or replaces contacts in @book_cache.
  *
- * If @extras is specified, it must have an equal length as the @contacts list. Each element
- * from the @extras list will be stored in association with its corresponding contact
- * in the @contacts list.
+ * If @extras is specified, it must have an equal length as the @contacts list.
+ * Similarly the non-NULL @custom_flags length should be the same as the length of the @contacts.
+ * Each element from the @extras list and @custom_flags list will be stored in association
+ * with its corresponding contact in the @contacts list.
  *
  * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
  *
@@ -4856,11 +4901,12 @@ gboolean
 e_book_cache_put_contacts (EBookCache *book_cache,
                           const GSList *contacts,
                           const GSList *extras,
+                          const GSList *custom_flags,
                           ECacheOfflineFlag offline_flag,
                           GCancellable *cancellable,
                           GError **error)
 {
-       const GSList *clink, *elink;
+       const GSList *clink, *elink, *flink;
        ECache *cache;
        ECacheColumnValues *other_columns;
        gboolean success;
@@ -4868,6 +4914,7 @@ e_book_cache_put_contacts (EBookCache *book_cache,
        g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
        g_return_val_if_fail (contacts != NULL, FALSE);
        g_return_val_if_fail (extras == NULL || g_slist_length ((GSList *) extras) == g_slist_length ((GSList 
*) contacts), FALSE);
+       g_return_val_if_fail (custom_flags == NULL || g_slist_length ((GSList *) contacts) == g_slist_length 
((GSList *) custom_flags), FALSE);
 
        cache = E_CACHE (book_cache);
        other_columns = e_cache_column_values_new ();
@@ -4875,9 +4922,12 @@ e_book_cache_put_contacts (EBookCache *book_cache,
        e_cache_lock (cache, E_CACHE_LOCK_WRITE);
        e_cache_freeze_revision_change (cache);
 
-       for (clink = contacts, elink = extras; clink; clink = g_slist_next (clink), elink = g_slist_next 
(elink)) {
+       for (clink = contacts, elink = extras, flink = custom_flags;
+            clink;
+            (clink = g_slist_next (clink)), (elink = g_slist_next (elink)), (flink = g_slist_next (flink))) {
                EContact *contact = clink->data;
                const gchar *extra = elink ? elink->data : NULL;
+               guint32 custom_flags_val = flink ? GPOINTER_TO_UINT (flink->data) : 0;
                gchar *uid, *rev, *vcard;
 
                g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
@@ -4889,6 +4939,7 @@ e_book_cache_put_contacts (EBookCache *book_cache,
 
                if (extra)
                        e_cache_column_values_take_value (other_columns, EBC_COLUMN_EXTRA, g_strdup (extra));
+               e_cache_column_values_take_value (other_columns, EBC_COLUMN_CUSTOM_FLAGS, g_strdup_printf 
("%u", custom_flags_val));
 
                uid = e_contact_get (contact, E_CONTACT_UID);
                rev = e_book_cache_dup_contact_revision (book_cache, contact);
@@ -4917,6 +4968,7 @@ e_book_cache_put_contacts (EBookCache *book_cache,
  * e_book_cache_remove_contact:
  * @book_cache: An #EBookCache
  * @uid: the uid of the contact to remove
+ * @custom_flags: custom flags for the contact with the given @uid, not interpreted by the @book_cache
  * @offline_flag: one of #ECacheOfflineFlag, whether removing this contact in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -4930,20 +4982,23 @@ e_book_cache_put_contacts (EBookCache *book_cache,
 gboolean
 e_book_cache_remove_contact (EBookCache *book_cache,
                             const gchar *uid,
+                            guint32 custom_flags,
                             ECacheOfflineFlag offline_flag,
                             GCancellable *cancellable,
                             GError **error)
 {
-       GSList *uids;
+       GSList *uids, *custom_flags_lst;
        gboolean success;
 
        g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
        g_return_val_if_fail (uid != NULL, FALSE);
 
        uids = g_slist_append (NULL, (gpointer) uid);
+       custom_flags_lst = g_slist_append (NULL, GUINT_TO_POINTER (custom_flags));
 
-       success = e_book_cache_remove_contacts (book_cache, uids, offline_flag, cancellable, error);
+       success = e_book_cache_remove_contacts (book_cache, uids, custom_flags_lst, offline_flag, 
cancellable, error);
 
+       g_slist_free (custom_flags_lst);
        g_slist_free (uids);
 
        return success;
@@ -4953,11 +5008,15 @@ e_book_cache_remove_contact (EBookCache *book_cache,
  * e_book_cache_remove_contacts:
  * @book_cache: An #EBookCache
  * @uids: (element-type utf8): a #GSList of uids indicating which contacts to remove
+ * @custom_flags: (element-type guint32) (nullable): an optional #GSList of custom flags for the @ids
  * @offline_flag: one of #ECacheOfflineFlag, whether removing these contacts in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Removes the contacts indicated by @uids from @book_cache.
+ * The @custom_flags is used, if not %NULL, only if the @offline_flag
+ * is %E_CACHE_IS_OFFLINE. Otherwise it's ignored. The length of
+ * the @custom_flags should match the length of @uids, when not %NULL.
  *
  * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
  *
@@ -4966,24 +5025,34 @@ e_book_cache_remove_contact (EBookCache *book_cache,
 gboolean
 e_book_cache_remove_contacts (EBookCache *book_cache,
                              const GSList *uids,
+                             const GSList *custom_flags,
                              ECacheOfflineFlag offline_flag,
                              GCancellable *cancellable,
                              GError **error)
 {
        ECache *cache;
-       const GSList *link;
+       const GSList *link, *flink;
        gboolean success = TRUE;
 
        g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
        g_return_val_if_fail (uids != NULL, FALSE);
+       g_return_val_if_fail (custom_flags == NULL || g_slist_length ((GSList *) uids) == g_slist_length 
((GSList *) custom_flags), FALSE);
 
        cache = E_CACHE (book_cache);
 
        e_cache_lock (cache, E_CACHE_LOCK_WRITE);
        e_cache_freeze_revision_change (cache);
 
-       for (link = uids; success && link; link = g_slist_next (link)) {
+       for (link = uids, flink = custom_flags; success && link; (link = g_slist_next (link)), (flink = 
g_slist_next (flink))) {
                const gchar *uid = link->data;
+               guint32 custom_flags_val = flink ? GPOINTER_TO_UINT (flink->data) : 0;
+
+               if (offline_flag == E_CACHE_IS_OFFLINE && flink) {
+                       success = e_book_cache_set_contact_custom_flags (book_cache, uid, custom_flags_val, 
cancellable, error);
+
+                       if (!success)
+                               break;
+               }
 
                success = e_cache_remove (cache, uid, offline_flag, cancellable, error);
        }
@@ -5103,6 +5172,101 @@ e_book_cache_get_vcard (EBookCache *book_cache,
        return TRUE;
 }
 
+/**
+ * e_book_cache_set_contact_custom_flags:
+ * @book_cache: an #EBookCache
+ * @uid: The uid of the contact to set the extra data for
+ * @custom_flags: the custom flags to set for the contact
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Sets or replaces the custom flags associated with a contact
+ * identified by the @uid.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_cache_set_contact_custom_flags (EBookCache *book_cache,
+                                      const gchar *uid,
+                                      guint32 custom_flags,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+       gchar *stmt;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+
+       if (!e_cache_contains (E_CACHE (book_cache), uid, E_CACHE_INCLUDE_DELETED)) {
+               g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object “%s” not found"), uid);
+               return FALSE;
+       }
+
+       stmt = e_cache_sqlite_stmt_printf (
+               "UPDATE " E_CACHE_TABLE_OBJECTS " SET " EBC_COLUMN_CUSTOM_FLAGS "=%u"
+               " WHERE " E_CACHE_COLUMN_UID "=%Q",
+               custom_flags, uid);
+
+       success = e_cache_sqlite_exec (E_CACHE (book_cache), stmt, cancellable, error);
+
+       e_cache_sqlite_stmt_free (stmt);
+
+       return success;
+}
+
+/**
+ * e_book_cache_get_contact_custom_flags:
+ * @book_cache: an #EBookCache
+ * @uid: The uid of the contact to set the extra data for
+ * @out_custom_flags: (out): return location to store the custom flags
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets the custom flags previously set for the @uid, either with
+ * e_book_cache_set_contact_custom_flags(), when adding contacts or
+ * when removing contacts in offline.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_cache_get_contact_custom_flags (EBookCache *book_cache,
+                                      const gchar *uid,
+                                      guint32 *out_custom_flags,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+       gchar *stmt;
+       guint64 value = 0;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+
+       if (!e_cache_contains (E_CACHE (book_cache), uid, E_CACHE_INCLUDE_DELETED)) {
+               g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object “%s” not found"), uid);
+               return FALSE;
+       }
+
+       stmt = e_cache_sqlite_stmt_printf (
+               "SELECT " EBC_COLUMN_CUSTOM_FLAGS " FROM " E_CACHE_TABLE_OBJECTS
+               " WHERE " E_CACHE_COLUMN_UID "=%Q",
+               uid);
+
+       success = e_cache_sqlite_select (E_CACHE (book_cache), stmt, e_book_cache_get_uint64_cb, &value, 
cancellable, error);
+
+       e_cache_sqlite_stmt_free (stmt);
+
+       if (out_custom_flags)
+               *out_custom_flags = (guint32) value;
+
+       return success;
+}
+
 /**
  * e_book_cache_set_contact_extra:
  * @book_cache: An #EBookCache
diff --git a/src/addressbook/libedata-book/e-book-cache.h b/src/addressbook/libedata-book/e-book-cache.h
index 1422437ab..37d060a12 100644
--- a/src/addressbook/libedata-book/e-book-cache.h
+++ b/src/addressbook/libedata-book/e-book-cache.h
@@ -95,7 +95,8 @@ void          e_book_cache_search_data_free   (/* EBookCacheSearchData * */ gpointer data)
  * @revision: the object revision
  * @object: the object itself
  * @extra: extra data stored with the object
- * @offline_state: objects offline state, one of #EOfflineState
+ * @custom_flags: object's custom flags
+ * @offline_state: object's offline state, one of #EOfflineState
  * @user_data: user data, as used in e_book_cache_search_with_callback()
  *
  * A callback called for each object row when using
@@ -110,6 +111,7 @@ typedef gboolean (* EBookCacheSearchFunc)   (EBookCache *book_cache,
                                                 const gchar *revision,
                                                 const gchar *object,
                                                 const gchar *extra,
+                                                guint32 custom_flags,
                                                 EOfflineState offline_state,
                                                 gpointer user_data);
 
@@ -221,22 +223,26 @@ ECollator *       e_book_cache_ref_collator       (EBookCache *book_cache);
 gboolean       e_book_cache_put_contact        (EBookCache *book_cache,
                                                 EContact *contact,
                                                 const gchar *extra,
+                                                guint32 custom_flags,
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_cache_put_contacts       (EBookCache *book_cache,
-                                                const GSList *contacts,
-                                                const GSList *extras,
+                                                const GSList *contacts, /* EContact * */
+                                                const GSList *extras, /* gchar * */
+                                                const GSList *custom_flags, /* guint32, through 
GUINT_TO_POINTER() */
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_cache_remove_contact     (EBookCache *book_cache,
                                                 const gchar *uid,
+                                                guint32 custom_flags,
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_cache_remove_contacts    (EBookCache *book_cache,
-                                                const GSList *uids,
+                                                const GSList *uids, /* gchar * */
+                                                const GSList *custom_flags, /* guint32, through 
GUINT_TO_POINTER() */
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
@@ -252,6 +258,18 @@ gboolean   e_book_cache_get_vcard          (EBookCache *book_cache,
                                                 gchar **out_vcard,
                                                 GCancellable *cancellable,
                                                 GError **error);
+gboolean       e_book_cache_set_contact_custom_flags
+                                               (EBookCache *book_cache,
+                                                const gchar *uid,
+                                                guint32 custom_flags,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_book_cache_get_contact_custom_flags
+                                               (EBookCache *book_cache,
+                                                const gchar *uid,
+                                                guint32 *out_custom_flags,
+                                                GCancellable *cancellable,
+                                                GError **error);
 gboolean       e_book_cache_set_contact_extra  (EBookCache *book_cache,
                                                 const gchar *uid,
                                                 const gchar *extra,
diff --git a/src/addressbook/libedata-book/e-book-meta-backend.c 
b/src/addressbook/libedata-book/e-book-meta-backend.c
index 66027d42a..79399d618 100644
--- a/src/addressbook/libedata-book/e-book-meta-backend.c
+++ b/src/addressbook/libedata-book/e-book-meta-backend.c
@@ -107,7 +107,7 @@ enum {
 
 static guint signals[LAST_SIGNAL];
 
-G_DEFINE_ABSTRACT_TYPE (EBookMetaBackend, e_book_meta_backend, E_TYPE_BOOK_BACKEND)
+G_DEFINE_ABSTRACT_TYPE (EBookMetaBackend, e_book_meta_backend, E_TYPE_BOOK_BACKEND_SYNC)
 
 G_DEFINE_BOXED_TYPE (EBookMetaBackendInfo, e_book_meta_backend_info, e_book_meta_backend_info_copy, 
e_book_meta_backend_info_free)
 
@@ -119,6 +119,7 @@ static gboolean ebmb_save_contact_wrapper_sync (EBookMetaBackend *meta_backend,
                                                EConflictResolution conflict_resolution,
                                                /* const */ EContact *in_contact,
                                                const gchar *extra,
+                                               guint32 opflags,
                                                const gchar *orig_uid,
                                                gboolean *out_requires_put,
                                                gchar **out_new_uid,
@@ -295,6 +296,7 @@ ebmb_gather_locally_cached_objects_cb (EBookCache *book_cache,
                                       const gchar *revision,
                                       const gchar *object,
                                       const gchar *extra,
+                                      guint32 custom_flags,
                                       EOfflineState offline_state,
                                       gpointer user_data)
 {
@@ -627,6 +629,7 @@ ebmb_upload_local_changes_sync (EBookMetaBackend *meta_backend,
        for (link = offline_changes; link && success; link = g_slist_next (link)) {
                ECacheOfflineChange *change = link->data;
                gchar *extra = NULL;
+               guint32 opflags = 0;
 
                success = !g_cancellable_set_error_if_cancelled (cancellable, error);
                if (!success)
@@ -640,6 +643,9 @@ ebmb_upload_local_changes_sync (EBookMetaBackend *meta_backend,
                if (!e_book_cache_get_contact_extra (book_cache, change->uid, &extra, cancellable, NULL))
                        extra = NULL;
 
+               if (!e_book_cache_get_contact_custom_flags (book_cache, change->uid, &opflags, cancellable, 
NULL))
+                       opflags = 0;
+
                if (change->state == E_OFFLINE_STATE_LOCALLY_CREATED ||
                    change->state == E_OFFLINE_STATE_LOCALLY_MODIFIED) {
                        EContact *contact = NULL;
@@ -648,7 +654,7 @@ ebmb_upload_local_changes_sync (EBookMetaBackend *meta_backend,
                        if (success) {
                                success = ebmb_save_contact_wrapper_sync (meta_backend, book_cache,
                                        change->state == E_OFFLINE_STATE_LOCALLY_MODIFIED,
-                                       conflict_resolution, contact, extra, change->uid, NULL, NULL, NULL, 
cancellable, error);
+                                       conflict_resolution, contact, extra, opflags, change->uid, NULL, 
NULL, NULL, cancellable, error);
                        }
 
                        g_clear_object (&contact);
@@ -656,10 +662,10 @@ ebmb_upload_local_changes_sync (EBookMetaBackend *meta_backend,
                        GError *local_error = NULL;
 
                        success = e_book_meta_backend_remove_contact_sync (meta_backend, conflict_resolution,
-                               change->uid, extra, change->object, cancellable, &local_error);
+                               change->uid, extra, change->object, opflags, cancellable, &local_error);
 
                        if (!success) {
-                               if (g_error_matches (local_error, E_DATA_BOOK_ERROR, 
E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND)) {
+                               if (g_error_matches (local_error, E_BOOK_CLIENT_ERROR, 
E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND)) {
                                        g_clear_error (&local_error);
                                        success = TRUE;
                                } else if (local_error) {
@@ -708,6 +714,7 @@ ebmb_maybe_remove_from_cache (EBookMetaBackend *meta_backend,
                              EBookCache *book_cache,
                              ECacheOfflineFlag offline_flag,
                              const gchar *uid,
+                             guint32 opflags,
                              GCancellable *cancellable,
                              GError **error)
 {
@@ -730,7 +737,7 @@ ebmb_maybe_remove_from_cache (EBookMetaBackend *meta_backend,
 
        book_backend = E_BOOK_BACKEND (meta_backend);
 
-       if (!e_book_cache_remove_contact (book_cache, uid, offline_flag, cancellable, error)) {
+       if (!e_book_cache_remove_contact (book_cache, uid, opflags, offline_flag, cancellable, error)) {
                g_object_unref (contact);
                return FALSE;
        }
@@ -975,6 +982,7 @@ ebmb_put_contact (EBookMetaBackend *meta_backend,
                  ECacheOfflineFlag offline_flag,
                  EContact *contact,
                  const gchar *extra,
+                 guint32 opflags,
                  GCancellable *cancellable,
                  GError **error)
 {
@@ -1020,7 +1028,7 @@ ebmb_put_contact (EBookMetaBackend *meta_backend,
                }
        }
 
-       success = success && e_book_cache_put_contact (book_cache, contact, extra, offline_flag, cancellable, 
error);
+       success = success && e_book_cache_put_contact (book_cache, contact, extra, opflags, offline_flag, 
cancellable, error);
 
        if (success)
                e_book_backend_notify_update (E_BOOK_BACKEND (meta_backend), contact);
@@ -1049,7 +1057,7 @@ ebmb_load_contact_wrapper_sync (EBookMetaBackend *meta_backend,
        if (preloaded_object && *preloaded_object) {
                contact = e_contact_new_from_vcard_with_uid (preloaded_object, uid);
                if (!contact) {
-                       g_propagate_error (error, e_data_book_create_error_fmt 
(E_DATA_BOOK_STATUS_INVALID_ARG, _("Preloaded object for UID “%s” is invalid"), uid));
+                       g_propagate_error (error, e_client_error_create_fmt (E_CLIENT_ERROR_INVALID_ARG, 
_("Preloaded object for UID “%s” is invalid"), uid));
                        return FALSE;
                }
        } else if (!e_book_meta_backend_ensure_connected_sync (meta_backend, cancellable, error) ||
@@ -1057,13 +1065,13 @@ ebmb_load_contact_wrapper_sync (EBookMetaBackend *meta_backend,
                g_free (extra);
                return FALSE;
        } else if (!contact) {
-               g_propagate_error (error, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_INVALID_ARG, 
_("Received object for UID “%s” is invalid"), uid));
+               g_propagate_error (error, e_client_error_create_fmt (E_CLIENT_ERROR_INVALID_ARG, _("Received 
object for UID “%s” is invalid"), uid));
                g_free (extra);
                return FALSE;
        }
 
        success = ebmb_put_contact (meta_backend, book_cache, offline_flag,
-               contact, extra ? extra : preloaded_extra, cancellable, &local_error);
+               contact, extra ? extra : preloaded_extra, 0, cancellable, &local_error);
 
        if (success && out_new_uid)
                *out_new_uid = e_contact_get (contact, E_CONTACT_UID);
@@ -1089,6 +1097,7 @@ ebmb_save_contact_wrapper_sync (EBookMetaBackend *meta_backend,
                                EConflictResolution conflict_resolution,
                                /* const */ EContact *in_contact,
                                const gchar *extra,
+                               guint32 opflags,
                                const gchar *orig_uid,
                                gboolean *out_requires_put,
                                gchar **out_new_uid,
@@ -1112,7 +1121,7 @@ ebmb_save_contact_wrapper_sync (EBookMetaBackend *meta_backend,
        success = e_book_meta_backend_inline_local_photos_sync (meta_backend, contact, cancellable, error);
 
        success = success && e_book_meta_backend_save_contact_sync (meta_backend, overwrite_existing, 
conflict_resolution,
-               contact, extra, &new_uid, &new_extra, cancellable, &local_error);
+               contact, extra, opflags, &new_uid, &new_extra, cancellable, &local_error);
 
        if (success && new_uid && *new_uid) {
                gchar *loaded_uid = NULL;
@@ -1121,7 +1130,7 @@ ebmb_save_contact_wrapper_sync (EBookMetaBackend *meta_backend,
                        new_extra ? new_extra : extra, &loaded_uid, cancellable, error);
 
                if (success && g_strcmp0 (loaded_uid, orig_uid) != 0)
-                       success = ebmb_maybe_remove_from_cache (meta_backend, book_cache, E_CACHE_IS_ONLINE, 
orig_uid, cancellable, error);
+                       success = ebmb_maybe_remove_from_cache (meta_backend, book_cache, E_CACHE_IS_ONLINE, 
orig_uid, opflags, cancellable, error);
 
                if (success && out_new_uid)
                        *out_new_uid = loaded_uid;
@@ -1158,7 +1167,7 @@ ebmb_get_backend_property (EBookBackend *book_backend,
        g_return_val_if_fail (E_IS_BOOK_META_BACKEND (book_backend), NULL);
        g_return_val_if_fail (prop_name != NULL, NULL);
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REVISION)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REVISION)) {
                EBookCache *book_cache;
                gchar *revision = NULL;
 
@@ -1173,9 +1182,9 @@ ebmb_get_backend_property (EBookBackend *book_backend,
                return revision;
        } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return g_strdup (e_book_meta_backend_get_capabilities (E_BOOK_META_BACKEND (book_backend)));
-       } else  if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       } else  if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                return g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                GString *fields;
                gint ii;
 
@@ -1196,7 +1205,7 @@ ebmb_get_backend_property (EBookBackend *book_backend,
 }
 
 static gboolean
-ebmb_open_sync (EBookBackend *book_backend,
+ebmb_open_sync (EBookBackendSync *book_backend,
                GCancellable *cancellable,
                GError **error)
 {
@@ -1205,7 +1214,7 @@ ebmb_open_sync (EBookBackend *book_backend,
 
        g_return_val_if_fail (E_IS_BOOK_META_BACKEND (book_backend), FALSE);
 
-       if (e_book_backend_is_opened (book_backend))
+       if (e_book_backend_is_opened (E_BOOK_BACKEND (book_backend)))
                return TRUE;
 
        meta_backend = E_BOOK_META_BACKEND (book_backend);
@@ -1248,7 +1257,7 @@ ebmb_open_sync (EBookBackend *book_backend,
 }
 
 static gboolean
-ebmb_refresh_sync (EBookBackend *book_backend,
+ebmb_refresh_sync (EBookBackendSync *book_backend,
                   GCancellable *cancellable,
                   GError **error)
 {
@@ -1281,6 +1290,7 @@ ebmb_create_contact_sync (EBookMetaBackend *meta_backend,
                          EBookCache *book_cache,
                          ECacheOfflineFlag *offline_flag,
                          EConflictResolution conflict_resolution,
+                         guint32 opflags,
                          EContact *contact,
                          gchar **out_new_uid,
                          EContact **out_new_contact,
@@ -1299,7 +1309,7 @@ ebmb_create_contact_sync (EBookMetaBackend *meta_backend,
 
                new_uid = e_util_generate_uid ();
                if (!new_uid) {
-                       g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_ARG, 
NULL));
+                       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_INVALID_ARG, NULL));
                        return FALSE;
                }
 
@@ -1310,7 +1320,7 @@ ebmb_create_contact_sync (EBookMetaBackend *meta_backend,
        }
 
        if (e_cache_contains (E_CACHE (book_cache), uid, E_CACHE_EXCLUDE_DELETED)) {
-               g_propagate_error (error, e_data_book_create_error 
(E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS, NULL));
+               g_propagate_error (error, e_book_client_error_create 
(E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS, NULL));
                return FALSE;
        }
 
@@ -1324,14 +1334,14 @@ ebmb_create_contact_sync (EBookMetaBackend *meta_backend,
        }
 
        if (*offline_flag == E_CACHE_IS_ONLINE) {
-               if (!ebmb_save_contact_wrapper_sync (meta_backend, book_cache, FALSE, conflict_resolution, 
contact, NULL, uid,
+               if (!ebmb_save_contact_wrapper_sync (meta_backend, book_cache, FALSE, conflict_resolution, 
contact, NULL, opflags, uid,
                        &requires_put, &new_uid, &new_extra, cancellable, error)) {
                        return FALSE;
                }
        }
 
        if (requires_put) {
-               success = e_book_cache_put_contact (book_cache, contact, new_extra, *offline_flag, 
cancellable, error);
+               success = e_book_cache_put_contact (book_cache, contact, new_extra, opflags, *offline_flag, 
cancellable, error);
                if (success)
                        e_book_backend_notify_update (E_BOOK_BACKEND (meta_backend), contact);
        } else {
@@ -1358,16 +1368,17 @@ ebmb_create_contact_sync (EBookMetaBackend *meta_backend,
 }
 
 static gboolean
-ebmb_create_contacts_sync (EBookBackend *book_backend,
+ebmb_create_contacts_sync (EBookBackendSync *book_backend,
                           const gchar * const *vcards,
-                          GQueue *out_contacts,
+                          guint32 opflags,
+                          GSList **out_contacts,
                           GCancellable *cancellable,
                           GError **error)
 {
        EBookMetaBackend *meta_backend;
        EBookCache *book_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
+       EConflictResolution conflict_resolution = e_book_util_operation_flags_to_conflict_resolution 
(opflags);
        gint ii;
        gboolean success = TRUE;
 
@@ -1375,8 +1386,10 @@ ebmb_create_contacts_sync (EBookBackend *book_backend,
        g_return_val_if_fail (vcards != NULL, FALSE);
        g_return_val_if_fail (out_contacts != NULL, FALSE);
 
-       if (!e_book_backend_get_writable (book_backend)) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_PERMISSION_DENIED, 
NULL));
+       *out_contacts = NULL;
+
+       if (!e_book_backend_get_writable (E_BOOK_BACKEND (book_backend))) {
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_PERMISSION_DENIED, NULL));
                return FALSE;
        }
 
@@ -1394,18 +1407,18 @@ ebmb_create_contacts_sync (EBookBackend *book_backend,
 
                contact = e_contact_new_from_vcard (vcards[ii]);
                if (!contact) {
-                       g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_ARG, 
NULL));
+                       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_INVALID_ARG, NULL));
                        success = FALSE;
                        break;
                }
 
                success = ebmb_create_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution,
-                       contact, NULL, &new_contact, cancellable, error);
+                       opflags, contact, NULL, &new_contact, cancellable, error);
 
                if (success) {
                        ebmb_foreach_cursor (meta_backend, new_contact, e_data_book_cursor_contact_added);
 
-                       g_queue_push_tail (out_contacts, new_contact);
+                       *out_contacts = g_slist_prepend (*out_contacts, new_contact);
                }
 
                g_object_unref (contact);
@@ -1413,9 +1426,11 @@ ebmb_create_contacts_sync (EBookBackend *book_backend,
 
        g_object_unref (book_cache);
 
-       if (!success) {
-               g_queue_foreach (out_contacts, (GFunc) g_object_unref, NULL);
-               g_queue_clear (out_contacts);
+       if (success) {
+               *out_contacts = g_slist_reverse (*out_contacts);
+       } else {
+               g_slist_free_full (*out_contacts, g_object_unref);
+               *out_contacts = NULL;
        }
 
        return success;
@@ -1426,6 +1441,7 @@ ebmb_modify_contact_sync (EBookMetaBackend *meta_backend,
                          EBookCache *book_cache,
                          ECacheOfflineFlag *offline_flag,
                          EConflictResolution conflict_resolution,
+                         guint32 opflags,
                          EContact *contact,
                          EContact **out_new_contact,
                          GCancellable *cancellable,
@@ -1441,14 +1457,14 @@ ebmb_modify_contact_sync (EBookMetaBackend *meta_backend,
 
        uid = e_contact_get_const (contact, E_CONTACT_UID);
        if (!uid) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_ARG, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_INVALID_ARG, NULL));
                return FALSE;
        }
 
        if (!e_book_cache_get_contact (book_cache, uid, FALSE, &existing_contact, cancellable, &local_error)) 
{
                if (g_error_matches (local_error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND)) {
                        g_clear_error (&local_error);
-                       local_error = e_data_book_create_error (E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, NULL);
+                       local_error = e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, 
NULL);
                }
 
                g_propagate_error (error, local_error);
@@ -1470,11 +1486,11 @@ ebmb_modify_contact_sync (EBookMetaBackend *meta_backend,
 
        if (success && *offline_flag == E_CACHE_IS_ONLINE) {
                success = ebmb_save_contact_wrapper_sync (meta_backend, book_cache, TRUE, conflict_resolution,
-                       contact, extra, uid, &requires_put, &new_uid, &new_extra, cancellable, error);
+                       contact, extra, opflags, uid, &requires_put, &new_uid, &new_extra, cancellable, 
error);
        }
 
        if (success && requires_put)
-               success = ebmb_put_contact (meta_backend, book_cache, *offline_flag, contact, new_extra ? 
new_extra : extra, cancellable, error);
+               success = ebmb_put_contact (meta_backend, book_cache, *offline_flag, contact, new_extra ? 
new_extra : extra, opflags, cancellable, error);
 
        if (success && out_new_contact) {
                if (new_uid) {
@@ -1494,16 +1510,17 @@ ebmb_modify_contact_sync (EBookMetaBackend *meta_backend,
 }
 
 static gboolean
-ebmb_modify_contacts_sync (EBookBackend *book_backend,
+ebmb_modify_contacts_sync (EBookBackendSync *book_backend,
                           const gchar * const *vcards,
-                          GQueue *out_contacts,
+                          guint32 opflags,
+                          GSList **out_contacts,
                           GCancellable *cancellable,
                           GError **error)
 {
        EBookMetaBackend *meta_backend;
        EBookCache *book_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
+       EConflictResolution conflict_resolution = e_book_util_operation_flags_to_conflict_resolution 
(opflags);
        gint ii;
        gboolean success = TRUE;
 
@@ -1511,8 +1528,10 @@ ebmb_modify_contacts_sync (EBookBackend *book_backend,
        g_return_val_if_fail (vcards != NULL, FALSE);
        g_return_val_if_fail (out_contacts != NULL, FALSE);
 
-       if (!e_book_backend_get_writable (book_backend)) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_PERMISSION_DENIED, 
NULL));
+       *out_contacts = NULL;
+
+       if (!e_book_backend_get_writable (E_BOOK_BACKEND (book_backend))) {
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_PERMISSION_DENIED, NULL));
                return FALSE;
        }
 
@@ -1530,19 +1549,19 @@ ebmb_modify_contacts_sync (EBookBackend *book_backend,
 
                contact = e_contact_new_from_vcard (vcards[ii]);
                if (!contact) {
-                       g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_ARG, 
NULL));
+                       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_INVALID_ARG, NULL));
                        success = FALSE;
                        break;
                }
 
-               success = ebmb_modify_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution,
+               success = ebmb_modify_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution, opflags,
                        contact, &new_contact, cancellable, error);
 
                if (success && new_contact) {
                        ebmb_foreach_cursor (meta_backend, contact, e_data_book_cursor_contact_removed);
                        ebmb_foreach_cursor (meta_backend, new_contact, e_data_book_cursor_contact_added);
 
-                       g_queue_push_tail (out_contacts, g_object_ref (new_contact));
+                       *out_contacts = g_slist_prepend (*out_contacts, g_object_ref (new_contact));
                }
 
                g_clear_object (&new_contact);
@@ -1551,9 +1570,11 @@ ebmb_modify_contacts_sync (EBookBackend *book_backend,
 
        g_object_unref (book_cache);
 
-       if (!success) {
-               g_queue_foreach (out_contacts, (GFunc) g_object_unref, NULL);
-               g_queue_clear (out_contacts);
+       if (success) {
+               *out_contacts = g_slist_reverse (*out_contacts);
+       } else {
+               g_slist_free_full (*out_contacts, g_object_unref);
+               *out_contacts = NULL;
        }
 
        return success;
@@ -1564,6 +1585,7 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
                          EBookCache *book_cache,
                          ECacheOfflineFlag *offline_flag,
                          EConflictResolution conflict_resolution,
+                         guint32 opflags,
                          const gchar *uid,
                          GCancellable *cancellable,
                          GError **error)
@@ -1578,7 +1600,7 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
        if (!e_book_cache_get_contact (book_cache, uid, FALSE, &existing_contact, cancellable, &local_error)) 
{
                if (g_error_matches (local_error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND)) {
                        g_clear_error (&local_error);
-                       local_error = e_data_book_create_error (E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, NULL);
+                       local_error = e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, 
NULL);
                }
 
                g_propagate_error (error, local_error);
@@ -1603,7 +1625,7 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
 
                g_warn_if_fail (e_book_cache_get_vcard (book_cache, uid, FALSE, &vcard_string, cancellable, 
NULL));
 
-               success = e_book_meta_backend_remove_contact_sync (meta_backend, conflict_resolution, uid, 
extra, vcard_string, cancellable, &local_error);
+               success = e_book_meta_backend_remove_contact_sync (meta_backend, conflict_resolution, uid, 
extra, vcard_string, opflags, cancellable, &local_error);
 
                g_free (vcard_string);
 
@@ -1616,7 +1638,7 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
                }
        }
 
-       success = success && ebmb_maybe_remove_from_cache (meta_backend, book_cache, *offline_flag, uid, 
cancellable, error);
+       success = success && ebmb_maybe_remove_from_cache (meta_backend, book_cache, *offline_flag, uid, 
opflags, cancellable, error);
 
        g_clear_object (&existing_contact);
        g_free (extra);
@@ -1625,23 +1647,28 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
 }
 
 static gboolean
-ebmb_remove_contacts_sync (EBookBackend *book_backend,
+ebmb_remove_contacts_sync (EBookBackendSync *book_backend,
                           const gchar * const *uids,
+                          guint32 opflags,
+                          GSList **out_removed_uids,
                           GCancellable *cancellable,
                           GError **error)
 {
        EBookMetaBackend *meta_backend;
        EBookCache *book_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
+       EConflictResolution conflict_resolution = e_book_util_operation_flags_to_conflict_resolution 
(opflags);
        gint ii;
        gboolean success = TRUE;
 
        g_return_val_if_fail (E_IS_BOOK_META_BACKEND (book_backend), FALSE);
        g_return_val_if_fail (uids != NULL, FALSE);
+       g_return_val_if_fail (out_removed_uids != NULL, FALSE);
 
-       if (!e_book_backend_get_writable (book_backend)) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_PERMISSION_DENIED, 
NULL));
+       *out_removed_uids = NULL;
+
+       if (!e_book_backend_get_writable (E_BOOK_BACKEND (book_backend))) {
+               g_propagate_error (error, e_book_client_error_create (E_CLIENT_ERROR_PERMISSION_DENIED, 
NULL));
                return FALSE;
        }
 
@@ -1658,21 +1685,25 @@ ebmb_remove_contacts_sync (EBookBackend *book_backend,
                }
 
                if (!uid) {
-                       g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_ARG, 
NULL));
+                       g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_INVALID_ARG, NULL));
                        success = FALSE;
                        break;
                }
 
-               success = ebmb_remove_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution, uid, cancellable, error);
+               success = ebmb_remove_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution, opflags, uid, cancellable, error);
+               if (success)
+                       *out_removed_uids = g_slist_prepend (*out_removed_uids, g_strdup (uid));
        }
 
        g_object_unref (book_cache);
 
+       *out_removed_uids = g_slist_reverse (*out_removed_uids);
+
        return success;
 }
 
 static EContact *
-ebmb_get_contact_sync (EBookBackend *book_backend,
+ebmb_get_contact_sync (EBookBackendSync *book_backend,
                       const gchar *uid,
                       GCancellable *cancellable,
                       GError **error)
@@ -1705,11 +1736,11 @@ ebmb_get_contact_sync (EBookBackend *book_backend,
                }
 
                if (!found)
-                       g_propagate_error (error, e_data_book_create_error 
(E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, NULL));
+                       g_propagate_error (error, e_book_client_error_create 
(E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, NULL));
 
                g_free (loaded_uid);
        } else if (local_error) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_OTHER_ERROR, 
local_error->message));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, 
local_error->message));
                g_clear_error (&local_error);
        }
 
@@ -1719,58 +1750,33 @@ ebmb_get_contact_sync (EBookBackend *book_backend,
 }
 
 static gboolean
-ebmb_get_contact_list_sync (EBookBackend *book_backend,
+ebmb_get_contact_list_sync (EBookBackendSync *book_backend,
                            const gchar *query,
-                           GQueue *out_contacts,
+                           GSList **out_contacts,
                            GCancellable *cancellable,
                            GError **error)
 {
-       GSList *contacts = NULL, *link;
-       gboolean success;
-
        g_return_val_if_fail (E_IS_BOOK_META_BACKEND (book_backend), FALSE);
        g_return_val_if_fail (out_contacts != NULL, FALSE);
 
-       success = e_book_meta_backend_search_sync (E_BOOK_META_BACKEND (book_backend), query, FALSE, 
&contacts, cancellable, error);
-       if (success) {
-               for (link = contacts; link; link = g_slist_next (link)) {
-                       EContact *contact = link->data;
-
-                       g_queue_push_tail (out_contacts, g_object_ref (contact));
-               }
-
-               g_slist_free_full (contacts, g_object_unref);
-       }
+       *out_contacts = NULL;
 
-       return success;
+       return e_book_meta_backend_search_sync (E_BOOK_META_BACKEND (book_backend), query, FALSE, 
out_contacts, cancellable, error);
 }
 
 static gboolean
-ebmb_get_contact_list_uids_sync (EBookBackend *book_backend,
+ebmb_get_contact_list_uids_sync (EBookBackendSync *book_backend,
                                 const gchar *query,
-                                GQueue *out_uids,
+                                GSList **out_uids,
                                 GCancellable *cancellable,
                                 GError **error)
 {
-       GSList *uids = NULL, *link;
-       gboolean success;
-
        g_return_val_if_fail (E_IS_BOOK_META_BACKEND (book_backend), FALSE);
        g_return_val_if_fail (out_uids != NULL, FALSE);
 
-       success = e_book_meta_backend_search_uids_sync (E_BOOK_META_BACKEND (book_backend), query, &uids, 
cancellable, error);
-       if (success) {
-               for (link = uids; link; link = g_slist_next (link)) {
-                       gchar *uid = link->data;
-
-                       g_queue_push_tail (out_uids, uid);
-                       link->data = NULL;
-               }
-
-               g_slist_free_full (uids, g_free);
-       }
+       *out_uids = NULL;
 
-       return success;
+       return e_book_meta_backend_search_uids_sync (E_BOOK_META_BACKEND (book_backend), query, out_uids, 
cancellable, error);
 }
 
 static void
@@ -2039,8 +2045,7 @@ ebmb_authenticate_sync (EBackend *backend,
        meta_backend = E_BOOK_META_BACKEND (backend);
 
        if (!e_backend_get_online (E_BACKEND (meta_backend))) {
-               g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_REPOSITORY_OFFLINE,
-                       e_client_error_to_string (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_REPOSITORY_OFFLINE, NULL));
 
                g_mutex_lock (&meta_backend->priv->wait_credentials_lock);
                meta_backend->priv->wait_credentials_stamp++;
@@ -2226,12 +2231,12 @@ ebmb_maybe_wait_for_credentials (EBookMetaBackend *meta_backend,
        if (!op_error || g_cancellable_is_cancelled (cancellable))
                return FALSE;
 
-       if (g_error_matches (op_error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE) &&
+       if (g_error_matches (op_error, E_CLIENT_ERROR, E_CLIENT_ERROR_TLS_NOT_AVAILABLE) &&
            e_book_meta_backend_get_ssl_error_details (meta_backend, &certificate_pem, &certificate_errors)) {
                reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
-       } else if (g_error_matches (op_error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED)) 
{
+       } else if (g_error_matches (op_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_REQUIRED)) {
                reason = E_SOURCE_CREDENTIALS_REASON_REQUIRED;
-       } else if (g_error_matches (op_error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED)) {
+       } else if (g_error_matches (op_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_FAILED)) {
                reason = E_SOURCE_CREDENTIALS_REASON_REJECTED;
        }
 
@@ -2438,6 +2443,7 @@ e_book_meta_backend_class_init (EBookMetaBackendClass *klass)
        GObjectClass *object_class;
        EBackendClass *backend_class;
        EBookBackendClass *book_backend_class;
+       EBookBackendSyncClass *book_backend_sync_class;
 
        g_type_class_add_private (klass, sizeof (EBookMetaBackendPrivate));
 
@@ -2449,16 +2455,18 @@ e_book_meta_backend_class_init (EBookMetaBackendClass *klass)
        klass->requires_reconnect = ebmb_requires_reconnect;
        klass->get_ssl_error_details = ebmb_get_ssl_error_details;
 
+       book_backend_sync_class = E_BOOK_BACKEND_SYNC_CLASS (klass);
+       book_backend_sync_class->open_sync = ebmb_open_sync;
+       book_backend_sync_class->refresh_sync = ebmb_refresh_sync;
+       book_backend_sync_class->create_contacts_sync = ebmb_create_contacts_sync;
+       book_backend_sync_class->modify_contacts_sync = ebmb_modify_contacts_sync;
+       book_backend_sync_class->remove_contacts_sync = ebmb_remove_contacts_sync;
+       book_backend_sync_class->get_contact_sync = ebmb_get_contact_sync;
+       book_backend_sync_class->get_contact_list_sync = ebmb_get_contact_list_sync;
+       book_backend_sync_class->get_contact_list_uids_sync = ebmb_get_contact_list_uids_sync;
+
        book_backend_class = E_BOOK_BACKEND_CLASS (klass);
        book_backend_class->get_backend_property = ebmb_get_backend_property;
-       book_backend_class->open_sync = ebmb_open_sync;
-       book_backend_class->refresh_sync = ebmb_refresh_sync;
-       book_backend_class->create_contacts_sync = ebmb_create_contacts_sync;
-       book_backend_class->modify_contacts_sync = ebmb_modify_contacts_sync;
-       book_backend_class->remove_contacts_sync = ebmb_remove_contacts_sync;
-       book_backend_class->get_contact_sync = ebmb_get_contact_sync;
-       book_backend_class->get_contact_list_sync = ebmb_get_contact_list_sync;
-       book_backend_class->get_contact_list_uids_sync = ebmb_get_contact_list_uids_sync;
        book_backend_class->start_view = ebmb_start_view;
        book_backend_class->stop_view = ebmb_stop_view;
        book_backend_class->get_direct_book = ebmb_get_direct_book;
@@ -2738,7 +2746,7 @@ ebmb_cache_revision_changed_cb (ECache *cache,
        revision = e_cache_dup_revision (cache);
        if (revision) {
                e_book_backend_notify_property_changed (E_BOOK_BACKEND (meta_backend),
-                       BOOK_BACKEND_PROPERTY_REVISION, revision);
+                       E_BOOK_BACKEND_PROPERTY_REVISION, revision);
                g_free (revision);
        }
 }
@@ -3271,8 +3279,7 @@ e_book_meta_backend_ensure_connected_sync (EBookMetaBackend *meta_backend,
        g_return_val_if_fail (E_IS_BOOK_META_BACKEND (meta_backend), FALSE);
 
        if (!e_backend_get_online (E_BACKEND (meta_backend))) {
-               g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_REPOSITORY_OFFLINE,
-                       e_client_error_to_string (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_REPOSITORY_OFFLINE, NULL));
 
                return FALSE;
        }
@@ -3515,7 +3522,7 @@ e_book_meta_backend_process_changes_sync (EBookMetaBackend *meta_backend,
                        continue;
                }
 
-               success = ebmb_maybe_remove_from_cache (meta_backend, book_cache, E_CACHE_IS_ONLINE, 
nfo->uid, cancellable, error);
+               success = ebmb_maybe_remove_from_cache (meta_backend, book_cache, E_CACHE_IS_ONLINE, 
nfo->uid, 0, cancellable, error);
        }
 
        /* Then modified objects */
@@ -3537,7 +3544,7 @@ e_book_meta_backend_process_changes_sync (EBookMetaBackend *meta_backend,
                success = ebmb_load_contact_wrapper_sync (meta_backend, book_cache, nfo->uid, nfo->object, 
nfo->extra, NULL, cancellable, &local_error);
 
                /* Do not stop on invalid objects, just notify about them later, and load as many as possible 
*/
-               if (!success && g_error_matches (local_error, E_DATA_BOOK_ERROR, 
E_DATA_BOOK_STATUS_INVALID_ARG)) {
+               if (!success && g_error_matches (local_error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG)) {
                        if (!invalid_objects) {
                                invalid_objects = g_string_new (local_error->message);
                        } else {
@@ -3569,7 +3576,7 @@ e_book_meta_backend_process_changes_sync (EBookMetaBackend *meta_backend,
                success = ebmb_load_contact_wrapper_sync (meta_backend, book_cache, nfo->uid, nfo->object, 
nfo->extra, NULL, cancellable, &local_error);
 
                /* Do not stop on invalid objects, just notify about them later, and load as many as possible 
*/
-               if (!success && g_error_matches (local_error, E_DATA_BOOK_ERROR, 
E_DATA_BOOK_STATUS_INVALID_ARG)) {
+               if (!success && g_error_matches (local_error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG)) {
                        if (!invalid_objects) {
                                invalid_objects = g_string_new (local_error->message);
                        } else {
@@ -3945,6 +3952,7 @@ e_book_meta_backend_load_contact_sync (EBookMetaBackend *meta_backend,
  * @conflict_resolution: one of #EConflictResolution, what to do on conflicts
  * @contact: an #EContact to save
  * @extra: (nullable): extra data saved with the contacts in an #EBookCache
+ * @opflags: bit-or of EBookOperationFlags
  * @out_new_uid: (out) (transfer full): return location for the UID of the saved contact
  * @out_new_extra: (out) (transfer full): return location for the extra data to store with the contact
  * @cancellable: optional #GCancellable object, or %NULL
@@ -3984,6 +3992,7 @@ e_book_meta_backend_save_contact_sync (EBookMetaBackend *meta_backend,
                                       EConflictResolution conflict_resolution,
                                       /* const */ EContact *contact,
                                       const gchar *extra,
+                                      guint32 opflags,
                                       gchar **out_new_uid,
                                       gchar **out_new_extra,
                                       GCancellable *cancellable,
@@ -4003,7 +4012,7 @@ e_book_meta_backend_save_contact_sync (EBookMetaBackend *meta_backend,
        g_return_val_if_fail (klass != NULL, FALSE);
 
        if (!klass->save_contact_sync) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_NOT_SUPPORTED, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                return FALSE;
        }
 
@@ -4023,6 +4032,7 @@ e_book_meta_backend_save_contact_sync (EBookMetaBackend *meta_backend,
                        conflict_resolution,
                        contact,
                        extra,
+                       opflags,
                        out_new_uid,
                        out_new_extra,
                        cancellable,
@@ -4045,6 +4055,7 @@ e_book_meta_backend_save_contact_sync (EBookMetaBackend *meta_backend,
  * @uid: a contact UID
  * @extra: (nullable): extra data being saved with the contact in the local cache, or %NULL
  * @object: (nullable): corresponding vCard object, as stored in the local cache, or %NULL
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -4064,6 +4075,7 @@ e_book_meta_backend_remove_contact_sync (EBookMetaBackend *meta_backend,
                                         const gchar *uid,
                                         const gchar *extra,
                                         const gchar *object,
+                                        guint32 opflags,
                                         GCancellable *cancellable,
                                         GError **error)
 {
@@ -4079,7 +4091,7 @@ e_book_meta_backend_remove_contact_sync (EBookMetaBackend *meta_backend,
        g_return_val_if_fail (klass != NULL, FALSE);
 
        if (!klass->remove_contact_sync) {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_NOT_SUPPORTED, NULL));
+               g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
                return FALSE;
        }
 
@@ -4094,7 +4106,7 @@ e_book_meta_backend_remove_contact_sync (EBookMetaBackend *meta_backend,
                g_clear_error (&local_error);
                repeat_count++;
 
-               success = klass->remove_contact_sync (meta_backend, conflict_resolution, uid, extra, object, 
cancellable, &local_error);
+               success = klass->remove_contact_sync (meta_backend, conflict_resolution, uid, extra, object, 
opflags, cancellable, &local_error);
 
                if (!success && repeat_count <= MAX_REPEAT_COUNT && !ebmb_maybe_wait_for_credentials 
(meta_backend, wait_credentials_stamp, local_error, cancellable))
                        break;
@@ -4233,7 +4245,7 @@ e_book_meta_backend_requires_reconnect (EBookMetaBackend *meta_backend)
  *
  * It is optional to implement this virtual method by the descendants.
  * It is used to receive SSL error details when any online operation
- * returns E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE error.
+ * returns E_CLIENT_ERROR, E_CLIENT_ERROR_TLS_NOT_AVAILABLE error.
  *
  * Returns: %TRUE, when the SSL error details had been available and
  *    the out parameters populated, %FALSE otherwise.
diff --git a/src/addressbook/libedata-book/e-book-meta-backend.h 
b/src/addressbook/libedata-book/e-book-meta-backend.h
index 6389f9f7e..23f80eb1a 100644
--- a/src/addressbook/libedata-book/e-book-meta-backend.h
+++ b/src/addressbook/libedata-book/e-book-meta-backend.h
@@ -23,7 +23,7 @@
 #define E_BOOK_META_BACKEND_H
 
 #include <libebackend/libebackend.h>
-#include <libedata-book/e-book-backend.h>
+#include <libedata-book/e-book-backend-sync.h>
 #include <libedata-book/e-book-cache.h>
 #include <libebook-contacts/libebook-contacts.h>
 
@@ -82,7 +82,7 @@ typedef struct _EBookMetaBackendPrivate EBookMetaBackendPrivate;
  **/
 struct _EBookMetaBackend {
        /*< private >*/
-       EBookBackend parent;
+       EBookBackendSync parent;
        EBookMetaBackendPrivate *priv;
 };
 
@@ -95,7 +95,7 @@ struct _EBookMetaBackend {
  */
 struct _EBookMetaBackendClass {
        /*< private >*/
-       EBookBackendClass parent_class;
+       EBookBackendSyncClass parent_class;
 
        /* For Direct Read Access */
        const gchar *backend_module_filename;
@@ -140,6 +140,7 @@ struct _EBookMetaBackendClass {
                                                 EConflictResolution conflict_resolution,
                                                 /* const */ EContact *contact,
                                                 const gchar *extra,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 gchar **out_new_uid,
                                                 gchar **out_new_extra,
                                                 GCancellable *cancellable,
@@ -149,6 +150,7 @@ struct _EBookMetaBackendClass {
                                                 const gchar *uid,
                                                 const gchar *extra,
                                                 const gchar *object,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
        gboolean        (* search_sync)         (EBookMetaBackend *meta_backend,
@@ -275,6 +277,7 @@ gboolean    e_book_meta_backend_save_contact_sync
                                                 EConflictResolution conflict_resolution,
                                                 /* const */ EContact *contact,
                                                 const gchar *extra,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 gchar **out_new_uid,
                                                 gchar **out_new_extra,
                                                 GCancellable *cancellable,
@@ -285,6 +288,7 @@ gboolean    e_book_meta_backend_remove_contact_sync
                                                 const gchar *uid,
                                                 const gchar *extra,
                                                 const gchar *object,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_meta_backend_search_sync (EBookMetaBackend *meta_backend,
diff --git a/src/addressbook/libedata-book/e-data-book.c b/src/addressbook/libedata-book/e-data-book.c
index ac381ff7a..837e48c70 100644
--- a/src/addressbook/libedata-book/e-data-book.c
+++ b/src/addressbook/libedata-book/e-data-book.c
@@ -237,285 +237,9 @@ data_book_convert_to_client_error (GError *error)
        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
                error->domain = E_BOOK_CLIENT_ERROR;
                error->code = E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK;
-
-               return;
-       }
-
-       if (error->domain != E_DATA_BOOK_ERROR)
-               return;
-
-       switch (error->code) {
-               case E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_REPOSITORY_OFFLINE;
-                       break;
-
-               case E_DATA_BOOK_STATUS_PERMISSION_DENIED:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_PERMISSION_DENIED;
-                       break;
-
-               case E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND:
-                       error->domain = E_BOOK_CLIENT_ERROR;
-                       error->code = E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND;
-                       break;
-
-               case E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS:
-                       error->domain = E_BOOK_CLIENT_ERROR;
-                       error->code = E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS;
-                       break;
-
-               case E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_AUTHENTICATION_FAILED;
-                       break;
-
-               case E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD;
-                       break;
-
-               case E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_TLS_NOT_AVAILABLE;
-                       break;
-
-               case E_DATA_BOOK_STATUS_NO_SUCH_BOOK:
-                       error->domain = E_BOOK_CLIENT_ERROR;
-                       error->code = E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK;
-                       break;
-
-               case E_DATA_BOOK_STATUS_BOOK_REMOVED:
-                       error->domain = E_BOOK_CLIENT_ERROR;
-                       error->code = E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE;
-                       break;
-
-               case E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_OFFLINE_UNAVAILABLE;
-                       break;
-
-               case E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED;
-                       break;
-
-               case E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED;
-                       break;
-
-               case E_DATA_BOOK_STATUS_INVALID_QUERY:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_INVALID_QUERY;
-                       break;
-
-               case E_DATA_BOOK_STATUS_QUERY_REFUSED:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_QUERY_REFUSED;
-                       break;
-
-               case E_DATA_BOOK_STATUS_COULD_NOT_CANCEL:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_COULD_NOT_CANCEL;
-                       break;
-
-               case E_DATA_BOOK_STATUS_NO_SPACE:
-                       error->domain = E_BOOK_CLIENT_ERROR;
-                       error->code = E_BOOK_CLIENT_ERROR_NO_SPACE;
-                       break;
-
-               case E_DATA_BOOK_STATUS_INVALID_ARG:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_INVALID_ARG;
-                       break;
-
-               case E_DATA_BOOK_STATUS_NOT_SUPPORTED:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_NOT_SUPPORTED;
-                       break;
-
-               case E_DATA_BOOK_STATUS_NOT_OPENED:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_NOT_OPENED;
-                       break;
-
-               case E_DATA_BOOK_STATUS_OUT_OF_SYNC:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_OUT_OF_SYNC;
-                       break;
-
-               case E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD:
-               case E_DATA_BOOK_STATUS_OTHER_ERROR:
-               case E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION:
-                       error->domain = E_CLIENT_ERROR;
-                       error->code = E_CLIENT_ERROR_OTHER_ERROR;
-                       break;
-
-               default:
-                       g_warn_if_reached ();
        }
 }
 
-/**
- * e_data_book_status_to_string:
- * @status: an #EDataBookStatus
- *
- * Get localized human readable description of the given status code.
- *
- * Returns: Localized human readable description of the given status code
- *
- * Since: 2.32
- **/
-const gchar *
-e_data_book_status_to_string (EDataBookStatus status)
-{
-       gint i;
-       static struct _statuses {
-               EDataBookStatus status;
-               const gchar *msg;
-       } statuses[] = {
-               { E_DATA_BOOK_STATUS_SUCCESS,                           N_("Success") },
-               { E_DATA_BOOK_STATUS_BUSY,                              N_("Backend is busy") },
-               { E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,                N_("Repository offline") },
-               { E_DATA_BOOK_STATUS_PERMISSION_DENIED,                 N_("Permission denied") },
-               { E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND,                 N_("Contact not found") },
-               { E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS,          N_("Contact ID already exists") },
-               { E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED,             N_("Authentication Failed") },
-               { E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED,           N_("Authentication Required") },
-               { E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD,                 N_("Unsupported field") },
-               { E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD, N_("Unsupported authentication 
method") },
-               { E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE,                 N_("TLS not available") },
-               { E_DATA_BOOK_STATUS_NO_SUCH_BOOK,                      N_("Address book does not exist") },
-               { E_DATA_BOOK_STATUS_BOOK_REMOVED,                      N_("Book removed") },
-               { E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE,               N_("Not available in offline mode") },
-               { E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED,        N_("Search size limit exceeded") },
-               { E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED,        N_("Search time limit exceeded") },
-               { E_DATA_BOOK_STATUS_INVALID_QUERY,                     N_("Invalid query") },
-               { E_DATA_BOOK_STATUS_QUERY_REFUSED,                     N_("Query refused") },
-               { E_DATA_BOOK_STATUS_COULD_NOT_CANCEL,                  N_("Could not cancel") },
-               /* { E_DATA_BOOK_STATUS_OTHER_ERROR,                    N_("Other error") }, */
-               { E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION,            N_("Invalid server version") },
-               { E_DATA_BOOK_STATUS_NO_SPACE,                          N_("No space") },
-               { E_DATA_BOOK_STATUS_INVALID_ARG,                       N_("Invalid argument") },
-               /* Translators: The string for NOT_SUPPORTED error */
-               { E_DATA_BOOK_STATUS_NOT_SUPPORTED,                     N_("Not supported") },
-               { E_DATA_BOOK_STATUS_NOT_OPENED,                        N_("Backend is not opened yet") },
-               { E_DATA_BOOK_STATUS_OUT_OF_SYNC,                       N_("Object is out of sync") }
-       };
-
-       for (i = 0; i < G_N_ELEMENTS (statuses); i++) {
-               if (statuses[i].status == status)
-                       return _(statuses[i].msg);
-       }
-
-       return _("Other error");
-}
-
-/* Create the EDataBook error quark */
-GQuark
-e_data_book_error_quark (void)
-{
-       #define ERR_PREFIX "org.gnome.evolution.dataserver.AddressBook."
-
-       static const GDBusErrorEntry entries[] = {
-               { E_DATA_BOOK_STATUS_SUCCESS,                           ERR_PREFIX "Success" },
-               { E_DATA_BOOK_STATUS_BUSY,                              ERR_PREFIX "Busy" },
-               { E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,                ERR_PREFIX "RepositoryOffline" },
-               { E_DATA_BOOK_STATUS_PERMISSION_DENIED,                 ERR_PREFIX "PermissionDenied" },
-               { E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND,                 ERR_PREFIX "ContactNotFound" },
-               { E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS,          ERR_PREFIX "ContactIDAlreadyExists" },
-               { E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED,             ERR_PREFIX "AuthenticationFailed" },
-               { E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED,           ERR_PREFIX "AuthenticationRequired" },
-               { E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD,                 ERR_PREFIX "UnsupportedField" },
-               { E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD, ERR_PREFIX 
"UnsupportedAuthenticationMethod" },
-               { E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE,                 ERR_PREFIX "TLSNotAvailable" },
-               { E_DATA_BOOK_STATUS_NO_SUCH_BOOK,                      ERR_PREFIX "NoSuchBook" },
-               { E_DATA_BOOK_STATUS_BOOK_REMOVED,                      ERR_PREFIX "BookRemoved" },
-               { E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE,               ERR_PREFIX "OfflineUnavailable" },
-               { E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED,        ERR_PREFIX "SearchSizeLimitExceeded" 
},
-               { E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED,        ERR_PREFIX "SearchTimeLimitExceeded" 
},
-               { E_DATA_BOOK_STATUS_INVALID_QUERY,                     ERR_PREFIX "InvalidQuery" },
-               { E_DATA_BOOK_STATUS_QUERY_REFUSED,                     ERR_PREFIX "QueryRefused" },
-               { E_DATA_BOOK_STATUS_COULD_NOT_CANCEL,                  ERR_PREFIX "CouldNotCancel" },
-               { E_DATA_BOOK_STATUS_OTHER_ERROR,                       ERR_PREFIX "OtherError" },
-               { E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION,            ERR_PREFIX "InvalidServerVersion" },
-               { E_DATA_BOOK_STATUS_NO_SPACE,                          ERR_PREFIX "NoSpace" },
-               { E_DATA_BOOK_STATUS_INVALID_ARG,                       ERR_PREFIX "InvalidArg" },
-               { E_DATA_BOOK_STATUS_NOT_SUPPORTED,                     ERR_PREFIX "NotSupported" },
-               { E_DATA_BOOK_STATUS_NOT_OPENED,                        ERR_PREFIX "NotOpened" },
-               { E_DATA_BOOK_STATUS_OUT_OF_SYNC,                       ERR_PREFIX "OutOfSync" }
-       };
-
-       #undef ERR_PREFIX
-
-       static volatile gsize quark_volatile = 0;
-
-       g_dbus_error_register_error_domain ("e-data-book-error", &quark_volatile, entries, G_N_ELEMENTS 
(entries));
-
-       return (GQuark) quark_volatile;
-}
-
-/**
- * e_data_book_create_error:
- * @status: #EDataBookStatus code
- * @custom_msg: Custom message to use for the error. When NULL,
- *              then uses a default message based on the @status code.
- *
- * Returns: NULL, when the @status is E_DATA_BOOK_STATUS_SUCCESS,
- *          or a newly allocated GError, which should be freed
- *          with g_error_free() call.
- *
- * Since: 2.32
- **/
-GError *
-e_data_book_create_error (EDataBookStatus status,
-                          const gchar *custom_msg)
-{
-       if (status == E_DATA_BOOK_STATUS_SUCCESS)
-               return NULL;
-
-       return g_error_new_literal (E_DATA_BOOK_ERROR, status, custom_msg ? custom_msg : 
e_data_book_status_to_string (status));
-}
-
-/**
- * e_data_book_create_error_fmt:
- * @status: an #EDataBookStatus
- * @custom_msg_fmt: Custom message to use for the error. When NULL,
- *   then uses a default message based on the @status code.
- * @...: arguments for the @custom_msg_fmt
- *
- * Similar as e_data_book_create_error(), only here, instead of custom_msg,
- * is used a printf() format to create a custom_msg for the error.
- *
- * Returns: (transfer full): a new #GError populated with the values
- *   from the parameters.
- *
- * Since: 2.32
- **/
-GError *
-e_data_book_create_error_fmt (EDataBookStatus status,
-                              const gchar *custom_msg_fmt,
-                              ...)
-{
-       GError *error;
-       gchar *custom_msg;
-       va_list ap;
-
-       if (!custom_msg_fmt)
-               return e_data_book_create_error (status, NULL);
-
-       va_start (ap, custom_msg_fmt);
-       custom_msg = g_strdup_vprintf (custom_msg_fmt, ap);
-       va_end (ap);
-
-       error = e_data_book_create_error (status, custom_msg);
-
-       g_free (custom_msg);
-
-       return error;
-}
-
 /**
  * e_data_book_string_slist_to_comma_string:
  * @strings: (element-type utf8): a list of gchar *
@@ -998,9 +722,10 @@ data_book_complete_create_contacts_cb (GObject *source_object,
 
 static gboolean
 data_book_handle_create_contacts_cb (EDBusAddressBook *dbus_interface,
-                                     GDBusMethodInvocation *invocation,
-                                     const gchar * const *in_vcards,
-                                     EDataBook *data_book)
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar * const *in_vcards,
+                                    guint32 in_opflags,
+                                    EDataBook *data_book)
 {
        EBookBackend *backend;
        AsyncContext *async_context;
@@ -1011,7 +736,7 @@ data_book_handle_create_contacts_cb (EDBusAddressBook *dbus_interface,
        async_context = async_context_new (data_book, invocation);
 
        e_book_backend_create_contacts (
-               backend, in_vcards,
+               backend, in_vcards, in_opflags,
                async_context->cancellable,
                data_book_complete_create_contacts_cb,
                async_context);
@@ -1047,9 +772,10 @@ data_book_complete_modify_contacts_cb (GObject *source_object,
 
 static gboolean
 data_book_handle_modify_contacts_cb (EDBusAddressBook *dbus_interface,
-                                     GDBusMethodInvocation *invocation,
-                                     const gchar * const *in_vcards,
-                                     EDataBook *data_book)
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar * const *in_vcards,
+                                    guint32 in_opflags,
+                                    EDataBook *data_book)
 {
        EBookBackend *backend;
        AsyncContext *async_context;
@@ -1060,7 +786,7 @@ data_book_handle_modify_contacts_cb (EDBusAddressBook *dbus_interface,
        async_context = async_context_new (data_book, invocation);
 
        e_book_backend_modify_contacts (
-               backend, in_vcards,
+               backend, in_vcards, in_opflags,
                async_context->cancellable,
                data_book_complete_modify_contacts_cb,
                async_context);
@@ -1096,9 +822,10 @@ data_book_complete_remove_contacts_cb (GObject *source_object,
 
 static gboolean
 data_book_handle_remove_contacts_cb (EDBusAddressBook *dbus_interface,
-                                     GDBusMethodInvocation *invocation,
-                                     const gchar * const *in_uids,
-                                     EDataBook *data_book)
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar * const *in_uids,
+                                    guint32 in_opflags,
+                                    EDataBook *data_book)
 {
        EBookBackend *backend;
        AsyncContext *async_context;
@@ -1109,7 +836,7 @@ data_book_handle_remove_contacts_cb (EDBusAddressBook *dbus_interface,
        async_context = async_context_new (data_book, invocation);
 
        e_book_backend_remove_contacts (
-               backend, in_uids,
+               backend, in_uids, in_opflags,
                async_context->cancellable,
                data_book_complete_remove_contacts_cb,
                async_context);
@@ -1469,16 +1196,16 @@ e_data_book_respond_refresh (EDataBook *book,
  * @book: An #EDataBook
  * @opid: An operation ID
  * @error: (nullable) (transfer full): Operation error, if any, automatically freed if passed it
- * @vcard: (nullable): the found vCard, as string, or %NULL, if it could not be found
+ * @contact: (nullable): the found #EContact, or %NULL, if it could not be found
  *
  * Notifies listeners of the completion of the get_contact method call.
- * Only one of @error and @vcard can be set.
+ * Only one of @error and @contact can be set.
  */
 void
 e_data_book_respond_get_contact (EDataBook *book,
                                  guint32 opid,
                                  GError *error,
-                                 const gchar *vcard)
+                                 const EContact *contact)
 {
        EBookBackend *backend;
        GSimpleAsyncResult *simple;
@@ -1497,11 +1224,7 @@ e_data_book_respond_get_contact (EDataBook *book,
        g_prefix_error (&error, "%s", _("Cannot get contact: "));
 
        if (error == NULL) {
-               EContact *contact;
-
-               contact = e_contact_new_from_vcard (vcard);
-               g_queue_push_tail (queue, g_object_ref (contact));
-               g_object_unref (contact);
+               g_queue_push_tail (queue, g_object_ref ((EContact *) contact));
        } else {
                g_simple_async_result_take_error (simple, error);
        }
@@ -1517,9 +1240,9 @@ e_data_book_respond_get_contact (EDataBook *book,
  * @book: An #EDataBook
  * @opid: An operation ID
  * @error: Operation error, if any, automatically freed if passed it
- * @cards: (allow-none) (element-type utf8): A list of vCard strings, or %NULL on error
+ * @contacts: (allow-none) (element-type EContact): A list of #EContact, or %NULL on error
  *
- * Finishes a call to get list of vCards which satisfy certain criteria.
+ * Finishes a call to get list of #EContact, which satisfy certain criteria.
  *
  * Since: 3.2
  **/
@@ -1527,7 +1250,7 @@ void
 e_data_book_respond_get_contact_list (EDataBook *book,
                                       guint32 opid,
                                       GError *error,
-                                      const GSList *cards)
+                                      const GSList *contacts)
 {
        EBookBackend *backend;
        GSimpleAsyncResult *simple;
@@ -1546,16 +1269,12 @@ e_data_book_respond_get_contact_list (EDataBook *book,
        g_prefix_error (&error, "%s", _("Cannot get contact list: "));
 
        if (error == NULL) {
-               GSList *list, *link;
+               GSList *link;
 
-               list = (GSList *) cards;
+               for (link = (GSList *) contacts; link; link = g_slist_next (link)) {
+                       EContact *contact = link->data;
 
-               for (link = list; link != NULL; link = g_slist_next (link)) {
-                       EContact *contact;
-
-                       contact = e_contact_new_from_vcard (link->data);
                        g_queue_push_tail (queue, g_object_ref (contact));
-                       g_object_unref (contact);
                }
 
        } else {
@@ -1653,12 +1372,10 @@ e_data_book_respond_create_contacts (EDataBook *book,
        g_prefix_error (&error, "%s", _("Cannot add contact: "));
 
        if (error == NULL) {
-               GSList *list, *link;
-
-               list = (GSList *) contacts;
+               GSList *link;
 
-               for (link = list; link != NULL; link = g_slist_next (link)) {
-                       EContact *contact = E_CONTACT (link->data);
+               for (link = (GSList *) contacts; link; link = g_slist_next (link)) {
+                       EContact *contact = link->data;
                        g_queue_push_tail (queue, g_object_ref (contact));
                }
 
@@ -1706,12 +1423,11 @@ e_data_book_respond_modify_contacts (EDataBook *book,
        g_prefix_error (&error, "%s", _("Cannot modify contacts: "));
 
        if (error == NULL) {
-               GSList *list, *link;
+               GSList *link;
 
-               list = (GSList *) contacts;
+               for (link = (GSList *) contacts; link; link = g_slist_next (link)) {
+                       EContact *contact = contacts->data;
 
-               for (link = list; link != NULL; link = g_slist_next (link)) {
-                       EContact *contact = E_CONTACT (contacts->data);
                        g_queue_push_tail (queue, g_object_ref (contact));
                }
 
@@ -1759,11 +1475,9 @@ e_data_book_respond_remove_contacts (EDataBook *book,
        g_prefix_error (&error, "%s", _("Cannot remove contacts: "));
 
        if (error == NULL) {
-               GSList *list, *link;
-
-               list = (GSList *) ids;
+               GSList *link;
 
-               for (link = list; link != NULL; link = g_slist_next (link))
+               for (link = (GSList *) ids; link; link = g_slist_next (link))
                        g_queue_push_tail (queue, g_strdup (link->data));
 
        } else {
@@ -1842,14 +1556,14 @@ e_data_book_report_backend_property_changed (EDataBook *book,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_REVISION))
                e_dbus_address_book_set_revision (dbus_interface, prop_value);
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                strv = g_strsplit (prop_value, ",", -1);
                e_dbus_address_book_set_required_fields (
                        dbus_interface, (const gchar * const *) strv);
                g_strfreev (strv);
        }
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                strv = g_strsplit (prop_value, ",", -1);
                e_dbus_address_book_set_supported_fields (
                        dbus_interface, (const gchar * const *) strv);
@@ -2048,13 +1762,13 @@ data_book_constructed (GObject *object)
                book, prop_name, prop_value);
        g_free (prop_value);
 
-       prop_name = BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
+       prop_name = E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
        prop_value = e_book_backend_get_backend_property (backend, prop_name);
        e_data_book_report_backend_property_changed (
                book, prop_name, prop_value);
        g_free (prop_value);
 
-       prop_name = BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
+       prop_name = E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
        prop_value = e_book_backend_get_backend_property (backend, prop_name);
        e_data_book_report_backend_property_changed (
                book, prop_name, prop_value);
diff --git a/src/addressbook/libedata-book/e-data-book.h b/src/addressbook/libedata-book/e-data-book.h
index 48e8a0bad..5603c7976 100644
--- a/src/addressbook/libedata-book/e-data-book.h
+++ b/src/addressbook/libedata-book/e-data-book.h
@@ -64,22 +64,6 @@ struct _EDataBookClass {
 
 GQuark e_data_book_error_quark (void);
 
-/**
- * E_DATA_BOOK_ERROR:
- *
- * Since: 2.30
- **/
-#define E_DATA_BOOK_ERROR e_data_book_error_quark ()
-
-GError *       e_data_book_create_error        (EDataBookStatus status,
-                                                const gchar *custom_msg);
-
-GError *       e_data_book_create_error_fmt    (EDataBookStatus status,
-                                                const gchar *custom_msg_fmt,
-                                                ...) G_GNUC_PRINTF (2, 3);
-
-const gchar *  e_data_book_status_to_string    (EDataBookStatus status);
-
 GType          e_data_book_get_type            (void) G_GNUC_CONST;
 EDataBook *    e_data_book_new                 (struct _EBookBackend *backend,
                                                 GDBusConnection *connection,
@@ -105,31 +89,31 @@ void               e_data_book_respond_create_contacts
                                                (EDataBook *book,
                                                 guint32 opid,
                                                 GError *error,
-                                                const GSList *contacts);
-void           e_data_book_respond_remove_contacts
+                                                const GSList *contacts); /* EContact * */
+void           e_data_book_respond_modify_contacts
                                                (EDataBook *book,
                                                 guint32 opid,
                                                 GError *error,
-                                                const GSList *ids);
-void           e_data_book_respond_modify_contacts
+                                                const GSList *contacts); /* EContact * */
+void           e_data_book_respond_remove_contacts
                                                (EDataBook *book,
                                                 guint32 opid,
                                                 GError *error,
-                                                const GSList *contacts);
+                                                const GSList *ids); /* gchar * */
 void           e_data_book_respond_get_contact (EDataBook *book,
                                                 guint32 opid,
                                                 GError *error,
-                                                const gchar *vcard);
+                                                const EContact *contact);
 void           e_data_book_respond_get_contact_list
                                                (EDataBook *book,
                                                 guint32 opid,
                                                 GError *error,
-                                                const GSList *cards);
+                                                const GSList *contacts); /* EContact * */
 void           e_data_book_respond_get_contact_list_uids
                                                (EDataBook *book,
                                                 guint32 opid,
                                                 GError *error,
-                                                const GSList *uids);
+                                                const GSList *uids); /* gchar * */
 
 void           e_data_book_report_error        (EDataBook *book,
                                                 const gchar *message);
diff --git a/src/addressbook/libedata-book/libedata-book.h b/src/addressbook/libedata-book/libedata-book.h
index b5db50376..183147d62 100644
--- a/src/addressbook/libedata-book/libedata-book.h
+++ b/src/addressbook/libedata-book/libedata-book.h
@@ -23,12 +23,13 @@
 #include <libebook-contacts/libebook-contacts.h>
 #include <libebackend/libebackend.h>
 
+#include <libedata-book/e-book-backend.h>
 #include <libedata-book/e-book-backend-cache.h>
 #include <libedata-book/e-book-backend-factory.h>
 #include <libedata-book/e-book-backend-sexp.h>
 #include <libedata-book/e-book-backend-sqlitedb.h>
 #include <libedata-book/e-book-backend-summary.h>
-#include <libedata-book/e-book-backend.h>
+#include <libedata-book/e-book-backend-sync.h>
 #include <libedata-book/e-book-cache.h>
 #include <libedata-book/e-book-meta-backend.h>
 #include <libedata-book/e-book-sqlite.h>
diff --git a/src/calendar/backends/contacts/e-cal-backend-contacts.c 
b/src/calendar/backends/contacts/e-cal-backend-contacts.c
index d9cff70ef..eef2fa564 100644
--- a/src/calendar/backends/contacts/e-cal-backend-contacts.c
+++ b/src/calendar/backends/contacts/e-cal-backend-contacts.c
@@ -1197,7 +1197,6 @@ static void
 e_cal_backend_contacts_open (ECalBackendSync *backend,
                              EDataCal *cal,
                              GCancellable *cancellable,
-                             gboolean only_if_exists,
                              GError **perror)
 {
        ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
diff --git a/src/calendar/backends/file/e-cal-backend-file.c b/src/calendar/backends/file/e-cal-backend-file.c
index 7505d5006..451561c67 100644
--- a/src/calendar/backends/file/e-cal-backend-file.c
+++ b/src/calendar/backends/file/e-cal-backend-file.c
@@ -1442,7 +1442,6 @@ static void
 e_cal_backend_file_open (ECalBackendSync *backend,
                          EDataCal *cal,
                          GCancellable *cancellable,
-                         gboolean only_if_exists,
                          GError **perror)
 {
        ECalBackendFile *cbfile;
@@ -1477,10 +1476,7 @@ e_cal_backend_file_open (ECalBackendSync *backend,
                if (g_access (str_uri, W_OK) != 0)
                        writable = FALSE;
        } else {
-               if (only_if_exists)
-                       err = ECC_ERROR (E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR);
-               else
-                       create_cal (cbfile, str_uri, &err);
+               create_cal (cbfile, str_uri, &err);
        }
 
        if (!err) {
diff --git a/src/calendar/backends/weather/e-cal-backend-weather.c 
b/src/calendar/backends/weather/e-cal-backend-weather.c
index 0fa5513f1..a1ec0c2cf 100644
--- a/src/calendar/backends/weather/e-cal-backend-weather.c
+++ b/src/calendar/backends/weather/e-cal-backend-weather.c
@@ -661,7 +661,6 @@ static void
 e_cal_backend_weather_open (ECalBackendSync *backend,
                             EDataCal *cal,
                             GCancellable *cancellable,
-                            gboolean only_if_exists,
                             GError **perror)
 {
        ECalBackendWeather *cbw;
diff --git a/src/calendar/libedata-cal/e-cal-backend-sync.c b/src/calendar/libedata-cal/e-cal-backend-sync.c
index 4bf602adf..8787c78a5 100644
--- a/src/calendar/libedata-cal/e-cal-backend-sync.c
+++ b/src/calendar/libedata-cal/e-cal-backend-sync.c
@@ -44,7 +44,6 @@ G_DEFINE_TYPE (ECalBackendSync, e_cal_backend_sync, E_TYPE_CAL_BACKEND)
  * @backend: An ECalBackendSync object.
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
- * @only_if_exists: Whether to open the calendar if and only if it already exists
  * or just create it when it does not exist.
  * @error: Out parameter for a #GError.
  *
@@ -54,7 +53,6 @@ void
 e_cal_backend_sync_open (ECalBackendSync *backend,
                          EDataCal *cal,
                          GCancellable *cancellable,
-                         gboolean only_if_exists,
                          GError **error)
 {
        ECalBackendSyncClass *class;
@@ -65,8 +63,7 @@ e_cal_backend_sync_open (ECalBackendSync *backend,
        g_return_if_fail (class != NULL);
 
        if (class->open_sync != NULL) {
-               class->open_sync (
-                       backend, cal, cancellable, only_if_exists, error);
+               class->open_sync (backend, cal, cancellable, error);
        } else {
                g_set_error_literal (
                        error, E_CLIENT_ERROR,
@@ -652,12 +649,11 @@ static void
 cal_backend_open (ECalBackend *backend,
                   EDataCal *cal,
                   guint32 opid,
-                  GCancellable *cancellable,
-                  gboolean only_if_exists)
+                  GCancellable *cancellable)
 {
        GError *error = NULL;
 
-       e_cal_backend_sync_open (E_CAL_BACKEND_SYNC (backend), cal, cancellable, only_if_exists, &error);
+       e_cal_backend_sync_open (E_CAL_BACKEND_SYNC (backend), cal, cancellable, &error);
 
        e_data_cal_respond_open (cal, opid, error);
 }
diff --git a/src/calendar/libedata-cal/e-cal-backend-sync.h b/src/calendar/libedata-cal/e-cal-backend-sync.h
index b0f8b85e1..90d472a7e 100644
--- a/src/calendar/libedata-cal/e-cal-backend-sync.h
+++ b/src/calendar/libedata-cal/e-cal-backend-sync.h
@@ -90,7 +90,6 @@ struct _ECalBackendSyncClass {
        void            (*open_sync)            (ECalBackendSync *backend,
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
-                                                gboolean only_if_exists,
                                                 GError **error);
        void            (*refresh_sync)         (ECalBackendSync *backend,
                                                 EDataCal *cal,
@@ -194,7 +193,6 @@ GType               e_cal_backend_sync_get_type     (void) G_GNUC_CONST;
 void           e_cal_backend_sync_open         (ECalBackendSync *backend,
                                                 EDataCal *cal,
                                                 GCancellable *cancellable,
-                                                gboolean only_if_exists,
                                                 GError **error);
 void           e_cal_backend_sync_refresh      (ECalBackendSync *backend,
                                                 EDataCal *cal,
diff --git a/src/calendar/libedata-cal/e-cal-backend.c b/src/calendar/libedata-cal/e-cal-backend.c
index 01bda3efc..adcd7b2a4 100644
--- a/src/calendar/libedata-cal/e-cal-backend.c
+++ b/src/calendar/libedata-cal/e-cal-backend.c
@@ -1606,7 +1606,7 @@ cal_backend_open_thread (GSimpleAsyncResult *simple,
 
                e_backend_ensure_online_state_updated (E_BACKEND (backend), cancellable);
 
-               class->open (backend, data_cal, opid, cancellable, FALSE);
+               class->open (backend, data_cal, opid, cancellable);
        }
 
        g_object_unref (data_cal);
diff --git a/src/calendar/libedata-cal/e-cal-backend.h b/src/calendar/libedata-cal/e-cal-backend.h
index 3423b1d10..9c6a5a64b 100644
--- a/src/calendar/libedata-cal/e-cal-backend.h
+++ b/src/calendar/libedata-cal/e-cal-backend.h
@@ -113,8 +113,7 @@ struct _ECalBackendClass {
        void            (*open)                 (ECalBackend *backend,
                                                 EDataCal *cal,
                                                 guint32 opid,
-                                                GCancellable *cancellable,
-                                                gboolean only_if_exists);
+                                                GCancellable *cancellable);
 
        void            (*refresh)              (ECalBackend *backend,
                                                 EDataCal *cal,
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.c b/src/calendar/libedata-cal/e-cal-meta-backend.c
index 94b069fea..8ca9d8237 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.c
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.c
@@ -1235,7 +1235,6 @@ static void
 ecmb_open_sync (ECalBackendSync *sync_backend,
                EDataCal *cal,
                GCancellable *cancellable,
-               gboolean only_if_exists,
                GError **error)
 {
        ECalMetaBackend *meta_backend;
diff --git a/src/examples/cursor/cursor-data.c b/src/examples/cursor/cursor-data.c
index 57bc51c07..9d19b5805 100644
--- a/src/examples/cursor/cursor-data.c
+++ b/src/examples/cursor/cursor-data.c
@@ -113,7 +113,7 @@ load_contacts (EBookClient *client,
 
        if (contacts != NULL) {
 
-               if (!e_book_client_add_contacts_sync (client, contacts, NULL, NULL, &error)) {
+               if (!e_book_client_add_contacts_sync (client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, 
NULL, &error)) {
 
                        /* If they were already added, ignore the error */
                        if (g_error_matches (error, E_BOOK_CLIENT_ERROR,
diff --git a/src/libedataserver/e-client.c b/src/libedataserver/e-client.c
index b85f99845..aadc84c84 100644
--- a/src/libedataserver/e-client.c
+++ b/src/libedataserver/e-client.c
@@ -67,7 +67,6 @@ struct _AsyncContext {
        gchar *capabilities;
        gchar *prop_name;
        gchar *prop_value;
-       gboolean only_if_exists;
 };
 
 enum {
@@ -626,15 +625,9 @@ client_open_thread (GSimpleAsyncResult *simple,
                     GObject *source_object,
                     GCancellable *cancellable)
 {
-       AsyncContext *async_context;
        GError *error = NULL;
 
-       async_context = g_simple_async_result_get_op_res_gpointer (simple);
-
-       e_client_open_sync (
-               E_CLIENT (source_object),
-               async_context->only_if_exists,
-               cancellable, &error);
+       e_client_open_sync (E_CLIENT (source_object), FALSE, cancellable, &error);
 
        if (error != NULL)
                g_simple_async_result_take_error (simple, error);
@@ -651,7 +644,6 @@ client_open (EClient *client,
        AsyncContext *async_context;
 
        async_context = g_slice_new0 (AsyncContext);
-       async_context->only_if_exists = only_if_exists;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data, client_open);
@@ -1602,8 +1594,7 @@ e_client_set_backend_property_sync (EClient *client,
 /**
  * e_client_open:
  * @client: an #EClient
- * @only_if_exists: if %TRUE, fail if this book doesn't already exist,
- *                  otherwise create it first
+ * @only_if_exists: this parameter is not used anymore
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -1673,8 +1664,7 @@ e_client_open_finish (EClient *client,
 /**
  * e_client_open_sync:
  * @client: an #EClient
- * @only_if_exists: if %TRUE, fail if this book doesn't already exist,
- *                  otherwise create it first
+ * @only_if_exists: this parameter is not used anymore
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
diff --git a/src/private/org.gnome.evolution.dataserver.AddressBook.xml 
b/src/private/org.gnome.evolution.dataserver.AddressBook.xml
index b91f82bbe..61c645ba0 100644
--- a/src/private/org.gnome.evolution.dataserver.AddressBook.xml
+++ b/src/private/org.gnome.evolution.dataserver.AddressBook.xml
@@ -42,15 +42,18 @@
 
   <method name="CreateContacts">
     <arg name="vcards" direction="in" type="as"/>
+    <arg name="opflags" direction="in" type="u"/>
     <arg name="uids" direction="out" type="as"/>
   </method>
 
   <method name="ModifyContacts">
     <arg name="vcards" direction="in" type="as"/>
+    <arg name="opflags" direction="in" type="u"/>
   </method>
 
   <method name="RemoveContacts">
     <arg name="uids" direction="in" type="as"/>
+    <arg name="opflags" direction="in" type="u"/>
   </method>
 
   <method name="GetContact">
diff --git a/tests/book-migration/setup-migration-test.c b/tests/book-migration/setup-migration-test.c
index 9021f5d62..dbc830c97 100644
--- a/tests/book-migration/setup-migration-test.c
+++ b/tests/book-migration/setup-migration-test.c
@@ -238,7 +238,7 @@ add_contacts (Book *book,
 {
        GError *error = NULL;
 
-       if (!e_book_client_add_contacts_sync (book, contacts, NULL, NULL, &error))
+       if (!e_book_client_add_contacts_sync (book, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, &error))
                g_error ("Failed to add contacts: %s", error->message);
 }
 
diff --git a/tests/book-migration/test-migration.c b/tests/book-migration/test-migration.c
index 172efa618..b7b40e2a1 100644
--- a/tests/book-migration/test-migration.c
+++ b/tests/book-migration/test-migration.c
@@ -174,10 +174,10 @@ test_add_remove_contact (MigrationFixture *fixture,
 
        contact = e_contact_new_from_vcard (arbitrary_vcard);
 
-       if (!e_book_client_add_contact_sync (book_client, contact, NULL, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, 
&error))
                g_error ("Failed to add contact: %s", error->message);
 
-       if (!e_book_client_remove_contact_sync (book_client, contact, NULL, &error))
+       if (!e_book_client_remove_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("Failed to remove contact: %s", error->message);
 
        g_object_unref (contact);
diff --git a/tests/libebook/client/client-test-utils.c b/tests/libebook/client/client-test-utils.c
index 33db04422..f6ff5363d 100644
--- a/tests/libebook/client/client-test-utils.c
+++ b/tests/libebook/client/client-test-utils.c
@@ -115,7 +115,7 @@ add_contact_from_test_case_verify (EBookClient *book_client,
        vcard = new_vcard_from_test_case (case_name);
        contact_orig = e_contact_new_from_vcard (vcard);
        g_free (vcard);
-       if (!e_book_client_add_contact_sync (book_client, contact_orig, &uid, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact_orig, E_BOOK_OPERATION_FLAG_NONE, &uid, 
NULL, &error))
                g_error ("add contact sync: %s", error->message);
 
        e_contact_set (contact_orig, E_CONTACT_UID, uid);
@@ -144,7 +144,7 @@ add_contact_verify (EBookClient *book_client,
        gchar *uid;
        GError *error = NULL;
 
-       if (!e_book_client_add_contact_sync (book_client, contact, &uid, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("add contact sync: %s", error->message);
 
        e_contact_set (contact, E_CONTACT_UID, uid);
diff --git a/tests/libebook/client/test-book-client-add-and-get-async.c 
b/tests/libebook/client/test-book-client-add-and-get-async.c
index a88f55550..3267aadcc 100644
--- a/tests/libebook/client/test-book-client-add-and-get-async.c
+++ b/tests/libebook/client/test-book-client-add-and-get-async.c
@@ -186,7 +186,7 @@ add_contacts (EBookClient *book_client,
        g_free (vcard);
        contacts = g_slist_prepend (contacts, contact);
 
-       e_book_client_add_contacts (book_client, contacts, NULL, contacts_added_cb, loop);
+       e_book_client_add_contacts (book_client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, 
contacts_added_cb, loop);
 
        e_util_free_object_slist (contacts);
 }
diff --git a/tests/libebook/client/test-book-client-add-contact.c 
b/tests/libebook/client/test-book-client-add-contact.c
index d618894a9..6ce86f721 100644
--- a/tests/libebook/client/test-book-client-add-contact.c
+++ b/tests/libebook/client/test-book-client-add-contact.c
@@ -70,7 +70,7 @@ test_add_contact_async (ETestServerFixture *fixture,
        contact = e_contact_new_from_vcard (vcard);
        g_free (vcard);
 
-       e_book_client_add_contact (book_client, contact, NULL, add_contact_cb, fixture->loop);
+       e_book_client_add_contact (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, add_contact_cb, 
fixture->loop);
        g_object_unref (contact);
 
        g_main_loop_run (fixture->loop);
diff --git a/tests/libebook/client/test-book-client-cursor-operations.c 
b/tests/libebook/client/test-book-client-cursor-operations.c
index b57add1af..9063d3dc6 100644
--- a/tests/libebook/client/test-book-client-cursor-operations.c
+++ b/tests/libebook/client/test-book-client-cursor-operations.c
@@ -309,7 +309,7 @@ cursor_fixture_add_contacts (CursorFixture *fixture,
                fixture->contacts[i] = contact;
        }
 
-       if (!e_book_client_add_contacts_sync (book_client, contacts, NULL, NULL, &error)) {
+       if (!e_book_client_add_contacts_sync (book_client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, 
&error)) {
 
                /* Dont complain here, we re-use the same addressbook for multiple tests
                 * and we can't add the same contacts twice
@@ -1312,11 +1312,11 @@ cursor_test_add_remove (CursorFixture *fixture,
 
                if (modify->add)
                        e_book_client_add_contact (
-                               book_client, contact,
+                               book_client, contact, E_BOOK_OPERATION_FLAG_NONE,
                                NULL, cursor_test_add_remove_ready_cb, &data);
                else
                        e_book_client_remove_contact (
-                               book_client, contact,
+                               book_client, contact, E_BOOK_OPERATION_FLAG_NONE,
                                NULL, cursor_test_add_remove_ready_cb, &data);
 
                /* Wait for result with an error timeout */
@@ -1331,14 +1331,11 @@ cursor_test_add_remove (CursorFixture *fixture,
 
                if (modify->add)
                        success = e_book_client_add_contact_sync (
-                               book_client,
-                               contact,
-                               &new_uid,
-                               NULL, &error);
+                               book_client, contact, E_BOOK_OPERATION_FLAG_NONE,
+                               &new_uid, NULL, &error);
                else
                        success = e_book_client_remove_contact_sync (
-                               book_client,
-                               contact,
+                               book_client, contact, E_BOOK_OPERATION_FLAG_NONE,
                                NULL, &error);
 
                if (!success)
diff --git a/tests/libebook/client/test-book-client-custom-summary.c 
b/tests/libebook/client/test-book-client-custom-summary.c
index 80f0cfc1c..c9e75948c 100644
--- a/tests/libebook/client/test-book-client-custom-summary.c
+++ b/tests/libebook/client/test-book-client-custom-summary.c
@@ -114,7 +114,7 @@ setup_book (ClientTestFixture *fixture)
                g_free (case_name);
        }
 
-       if (!e_book_client_add_contacts_sync (book_client, contacts, NULL, NULL, &error)) {
+       if (!e_book_client_add_contacts_sync (book_client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, 
&error)) {
 
                /* Dont complain here, we may re-use the same addressbook for multiple tests
                 * and we can't add the same contacts twice
diff --git a/tests/libebook/client/test-book-client-e164-param.c 
b/tests/libebook/client/test-book-client-e164-param.c
index 3d2ea5476..f254bfeed 100644
--- a/tests/libebook/client/test-book-client-e164-param.c
+++ b/tests/libebook/client/test-book-client-e164-param.c
@@ -98,7 +98,7 @@ test_add_e164_param (ETestServerFixture *fixture,
        values = e_vcard_attribute_get_param (tel, EVC_X_E164);
        g_assert (values == NULL);
 
-       if (!e_book_client_add_contact_sync (book_client, contact, &uid, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("Failed to add contact: %s", error->message);
 
        g_object_unref (contact);
diff --git a/tests/libebook/client/test-book-client-get-revision.c 
b/tests/libebook/client/test-book-client-get-revision.c
index 8995f0659..cd7c41395 100644
--- a/tests/libebook/client/test-book-client-get-revision.c
+++ b/tests/libebook/client/test-book-client-get-revision.c
@@ -40,7 +40,7 @@ get_revision_compare_cycle (EBookClient *client)
                exit (1);
        }
 
-       if (!e_book_client_remove_contact_sync (client, contact, NULL, &error))
+       if (!e_book_client_remove_contact_sync (client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("Unable to remove contact: %s", error->message);
 
        g_object_unref (contact);
diff --git a/tests/libebook/client/test-book-client-modify-contact.c 
b/tests/libebook/client/test-book-client-modify-contact.c
index ac50c1f80..11a48b93f 100644
--- a/tests/libebook/client/test-book-client-modify-contact.c
+++ b/tests/libebook/client/test-book-client-modify-contact.c
@@ -65,7 +65,7 @@ test_modify_contact_sync (ETestServerFixture *fixture,
 
        verify_premodify_and_prepare_contact (contact);
 
-       if (!e_book_client_modify_contact_sync (book_client, contact, NULL, &error))
+       if (!e_book_client_modify_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("modify contact sync: %s", error->message);
 
        if (!e_book_client_get_contact_sync (book_client, e_contact_get_const (contact, E_CONTACT_UID),
@@ -134,7 +134,7 @@ test_modify_contact_async (ETestServerFixture *fixture,
 
        data.contact = contact;
        data.loop = fixture->loop;
-       e_book_client_modify_contact (book_client, contact, NULL, contact_modified_cb, &data);
+       e_book_client_modify_contact (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
contact_modified_cb, &data);
 
        g_main_loop_run (fixture->loop);
 
diff --git a/tests/libebook/client/test-book-client-photo-is-uri.c 
b/tests/libebook/client/test-book-client-photo-is-uri.c
index e698597ed..1f33c1a09 100644
--- a/tests/libebook/client/test-book-client-photo-is-uri.c
+++ b/tests/libebook/client/test-book-client-photo-is-uri.c
@@ -137,7 +137,7 @@ give_james_brown_micheal_jacksons_face (EBookClient *book)
        e_contact_photo_free (micheal_face);
        e_contact_photo_free (james_face);
 
-       if (!e_book_client_modify_contact_sync (book, james, NULL, &error))
+       if (!e_book_client_modify_contact_sync (book, james, E_BOOK_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("Failed to modify contact with cross referenced photo: %s", error->message);
 }
 
@@ -169,7 +169,7 @@ update_contact_inline (EBookClient *book,
 
        e_contact_photo_free (photo);
 
-       if (!e_book_client_modify_contact_sync (book, contact, NULL, &error))
+       if (!e_book_client_modify_contact_sync (book, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("Failed to modify contact with inline photo data: %s", error->message);
 }
 
@@ -218,7 +218,7 @@ complete (EBookClientView *view,
        case ITERATION_DELETE_JAMES:
                assert_uri_exists (book, james_brown_uid);
 
-               if (!e_book_client_remove_contact_by_uid_sync (book, james_brown_uid, NULL, &local_error))
+               if (!e_book_client_remove_contact_by_uid_sync (book, james_brown_uid, 
E_BOOK_OPERATION_FLAG_NONE, NULL, &local_error))
                        g_error ("Error removing contact: %s", local_error->message);
 
                g_free (james_brown_uid);
@@ -232,7 +232,7 @@ complete (EBookClientView *view,
        case ITERATION_DELETE_MICHEAL:
                assert_uri_exists (book, micheal_jackson_uid);
 
-               if (!e_book_client_remove_contact_by_uid_sync (book, micheal_jackson_uid, NULL, &local_error))
+               if (!e_book_client_remove_contact_by_uid_sync (book, micheal_jackson_uid, 
E_BOOK_OPERATION_FLAG_NONE, NULL, &local_error))
                        g_error ("Error removing contact: %s", local_error->message);
 
                g_free (micheal_jackson_uid);
diff --git a/tests/libebook/client/test-book-client-preserve-uid.c 
b/tests/libebook/client/test-book-client-preserve-uid.c
index 2afcbdf74..fa0aa4dc7 100644
--- a/tests/libebook/client/test-book-client-preserve-uid.c
+++ b/tests/libebook/client/test-book-client-preserve-uid.c
@@ -45,7 +45,7 @@ test_preserve_uid (ETestServerFixture *fixture,
 
        e_contact_set (contact, E_CONTACT_UID, TEST_CONTACT_UID);
 
-       if (!e_book_client_add_contact_sync (book_client, contact, &uid, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("Failed to add contact: %s", error->message);
 
        g_assert_cmpstr (uid, ==, TEST_CONTACT_UID);
@@ -73,7 +73,7 @@ test_uid_conflict (ETestServerFixture *fixture,
 
        e_contact_set (contact, E_CONTACT_UID, TEST_CONTACT_UID);
 
-       if (!e_book_client_add_contact_sync (book_client, contact, NULL, NULL, &error)) {
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, 
&error)) {
                g_assert (g_error_matches (error, E_BOOK_CLIENT_ERROR, 
E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS));
                g_error_free (error);
        } else
diff --git a/tests/libebook/client/test-book-client-remove-contact-by-uid.c 
b/tests/libebook/client/test-book-client-remove-contact-by-uid.c
index 7bbcc4712..b333a8d93 100644
--- a/tests/libebook/client/test-book-client-remove-contact-by-uid.c
+++ b/tests/libebook/client/test-book-client-remove-contact-by-uid.c
@@ -38,7 +38,7 @@ test_remove_contact_by_uid_sync (ETestServerFixture *fixture,
 
        uid = e_contact_get (contact, E_CONTACT_UID);
 
-       if (!e_book_client_remove_contact_by_uid_sync (book_client, uid, NULL, &error))
+       if (!e_book_client_remove_contact_by_uid_sync (book_client, uid, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("remove contact sync: %s", error->message);
 
        if (!e_book_client_get_contact_sync (book_client, uid, &contact, NULL, &error) &&
@@ -94,7 +94,7 @@ test_remove_contact_by_uid_async (ETestServerFixture *fixture,
 
        data.uid = uid;
        data.loop = fixture->loop;
-       e_book_client_remove_contact_by_uid (book_client, uid, NULL, remove_contact_by_uid_cb, &data);
+       e_book_client_remove_contact_by_uid (book_client, uid, E_BOOK_OPERATION_FLAG_NONE, NULL, 
remove_contact_by_uid_cb, &data);
 
        g_object_unref (contact);
 
diff --git a/tests/libebook/client/test-book-client-remove-contact.c 
b/tests/libebook/client/test-book-client-remove-contact.c
index 4fc04e065..850be973f 100644
--- a/tests/libebook/client/test-book-client-remove-contact.c
+++ b/tests/libebook/client/test-book-client-remove-contact.c
@@ -41,7 +41,7 @@ check_removed_contact (EBookClient *book_client,
        else
                g_clear_error (&error);
 
-       if (e_book_client_remove_contact_by_uid_sync (book_client, uid, NULL, &error))
+       if (e_book_client_remove_contact_by_uid_sync (book_client, uid, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("succeeded to remove the already removed contact");
        else if (!g_error_matches (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND))
                g_error (
@@ -67,7 +67,7 @@ test_remove_contact_sync (ETestServerFixture *fixture,
 
        uid = e_contact_get (contact, E_CONTACT_UID);
 
-       if (!e_book_client_remove_contact_sync (book_client, contact, NULL, &error))
+       if (!e_book_client_remove_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("remove contact sync: %s", error->message);
 
        g_object_unref (contact);
@@ -116,7 +116,7 @@ test_remove_contact_async (ETestServerFixture *fixture,
 
        data.uid = uid;
        data.loop = fixture->loop;
-       e_book_client_remove_contact (book_client, contact, NULL, remove_contact_cb, &data);
+       e_book_client_remove_contact (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
remove_contact_cb, &data);
 
        g_object_unref (contact);
 
diff --git a/tests/libebook/client/test-book-client-remove-contacts.c 
b/tests/libebook/client/test-book-client-remove-contacts.c
index a51517bfa..d7ca10583 100644
--- a/tests/libebook/client/test-book-client-remove-contacts.c
+++ b/tests/libebook/client/test-book-client-remove-contacts.c
@@ -82,7 +82,7 @@ test_remove_contacts_sync (ETestServerFixture *fixture,
        if (!fill_book_client (book_client, &uids))
                g_error ("Failed to add contacts");
 
-       if (!e_book_client_remove_contacts_sync (book_client, uids, NULL, &error))
+       if (!e_book_client_remove_contacts_sync (book_client, uids, E_BOOK_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("remove contact sync: %s", error->message);
 
        /* This will assert they are actually removed */
@@ -126,7 +126,7 @@ test_remove_contacts_async (ETestServerFixture *fixture,
 
        data.uids = uids;
        data.loop = fixture->loop;
-       e_book_client_remove_contacts (book_client, uids, NULL, remove_contacts_cb, &data);
+       e_book_client_remove_contacts (book_client, uids, E_BOOK_OPERATION_FLAG_NONE, NULL, 
remove_contacts_cb, &data);
 
        g_main_loop_run (fixture->loop);
 
diff --git a/tests/libebook/client/test-book-client-self.c b/tests/libebook/client/test-book-client-self.c
index a1537b97d..b146bbf47 100644
--- a/tests/libebook/client/test-book-client-self.c
+++ b/tests/libebook/client/test-book-client-self.c
@@ -65,7 +65,7 @@ test_set_self (ETestServerFixture *fixture,
        if (e_book_client_get_contact_sync (client, "simple-1", &loaded_contact, NULL, NULL)) {
                g_clear_object (&loaded_contact);
 
-               e_book_client_remove_contact_by_uid_sync (client, "simple-1", NULL, &error);
+               e_book_client_remove_contact_by_uid_sync (client, "simple-1", E_BOOK_OPERATION_FLAG_NONE, 
NULL, &error);
                g_assert_no_error (error);
        }
 
diff --git a/tests/libebook/client/test-book-client-write-write.c 
b/tests/libebook/client/test-book-client-write-write.c
index 00e6caed4..e31f52d11 100644
--- a/tests/libebook/client/test-book-client-write-write.c
+++ b/tests/libebook/client/test-book-client-write-write.c
@@ -133,7 +133,7 @@ test_write_thread_contact_fetched (GObject *source_object,
        e_contact_set (contact, data->field, data->value);
 
        e_book_client_modify_contact (
-               data->client, contact, NULL,
+               data->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                (GAsyncReadyCallback) test_write_thread_contact_modified, data);
 
        g_object_unref (contact);
diff --git a/tests/libedata-book/test-book-cache-cursor-calculate.c 
b/tests/libedata-book/test-book-cache-cursor-calculate.c
index 7eb21b7a3..8d32229c5 100644
--- a/tests/libedata-book/test-book-cache-cursor-calculate.c
+++ b/tests/libedata-book/test-book-cache-cursor-calculate.c
@@ -260,7 +260,7 @@ test_cursor_calculate_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[19 - 1],
                                        e_contact_get_const (fixture->contacts[19 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Rename Müller -> Sade Adu */
@@ -269,7 +269,7 @@ test_cursor_calculate_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[20 - 1],
                                        e_contact_get_const (fixture->contacts[20 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Check new position */
@@ -410,7 +410,7 @@ test_cursor_calculate_filtered_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[18 - 1],
                                        e_contact_get_const (fixture->contacts[18 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* 'black-birds' -> Sade Adu */
@@ -419,7 +419,7 @@ test_cursor_calculate_filtered_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[17 - 1],
                                        e_contact_get_const (fixture->contacts[17 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Check new position */
@@ -573,7 +573,7 @@ test_cursor_calculate_descending_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[19 - 1],
                                        e_contact_get_const (fixture->contacts[19 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Rename Müller -> Sade Adu */
@@ -582,7 +582,7 @@ test_cursor_calculate_descending_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[20 - 1],
                                        e_contact_get_const (fixture->contacts[20 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Check new position */
diff --git a/tests/libedata-book/test-book-cache-offline.c b/tests/libedata-book/test-book-cache-offline.c
index b0fdc770b..745aa8e3b 100644
--- a/tests/libedata-book/test-book-cache-offline.c
+++ b/tests/libedata-book/test-book-cache-offline.c
@@ -435,6 +435,7 @@ test_offline_basics (TCUFixture *fixture,
        gint ii;
        const gchar *uid;
        gchar *saved_extra = NULL, *tmp;
+       guint32 custom_flags;
        GSList *uids = NULL;
        GError *error = NULL;
 
@@ -523,6 +524,14 @@ test_offline_basics (TCUFixture *fixture,
                        g_free (saved_extra);
                        saved_extra = NULL;
 
+                       g_assert (e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 123, NULL, 
&error));
+                       g_assert_no_error (error);
+
+                       custom_flags = 0;
+                       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, 
&custom_flags, NULL, &error));
+                       g_assert_no_error (error);
+                       g_assert_cmpint (custom_flags, ==, 123);
+
                        /* Search when locally deleted */
                        test_basic_search (fixture, EXPECT_DEFAULT);
                } else {
@@ -546,7 +555,7 @@ test_offline_basics (TCUFixture *fixture,
        /* Edit in online */
        e_contact_set (contact, E_CONTACT_REV, "rev-1");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_ONLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_ONLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        test_verify_storage (fixture, uid, "rev-1", NULL, E_OFFLINE_STATE_SYNCED);
@@ -554,7 +563,7 @@ test_offline_basics (TCUFixture *fixture,
 
        e_contact_set (contact, E_CONTACT_REV, "rev-2");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, "extra-2", E_CACHE_IS_ONLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, "extra-2", 0, E_CACHE_IS_ONLINE, 
NULL, &error));
        g_assert_no_error (error);
 
        test_verify_storage (fixture, uid, "rev-2", "extra-2", E_OFFLINE_STATE_SYNCED);
@@ -571,11 +580,19 @@ test_offline_basics (TCUFixture *fixture,
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
        g_assert_no_error (error);
 
+       g_assert (e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 234, NULL, &error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 234);
+
        /* Search before delete */
        test_basic_search (fixture, EXPECT_CUSTOM_1);
 
        /* Delete in online */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_ONLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_ONLINE, NULL, &error));
        g_assert_no_error (error);
 
        g_assert (!e_cache_set_offline_state (E_CACHE (fixture->book_cache), uid, 
E_OFFLINE_STATE_LOCALLY_MODIFIED, NULL, &error));
@@ -603,6 +620,14 @@ test_offline_basics (TCUFixture *fixture,
        g_assert_null (uids);
        g_clear_error (&error);
 
+       g_assert (!e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 456, NULL, &error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
+       g_assert (!e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
        g_clear_object (&contact);
 
        /* Search after delete */
@@ -630,7 +655,7 @@ test_offline_add_one (TCUFixture *fixture,
                test_check_offline_state (fixture, uid, E_OFFLINE_STATE_UNKNOWN);
 
                /* Add a contact in offline */
-               g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_OFFLINE, 
NULL, &error));
+               g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, 
E_CACHE_IS_OFFLINE, NULL, &error));
                g_assert_no_error (error);
        } else {
                uid = case_name;
@@ -709,7 +734,7 @@ test_offline_add_edit (TCUFixture *fixture,
        /* Modify added in offline */
        e_contact_set (contact, E_CONTACT_REV, "rev-2");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, 
NULL);
@@ -728,6 +753,7 @@ test_offline_add_delete (TCUFixture *fixture,
                         gconstpointer user_data)
 {
        EContact *contact = NULL;
+       guint32 custom_flags = 0;
        const gchar *uid;
        GError *error = NULL;
 
@@ -752,13 +778,37 @@ test_offline_add_delete (TCUFixture *fixture,
 
        /* Delete added in offline */
 
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 1, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
+       g_assert (!e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
        test_offline_add_one (fixture, "simple-1", 3, EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, NULL);
 
        test_check_offline_changes (fixture, NULL);
 
+       /* Add in online */
+
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 333, E_CACHE_IS_ONLINE, NULL, 
&error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 333);
+
+       /* Delete in offline */
+
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 246, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 246);
+
        g_clear_object (&contact);
 }
 
@@ -790,7 +840,7 @@ test_offline_add_delete_add (TCUFixture *fixture,
        g_assert_nonnull (uid);
 
        /* Delete added in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        test_offline_add_one (fixture, "simple-1", 3, EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, NULL);
@@ -845,6 +895,7 @@ test_offline_edit_common (TCUFixture *fixture,
                          gchar **out_uid)
 {
        EContact *contact = NULL;
+       guint32 custom_flags = 0;
        const gchar *uid;
        GError *error = NULL;
 
@@ -861,11 +912,21 @@ test_offline_edit_common (TCUFixture *fixture,
        test_check_offline_changes (fixture, NULL);
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 0);
+
        /* Modify in offline */
        e_contact_set (contact, E_CONTACT_REV, "rev-2");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 369, E_CACHE_IS_OFFLINE, 
NULL, &error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
        g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 369);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
        g_assert_no_error (error);
@@ -902,7 +963,7 @@ test_offline_edit_delete (TCUFixture *fixture,
        test_offline_edit_common (fixture, &uid);
 
        /* Delete the modified contact in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -968,7 +1029,7 @@ test_offline_delete (TCUFixture *fixture,
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
        /* Delete in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -1007,7 +1068,7 @@ test_offline_delete_add (TCUFixture *fixture,
 
        /* Delete locally created in offline */
        test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, NULL);
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, "simple-1", E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, "simple-1", 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
@@ -1020,7 +1081,7 @@ test_offline_delete_add (TCUFixture *fixture,
        test_check_offline_state (fixture, "simple-1", E_OFFLINE_STATE_UNKNOWN);
 
        /* Delete synced in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -1047,7 +1108,7 @@ test_offline_delete_add (TCUFixture *fixture,
        /* Modify the previous contact and add it again */
        e_contact_set (contact, E_CONTACT_REV, "rev-3");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 4);
@@ -1089,7 +1150,7 @@ test_offline_delete_resync (TCUFixture *fixture,
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
        /* Delete in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
diff --git a/tests/libedata-book/test-book-cache-utils.c b/tests/libedata-book/test-book-cache-utils.c
index 34a92a1d5..b2589bcc0 100644
--- a/tests/libedata-book/test-book-cache-utils.c
+++ b/tests/libedata-book/test-book-cache-utils.c
@@ -91,7 +91,7 @@ tcu_add_contact_from_test_case (TCUFixture *fixture,
 
        contact = tcu_new_contact_from_test_case (case_name);
 
-       if (!e_book_cache_put_contact (fixture->book_cache, contact, case_name, E_CACHE_IS_ONLINE, NULL, 
&error))
+       if (!e_book_cache_put_contact (fixture->book_cache, contact, case_name, 0, E_CACHE_IS_ONLINE, NULL, 
&error))
                g_error ("Failed to add contact: %s", error->message);
 
        if (ret_contact)
@@ -249,7 +249,7 @@ tcu_cursor_fixture_setup (TCUCursorFixture *fixture,
                fixture->contacts[ii] = g_object_ref (contact);
        }
 
-       if (!e_book_cache_put_contacts (base_fixture->book_cache, contacts, extra_list, E_CACHE_IS_ONLINE, 
NULL, &error)) {
+       if (!e_book_cache_put_contacts (base_fixture->book_cache, contacts, extra_list, NULL, 
E_CACHE_IS_ONLINE, NULL, &error)) {
                /* Dont complain here, we re-use the same addressbook for multiple tests
                 * and we can't add the same contacts twice
                 */
diff --git a/tests/libedata-book/test-book-meta-backend.c b/tests/libedata-book/test-book-meta-backend.c
index e938b0d0b..e63ae845a 100644
--- a/tests/libedata-book/test-book-meta-backend.c
+++ b/tests/libedata-book/test-book-meta-backend.c
@@ -360,6 +360,7 @@ e_book_meta_backend_test_save_contact_sync (EBookMetaBackend *meta_backend,
                                            EConflictResolution conflict_resolution,
                                            EContact *contact,
                                            const gchar *extra,
+                                           guint32 opflags,
                                            gchar **out_new_uid,
                                            gchar **out_new_extra,
                                            GCancellable *cancellable,
@@ -382,7 +383,7 @@ e_book_meta_backend_test_save_contact_sync (EBookMetaBackend *meta_backend,
 
        if (g_hash_table_contains (test_backend->contacts, uid)) {
                if (!overwrite_existing) {
-                       g_propagate_error (error, e_data_book_create_error 
(E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS, NULL));
+                       g_propagate_error (error, e_book_client_error_create 
(E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS, NULL));
                        return FALSE;
                }
 
@@ -426,7 +427,7 @@ e_book_meta_backend_test_load_contact_sync (EBookMetaBackend *meta_backend,
                *out_extra = g_strconcat ("extra for ", uid, NULL);
                return TRUE;
        } else {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, 
NULL));
+               g_propagate_error (error, e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, 
NULL));
        }
 
        return FALSE;
@@ -438,6 +439,7 @@ e_book_meta_backend_test_remove_contact_sync (EBookMetaBackend *meta_backend,
                                              const gchar *uid,
                                              const gchar *extra,
                                              const gchar *object,
+                                             guint32 opflags,
                                              GCancellable *cancellable,
                                              GError **error)
 {
@@ -461,7 +463,7 @@ e_book_meta_backend_test_remove_contact_sync (EBookMetaBackend *meta_backend,
                g_assert_cmpstr (expected_extra, ==, extra);
                g_free (expected_extra);
        } else {
-               g_propagate_error (error, e_data_book_create_error (E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, 
NULL));
+               g_propagate_error (error, e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, 
NULL));
        }
 
        return success;
@@ -591,7 +593,7 @@ e_book_meta_backend_test_new (EBookCache *cache)
                gchar *extra;
 
                extra = g_strconcat ("extra for ", e_contact_get_const (contact, E_CONTACT_UID), NULL);
-               success = e_book_cache_put_contact (cache, contact, extra, E_CACHE_IS_ONLINE, NULL, &error);
+               success = e_book_cache_put_contact (cache, contact, extra, 0, E_CACHE_IS_ONLINE, NULL, 
&error);
                g_free (extra);
 
                g_assert_no_error (error);
@@ -633,7 +635,7 @@ e_book_meta_backend_test_change_online (EBookMetaBackend *meta_backend,
 static void
 e_book_meta_backend_test_call_refresh (EBookMetaBackend *meta_backend)
 {
-       EBookBackendClass *backend_class;
+       EBookBackendSyncClass *backend_sync_class;
        EFlag *flag;
        gulong handler_id;
        gboolean success;
@@ -641,9 +643,9 @@ e_book_meta_backend_test_call_refresh (EBookMetaBackend *meta_backend)
 
        g_assert_nonnull (meta_backend);
 
-       backend_class = E_BOOK_BACKEND_GET_CLASS (meta_backend);
-       g_return_if_fail (backend_class != NULL);
-       g_return_if_fail (backend_class->refresh_sync != NULL);
+       backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
+       g_return_if_fail (backend_sync_class != NULL);
+       g_return_if_fail (backend_sync_class->refresh_sync != NULL);
 
        if (!e_backend_get_online (E_BACKEND (meta_backend)))
                return;
@@ -653,7 +655,7 @@ e_book_meta_backend_test_call_refresh (EBookMetaBackend *meta_backend)
        handler_id = g_signal_connect_swapped (meta_backend, "refresh-completed",
                G_CALLBACK (e_flag_set), flag);
 
-       success = backend_class->refresh_sync (E_BOOK_BACKEND (meta_backend), NULL, &error);
+       success = backend_sync_class->refresh_sync (E_BOOK_BACKEND_SYNC (meta_backend), NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
 
@@ -837,19 +839,19 @@ static void
 test_create_contacts (EBookMetaBackend *meta_backend)
 {
        EBookMetaBackendTest *test_backend;
-       EBookBackendClass *backend_class;
+       EBookBackendSyncClass *backend_sync_class;
        EBookCache *book_cache;
        GSList *offline_changes;
        gchar *vcards[2] = { NULL, NULL }, *tmp;
-       GQueue new_contacts = G_QUEUE_INIT;
+       GSList *new_contacts = NULL;
        gboolean success;
        GError *error = NULL;
 
        g_assert_nonnull (meta_backend);
 
-       backend_class = E_BOOK_BACKEND_GET_CLASS (meta_backend);
-       g_return_if_fail (backend_class != NULL);
-       g_return_if_fail (backend_class->create_contacts_sync != NULL);
+       backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
+       g_return_if_fail (backend_sync_class != NULL);
+       g_return_if_fail (backend_sync_class->create_contacts_sync != NULL);
 
        test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
        book_cache = e_book_meta_backend_ref_cache (meta_backend);
@@ -860,11 +862,11 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        /* Try to add existing contact, it should fail */
        vcards[0] = tcu_new_vcard_from_test_case ("custom-1");
 
-       success = backend_class->create_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
-       g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS);
+       success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
+       g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS);
        g_assert (!success);
-       g_assert_cmpint (g_queue_get_length (&new_contacts), ==, 0);
+       g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
        g_clear_error (&error);
        g_free (vcards[0]);
 
@@ -873,19 +875,19 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        /* Try to add new contact */
        vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
 
-       success = backend_class->create_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+       success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&new_contacts), ==, 1);
-       g_assert_cmpstr (e_contact_get_const (g_queue_peek_head (&new_contacts), E_CONTACT_UID), ==, 
"custom-7");
+       g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
+       g_assert_cmpstr (e_contact_get_const (new_contacts->data, E_CONTACT_UID), ==, "custom-7");
        g_assert_cmpint (test_backend->connect_count, ==, 1);
        g_assert_cmpint (test_backend->list_count, ==, 0);
        g_assert_cmpint (test_backend->load_count, ==, 1);
        g_assert_cmpint (test_backend->save_count, ==, 1);
 
-       g_queue_foreach (&new_contacts, (GFunc) g_object_unref, NULL);
-       g_queue_clear (&new_contacts);
+       g_slist_free_full (new_contacts, g_object_unref);
+       new_contacts = NULL;
        g_free (vcards[0]);
 
        ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
@@ -898,11 +900,11 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        /* Try to add existing contact, it should fail */
        vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
 
-       success = backend_class->create_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
-       g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS);
+       success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
+       g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS);
        g_assert (!success);
-       g_assert_cmpint (g_queue_get_length (&new_contacts), ==, 0);
+       g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
        g_clear_error (&error);
        g_free (vcards[0]);
        g_assert_cmpint (test_backend->load_count, ==, 0);
@@ -911,18 +913,18 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        /* Try to add new contact */
        vcards[0] = tcu_new_vcard_from_test_case ("custom-8");
 
-       success = backend_class->create_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+       success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&new_contacts), ==, 1);
-       g_assert_cmpstr (e_contact_get_const (g_queue_peek_head (&new_contacts), E_CONTACT_UID), ==, 
"custom-8");
+       g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
+       g_assert_cmpstr (e_contact_get_const (new_contacts->data, E_CONTACT_UID), ==, "custom-8");
        g_assert_cmpint (test_backend->connect_count, ==, 0);
        g_assert_cmpint (test_backend->load_count, ==, 0);
        g_assert_cmpint (test_backend->save_count, ==, 0);
 
-       g_queue_foreach (&new_contacts, (GFunc) g_object_unref, NULL);
-       g_queue_clear (&new_contacts);
+       g_slist_free_full (new_contacts, g_object_unref);
+       new_contacts = NULL;
        g_free (vcards[0]);
 
        ebmb_test_hash_contains (test_backend->contacts, TRUE, FALSE,
@@ -950,25 +952,25 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        g_assert_nonnull (tmp);
        memcpy (tmp, "X-TEST:*007*", 12);
 
-       success = backend_class->create_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+       success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&new_contacts), ==, 1);
-       g_assert_cmpstr (e_contact_get_const (g_queue_peek_head (&new_contacts), E_CONTACT_UID), !=, 
"custom-9");
+       g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
+       g_assert_cmpstr (e_contact_get_const (new_contacts->data, E_CONTACT_UID), !=, "custom-9");
        g_assert_cmpint (test_backend->connect_count, ==, 1);
        g_assert_cmpint (test_backend->list_count, ==, 1);
        g_assert_cmpint (test_backend->load_count, ==, 2);
        g_assert_cmpint (test_backend->save_count, ==, 2);
 
-       tmp = e_vcard_to_string (E_VCARD (g_queue_peek_head (&new_contacts)), EVC_FORMAT_VCARD_30);
+       tmp = e_vcard_to_string (E_VCARD (new_contacts->data), EVC_FORMAT_VCARD_30);
        g_assert_nonnull (tmp);
        g_assert_nonnull (strstr (tmp, "X-TEST:*007*\r\n"));
-       g_assert_nonnull (strstr (tmp, e_contact_get_const (g_queue_peek_head (&new_contacts), 
E_CONTACT_UID)));
+       g_assert_nonnull (strstr (tmp, e_contact_get_const (new_contacts->data, E_CONTACT_UID)));
        g_free (tmp);
 
-       g_queue_foreach (&new_contacts, (GFunc) g_object_unref, NULL);
-       g_queue_clear (&new_contacts);
+       g_slist_free_full (new_contacts, g_object_unref);
+       new_contacts = NULL;
        g_free (vcards[0]);
 
        ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
@@ -1008,21 +1010,21 @@ static void
 test_modify_contacts (EBookMetaBackend *meta_backend)
 {
        EBookMetaBackendTest *test_backend;
-       EBookBackendClass *backend_class;
+       EBookBackendSyncClass *backend_sync_class;
        EBookCache *book_cache;
        EContact *contact;
        GSList *offline_changes;
        gchar *vcards[2] = { NULL, NULL }, *tmp;
-       GQueue new_contacts = G_QUEUE_INIT;
+       GSList *new_contacts = NULL;
        gint old_rev, new_rev;
        gboolean success;
        GError *error = NULL;
 
        g_assert_nonnull (meta_backend);
 
-       backend_class = E_BOOK_BACKEND_GET_CLASS (meta_backend);
-       g_return_if_fail (backend_class != NULL);
-       g_return_if_fail (backend_class->modify_contacts_sync != NULL);
+       backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
+       g_return_if_fail (backend_sync_class != NULL);
+       g_return_if_fail (backend_sync_class->modify_contacts_sync != NULL);
 
        test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
        book_cache = e_book_meta_backend_ref_cache (meta_backend);
@@ -1035,22 +1037,22 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
        g_assert_nonnull (tmp);
        memcpy (tmp + 4, "unknown", 7);
 
-       success = backend_class->modify_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
-       g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND);
+       success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
+       g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
        g_assert (!success);
-       g_assert_cmpint (g_queue_get_length (&new_contacts), ==, 0);
+       g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
        g_clear_error (&error);
        g_free (vcards[0]);
 
        /* Modify existing contact */
        vcards[0] = ebmb_test_modify_case ("custom-1");
 
-       success = backend_class->modify_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+       success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&new_contacts), ==, 1);
+       g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
        g_assert_cmpint (test_backend->load_count, ==, 1);
        g_assert_cmpint (test_backend->save_count, ==, 1);
 
@@ -1065,7 +1067,7 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
 
        g_object_unref (contact);
 
-       contact = g_queue_peek_head (&new_contacts);
+       contact = new_contacts->data;
        g_assert_nonnull (contact);
        g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_REV));
        g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_FULL_NAME));
@@ -1075,8 +1077,8 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
        g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_FULL_NAME), ==, MODIFIED_FN_STR);
        g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-1");
 
-       g_queue_foreach (&new_contacts, (GFunc) g_object_unref, NULL);
-       g_queue_clear (&new_contacts);
+       g_slist_free_full (new_contacts, g_object_unref);
+       new_contacts = NULL;
        g_free (vcards[0]);
 
        /* Going offline */
@@ -1087,11 +1089,11 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
        /* Modify custom-2 */
        vcards[0] = ebmb_test_modify_case ("custom-2");
 
-       success = backend_class->modify_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+       success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&new_contacts), ==, 1);
+       g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
        g_assert_cmpint (test_backend->load_count, ==, 0);
        g_assert_cmpint (test_backend->save_count, ==, 0);
 
@@ -1106,7 +1108,7 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
 
        g_object_unref (contact);
 
-       contact = g_queue_peek_head (&new_contacts);
+       contact = new_contacts->data;
        g_assert_nonnull (contact);
        g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_REV));
        g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_FULL_NAME));
@@ -1116,8 +1118,8 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
        g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_FULL_NAME), ==, MODIFIED_FN_STR);
        g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-2");
 
-       g_queue_foreach (&new_contacts, (GFunc) g_object_unref, NULL);
-       g_queue_clear (&new_contacts);
+       g_slist_free_full (new_contacts, g_object_unref);
+       new_contacts = NULL;
        g_free (vcards[0]);
 
        /* Going online */
@@ -1139,18 +1141,19 @@ static void
 test_remove_contacts (EBookMetaBackend *meta_backend)
 {
        EBookMetaBackendTest *test_backend;
-       EBookBackendClass *backend_class;
+       EBookBackendSyncClass *backend_sync_class;
        EBookCache *book_cache;
        const gchar *uids[2] = { NULL, NULL };
        GSList *offline_changes;
+       GSList *removed_uids = NULL;
        gboolean success;
        GError *error = NULL;
 
        g_assert_nonnull (meta_backend);
 
-       backend_class = E_BOOK_BACKEND_GET_CLASS (meta_backend);
-       g_return_if_fail (backend_class != NULL);
-       g_return_if_fail (backend_class->remove_contacts_sync != NULL);
+       backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
+       g_return_if_fail (backend_sync_class != NULL);
+       g_return_if_fail (backend_sync_class->remove_contacts_sync != NULL);
 
        test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
        book_cache = e_book_meta_backend_ref_cache (meta_backend);
@@ -1159,22 +1162,27 @@ test_remove_contacts (EBookMetaBackend *meta_backend)
        /* Remove non-existing contact */
        uids[0] = "unknown-contact";
 
-       success = backend_class->remove_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) uids, NULL, &error);
-       g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND);
+       success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
+       g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
        g_assert (!success);
+       g_assert_null (removed_uids);
        g_clear_error (&error);
 
        /* Remove existing contact */
        uids[0] = "custom-1";
 
-       success = backend_class->remove_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) uids, NULL, &error);
+       success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (test_backend->load_count, ==, 0);
        g_assert_cmpint (test_backend->save_count, ==, 0);
        g_assert_cmpint (test_backend->remove_count, ==, 1);
+       g_assert_cmpint (g_slist_length (removed_uids), ==, 1);
+       g_assert_cmpstr (removed_uids->data, ==, uids[0]);
+       g_slist_free_full (removed_uids, g_free);
+       removed_uids = NULL;
 
        ebmb_test_hash_contains (test_backend->contacts, TRUE, FALSE,
                "custom-1", NULL,
@@ -1188,13 +1196,17 @@ test_remove_contacts (EBookMetaBackend *meta_backend)
        /* Remove existing contact */
        uids[0] = "custom-3";
 
-       success = backend_class->remove_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) uids, NULL, &error);
+       success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (test_backend->load_count, ==, 0);
        g_assert_cmpint (test_backend->save_count, ==, 0);
        g_assert_cmpint (test_backend->remove_count, ==, 0);
+       g_assert_cmpint (g_slist_length (removed_uids), ==, 1);
+       g_assert_cmpstr (removed_uids->data, ==, uids[0]);
+       g_slist_free_full (removed_uids, g_free);
+       removed_uids = NULL;
 
        ebmb_test_hash_contains (test_backend->contacts, FALSE, FALSE,
                "custom-3", NULL,
@@ -1230,34 +1242,34 @@ static void
 test_get_contact (EBookMetaBackend *meta_backend)
 {
        EBookMetaBackendTest *test_backend;
-       EBookBackendClass *backend_class;
+       EBookBackendSyncClass *backend_sync_class;
        EBookCache *book_cache;
        EContact *contact;
        GError *error = NULL;
 
        g_assert_nonnull (meta_backend);
 
-       backend_class = E_BOOK_BACKEND_GET_CLASS (meta_backend);
-       g_return_if_fail (backend_class != NULL);
-       g_return_if_fail (backend_class->get_contact_sync != NULL);
+       backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
+       g_return_if_fail (backend_sync_class != NULL);
+       g_return_if_fail (backend_sync_class->get_contact_sync != NULL);
 
        test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
        book_cache = e_book_meta_backend_ref_cache (meta_backend);
        g_assert_nonnull (book_cache);
 
-       e_book_cache_remove_contact (book_cache, "custom-5", E_CACHE_IS_ONLINE, NULL, &error);
+       e_book_cache_remove_contact (book_cache, "custom-5", 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
-       e_book_cache_remove_contact (book_cache, "custom-6", E_CACHE_IS_ONLINE, NULL, &error);
+       e_book_cache_remove_contact (book_cache, "custom-6", 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
 
        /* Non-existing */
-       contact = backend_class->get_contact_sync (E_BOOK_BACKEND (meta_backend), "unknown-contact", NULL, 
&error);
-       g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND);
+       contact = backend_sync_class->get_contact_sync (E_BOOK_BACKEND_SYNC (meta_backend), 
"unknown-contact", NULL, &error);
+       g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
        g_assert_null (contact);
        g_clear_error (&error);
 
        /* Existing */
-       contact = backend_class->get_contact_sync (E_BOOK_BACKEND (meta_backend), "custom-1", NULL, &error);
+       contact = backend_sync_class->get_contact_sync (E_BOOK_BACKEND_SYNC (meta_backend), "custom-1", NULL, 
&error);
        g_assert_no_error (error);
        g_assert_nonnull (contact);
        g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-1");
@@ -1270,8 +1282,8 @@ test_get_contact (EBookMetaBackend *meta_backend)
 
        e_book_meta_backend_test_reset_counters (test_backend);
 
-       contact = backend_class->get_contact_sync (E_BOOK_BACKEND (meta_backend), "custom-5", NULL, &error);
-       g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND);
+       contact = backend_sync_class->get_contact_sync (E_BOOK_BACKEND_SYNC (meta_backend), "custom-5", NULL, 
&error);
+       g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
        g_assert_null (contact);
        g_clear_error (&error);
        g_assert_cmpint (test_backend->connect_count, ==, 0);
@@ -1284,14 +1296,14 @@ test_get_contact (EBookMetaBackend *meta_backend)
        g_assert (e_cache_contains (E_CACHE (book_cache), "custom-5", E_CACHE_EXCLUDE_DELETED));
 
        /* Remove it from the cache, thus it's loaded from the "server" on demand */
-       e_book_cache_remove_contact (book_cache, "custom-5", E_CACHE_IS_ONLINE, NULL, &error);
+       e_book_cache_remove_contact (book_cache, "custom-5", 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
 
        g_assert_cmpint (test_backend->connect_count, ==, 1);
        e_book_meta_backend_test_reset_counters (test_backend);
        g_assert_cmpint (test_backend->connect_count, ==, 0);
 
-       contact = backend_class->get_contact_sync (E_BOOK_BACKEND (meta_backend), "custom-5", NULL, &error);
+       contact = backend_sync_class->get_contact_sync (E_BOOK_BACKEND_SYNC (meta_backend), "custom-5", NULL, 
&error);
        g_assert_no_error (error);
        g_assert_nonnull (contact);
        g_assert_cmpint (test_backend->connect_count, ==, 0);
@@ -1308,63 +1320,61 @@ test_get_contact (EBookMetaBackend *meta_backend)
 static void
 test_get_contact_list (EBookMetaBackend *meta_backend)
 {
-       EBookBackendClass *backend_class;
-       GQueue contacts = G_QUEUE_INIT;
+       EBookBackendSyncClass *backend_sync_class;
+       GSList *contacts = NULL;
        EContact *contact;
        gboolean success;
        GError *error = NULL;
 
        g_assert_nonnull (meta_backend);
 
-       backend_class = E_BOOK_BACKEND_GET_CLASS (meta_backend);
-       g_return_if_fail (backend_class != NULL);
-       g_return_if_fail (backend_class->get_contact_list_sync != NULL);
+       backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
+       g_return_if_fail (backend_sync_class != NULL);
+       g_return_if_fail (backend_sync_class->get_contact_list_sync != NULL);
 
-       success = backend_class->get_contact_list_sync (E_BOOK_BACKEND (meta_backend),
+       success = backend_sync_class->get_contact_list_sync (E_BOOK_BACKEND_SYNC (meta_backend),
                "(is \"uid\" \"unknown-contact\")", &contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&contacts), ==, 0);
+       g_assert_cmpint (g_slist_length (contacts), ==, 0);
 
-       success = backend_class->get_contact_list_sync (E_BOOK_BACKEND (meta_backend),
+       success = backend_sync_class->get_contact_list_sync (E_BOOK_BACKEND_SYNC (meta_backend),
                "(is \"uid\" \"custom-3\")", &contacts, NULL, &error);
        g_assert_no_error (error);
-       g_assert_cmpint (g_queue_get_length (&contacts), ==, 1);
-       contact = g_queue_peek_head (&contacts);
+       g_assert_cmpint (g_slist_length (contacts), ==, 1);
+       contact = contacts->data;
        g_assert_nonnull (contact);
        g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-3");
-       g_queue_foreach (&contacts, (GFunc) g_object_unref, NULL);
-       g_queue_clear (&contacts);
+       g_slist_free_full (contacts, g_object_unref);
 }
 
 static void
 test_get_contact_list_uids (EBookMetaBackend *meta_backend)
 {
-       EBookBackendClass *backend_class;
-       GQueue uids = G_QUEUE_INIT;
+       EBookBackendSyncClass *backend_sync_class;
+       GSList *uids = NULL;
        gboolean success;
        GError *error = NULL;
 
        g_assert_nonnull (meta_backend);
 
-       backend_class = E_BOOK_BACKEND_GET_CLASS (meta_backend);
-       g_return_if_fail (backend_class != NULL);
-       g_return_if_fail (backend_class->get_contact_list_uids_sync != NULL);
+       backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
+       g_return_if_fail (backend_sync_class != NULL);
+       g_return_if_fail (backend_sync_class->get_contact_list_uids_sync != NULL);
 
-       success = backend_class->get_contact_list_uids_sync (E_BOOK_BACKEND (meta_backend),
+       success = backend_sync_class->get_contact_list_uids_sync (E_BOOK_BACKEND_SYNC (meta_backend),
                "(is \"uid\" \"unknown-contact\")", &uids, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&uids), ==, 0);
+       g_assert_cmpint (g_slist_length (uids), ==, 0);
 
-       success = backend_class->get_contact_list_uids_sync (E_BOOK_BACKEND (meta_backend),
+       success = backend_sync_class->get_contact_list_uids_sync (E_BOOK_BACKEND_SYNC (meta_backend),
                "(is \"uid\" \"custom-3\")", &uids, NULL, &error);
        g_assert_no_error (error);
-       g_assert_cmpint (g_queue_get_length (&uids), ==, 1);
-       g_assert_nonnull (g_queue_peek_head (&uids));
-       g_assert_cmpstr (g_queue_peek_head (&uids), ==, "custom-3");
-       g_queue_foreach (&uids, (GFunc) g_free, NULL);
-       g_queue_clear (&uids);
+       g_assert_cmpint (g_slist_length (uids), ==, 1);
+       g_assert_nonnull (uids->data);
+       g_assert_cmpstr (uids->data, ==, "custom-3");
+       g_slist_free_full (uids, g_free);
 }
 
 static void
@@ -1537,10 +1547,12 @@ static void
 test_cursor (EBookMetaBackend *meta_backend)
 {
        EBookBackendClass *backend_class;
+       EBookBackendSyncClass *backend_sync_class;
        EDataBookCursor *cursor;
        EContactField sort_fields[] = { E_CONTACT_FULL_NAME };
        EBookCursorSortType sort_types[] = { E_BOOK_CURSOR_SORT_ASCENDING };
-       GQueue contacts = G_QUEUE_INIT;
+       GSList *contacts = NULL;
+       GSList *removed_uids = NULL;
        gchar *vcards[2] = { NULL, NULL };
        const gchar *uids[2] = { NULL, NULL };
        gint traversed;
@@ -1553,9 +1565,12 @@ test_cursor (EBookMetaBackend *meta_backend)
        g_return_if_fail (backend_class != NULL);
        g_return_if_fail (backend_class->create_cursor != NULL);
        g_return_if_fail (backend_class->delete_cursor != NULL);
-       g_return_if_fail (backend_class->create_contacts_sync != NULL);
-       g_return_if_fail (backend_class->modify_contacts_sync != NULL);
-       g_return_if_fail (backend_class->remove_contacts_sync != NULL);
+
+       backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
+       g_return_if_fail (backend_sync_class != NULL);
+       g_return_if_fail (backend_sync_class->create_contacts_sync != NULL);
+       g_return_if_fail (backend_sync_class->modify_contacts_sync != NULL);
+       g_return_if_fail (backend_sync_class->remove_contacts_sync != NULL);
 
        /* Create the cursor */
        cursor = backend_class->create_cursor (E_BOOK_BACKEND (meta_backend),
@@ -1573,13 +1588,13 @@ test_cursor (EBookMetaBackend *meta_backend)
 
        /* Create */
        vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
-       success = backend_class->create_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &contacts, NULL, &error);
+       success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&contacts), ==, 1);
-       g_queue_foreach (&contacts, (GFunc) g_object_unref, NULL);
-       g_queue_clear (&contacts);
+       g_assert_cmpint (g_slist_length (contacts), ==, 1);
+       g_slist_free_full (contacts, g_object_unref);
+       contacts = NULL;
        g_free (vcards[0]);
 
        g_assert_cmpint (e_data_book_cursor_get_total (cursor), ==, 6);
@@ -1587,13 +1602,13 @@ test_cursor (EBookMetaBackend *meta_backend)
 
        /* Modify */
        vcards[0] = ebmb_test_modify_case ("custom-2");
-       success = backend_class->modify_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) vcards, &contacts, NULL, &error);
+       success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
-       g_assert_cmpint (g_queue_get_length (&contacts), ==, 1);
-       g_queue_foreach (&contacts, (GFunc) g_object_unref, NULL);
-       g_queue_clear (&contacts);
+       g_assert_cmpint (g_slist_length (contacts), ==, 1);
+       g_slist_free_full (contacts, g_object_unref);
+       contacts = NULL;
        g_free (vcards[0]);
 
        g_assert_cmpint (e_data_book_cursor_get_total (cursor), ==, 6);
@@ -1601,10 +1616,14 @@ test_cursor (EBookMetaBackend *meta_backend)
 
        /* Remove */
        uids[0] = "custom-3";
-       success = backend_class->remove_contacts_sync (E_BOOK_BACKEND (meta_backend),
-               (const gchar * const *) uids, NULL, &error);
+       success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
+               (const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
+       g_assert_cmpint (g_slist_length (removed_uids), ==, 1);
+       g_assert_cmpstr (removed_uids->data, ==, uids[0]);
+       g_slist_free_full (removed_uids, g_free);
+       removed_uids = NULL;
 
        g_assert_cmpint (e_data_book_cursor_get_total (cursor), ==, 5);
        g_assert_cmpint (e_data_book_cursor_get_position (cursor), ==, 2);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]