[evolution-data-server/eclient] Implement e_client_get/set_backend_property functions



commit 95f66f28d5141a757dde4306f710deafc6427174
Author: Milan Crha <mcrha redhat com>
Date:   Mon May 9 16:50:15 2011 +0200

    Implement e_client_get/set_backend_property functions

 addressbook/backends/file/e-book-backend-file.c    |  104 ++---
 .../backends/google/e-book-backend-google.c        |  304 ++++++------
 .../backends/groupwise/e-book-backend-groupwise.c  |  152 +++----
 addressbook/backends/ldap/e-book-backend-ldap.c    |  128 +++---
 addressbook/backends/vcf/e-book-backend-vcf.c      |   67 ++--
 .../backends/webdav/e-book-backend-webdav.c        |  104 ++---
 addressbook/libebook/e-book-client.c               |  496 +++++---------------
 addressbook/libebook/e-book-client.h               |   27 +-
 addressbook/libebook/e-book.c                      |   79 +++-
 addressbook/libedata-book/e-book-backend-sync.c    |  319 +++++--------
 addressbook/libedata-book/e-book-backend-sync.h    |   14 +-
 addressbook/libedata-book/e-book-backend.c         |  163 ++++----
 addressbook/libedata-book/e-book-backend.h         |   24 +-
 addressbook/libedata-book/e-data-book.c            |  190 ++++----
 addressbook/libedata-book/e-data-book.h            |   30 +-
 addressbook/libegdbus/e-gdbus-book.c               |  137 +++----
 addressbook/libegdbus/e-gdbus-book.h               |   48 +--
 calendar/backends/caldav/e-cal-backend-caldav.c    |  147 +++---
 .../backends/contacts/e-cal-backend-contacts.c     |   82 ++--
 calendar/backends/file/e-cal-backend-file.c        |  133 +++---
 .../backends/groupwise/e-cal-backend-groupwise.c   |  168 ++++----
 calendar/backends/http/e-cal-backend-http.c        |  103 ++---
 calendar/backends/weather/e-cal-backend-weather.c  |   84 ++--
 calendar/libecal/e-cal-client.c                    |  403 +++++-----------
 calendar/libecal/e-cal-client.h                    |   23 +-
 calendar/libecal/e-cal.c                           |   24 +-
 calendar/libedata-cal/e-cal-backend-sync.c         |  190 ++++----
 calendar/libedata-cal/e-cal-backend-sync.h         |   12 +-
 calendar/libedata-cal/e-cal-backend.c              |  157 ++++---
 calendar/libedata-cal/e-cal-backend.h              |   23 +-
 calendar/libedata-cal/e-data-cal.c                 |  183 ++------
 calendar/libedata-cal/e-data-cal.h                 |   28 +-
 calendar/libegdbus/e-gdbus-cal.c                   |  158 ++-----
 calendar/libegdbus/e-gdbus-cal.h                   |   59 +--
 libedataserver/Makefile.am                         |    1 +
 libedataserver/e-client-private.h                  |  121 +++++
 libedataserver/e-client.c                          |  230 +++++++++-
 libedataserver/e-client.h                          |  145 ++-----
 po/POTFILES.in                                     |    4 +-
 tests/libebook/client/Makefile.am                  |   15 +-
 tests/libebook/client/test-client-examine.c        |  403 ++++++++++++++++
 .../libebook/client/test-client-get-capabilities.c |  230 ---------
 .../client/test-client-get-required-fields.c       |  215 ---------
 .../test-client-get-supported-auth-methods.c       |  215 ---------
 .../client/test-client-get-supported-fields.c      |  215 ---------
 tests/libecal/client/test-client-examine.c         |  234 ++++++----
 46 files changed, 2660 insertions(+), 3731 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 49d32f1..ab12c07 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -749,47 +749,6 @@ e_book_backend_file_authenticate_user (EBookBackendSync *backend,
 	/* Success */
 }
 
-static void
-e_book_backend_file_get_required_fields (EBookBackendSync *backend,
-					  EDataBook *book,
-					  GCancellable *cancellable,
-					  GSList **fields_out,
-					  GError **perror)
-{
-	GSList *fields = NULL;
-
-	fields = g_slist_append (fields , g_strdup (e_contact_field_name (E_CONTACT_FILE_AS)));
-	*fields_out = fields;
-}
-
-static void
-e_book_backend_file_get_supported_auth_methods (EBookBackendSync *backend,
-						EDataBook *book,
-						GCancellable *cancellable,
-						GSList **methods_out,
-						GError **perror)
-{
-	*methods_out = NULL;
-}
-
-static void
-e_book_backend_file_get_supported_fields (EBookBackendSync *backend,
-					  EDataBook *book,
-					  GCancellable *cancellable,
-					  GSList **fields_out,
-					  GError **perror)
-{
-	GSList *fields = NULL;
-	gint i;
-
-	/* XXX we need a way to say "we support everything", since the
-	   file backend does */
-	for (i = 1; i < E_CONTACT_FIELD_LAST; i++)
-		fields = g_slist_append (fields, g_strdup (e_contact_field_name (i)));
-
-	*fields_out = fields;
-}
-
 /*
 ** versions:
 **
@@ -1218,10 +1177,36 @@ e_book_backend_file_remove (EBookBackendSync *backend,
 	   that the addressbook is still valid */
 }
 
-static void
-e_book_backend_file_get_capabilities (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, gchar **capabilities, GError **error)
+static gboolean
+e_book_backend_file_get_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
 {
-	*capabilities = g_strdup ("local,do-initial-query,bulk-removes,contact-lists");
+	gboolean processed = TRUE;
+
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_CAPABILITIES)) {
+		*prop_value = g_strdup ("local,do-initial-query,bulk-removes,contact-lists");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+		*prop_value = g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+		GSList *fields = NULL;
+		gint i;
+
+		/* XXX we need a way to say "we support everything", since the
+		   file backend does */
+		for (i = 1; i < E_CONTACT_FIELD_LAST; i++)
+			fields = g_slist_append (fields, (gpointer) e_contact_field_name (i));
+
+		*prop_value = e_data_book_string_slist_to_comma_string (fields);
+		g_slist_free (fields);
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+		*prop_value = NULL;
+	} else {
+		processed = FALSE;
+	}
+
+	return processed;
 }
 
 static void
@@ -1354,23 +1339,20 @@ e_book_backend_file_class_init (EBookBackendFileClass *klass)
 	backend_class = E_BOOK_BACKEND_CLASS (klass);
 
 	/* Set the virtual methods. */
-	backend_class->start_book_view			= e_book_backend_file_start_book_view;
-	backend_class->stop_book_view			= e_book_backend_file_stop_book_view;
-	backend_class->set_online			= e_book_backend_file_set_online;
-	backend_class->sync				= e_book_backend_file_sync;
-
-	sync_class->open_sync				= e_book_backend_file_open;
-	sync_class->remove_sync				= e_book_backend_file_remove;
-	sync_class->get_capabilities_sync		= e_book_backend_file_get_capabilities;
-	sync_class->create_contact_sync			= e_book_backend_file_create_contact;
-	sync_class->remove_contacts_sync		= e_book_backend_file_remove_contacts;
-	sync_class->modify_contact_sync			= e_book_backend_file_modify_contact;
-	sync_class->get_contact_sync			= e_book_backend_file_get_contact;
-	sync_class->get_contact_list_sync		= e_book_backend_file_get_contact_list;
-	sync_class->authenticate_user_sync		= e_book_backend_file_authenticate_user;
-	sync_class->get_supported_auth_methods_sync	= e_book_backend_file_get_supported_auth_methods;
-	sync_class->get_supported_fields_sync		= e_book_backend_file_get_supported_fields;
-	sync_class->get_required_fields_sync		= e_book_backend_file_get_required_fields;
+	backend_class->start_book_view		= e_book_backend_file_start_book_view;
+	backend_class->stop_book_view		= e_book_backend_file_stop_book_view;
+	backend_class->set_online		= e_book_backend_file_set_online;
+	backend_class->sync			= e_book_backend_file_sync;
+
+	sync_class->open_sync			= e_book_backend_file_open;
+	sync_class->remove_sync			= e_book_backend_file_remove;
+	sync_class->get_backend_property_sync	= e_book_backend_file_get_backend_property;
+	sync_class->create_contact_sync		= e_book_backend_file_create_contact;
+	sync_class->remove_contacts_sync	= e_book_backend_file_remove_contacts;
+	sync_class->modify_contact_sync		= e_book_backend_file_modify_contact;
+	sync_class->get_contact_sync		= e_book_backend_file_get_contact;
+	sync_class->get_contact_list_sync	= e_book_backend_file_get_contact_list;
+	sync_class->authenticate_user_sync	= e_book_backend_file_authenticate_user;
 
 	object_class->dispose = e_book_backend_file_dispose;
 	object_class->finalize = e_book_backend_file_finalize;
diff --git a/addressbook/backends/google/e-book-backend-google.c b/addressbook/backends/google/e-book-backend-google.c
index a06fb22..5976bdf 100644
--- a/addressbook/backends/google/e-book-backend-google.c
+++ b/addressbook/backends/google/e-book-backend-google.c
@@ -1349,146 +1349,6 @@ e_book_backend_google_authenticate_user (EBookBackend *backend, EDataBook *book,
 }
 
 static void
-e_book_backend_google_get_supported_auth_methods (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
-{
-	GSList methods = { (gpointer) "plain/password", NULL, };
-
-	__debug__ (G_STRFUNC);
-	e_data_book_respond_get_supported_auth_methods (book, opid, NULL, &methods);
-}
-
-static void
-e_book_backend_google_get_required_fields (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
-{
-	__debug__ (G_STRFUNC);
-	e_data_book_respond_get_required_fields (book, opid, NULL, NULL);
-}
-
-static void
-e_book_backend_google_get_supported_fields (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
-{
-	GSList *fields = NULL;
-	guint i;
-	const gint supported_fields[] = {
-		E_CONTACT_FULL_NAME,
-		E_CONTACT_EMAIL_1,
-		E_CONTACT_EMAIL_2,
-		E_CONTACT_EMAIL_3,
-		E_CONTACT_EMAIL_4,
-		E_CONTACT_ADDRESS_LABEL_HOME,
-		E_CONTACT_ADDRESS_LABEL_WORK,
-		E_CONTACT_ADDRESS_LABEL_OTHER,
-		E_CONTACT_PHONE_HOME,
-		E_CONTACT_PHONE_HOME_FAX,
-		E_CONTACT_PHONE_BUSINESS,
-		E_CONTACT_PHONE_BUSINESS_FAX,
-		E_CONTACT_PHONE_MOBILE,
-		E_CONTACT_PHONE_PAGER,
-		E_CONTACT_IM_AIM,
-		E_CONTACT_IM_JABBER,
-		E_CONTACT_IM_YAHOO,
-		E_CONTACT_IM_MSN,
-		E_CONTACT_IM_ICQ,
-		E_CONTACT_IM_SKYPE,
-		E_CONTACT_IM_GADUGADU,
-		E_CONTACT_IM_GROUPWISE,
-		E_CONTACT_ADDRESS,
-		E_CONTACT_ADDRESS_HOME,
-		E_CONTACT_ADDRESS_WORK,
-		E_CONTACT_ADDRESS_OTHER,
-		E_CONTACT_NAME,
-		E_CONTACT_GIVEN_NAME,
-		E_CONTACT_FAMILY_NAME,
-		E_CONTACT_PHONE_ASSISTANT,
-		E_CONTACT_PHONE_BUSINESS_2,
-		E_CONTACT_PHONE_CALLBACK,
-		E_CONTACT_PHONE_CAR,
-		E_CONTACT_PHONE_COMPANY,
-		E_CONTACT_PHONE_HOME_2,
-		E_CONTACT_PHONE_ISDN,
-		E_CONTACT_PHONE_OTHER,
-		E_CONTACT_PHONE_OTHER_FAX,
-		E_CONTACT_PHONE_PRIMARY,
-		E_CONTACT_PHONE_RADIO,
-		E_CONTACT_PHONE_TELEX,
-		E_CONTACT_PHONE_TTYTDD,
-		E_CONTACT_IM_AIM_HOME_1,
-		E_CONTACT_IM_AIM_HOME_2,
-		E_CONTACT_IM_AIM_HOME_3,
-		E_CONTACT_IM_AIM_WORK_1,
-		E_CONTACT_IM_AIM_WORK_2,
-		E_CONTACT_IM_AIM_WORK_3,
-		E_CONTACT_IM_GROUPWISE_HOME_1,
-		E_CONTACT_IM_GROUPWISE_HOME_2,
-		E_CONTACT_IM_GROUPWISE_HOME_3,
-		E_CONTACT_IM_GROUPWISE_WORK_1,
-		E_CONTACT_IM_GROUPWISE_WORK_2,
-		E_CONTACT_IM_GROUPWISE_WORK_3,
-		E_CONTACT_IM_JABBER_HOME_1,
-		E_CONTACT_IM_JABBER_HOME_2,
-		E_CONTACT_IM_JABBER_HOME_3,
-		E_CONTACT_IM_JABBER_WORK_1,
-		E_CONTACT_IM_JABBER_WORK_2,
-		E_CONTACT_IM_JABBER_WORK_3,
-		E_CONTACT_IM_YAHOO_HOME_1,
-		E_CONTACT_IM_YAHOO_HOME_2,
-		E_CONTACT_IM_YAHOO_HOME_3,
-		E_CONTACT_IM_YAHOO_WORK_1,
-		E_CONTACT_IM_YAHOO_WORK_2,
-		E_CONTACT_IM_YAHOO_WORK_3,
-		E_CONTACT_IM_MSN_HOME_1,
-		E_CONTACT_IM_MSN_HOME_2,
-		E_CONTACT_IM_MSN_HOME_3,
-		E_CONTACT_IM_MSN_WORK_1,
-		E_CONTACT_IM_MSN_WORK_2,
-		E_CONTACT_IM_MSN_WORK_3,
-		E_CONTACT_IM_ICQ_HOME_1,
-		E_CONTACT_IM_ICQ_HOME_2,
-		E_CONTACT_IM_ICQ_HOME_3,
-		E_CONTACT_IM_ICQ_WORK_1,
-		E_CONTACT_IM_ICQ_WORK_2,
-		E_CONTACT_IM_ICQ_WORK_3,
-		E_CONTACT_EMAIL,
-		E_CONTACT_IM_GADUGADU_HOME_1,
-		E_CONTACT_IM_GADUGADU_HOME_2,
-		E_CONTACT_IM_GADUGADU_HOME_3,
-		E_CONTACT_IM_GADUGADU_WORK_1,
-		E_CONTACT_IM_GADUGADU_WORK_2,
-		E_CONTACT_IM_GADUGADU_WORK_3,
-		E_CONTACT_TEL,
-		E_CONTACT_IM_SKYPE_HOME_1,
-		E_CONTACT_IM_SKYPE_HOME_2,
-		E_CONTACT_IM_SKYPE_HOME_3,
-		E_CONTACT_IM_SKYPE_WORK_1,
-		E_CONTACT_IM_SKYPE_WORK_2,
-		E_CONTACT_IM_SKYPE_WORK_3,
-		E_CONTACT_SIP,
-		E_CONTACT_ORG,
-		E_CONTACT_ORG_UNIT,
-		E_CONTACT_TITLE,
-		E_CONTACT_ROLE,
-		E_CONTACT_HOMEPAGE_URL,
-		E_CONTACT_BLOG_URL,
-		E_CONTACT_BIRTH_DATE,
-		E_CONTACT_ANNIVERSARY,
-		E_CONTACT_NOTE,
-		E_CONTACT_CATEGORIES,
-		E_CONTACT_CATEGORY_LIST
-	};
-
-	__debug__ (G_STRFUNC);
-
-	/* Add all the fields above to the list */
-	for (i = 0; i < G_N_ELEMENTS (supported_fields); i++) {
-		const gchar *field_name = e_contact_field_name (supported_fields[i]);
-		fields = g_slist_prepend (fields, (gpointer) field_name);
-	}
-
-	e_data_book_respond_get_supported_fields (book, opid, NULL, fields);
-	g_slist_free (fields);
-}
-
-static void
 e_book_backend_google_remove (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
 {
 	__debug__ (G_STRFUNC);
@@ -1560,11 +1420,144 @@ e_book_backend_google_open (EBookBackend *backend, EDataBook *book, guint opid,
 }
 
 static void
-e_book_backend_google_get_capabilities (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
+e_book_backend_google_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
 {
 	__debug__ (G_STRFUNC);
 
-	e_data_book_respond_get_capabilities (book, opid, NULL, "net,do-initial-query,contact-lists");
+	g_return_if_fail (prop_name != NULL);
+
+	if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_CAPABILITIES)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, "net,do-initial-query,contact-lists");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, "");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+		GSList *fields = NULL;
+		gchar *fields_str;
+		guint i;
+		const gint supported_fields[] = {
+			E_CONTACT_FULL_NAME,
+			E_CONTACT_EMAIL_1,
+			E_CONTACT_EMAIL_2,
+			E_CONTACT_EMAIL_3,
+			E_CONTACT_EMAIL_4,
+			E_CONTACT_ADDRESS_LABEL_HOME,
+			E_CONTACT_ADDRESS_LABEL_WORK,
+			E_CONTACT_ADDRESS_LABEL_OTHER,
+			E_CONTACT_PHONE_HOME,
+			E_CONTACT_PHONE_HOME_FAX,
+			E_CONTACT_PHONE_BUSINESS,
+			E_CONTACT_PHONE_BUSINESS_FAX,
+			E_CONTACT_PHONE_MOBILE,
+			E_CONTACT_PHONE_PAGER,
+			E_CONTACT_IM_AIM,
+			E_CONTACT_IM_JABBER,
+			E_CONTACT_IM_YAHOO,
+			E_CONTACT_IM_MSN,
+			E_CONTACT_IM_ICQ,
+			E_CONTACT_IM_SKYPE,
+			E_CONTACT_IM_GADUGADU,
+			E_CONTACT_IM_GROUPWISE,
+			E_CONTACT_ADDRESS,
+			E_CONTACT_ADDRESS_HOME,
+			E_CONTACT_ADDRESS_WORK,
+			E_CONTACT_ADDRESS_OTHER,
+			E_CONTACT_NAME,
+			E_CONTACT_GIVEN_NAME,
+			E_CONTACT_FAMILY_NAME,
+			E_CONTACT_PHONE_ASSISTANT,
+			E_CONTACT_PHONE_BUSINESS_2,
+			E_CONTACT_PHONE_CALLBACK,
+			E_CONTACT_PHONE_CAR,
+			E_CONTACT_PHONE_COMPANY,
+			E_CONTACT_PHONE_HOME_2,
+			E_CONTACT_PHONE_ISDN,
+			E_CONTACT_PHONE_OTHER,
+			E_CONTACT_PHONE_OTHER_FAX,
+			E_CONTACT_PHONE_PRIMARY,
+			E_CONTACT_PHONE_RADIO,
+			E_CONTACT_PHONE_TELEX,
+			E_CONTACT_PHONE_TTYTDD,
+			E_CONTACT_IM_AIM_HOME_1,
+			E_CONTACT_IM_AIM_HOME_2,
+			E_CONTACT_IM_AIM_HOME_3,
+			E_CONTACT_IM_AIM_WORK_1,
+			E_CONTACT_IM_AIM_WORK_2,
+			E_CONTACT_IM_AIM_WORK_3,
+			E_CONTACT_IM_GROUPWISE_HOME_1,
+			E_CONTACT_IM_GROUPWISE_HOME_2,
+			E_CONTACT_IM_GROUPWISE_HOME_3,
+			E_CONTACT_IM_GROUPWISE_WORK_1,
+			E_CONTACT_IM_GROUPWISE_WORK_2,
+			E_CONTACT_IM_GROUPWISE_WORK_3,
+			E_CONTACT_IM_JABBER_HOME_1,
+			E_CONTACT_IM_JABBER_HOME_2,
+			E_CONTACT_IM_JABBER_HOME_3,
+			E_CONTACT_IM_JABBER_WORK_1,
+			E_CONTACT_IM_JABBER_WORK_2,
+			E_CONTACT_IM_JABBER_WORK_3,
+			E_CONTACT_IM_YAHOO_HOME_1,
+			E_CONTACT_IM_YAHOO_HOME_2,
+			E_CONTACT_IM_YAHOO_HOME_3,
+			E_CONTACT_IM_YAHOO_WORK_1,
+			E_CONTACT_IM_YAHOO_WORK_2,
+			E_CONTACT_IM_YAHOO_WORK_3,
+			E_CONTACT_IM_MSN_HOME_1,
+			E_CONTACT_IM_MSN_HOME_2,
+			E_CONTACT_IM_MSN_HOME_3,
+			E_CONTACT_IM_MSN_WORK_1,
+			E_CONTACT_IM_MSN_WORK_2,
+			E_CONTACT_IM_MSN_WORK_3,
+			E_CONTACT_IM_ICQ_HOME_1,
+			E_CONTACT_IM_ICQ_HOME_2,
+			E_CONTACT_IM_ICQ_HOME_3,
+			E_CONTACT_IM_ICQ_WORK_1,
+			E_CONTACT_IM_ICQ_WORK_2,
+			E_CONTACT_IM_ICQ_WORK_3,
+			E_CONTACT_EMAIL,
+			E_CONTACT_IM_GADUGADU_HOME_1,
+			E_CONTACT_IM_GADUGADU_HOME_2,
+			E_CONTACT_IM_GADUGADU_HOME_3,
+			E_CONTACT_IM_GADUGADU_WORK_1,
+			E_CONTACT_IM_GADUGADU_WORK_2,
+			E_CONTACT_IM_GADUGADU_WORK_3,
+			E_CONTACT_TEL,
+			E_CONTACT_IM_SKYPE_HOME_1,
+			E_CONTACT_IM_SKYPE_HOME_2,
+			E_CONTACT_IM_SKYPE_HOME_3,
+			E_CONTACT_IM_SKYPE_WORK_1,
+			E_CONTACT_IM_SKYPE_WORK_2,
+			E_CONTACT_IM_SKYPE_WORK_3,
+			E_CONTACT_SIP,
+			E_CONTACT_ORG,
+			E_CONTACT_ORG_UNIT,
+			E_CONTACT_TITLE,
+			E_CONTACT_ROLE,
+			E_CONTACT_HOMEPAGE_URL,
+			E_CONTACT_BLOG_URL,
+			E_CONTACT_BIRTH_DATE,
+			E_CONTACT_ANNIVERSARY,
+			E_CONTACT_NOTE,
+			E_CONTACT_CATEGORIES,
+			E_CONTACT_CATEGORY_LIST
+		};
+
+		/* Add all the fields above to the list */
+		for (i = 0; i < G_N_ELEMENTS (supported_fields); i++) {
+			const gchar *field_name = e_contact_field_name (supported_fields[i]);
+			fields = g_slist_prepend (fields, (gpointer) field_name);
+		}
+
+		fields_str = e_data_book_string_slist_to_comma_string (fields);
+
+		e_data_book_respond_get_backend_property (book, opid, NULL, fields_str);
+
+		g_slist_free (fields);
+		g_free (fields_str);
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, "plain/password");
+	} else {
+		E_BOOK_BACKEND_CLASS (e_book_backend_google_parent_class)->get_backend_property (backend, book, opid, cancellable, prop_name);
+	}
 }
 
 static void
@@ -1676,21 +1669,18 @@ e_book_backend_google_class_init (EBookBackendGoogleClass *klass)
 	g_type_class_add_private (klass, sizeof (EBookBackendGooglePrivate));
 
 	/* Set the virtual methods. */
-	backend_class->open				= e_book_backend_google_open;
-	backend_class->get_capabilities			= e_book_backend_google_get_capabilities;
-	backend_class->start_book_view			= e_book_backend_google_start_book_view;
-	backend_class->stop_book_view			= e_book_backend_google_stop_book_view;
-	backend_class->set_online			= e_book_backend_google_set_online;
-	backend_class->remove				= e_book_backend_google_remove;
-	backend_class->create_contact			= e_book_backend_google_create_contact;
-	backend_class->remove_contacts			= e_book_backend_google_remove_contacts;
-	backend_class->modify_contact			= e_book_backend_google_modify_contact;
-	backend_class->get_contact			= e_book_backend_google_get_contact;
-	backend_class->get_contact_list			= e_book_backend_google_get_contact_list;
-	backend_class->authenticate_user		= e_book_backend_google_authenticate_user;
-	backend_class->get_supported_fields		= e_book_backend_google_get_supported_fields;
-	backend_class->get_required_fields		= e_book_backend_google_get_required_fields;
-	backend_class->get_supported_auth_methods	= e_book_backend_google_get_supported_auth_methods;
+	backend_class->open			= e_book_backend_google_open;
+	backend_class->get_backend_property	= e_book_backend_google_get_backend_property;
+	backend_class->start_book_view		= e_book_backend_google_start_book_view;
+	backend_class->stop_book_view		= e_book_backend_google_stop_book_view;
+	backend_class->set_online		= e_book_backend_google_set_online;
+	backend_class->remove			= e_book_backend_google_remove;
+	backend_class->create_contact		= e_book_backend_google_create_contact;
+	backend_class->remove_contacts		= e_book_backend_google_remove_contacts;
+	backend_class->modify_contact		= e_book_backend_google_modify_contact;
+	backend_class->get_contact		= e_book_backend_google_get_contact;
+	backend_class->get_contact_list		= e_book_backend_google_get_contact_list;
+	backend_class->authenticate_user	= e_book_backend_google_authenticate_user;
 
 	object_class->dispose  = e_book_backend_google_dispose;
 	object_class->finalize = e_book_backend_google_finalize;
diff --git a/addressbook/backends/groupwise/e-book-backend-groupwise.c b/addressbook/backends/groupwise/e-book-backend-groupwise.c
index 9b625b7..536ca32 100644
--- a/addressbook/backends/groupwise/e-book-backend-groupwise.c
+++ b/addressbook/backends/groupwise/e-book-backend-groupwise.c
@@ -3301,55 +3301,6 @@ e_book_backend_groupwise_authenticate_user (EBookBackend *backend,
 }
 
 static void
-e_book_backend_groupwise_get_required_fields (EBookBackend *backend,
-					       EDataBook    *book,
-					       guint32       opid,
-					       GCancellable *cancellable)
-{
-	GSList *fields = NULL;
-
-	if (enable_debug)
-		printf ("\ne_book_backend_groupwise_get_required_fields...\n");
-
-	fields = g_slist_append (fields, (gchar *)e_contact_field_name (E_CONTACT_FILE_AS));
-	e_data_book_respond_get_supported_fields (book, opid,
-						  EDB_ERROR (SUCCESS),
-						  fields);
-	g_slist_free (fields);
-
-}
-
-static void
-e_book_backend_groupwise_get_supported_fields (EBookBackend *backend,
-					       EDataBook    *book,
-					       guint32       opid,
-					       GCancellable *cancellable)
-{
-	GSList *fields = NULL;
-	gint i;
-
-	if (enable_debug)
-		printf ("\ne_book_backend_groupwise_get_supported_fields...\n");
-
-	for (i = 0; i < G_N_ELEMENTS (mappings); i++)
-		fields = g_slist_append (fields, g_strdup (e_contact_field_name (mappings[i].field_id)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_2)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_3)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_ICQ)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_YAHOO)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_GADUGADU)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_MSN)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_SKYPE)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_JABBER)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_IM_GROUPWISE)));
-	fields = g_slist_append (fields, g_strdup (e_contact_field_name (E_CONTACT_ADDRESS_WORK)));
-	e_data_book_respond_get_supported_fields (book, opid,
-						  EDB_ERROR (SUCCESS),
-						  fields);
-	g_slist_free (fields);
-}
-
-static void
 #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
 file_errcall (const DB_ENV *env, const gchar *buf1, const gchar *buf2)
 #else
@@ -3603,34 +3554,52 @@ e_book_backend_groupwise_remove (EBookBackend *backend,
 }
 
 static void
-e_book_backend_groupwise_get_capabilities (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
-{
-	if (enable_debug)
-		printf ("\n%s...\n", G_STRFUNC);
-
-	/* do-initialy-query is enabled for system address book also, so that we get the
-	 * book_view, which is needed for displaying cache update progress.
-	 * and null query is handled for system address book.
-	 */
-	e_data_book_respond_get_capabilities (book, opid, NULL, "net,bulk-removes,do-initial-query,contact-lists");
-}
-
-static void
-e_book_backend_groupwise_get_supported_auth_methods (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
+e_book_backend_groupwise_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
 {
-	GSList *auth_methods = NULL;
-	gchar *auth_method;
-
 	if (enable_debug)
-		printf ("\ne_book_backend_groupwise_get_supported_auth_methods...\n");
-	auth_method =  g_strdup_printf ("plain/password");
-	auth_methods = g_slist_append (auth_methods, auth_method);
-	e_data_book_respond_get_supported_auth_methods (book,
-							opid,
-							EDB_ERROR (SUCCESS),
-							auth_methods);
-	g_free (auth_method);
-	g_slist_free (auth_methods);
+		printf ("\n%s (prop_name: %s)...\n", G_STRFUNC, prop_name ? prop_name : "NULL");
+
+	g_return_if_fail (prop_name != NULL);
+
+	if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_CAPABILITIES)) {
+		/* do-initialy-query is enabled for system address book also, so that we get the
+		 * book_view, which is needed for displaying cache update progress.
+		 * and null query is handled for system address book.
+		 */
+		e_data_book_respond_get_backend_property (book, opid, NULL, "net,bulk-removes,do-initial-query,contact-lists");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, e_contact_field_name (E_CONTACT_FILE_AS));
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+		gchar *fields_str;
+		GSList *fields = NULL;
+		gint i;
+
+		for (i = 0; i < G_N_ELEMENTS (mappings); i++) {
+			fields = g_slist_append (fields, (gpointer) e_contact_field_name (mappings[i].field_id));
+		}
+
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_EMAIL_2));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_EMAIL_3));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_IM_ICQ));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_IM_YAHOO));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_IM_GADUGADU));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_IM_MSN));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_IM_SKYPE));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_IM_JABBER));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_IM_GROUPWISE));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_ADDRESS_WORK));
+
+		fields_str = e_data_book_string_slist_to_comma_string (fields);
+
+		e_data_book_respond_get_backend_property (book, opid, NULL, fields_str);
+
+		g_slist_free (fields);
+		g_free (fields_str);
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, "plain/password");
+	} else {
+		E_BOOK_BACKEND_CLASS (e_book_backend_groupwise_parent_class)->get_backend_property (backend, book, opid, cancellable, prop_name);
+	}
 }
 
 static void
@@ -3781,24 +3750,21 @@ e_book_backend_groupwise_class_init (EBookBackendGroupwiseClass *klass)
 	parent_class = E_BOOK_BACKEND_CLASS (klass);
 
 	/* Set the virtual methods. */
-	parent_class->open				= e_book_backend_groupwise_open;
-	parent_class->get_capabilities			= e_book_backend_groupwise_get_capabilities;
-
-	parent_class->create_contact			= e_book_backend_groupwise_create_contact;
-	parent_class->remove_contacts			= e_book_backend_groupwise_remove_contacts;
-	parent_class->modify_contact			= e_book_backend_groupwise_modify_contact;
-	parent_class->get_contact			= e_book_backend_groupwise_get_contact;
-	parent_class->get_contact_list			= e_book_backend_groupwise_get_contact_list;
-	parent_class->start_book_view			= e_book_backend_groupwise_start_book_view;
-	parent_class->stop_book_view			= e_book_backend_groupwise_stop_book_view;
-	parent_class->authenticate_user			= e_book_backend_groupwise_authenticate_user;
-	parent_class->get_required_fields		= e_book_backend_groupwise_get_required_fields;
-	parent_class->get_supported_fields		= e_book_backend_groupwise_get_supported_fields;
-	parent_class->get_supported_auth_methods	= e_book_backend_groupwise_get_supported_auth_methods;
-	parent_class->remove				= e_book_backend_groupwise_remove;
-	parent_class->set_online			= e_book_backend_groupwise_set_online;
-
-	object_class->dispose				= e_book_backend_groupwise_dispose;
+	parent_class->open			= e_book_backend_groupwise_open;
+	parent_class->get_backend_property	= e_book_backend_groupwise_get_backend_property;
+
+	parent_class->create_contact		= e_book_backend_groupwise_create_contact;
+	parent_class->remove_contacts		= e_book_backend_groupwise_remove_contacts;
+	parent_class->modify_contact		= e_book_backend_groupwise_modify_contact;
+	parent_class->get_contact		= e_book_backend_groupwise_get_contact;
+	parent_class->get_contact_list		= e_book_backend_groupwise_get_contact_list;
+	parent_class->start_book_view		= e_book_backend_groupwise_start_book_view;
+	parent_class->stop_book_view		= e_book_backend_groupwise_stop_book_view;
+	parent_class->authenticate_user		= e_book_backend_groupwise_authenticate_user;
+	parent_class->remove			= e_book_backend_groupwise_remove;
+	parent_class->set_online		= e_book_backend_groupwise_set_online;
+
+	object_class->dispose			= e_book_backend_groupwise_dispose;
 }
 
 static void
diff --git a/addressbook/backends/ldap/e-book-backend-ldap.c b/addressbook/backends/ldap/e-book-backend-ldap.c
index ea384d3..ca29071 100644
--- a/addressbook/backends/ldap/e-book-backend-ldap.c
+++ b/addressbook/backends/ldap/e-book-backend-ldap.c
@@ -4923,55 +4923,6 @@ e_book_backend_ldap_authenticate_user (EBookBackend *backend,
 }
 
 static void
-e_book_backend_ldap_get_required_fields (EBookBackend *backend,
-					  EDataBook    *book,
-					  guint32       opid,
-					  GCancellable *cancellable)
-{
-	GSList *fields = NULL;
-
-	/*FIMEME we should look at mandatory attributs in the schema
-	  and return all those fields here */
-	fields = g_slist_append (fields, (gchar *)e_contact_field_name (E_CONTACT_FILE_AS));
-	fields = g_slist_append (fields, (gchar *)e_contact_field_name (E_CONTACT_FULL_NAME));
-	fields = g_slist_append (fields, (gchar *)e_contact_field_name (E_CONTACT_FAMILY_NAME));
-
-	e_data_book_respond_get_required_fields (book,
-						  opid,
-						  EDB_ERROR (SUCCESS),
-						  fields);
-	g_slist_free (fields);
-}
-
-static void
-e_book_backend_ldap_get_supported_fields (EBookBackend *backend,
-					  EDataBook    *book,
-					  guint32       opid,
-					  GCancellable *cancellable)
-{
-	EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
-
-	e_data_book_respond_get_supported_fields (book,
-						  opid,
-						  EDB_ERROR (SUCCESS),
-						  bl->priv->supported_fields);
-}
-
-static void
-e_book_backend_ldap_get_supported_auth_methods (EBookBackend *backend,
-						EDataBook    *book,
-						guint32       opid,
-						GCancellable *cancellable)
-{
-	EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
-
-	e_data_book_respond_get_supported_auth_methods (book,
-							opid,
-							EDB_ERROR (SUCCESS),
-							bl->priv->supported_auth_methods);
-}
-
-static void
 ldap_cancel_op (gpointer key, gpointer value, gpointer data)
 {
 	EBookBackendLDAP *bl = data;
@@ -5155,12 +5106,52 @@ e_book_backend_ldap_remove (EBookBackend *backend, EDataBook *book, guint32 opid
 }
 
 static void
-e_book_backend_ldap_get_capabilities (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
+e_book_backend_ldap_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
 {
-	if (can_browse (backend) || E_BOOK_BACKEND_LDAP (backend)->priv->marked_for_offline)
-		e_data_book_respond_get_capabilities (book, opid, NULL, "net,anon-access,contact-lists,do-initial-query");
-	else
-		e_data_book_respond_get_capabilities (book, opid, NULL, "net,anon-access,contact-lists");
+	g_return_if_fail (prop_name != NULL);
+
+	if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_CAPABILITIES)) {
+		if (can_browse (backend) || E_BOOK_BACKEND_LDAP (backend)->priv->marked_for_offline)
+			e_data_book_respond_get_backend_property (book, opid, NULL, "net,anon-access,contact-lists,do-initial-query");
+		else
+			e_data_book_respond_get_backend_property (book, opid, NULL, "net,anon-access,contact-lists");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+		gchar *fields_str;
+		GSList *fields = NULL;
+
+		/*FIMEME we should look at mandatory attributs in the schema
+		  and return all those fields here */
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_FILE_AS));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_FULL_NAME));
+		fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_FAMILY_NAME));
+
+		fields_str = e_data_book_string_slist_to_comma_string (fields);
+
+		e_data_book_respond_get_backend_property (book, opid, NULL, fields_str);
+
+		g_slist_free (fields);
+		g_free (fields_str);
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+		EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
+		gchar *str;
+
+		str = e_data_book_string_slist_to_comma_string (bl->priv->supported_fields);
+
+		e_data_book_respond_get_backend_property (book, opid, NULL, str);
+
+		g_free (str);
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+		EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
+		gchar *str;
+
+		str = e_data_book_string_slist_to_comma_string (bl->priv->supported_auth_methods);
+
+		e_data_book_respond_get_backend_property (book, opid, NULL, str);
+
+		g_free (str);
+	} else {
+		E_BOOK_BACKEND_CLASS (e_book_backend_ldap_parent_class)->get_backend_property (backend, book, opid, cancellable, prop_name);
+	}
 }
 
 #if 0
@@ -5363,22 +5354,19 @@ e_book_backend_ldap_class_init (EBookBackendLDAPClass *klass)
 	parent_class = E_BOOK_BACKEND_CLASS (klass);
 
 	/* Set the virtual methods. */
-	parent_class->open				= e_book_backend_ldap_open;
-	parent_class->remove				= e_book_backend_ldap_remove;
-	parent_class->get_capabilities			= e_book_backend_ldap_get_capabilities;
-
-	parent_class->create_contact			= e_book_backend_ldap_create_contact;
-	parent_class->remove_contacts			= e_book_backend_ldap_remove_contacts;
-	parent_class->modify_contact			= e_book_backend_ldap_modify_contact;
-	parent_class->get_contact			= e_book_backend_ldap_get_contact;
-	parent_class->get_contact_list			= e_book_backend_ldap_get_contact_list;
-	parent_class->start_book_view			= e_book_backend_ldap_start_book_view;
-	parent_class->stop_book_view			= e_book_backend_ldap_stop_book_view;
-	parent_class->authenticate_user			= e_book_backend_ldap_authenticate_user;
-	parent_class->get_required_fields		= e_book_backend_ldap_get_required_fields;
-	parent_class->get_supported_fields		= e_book_backend_ldap_get_supported_fields;
-	parent_class->get_supported_auth_methods	= e_book_backend_ldap_get_supported_auth_methods;
-	parent_class->set_online			= e_book_backend_ldap_set_online;
+	parent_class->open			= e_book_backend_ldap_open;
+	parent_class->remove			= e_book_backend_ldap_remove;
+	parent_class->get_backend_property	= e_book_backend_ldap_get_backend_property;
+
+	parent_class->create_contact		= e_book_backend_ldap_create_contact;
+	parent_class->remove_contacts		= e_book_backend_ldap_remove_contacts;
+	parent_class->modify_contact		= e_book_backend_ldap_modify_contact;
+	parent_class->get_contact		= e_book_backend_ldap_get_contact;
+	parent_class->get_contact_list		= e_book_backend_ldap_get_contact_list;
+	parent_class->start_book_view		= e_book_backend_ldap_start_book_view;
+	parent_class->stop_book_view		= e_book_backend_ldap_stop_book_view;
+	parent_class->authenticate_user		= e_book_backend_ldap_authenticate_user;
+	parent_class->set_online		= e_book_backend_ldap_set_online;
 
 	object_class->dispose = e_book_backend_ldap_dispose;
 }
diff --git a/addressbook/backends/vcf/e-book-backend-vcf.c b/addressbook/backends/vcf/e-book-backend-vcf.c
index 861200b..daa64c8 100644
--- a/addressbook/backends/vcf/e-book-backend-vcf.c
+++ b/addressbook/backends/vcf/e-book-backend-vcf.c
@@ -549,37 +549,6 @@ e_book_backend_vcf_authenticate_user (EBookBackendSync *backend,
 	/* Success */
 }
 
-static void
-e_book_backend_vcf_get_required_fields (EBookBackendSync *backend,
-					EDataBook *book,
-					GCancellable *cancellable,
-					GSList **fields_out,
-					GError **perror)
-{
-	GSList *fields = NULL;
-
-	fields = g_slist_append (fields , g_strdup (e_contact_field_name (E_CONTACT_FILE_AS)));
-	*fields_out = fields;
-}
-
-static void
-e_book_backend_vcf_get_supported_fields (EBookBackendSync *backend,
-					 EDataBook *book,
-					 GCancellable *cancellable,
-					 GSList **fields_out,
-					 GError **perror)
-{
-	GSList *fields = NULL;
-	gint i;
-
-	/* XXX we need a way to say "we support everything", since the
-	   vcf backend does */
-	for (i = 0; i < E_CONTACT_FIELD_LAST; i++)
-		fields = g_slist_append (fields, (gchar *)e_contact_field_name (i));
-
-	*fields_out = fields;
-}
-
 #ifdef CREATE_DEFAULT_VCARD
 # include <libedata-book/ximian-vcard.h>
 #endif
@@ -667,10 +636,36 @@ e_book_backend_vcf_open (EBookBackendSync        *backend,
 	g_free (uri);
 }
 
-static void
-e_book_backend_vcf_get_capabilities (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, gchar **capabilities, GError **error)
+static gboolean
+e_book_backend_vcf_get_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
 {
-	*capabilities = g_strdup ("local,do-initial-query,contact-lists");
+	gboolean processed = TRUE;
+
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_CAPABILITIES)) {
+		*prop_value = g_strdup ("local,do-initial-query,contact-lists");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+		*prop_value = g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+		GSList *fields = NULL;
+		gint i;
+
+		/* XXX we need a way to say "we support everything", since the
+		   vcf backend does */
+		for (i = 1; i < E_CONTACT_FIELD_LAST; i++)
+			fields = g_slist_append (fields, (gpointer) e_contact_field_name (i));
+
+		*prop_value = e_data_book_string_slist_to_comma_string (fields);
+		g_slist_free (fields);
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+		*prop_value = NULL;
+	} else {
+		processed = FALSE;
+	}
+
+	return processed;
 }
 
 static void
@@ -741,15 +736,13 @@ e_book_backend_vcf_class_init (EBookBackendVCFClass *klass)
 	backend_class->set_online		= e_book_backend_vcf_set_online;
 
 	sync_class->open_sync			= e_book_backend_vcf_open;
-	sync_class->get_capabilities_sync	= e_book_backend_vcf_get_capabilities;
+	sync_class->get_backend_property_sync	= e_book_backend_vcf_get_backend_property;
 	sync_class->create_contact_sync		= e_book_backend_vcf_create_contact;
 	sync_class->remove_contacts_sync	= e_book_backend_vcf_remove_contacts;
 	sync_class->modify_contact_sync		= e_book_backend_vcf_modify_contact;
 	sync_class->get_contact_sync		= e_book_backend_vcf_get_contact;
 	sync_class->get_contact_list_sync	= e_book_backend_vcf_get_contact_list;
 	sync_class->authenticate_user_sync	= e_book_backend_vcf_authenticate_user;
-	sync_class->get_required_fields_sync	= e_book_backend_vcf_get_required_fields;
-	sync_class->get_supported_fields_sync	= e_book_backend_vcf_get_supported_fields;
 
 	object_class->dispose = e_book_backend_vcf_dispose;
 }
diff --git a/addressbook/backends/webdav/e-book-backend-webdav.c b/addressbook/backends/webdav/e-book-backend-webdav.c
index 02927c8..85827ee 100644
--- a/addressbook/backends/webdav/e-book-backend-webdav.c
+++ b/addressbook/backends/webdav/e-book-backend-webdav.c
@@ -1122,47 +1122,6 @@ e_book_backend_webdav_authenticate_user (EBookBackend *backend, EDataBook *book,
 	}
 }
 
-static void
-e_book_backend_webdav_get_supported_fields (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
-{
-	GSList *fields = NULL;
-	gint    i;
-
-	/* we support everything */
-	for (i = 1; i < E_CONTACT_FIELD_LAST; ++i) {
-		fields = g_slist_append (fields, (gpointer) e_contact_field_name (i));
-	}
-
-	e_data_book_respond_get_supported_fields (book, opid, EDB_ERROR (SUCCESS), fields);
-	g_slist_free (fields);
-}
-
-static void
-e_book_backend_webdav_get_supported_auth_methods (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
-{
-	GSList *auth_methods = NULL;
-
-	auth_methods = g_slist_append (auth_methods, (gpointer) "plain/password");
-
-	e_data_book_respond_get_supported_auth_methods (book, opid, EDB_ERROR (SUCCESS), auth_methods);
-
-	g_slist_free (auth_methods);
-}
-
-static void
-e_book_backend_webdav_get_required_fields (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
-{
-	GSList      *fields = NULL;
-	const gchar *field_name;
-
-	field_name = e_contact_field_name (E_CONTACT_FILE_AS);
-	fields     = g_slist_append (fields , (gpointer) field_name);
-
-	e_data_book_respond_get_supported_fields (book, opid, EDB_ERROR (SUCCESS), fields);
-
-	g_slist_free (fields);
-}
-
 /** authentication callback for libsoup */
 static void soup_authenticate (SoupSession *session, SoupMessage *message,
                               SoupAuth *auth, gboolean retrying, gpointer data)
@@ -1342,9 +1301,35 @@ e_book_backend_webdav_set_online (EBookBackend *backend, gboolean is_online)
 }
 
 static void
-e_book_backend_webdav_get_capabilities (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
+e_book_backend_webdav_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
 {
-	e_data_book_respond_get_capabilities (book, opid, NULL, "net,do-initial-query,contact-lists");
+	g_return_if_fail (prop_name != NULL);
+
+	if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_CAPABILITIES)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, "net,do-initial-query,contact-lists");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, e_contact_field_name (E_CONTACT_FILE_AS));
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+		gchar *fields_str;
+		GSList *fields = NULL;
+		gint    i;
+
+		/* we support everything */
+		for (i = 1; i < E_CONTACT_FIELD_LAST; ++i) {
+			fields = g_slist_append (fields, (gpointer) e_contact_field_name (i));
+		}
+
+		fields_str = e_data_book_string_slist_to_comma_string (fields);
+
+		e_data_book_respond_get_backend_property (book, opid, NULL, fields_str);
+
+		g_slist_free (fields);
+		g_free (fields_str);
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, "plain/password");
+	} else {
+		E_BOOK_BACKEND_CLASS (e_book_backend_webdav_parent_class)->get_backend_property (backend, book, opid, cancellable, prop_name);
+	}
 }
 
 EBookBackend *
@@ -1386,24 +1371,21 @@ e_book_backend_webdav_class_init (EBookBackendWebdavClass *klass)
 	backend_class = E_BOOK_BACKEND_CLASS (klass);
 
 	/* Set the virtual methods. */
-	backend_class->open				= e_book_backend_webdav_open;
-	backend_class->get_capabilities			= e_book_backend_webdav_get_capabilities;
-
-	backend_class->create_contact			= e_book_backend_webdav_create_contact;
-	backend_class->remove_contacts			= e_book_backend_webdav_remove_contacts;
-	backend_class->modify_contact			= e_book_backend_webdav_modify_contact;
-	backend_class->get_contact			= e_book_backend_webdav_get_contact;
-	backend_class->get_contact_list			= e_book_backend_webdav_get_contact_list;
-	backend_class->start_book_view			= e_book_backend_webdav_start_book_view;
-	backend_class->stop_book_view			= e_book_backend_webdav_stop_book_view;
-	backend_class->authenticate_user		= e_book_backend_webdav_authenticate_user;
-	backend_class->get_supported_fields		= e_book_backend_webdav_get_supported_fields;
-	backend_class->get_required_fields		= e_book_backend_webdav_get_required_fields;
-	backend_class->get_supported_auth_methods	= e_book_backend_webdav_get_supported_auth_methods;
-	backend_class->remove				= e_book_backend_webdav_remove;
-	backend_class->set_online			= e_book_backend_webdav_set_online;
-
-	object_class->dispose                     = e_book_backend_webdav_dispose;
+	backend_class->open			= e_book_backend_webdav_open;
+	backend_class->get_backend_property	= e_book_backend_webdav_get_backend_property;
+
+	backend_class->create_contact		= e_book_backend_webdav_create_contact;
+	backend_class->remove_contacts		= e_book_backend_webdav_remove_contacts;
+	backend_class->modify_contact		= e_book_backend_webdav_modify_contact;
+	backend_class->get_contact		= e_book_backend_webdav_get_contact;
+	backend_class->get_contact_list		= e_book_backend_webdav_get_contact_list;
+	backend_class->start_book_view		= e_book_backend_webdav_start_book_view;
+	backend_class->stop_book_view		= e_book_backend_webdav_stop_book_view;
+	backend_class->authenticate_user	= e_book_backend_webdav_authenticate_user;
+	backend_class->remove			= e_book_backend_webdav_remove;
+	backend_class->set_online		= e_book_backend_webdav_set_online;
+
+	object_class->dispose			= e_book_backend_webdav_dispose;
 
 	g_type_class_add_private (object_class, sizeof (EBookBackendWebdavPrivate));
 }
diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
index d479427..ce30a87 100644
--- a/addressbook/libebook/e-book-client.c
+++ b/addressbook/libebook/e-book-client.c
@@ -28,6 +28,7 @@
 #include <gio/gio.h>
 
 #include "libedataserver/e-data-server-util.h"
+#include "libedataserver/e-client-private.h"
 
 #include "e-book-client.h"
 #include "e-contact.h"
@@ -47,6 +48,34 @@ struct _EBookClientPrivate
 
 G_DEFINE_TYPE (EBookClient, e_book_client, E_TYPE_CLIENT)
 
+/**
+ * Well-known book backend properties:
+ * @BOOK_BACKEND_PROPERTY_LOADED: Is set to "TRUE" or "FALSE" depending
+ *   on the backend's loaded state.
+ * @BOOK_BACKEND_PROPERTY_ONLINE: Is set to "TRUE" or "FALSE" depending
+ *   on the backend's loaded state. See also e_client_is_online().
+ * @BOOK_BACKEND_PROPERTY_READONLY: Is set to "TRUE" or "FALSE" depending
+ *   on the backend's readonly state. See also e_client_is_readonly().
+ * @BOOK_BACKEND_PROPERTY_CACHE_DIR: Local folder with cached data used
+ *   by the backend.
+ * @BOOK_BACKEND_PROPERTY_CAPABILITIES: Retrieves comma-separated list
+ *   of	capabilities supported by the backend. Preferred method of retreiving
+ *   and working with capabilities is e_client_get_capabilities() and
+ *   e_client_check_capability().
+ * @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
+ *   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.
+ * @BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS: Retrieves comma-separated list
+ *   of supported authentication methods by the backend.
+ *   Use e_client_util_parse_comma_strings() to parse returned string value
+ *   into a #GSList.
+ **/
+
 GQuark
 e_book_client_error_quark (void)
 {
@@ -900,21 +929,21 @@ e_book_client_is_self (EContact *contact)
 }
 
 static void
-book_client_open (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+book_client_get_backend_property (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_client_proxy_call_boolean (client, only_if_exists, cancellable, callback, user_data, book_client_open,
-			e_gdbus_book_call_open,
-			e_gdbus_book_call_open_finish, NULL, NULL, NULL, NULL);
+	e_client_proxy_call_string (client, prop_name, cancellable, callback, user_data, book_client_get_backend_property,
+			e_gdbus_book_call_get_backend_property,
+			NULL, NULL, e_gdbus_book_call_get_backend_property_finish, NULL, NULL);
 }
 
 static gboolean
-book_client_open_finish (EClient *client, GAsyncResult *result, GError **error)
+book_client_get_backend_property_finish (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error)
 {
-	return e_client_proxy_call_finish_void (client, result, error, book_client_open);
+	return e_client_proxy_call_finish_string (client, result, prop_value, error, book_client_get_backend_property);
 }
 
 static gboolean
-book_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error)
+book_client_get_backend_property_sync (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error)
 {
 	EBookClient *book_client;
 
@@ -930,27 +959,35 @@ book_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *c
 		return FALSE;
 	}
 
-	return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_book_call_open_sync);
+	return e_client_proxy_call_sync_string__string (client, prop_name, prop_value, cancellable, error, e_gdbus_book_call_get_backend_property_sync);
 }
 
 static void
-book_client_remove (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+book_client_set_backend_property (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_client_proxy_call_void (client, cancellable, callback, user_data, book_client_remove,
-			e_gdbus_book_call_remove,
-			e_gdbus_book_call_remove_finish, NULL, NULL, NULL, NULL);
+	gchar **prop_name_value;
+
+	prop_name_value = e_gdbus_book_encode_set_backend_property (prop_name, prop_value);
+
+	e_client_proxy_call_strv (client, (const gchar * const *) prop_name_value, cancellable, callback, user_data, book_client_set_backend_property,
+			e_gdbus_book_call_set_backend_property,
+			e_gdbus_book_call_set_backend_property_finish, NULL, NULL, NULL, NULL);
+
+	g_strfreev (prop_name_value);
 }
 
 static gboolean
-book_client_remove_finish (EClient *client, GAsyncResult *result, GError **error)
+book_client_set_backend_property_finish (EClient *client, GAsyncResult *result, GError **error)
 {
-	return e_client_proxy_call_finish_void (client, result, error, book_client_remove);
+	return e_client_proxy_call_finish_void (client, result, error, book_client_set_backend_property);
 }
 
 static gboolean
-book_client_remove_sync (EClient *client, GCancellable *cancellable, GError **error)
+book_client_set_backend_property_sync (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error)
 {
 	EBookClient *book_client;
+	gboolean res;
+	gchar **prop_name_value;
 
 	g_return_val_if_fail (client != NULL, FALSE);
 	g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
@@ -964,409 +1001,82 @@ book_client_remove_sync (EClient *client, GCancellable *cancellable, GError **er
 		return FALSE;
 	}
 
-	return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_book_call_remove_sync);
-}
-
-
-/**
- * e_book_client_get_capabilities:
- * @client: an #EBookClient
- * @cancellable: a #GCancellable; can be %NULL
- * @callback: callback to call when a result is ready
- * @user_data: user data for the @callback
- *
- * Starts retrieval of the list of capabilities which the backend for this address book
- * supports. The call is finished by e_book_client_get_capabilities_finish() from
- * the @callback.
- *
- * Note: Usually is sufficient to use e_client_get_capabilities() or e_client_check_capability(),
- * which caches capabilities of a backend on the client side.
- *
- * Since: 3.2
- **/
-void
-e_book_client_get_capabilities (EBookClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
-{
-	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data, e_book_client_get_capabilities,
-			e_gdbus_book_call_get_capabilities,
-			NULL, NULL, e_gdbus_book_call_get_capabilities_finish, NULL, NULL);
-}
-
-/**
- * e_book_client_get_capabilities_finish:
- * @client: an #EBookClient
- * @result: a #GAsyncResult
- * @capabilities: (out): list of strings with capabilities
- * @error: (out): a #GError to set an error, if any
- *
- * Finishes previous call of e_book_client_get_capabilities() and
- * sets @capabilities to a list of strings of backend capabilities.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_book_client_get_capabilities_finish (EBookClient *client, GAsyncResult *result, GSList **capabilities, GError **error)
-{
-	gboolean res;
-	gchar *out_string = NULL;
-
-	g_return_val_if_fail (capabilities != NULL, FALSE);
-
-	res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_book_client_get_capabilities);
-
-	if (res && out_string)
-		*capabilities = e_client_util_parse_capabilities (out_string);
-	else
-		*capabilities = NULL;
-
-	g_free (out_string);
-
-	return res;
-}
-
-/**
- * e_book_client_get_capabilities_sync:
- * @client: an #EBookClient
- * @capabilities: (out): list of strings with capabilities
- * @cancellable: a #GCancellable; can be %NULL
- * @error: (out): a #GError to set an error, if any
- *
- * Retrieves a list of capabilities which the backend for this address book
- * supports and sets @capabilities to that list.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Note: Usually is sufficient to use e_client_get_capabilities() or e_client_check_capability(),
- * which caches capabilities of a backend on the client side.
- *
- * Since: 3.2
- **/
-gboolean
-e_book_client_get_capabilities_sync (EBookClient *client, GSList **capabilities, GCancellable *cancellable, GError **error)
-{
-	gboolean res;
-	gchar *out_string = NULL;
-
-	g_return_val_if_fail (client != NULL, FALSE);
-	g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
-	g_return_val_if_fail (client->priv != NULL, FALSE);
-	g_return_val_if_fail (capabilities != NULL, FALSE);
-
-	if (!client->priv->gdbus_book) {
-		set_proxy_gone_error (error);
-		return FALSE;
-	}
-
-	res = e_client_proxy_call_sync_void__string (E_CLIENT (client), &out_string, cancellable, error, e_gdbus_book_call_get_capabilities_sync);
-
-	if (res && out_string)
-		*capabilities = e_client_util_parse_capabilities (out_string);
-	else
-		*capabilities = NULL;
-
-	g_free (out_string);
+	prop_name_value = e_gdbus_book_encode_set_backend_property (prop_name, prop_value);
+	res = e_client_proxy_call_sync_strv__void (client, (const gchar * const *) prop_name_value, cancellable, error, e_gdbus_book_call_set_backend_property_sync);
+	g_strfreev (prop_name_value);
 
 	return res;
 }
 
-/**
- * e_book_client_get_required_fields:
- * @client: an #EBookClient
- * @cancellable: a #GCancellable; can be %NULL
- * @callback: callback to call when a result is ready
- * @user_data: user data for the @callback
- *
- * Gets a list of fields that are required to be filled in for
- * all contacts in this @client. The call is finished by
- * e_book_client_get_required_fields_finish() from the @callback.
- *
- * Since: 3.2
- **/
-void
-e_book_client_get_required_fields (EBookClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+static void
+book_client_open (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data, e_book_client_get_required_fields,
-			e_gdbus_book_call_get_required_fields,
-			NULL, NULL, NULL, e_gdbus_book_call_get_required_fields_finish, NULL);
+	e_client_proxy_call_boolean (client, only_if_exists, cancellable, callback, user_data, book_client_open,
+			e_gdbus_book_call_open,
+			e_gdbus_book_call_open_finish, NULL, NULL, NULL, NULL);
 }
 
-/**
- * e_book_client_get_required_fields_finish:
- * @client: an #EBookClient
- * @result: a #GAsyncResult
- * @fields: (out): list of strings with required fields
- * @error: (out): a #GError to set an error, if any
- *
- * Finishes previous call of e_book_client_get_required_fields() and
- * sets @fields to a list of strings of required fields by a backend.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_book_client_get_required_fields_finish (EBookClient *client, GAsyncResult *result, GSList **fields, GError **error)
+static gboolean
+book_client_open_finish (EClient *client, GAsyncResult *result, GError **error)
 {
-	gboolean res;
-	gchar **out_strv = NULL;
-
-	g_return_val_if_fail (fields != NULL, FALSE);
-
-	res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_strv, error, e_book_client_get_required_fields);
-
-	if (res && out_strv)
-		*fields = e_client_util_strv_to_slist ((const gchar * const *) out_strv);
-	else
-		*fields = NULL;
-
-	g_strfreev (out_strv);
-
-	return res;
+	return e_client_proxy_call_finish_void (client, result, error, book_client_open);
 }
 
-/**
- * e_book_client_get_required_fields_sync:
- * @client: an #EBookClient
- * @fields: (out): list of strings with required fields
- * @cancellable: a #GCancellable; can be %NULL
- * @error: (out): a #GError to set an error, if any
- *
- * Gets a list of fields that are required to be filled in for
- * all contacts in this @client. Sets @fields to a list of strings
- * of required fields by a backend.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_book_client_get_required_fields_sync (EBookClient *client, GSList **fields, GCancellable *cancellable, GError **error)
+static gboolean
+book_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error)
 {
-	gboolean res;
-	gchar **out_strv = NULL;
+	EBookClient *book_client;
 
 	g_return_val_if_fail (client != NULL, FALSE);
 	g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
-	g_return_val_if_fail (client->priv != NULL, FALSE);
-	g_return_val_if_fail (fields != NULL, FALSE);
 
-	if (!client->priv->gdbus_book) {
-		set_proxy_gone_error (error);
-		return FALSE;
-	}
-
-	res = e_client_proxy_call_sync_void__strv (E_CLIENT (client), &out_strv, cancellable, error, e_gdbus_book_call_get_required_fields_sync);
-
-	if (res && out_strv)
-		*fields = e_client_util_strv_to_slist ((const gchar * const *) out_strv);
-	else
-		*fields = NULL;
-
-	g_strfreev (out_strv);
-
-	return res;
-}
-
-/**
- * e_book_client_get_supported_fields:
- * @client: an #EBookClient
- * @cancellable: a #GCancellable; can be %NULL
- * @callback: callback to call when a result is ready
- * @user_data: user data for the @callback
- *
- * Gets a list of fields that can be stored for contacts
- * in this @client. Other fields may be discarded. The call is finished by
- * e_book_client_get_supported_fields_finish() from the @callback.
- *
- * Since: 3.2
- **/
-void
-e_book_client_get_supported_fields (EBookClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
-{
-	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data, e_book_client_get_supported_fields,
-			e_gdbus_book_call_get_supported_fields,
-			NULL, NULL, NULL, e_gdbus_book_call_get_supported_fields_finish, NULL);
-}
-
-/**
- * e_book_client_get_supported_fields_finish:
- * @client: an #EBookClient
- * @result: a #GAsyncResult
- * @fields: (out): list of strings with supported fields
- * @error: (out): a #GError to set an error, if any
- *
- * Finishes previous call of e_book_client_get_supported_fields() and
- * sets @fields to a list of strings of supported fields by a backend.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_book_client_get_supported_fields_finish (EBookClient *client, GAsyncResult *result, GSList **fields, GError **error)
-{
-	gboolean res;
-	gchar **out_strv = NULL;
-
-	g_return_val_if_fail (fields != NULL, FALSE);
-
-	res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_strv, error, e_book_client_get_supported_fields);
-
-	if (res && out_strv)
-		*fields = e_client_util_strv_to_slist ((const gchar * const *) out_strv);
-	else
-		*fields = NULL;
-
-	g_strfreev (out_strv);
-
-	return res;
-}
-
-/**
- * e_book_client_get_supported_fields_sync:
- * @client: an #EBookClient
- * @fields: (out): list of strings with supported fields
- * @cancellable: a #GCancellable; can be %NULL
- * @error: (out): a #GError to set an error, if any
- *
- * Gets a list of fields that can be stored for contacts
- * in this @client. Other fields may be discarded. Sets @fields
- * to a list of strings of required fields by a backend.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_book_client_get_supported_fields_sync (EBookClient *client, GSList **fields, GCancellable *cancellable, GError **error)
-{
-	gboolean res;
-	gchar **out_strv = NULL;
-
-	g_return_val_if_fail (client != NULL, FALSE);
-	g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
-	g_return_val_if_fail (client->priv != NULL, FALSE);
+	book_client = E_BOOK_CLIENT (client);
+	g_return_val_if_fail (book_client != NULL, FALSE);
+	g_return_val_if_fail (book_client->priv != NULL, FALSE);
 
-	if (!client->priv->gdbus_book) {
+	if (!book_client->priv->gdbus_book) {
 		set_proxy_gone_error (error);
 		return FALSE;
 	}
 
-	res = e_client_proxy_call_sync_void__strv (E_CLIENT (client), &out_strv, cancellable, error, e_gdbus_book_call_get_supported_fields_sync);
-
-	if (res && out_strv)
-		*fields = e_client_util_strv_to_slist ((const gchar * const *) out_strv);
-	else
-		*fields = NULL;
-
-	g_strfreev (out_strv);
-
-	return res;
+	return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_book_call_open_sync);
 }
 
-/**
- * e_book_client_get_supported_auth_methods:
- * @client: an #EBookClient
- * @cancellable: a #GCancellable; can be %NULL
- * @callback: callback to call when a result is ready
- * @user_data: user data for the @callback
- *
- * Queries @client for the list of authentication methods it supports.
- * The call is finished by e_book_client_get_supported_auth_methods_finish()
- * from the @callback.
- *
- * Since: 3.2
- **/
-void
-e_book_client_get_supported_auth_methods (EBookClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+static void
+book_client_remove (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data, e_book_client_get_supported_auth_methods,
-			e_gdbus_book_call_get_supported_auth_methods,
-			NULL, NULL, NULL, e_gdbus_book_call_get_supported_auth_methods_finish, NULL);
+	e_client_proxy_call_void (client, cancellable, callback, user_data, book_client_remove,
+			e_gdbus_book_call_remove,
+			e_gdbus_book_call_remove_finish, NULL, NULL, NULL, NULL);
 }
 
-/**
- * e_book_client_get_supported_auth_methods_finish:
- * @client: an #EBookClient
- * @result: a #GAsyncResult
- * @auth_methods: (out): list of strings with supported authentication methods
- * @error: (out): a #GError to set an error, if any
- *
- * Finishes previous call of e_book_client_get_supported_auth_methods() and
- * sets @auth_methods to a list of strings of supported authentication methods by a backend.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_book_client_get_supported_auth_methods_finish	(EBookClient *client, GAsyncResult *result, GSList **auth_methods, GError **error)
+static gboolean
+book_client_remove_finish (EClient *client, GAsyncResult *result, GError **error)
 {
-	gboolean res;
-	gchar **out_strv = NULL;
-
-	res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_strv, error, e_book_client_get_supported_auth_methods);
-
-	if (res && out_strv)
-		*auth_methods = e_client_util_strv_to_slist ((const gchar * const *) out_strv);
-	else
-		*auth_methods = NULL;
-
-	g_strfreev (out_strv);
-
-	return res;
+	return e_client_proxy_call_finish_void (client, result, error, book_client_remove);
 }
 
-/**
- * e_book_client_get_supported_auth_methods_sync:
- * @client: an #EBookClient
- * @auth_methods: (out): list of strings with supported authentication methods
- * @cancellable: a #GCancellable; can be %NULL
- * @error: (out): a #GError to set an error, if any
- *
- * Queries @client for the list of authentication methods it supports.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_book_client_get_supported_auth_methods_sync (EBookClient *client, GSList **auth_methods, GCancellable *cancellable, GError **error)
+static gboolean
+book_client_remove_sync (EClient *client, GCancellable *cancellable, GError **error)
 {
-	gboolean res;
-	gchar **out_strv = NULL;
+	EBookClient *book_client;
 
 	g_return_val_if_fail (client != NULL, FALSE);
 	g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
-	g_return_val_if_fail (client->priv != NULL, FALSE);
 
-	if (!client->priv->gdbus_book) {
+	book_client = E_BOOK_CLIENT (client);
+	g_return_val_if_fail (book_client != NULL, FALSE);
+	g_return_val_if_fail (book_client->priv != NULL, FALSE);
+
+	if (!book_client->priv->gdbus_book) {
 		set_proxy_gone_error (error);
 		return FALSE;
 	}
 
-	res = e_client_proxy_call_sync_void__strv (E_CLIENT (client), &out_strv, cancellable, error, e_gdbus_book_call_get_supported_auth_methods_sync);
-
-	if (res && out_strv)
-		*auth_methods = e_client_util_strv_to_slist ((const gchar * const *) out_strv);
-	else
-		*auth_methods = NULL;
-
-	g_strfreev (out_strv);
-
-	return res;
+	return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_book_call_remove_sync);
 }
 
+
 /**
  * e_book_client_add_contact:
  * @client: an #EBookClient
@@ -2317,7 +2027,7 @@ book_client_retrieve_capabilities (EClient *client)
 	if (!book_client->priv->gdbus_book)
 		return NULL;
 
-	e_gdbus_book_call_get_capabilities_sync (book_client->priv->gdbus_book, &capabilities, NULL, &error);
+	e_gdbus_book_call_get_backend_property_sync (book_client->priv->gdbus_book, BOOK_BACKEND_PROPERTY_CAPABILITIES, &capabilities, NULL, &error);
 
 	if (error) {
 		g_debug ("%s: Failed to retrieve capabilitites: %s", G_STRFUNC, error->message);
@@ -2386,14 +2096,20 @@ e_book_client_class_init (EBookClientClass *klass)
 	object_class->finalize = book_client_finalize;
 
 	client_class = E_CLIENT_CLASS (klass);
-	client_class->get_dbus_proxy = book_client_get_dbus_proxy;
-	client_class->unwrap_dbus_error = book_client_unwrap_dbus_error;
-	client_class->handle_authentication = book_client_handle_authentication;
-	client_class->retrieve_capabilities = book_client_retrieve_capabilities;
-	client_class->open = book_client_open;
-	client_class->open_finish = book_client_open_finish;
-	client_class->open_sync = book_client_open_sync;
-	client_class->remove = book_client_remove;
-	client_class->remove_finish = book_client_remove_finish;
-	client_class->remove_sync = book_client_remove_sync;
+	client_class->get_dbus_proxy			= book_client_get_dbus_proxy;
+	client_class->unwrap_dbus_error			= book_client_unwrap_dbus_error;
+	client_class->handle_authentication		= book_client_handle_authentication;
+	client_class->retrieve_capabilities		= book_client_retrieve_capabilities;
+	client_class->get_backend_property		= book_client_get_backend_property;
+	client_class->get_backend_property_finish	= book_client_get_backend_property_finish;
+	client_class->get_backend_property_sync		= book_client_get_backend_property_sync;
+	client_class->set_backend_property		= book_client_set_backend_property;
+	client_class->set_backend_property_finish	= book_client_set_backend_property_finish;
+	client_class->set_backend_property_sync		= book_client_set_backend_property_sync;
+	client_class->open				= book_client_open;
+	client_class->open_finish			= book_client_open_finish;
+	client_class->open_sync				= book_client_open_sync;
+	client_class->remove				= book_client_remove;
+	client_class->remove_finish			= book_client_remove_finish;
+	client_class->remove_sync			= book_client_remove_sync;
 }
diff --git a/addressbook/libebook/e-book-client.h b/addressbook/libebook/e-book-client.h
index c8d8d18..a800f36 100644
--- a/addressbook/libebook/e-book-client.h
+++ b/addressbook/libebook/e-book-client.h
@@ -29,6 +29,8 @@
 #include <libedataserver/e-source-list.h>
 #include <libebook/e-book-view.h>
 
+G_BEGIN_DECLS
+
 #define E_TYPE_BOOK_CLIENT		(e_book_client_get_type ())
 #define E_BOOK_CLIENT(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_BOOK_CLIENT, EBookClient))
 #define E_BOOK_CLIENT_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_BOOK_CLIENT, EBookClientClass))
@@ -36,7 +38,14 @@
 #define E_IS_BOOK_CLIENT_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_BOOK_CLIENT))
 #define E_BOOK_CLIENT_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_BOOK_CLIENT, EBookClientClass))
 
-G_BEGIN_DECLS
+#define BOOK_BACKEND_PROPERTY_LOADED			"loaded"
+#define BOOK_BACKEND_PROPERTY_ONLINE			"online"
+#define BOOK_BACKEND_PROPERTY_READONLY			"readonly"
+#define BOOK_BACKEND_PROPERTY_CACHE_DIR			"cache-dir"
+#define BOOK_BACKEND_PROPERTY_CAPABILITIES		"capabilities"
+#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS		"required-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS		"supported-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS	"supported-auth-methods"
 
 #define E_BOOK_CLIENT_ERROR e_book_client_error_quark ()
 
@@ -89,22 +98,6 @@ gboolean	e_book_client_set_self				(EBookClient *client, EContact *contact, GErr
 gboolean	e_book_client_is_self				(EContact *contact);
 
 /* Addressbook methods */
-void		e_book_client_get_capabilities			(EBookClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_book_client_get_capabilities_finish		(EBookClient *client, GAsyncResult *result, GSList **capabilities, GError **error);
-gboolean	e_book_client_get_capabilities_sync		(EBookClient *client, GSList **capabilities, GCancellable *cancellable, GError **error);
-
-void		e_book_client_get_required_fields		(EBookClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_book_client_get_required_fields_finish	(EBookClient *client, GAsyncResult *result, GSList **fields, GError **error);
-gboolean	e_book_client_get_required_fields_sync		(EBookClient *client, GSList **fields, GCancellable *cancellable, GError **error);
-
-void		e_book_client_get_supported_fields		(EBookClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_book_client_get_supported_fields_finish	(EBookClient *client, GAsyncResult *result, GSList **fields, GError **error);
-gboolean	e_book_client_get_supported_fields_sync		(EBookClient *client, GSList **fields, GCancellable *cancellable, GError **error);
-
-void		e_book_client_get_supported_auth_methods	(EBookClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_book_client_get_supported_auth_methods_finish	(EBookClient *client, GAsyncResult *result, GSList **auth_methods, GError **error);
-gboolean	e_book_client_get_supported_auth_methods_sync	(EBookClient *client, GSList **auth_methods, GCancellable *cancellable, GError **error);
-
 void		e_book_client_add_contact			(EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
 gboolean	e_book_client_add_contact_finish		(EBookClient *client, GAsyncResult *result, gchar **added_uid, GError **error);
 gboolean	e_book_client_add_contact_sync			(EBookClient *client, /* const */ EContact *contact, gchar **added_uid, GCancellable *cancellable, GError **error);
diff --git a/addressbook/libebook/e-book.c b/addressbook/libebook/e-book.c
index 26b6b5e..2d14d30 100644
--- a/addressbook/libebook/e-book.c
+++ b/addressbook/libebook/e-book.c
@@ -52,6 +52,11 @@
 #include "e-gdbus-book-factory.h"
 #include "e-gdbus-book-view.h"
 
+#define BOOK_BACKEND_PROPERTY_CAPABILITIES		"capabilities"
+#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS		"required-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS		"supported-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS	"supported-auth-methods"
+
 static gchar ** flatten_stringlist (GList *list);
 static GList *array_to_stringlist (gchar **list);
 static EList *array_to_elist (gchar **list);
@@ -714,7 +719,8 @@ e_book_commit_contact_async (EBook *book,
  *
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
- * Deprecated: 3.2: Use e_book_client_get_required_fields_sync() instead.
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
+ * an #EBookClient object with #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
  **/
 gboolean
 e_book_get_required_fields (EBook *book,
@@ -722,14 +728,17 @@ e_book_get_required_fields (EBook *book,
                             GError **error)
 {
 	GError *err = NULL;
-	gchar **list = NULL;
+	gchar **list = NULL, *list_str = NULL;
 
 	g_return_val_if_fail (E_IS_BOOK (book), FALSE);
 
 	e_return_error_if_fail (
 		book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	e_gdbus_book_call_get_required_fields_sync (book->priv->gdbus_book, &list, NULL, &err);
+	e_gdbus_book_call_get_backend_property_sync (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS, &list_str, NULL, &err);
+
+	list = g_strsplit (list_str, ",", -1);
+	g_free (list_str);
 
 	if (list) {
 		*fields = array_to_stringlist (list);
@@ -743,7 +752,7 @@ e_book_get_required_fields (EBook *book,
 static void
 get_required_fields_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
 {
-	gchar **fields = NULL;
+	gchar **fields = NULL, *fields_str = NULL;
 	GError *err = NULL, *error = NULL;
 	AsyncData *data = user_data;
 	EBookEListAsyncCallback excb = data->excallback;
@@ -752,7 +761,10 @@ get_required_fields_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user
 	#endif
 	EList *efields = NULL;
 
-	e_gdbus_book_call_get_required_fields_finish (G_DBUS_PROXY (gdbus_book), res, &fields, &error);
+	e_gdbus_book_call_get_backend_property_finish (G_DBUS_PROXY (gdbus_book), res, &fields_str, &error);
+
+	fields = g_strsplit (fields_str, ",", -1);
+	g_free (fields_str);
 
 	efields = array_to_elist (fields);
 
@@ -805,7 +817,7 @@ e_book_async_get_required_fields (EBook *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_required_fields (book->priv->gdbus_book, NULL, get_required_fields_reply, data);
+	e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS, NULL, get_required_fields_reply, data);
 
 	return TRUE;
 }
@@ -824,7 +836,8 @@ e_book_async_get_required_fields (EBook *book,
  *
  * Since: 2.32
  *
- * Deprecated: 3.2: Use e_book_client_get_required_fields() and e_book_client_get_required_fields_finish() instead.
+ * 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.
  **/
 gboolean
 e_book_get_required_fields_async (EBook *book,
@@ -843,7 +856,7 @@ e_book_get_required_fields_async (EBook *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_required_fields (book->priv->gdbus_book, NULL, get_required_fields_reply, data);
+	e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS, NULL, get_required_fields_reply, data);
 
 	return TRUE;
 }
@@ -861,7 +874,8 @@ e_book_get_required_fields_async (EBook *book,
  *
  * Returns: %TRUE if successful, %FALSE otherwise
  *
- * Deprecated: 3.2: Use e_book_client_get_supported_fields_sync() instead.
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
+ * an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
  **/
 gboolean
 e_book_get_supported_fields  (EBook *book,
@@ -869,15 +883,17 @@ e_book_get_supported_fields  (EBook *book,
                               GError **error)
 {
 	GError *err = NULL;
-	gchar **list = NULL;
+	gchar **list = NULL, *list_str = NULL;
 
 	g_return_val_if_fail (E_IS_BOOK (book), FALSE);
 
 	e_return_error_if_fail (
 		book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	e_gdbus_book_call_get_supported_fields_sync (book->priv->gdbus_book, &list, NULL, &err);
+	e_gdbus_book_call_get_backend_property_sync (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, &list_str, NULL, &err);
 
+	list = g_strsplit (list_str, ",", -1);
+	g_free (list_str);
 	if (list) {
 		*fields = array_to_stringlist (list);
 		g_strfreev (list);
@@ -890,7 +906,7 @@ e_book_get_supported_fields  (EBook *book,
 static void
 get_supported_fields_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
 {
-	gchar **fields = NULL;
+	gchar **fields = NULL, *fields_str = NULL;
 	GError *err = NULL, *error = NULL;
 	AsyncData *data = user_data;
 	EBookEListAsyncCallback excb = data->excallback;
@@ -899,7 +915,10 @@ get_supported_fields_reply (GObject *gdbus_book, GAsyncResult *res, gpointer use
 	#endif
 	EList *efields;
 
-	e_gdbus_book_call_get_supported_fields_finish (G_DBUS_PROXY (gdbus_book), res, &fields, &error);
+	e_gdbus_book_call_get_backend_property_finish (G_DBUS_PROXY (gdbus_book), res, &fields_str, &error);
+
+	fields = g_strsplit (fields_str, ",", -1);
+	g_free (fields_str);
 
 	efields = array_to_elist (fields);
 
@@ -953,7 +972,7 @@ e_book_async_get_supported_fields (EBook *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_supported_fields (book->priv->gdbus_book, NULL, get_supported_fields_reply, data);
+	e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, NULL, get_supported_fields_reply, data);
 
 	return TRUE;
 }
@@ -973,7 +992,8 @@ e_book_async_get_supported_fields (EBook *book,
  *
  * Since: 2.32
  *
- * Deprecated: 3.2: Use e_book_client_get_supported_fields() and e_book_client_get_supported_fields_finish() instead.
+ * 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.
  **/
 gboolean
 e_book_get_supported_fields_async (EBook *book,
@@ -992,7 +1012,7 @@ e_book_get_supported_fields_async (EBook *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_supported_fields (book->priv->gdbus_book, NULL, get_supported_fields_reply, data);
+	e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, NULL, get_supported_fields_reply, data);
 
 	return TRUE;
 }
@@ -1009,7 +1029,8 @@ e_book_get_supported_fields_async (EBook *book,
  *
  * Returns: %TRUE if successful, %FALSE otherwise
  *
- * Deprecated: 3.2: Use e_book_client_get_supported_auth_methods_sync() instead.
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
+ * an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS instead.
  **/
 gboolean
 e_book_get_supported_auth_methods (EBook *book,
@@ -1017,6 +1038,7 @@ e_book_get_supported_auth_methods (EBook *book,
                                    GError **error)
 {
 	GError *err = NULL;
+	gchar *list_str = NULL;
 	gchar **list = NULL;
 
 	g_return_val_if_fail (E_IS_BOOK (book), FALSE);
@@ -1024,7 +1046,10 @@ e_book_get_supported_auth_methods (EBook *book,
 	e_return_error_if_fail (
 		book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	e_gdbus_book_call_get_supported_auth_methods_sync (book->priv->gdbus_book, &list, NULL, &err);
+	e_gdbus_book_call_get_backend_property_sync (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS, &list_str, NULL, &err);
+
+	list = g_strsplit (list_str, ",", -1);
+	g_free (list_str);
 
 	if (list) {
 		*auth_methods = array_to_stringlist (list);
@@ -1038,7 +1063,7 @@ e_book_get_supported_auth_methods (EBook *book,
 static void
 get_supported_auth_methods_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
 {
-	gchar **methods = NULL;
+	gchar **methods = NULL, *methods_str = NULL;
 	GError *err = NULL, *error = NULL;
 	AsyncData *data = user_data;
 	EBookEListAsyncCallback excb = data->excallback;
@@ -1047,7 +1072,10 @@ get_supported_auth_methods_reply (GObject *gdbus_book, GAsyncResult *res, gpoint
 	#endif
 	EList *emethods;
 
-	e_gdbus_book_call_get_supported_auth_methods_finish (G_DBUS_PROXY (gdbus_book), res, &methods, &error);
+	e_gdbus_book_call_get_backend_property_finish (G_DBUS_PROXY (gdbus_book), res, &methods_str, &error);
+
+	methods = g_strsplit (methods_str, ",", -1);
+	g_free (methods_str);
 
 	emethods = array_to_elist (methods);
 
@@ -1100,7 +1128,7 @@ e_book_async_get_supported_auth_methods (EBook *book,
 	data->callback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_supported_auth_methods (book->priv->gdbus_book, NULL, get_supported_auth_methods_reply, data);
+	e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS, NULL, get_supported_auth_methods_reply, data);
 
 	return TRUE;
 }
@@ -1119,7 +1147,8 @@ e_book_async_get_supported_auth_methods (EBook *book,
  *
  * Since: 2.32
  *
- * Deprecated: 3.2: Use e_book_client_get_supported_auth_methods() and e_book_client_get_supported_auth_methods_finish() instead.
+ * 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_AUTH_METHODS instead.
  **/
 gboolean
 e_book_get_supported_auth_methods_async (EBook *book,
@@ -1138,7 +1167,7 @@ e_book_get_supported_auth_methods_async (EBook *book,
 	data->excallback = cb;
 	data->closure = closure;
 
-	e_gdbus_book_call_get_supported_auth_methods (book->priv->gdbus_book, NULL, get_supported_auth_methods_reply, data);
+	e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS, NULL, get_supported_auth_methods_reply, data);
 
 	return TRUE;
 }
@@ -2873,7 +2902,7 @@ e_book_get_source (EBook *book)
  *
  * Returns: The capabilities list
  *
- * Deprecated: 3.2: Use e_client_get_capabilities() or e_book_client_get_capabilities_sync() on an #EBookClient object instead.
+ * Deprecated: 3.2: Use e_client_get_capabilities() on an #EBookClient object.
  */
 const gchar *
 e_book_get_static_capabilities (EBook *book,
@@ -2887,7 +2916,7 @@ e_book_get_static_capabilities (EBook *book,
 	if (!book->priv->cap_queried) {
 		gchar *cap = NULL;
 
-		if (!e_gdbus_book_call_get_capabilities_sync (book->priv->gdbus_book, &cap, NULL, error)) {
+		if (!e_gdbus_book_call_get_backend_property_sync (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_CAPABILITIES, &cap, NULL, error)) {
 			return NULL;
 		}
 
diff --git a/addressbook/libedata-book/e-book-backend-sync.c b/addressbook/libedata-book/e-book-backend-sync.c
index 0ff670a..ce3072d 100644
--- a/addressbook/libedata-book/e-book-backend-sync.c
+++ b/addressbook/libedata-book/e-book-backend-sync.c
@@ -110,29 +110,61 @@ e_book_backend_sync_remove (EBookBackendSync *backend,
 }
 
 /**
- * e_book_backend_sync_get_capabilities:
+ * e_book_backend_sync_get_backend_property:
  * @backend: an #EBookBackendSync
  * @book: an #EDataBook
  * @cancellable: a #GCancellable for the operation
- * @capabilities: a string of comma-separated capabilities for this backend
- * @removed_ids: a pointer to a location to store a list of the contacts actually removed
+ * @prop_name: Property name whose value to retrieve.
+ * @prop_value: Return value of the @prop_name.
  * @error: #GError to set, when something fails
  *
- * Queries for @capabilities of the @backend.
+ * Calls the get_backend_property_sync method on the given backend.
+ *
+ * Returns whether processed this property. Returning FALSE means to pass
+ * the call to the EBookBackend parent class, thus neither @error should be
+ * set in this case.
+ *
+ * Since: 3.2
  **/
-void
-e_book_backend_sync_get_capabilities (EBookBackendSync *backend,
-				      EDataBook *book,
-				      GCancellable *cancellable,
-				      gchar **capabilities,
-				      GError **error)
+gboolean
+e_book_backend_sync_get_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
 {
-	e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (capabilities, E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_capabilities_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
+	e_return_data_book_error_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_val_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_val_if_fail (prop_name, E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_val_if_fail (prop_value, E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_val_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_backend_property_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
 
-	(* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_capabilities_sync) (backend, book, cancellable, capabilities, error);
+	return (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_backend_property_sync) (backend, book, cancellable, prop_name, prop_value, error);
+}
+
+/**
+ * e_book_backend_sync_set_backend_property:
+ * @backend: an #EBookBackendSync
+ * @book: an #EDataBook
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: Property name to set.
+ * @prop_value: New value of the @prop_name.
+ * @error: #GError to set, when something fails
+ *
+ * Calls the set_backend_property_sync method on the given backend.
+ *
+ * Returns whether processed this property. Returning FALSE means to pass
+ * the call to the EBookBackend parent class, thus neither @error should be
+ * set in this case.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_backend_sync_set_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error)
+{
+	e_return_data_book_error_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_val_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_val_if_fail (prop_name, E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_val_if_fail (prop_value, E_DATA_BOOK_STATUS_INVALID_ARG);
+	e_return_data_book_error_val_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->set_backend_property_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
+
+	return (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->set_backend_property_sync) (backend, book, cancellable, prop_name, prop_value, error);
 }
 
 /**
@@ -275,89 +307,8 @@ e_book_backend_sync_authenticate_user (EBookBackendSync *backend,
 	(* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->authenticate_user_sync) (backend, book, cancellable, credentials, error);
 }
 
-/**
- * e_book_backend_sync_get_required_fields:
- * @backend: an #EBookBackendSync
- * @book: an #EDataBook
- * @cancellable: a #GCancellable for the operation
- * @fields: a pointer to a location to store the fields
- * @error: #GError to set, when something fails
- *
- * Gets a list of the fields required for all contacts in @book. The
- * fields are represented by strings from #e_contact_field_name. The list
- * and its contents must be freed by the caller.
- **/
-void
-e_book_backend_sync_get_required_fields (EBookBackendSync *backend,
-					 EDataBook *book,
-					 GCancellable *cancellable,
-					 GSList **fields,
-					 GError **error)
-{
-	e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (fields, E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_required_fields_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
-
-	(* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_required_fields_sync) (backend, book, cancellable, fields, error);
-}
-
-/**
- * e_book_backend_sync_get_supported_fields:
- * @backend: an #EBookBackendSync
- * @book: an #EDataBook
- * @cancellable: a #GCancellable for the operation
- * @fields: a pointer to a location to store the fields
- * @error: #GError to set, when something fails
- *
- * Gets a list of the fields supported for contacts in @book. Other fields
- * may not be stored. The fields are represented by strings from #e_contact_field_name.
- * The list and its contents must be freed by the caller.
- **/
-void
-e_book_backend_sync_get_supported_fields (EBookBackendSync *backend,
-					  EDataBook *book,
-					  GCancellable *cancellable,
-					  GSList **fields,
-					  GError **error)
-{
-	e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (fields, E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_supported_fields_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
-
-	(* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_supported_fields_sync) (backend, book, cancellable, fields, error);
-}
-
-/**
- * e_book_backend_sync_get_supported_auth_methods:
- * @backend: an #EBookBackendSync
- * @book: an #EDataBook
- * @cancellable: a #GCancellable for the operation
- * @methods: a pointer to a location to store the methods
- * @error: #GError to set, when something fails
- *
- * Gets a list of the authentication methods supported by @book. The
- * methods are represented by strings. The list and its contents must
- * be freed by the caller.
- **/
-void
-e_book_backend_sync_get_supported_auth_methods (EBookBackendSync *backend,
-						EDataBook *book,
-						GCancellable *cancellable,
-						GSList **methods,
-						GError **error)
-{
-	e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (methods, E_DATA_BOOK_STATUS_INVALID_ARG);
-	e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_supported_auth_methods_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
-
-	(* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_supported_auth_methods_sync) (backend, book, cancellable, methods, error);
-}
-
 static void
-_e_book_backend_open (EBookBackend *backend,
+book_backend_open (EBookBackend *backend,
 		      EDataBook    *book,
 		      guint32       opid,
 		      GCancellable *cancellable,
@@ -371,7 +322,7 @@ _e_book_backend_open (EBookBackend *backend,
 }
 
 static void
-_e_book_backend_remove (EBookBackend *backend,
+book_backend_remove (EBookBackend *backend,
 			EDataBook    *book,
 			guint32       opid,
 			GCancellable *cancellable)
@@ -384,27 +335,36 @@ _e_book_backend_remove (EBookBackend *backend,
 }
 
 static void
-_e_book_backend_get_capabilities (EBookBackend *backend,
-				  EDataBook    *book,
-				  guint32       opid,
-				  GCancellable *cancellable)
+book_backend_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
 {
 	GError *error = NULL;
-	gchar *capabilities = NULL;
+	gchar *prop_value = NULL;
 
-	e_book_backend_sync_get_capabilities (E_BOOK_BACKEND_SYNC (backend), book, cancellable, &capabilities, &error);
+	if (e_book_backend_sync_get_backend_property (E_BOOK_BACKEND_SYNC (backend), book, cancellable, prop_name, &prop_value, &error))
+		e_data_book_respond_get_backend_property (book, opid, error, prop_value);
+	else
+		(* E_BOOK_BACKEND_CLASS (e_book_backend_sync_parent_class)->get_backend_property) (backend, book, opid, cancellable, prop_name);
 
-	e_data_book_respond_get_capabilities (book, opid, error, capabilities);
+	g_free (prop_value);
+}
 
-	g_free (capabilities);
+static void
+book_backend_set_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
+{
+	GError *error = NULL;
+
+	if (e_book_backend_sync_set_backend_property (E_BOOK_BACKEND_SYNC (backend), book, cancellable, prop_name, prop_value, &error))
+		e_data_book_respond_set_backend_property (book, opid, error);
+	else
+		(* E_BOOK_BACKEND_CLASS (e_book_backend_sync_parent_class)->set_backend_property) (backend, book, opid, cancellable, prop_name, prop_value);
 }
 
 static void
-_e_book_backend_create_contact (EBookBackend *backend,
-				EDataBook    *book,
-				guint32       opid,
-				GCancellable *cancellable,
-				const gchar   *vcard)
+book_backend_create_contact (EBookBackend *backend,
+			     EDataBook    *book,
+			     guint32       opid,
+			     GCancellable *cancellable,
+			     const gchar   *vcard)
 {
 	GError *error = NULL;
 	EContact *contact = NULL;
@@ -418,11 +378,11 @@ _e_book_backend_create_contact (EBookBackend *backend,
 }
 
 static void
-_e_book_backend_remove_contacts (EBookBackend *backend,
-				 EDataBook    *book,
-				 guint32       opid,
-				 GCancellable *cancellable,
-				 const GSList *id_list)
+book_backend_remove_contacts (EBookBackend *backend,
+			      EDataBook    *book,
+			      guint32       opid,
+			      GCancellable *cancellable,
+			      const GSList *id_list)
 {
 	GError *error = NULL;
 	GSList *ids = NULL;
@@ -438,11 +398,11 @@ _e_book_backend_remove_contacts (EBookBackend *backend,
 }
 
 static void
-_e_book_backend_modify_contact (EBookBackend *backend,
-				EDataBook    *book,
-				guint32       opid,
-				GCancellable *cancellable,
-				const gchar   *vcard)
+book_backend_modify_contact (EBookBackend *backend,
+			     EDataBook    *book,
+			     guint32       opid,
+			     GCancellable *cancellable,
+			     const gchar   *vcard)
 {
 	GError *error = NULL;
 	EContact *contact = NULL;
@@ -456,11 +416,11 @@ _e_book_backend_modify_contact (EBookBackend *backend,
 }
 
 static void
-_e_book_backend_get_contact (EBookBackend *backend,
-			     EDataBook    *book,
-			     guint32       opid,
-			     GCancellable *cancellable,
-			     const gchar   *id)
+book_backend_get_contact (EBookBackend *backend,
+			  EDataBook    *book,
+			  guint32       opid,
+			  GCancellable *cancellable,
+			  const gchar   *id)
 {
 	GError *error = NULL;
 	gchar *vcard = NULL;
@@ -474,11 +434,11 @@ _e_book_backend_get_contact (EBookBackend *backend,
 }
 
 static void
-_e_book_backend_get_contact_list (EBookBackend *backend,
-				  EDataBook    *book,
-				  guint32       opid,
-				  GCancellable *cancellable,
-				  const gchar   *query)
+book_backend_get_contact_list (EBookBackend *backend,
+			       EDataBook    *book,
+			       guint32       opid,
+			       GCancellable *cancellable,
+			       const gchar   *query)
 {
 	GError *error = NULL;
 	GSList *cards = NULL;
@@ -492,11 +452,11 @@ _e_book_backend_get_contact_list (EBookBackend *backend,
 }
 
 static void
-_e_book_backend_authenticate_user (EBookBackend *backend,
-				   EDataBook    *book,
-				   guint32       opid,
-				   GCancellable *cancellable,
-				   ECredentials *credentials)
+book_backend_authenticate_user (EBookBackend *backend,
+				EDataBook    *book,
+				guint32       opid,
+				GCancellable *cancellable,
+				ECredentials *credentials)
 {
 	GError *error = NULL;
 
@@ -505,61 +465,18 @@ _e_book_backend_authenticate_user (EBookBackend *backend,
 	e_data_book_respond_authenticate_user (book, opid, error);
 }
 
-static void
-_e_book_backend_get_required_fields (EBookBackend *backend,
-				     EDataBook    *book,
-				     guint32       opid,
-				     GCancellable *cancellable)
-{
-	GError *error = NULL;
-	GSList *fields = NULL;
-
-	e_book_backend_sync_get_required_fields (E_BOOK_BACKEND_SYNC (backend), book, cancellable, &fields, &error);
-
-	e_data_book_respond_get_required_fields (book, opid, error, fields);
-
-	if (fields) {
-		g_slist_foreach (fields, (GFunc) g_free, NULL);
-		g_slist_free (fields);
-	}
-}
-
-static void
-_e_book_backend_get_supported_fields (EBookBackend *backend,
-				      EDataBook    *book,
-				      guint32       opid,
-				      GCancellable *cancellable)
+static gboolean
+book_backend_sync_get_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
 {
-	GError *error = NULL;
-	GSList *fields = NULL;
-
-	e_book_backend_sync_get_supported_fields (E_BOOK_BACKEND_SYNC (backend), book, cancellable, &fields, &error);
-
-	e_data_book_respond_get_supported_fields (book, opid, error, fields);
-
-	if (fields) {
-		g_slist_foreach (fields, (GFunc) g_free, NULL);
-		g_slist_free (fields);
-	}
+	/* to indicate to pass to the EBookBackend parent class */
+	return FALSE;
 }
 
-static void
-_e_book_backend_get_supported_auth_methods (EBookBackend *backend,
-					    EDataBook    *book,
-					    guint32       opid,
-					    GCancellable *cancellable)
+static gboolean
+book_backend_sync_set_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error)
 {
-	GError *error = NULL;
-	GSList *methods = NULL;
-
-	e_book_backend_sync_get_supported_auth_methods (E_BOOK_BACKEND_SYNC (backend), book, cancellable, &methods, &error);
-
-	e_data_book_respond_get_supported_auth_methods (book, opid, error, methods);
-
-	if (methods) {
-		g_slist_foreach (methods, (GFunc) g_free, NULL);
-		g_slist_free (methods);
-	}
+	/* to indicate to pass to the EBookBackend parent class */
+	return FALSE;
 }
 
 static void
@@ -597,19 +514,19 @@ e_book_backend_sync_class_init (EBookBackendSyncClass *klass)
 	parent_class = g_type_class_peek_parent (klass);
 
 	object_class = (GObjectClass *) klass;
-
-	backend_class->open = _e_book_backend_open;
-	backend_class->authenticate_user = _e_book_backend_authenticate_user;
-	backend_class->remove = _e_book_backend_remove;
-	backend_class->get_capabilities = _e_book_backend_get_capabilities;
-	backend_class->create_contact = _e_book_backend_create_contact;
-	backend_class->remove_contacts = _e_book_backend_remove_contacts;
-	backend_class->modify_contact = _e_book_backend_modify_contact;
-	backend_class->get_contact = _e_book_backend_get_contact;
-	backend_class->get_contact_list = _e_book_backend_get_contact_list;
-	backend_class->get_required_fields = _e_book_backend_get_required_fields;
-	backend_class->get_supported_fields = _e_book_backend_get_supported_fields;
-	backend_class->get_supported_auth_methods = _e_book_backend_get_supported_auth_methods;
-
 	object_class->dispose = e_book_backend_sync_dispose;
+
+	backend_class->open			= book_backend_open;
+	backend_class->authenticate_user	= book_backend_authenticate_user;
+	backend_class->remove			= book_backend_remove;
+	backend_class->get_backend_property	= book_backend_get_backend_property;
+	backend_class->set_backend_property	= book_backend_set_backend_property;
+	backend_class->create_contact		= book_backend_create_contact;
+	backend_class->remove_contacts		= book_backend_remove_contacts;
+	backend_class->modify_contact		= book_backend_modify_contact;
+	backend_class->get_contact		= book_backend_get_contact;
+	backend_class->get_contact_list		= book_backend_get_contact_list;
+
+	klass->get_backend_property_sync	= book_backend_sync_get_backend_property;
+	klass->set_backend_property_sync	= book_backend_sync_set_backend_property;
 }
diff --git a/addressbook/libedata-book/e-book-backend-sync.h b/addressbook/libedata-book/e-book-backend-sync.h
index 38d80bf..a50f24f 100644
--- a/addressbook/libedata-book/e-book-backend-sync.h
+++ b/addressbook/libedata-book/e-book-backend-sync.h
@@ -32,16 +32,13 @@ struct _EBookBackendSyncClass {
 	void (*open_sync)			(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, gboolean only_if_exists, GError **error);
 	void (*authenticate_user_sync)		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, ECredentials *credentials, GError **error);
 	void (*remove_sync)			(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GError **error);
-	void (*get_capabilities_sync)		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, gchar **capabilities, GError **error);
+	gboolean (*get_backend_property_sync)	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error);
+	gboolean (*set_backend_property_sync)	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error);
 	void (*create_contact_sync)		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *vcard, EContact **contact, GError **error);
 	void (*remove_contacts_sync)		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const GSList *id_list, GSList **removed_ids, GError **error);
 	void (*modify_contact_sync)		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *vcard, EContact **contact, GError **error);
 	void (*get_contact_sync)		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *id, gchar **vcard, GError **error);
 	void (*get_contact_list_sync)		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *query, GSList **contacts, GError **error);
-
-	void (*get_required_fields_sync)	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GSList **fields, GError **error);
-	void (*get_supported_fields_sync)	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GSList **fields, GError **error);
-	void (*get_supported_auth_methods_sync)	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GSList **methods, GError **error);
 };
 
 GType		e_book_backend_sync_get_type		(void);
@@ -51,17 +48,14 @@ gboolean	e_book_backend_sync_construct		(EBookBackendSync *backend);
 void		e_book_backend_sync_open		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, gboolean only_if_exists, GError **error);
 void		e_book_backend_sync_authenticate_user	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, ECredentials *credentials, GError **error);
 void		e_book_backend_sync_remove		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GError **error);
-void		e_book_backend_sync_get_capabilities	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, gchar **capabilities, GError **error);
+gboolean	e_book_backend_sync_get_backend_property(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error);
+gboolean	e_book_backend_sync_set_backend_property(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error);
 void		e_book_backend_sync_create_contact	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *vcard, EContact **contact, GError **error);
 void		e_book_backend_sync_remove_contacts	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const GSList *id_list, GSList **removed_ids, GError **error);
 void		e_book_backend_sync_modify_contact	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *vcard, EContact **contact, GError **error);
 void		e_book_backend_sync_get_contact		(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *id, gchar **vcard, GError **error);
 void		e_book_backend_sync_get_contact_list	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *query, GSList **contacts, GError **error);
 
-void		e_book_backend_sync_get_required_fields	(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GSList **fields, GError **error);
-void		e_book_backend_sync_get_supported_fields(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GSList **fields, GError **error);
-void		e_book_backend_sync_get_supported_auth_methods (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GSList **methods, GError **error);
-
 G_END_DECLS
 
 #endif /* __E_BOOK_BACKEND_SYNC_H__ */
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index 1abfee5..3536824 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -8,6 +8,8 @@
 
 #include <config.h>
 
+#include <glib/gi18n-lib.h>
+
 #include <libedataserver/e-data-server-util.h>
 
 #include "e-data-book-view.h"
@@ -68,6 +70,38 @@ book_backend_set_default_cache_dir (EBookBackend *backend)
 }
 
 static void
+book_backend_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
+{
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+	g_return_if_fail (book != NULL);
+	g_return_if_fail (prop_name != NULL);
+
+	if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_LOADED)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_loaded (backend) ? "TRUE" : "FALSE");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_ONLINE)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, backend->priv->online ? "TRUE" : "FALSE");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_READONLY)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_readonly (backend) ? "TRUE" : "FALSE");
+	} else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_CACHE_DIR)) {
+		e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_get_cache_dir (backend));
+	} else {
+		e_data_book_respond_get_backend_property (book, opid, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_NOT_SUPPORTED, _("Unknown book property '%s'"), prop_name), NULL);
+	}
+}
+
+static void
+book_backend_set_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
+{
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+	g_return_if_fail (book != NULL);
+	g_return_if_fail (prop_name != NULL);
+
+	e_data_book_respond_set_backend_property (book, opid, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_NOT_SUPPORTED, _("Cannot change value of book property '%s'"), prop_name));
+}
+
+static void
 book_backend_set_property (GObject *object,
                            guint property_id,
                            const GValue *value,
@@ -141,18 +175,21 @@ book_backend_finalize (GObject *object)
 }
 
 static void
-e_book_backend_class_init (EBookBackendClass *class)
+e_book_backend_class_init (EBookBackendClass *klass)
 {
 	GObjectClass *object_class;
 
-	g_type_class_add_private (class, sizeof (EBookBackendPrivate));
+	g_type_class_add_private (klass, sizeof (EBookBackendPrivate));
 
-	object_class = G_OBJECT_CLASS (class);
+	object_class = G_OBJECT_CLASS (klass);
 	object_class->set_property = book_backend_set_property;
 	object_class->get_property = book_backend_get_property;
 	object_class->dispose = book_backend_dispose;
 	object_class->finalize = book_backend_finalize;
 
+	klass->get_backend_property = book_backend_get_backend_property;
+	klass->set_backend_property = book_backend_set_backend_property;
+
 	g_object_class_install_property (
 		object_class,
 		PROP_CACHE_DIR,
@@ -515,78 +552,6 @@ e_book_backend_authenticate_user (EBookBackend *backend,
 	(* E_BOOK_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, book, opid, cancellable, credentials);
 }
 
-/**
- * e_book_backend_get_required_fields:
- * @backend: an #EBookBackend
- * @book: an #EDataBook
- * @cancellable: a #GCancellable for the operation
- * @opid: the ID to use for this operation
- *
- * Executes a 'get required fields' request specified by @opid on @book
- * using @backend.
- * This might be finished with e_data_book_respond_get_required_fields().
- **/
-void
-e_book_backend_get_required_fields (EBookBackend *backend,
-				     EDataBook    *book,
-				     guint32       opid,
-				     GCancellable *cancellable)
-{
-	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
-	g_return_if_fail (E_IS_DATA_BOOK (book));
-	g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_required_fields);
-
-	(* E_BOOK_BACKEND_GET_CLASS (backend)->get_required_fields) (backend, book, opid, cancellable);
-}
-
-/**
- * e_book_backend_get_supported_fields:
- * @backend: an #EBookBackend
- * @book: an #EDataBook
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- *
- * Executes a 'get supported fields' request specified by @opid on @book
- * using @backend.
- * This might be finished with e_data_book_respond_get_supported_fields().
- **/
-void
-e_book_backend_get_supported_fields (EBookBackend *backend,
-				     EDataBook    *book,
-				     guint32       opid,
-				     GCancellable *cancellable)
-{
-	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
-	g_return_if_fail (E_IS_DATA_BOOK (book));
-	g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_supported_fields);
-
-	(* E_BOOK_BACKEND_GET_CLASS (backend)->get_supported_fields) (backend, book, opid, cancellable);
-}
-
-/**
- * e_book_backend_get_supported_auth_methods:
- * @backend: an #EBookBackend
- * @book: an #EDataBook
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- *
- * Executes a 'get supported auth methods' request specified by @opid on @book
- * using @backend.
- * This might be finished with e_data_book_respond_get_supported_auth_methods().
- **/
-void
-e_book_backend_get_supported_auth_methods (EBookBackend *backend,
-					   EDataBook    *book,
-					   guint32       opid,
-					   GCancellable *cancellable)
-{
-	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
-	g_return_if_fail (E_IS_DATA_BOOK (book));
-	g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_supported_auth_methods);
-
-	(* E_BOOK_BACKEND_GET_CLASS (backend)->get_supported_auth_methods) (backend, book, opid, cancellable);
-}
-
 static void
 last_client_gone (EBookBackend *backend)
 {
@@ -723,22 +688,58 @@ e_book_backend_foreach_view (EBookBackend *backend, gboolean (* callback) (EData
 }
 
 /**
- * e_book_backend_get_capabilities:
+ * e_book_backend_get_book_backend_property:
  * @backend: an #EBookBackend
  * @book: an #EDataBook
  * @opid: the ID to use for this operation
  * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to get value of; cannot be NULL
  *
- * Gets the capabilities offered by this @backend.
- * This might be finished with e_data_book_respond_get_capabilities().
+ * Calls the get_backend_property method on the given backend.
+ * This might be finished with e_data_book_respond_get_backend_property().
+ * Default implementation takes care of common properties and returns
+ * an 'unsupported' error for any unknown properties. The subclass may
+ * always call this default implementation for properties which fetching
+ * it doesn't overwrite.
+ *
+ * Since: 3.2
  **/
 void
-e_book_backend_get_capabilities (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
+e_book_backend_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
 {
 	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
-	g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_capabilities);
+	g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_backend_property);
+
+	E_BOOK_BACKEND_GET_CLASS (backend)->get_backend_property (backend, book, opid, cancellable, prop_name);
+}
+
+/**
+ * e_book_backend_set_backend_property:
+ * @backend: an #EBookBackend
+ * @book: an #EDataBook
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to change; cannot be NULL
+ * @prop_value: value to set to @prop_name; cannot be NULL
+ *
+ * Calls the set_backend_property method on the given backend.
+ * This might be finished with e_data_book_respond_set_backend_property().
+ * Default implementation simply returns an 'unsupported' error.
+ * The subclass may always call this default implementation for properties
+ * which fetching it doesn't overwrite.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_backend_set_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
+{
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+	g_return_if_fail (prop_name != NULL);
+	g_return_if_fail (prop_value != NULL);
+	g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->set_backend_property != NULL);
 
-	E_BOOK_BACKEND_GET_CLASS (backend)->get_capabilities (backend, book, opid, cancellable);
+	E_BOOK_BACKEND_GET_CLASS (backend)->set_backend_property (backend, book, opid, cancellable, prop_name, prop_value);
 }
 
 /**
diff --git a/addressbook/libedata-book/e-book-backend.h b/addressbook/libedata-book/e-book-backend.h
index 93d0399..50caa08 100644
--- a/addressbook/libedata-book/e-book-backend.h
+++ b/addressbook/libedata-book/e-book-backend.h
@@ -41,6 +41,15 @@ G_BEGIN_DECLS
 #define E_IS_BOOK_BACKEND_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_BOOK_BACKEND))
 #define E_BOOK_BACKEND_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), E_TYPE_BOOK_BACKEND, EBookBackendClass))
 
+#define BOOK_BACKEND_PROPERTY_LOADED			"loaded"
+#define BOOK_BACKEND_PROPERTY_ONLINE			"online"
+#define BOOK_BACKEND_PROPERTY_READONLY			"readonly"
+#define BOOK_BACKEND_PROPERTY_CACHE_DIR			"cache-dir"
+#define BOOK_BACKEND_PROPERTY_CAPABILITIES		"capabilities"
+#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS		"required-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS		"supported-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS	"supported-auth-methods"
+
 typedef struct _EBookBackendPrivate EBookBackendPrivate;
 
 struct _EBookBackend {
@@ -52,10 +61,12 @@ struct _EBookBackendClass {
 	GObjectClass parent_class;
 
 	/* Virtual methods */
+        void	(* get_backend_property)	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name);
+        void	(* set_backend_property)	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value);
+
 	void	(* open)			(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, gboolean only_if_exists);
 	void	(* authenticate_user)		(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, ECredentials *credentials);
 	void	(* remove)			(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
-        void	(* get_capabilities)		(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
 	void	(* set_online)			(EBookBackend *backend, gboolean is_online);
 
 	void	(* create_contact)		(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard);
@@ -63,9 +74,6 @@ struct _EBookBackendClass {
 	void	(* modify_contact)		(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard);
 	void	(* get_contact)			(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *id);
 	void	(* get_contact_list)		(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *query);
-	void	(* get_required_fields)		(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
-	void	(* get_supported_fields)	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
-	void	(* get_supported_auth_methods)	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
 
 	void	(* start_book_view)		(EBookBackend *backend, EDataBookView *book_view);
 	void	(* stop_book_view)		(EBookBackend *backend, EDataBookView *book_view);
@@ -90,18 +98,17 @@ gboolean	e_book_backend_is_readonly	(EBookBackend *backend);
 gboolean	e_book_backend_is_removed	(EBookBackend *backend);
 void		e_book_backend_set_online	(EBookBackend *backend, gboolean is_online);
 
+void		e_book_backend_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name);
+void		e_book_backend_set_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value);
+
 void		e_book_backend_open		(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, gboolean only_if_exists);
 void		e_book_backend_authenticate_user(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, ECredentials *credentials);
 void		e_book_backend_remove		(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
-void		e_book_backend_get_capabilities (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
 void		e_book_backend_create_contact	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard);
 void		e_book_backend_remove_contacts	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const GSList *id_list);
 void		e_book_backend_modify_contact	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard);
 void		e_book_backend_get_contact	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *id);
 void		e_book_backend_get_contact_list	(EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *query);
-void		e_book_backend_get_supported_fields (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
-void		e_book_backend_get_required_fields  (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
-void		e_book_backend_get_supported_auth_methods (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
 
 void		e_book_backend_start_book_view	(EBookBackend *backend, EDataBookView *view);
 void		e_book_backend_stop_book_view	(EBookBackend *backend, EDataBookView *view);
@@ -128,4 +135,3 @@ void		e_book_backend_set_is_removed	(EBookBackend *backend, gboolean is_removed)
 G_END_DECLS
 
 #endif /* __E_BOOK_BACKEND_H__ */
-
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index cd486df..9fd618a 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -62,10 +62,8 @@ typedef enum {
 	OP_ADD_CONTACT,
 	OP_REMOVE_CONTACTS,
 	OP_MODIFY_CONTACT,
-	OP_GET_CAPABILITIES,
-	OP_GET_REQUIRED_FIELDS,
-	OP_GET_SUPPORTED_FIELDS,
-	OP_GET_SUPPORTED_AUTH_METHODS,
+	OP_GET_BACKEND_PROPERTY,
+	OP_SET_BACKEND_PROPERTY,
 	OP_GET_BOOK_VIEW,
 	OP_CANCEL_OPERATION,
 	OP_CANCEL_ALL,
@@ -95,12 +93,15 @@ typedef struct {
 		gchar *query;
 		/* OP_CANCEL_OPERATION */
 		guint opid;
+		/* OP_GET_BACKEND_PROPERTY */
+		gchar *prop_name;
+		/* OP_SET_BACKEND_PROPERTY */
+		struct _sbp {
+			gchar *prop_name;
+			gchar *prop_value;
+		} sbp;
 
 		/* - OP_REMOVE */
-		/* - OP_GET_CAPABILITIES */
-		/* - OP_GET_REQUIRED_FIELDS */
-		/* - OP_GET_SUPPORTED_FIELDS */
-		/* - OP_GET_SUPPORTED_AUTH_METHODS */
 		/* - OP_CANCEL_ALL */
 		/* - OP_CLOSE */
 	} d;
@@ -164,17 +165,14 @@ operation_thread (gpointer data, gpointer user_data)
 	case OP_REMOVE:
 		e_book_backend_remove (backend, op->book, op->id, op->cancellable);
 		break;
-	case OP_GET_CAPABILITIES:
-		e_book_backend_get_capabilities (backend, op->book, op->id, op->cancellable);
+	case OP_GET_BACKEND_PROPERTY:
+		e_book_backend_get_backend_property (backend, op->book, op->id, op->cancellable, op->d.prop_name);
+		g_free (op->d.prop_name);
 		break;
-	case OP_GET_REQUIRED_FIELDS:
-		e_book_backend_get_required_fields (backend, op->book, op->id, op->cancellable);
-		break;
-	case OP_GET_SUPPORTED_FIELDS:
-		e_book_backend_get_supported_fields (backend, op->book, op->id, op->cancellable);
-		break;
-	case OP_GET_SUPPORTED_AUTH_METHODS:
-		e_book_backend_get_supported_auth_methods (backend, op->book, op->id, op->cancellable);
+	case OP_SET_BACKEND_PROPERTY:
+		e_book_backend_set_backend_property (backend, op->book, op->id, op->cancellable, op->d.sbp.prop_name, op->d.sbp.prop_value);
+		g_free (op->d.sbp.prop_name);
+		g_free (op->d.sbp.prop_value);
 		break;
 	case OP_GET_BOOK_VIEW:
 		if (op->d.query) {
@@ -436,31 +434,37 @@ data_book_return_error (GDBusMethodInvocation *invocation, const GError *perror,
 	g_error_free (error);
 }
 
-
-static void
-return_error_and_list (EGdbusBook *gdbus_object, void (* complete_func) (EGdbusBook *object, guint opid, const GError *error, const gchar * const *out_array), guint32 opid, GError *error, const gchar *error_prefix, const GSList *list)
+/* takes a list of strings and converts it to a comma-separated string of values;
+   free returned pointer with g_free() */
+gchar *
+e_data_book_string_slist_to_comma_string (const GSList *strings)
 {
-	g_return_if_fail (error_prefix != NULL);
-	g_return_if_fail (complete_func != NULL);
+	GString *tmp;
+	gchar *res;
+	const GSList *l;
 
-	if (error) {
-		g_prefix_error (&error, "%s", error_prefix);
-		complete_func (gdbus_object, opid, error, NULL);
-		g_error_free (error);
-	} else {
-		gchar **array;
-		const GSList *l;
-		gint i = 0;
+	tmp = g_string_new ("");
+	for (l = strings; l != NULL; l = l->next) {
+		const gchar *str = l->data;
 
-		array = g_new0 (gchar *, g_slist_length ((GSList *) list) + 1);
-		for (l = list; l != NULL; l = l->next) {
-			array[i++] = e_util_utf8_make_valid (l->data);
-		}
+		if (!str)
+			continue;
 
-		complete_func (gdbus_object, opid, NULL, (const gchar * const *) array);
+		if (strchr (str, ',')) {
+			g_warning ("%s: String cannot contain comma; skipping value '%s'\n", G_STRFUNC, str);
+			continue;
+		}
 
-		g_strfreev (array);
+		if (tmp->len)
+			g_string_append_c (tmp, ',');
+		g_string_append (tmp, str);
 	}
+
+	res = e_util_utf8_make_valid (tmp->str);
+
+	g_string_free (tmp, TRUE);
+
+	return res;
 }
 
 static gboolean
@@ -621,52 +625,28 @@ impl_Book_removeContacts (EGdbusBook *object, GDBusMethodInvocation *invocation,
 }
 
 static gboolean
-impl_Book_getCapabilities (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
+impl_Book_getBackendProperty (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name, EDataBook *book)
 {
 	OperationData *op;
 
-	op = op_new (OP_GET_CAPABILITIES, book);
+	op = op_new (OP_GET_BACKEND_PROPERTY, book);
+	op->d.prop_name = g_strdup (in_prop_name);
 
-	e_gdbus_book_complete_get_capabilities (book->priv->gdbus_object, invocation, op->id);
+	e_gdbus_book_complete_get_backend_property (book->priv->gdbus_object, invocation, op->id);
 	e_operation_pool_push (ops_pool, op);
 
 	return TRUE;
 }
 
 static gboolean
-impl_Book_getSupportedFields (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
+impl_Book_setBackendProperty (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *in_prop_name_value, EDataBook *book)
 {
 	OperationData *op;
 
-	op = op_new (OP_GET_SUPPORTED_FIELDS, book);
+	op = op_new (OP_SET_BACKEND_PROPERTY, book);
+	g_return_val_if_fail (e_gdbus_book_decode_set_backend_property (in_prop_name_value, &op->d.sbp.prop_name, &op->d.sbp.prop_value), FALSE);
 
-	e_gdbus_book_complete_get_supported_fields (book->priv->gdbus_object, invocation, op->id);
-	e_operation_pool_push (ops_pool, op);
-
-	return TRUE;
-}
-
-static gboolean
-impl_Book_getRequiredFields (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
-{
-	OperationData *op;
-
-	op = op_new (OP_GET_REQUIRED_FIELDS, book);
-
-	e_gdbus_book_complete_get_required_fields (book->priv->gdbus_object, invocation, op->id);
-	e_operation_pool_push (ops_pool, op);
-
-	return TRUE;
-}
-
-static gboolean
-impl_Book_getSupportedAuthMethods (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
-{
-	OperationData *op;
-
-	op = op_new (OP_GET_SUPPORTED_AUTH_METHODS, book);
-
-	e_gdbus_book_complete_get_supported_auth_methods (book->priv->gdbus_object, invocation, op->id);
+	e_gdbus_book_complete_set_backend_property (book->priv->gdbus_object, invocation, op->id);
 	e_operation_pool_push (ops_pool, op);
 
 	return TRUE;
@@ -770,21 +750,35 @@ e_data_book_respond_remove (EDataBook *book, guint opid, GError *error)
 }
 
 void
-e_data_book_respond_get_capabilities (EDataBook *book, guint32 opid, GError *error, const gchar *capabilities)
+e_data_book_respond_get_backend_property (EDataBook *book, guint32 opid, GError *error, const gchar *prop_value)
 {
-	gchar *gdbus_capabilities = NULL;
+	gchar *gdbus_prop_value = NULL;
 
 	op_complete (book, opid);
 
 	/* Translators: This is prefix to a detailed error message */
-	g_prefix_error (&error, "%s", _("Cannot get capabilities: "));
+	g_prefix_error (&error, "%s", _("Cannot get backend property: "));
 
-	e_gdbus_book_emit_get_capabilities_done (book->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (capabilities, &gdbus_capabilities));
+	e_gdbus_book_emit_get_backend_property_done (book->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (prop_value, &gdbus_prop_value));
 
 	if (error)
 		g_error_free (error);
 
-	g_free (gdbus_capabilities);
+	g_free (gdbus_prop_value);
+}
+
+void
+e_data_book_respond_set_backend_property (EDataBook *book, guint32 opid, GError *error)
+{
+	op_complete (book, opid);
+
+	/* Translators: This is prefix to a detailed error message */
+	g_prefix_error (&error, "%s", _("Cannot set backend property: "));
+
+	e_gdbus_book_emit_set_backend_property_done (book->priv->gdbus_object, opid, error);
+
+	if (error)
+		g_error_free (error);
 }
 
 void
@@ -808,8 +802,25 @@ e_data_book_respond_get_contact (EDataBook *book, guint32 opid, GError *error, c
 void
 e_data_book_respond_get_contact_list (EDataBook *book, guint32 opid, GError *error, const GSList *cards)
 {
-	/* Translators: This is prefix to a detailed error message */
-	return_error_and_list (book->priv->gdbus_object, e_gdbus_book_emit_get_contact_list_done, opid, error, _("Cannot get contact list: %s"), cards);
+	if (error) {
+		/* Translators: This is prefix to a detailed error message */
+		g_prefix_error (&error, "%s", _("Cannot get contact list: "));
+		e_gdbus_book_emit_get_contact_list_done (book->priv->gdbus_object, opid, error, NULL);
+		g_error_free (error);
+	} else {
+		gchar **array;
+		const GSList *l;
+		gint i = 0;
+
+		array = g_new0 (gchar *, g_slist_length ((GSList *) cards) + 1);
+		for (l = cards; l != NULL; l = l->next) {
+			array[i++] = e_util_utf8_make_valid (l->data);
+		}
+
+		e_gdbus_book_emit_get_contact_list_done (book->priv->gdbus_object, opid, NULL, (const gchar * const *) array);
+
+		g_strfreev (array);
+	}
 }
 
 void
@@ -889,27 +900,6 @@ e_data_book_respond_remove_contacts (EDataBook *book, guint32 opid, GError *erro
 }
 
 void
-e_data_book_respond_get_supported_fields (EDataBook *book, guint32 opid, GError *error, const GSList *fields)
-{
-	/* Translators: This is prefix to a detailed error message */
-	return_error_and_list (book->priv->gdbus_object, e_gdbus_book_emit_get_supported_fields_done, opid, error, _("Cannot get supported fields: %s"), fields);
-}
-
-void
-e_data_book_respond_get_required_fields (EDataBook *book, guint32 opid, GError *error, const GSList *fields)
-{
-	/* Translators: This is prefix to a detailed error message */
-	return_error_and_list (book->priv->gdbus_object, e_gdbus_book_emit_get_required_fields_done, opid, error, _("Cannot get required fields: %s"), fields);
-}
-
-void
-e_data_book_respond_get_supported_auth_methods (EDataBook *book, guint32 opid, GError *error, const GSList *auth_methods)
-{
-	/* Translators: This is prefix to a detailed error message */
-	return_error_and_list (book->priv->gdbus_object, e_gdbus_book_emit_get_supported_auth_methods_done, opid, error, _("Cannot get supported authentication methods: %s"), auth_methods);
-}
-
-void
 e_data_book_report_error (EDataBook *book, const gchar *message)
 {
 	g_return_if_fail (book != NULL);
@@ -996,10 +986,8 @@ e_data_book_init (EDataBook *ebook)
 	g_signal_connect (gdbus_object, "handle-add-contact", G_CALLBACK (impl_Book_addContact), ebook);
 	g_signal_connect (gdbus_object, "handle-remove-contacts", G_CALLBACK (impl_Book_removeContacts), ebook);
 	g_signal_connect (gdbus_object, "handle-modify-contact", G_CALLBACK (impl_Book_modifyContact), ebook);
-	g_signal_connect (gdbus_object, "handle-get-capabilities", G_CALLBACK (impl_Book_getCapabilities), ebook);
-	g_signal_connect (gdbus_object, "handle-get-required-fields", G_CALLBACK (impl_Book_getRequiredFields), ebook);
-	g_signal_connect (gdbus_object, "handle-get-supported-fields", G_CALLBACK (impl_Book_getSupportedFields), ebook);
-	g_signal_connect (gdbus_object, "handle-get-supported-auth-methods", G_CALLBACK (impl_Book_getSupportedAuthMethods), ebook);
+	g_signal_connect (gdbus_object, "handle-get-backend-property", G_CALLBACK (impl_Book_getBackendProperty), ebook);
+	g_signal_connect (gdbus_object, "handle-set-backend-property", G_CALLBACK (impl_Book_setBackendProperty), ebook);
 	g_signal_connect (gdbus_object, "handle-get-view", G_CALLBACK (impl_Book_getBookView), ebook);
 	g_signal_connect (gdbus_object, "handle-cancel-operation", G_CALLBACK (impl_Book_cancelOperation), ebook);
 	g_signal_connect (gdbus_object, "handle-cancel-all", G_CALLBACK (impl_Book_cancelAll), ebook);
diff --git a/addressbook/libedata-book/e-data-book.h b/addressbook/libedata-book/e-data-book.h
index 8768579..1c7ea9c 100644
--- a/addressbook/libedata-book/e-data-book.h
+++ b/addressbook/libedata-book/e-data-book.h
@@ -104,6 +104,28 @@ const gchar *e_data_book_status_to_string (EDataBookStatus status);
 		}								\
 	} G_STMT_END
 
+/**
+ * e_return_data_book_error_if_fail:
+ *
+ * Same as e_return_data_book_error_if_fail(), only returns FALSE on a failure
+ *
+ * Since: 3.2
+ **/
+#define e_return_data_book_error_val_if_fail(expr, _code)			\
+	G_STMT_START {								\
+		if (G_LIKELY (expr)) {						\
+		} else {							\
+			g_log (G_LOG_DOMAIN,					\
+				G_LOG_LEVEL_CRITICAL,				\
+				"file %s: line %d (%s): assertion `%s' failed",	\
+				__FILE__, __LINE__, G_STRFUNC, #expr);		\
+			g_set_error (error, E_DATA_BOOK_ERROR, (_code),		\
+				"file %s: line %d (%s): assertion `%s' failed",	\
+				__FILE__, __LINE__, G_STRFUNC, #expr);		\
+			return FALSE;						\
+		}								\
+	} G_STMT_END
+
 GType		e_data_book_get_type				(void);
 EDataBook *	e_data_book_new					(EBookBackend *backend, ESource *source);
 EBookBackend *	e_data_book_get_backend				(EDataBook *book);
@@ -113,14 +135,12 @@ guint		e_data_book_register_gdbus_object		(EDataBook *cal, GDBusConnection *conn
 
 void		e_data_book_respond_open			(EDataBook *book, guint32 opid, GError *error);
 void		e_data_book_respond_remove			(EDataBook *book, guint32 opid, GError *error);
-void		e_data_book_respond_get_capabilities		(EDataBook *book, guint32 opid, GError *error, const gchar *capabilities);
+void		e_data_book_respond_get_backend_property	(EDataBook *book, guint32 opid, GError *error, const gchar *prop_value);
+void		e_data_book_respond_set_backend_property	(EDataBook *book, guint32 opid, GError *error);
 void		e_data_book_respond_create			(EDataBook *book, guint32 opid, GError *error, const EContact *contact);
 void		e_data_book_respond_remove_contacts		(EDataBook *book, guint32 opid, GError *error, const GSList *ids);
 void		e_data_book_respond_modify			(EDataBook *book, guint32 opid, GError *error, const EContact *contact);
 void		e_data_book_respond_authenticate_user		(EDataBook *book, guint32 opid, GError *error);
-void		e_data_book_respond_get_supported_fields	(EDataBook *book, guint32 opid, GError *error, const GSList *fields);
-void		e_data_book_respond_get_required_fields		(EDataBook *book, guint32 opid, GError *error, const GSList *fields);
-void		e_data_book_respond_get_supported_auth_methods	(EDataBook *book, guint32 opid, GError *error, const GSList *fields);
 void		e_data_book_respond_get_contact			(EDataBook *book, guint32 opid, GError *error, const gchar *vcard);
 void		e_data_book_respond_get_contact_list		(EDataBook *book, guint32 opid, GError *error, const GSList *cards);
 
@@ -129,6 +149,8 @@ void		e_data_book_report_readonly			(EDataBook *book, gboolean readonly);
 void		e_data_book_report_online			(EDataBook *book, gboolean is_online);
 void		e_data_book_report_auth_required		(EDataBook *book, const ECredentials *credentials);
 
+gchar *		e_data_book_string_slist_to_comma_string	(const GSList *strings);
+
 G_END_DECLS
 
 #endif /* __E_DATA_BOOK_H__ */
diff --git a/addressbook/libegdbus/e-gdbus-book.c b/addressbook/libegdbus/e-gdbus-book.c
index c2b3357..97b39c9 100644
--- a/addressbook/libegdbus/e-gdbus-book.c
+++ b/addressbook/libegdbus/e-gdbus-book.c
@@ -55,14 +55,10 @@ enum
 	__REMOVE_CONTACTS_DONE_SIGNAL,
 	__MODIFY_CONTACT_METHOD,
 	__MODIFY_CONTACT_DONE_SIGNAL,
-	__GET_CAPABILITIES_METHOD,
-	__GET_CAPABILITIES_DONE_SIGNAL,
-	__GET_REQUIRED_FIELDS_METHOD,
-	__GET_REQUIRED_FIELDS_DONE_SIGNAL,
-	__GET_SUPPORTED_FIELDS_METHOD,
-	__GET_SUPPORTED_FIELDS_DONE_SIGNAL,
-	__GET_SUPPORTED_AUTH_METHODS_METHOD,
-	__GET_SUPPORTED_AUTH_METHODS_DONE_SIGNAL,
+	__GET_BACKEND_PROPERTY_METHOD,
+	__GET_BACKEND_PROPERTY_DONE_SIGNAL,
+	__SET_BACKEND_PROPERTY_METHOD,
+	__SET_BACKEND_PROPERTY_DONE_SIGNAL,
 	__GET_VIEW_METHOD,
 	__GET_VIEW_DONE_SIGNAL,
 	__CANCEL_OPERATION_METHOD,
@@ -126,10 +122,8 @@ E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV	(GDBUS_BOOK_INTERFACE_NAME,
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_BOOK_INTERFACE_NAME, add_contact)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_BOOK_INTERFACE_NAME, remove_contacts)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_BOOK_INTERFACE_NAME, modify_contact)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_BOOK_INTERFACE_NAME, get_capabilities)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV	(GDBUS_BOOK_INTERFACE_NAME, get_required_fields)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV	(GDBUS_BOOK_INTERFACE_NAME, get_supported_fields)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV	(GDBUS_BOOK_INTERFACE_NAME, get_supported_auth_methods)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_BOOK_INTERFACE_NAME, get_backend_property)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_BOOK_INTERFACE_NAME, set_backend_property)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_BOOK_INTERFACE_NAME, get_view)
 
 static void
@@ -156,10 +150,8 @@ e_gdbus_book_default_init (EGdbusBookIface *iface)
 	E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusBookIface, "addContact",			add_contact, __ADD_CONTACT_METHOD, __ADD_CONTACT_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID	(EGdbusBookIface, "removeContacts",		remove_contacts, __REMOVE_CONTACTS_METHOD, __REMOVE_CONTACTS_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_STRING__VOID	(EGdbusBookIface, "modifyContact",		modify_contact, __MODIFY_CONTACT_METHOD, __MODIFY_CONTACT_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRING	(EGdbusBookIface, "getCapabilities",		get_capabilities, __GET_CAPABILITIES_METHOD, __GET_CAPABILITIES_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRV	(EGdbusBookIface, "getRequiredFields",		get_required_fields, __GET_REQUIRED_FIELDS_METHOD, __GET_REQUIRED_FIELDS_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRV	(EGdbusBookIface, "getSupportedFields",		get_supported_fields, __GET_SUPPORTED_FIELDS_METHOD, __GET_SUPPORTED_FIELDS_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRV	(EGdbusBookIface, "getSupportedAuthMethods",	get_supported_auth_methods, __GET_SUPPORTED_AUTH_METHODS_METHOD, __GET_SUPPORTED_AUTH_METHODS_DONE_SIGNAL)
+	E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusBookIface, "getBackendProperty",		get_backend_property, __GET_BACKEND_PROPERTY_METHOD, __GET_BACKEND_PROPERTY_DONE_SIGNAL)
+	E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID	(EGdbusBookIface, "setBackendProperty",		set_backend_property, __SET_BACKEND_PROPERTY_METHOD, __SET_BACKEND_PROPERTY_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusBookIface, "getView",			get_view, __GET_VIEW_METHOD, __GET_VIEW_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_UINT		(EGdbusBookIface, "cancelOperation",		cancel_operation, __CANCEL_OPERATION_METHOD)
 	E_INIT_GDBUS_METHOD_VOID		(EGdbusBookIface, "cancelAll",			cancel_all, __CANCEL_ALL_METHOD)
@@ -327,83 +319,74 @@ e_gdbus_book_call_modify_contact_sync (GDBusProxy *proxy, const gchar *in_vcard,
 }
 
 void
-e_gdbus_book_call_get_capabilities (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+e_gdbus_book_call_get_backend_property (GDBusProxy *proxy, const gchar *in_prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_gdbus_proxy_call_void ("getCapabilities", e_gdbus_book_call_get_capabilities, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+	e_gdbus_proxy_call_string ("getBackendProperty", e_gdbus_book_call_get_backend_property, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_prop_name, cancellable, callback, user_data);
 }
 
 gboolean
-e_gdbus_book_call_get_capabilities_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_capabilities, GError **error)
+e_gdbus_book_call_get_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_prop_value, GError **error)
 {
-	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_capabilities, error, e_gdbus_book_call_get_capabilities);
+	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_prop_value, error, e_gdbus_book_call_get_backend_property);
 }
 
 gboolean
-e_gdbus_book_call_get_capabilities_sync (GDBusProxy *proxy, gchar **out_capabilities, GCancellable *cancellable, GError **error)
+e_gdbus_book_call_get_backend_property_sync (GDBusProxy *proxy, const gchar *in_prop_name, gchar **out_prop_value, GCancellable *cancellable, GError **error)
 {
-	return e_gdbus_proxy_call_sync_void__string (proxy, out_capabilities, cancellable, error,
-		e_gdbus_book_call_get_capabilities,
-		e_gdbus_book_call_get_capabilities_finish);
+	return e_gdbus_proxy_call_sync_string__string (proxy, in_prop_name, out_prop_value, cancellable, error,
+		e_gdbus_book_call_get_backend_property,
+		e_gdbus_book_call_get_backend_property_finish);
 }
 
-void
-e_gdbus_book_call_get_required_fields (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_book_encode_set_backend_property (const gchar *in_prop_name, const gchar *in_prop_value)
 {
-	e_gdbus_proxy_call_void ("getRequiredFields", e_gdbus_book_call_get_required_fields, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
-}
+	gchar **strv;
 
-gboolean
-e_gdbus_book_call_get_required_fields_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_fields, GError **error)
-{
-	return e_gdbus_proxy_finish_call_strv (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_fields, error, e_gdbus_book_call_get_required_fields);
-}
+	strv = g_new0 (gchar *, 3);
+	strv[0] = e_util_utf8_make_valid (in_prop_name ? in_prop_name : "");
+	strv[1] = e_util_utf8_make_valid (in_prop_value ? in_prop_value : "");
+	strv[2] = NULL;
 
-gboolean
-e_gdbus_book_call_get_required_fields_sync (GDBusProxy *proxy, gchar ***out_fields, GCancellable *cancellable, GError **error)
-{
-	return e_gdbus_proxy_call_sync_void__strv (proxy, out_fields, cancellable, error,
-		e_gdbus_book_call_get_required_fields,
-		e_gdbus_book_call_get_required_fields_finish);
-}
-
-void
-e_gdbus_book_call_get_supported_fields (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
-{
-	e_gdbus_proxy_call_void ("getSupportedFields", e_gdbus_book_call_get_supported_fields, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+	return strv;
 }
 
+/* free out_prop_name and out_prop_value with g_free() */
 gboolean
-e_gdbus_book_call_get_supported_fields_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_fields, GError **error)
+e_gdbus_book_decode_set_backend_property (const gchar * const *in_strv, gchar **out_prop_name, gchar **out_prop_value)
 {
-	return e_gdbus_proxy_finish_call_strv (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_fields, error, e_gdbus_book_call_get_supported_fields);
-}
+	g_return_val_if_fail (in_strv != NULL, FALSE);
+	g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+	g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+	g_return_val_if_fail (in_strv[2] == NULL, FALSE);
+	g_return_val_if_fail (out_prop_name != NULL, FALSE);
+	g_return_val_if_fail (out_prop_value != NULL, FALSE);
 
-gboolean
-e_gdbus_book_call_get_supported_fields_sync (GDBusProxy *proxy, gchar ***out_fields, GCancellable *cancellable, GError **error)
-{
-	return e_gdbus_proxy_call_sync_void__strv (proxy, out_fields, cancellable, error,
-		e_gdbus_book_call_get_supported_fields,
-		e_gdbus_book_call_get_supported_fields_finish);
+	*out_prop_name = g_strdup (in_strv[0]);
+	*out_prop_value = g_strdup (in_strv[1]);
+
+	return TRUE;
 }
 
 void
-e_gdbus_book_call_get_supported_auth_methods (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+e_gdbus_book_call_set_backend_property (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_gdbus_proxy_call_void ("getSupportedAuthMethods", e_gdbus_book_call_get_supported_auth_methods, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+	e_gdbus_proxy_call_strv ("setBackendProperty", e_gdbus_book_call_set_backend_property, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_prop_name_value, cancellable, callback, user_data);
 }
 
 gboolean
-e_gdbus_book_call_get_supported_auth_methods_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_auth_methods, GError **error)
+e_gdbus_book_call_set_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
 {
-	return e_gdbus_proxy_finish_call_strv (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_auth_methods, error, e_gdbus_book_call_get_supported_auth_methods);
+	return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_book_call_set_backend_property);
 }
 
 gboolean
-e_gdbus_book_call_get_supported_auth_methods_sync (GDBusProxy *proxy, gchar ***out_auth_methods, GCancellable *cancellable, GError **error)
+e_gdbus_book_call_set_backend_property_sync (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GError **error)
 {
-	return e_gdbus_proxy_call_sync_void__strv (proxy, out_auth_methods, cancellable, error,
-		e_gdbus_book_call_get_supported_auth_methods,
-		e_gdbus_book_call_get_supported_auth_methods_finish);
+	return e_gdbus_proxy_call_sync_strv__void (proxy, in_prop_name_value, cancellable, error,
+		e_gdbus_book_call_set_backend_property,
+		e_gdbus_book_call_set_backend_property_finish);
 }
 
 void
@@ -502,10 +485,8 @@ DECLARE_EMIT_DONE_SIGNAL_1 (get_contact_list,		__GET_CONTACT_LIST_DONE_SIGNAL, c
 DECLARE_EMIT_DONE_SIGNAL_1 (add_contact,		__ADD_CONTACT_DONE_SIGNAL, const gchar *)
 DECLARE_EMIT_DONE_SIGNAL_0 (remove_contacts,		__REMOVE_CONTACTS_DONE_SIGNAL)
 DECLARE_EMIT_DONE_SIGNAL_0 (modify_contact,		__MODIFY_CONTACT_DONE_SIGNAL)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_capabilities,		__GET_CAPABILITIES_DONE_SIGNAL, const gchar *)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_required_fields,	__GET_REQUIRED_FIELDS_DONE_SIGNAL, const gchar * const *)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_supported_fields,	__GET_SUPPORTED_FIELDS_DONE_SIGNAL, const gchar * const *)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_supported_auth_methods,	__GET_SUPPORTED_AUTH_METHODS_DONE_SIGNAL, const gchar * const *)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_backend_property,	__GET_BACKEND_PROPERTY_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_0 (set_backend_property,	__SET_BACKEND_PROPERTY_DONE_SIGNAL)
 DECLARE_EMIT_DONE_SIGNAL_1 (get_view,			__GET_VIEW_DONE_SIGNAL, const gchar *)
 
 void
@@ -548,10 +529,8 @@ E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(book, getContactList, query, "s", vc
 E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(book, addContact, vcard, "s", uid, "s")
 E_DECLARE_GDBUS_ASYNC_METHOD_1			(book, removeContacts, list, "as")
 E_DECLARE_GDBUS_ASYNC_METHOD_1			(book, modifyContact, vcard, "s")
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(book, getCapabilities, capabilities, "s")
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(book, getRequiredFields, fields, "as")
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(book, getSupportedFields, fields, "as")
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(book, getSupportedAuthMethods, auth_methods, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(book, getBackendProperty, prop_name, "s", prop_value, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1			(book, setBackendProperty, prop_name_value, "as")
 E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(book, getView, query, "s", view, "s")
 
 E_DECLARE_GDBUS_SYNC_METHOD_1			(book, cancelOperation, opid, "u")
@@ -568,10 +547,8 @@ static const GDBusMethodInfo * const e_gdbus_book_method_info_pointers[] =
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, addContact),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, removeContacts),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, modifyContact),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getCapabilities),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getRequiredFields),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getSupportedFields),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getSupportedAuthMethods),
+	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getBackendProperty),
+	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, setBackendProperty),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getView),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, cancelOperation),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (book, cancelAll),
@@ -594,10 +571,8 @@ static const GDBusSignalInfo * const e_gdbus_book_signal_info_pointers[] =
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, addContact_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, removeContacts_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, modifyContact_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getCapabilities_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getRequiredFields_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getSupportedFields_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getSupportedAuthMethods_done),
+	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getBackendProperty_done),
+	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, setBackendProperty_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getView_done),
 	NULL
 };
@@ -801,10 +776,8 @@ e_gdbus_book_proxy_init (EGdbusBookProxy *proxy)
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (add_contact);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID   (remove_contacts);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID   (modify_contact);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_capabilities);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV   (get_required_fields);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV   (get_supported_fields);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV   (get_supported_auth_methods);
+	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_backend_property);
+	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID	  (set_backend_property);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_view);
 }
 
diff --git a/addressbook/libegdbus/e-gdbus-book.h b/addressbook/libegdbus/e-gdbus-book.h
index 98d6da4..6223cce 100644
--- a/addressbook/libegdbus/e-gdbus-book.h
+++ b/addressbook/libegdbus/e-gdbus-book.h
@@ -142,17 +142,11 @@ struct _EGdbusBookIface
 	gboolean (*handle_modify_contact)	(EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_vcard);
 	void	 (*modify_contact_done)		(EGdbusBook *object, guint arg_opid, const GError *arg_error);
 
-	gboolean (*handle_get_capabilities)	(EGdbusBook *object, GDBusMethodInvocation *invocation);
-	void	 (*get_capabilities_done)	(EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar **out_capabilities);
+	gboolean (*handle_get_backend_property)	(EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name);
+	void	 (*get_backend_property_done)	(EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar **out_prop_value);
 
-	gboolean (*handle_get_required_fields)	(EGdbusBook *object, GDBusMethodInvocation *invocation);
-	void	 (*get_required_fields_done)	(EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar ***out_fields);
-
-	gboolean (*handle_get_supported_fields)	(EGdbusBook *object, GDBusMethodInvocation *invocation);
-	void	 (*get_supported_fields_done)	(EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar ***out_fields);
-
-	gboolean (*handle_get_supported_auth_methods) (EGdbusBook *object, GDBusMethodInvocation *invocation);
-	void	 (*get_supported_auth_methods_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar ***out_auth_methods);
+	gboolean (*handle_set_backend_property)	(EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name_value);
+	void	 (*set_backend_property_done)	(EGdbusBook *object, guint arg_opid, const GError *arg_error);
 
 	gboolean (*handle_get_view)		(EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_query);
 	void	 (*get_view_done)		(EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar **out_view);
@@ -198,21 +192,15 @@ void		e_gdbus_book_call_modify_contact (GDBusProxy *proxy, const gchar *in_vcard
 gboolean	e_gdbus_book_call_modify_contact_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
 gboolean	e_gdbus_book_call_modify_contact_sync (GDBusProxy *proxy, const gchar *in_vcard, GCancellable *cancellable, GError **error);
 
-void		e_gdbus_book_call_get_capabilities (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_book_call_get_capabilities_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_capabilities, GError **error);
-gboolean	e_gdbus_book_call_get_capabilities_sync (GDBusProxy *proxy, gchar **out_capabilities, GCancellable *cancellable, GError **error);
-
-void		e_gdbus_book_call_get_required_fields (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_book_call_get_required_fields_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_fields, GError **error);
-gboolean	e_gdbus_book_call_get_required_fields_sync (GDBusProxy *proxy, gchar ***out_fields, GCancellable *cancellable, GError **error);
-
-void		e_gdbus_book_call_get_supported_fields (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_book_call_get_supported_fields_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_fields, GError **error);
-gboolean	e_gdbus_book_call_get_supported_fields_sync (GDBusProxy *proxy, gchar ***out_fields, GCancellable *cancellable, GError **error);
+void		e_gdbus_book_call_get_backend_property (GDBusProxy *proxy, const gchar *in_prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_gdbus_book_call_get_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_prop_value, GError **error);
+gboolean	e_gdbus_book_call_get_backend_property_sync (GDBusProxy *proxy, const gchar *prop_name, gchar **out_prop_value, GCancellable *cancellable, GError **error);
 
-void		e_gdbus_book_call_get_supported_auth_methods (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_book_call_get_supported_auth_methods_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_auth_methods, GError **error);
-gboolean	e_gdbus_book_call_get_supported_auth_methods_sync (GDBusProxy *proxy, gchar ***out_auth_methods, GCancellable *cancellable, GError **error);
+gchar **	e_gdbus_book_encode_set_backend_property (const gchar *in_prop_name, const gchar *in_prop_value);
+gboolean	e_gdbus_book_decode_set_backend_property (const gchar * const *in_strv, gchar **out_prop_name, gchar **out_prop_value);
+void		e_gdbus_book_call_set_backend_property (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_gdbus_book_call_set_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean	e_gdbus_book_call_set_backend_property_sync (GDBusProxy *proxy, const gchar * const *prop_name_value, GCancellable *cancellable, GError **error);
 
 void		e_gdbus_book_call_get_view (GDBusProxy *proxy, const gchar *in_query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
 gboolean	e_gdbus_book_call_get_view_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_view_path, GError **error);
@@ -239,10 +227,8 @@ gboolean	e_gdbus_book_call_close_sync (GDBusProxy *proxy, GCancellable *cancella
 #define e_gdbus_book_complete_add_contact			e_gdbus_complete_async_method
 #define e_gdbus_book_complete_remove_contacts			e_gdbus_complete_async_method
 #define e_gdbus_book_complete_modify_contact			e_gdbus_complete_async_method
-#define e_gdbus_book_complete_get_capabilities			e_gdbus_complete_async_method
-#define e_gdbus_book_complete_get_required_fields		e_gdbus_complete_async_method
-#define e_gdbus_book_complete_get_supported_fields		e_gdbus_complete_async_method
-#define e_gdbus_book_complete_get_supported_auth_methods	e_gdbus_complete_async_method
+#define e_gdbus_book_complete_get_backend_property		e_gdbus_complete_async_method
+#define e_gdbus_book_complete_set_backend_property		e_gdbus_complete_async_method
 #define e_gdbus_book_complete_get_view				e_gdbus_complete_async_method
 #define e_gdbus_book_complete_cancel_operation			e_gdbus_complete_sync_method_void
 #define e_gdbus_book_complete_cancel_all			e_gdbus_complete_sync_method_void
@@ -256,10 +242,8 @@ void e_gdbus_book_emit_get_contact_list_done		(EGdbusBook *object, guint arg_opi
 void e_gdbus_book_emit_add_contact_done			(EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar *out_uid);
 void e_gdbus_book_emit_remove_contacts_done		(EGdbusBook *object, guint arg_opid, const GError *arg_error);
 void e_gdbus_book_emit_modify_contact_done		(EGdbusBook *object, guint arg_opid, const GError *arg_error);
-void e_gdbus_book_emit_get_capabilities_done		(EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar *out_capabilities);
-void e_gdbus_book_emit_get_required_fields_done		(EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar * const *out_fields);
-void e_gdbus_book_emit_get_supported_fields_done	(EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar * const *out_fields);
-void e_gdbus_book_emit_get_supported_auth_methods_done	(EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar * const *out_auth_methods);
+void e_gdbus_book_emit_get_backend_property_done	(EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar *out_prop_value);
+void e_gdbus_book_emit_set_backend_property_done	(EGdbusBook *object, guint arg_opid, const GError *arg_error);
 void e_gdbus_book_emit_get_view_done			(EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar *out_view);
 
 /* D-Bus Signal Emission Helpers */
diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c
index 8403242..aba825c 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -2196,44 +2196,69 @@ get_usermail (ECalBackend *backend)
 /* ************************************************************************* */
 /* ********** ECalBackendSync virtual function implementation *************  */
 
-static void
-caldav_get_cal_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
+static gboolean
+caldav_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
 {
-	*address = get_usermail (E_CAL_BACKEND (backend));
-}
+	gboolean processed = TRUE;
 
-static void
-caldav_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
-{
-	*address = get_usermail (E_CAL_BACKEND (backend));
-}
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
 
-static void
-caldav_get_capabilities (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **capabilities, GError **perror)
-{
-	ESource *source;
-	GString *caps;
-	gchar *usermail;
+	if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAPABILITIES)) {
+		ESource *source;
+		GString *caps;
+		gchar *usermail;
 
-	caps = g_string_new (CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
-			     CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
-			     CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
+		caps = g_string_new (CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
+				     CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
+				     CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
 
-	usermail = get_usermail (E_CAL_BACKEND (backend));
-	if (!usermail || !*usermail)
-		g_string_append (caps, "," CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS);
-	g_free (usermail);
+		usermail = get_usermail (E_CAL_BACKEND (backend));
+		if (!usermail || !*usermail)
+			g_string_append (caps, "," CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS);
+		g_free (usermail);
 
-	source = e_cal_backend_get_source (E_CAL_BACKEND (backend));
-	if (source) {
-		const gchar *prop = e_source_get_property (source, "autoschedule");
+		source = e_cal_backend_get_source (E_CAL_BACKEND (backend));
+		if (source) {
+			const gchar *prop = e_source_get_property (source, "autoschedule");
+
+			if (prop && g_str_equal (prop, "1"))
+				g_string_append (caps, "," CAL_STATIC_CAPABILITY_CREATE_MESSAGES
+						       "," CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+		}
+
+		*prop_value = g_string_free (caps, FALSE);
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+		   g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+		*prop_value = get_usermail (E_CAL_BACKEND (backend));
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+		ECalComponent *comp;
+
+		comp = e_cal_component_new ();
+
+		switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
+		case ICAL_VEVENT_COMPONENT:
+			e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
+			break;
+		case ICAL_VTODO_COMPONENT:
+			e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
+			break;
+		case ICAL_VJOURNAL_COMPONENT:
+			e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
+			break;
+		default:
+			g_object_unref (comp);
+			g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+			return TRUE;
+		}
 
-		if (prop && g_str_equal (prop, "1"))
-			g_string_append (caps, "," CAL_STATIC_CAPABILITY_CREATE_MESSAGES
-					       "," CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+		*prop_value = e_cal_component_get_as_string (comp);
+		g_object_unref (comp);
+	} else {
+		processed = FALSE;
 	}
 
-	*capabilities = g_string_free (caps, FALSE);
+	return processed;
 }
 
 static gboolean
@@ -3968,33 +3993,6 @@ caldav_send_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *canc
 }
 
 static void
-caldav_get_default_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **object, GError **perror)
-{
-	ECalComponent *comp;
-
-	comp = e_cal_component_new ();
-
-	switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
-	case ICAL_VEVENT_COMPONENT:
-		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
-		break;
-	case ICAL_VTODO_COMPONENT:
-		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
-		break;
-	case ICAL_VJOURNAL_COMPONENT:
-		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
-		break;
-	default:
-		g_object_unref (comp);
-		g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
-		return;
-	}
-
-	*object = e_cal_component_get_as_string (comp);
-	g_object_unref (comp);
-}
-
-static void
 caldav_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **perror)
 {
 	ECalBackendCalDAV        *cbdav;
@@ -4565,29 +4563,26 @@ e_cal_backend_caldav_class_init (ECalBackendCalDAVClass *class)
 	object_class->dispose  = e_cal_backend_caldav_dispose;
 	object_class->finalize = e_cal_backend_caldav_finalize;
 
-	sync_class->get_cal_email_address_sync   = caldav_get_cal_email_address;
-	sync_class->get_alarm_email_address_sync = caldav_get_alarm_email_address;
-	sync_class->get_capabilities_sync	 = caldav_get_capabilities;
+	sync_class->get_backend_property_sync	= caldav_get_backend_property;
 
-	sync_class->open_sync                    = caldav_do_open;
-	sync_class->authenticate_user_sync	 = caldav_authenticate_user;
-	sync_class->refresh_sync                 = caldav_refresh;
-	sync_class->remove_sync                  = caldav_remove;
+	sync_class->open_sync			= caldav_do_open;
+	sync_class->authenticate_user_sync	= caldav_authenticate_user;
+	sync_class->refresh_sync		= caldav_refresh;
+	sync_class->remove_sync			= caldav_remove;
 
-	sync_class->create_object_sync = caldav_create_object;
-	sync_class->modify_object_sync = caldav_modify_object;
-	sync_class->remove_object_sync = caldav_remove_object;
+	sync_class->create_object_sync		= caldav_create_object;
+	sync_class->modify_object_sync		= caldav_modify_object;
+	sync_class->remove_object_sync		= caldav_remove_object;
 
-	sync_class->receive_objects_sync      = caldav_receive_objects;
-	sync_class->send_objects_sync         = caldav_send_objects;
-	sync_class->get_default_object_sync   = caldav_get_default_object;
-	sync_class->get_object_sync           = caldav_get_object;
-	sync_class->get_object_list_sync      = caldav_get_object_list;
-	sync_class->add_timezone_sync         = caldav_add_timezone;
-	sync_class->get_free_busy_sync        = caldav_get_free_busy;
+	sync_class->receive_objects_sync	= caldav_receive_objects;
+	sync_class->send_objects_sync		= caldav_send_objects;
+	sync_class->get_object_sync		= caldav_get_object;
+	sync_class->get_object_list_sync	= caldav_get_object_list;
+	sync_class->add_timezone_sync		= caldav_add_timezone;
+	sync_class->get_free_busy_sync		= caldav_get_free_busy;
 
-	backend_class->start_view = caldav_start_view;
-	backend_class->set_online = caldav_set_online;
+	backend_class->start_view		= caldav_start_view;
+	backend_class->set_online		= caldav_set_online;
 
-	backend_class->internal_get_timezone  = caldav_internal_get_timezone;
+	backend_class->internal_get_timezone	= caldav_internal_get_timezone;
 }
diff --git a/calendar/backends/contacts/e-cal-backend-contacts.c b/calendar/backends/contacts/e-cal-backend-contacts.c
index 825c73c..1b276d9 100644
--- a/calendar/backends/contacts/e-cal-backend-contacts.c
+++ b/calendar/backends/contacts/e-cal-backend-contacts.c
@@ -790,30 +790,29 @@ create_anniversary (ECalBackendContacts *cbc, EContact *contact)
 
 /* First the empty stubs */
 
-static void
-e_cal_backend_contacts_get_cal_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
-{
-	/* A contact backend has no particular email address associated
-	 * with it (although that would be a useful feature some day).
-	 */
-	*address = NULL;
-}
-
-static void
-e_cal_backend_contacts_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
-						gchar **address, GError **perror)
+static gboolean
+e_cal_backend_contacts_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
 {
-	/* A contact backend has no particular email address associated
-	 * with it (although that would be a useful feature some day).
-	 */
-	*address = NULL;
-}
+	gboolean processed = TRUE;
+
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAPABILITIES)) {
+		*prop_value = NULL;
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+		   g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+		/* A contact backend has no particular email address associated
+		 * with it (although that would be a useful feature some day).
+		 */
+		*prop_value = NULL;
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+		g_propagate_error (perror, EDC_ERROR (UnsupportedMethod));
+	} else {
+		processed = FALSE;
+	}
 
-static void
-e_cal_backend_contacts_get_capabilities (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
-					gchar **capabilities, GError **perror)
-{
-	*capabilities = NULL;
+	return processed;
 }
 
 static void
@@ -824,13 +823,6 @@ e_cal_backend_contacts_remove (ECalBackendSync *backend, EDataCal *cal, GCancell
 }
 
 static void
-e_cal_backend_contacts_get_default_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
-					   gchar **object, GError **perror)
-{
-	g_propagate_error (perror, EDC_ERROR (UnsupportedMethod));
-}
-
-static void
 e_cal_backend_contacts_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
 				   const gchar *uid, const gchar *rid,
 				   gchar **object, GError **perror)
@@ -1197,22 +1189,18 @@ e_cal_backend_contacts_class_init (ECalBackendContactsClass *class)
 
 	object_class->finalize = e_cal_backend_contacts_finalize;
 
-	sync_class->get_cal_email_address_sync = e_cal_backend_contacts_get_cal_email_address;
-	sync_class->get_alarm_email_address_sync = e_cal_backend_contacts_get_alarm_email_address;
-	sync_class->get_capabilities_sync = e_cal_backend_contacts_get_capabilities;
-	sync_class->open_sync = e_cal_backend_contacts_open;
-	sync_class->remove_sync = e_cal_backend_contacts_remove;
-	sync_class->create_object_sync = e_cal_backend_contacts_create_object;
-	sync_class->receive_objects_sync = e_cal_backend_contacts_receive_objects;
-	sync_class->send_objects_sync = e_cal_backend_contacts_send_objects;
-	sync_class->get_default_object_sync = e_cal_backend_contacts_get_default_object;
-	sync_class->get_object_sync = e_cal_backend_contacts_get_object;
-	sync_class->get_object_list_sync = e_cal_backend_contacts_get_object_list;
-	sync_class->add_timezone_sync = e_cal_backend_contacts_add_timezone;
-	sync_class->get_free_busy_sync = e_cal_backend_contacts_get_free_busy;
-
-	backend_class->start_view = e_cal_backend_contacts_start_view;
-	backend_class->set_online = e_cal_backend_contacts_set_online;
-
-	backend_class->internal_get_timezone = e_cal_backend_contacts_internal_get_timezone;
+	sync_class->get_backend_property_sync	= e_cal_backend_contacts_get_backend_property;
+	sync_class->open_sync			= e_cal_backend_contacts_open;
+	sync_class->remove_sync			= e_cal_backend_contacts_remove;
+	sync_class->create_object_sync		= e_cal_backend_contacts_create_object;
+	sync_class->receive_objects_sync	= e_cal_backend_contacts_receive_objects;
+	sync_class->send_objects_sync		= e_cal_backend_contacts_send_objects;
+	sync_class->get_object_sync		= e_cal_backend_contacts_get_object;
+	sync_class->get_object_list_sync	= e_cal_backend_contacts_get_object_list;
+	sync_class->add_timezone_sync		= e_cal_backend_contacts_add_timezone;
+	sync_class->get_free_busy_sync		= e_cal_backend_contacts_get_free_busy;
+
+	backend_class->start_view		= e_cal_backend_contacts_start_view;
+	backend_class->set_online		= e_cal_backend_contacts_set_online;
+	backend_class->internal_get_timezone	= e_cal_backend_contacts_internal_get_timezone;
 }
diff --git a/calendar/backends/file/e-cal-backend-file.c b/calendar/backends/file/e-cal-backend-file.c
index 270ae11..9a55bbc 100644
--- a/calendar/backends/file/e-cal-backend-file.c
+++ b/calendar/backends/file/e-cal-backend-file.c
@@ -392,31 +392,53 @@ lookup_component (ECalBackendFile *cbfile, const gchar *uid)
 /* Calendar backend methods */
 
 /* Get_email_address handler for the file backend */
-static void
-e_cal_backend_file_get_cal_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
-{
-	/* A file backend has no particular email address associated
-	 * with it (although that would be a useful feature some day).
-	 */
-	*address = NULL;
-}
+static gboolean
+e_cal_backend_file_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
+{
+	gboolean processed = TRUE;
+
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAPABILITIES)) {
+		*prop_value = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
+					CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
+					CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED ","
+					CAL_STATIC_CAPABILITY_NO_THISANDPRIOR);
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+		   g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+		/* A file backend has no particular email address associated
+		 * with it (although that would be a useful feature some day).
+		 */
+		*prop_value = NULL;
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+		ECalComponent *comp;
 
-static void
-e_cal_backend_file_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
-{
-	/* A file backend has no particular email address associated
-	 * with it (although that would be a useful feature some day).
-	 */
-	*address = NULL;
-}
+		comp = e_cal_component_new ();
 
-static void
-e_cal_backend_file_get_capabilities (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **capabilities, GError **perror)
-{
-	*capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
-				  CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
-				  CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED ","
-				  CAL_STATIC_CAPABILITY_NO_THISANDPRIOR);
+		switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
+		case ICAL_VEVENT_COMPONENT:
+			e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
+			break;
+		case ICAL_VTODO_COMPONENT:
+			e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
+			break;
+		case ICAL_VJOURNAL_COMPONENT:
+			e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
+			break;
+		default:
+			g_object_unref (comp);
+			g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+			return TRUE;
+		}
+
+		*prop_value = e_cal_component_get_as_string (comp);
+		g_object_unref (comp);
+	} else {
+		processed = FALSE;
+	}
+
+	return processed;
 }
 
 /* function to resolve timezones */
@@ -1356,33 +1378,6 @@ e_cal_backend_file_set_online (ECalBackend *backend, gboolean is_online)
 }
 
 static void
-e_cal_backend_file_get_default_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **object, GError **perror)
-{
-	ECalComponent *comp;
-
-	comp = e_cal_component_new ();
-
-	switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
-	case ICAL_VEVENT_COMPONENT:
-		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
-		break;
-	case ICAL_VTODO_COMPONENT:
-		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
-		break;
-	case ICAL_VJOURNAL_COMPONENT:
-		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
-		break;
-	default:
-		g_object_unref (comp);
-		g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
-		return;
-	}
-
-	*object = e_cal_component_get_as_string (comp);
-	g_object_unref (comp);
-}
-
-static void
 add_detached_recur_to_vcalendar (gpointer key, gpointer value, gpointer user_data)
 {
 	ECalComponent *recurrence = value;
@@ -3079,27 +3074,23 @@ e_cal_backend_file_class_init (ECalBackendFileClass *class)
 	object_class->finalize = e_cal_backend_file_finalize;
 	object_class->constructed = cal_backend_file_constructed;
 
-	sync_class->get_cal_email_address_sync = e_cal_backend_file_get_cal_email_address;
-	sync_class->get_alarm_email_address_sync = e_cal_backend_file_get_alarm_email_address;
-	sync_class->get_capabilities_sync = e_cal_backend_file_get_capabilities;
-	sync_class->open_sync = e_cal_backend_file_open;
-	sync_class->remove_sync = e_cal_backend_file_remove;
-	sync_class->create_object_sync = e_cal_backend_file_create_object;
-	sync_class->modify_object_sync = e_cal_backend_file_modify_object;
-	sync_class->remove_object_sync = e_cal_backend_file_remove_object;
-	sync_class->receive_objects_sync = e_cal_backend_file_receive_objects;
-	sync_class->send_objects_sync = e_cal_backend_file_send_objects;
-	sync_class->get_default_object_sync = e_cal_backend_file_get_default_object;
-	sync_class->get_object_sync = e_cal_backend_file_get_object;
-	sync_class->get_object_list_sync = e_cal_backend_file_get_object_list;
-	sync_class->get_attachment_uris_sync = e_cal_backend_file_get_attachment_uris;
-	sync_class->add_timezone_sync = e_cal_backend_file_add_timezone;
-	sync_class->get_free_busy_sync = e_cal_backend_file_get_free_busy;
-
-	backend_class->start_view = e_cal_backend_file_start_view;
-	backend_class->set_online = e_cal_backend_file_set_online;
-
-	backend_class->internal_get_timezone = e_cal_backend_file_internal_get_timezone;
+	sync_class->get_backend_property_sync	= e_cal_backend_file_get_backend_property;
+	sync_class->open_sync			= e_cal_backend_file_open;
+	sync_class->remove_sync			= e_cal_backend_file_remove;
+	sync_class->create_object_sync		= e_cal_backend_file_create_object;
+	sync_class->modify_object_sync		= e_cal_backend_file_modify_object;
+	sync_class->remove_object_sync		= e_cal_backend_file_remove_object;
+	sync_class->receive_objects_sync	= e_cal_backend_file_receive_objects;
+	sync_class->send_objects_sync		= e_cal_backend_file_send_objects;
+	sync_class->get_object_sync		= e_cal_backend_file_get_object;
+	sync_class->get_object_list_sync	= e_cal_backend_file_get_object_list;
+	sync_class->get_attachment_uris_sync	= e_cal_backend_file_get_attachment_uris;
+	sync_class->add_timezone_sync		= e_cal_backend_file_add_timezone;
+	sync_class->get_free_busy_sync		= e_cal_backend_file_get_free_busy;
+
+	backend_class->start_view		= e_cal_backend_file_start_view;
+	backend_class->set_online		= e_cal_backend_file_set_online;
+	backend_class->internal_get_timezone	= e_cal_backend_file_internal_get_timezone;
 }
 
 void
diff --git a/calendar/backends/groupwise/e-cal-backend-groupwise.c b/calendar/backends/groupwise/e-cal-backend-groupwise.c
index f72e2f2..9717140 100644
--- a/calendar/backends/groupwise/e-cal-backend-groupwise.c
+++ b/calendar/backends/groupwise/e-cal-backend-groupwise.c
@@ -1247,53 +1247,75 @@ e_cal_backend_groupwise_finalize (GObject *object)
 
 /* Calendar backend methods */
 
-/* return email address of the person who opened the calendar */
-static void
-e_cal_backend_groupwise_get_cal_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
+static gboolean
+e_cal_backend_groupwise_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
 {
-	ECalBackendGroupwise *cbgw;
-	ECalBackendGroupwisePrivate *priv;
-
-	cbgw = E_CAL_BACKEND_GROUPWISE (backend);
-	priv = cbgw->priv;
-
-	if (priv->is_online) {
-		if (priv->user_email)
-			g_free (priv->user_email);
+	gboolean processed = TRUE;
+
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAPABILITIES)) {
+		*prop_value = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
+					CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY ","
+					CAL_STATIC_CAPABILITY_REMOVE_ALARMS ","
+					CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
+					CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
+					CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK ","
+					CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR ","
+					CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS ","
+					CAL_STATIC_CAPABILITY_SAVE_SCHEDULES ","
+					CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT ","
+					CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED ","
+					CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY ","
+					CAL_STATIC_CAPABILITY_NO_ORGANIZER ","
+					CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER ","
+					CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING ","
+					CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)) {
+		/* return email address of the person who opened the calendar */
+		ECalBackendGroupwise *cbgw;
+		ECalBackendGroupwisePrivate *priv;
+
+		cbgw = E_CAL_BACKEND_GROUPWISE (backend);
+		priv = cbgw->priv;
+
+		if (priv->is_online) {
+			if (priv->user_email)
+				g_free (priv->user_email);
+
+			priv->user_email = g_strdup (e_gw_connection_get_user_email (cbgw->priv->cnc));
+		}
 
-		priv->user_email = g_strdup (e_gw_connection_get_user_email (cbgw->priv->cnc));
-	}
+		*prop_value = g_strdup (priv->user_email);
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+		/* group wise does not support email based alarms */
+		*prop_value = NULL;
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+		ECalComponent *comp;
 
-	*address = g_strdup (priv->user_email);
-}
+		comp = e_cal_component_new ();
 
-static void
-e_cal_backend_groupwise_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
-{
-	/*group wise does not support email based alarms */
+		switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
+		case ICAL_VEVENT_COMPONENT:
+			e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
+			break;
+		case ICAL_VTODO_COMPONENT:
+			e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
+			break;
+		default:
+			g_object_unref (comp);
+			g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+			return TRUE;
+		}
 
-	*address = NULL;
-}
+		*prop_value = e_cal_component_get_as_string (comp);
+		g_object_unref (comp);
+	} else {
+		processed = FALSE;
+	}
 
-static void
-e_cal_backend_groupwise_get_capabilities (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **capabilities, GError **perror)
-{
-	*capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
-				  CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY ","
-				  CAL_STATIC_CAPABILITY_REMOVE_ALARMS ","
-				  CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
-				  CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
-				  CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK ","
-				  CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR ","
-				  CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS ","
-				  CAL_STATIC_CAPABILITY_SAVE_SCHEDULES ","
-				  CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT ","
-				  CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED ","
-				  CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY ","
-				  CAL_STATIC_CAPABILITY_NO_ORGANIZER ","
-				  CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER ","
-				  CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING ","
-				  CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+	return processed;
 }
 
 static void
@@ -1464,31 +1486,6 @@ e_cal_backend_groupwise_set_online (ECalBackend *backend, gboolean is_online)
 	PRIV_UNLOCK (priv);
 }
 
-static void
-e_cal_backend_groupwise_get_default_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **object, GError **perror)
-{
-
-	ECalComponent *comp;
-
-	comp = e_cal_component_new ();
-
-	switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
-	case ICAL_VEVENT_COMPONENT:
-		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
-		break;
-	case ICAL_VTODO_COMPONENT:
-		e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
-		break;
-	default:
-		g_object_unref (comp);
-		g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
-		return;
-	}
-
-	*object = e_cal_component_get_as_string (comp);
-	g_object_unref (comp);
-}
-
 /* Get_object_component handler for the groupwise backend */
 static void
 e_cal_backend_groupwise_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **error)
@@ -2605,27 +2602,24 @@ e_cal_backend_groupwise_class_init (ECalBackendGroupwiseClass *class)
 
 	object_class->finalize = e_cal_backend_groupwise_finalize;
 
-	sync_class->get_cal_email_address_sync = e_cal_backend_groupwise_get_cal_email_address;
-	sync_class->get_alarm_email_address_sync = e_cal_backend_groupwise_get_alarm_email_address;
-	sync_class->get_capabilities_sync = e_cal_backend_groupwise_get_capabilities;
-	sync_class->open_sync = e_cal_backend_groupwise_open;
-	sync_class->authenticate_user_sync = e_cal_backend_groupwise_authenticate_user;
-	sync_class->remove_sync = e_cal_backend_groupwise_remove;
-	sync_class->create_object_sync = e_cal_backend_groupwise_create_object;
-	sync_class->modify_object_sync = e_cal_backend_groupwise_modify_object;
-	sync_class->remove_object_sync = e_cal_backend_groupwise_remove_object;
-	sync_class->receive_objects_sync = e_cal_backend_groupwise_receive_objects;
-	sync_class->send_objects_sync = e_cal_backend_groupwise_send_objects;
-	sync_class->get_default_object_sync = e_cal_backend_groupwise_get_default_object;
-	sync_class->get_object_sync = e_cal_backend_groupwise_get_object;
-	sync_class->get_object_list_sync = e_cal_backend_groupwise_get_object_list;
-	sync_class->get_attachment_uris_sync = e_cal_backend_groupwise_get_attachment_uris;
-	sync_class->add_timezone_sync = e_cal_backend_groupwise_add_timezone;
-	sync_class->get_free_busy_sync = e_cal_backend_groupwise_get_free_busy;
-
-	backend_class->start_view = e_cal_backend_groupwise_start_view;
-	backend_class->set_online = e_cal_backend_groupwise_set_online;
-	backend_class->internal_get_timezone = e_cal_backend_groupwise_internal_get_timezone;
+	sync_class->get_backend_property_sync	= e_cal_backend_groupwise_get_backend_property;
+	sync_class->open_sync			= e_cal_backend_groupwise_open;
+	sync_class->authenticate_user_sync	= e_cal_backend_groupwise_authenticate_user;
+	sync_class->remove_sync			= e_cal_backend_groupwise_remove;
+	sync_class->create_object_sync		= e_cal_backend_groupwise_create_object;
+	sync_class->modify_object_sync		= e_cal_backend_groupwise_modify_object;
+	sync_class->remove_object_sync		= e_cal_backend_groupwise_remove_object;
+	sync_class->receive_objects_sync	= e_cal_backend_groupwise_receive_objects;
+	sync_class->send_objects_sync		= e_cal_backend_groupwise_send_objects;
+	sync_class->get_object_sync		= e_cal_backend_groupwise_get_object;
+	sync_class->get_object_list_sync	= e_cal_backend_groupwise_get_object_list;
+	sync_class->get_attachment_uris_sync	= e_cal_backend_groupwise_get_attachment_uris;
+	sync_class->add_timezone_sync		= e_cal_backend_groupwise_add_timezone;
+	sync_class->get_free_busy_sync		= e_cal_backend_groupwise_get_free_busy;
+
+	backend_class->start_view		= e_cal_backend_groupwise_start_view;
+	backend_class->set_online		= e_cal_backend_groupwise_set_online;
+	backend_class->internal_get_timezone	= e_cal_backend_groupwise_internal_get_timezone;
 }
 
 void
diff --git a/calendar/backends/http/e-cal-backend-http.c b/calendar/backends/http/e-cal-backend-http.c
index 44d9016..f9cf520 100644
--- a/calendar/backends/http/e-cal-backend-http.c
+++ b/calendar/backends/http/e-cal-backend-http.c
@@ -155,31 +155,36 @@ e_cal_backend_http_finalize (GObject *object)
 
 /* Calendar backend methods */
 
-static void
-e_cal_backend_http_get_cal_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
+static gboolean
+e_cal_backend_http_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
 {
-	/* A HTTP backend has no particular email address associated
-	 * with it (although that would be a useful feature some day).
-	 */
-	*address = NULL;
-}
+	gboolean processed = TRUE;
+
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAPABILITIES)) {
+		*prop_value = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
+					CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+		   g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+		/* A HTTP backend has no particular email address associated
+		 * with it (although that would be a useful feature some day).
+		 */
+		*prop_value = NULL;
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+		icalcomponent *icalcomp;
+		icalcomponent_kind kind;
+
+		kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
+		icalcomp = e_cal_util_new_component (kind);
+		*prop_value = icalcomponent_as_ical_string_r (icalcomp);
+		icalcomponent_free (icalcomp);
+	} else {
+		processed = FALSE;
+	}
 
-static void
-e_cal_backend_http_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
-{
-	/* A HTTP backend has no particular email address associated
-	 * with it (although that would be a useful feature some day).
-	 */
-	*address = NULL;
-}
-
-static void
-e_cal_backend_http_get_capabilities (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **capabilities, GError **perror)
-{
-	*capabilities = g_strdup (
-		CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
-		CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED
-		);
+	return processed;
 }
 
 static gchar *
@@ -862,18 +867,6 @@ e_cal_backend_http_set_online (ECalBackend *backend, gboolean is_online)
 		e_cal_backend_notify_online (backend, priv->is_online);
 }
 
-static void
-e_cal_backend_http_get_default_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **object, GError **perror)
-{
-	icalcomponent *icalcomp;
-	icalcomponent_kind kind;
-
-	kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
-	icalcomp = e_cal_util_new_component (kind);
-	*object = icalcomponent_as_ical_string_r (icalcomp);
-	icalcomponent_free (icalcomp);
-}
-
 /* Get_object_component handler for the http backend */
 static void
 e_cal_backend_http_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **error)
@@ -1304,26 +1297,22 @@ e_cal_backend_http_class_init (ECalBackendHttpClass *class)
 	object_class->dispose = e_cal_backend_http_dispose;
 	object_class->finalize = e_cal_backend_http_finalize;
 
-	sync_class->get_cal_email_address_sync = e_cal_backend_http_get_cal_email_address;
-	sync_class->get_alarm_email_address_sync = e_cal_backend_http_get_alarm_email_address;
-	sync_class->get_capabilities_sync = e_cal_backend_http_get_capabilities;
-	sync_class->open_sync = e_cal_backend_http_open;
-	sync_class->authenticate_user_sync = e_cal_backend_http_authenticate_user;
-	sync_class->refresh_sync = e_cal_backend_http_refresh;
-	sync_class->remove_sync = e_cal_backend_http_remove;
-	sync_class->create_object_sync = e_cal_backend_http_create_object;
-	sync_class->modify_object_sync = e_cal_backend_http_modify_object;
-	sync_class->remove_object_sync = e_cal_backend_http_remove_object;
-	sync_class->receive_objects_sync = e_cal_backend_http_receive_objects;
-	sync_class->send_objects_sync = e_cal_backend_http_send_objects;
-	sync_class->get_default_object_sync = e_cal_backend_http_get_default_object;
-	sync_class->get_object_sync = e_cal_backend_http_get_object;
-	sync_class->get_object_list_sync = e_cal_backend_http_get_object_list;
-	sync_class->add_timezone_sync = e_cal_backend_http_add_timezone;
-	sync_class->get_free_busy_sync = e_cal_backend_http_get_free_busy;
-
-	backend_class->start_view = e_cal_backend_http_start_view;
-	backend_class->set_online = e_cal_backend_http_set_online;
-
-	backend_class->internal_get_timezone = e_cal_backend_http_internal_get_timezone;
+	sync_class->get_backend_property_sync	= e_cal_backend_http_get_backend_property;
+	sync_class->open_sync			= e_cal_backend_http_open;
+	sync_class->authenticate_user_sync	= e_cal_backend_http_authenticate_user;
+	sync_class->refresh_sync		= e_cal_backend_http_refresh;
+	sync_class->remove_sync			= e_cal_backend_http_remove;
+	sync_class->create_object_sync		= e_cal_backend_http_create_object;
+	sync_class->modify_object_sync		= e_cal_backend_http_modify_object;
+	sync_class->remove_object_sync		= e_cal_backend_http_remove_object;
+	sync_class->receive_objects_sync	= e_cal_backend_http_receive_objects;
+	sync_class->send_objects_sync		= e_cal_backend_http_send_objects;
+	sync_class->get_object_sync		= e_cal_backend_http_get_object;
+	sync_class->get_object_list_sync	= e_cal_backend_http_get_object_list;
+	sync_class->add_timezone_sync		= e_cal_backend_http_add_timezone;
+	sync_class->get_free_busy_sync		= e_cal_backend_http_get_free_busy;
+
+	backend_class->start_view		= e_cal_backend_http_start_view;
+	backend_class->set_online		= e_cal_backend_http_set_online;
+	backend_class->internal_get_timezone	= e_cal_backend_http_internal_get_timezone;
 }
diff --git a/calendar/backends/weather/e-cal-backend-weather.c b/calendar/backends/weather/e-cal-backend-weather.c
index 6fe42fc..db652e0 100644
--- a/calendar/backends/weather/e-cal-backend-weather.c
+++ b/calendar/backends/weather/e-cal-backend-weather.c
@@ -452,31 +452,34 @@ create_weather (ECalBackendWeather *cbw, WeatherInfo *report, gboolean is_foreca
 	return cal_comp;
 }
 
-static void
-e_cal_backend_weather_get_cal_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
-{
-	/* Weather has no particular email addresses associated with it */
-	*address = NULL;
-}
-
-static void
-e_cal_backend_weather_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **perror)
+static gboolean
+e_cal_backend_weather_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
 {
-	/* Weather has no particular email addresses associated with it */
-	*address = NULL;
-}
+	gboolean processed = TRUE;
+
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAPABILITIES)) {
+		*prop_value = g_strdup (CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT ","
+					CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS ","
+					CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS ","
+					CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS ","
+					CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT ","
+					CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
+					CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
+					CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+		   g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+		/* Weather has no particular email addresses associated with it */
+		*prop_value = NULL;
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+		g_propagate_error (perror, EDC_ERROR (UnsupportedMethod));
+	} else {
+		processed = FALSE;
+	}
 
-static void
-e_cal_backend_weather_get_capabilities (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **capabilities, GError **perror)
-{
-	*capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT ","
-				  CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS  ","
-				  CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS  ","
-				  CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS  ","
-				  CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT  ","
-				  CAL_STATIC_CAPABILITY_NO_THISANDFUTURE  ","
-				  CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
-				  CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
+	return processed;
 }
 
 static void
@@ -569,12 +572,6 @@ e_cal_backend_weather_receive_objects (ECalBackendSync *backend, EDataCal *cal,
 }
 
 static void
-e_cal_backend_weather_get_default_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **object, GError **perror)
-{
-	g_propagate_error (perror, EDC_ERROR (UnsupportedMethod));
-}
-
-static void
 e_cal_backend_weather_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **error)
 {
 	ECalBackendWeather *cbw = E_CAL_BACKEND_WEATHER (backend);
@@ -870,20 +867,17 @@ e_cal_backend_weather_class_init (ECalBackendWeatherClass *class)
 
 	object_class->finalize = e_cal_backend_weather_finalize;
 
-	sync_class->get_cal_email_address_sync = e_cal_backend_weather_get_cal_email_address;
-	sync_class->get_alarm_email_address_sync = e_cal_backend_weather_get_alarm_email_address;
-	sync_class->get_capabilities_sync = e_cal_backend_weather_get_capabilities;
-	sync_class->open_sync = e_cal_backend_weather_open;
-	sync_class->refresh_sync = e_cal_backend_weather_refresh;
-	sync_class->remove_sync = e_cal_backend_weather_remove;
-	sync_class->receive_objects_sync = e_cal_backend_weather_receive_objects;
-	sync_class->get_default_object_sync = e_cal_backend_weather_get_default_object;
-	sync_class->get_object_sync = e_cal_backend_weather_get_object;
-	sync_class->get_object_list_sync = e_cal_backend_weather_get_object_list;
-	sync_class->add_timezone_sync = e_cal_backend_weather_add_timezone;
-	sync_class->get_free_busy_sync = e_cal_backend_weather_get_free_busy;
-	backend_class->start_view = e_cal_backend_weather_start_view;
-	backend_class->set_online = e_cal_backend_weather_set_online;
-
-	backend_class->internal_get_timezone = e_cal_backend_weather_internal_get_timezone;
+	sync_class->get_backend_property_sync	= e_cal_backend_weather_get_backend_property;
+	sync_class->open_sync			= e_cal_backend_weather_open;
+	sync_class->refresh_sync		= e_cal_backend_weather_refresh;
+	sync_class->remove_sync			= e_cal_backend_weather_remove;
+	sync_class->receive_objects_sync	= e_cal_backend_weather_receive_objects;
+	sync_class->get_object_sync		= e_cal_backend_weather_get_object;
+	sync_class->get_object_list_sync	= e_cal_backend_weather_get_object_list;
+	sync_class->add_timezone_sync		= e_cal_backend_weather_add_timezone;
+	sync_class->get_free_busy_sync		= e_cal_backend_weather_get_free_busy;
+
+	backend_class->start_view		= e_cal_backend_weather_start_view;
+	backend_class->set_online		= e_cal_backend_weather_set_online;
+	backend_class->internal_get_timezone	= e_cal_backend_weather_internal_get_timezone;
 }
diff --git a/calendar/libecal/e-cal-client.c b/calendar/libecal/e-cal-client.c
index a7dd348..bd95a3f 100644
--- a/calendar/libecal/e-cal-client.c
+++ b/calendar/libecal/e-cal-client.c
@@ -28,6 +28,7 @@
 #include <gio/gio.h>
 
 #include "libedataserver/e-data-server-util.h"
+#include "libedataserver/e-client-private.h"
 
 #include "libedata-cal/e-data-cal-types.h"
 
@@ -65,6 +66,30 @@ static guint signals[LAST_SIGNAL];
 G_DEFINE_TYPE (ECalClient, e_cal_client, E_TYPE_CLIENT)
 
 /**
+ * Well-known calendar backend properties:
+ * @CAL_BACKEND_PROPERTY_LOADED: Is set to "TRUE" or "FALSE" depending
+ *   on the backend's loaded state.
+ * @CAL_BACKEND_PROPERTY_ONLINE: Is set to "TRUE" or "FALSE" depending
+ *   on the backend's loaded state. See also e_client_is_online().
+ * @CAL_BACKEND_PROPERTY_READONLY: Is set to "TRUE" or "FALSE" depending
+ *   on the backend's readonly state. See also e_client_is_readonly().
+ * @CAL_BACKEND_PROPERTY_CACHE_DIR: Local folder with cached data used
+ *   by the backend.
+ * @CAL_BACKEND_PROPERTY_CAPABILITIES: Retrieves comma-separated list
+ *   of	capabilities supported by the backend. Preferred method of retreiving
+ *   and working with capabilities is e_client_get_capabilities() and
+ *   e_client_check_capability().
+ * @CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS: Contains default calendar's email
+ *   address suggested by the backend.
+ * @CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS: Contains default alarm email
+ *   address suggested by the backend.
+ * @CAL_BACKEND_PROPERTY_DEFAULT_OBJECT: Contains iCal component string
+ *   of an #icalcomponent with the default values for properties needed.
+ *   Preferred way of retrieving this property is by
+ *   calling e_cal_client_get_default_object().
+ **/
+
+/**
  * e_cal_client_source_type_enum_get_type:
  *
  * Registers the #ECalClientSourceTypeEnum type with glib.
@@ -913,7 +938,7 @@ e_cal_client_get_local_attachment_store (ECalClient *client)
 	if (client->priv->cache_dir || !client->priv->gdbus_cal)
 		return client->priv->cache_dir;
 
-	e_gdbus_cal_call_get_cache_dir_sync (client->priv->gdbus_cal, &cache_dir, NULL, &error);
+	e_gdbus_cal_call_get_backend_property_sync (client->priv->gdbus_cal, CAL_BACKEND_PROPERTY_CACHE_DIR, &cache_dir, NULL, &error);
 
 	if (error == NULL) {
 		client->priv->cache_dir = cache_dir;
@@ -1781,21 +1806,21 @@ e_cal_client_get_component_as_string (ECalClient *client, icalcomponent *icalcom
 }
 
 static void
-cal_client_open (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+cal_client_get_backend_property (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_client_proxy_call_boolean (client, only_if_exists, cancellable, callback, user_data, cal_client_open,
-			e_gdbus_cal_call_open,
-			e_gdbus_cal_call_open_finish, NULL, NULL, NULL, NULL);
+	e_client_proxy_call_string (client, prop_name, cancellable, callback, user_data, cal_client_get_backend_property,
+			e_gdbus_cal_call_get_backend_property,
+			NULL, NULL, e_gdbus_cal_call_get_backend_property_finish, NULL, NULL);
 }
 
 static gboolean
-cal_client_open_finish (EClient *client, GAsyncResult *result, GError **error)
+cal_client_get_backend_property_finish (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error)
 {
-	return e_client_proxy_call_finish_void (client, result, error, cal_client_open);
+	return e_client_proxy_call_finish_string (client, result, prop_value, error, cal_client_get_backend_property);
 }
 
 static gboolean
-cal_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error)
+cal_client_get_backend_property_sync (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error)
 {
 	ECalClient *cal_client;
 
@@ -1811,27 +1836,35 @@ cal_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *ca
 		return FALSE;
 	}
 
-	return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_cal_call_open_sync);
+	return e_client_proxy_call_sync_string__string (client, prop_name, prop_value, cancellable, error, e_gdbus_cal_call_get_backend_property_sync);
 }
 
 static void
-cal_client_remove (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+cal_client_set_backend_property (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_client_proxy_call_void (client, cancellable, callback, user_data, cal_client_remove,
-			e_gdbus_cal_call_remove,
-			e_gdbus_cal_call_remove_finish, NULL, NULL, NULL, NULL);
+	gchar **prop_name_value;
+
+	prop_name_value = e_gdbus_cal_encode_set_backend_property (prop_name, prop_value);
+
+	e_client_proxy_call_strv (client, (const gchar * const *) prop_name_value, cancellable, callback, user_data, cal_client_set_backend_property,
+			e_gdbus_cal_call_set_backend_property,
+			e_gdbus_cal_call_set_backend_property_finish, NULL, NULL, NULL, NULL);
+
+	g_strfreev (prop_name_value);
 }
 
 static gboolean
-cal_client_remove_finish (EClient *client, GAsyncResult *result, GError **error)
+cal_client_set_backend_property_finish (EClient *client, GAsyncResult *result, GError **error)
 {
-	return e_client_proxy_call_finish_void (client, result, error, cal_client_remove);
+	return e_client_proxy_call_finish_void (client, result, error, cal_client_set_backend_property);
 }
 
 static gboolean
-cal_client_remove_sync (EClient *client, GCancellable *cancellable, GError **error)
+cal_client_set_backend_property_sync (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error)
 {
 	ECalClient *cal_client;
+	gboolean res;
+	gchar **prop_name_value;
 
 	g_return_val_if_fail (client != NULL, FALSE);
 	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
@@ -1845,113 +1878,79 @@ cal_client_remove_sync (EClient *client, GCancellable *cancellable, GError **err
 		return FALSE;
 	}
 
-	return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_cal_call_remove_sync);
+	prop_name_value = e_gdbus_cal_encode_set_backend_property (prop_name, prop_value);
+	res = e_client_proxy_call_sync_strv__void (client, (const gchar * const *) prop_name_value, cancellable, error, e_gdbus_cal_call_set_backend_property_sync);
+	g_strfreev (prop_name_value);
+
+	return res;
 }
 
+static void
+cal_client_open (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+	e_client_proxy_call_boolean (client, only_if_exists, cancellable, callback, user_data, cal_client_open,
+			e_gdbus_cal_call_open,
+			e_gdbus_cal_call_open_finish, NULL, NULL, NULL, NULL);
+}
 
-/**
- * e_cal_client_get_capabilities:
- * @client: an #ECalClient
- * @cancellable: a #GCancellable; can be %NULL
- * @callback: callback to call when a result is ready
- * @user_data: user data for the @callback
- *
- * Starts retrieval of the list of capabilities which the backend for this calendar
- * supports. The call is finished by e_cal_client_get_capabilities_finish() from
- * the @callback.
- *
- * Note: Usually is sufficient to use e_client_get_capabilities() or e_client_check_capability(),
- * which caches capabilities of a backend on the client side.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_get_capabilities (ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+static gboolean
+cal_client_open_finish (EClient *client, GAsyncResult *result, GError **error)
 {
-	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data, e_cal_client_get_capabilities,
-			e_gdbus_cal_call_get_capabilities,
-			NULL, NULL, e_gdbus_cal_call_get_capabilities_finish, NULL, NULL);
+	return e_client_proxy_call_finish_void (client, result, error, cal_client_open);
 }
 
-/**
- * e_cal_client_get_capabilities_finish:
- * @client: an #ECalClient
- * @result: a #GAsyncResult
- * @capabilities: (out): list of strings with capabilities
- * @error: (out): a #GError to set an error, if any
- *
- * Finishes previous call of e_cal_client_get_capabilities() and
- * sets @capabilities to a list of strings of backend capabilities.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_get_capabilities_finish (ECalClient *client, GAsyncResult *result, GSList **capabilities, GError **error)
+static gboolean
+cal_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error)
 {
-	gboolean res;
-	gchar *out_string = NULL;
+	ECalClient *cal_client;
 
-	g_return_val_if_fail (capabilities != NULL, FALSE);
+	g_return_val_if_fail (client != NULL, FALSE);
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
 
-	res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_cal_client_get_capabilities);
+	cal_client = E_CAL_CLIENT (client);
+	g_return_val_if_fail (cal_client != NULL, FALSE);
+	g_return_val_if_fail (cal_client->priv != NULL, FALSE);
 
-	if (res && out_string)
-		*capabilities = e_client_util_parse_capabilities (out_string);
-	else
-		*capabilities = NULL;
+	if (!cal_client->priv->gdbus_cal) {
+		set_proxy_gone_error (error);
+		return FALSE;
+	}
 
-	g_free (out_string);
+	return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_cal_call_open_sync);
+}
 
-	return res;
+static void
+cal_client_remove (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+	e_client_proxy_call_void (client, cancellable, callback, user_data, cal_client_remove,
+			e_gdbus_cal_call_remove,
+			e_gdbus_cal_call_remove_finish, NULL, NULL, NULL, NULL);
 }
 
-/**
- * e_cal_client_get_capabilities_sync:
- * @client: an #ECalClient
- * @capabilities: (out): list of strings with capabilities
- * @cancellable: a #GCancellable; can be %NULL
- * @error: (out): a #GError to set an error, if any
- *
- * Retrieves a list of capabilities which the backend for this calendar
- * supports and sets @capabilities to that list.
- * This list should be freed with e_client_util_free_string_slist().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Note: Usually is sufficient to use e_client_get_capabilities() or e_client_check_capability(),
- * which caches capabilities of a backend on the client side.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_get_capabilities_sync (ECalClient *client, GSList **capabilities, GCancellable *cancellable, GError **error)
+static gboolean
+cal_client_remove_finish (EClient *client, GAsyncResult *result, GError **error)
 {
-	gboolean res;
-	gchar *out_string = NULL;
+	return e_client_proxy_call_finish_void (client, result, error, cal_client_remove);
+}
+
+static gboolean
+cal_client_remove_sync (EClient *client, GCancellable *cancellable, GError **error)
+{
+	ECalClient *cal_client;
 
 	g_return_val_if_fail (client != NULL, FALSE);
 	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
-	g_return_val_if_fail (client->priv != NULL, FALSE);
-	g_return_val_if_fail (capabilities != NULL, FALSE);
 
-	if (!client->priv->gdbus_cal) {
+	cal_client = E_CAL_CLIENT (client);
+	g_return_val_if_fail (cal_client != NULL, FALSE);
+	g_return_val_if_fail (cal_client->priv != NULL, FALSE);
+
+	if (!cal_client->priv->gdbus_cal) {
 		set_proxy_gone_error (error);
 		return FALSE;
 	}
 
-	res = e_client_proxy_call_sync_void__string (E_CLIENT (client), &out_string, cancellable, error, e_gdbus_cal_call_get_capabilities_sync);
-
-	if (res && out_string)
-		*capabilities = e_client_util_parse_capabilities (out_string);
-	else
-		*capabilities = NULL;
-
-	g_free (out_string);
-
-	return res;
+	return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_cal_call_remove_sync);
 }
 
 static gboolean
@@ -1980,174 +1979,6 @@ complete_string_exchange (gboolean res, gchar *out_string, gchar **result, GErro
 }
 
 /**
- * e_cal_client_get_cal_email_address:
- * @client: an #ECalClient
- * @cancellable: a #GCancellable; can be %NULL
- * @callback: callback to call when a result is ready
- * @user_data: user data for the @callback
- *
- * Queries the calendar address associated with a calendar client.
- * The call is finished by e_cal_client_get_cal_email_address_finish() from
- * the @callback.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_get_cal_email_address (ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
-{
-	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data, e_cal_client_get_cal_email_address,
-			e_gdbus_cal_call_get_cal_email_address,
-			NULL, NULL, e_gdbus_cal_call_get_cal_email_address_finish, NULL, NULL);
-}
-
-/**
- * e_cal_client_get_cal_email_address_finish:
- * @client: an #ECalClient
- * @result: a #GAsyncResult
- * @address: (out): Calendar's e-mail address
- * @error: (out): a #GError to set an error, if any
- *
- * Finishes previous call of e_cal_client_get_cal_email_address() and
- * sets @address the calendar address associated with a calendar client.
- * This address should be freed with g_free().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_get_cal_email_address_finish (ECalClient *client, GAsyncResult *result, gchar **address, GError **error)
-{
-	gboolean res;
-	gchar *out_string = NULL;
-
-	g_return_val_if_fail (address != NULL, FALSE);
-
-	res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_cal_client_get_cal_email_address);
-
-	return complete_string_exchange (res, out_string, address, error);
-}
-
-/**
- * e_cal_client_get_cal_email_address_sync:
- * @client: an #ECalClient
- * @address: (out): Calendar's e-mail address
- * @cancellable: a #GCancellable; can be %NULL
- * @error: (out): a #GError to set an error, if any
- *
- * Queries the calendar address associated with a calendar client.
- * This address should be freed with g_free().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_get_cal_email_address_sync (ECalClient *client, gchar **address, GCancellable *cancellable, GError **error)
-{
-	gboolean res;
-	gchar *out_string = NULL;
-
-	g_return_val_if_fail (client != NULL, FALSE);
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
-	g_return_val_if_fail (client->priv != NULL, FALSE);
-	g_return_val_if_fail (address != NULL, FALSE);
-
-	if (!client->priv->gdbus_cal) {
-		set_proxy_gone_error (error);
-		return FALSE;
-	}
-
-	res = e_client_proxy_call_sync_void__string (E_CLIENT (client), &out_string, cancellable, error, e_gdbus_cal_call_get_cal_email_address_sync);
-
-	return complete_string_exchange (res, out_string, address, error);
-}
-
-/**
- * e_cal_client_get_alarm_email_address:
- * @client: an #ECalClient
- * @cancellable: a #GCancellable; can be %NULL
- * @callback: callback to call when a result is ready
- * @user_data: user data for the @callback
- *
- * Queries the address to be used for alarms in a calendar client.
- * The call is finished by e_cal_client_get_alarm_email_address_finish() from
- * the @callback.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_get_alarm_email_address (ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
-{
-	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data, e_cal_client_get_alarm_email_address,
-			e_gdbus_cal_call_get_alarm_email_address,
-			NULL, NULL, e_gdbus_cal_call_get_alarm_email_address_finish, NULL, NULL);
-}
-
-/**
- * e_cal_client_get_alarm_email_address_finish:
- * @client: an #ECalClient
- * @result: a #GAsyncResult
- * @address: (out): Calendar's e-mail address for alarms
- * @error: (out): a #GError to set an error, if any
- *
- * Finishes previous call of e_cal_client_get_alarm_email_address() and
- * sets @addressto the address to be used for alarms in a calendar client.
- * This address should be freed with g_free().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_get_alarm_email_address_finish (ECalClient *client, GAsyncResult *result, gchar **address, GError **error)
-{
-	gboolean res;
-	gchar *out_string = NULL;
-
-	g_return_val_if_fail (address != NULL, FALSE);
-
-	res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_cal_client_get_alarm_email_address);
-
-	return complete_string_exchange (res, out_string, address, error);
-}
-
-/**
- * e_cal_client_get_alarm_email_address_sync:
- * @client: an #ECalClient
- * @address: (out): Calendar's e-mail address for alarms
- * @cancellable: a #GCancellable; can be %NULL
- * @error: (out): a #GError to set an error, if any
- *
- * Queries the address to be used for alarms in a calendar client.
- * This address should be freed with g_free().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_get_alarm_email_address_sync (ECalClient *client, gchar **address, GCancellable *cancellable, GError **error)
-{
-	gboolean res;
-	gchar *out_string = NULL;
-
-	g_return_val_if_fail (client != NULL, FALSE);
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
-	g_return_val_if_fail (client->priv != NULL, FALSE);
-	g_return_val_if_fail (address != NULL, FALSE);
-
-	if (!client->priv->gdbus_cal) {
-		set_proxy_gone_error (error);
-		return FALSE;
-	}
-
-	res = e_client_proxy_call_sync_void__string (E_CLIENT (client), &out_string, cancellable, error, e_gdbus_cal_call_get_alarm_email_address_sync);
-
-	return complete_string_exchange (res, out_string, address, error);
-}
-
-/**
  * e_cal_client_get_default_object:
  * @client: an #ECalClient
  * @cancellable: a #GCancellable; can be %NULL
@@ -2163,9 +1994,9 @@ e_cal_client_get_alarm_email_address_sync (ECalClient *client, gchar **address,
 void
 e_cal_client_get_default_object (ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data, e_cal_client_get_default_object,
-			e_gdbus_cal_call_get_default_object,
-			NULL, NULL, e_gdbus_cal_call_get_default_object_finish, NULL, NULL);
+	e_client_proxy_call_string (E_CLIENT (client), CAL_BACKEND_PROPERTY_DEFAULT_OBJECT, cancellable, callback, user_data, e_cal_client_get_default_object,
+			e_gdbus_cal_call_get_backend_property,
+			NULL, NULL, e_gdbus_cal_call_get_backend_property_finish, NULL, NULL);
 }
 
 static gboolean
@@ -2249,7 +2080,7 @@ e_cal_client_get_default_object_sync (ECalClient *client, icalcomponent **icalco
 		return FALSE;
 	}
 
-	res = e_client_proxy_call_sync_void__string (E_CLIENT (client), &out_string, cancellable, error, e_gdbus_cal_call_get_default_object_sync);
+	res = e_client_proxy_call_sync_string__string (E_CLIENT (client), CAL_BACKEND_PROPERTY_DEFAULT_OBJECT, &out_string, cancellable, error, e_gdbus_cal_call_get_backend_property_sync);
 
 	return complete_get_object (res, out_string, icalcomp, error);
 }
@@ -4163,7 +3994,7 @@ cal_client_retrieve_capabilities (EClient *client)
 	if (!cal_client->priv->gdbus_cal)
 		return NULL;
 
-	e_gdbus_cal_call_get_capabilities_sync (cal_client->priv->gdbus_cal, &capabilities, NULL, &error);
+	e_gdbus_cal_call_get_backend_property_sync (cal_client->priv->gdbus_cal, CAL_BACKEND_PROPERTY_CAPABILITIES, &capabilities, NULL, &error);
 
 	if (error) {
 		g_debug ("%s: Failed to retrieve capabilitites: %s", G_STRFUNC, error->message);
@@ -4260,16 +4091,22 @@ e_cal_client_class_init (ECalClientClass *klass)
 	object_class->finalize = cal_client_finalize;
 
 	client_class = E_CLIENT_CLASS (klass);
-	client_class->get_dbus_proxy = cal_client_get_dbus_proxy;
-	client_class->unwrap_dbus_error = cal_client_unwrap_dbus_error;
-	client_class->handle_authentication = cal_client_handle_authentication;
-	client_class->retrieve_capabilities = cal_client_retrieve_capabilities;
-	client_class->open = cal_client_open;
-	client_class->open_finish = cal_client_open_finish;
-	client_class->open_sync = cal_client_open_sync;
-	client_class->remove = cal_client_remove;
-	client_class->remove_finish = cal_client_remove_finish;
-	client_class->remove_sync = cal_client_remove_sync;
+	client_class->get_dbus_proxy			= cal_client_get_dbus_proxy;
+	client_class->unwrap_dbus_error			= cal_client_unwrap_dbus_error;
+	client_class->handle_authentication		= cal_client_handle_authentication;
+	client_class->retrieve_capabilities		= cal_client_retrieve_capabilities;
+	client_class->get_backend_property		= cal_client_get_backend_property;
+	client_class->get_backend_property_finish	= cal_client_get_backend_property_finish;
+	client_class->get_backend_property_sync		= cal_client_get_backend_property_sync;
+	client_class->set_backend_property		= cal_client_set_backend_property;
+	client_class->set_backend_property_finish	= cal_client_set_backend_property_finish;
+	client_class->set_backend_property_sync		= cal_client_set_backend_property_sync;
+	client_class->open				= cal_client_open;
+	client_class->open_finish			= cal_client_open_finish;
+	client_class->open_sync				= cal_client_open_sync;
+	client_class->remove				= cal_client_remove;
+	client_class->remove_finish			= cal_client_remove_finish;
+	client_class->remove_sync			= cal_client_remove_sync;
 
 	signals[FREE_BUSY_DATA] = g_signal_new (
 		"free-busy-data",
diff --git a/calendar/libecal/e-cal-client.h b/calendar/libecal/e-cal-client.h
index 02f0397..4f38284 100644
--- a/calendar/libecal/e-cal-client.h
+++ b/calendar/libecal/e-cal-client.h
@@ -30,6 +30,8 @@
 #include <libecal/e-cal-util.h>
 #include <libecal/e-cal-view.h>
 
+G_BEGIN_DECLS
+
 #define E_TYPE_CAL_CLIENT		(e_cal_client_get_type ())
 #define E_CAL_CLIENT(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_CAL_CLIENT, ECalClient))
 #define E_CAL_CLIENT_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_CAL_CLIENT, ECalClientClass))
@@ -37,7 +39,14 @@
 #define E_IS_CAL_CLIENT_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_CAL_CLIENT))
 #define E_CAL_CLIENT_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CAL_CLIENT, ECalClientClass))
 
-G_BEGIN_DECLS
+#define CAL_BACKEND_PROPERTY_LOADED			"loaded"
+#define CAL_BACKEND_PROPERTY_ONLINE			"online"
+#define CAL_BACKEND_PROPERTY_READONLY			"readonly"
+#define CAL_BACKEND_PROPERTY_CACHE_DIR			"cache-dir"
+#define CAL_BACKEND_PROPERTY_CAPABILITIES		"capabilities"
+#define CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS		"cal-email-address"
+#define CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS	"alarm-email-address"
+#define CAL_BACKEND_PROPERTY_DEFAULT_OBJECT		"default-object"
 
 typedef enum {
 	E_CAL_CLIENT_SOURCE_TYPE_EVENT,
@@ -117,18 +126,6 @@ void		e_cal_client_generate_instances_for_object	(ECalClient *client, icalcompon
 gchar *		e_cal_client_get_component_as_string		(ECalClient *client, icalcomponent *icalcomp);
 
 /* Calendar methods */
-void		e_cal_client_get_capabilities			(ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_cal_client_get_capabilities_finish		(ECalClient *client, GAsyncResult *result, GSList **capabilities, GError **error);
-gboolean	e_cal_client_get_capabilities_sync		(ECalClient *client, GSList **capabilities, GCancellable *cancellable, GError **error);
-
-void		e_cal_client_get_cal_email_address		(ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_cal_client_get_cal_email_address_finish	(ECalClient *client, GAsyncResult *result, gchar **address, GError **error);
-gboolean	e_cal_client_get_cal_email_address_sync		(ECalClient *client, gchar **address, GCancellable *cancellable, GError **error);
-
-void		e_cal_client_get_alarm_email_address		(ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_cal_client_get_alarm_email_address_finish	(ECalClient *client, GAsyncResult *result, gchar **address, GError **error);
-gboolean	e_cal_client_get_alarm_email_address_sync	(ECalClient *client, gchar **address, GCancellable *cancellable, GError **error);
-
 void		e_cal_client_get_default_object			(ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
 gboolean	e_cal_client_get_default_object_finish		(ECalClient *client, GAsyncResult *result, icalcomponent **icalcomp, GError **error);
 gboolean	e_cal_client_get_default_object_sync		(ECalClient *client, icalcomponent **icalcomp, GCancellable *cancellable, GError **error);
diff --git a/calendar/libecal/e-cal.c b/calendar/libecal/e-cal.c
index 9b1a942..eee4375 100644
--- a/calendar/libecal/e-cal.c
+++ b/calendar/libecal/e-cal.c
@@ -59,6 +59,12 @@
 #include "e-gdbus-cal-view.h"
 #include "e-gdbus-cal-factory.h"
 
+#define CAL_BACKEND_PROPERTY_CACHE_DIR			"cache-dir"
+#define CAL_BACKEND_PROPERTY_CAPABILITIES		"capabilities"
+#define CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS		"cal-email-address"
+#define CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS	"alarm-email-address"
+#define CAL_BACKEND_PROPERTY_DEFAULT_OBJECT		"default-object"
+
 static guint active_cals = 0, cal_connection_closed_id = 0;
 static EGdbusCalFactory *cal_factory_proxy = NULL;
 static GStaticRecMutex cal_factory_proxy_lock = G_STATIC_REC_MUTEX_INIT;
@@ -1077,8 +1083,8 @@ set_local_attachment_store (ECal *ecal)
 	gchar *cache_dir = NULL;
 	GError *error = NULL;
 
-	e_gdbus_cal_call_get_cache_dir_sync (
-		ecal->priv->gdbus_cal, &cache_dir, NULL, &error);
+	e_gdbus_cal_call_get_backend_property_sync (
+		ecal->priv->gdbus_cal, CAL_BACKEND_PROPERTY_CACHE_DIR, &cache_dir, NULL, &error);
 
 	if (error == NULL)
 		ecal->priv->local_attachment_store = cache_dir;
@@ -1995,7 +2001,8 @@ e_cal_is_read_only (ECal *ecal, gboolean *read_only, GError **error)
  * Returns: TRUE if the operation was successful, FALSE if there
  * was an error.
  *
- * Deprecated: 3.2: Use e_cal_client_get_cal_email_address_sync() instead.
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync()
+ * with #CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS instead.
  **/
 gboolean
 e_cal_get_cal_address (ECal *ecal, gchar **cal_address, GError **error)
@@ -2016,7 +2023,7 @@ e_cal_get_cal_address (ECal *ecal, gchar **cal_address, GError **error)
 			E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 		}
 
-		if (!e_gdbus_cal_call_get_cal_email_address_sync (priv->gdbus_cal, &priv->cal_address, NULL, error)) {
+		if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS, &priv->cal_address, NULL, error)) {
 			UNLOCK_CACHE ();
 			E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 		}
@@ -2039,7 +2046,8 @@ e_cal_get_cal_address (ECal *ecal, gchar **cal_address, GError **error)
  * Returns: TRUE if the operation was successful, FALSE if there was
  * an error while contacting the backend.
  *
- * Deprecated: 3.2: Use e_cal_client_get_alarm_email_address_sync() instead.
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync()
+ * with #CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS instead.
  */
 gboolean
 e_cal_get_alarm_email_address (ECal *ecal, gchar **alarm_address, GError **error)
@@ -2056,7 +2064,7 @@ e_cal_get_alarm_email_address (ECal *ecal, gchar **alarm_address, GError **error
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_get_alarm_email_address_sync (priv->gdbus_cal, alarm_address, NULL, error)) {
+	if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS, alarm_address, NULL, error)) {
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
@@ -2109,7 +2117,7 @@ load_capabilities (ECal *ecal, GError **error)
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
 	}
 
-	if (!e_gdbus_cal_call_get_capabilities_sync (priv->gdbus_cal, &priv->capabilities, NULL, error)) {
+	if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_CAPABILITIES, &priv->capabilities, NULL, error)) {
 		UNLOCK_CACHE ();
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
@@ -2344,7 +2352,7 @@ e_cal_get_default_object (ECal *ecal, icalcomponent **icalcomp, GError **error)
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
 	}
 
-	if (!e_gdbus_cal_call_get_default_object_sync (priv->gdbus_cal, &object, NULL, error)) {
+	if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT, &object, NULL, error)) {
 		E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
 	}
 
diff --git a/calendar/libedata-cal/e-cal-backend-sync.c b/calendar/libedata-cal/e-cal-backend-sync.c
index 52264bf..29f6984 100644
--- a/calendar/libedata-cal/e-cal-backend-sync.c
+++ b/calendar/libedata-cal/e-cal-backend-sync.c
@@ -21,14 +21,24 @@ struct _ECalBackendSyncPrivate {
 	gboolean mutex_lock;
 };
 
-#define LOCK_WRAPPER(func, args) G_STMT_START {				\
-	gboolean locked = backend->priv->mutex_lock;			\
-	g_return_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func);\
-	if (locked)							\
-		g_mutex_lock (backend->priv->sync_mutex);		\
-	(* E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func) args;		\
-	if (locked)							\
-		g_mutex_unlock (backend->priv->sync_mutex);		\
+#define LOCK_WRAPPER(func, args) G_STMT_START {									\
+	gboolean locked = backend->priv->mutex_lock;								\
+	e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func, NotSupported);		\
+	if (locked)												\
+		g_mutex_lock (backend->priv->sync_mutex);							\
+	(* E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func) args;							\
+	if (locked)												\
+		g_mutex_unlock (backend->priv->sync_mutex);							\
+	} G_STMT_END
+
+#define LOCK_WRAPPER_RET_VAL(func, args) G_STMT_START {								\
+	gboolean locked = backend->priv->mutex_lock;								\
+	e_return_data_cal_error_val_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func, NotSupported);	\
+	if (locked)												\
+		g_mutex_lock (backend->priv->sync_mutex);							\
+	res = (* E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func) args;						\
+	if (locked)												\
+		g_mutex_unlock (backend->priv->sync_mutex);							\
 	} G_STMT_END
 
 /**
@@ -126,79 +136,65 @@ e_cal_backend_sync_refresh  (ECalBackendSync *backend, EDataCal *cal, GCancellab
 }
 
 /**
- * e_cal_backend_sync_get_capabilities:
+ * e_cal_backend_sync_get_backend_property:
  * @backend: An ECalBackendSync object.
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
- * @capabilities: Return value for comma-separated list of capabilities.
+ * @prop_name: Property name whose value to retrieve.
+ * @prop_value: Return value of the @prop_name.
  * @error: Out parameter for a #GError.
  *
- * Calls the get_capabilities_sync method on the given backend.
- */
-void
-e_cal_backend_sync_get_capabilities (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **capabilities, GError **error)
+ * Calls the get_backend_property_sync method on the given backend.
+ *
+ * Returns whether processed this property. Returning FALSE means to pass
+ * the call to the ECalBackend parent class, thus neither @error should be
+ * set in this case.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_backend_sync_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
 {
-	e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
-	e_return_data_cal_error_if_fail (capabilities, InvalidArg);
+	gboolean res = FALSE;
 
-	LOCK_WRAPPER (get_capabilities_sync, (backend, cal, cancellable, capabilities, error));
-}
+	e_return_data_cal_error_val_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
+	e_return_data_cal_error_val_if_fail (prop_name, InvalidArg);
+	e_return_data_cal_error_val_if_fail (prop_value, InvalidArg);
 
-/**
- * e_cal_backend_sync_get_cal_email_address:
- * @backend: An ECalBackendSync object.
- * @cal: An EDataCal object.
- * @cancellable: a #GCancellable for the operation
- * @address: Return value for the address.
- * @error: Out parameter for a #GError.
- *
- * Calls the get_cal_email_address_sync method on the given backend.
- */
-void
-e_cal_backend_sync_get_cal_email_address  (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **error)
-{
-	e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
-	e_return_data_cal_error_if_fail (address, InvalidArg);
+	LOCK_WRAPPER_RET_VAL (get_backend_property_sync, (backend, cal, cancellable, prop_name, prop_value, error));
 
-	LOCK_WRAPPER (get_cal_email_address_sync, (backend, cal, cancellable, address, error));
+	return res;
 }
 
 /**
- * e_cal_backend_sync_get_alarm_email_address:
+ * e_cal_backend_sync_set_backend_property:
  * @backend: An ECalBackendSync object.
  * @cal: An EDataCal object.
  * @cancellable: a #GCancellable for the operation
- * @address: Return value for the address.
+ * @prop_name: Property name to set.
+ * @prop_value: New value of the @prop_name.
  * @error: Out parameter for a #GError.
  *
- * Calls the get_alarm_email_address_sync method on the given backend.
- */
-void
-e_cal_backend_sync_get_alarm_email_address  (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **error)
+ * Calls the set_backend_property_sync method on the given backend.
+ *
+ * Returns whether processed this property. Returning FALSE means to pass
+ * the call to the ECalBackend parent class, thus neither @error should be
+ * set in this case.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_backend_sync_set_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error)
 {
-	e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
-	e_return_data_cal_error_if_fail (address, InvalidArg);
+	gboolean res = FALSE;
 
-	LOCK_WRAPPER (get_alarm_email_address_sync, (backend, cal, cancellable, address, error));
-}
+	e_return_data_cal_error_val_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
+	e_return_data_cal_error_val_if_fail (prop_name, InvalidArg);
+	e_return_data_cal_error_val_if_fail (prop_value, InvalidArg);
 
-/**
- * e_cal_backend_sync_get_default_object:
- * @backend: An ECalBackendSync object.
- * @cal: An EDataCal object.
- * @cancellable: a #GCancellable for the operation
- * @calobj: Placeholder for returned object.
- * @error: Out parameter for a #GError.
- *
- * Calls the get_default_object_sync method on the given backend.
- */
-void
-e_cal_backend_sync_get_default_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **calobj, GError **error)
-{
-	e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
-	e_return_data_cal_error_if_fail (calobj, InvalidArg);
+	LOCK_WRAPPER_RET_VAL (set_backend_property_sync, (backend, cal, cancellable, prop_name, prop_value, error));
 
-	LOCK_WRAPPER (get_default_object_sync, (backend, cal, cancellable, calobj, error));
+	return res;
 }
 
 /**
@@ -510,55 +506,28 @@ cal_backend_refresh (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancell
 }
 
 static void
-cal_backend_get_capabilities (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
+cal_backend_get_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
 {
 	GError *error = NULL;
-	gchar *capabilities = NULL;
+	gchar *prop_value = NULL;
 
-	e_cal_backend_sync_get_capabilities (E_CAL_BACKEND_SYNC (backend), cal, cancellable, &capabilities, &error);
+	if (e_cal_backend_sync_get_backend_property (E_CAL_BACKEND_SYNC (backend), cal, cancellable, prop_name, &prop_value, &error))
+		e_data_cal_respond_get_backend_property (cal, opid, error, prop_value);
+	else
+		(* E_CAL_BACKEND_CLASS (e_cal_backend_sync_parent_class)->get_backend_property) (backend, cal, opid, cancellable, prop_name);
 
-	e_data_cal_respond_get_capabilities (cal, opid, error, capabilities);
-
-	g_free (capabilities);
+	g_free (prop_value);
 }
 
 static void
-cal_backend_get_cal_email_address (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
+cal_backend_set_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
 {
 	GError *error = NULL;
-	gchar *address = NULL;
-
-	e_cal_backend_sync_get_cal_email_address (E_CAL_BACKEND_SYNC (backend), cal, cancellable, &address, &error);
 
-	e_data_cal_respond_get_cal_email_address (cal, opid, error, address);
-
-	g_free (address);
-}
-
-static void
-cal_backend_get_alarm_email_address (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
-{
-	GError *error = NULL;
-	gchar *address = NULL;
-
-	e_cal_backend_sync_get_alarm_email_address (E_CAL_BACKEND_SYNC (backend), cal, cancellable, &address, &error);
-
-	e_data_cal_respond_get_alarm_email_address (cal, opid, error, address);
-
-	g_free (address);
-}
-
-static void
-cal_backend_get_default_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
-{
-	GError *error = NULL;
-	gchar *calobj = NULL;
-
-	e_cal_backend_sync_get_default_object (E_CAL_BACKEND_SYNC (backend), cal, cancellable, &calobj, &error);
-
-	e_data_cal_respond_get_default_object (cal, opid, error, calobj);
-
-	g_free (calobj);
+	if (e_cal_backend_sync_set_backend_property (E_CAL_BACKEND_SYNC (backend), cal, cancellable, prop_name, prop_value, &error))
+		e_data_cal_respond_set_backend_property (cal, opid, error);
+	else
+		(* E_CAL_BACKEND_CLASS (e_cal_backend_sync_parent_class)->set_backend_property) (backend, cal, opid, cancellable, prop_name, prop_value);
 }
 
 static void
@@ -799,6 +768,20 @@ cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
 	return zone;
 }
 
+static gboolean
+cal_backend_sync_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
+{
+	/* to indicate to pass to the ECalBackend parent class */
+	return FALSE;
+}
+
+static gboolean
+cal_backend_sync_set_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error)
+{
+	/* to indicate to pass to the ECalBackend parent class */
+	return FALSE;
+}
+
 static void
 e_cal_backend_sync_init (ECalBackendSync *backend)
 {
@@ -841,10 +824,8 @@ e_cal_backend_sync_class_init (ECalBackendSyncClass *klass)
 	backend_class->authenticate_user	= cal_backend_authenticate_user;
 	backend_class->remove			= cal_backend_remove;
 	backend_class->refresh			= cal_backend_refresh;
-	backend_class->get_capabilities		= cal_backend_get_capabilities;
-	backend_class->get_cal_email_address	= cal_backend_get_cal_email_address;
-	backend_class->get_alarm_email_address	= cal_backend_get_alarm_email_address;
-	backend_class->get_default_object	= cal_backend_get_default_object;
+	backend_class->get_backend_property	= cal_backend_get_backend_property;
+	backend_class->set_backend_property	= cal_backend_set_backend_property;
 	backend_class->get_object		= cal_backend_get_object;
 	backend_class->get_object_list		= cal_backend_get_object_list;
 	backend_class->get_free_busy		= cal_backend_get_free_busy;
@@ -857,4 +838,7 @@ e_cal_backend_sync_class_init (ECalBackendSyncClass *klass)
 	backend_class->get_timezone		= cal_backend_get_timezone;
 	backend_class->add_timezone		= cal_backend_add_timezone;
 	backend_class->internal_get_timezone	= cal_backend_internal_get_timezone;
+
+	klass->get_backend_property_sync	= cal_backend_sync_get_backend_property;
+	klass->set_backend_property_sync	= cal_backend_sync_set_backend_property;
 }
diff --git a/calendar/libedata-cal/e-cal-backend-sync.h b/calendar/libedata-cal/e-cal-backend-sync.h
index 1b3fec7..d0bb5ed 100644
--- a/calendar/libedata-cal/e-cal-backend-sync.h
+++ b/calendar/libedata-cal/e-cal-backend-sync.h
@@ -36,10 +36,8 @@ struct _ECalBackendSyncClass {
 	void	(* remove_sync)			(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error);
 
 	void	(* refresh_sync)		(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error);
-	void	(* get_capabilities_sync)	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **capabilities, GError **error);
-	void	(* get_cal_email_address_sync)	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **error);
-	void	(* get_alarm_email_address_sync)(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **error);
-	void	(* get_default_object_sync)	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **calobj, GError **error);
+	gboolean (* get_backend_property_sync)	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error);
+	gboolean (* set_backend_property_sync)	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error);
 	void	(* get_object_sync)		(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **calobj, GError **error);
 	void	(* get_object_list_sync)	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp, GSList **calobjs, GError **error);
 	void	(* get_free_busy_sync)		(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users, time_t start, time_t end, GSList **freebusyobjs, GError **error);
@@ -61,10 +59,8 @@ void	e_cal_backend_sync_open			(ECalBackendSync *backend, EDataCal *cal, GCancel
 void	e_cal_backend_sync_authenticate_user	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, ECredentials *credentials, GError **error);
 void	e_cal_backend_sync_remove		(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error);
 void	e_cal_backend_sync_refresh		(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error);
-void	e_cal_backend_sync_get_capabilities	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **capabilities, GError **error);
-void	e_cal_backend_sync_get_cal_email_address(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **error);
-void	e_cal_backend_sync_get_alarm_email_address(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **address, GError **error);
-void	e_cal_backend_sync_get_default_object	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gchar **calobj, GError **error);
+gboolean e_cal_backend_sync_get_backend_property(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error);
+gboolean e_cal_backend_sync_set_backend_property(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error);
 void	e_cal_backend_sync_get_object		(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **calobj, GError **error);
 void	e_cal_backend_sync_get_object_list	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp, GSList **calobjs, GError **error);
 void	e_cal_backend_sync_get_free_busy	(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users, time_t start, time_t end, GSList **freebusyobjs, GError **error);
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index 55222fc..453f676 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -22,9 +22,8 @@
  */
 
 #include <config.h>
-#include <libxml/parser.h>
-#include <libxml/parserInternals.h>
-#include <libxml/xmlmemory.h>
+
+#include <glib/gi18n-lib.h>
 
 #include <libedataserver/e-data-server-util.h>
 
@@ -186,6 +185,38 @@ cal_backend_set_kind (ECalBackend *backend,
 }
 
 static void
+cal_backend_get_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
+{
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (E_IS_CAL_BACKEND (backend));
+	g_return_if_fail (cal != NULL);
+	g_return_if_fail (prop_name != NULL);
+
+	if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_LOADED)) {
+		e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_loaded (backend) ? "TRUE" : "FALSE");
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ONLINE)) {
+		e_data_cal_respond_get_backend_property (cal, opid, NULL, backend->priv->online ? "TRUE" : "FALSE");
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_READONLY)) {
+		e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_readonly (backend) ? "TRUE" : "FALSE");
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CACHE_DIR)) {
+		e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_get_cache_dir (backend));
+	} else {
+		e_data_cal_respond_get_backend_property (cal, opid, e_data_cal_create_error_fmt (NotSupported, _("Unknown calendar property '%s'"), prop_name), NULL);
+	}
+}
+
+static void
+cal_backend_set_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
+{
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (E_IS_CAL_BACKEND (backend));
+	g_return_if_fail (cal != NULL);
+	g_return_if_fail (prop_name != NULL);
+
+	e_data_cal_respond_set_backend_property (cal, opid, e_data_cal_create_error_fmt (NotSupported, _("Cannot change value of calendar property '%s'"), prop_name));
+}
+
+static void
 cal_backend_set_property (GObject *object,
                           guint property_id,
                           const GValue *value,
@@ -286,18 +317,21 @@ cal_backend_constructed (GObject *object)
 }
 
 static void
-e_cal_backend_class_init (ECalBackendClass *class)
+e_cal_backend_class_init (ECalBackendClass *klass)
 {
 	GObjectClass *object_class;
 
-	g_type_class_add_private (class, sizeof (ECalBackendPrivate));
+	g_type_class_add_private (klass, sizeof (ECalBackendPrivate));
 
-	object_class = G_OBJECT_CLASS (class);
+	object_class = G_OBJECT_CLASS (klass);
 	object_class->set_property = cal_backend_set_property;
 	object_class->get_property = cal_backend_get_property;
 	object_class->finalize = cal_backend_finalize;
 	object_class->constructed = cal_backend_constructed;
 
+	klass->get_backend_property = cal_backend_get_backend_property;
+	klass->set_backend_property = cal_backend_set_backend_property;
+
 	g_object_class_install_property (
 		object_class,
 		PROP_CACHE_DIR,
@@ -345,7 +379,7 @@ e_cal_backend_class_init (ECalBackendClass *class)
 
 	signals[LAST_CLIENT_GONE] = g_signal_new (
 		"last_client_gone",
-		G_TYPE_FROM_CLASS (class),
+		G_TYPE_FROM_CLASS (klass),
 		G_SIGNAL_RUN_FIRST,
 		G_STRUCT_OFFSET (ECalBackendClass, last_client_gone),
 		NULL, NULL,
@@ -539,25 +573,61 @@ e_cal_backend_set_cache_dir (ECalBackend *backend,
 	g_object_notify (G_OBJECT (backend), "cache-dir");
 }
 
+/**
+ * e_cal_backend_get_backend_property:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to get value of; cannot be NULL
+ *
+ * Calls the get_backend_property method on the given backend.
+ * This might be finished with e_data_cal_respond_get_backend_property().
+ * Default implementation takes care of common properties and returns
+ * an 'unsupported' error for any unknown properties. The subclass may
+ * always call this default implementation for properties which fetching
+ * it doesn't overwrite.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_backend_get_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
+{
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (E_IS_CAL_BACKEND (backend));
+	g_return_if_fail (prop_name != NULL);
+	g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property != NULL);
+
+	(* E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property) (backend, cal, opid, cancellable, prop_name);
+}
 
 /**
- * e_cal_backend_get_capabilities:
+ * e_cal_backend_set_backend_property:
  * @backend: an #ECalBackend
  * @cal: an #EDataCal
  * @opid: the ID to use for this operation
  * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to change; cannot be NULL
+ * @prop_value: value to set to @prop_name; cannot be NULL
+ *
+ * Calls the set_backend_property method on the given backend.
+ * This might be finished with e_data_cal_respond_set_backend_property().
+ * Default implementation simply returns an 'unsupported' error.
+ * The subclass may always call this default implementation for properties
+ * which fetching it doesn't overwrite.
  *
- * Calls the get_capabilities method on the given backend.
- * This might be finished with e_data_cal_respond_get_capabilities().
+ * Since: 3.2
  **/
 void
-e_cal_backend_get_capabilities (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
+e_cal_backend_set_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
 {
 	g_return_if_fail (backend != NULL);
 	g_return_if_fail (E_IS_CAL_BACKEND (backend));
-	g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_capabilities != NULL);
+	g_return_if_fail (prop_name != NULL);
+	g_return_if_fail (prop_value != NULL);
+	g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property != NULL);
 
-	(* E_CAL_BACKEND_GET_CLASS (backend)->get_capabilities) (backend, cal, opid, cancellable);
+	(* E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property) (backend, cal, opid, cancellable, prop_name, prop_value);
 }
 
 static void
@@ -839,67 +909,6 @@ e_cal_backend_refresh (ECalBackend *backend, EDataCal *cal, guint32 opid, GCance
 }
 
 /**
- * e_cal_backend_get_cal_email_address:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- *
- * Queries the cal address associated with a calendar backend, which
- * must already have an open calendar.
- * This might be finished with e_data_cal_respond_get_cal_email_address().
- **/
-void
-e_cal_backend_get_cal_email_address (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
-{
-	g_return_if_fail (backend != NULL);
-	g_return_if_fail (E_IS_CAL_BACKEND (backend));
-	g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_cal_email_address != NULL);
-
-	(* E_CAL_BACKEND_GET_CLASS (backend)->get_cal_email_address) (backend, cal, opid, cancellable);
-}
-
-/**
- * e_cal_backend_get_alarm_email_address:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- *
- * Calls the get_alarm_email_address method on the given backend.
- * This might be finished with e_data_cal_respond_get_alarm_email_address().
- **/
-void
-e_cal_backend_get_alarm_email_address (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
-{
-	g_return_if_fail (backend != NULL);
-	g_return_if_fail (E_IS_CAL_BACKEND (backend));
-	g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_alarm_email_address != NULL);
-
-	(* E_CAL_BACKEND_GET_CLASS (backend)->get_alarm_email_address) (backend, cal, opid, cancellable);
-}
-
-/**
- * e_cal_backend_get_default_object:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @opid: the ID to use for this operation
- * @cancellable: a #GCancellable for the operation
- *
- * Calls the get_default_object method on the given backend.
- * This might be finished with e_data_cal_respond_get_default_object().
- **/
-void
-e_cal_backend_get_default_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
-{
-	g_return_if_fail (backend != NULL);
-	g_return_if_fail (E_IS_CAL_BACKEND (backend));
-	g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_default_object != NULL);
-
-	(* E_CAL_BACKEND_GET_CLASS (backend)->get_default_object) (backend, cal, opid, cancellable);
-}
-
-/**
  * e_cal_backend_get_object:
  * @backend: an #ECalBackend
  * @cal: an #EDataCal
diff --git a/calendar/libedata-cal/e-cal-backend.h b/calendar/libedata-cal/e-cal-backend.h
index d28ed28..a540d4d 100644
--- a/calendar/libedata-cal/e-cal-backend.h
+++ b/calendar/libedata-cal/e-cal-backend.h
@@ -43,6 +43,15 @@ G_BEGIN_DECLS
 #define E_IS_CAL_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CAL_BACKEND))
 #define E_CAL_BACKEND_GET_CLASS(obj)  (E_CAL_BACKEND_CLASS (G_OBJECT_GET_CLASS (obj)))
 
+#define CAL_BACKEND_PROPERTY_LOADED			"loaded"
+#define CAL_BACKEND_PROPERTY_ONLINE			"online"
+#define CAL_BACKEND_PROPERTY_READONLY			"readonly"
+#define CAL_BACKEND_PROPERTY_CACHE_DIR			"cache-dir"
+#define CAL_BACKEND_PROPERTY_CAPABILITIES		"capabilities"
+#define CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS		"cal-email-address"
+#define CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS	"alarm-email-address"
+#define CAL_BACKEND_PROPERTY_DEFAULT_OBJECT		"default-object"
+
 struct _ECalBackendCache;
 
 typedef struct _ECalBackendPrivate ECalBackendPrivate;
@@ -57,16 +66,15 @@ struct _ECalBackendClass {
 	GObjectClass parent_class;
 
 	/* Virtual methods */
+        void	(* get_backend_property)	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name);
+        void	(* set_backend_property)	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value);
+
 	void	(* open)			(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, gboolean only_if_exists);
 	void	(* authenticate_user)		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, ECredentials *credentials);
 	void	(* remove)			(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
 	void	(* set_online)			(ECalBackend *backend, gboolean is_online);
 
 	void	(* refresh)			(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
-        void	(* get_capabilities)		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
-	void	(* get_cal_email_address)	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
-	void	(* get_alarm_email_address)	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
-	void	(* get_default_object)		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
 	void	(* get_object)			(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid);
 	void	(* get_object_list)		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *sexp);
 	void	(* get_free_busy)		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const GSList *users, time_t start, time_t end);
@@ -110,15 +118,14 @@ void		e_cal_backend_foreach_view		(ECalBackend *backend, gboolean (* callback) (
 
 void		e_cal_backend_set_notification_proxy	(ECalBackend *backend, ECalBackend *proxy);
 
+void		e_cal_backend_get_backend_property	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name);
+void		e_cal_backend_set_backend_property	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value);
+
 void		e_cal_backend_set_online		(ECalBackend *backend, gboolean is_online);
 void		e_cal_backend_open			(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, gboolean only_if_exists);
 void		e_cal_backend_authenticate_user		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, ECredentials *credentials);
 void		e_cal_backend_remove			(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
 void		e_cal_backend_refresh			(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
-void		e_cal_backend_get_capabilities		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
-void		e_cal_backend_get_cal_email_address	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
-void		e_cal_backend_get_alarm_email_address	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
-void		e_cal_backend_get_default_object	(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
 void		e_cal_backend_get_object		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid);
 void		e_cal_backend_get_object_list		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *sexp);
 void		e_cal_backend_get_free_busy		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const GSList *users, time_t start, time_t end);
diff --git a/calendar/libedata-cal/e-data-cal.c b/calendar/libedata-cal/e-data-cal.c
index 9cab4d1..6f4d52d 100644
--- a/calendar/libedata-cal/e-data-cal.c
+++ b/calendar/libedata-cal/e-data-cal.c
@@ -61,11 +61,8 @@ typedef enum {
 	OP_AUTHENTICATE,
 	OP_REMOVE,
 	OP_REFRESH,
-	OP_GET_CACHE_DIR,
-	OP_GET_CAPABILITIES,
-	OP_GET_CAL_EMAIL_ADDRESS,
-	OP_GET_ALARM_EMAIL_ADDRESS,
-	OP_GET_DEFAULT_OBJECT,
+	OP_GET_BACKEND_PROPERTY,
+	OP_SET_BACKEND_PROPERTY,
 	OP_GET_OBJECT,
 	OP_GET_OBJECT_LIST,
 	OP_GET_FREE_BUSY,
@@ -131,14 +128,16 @@ typedef struct {
 		gchar *tzobject;
 		/* OP_CANCEL_OPERATION */
 		guint opid;
+		/* OP_GET_BACKEND_PROPERTY */
+		gchar *prop_name;
+		/* OP_SET_BACKEND_PROPERTY */
+		struct _sbp {
+			gchar *prop_name;
+			gchar *prop_value;
+		} sbp;
 
 		/* OP_REMOVE */
 		/* OP_REFRESH */
-		/* OP_GET_CACHE_DIR */
-		/* OP_GET_CAPABILITIES */
-		/* OP_GET_CAL_EMAIL_ADDRESS */
-		/* OP_GET_ALARM_EMAIL_ADDRESS */
-		/* OP_GET_DEFAULT_OBJECT */
 		/* OP_CANCEL_ALL */
 		/* OP_CLOSE */
 	} d;
@@ -182,24 +181,14 @@ operation_thread (gpointer data, gpointer user_data)
 	case OP_REFRESH:
 		e_cal_backend_refresh (backend, op->cal, op->id, op->cancellable);
 		break;
-	case OP_GET_CACHE_DIR: {
-		gchar *gdbus_cache_dir = NULL;
-
-		e_gdbus_cal_emit_get_cache_dir_done (op->cal->priv->gdbus_object, op->id, NULL, e_util_ensure_gdbus_string (e_cal_backend_get_cache_dir (backend), &gdbus_cache_dir));
-
-		g_free (gdbus_cache_dir);
-		} break;
-	case OP_GET_CAPABILITIES:
-		e_cal_backend_get_capabilities (backend, op->cal, op->id, op->cancellable);
-		break;
-	case OP_GET_CAL_EMAIL_ADDRESS:
-		e_cal_backend_get_cal_email_address (backend, op->cal, op->id, op->cancellable);
+	case OP_GET_BACKEND_PROPERTY:
+		e_cal_backend_get_backend_property (backend, op->cal, op->id, op->cancellable, op->d.prop_name);
+		g_free (op->d.prop_name);
 		break;
-	case OP_GET_ALARM_EMAIL_ADDRESS:
-		e_cal_backend_get_alarm_email_address (backend, op->cal, op->id, op->cancellable);
-		break;
-	case OP_GET_DEFAULT_OBJECT:
-		e_cal_backend_get_default_object (backend, op->cal, op->id, op->cancellable);
+	case OP_SET_BACKEND_PROPERTY:
+		e_cal_backend_set_backend_property (backend, op->cal, op->id, op->cancellable, op->d.sbp.prop_name, op->d.sbp.prop_value);
+		g_free (op->d.sbp.prop_name);
+		g_free (op->d.sbp.prop_value);
 		break;
 	case OP_GET_OBJECT:
 		e_cal_backend_get_object (backend, op->cal, op->id, op->cancellable, op->d.ur.uid, op->d.ur.rid && *op->d.ur.rid ? op->d.ur.rid : NULL);
@@ -615,65 +604,28 @@ impl_Cal_refresh (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal
 }
 
 static gboolean
-impl_Cal_getCacheDir (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
-{
-	OperationData *op;
-
-	op = op_new (OP_GET_CACHE_DIR, cal);
-
-	e_gdbus_cal_complete_get_cache_dir (cal->priv->gdbus_object, invocation, op->id);
-	e_operation_pool_push (ops_pool, op);
-
-	return TRUE;
-}
-
-static gboolean
-impl_Cal_getCapabilities (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
-{
-	OperationData *op;
-
-	op = op_new (OP_GET_CAPABILITIES, cal);
-
-	e_gdbus_cal_complete_get_capabilities (cal->priv->gdbus_object, invocation, op->id);
-	e_operation_pool_push (ops_pool, op);
-
-	return TRUE;
-}
-
-static gboolean
-impl_Cal_getCalEmailAddress (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
-{
-	OperationData *op;
-
-	op = op_new (OP_GET_CAL_EMAIL_ADDRESS, cal);
-
-	e_gdbus_cal_complete_get_cal_email_address (cal->priv->gdbus_object, invocation, op->id);
-	e_operation_pool_push (ops_pool, op);
-
-	return TRUE;
-}
-
-static gboolean
-impl_Cal_getAlarmEmailAddress (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+impl_Cal_getBackendProperty (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name, EDataCal *cal)
 {
 	OperationData *op;
 
-	op = op_new (OP_GET_ALARM_EMAIL_ADDRESS, cal);
+	op = op_new (OP_GET_BACKEND_PROPERTY, cal);
+	op->d.prop_name = g_strdup (in_prop_name);
 
-	e_gdbus_cal_complete_get_alarm_email_address (cal->priv->gdbus_object, invocation, op->id);
+	e_gdbus_cal_complete_get_backend_property (cal->priv->gdbus_object, invocation, op->id);
 	e_operation_pool_push (ops_pool, op);
 
 	return TRUE;
 }
 
 static gboolean
-impl_Cal_getDefaultObject (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+impl_Cal_setBackendProperty (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_prop_name_value, EDataCal *cal)
 {
 	OperationData *op;
 
-	op = op_new (OP_GET_DEFAULT_OBJECT, cal);
+	op = op_new (OP_SET_BACKEND_PROPERTY, cal);
+	g_return_val_if_fail (e_gdbus_cal_decode_set_backend_property (in_prop_name_value, &op->d.sbp.prop_name, &op->d.sbp.prop_value), FALSE);
 
-	e_gdbus_cal_complete_get_default_object (cal->priv->gdbus_object, invocation, op->id);
+	e_gdbus_cal_complete_set_backend_property (cal->priv->gdbus_object, invocation, op->id);
 	e_operation_pool_push (ops_pool, op);
 
 	return TRUE;
@@ -995,101 +947,47 @@ e_data_cal_respond_refresh (EDataCal *cal, guint32 opid, GError *error)
 }
 
 /**
- * e_data_cal_respond_get_capabilities:
+ * e_data_cal_respond_get_backend_property:
  * @cal: A calendar client interface.
  * @error: Operation error, if any, automatically freed if passed it.
- * @calabilities: Comma-separated list of capabilities for the calendar.
+ * @prop_value: Value of a property
  *
- * Notifies listeners of the completion of the get_capabilities method call.
+ * Notifies listeners of the completion of the get_backend_property method call.
  */
 void
-e_data_cal_respond_get_capabilities (EDataCal *cal, guint32 opid, GError *error, const gchar *capabilities)
+e_data_cal_respond_get_backend_property (EDataCal *cal, guint32 opid, GError *error, const gchar *prop_value)
 {
-	gchar *gdbus_capabilities = NULL;
+	gchar *gdbus_prop_value = NULL;
 
 	op_complete (cal, opid);
 
 	/* Translators: This is prefix to a detailed error message */
-	g_prefix_error (&error, "%s", _("Cannot retrieve calendar capabilities: "));
+	g_prefix_error (&error, "%s", _("Cannot retrieve backend property: "));
 
-	e_gdbus_cal_emit_get_capabilities_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (capabilities, &gdbus_capabilities));
+	e_gdbus_cal_emit_get_backend_property_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (prop_value, &gdbus_prop_value));
 
-	g_free (gdbus_capabilities);
+	g_free (gdbus_prop_value);
 	if (error)
 		g_error_free (error);
 }
 
 /**
- * e_data_cal_respond_get_cal_email_address:
+ * e_data_cal_respond_set_backend_property:
  * @cal: A calendar client interface.
  * @error: Operation error, if any, automatically freed if passed it.
- * @address: Calendar address.
  *
- * Notifies listeners of the completion of the get_cal_email_address method call.
+ * Notifies listeners of the completion of the set_backend_property method call.
  */
 void
-e_data_cal_respond_get_cal_email_address (EDataCal *cal, guint32 opid, GError *error, const gchar *address)
+e_data_cal_respond_set_backend_property (EDataCal *cal, guint32 opid, GError *error)
 {
-	gchar *gdbus_address = NULL;
-
 	op_complete (cal, opid);
 
 	/* Translators: This is prefix to a detailed error message */
-	g_prefix_error (&error, "%s", _("Cannot retrieve calendar address: "));
+	g_prefix_error (&error, "%s", _("Cannot set backend property: "));
 
-	e_gdbus_cal_emit_get_cal_email_address_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (address, &gdbus_address));
+	e_gdbus_cal_emit_set_backend_property_done (cal->priv->gdbus_object, opid, error);
 
-	g_free (gdbus_address);
-	if (error)
-		g_error_free (error);
-}
-
-/**
- * e_data_cal_respond_get_alarm_email_address:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- * @address: Alarm email address.
- *
- * Notifies listeners of the completion of the get_alarm_email_address method call.
- */
-void
-e_data_cal_respond_get_alarm_email_address (EDataCal *cal, guint32 opid, GError *error, const gchar *address)
-{
-	gchar *gdbus_address = NULL;
-
-	op_complete (cal, opid);
-
-	/* Translators: This is prefix to a detailed error message */
-	g_prefix_error (&error, "%s", _("Cannot retrieve calendar alarm e-mail address: "));
-
-	e_gdbus_cal_emit_get_alarm_email_address_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (address, &gdbus_address));
-
-	g_free (gdbus_address);
-	if (error)
-		g_error_free (error);
-}
-
-/**
- * e_data_cal_respond_get_default_object:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- * @object: The default object as an iCalendar string.
- *
- * Notifies listeners of the completion of the get_default_object method call.
- */
-void
-e_data_cal_respond_get_default_object (EDataCal *cal, guint32 opid, GError *error, const gchar *object)
-{
-	gchar *gdbus_object = NULL;
-
-	op_complete (cal, opid);
-
-	/* Translators: This is prefix to a detailed error message */
-	g_prefix_error (&error, "%s", _("Cannot retrieve default calendar object: "));
-
-	e_gdbus_cal_emit_get_default_object_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (object, &gdbus_object));
-
-	g_free (gdbus_object);
 	if (error)
 		g_error_free (error);
 }
@@ -1475,11 +1373,8 @@ e_data_cal_init (EDataCal *ecal)
 	g_signal_connect (gdbus_object, "handle-authenticate-user", G_CALLBACK (impl_Cal_authenticateUser), ecal);
 	g_signal_connect (gdbus_object, "handle-remove", G_CALLBACK (impl_Cal_remove), ecal);
 	g_signal_connect (gdbus_object, "handle-refresh", G_CALLBACK (impl_Cal_refresh), ecal);
-	g_signal_connect (gdbus_object, "handle-get-cache-dir", G_CALLBACK (impl_Cal_getCacheDir), ecal);
-	g_signal_connect (gdbus_object, "handle-get-capabilities", G_CALLBACK (impl_Cal_getCapabilities), ecal);
-	g_signal_connect (gdbus_object, "handle-get-cal-email-address", G_CALLBACK (impl_Cal_getCalEmailAddress), ecal);
-	g_signal_connect (gdbus_object, "handle-get-alarm-email-address", G_CALLBACK (impl_Cal_getAlarmEmailAddress), ecal);
-	g_signal_connect (gdbus_object, "handle-get-default-object", G_CALLBACK (impl_Cal_getDefaultObject), ecal);
+	g_signal_connect (gdbus_object, "handle-get-backend-property", G_CALLBACK (impl_Cal_getBackendProperty), ecal);
+	g_signal_connect (gdbus_object, "handle-set-backend-property", G_CALLBACK (impl_Cal_setBackendProperty), ecal);
 	g_signal_connect (gdbus_object, "handle-get-object", G_CALLBACK (impl_Cal_getObject), ecal);
 	g_signal_connect (gdbus_object, "handle-get-object-list", G_CALLBACK (impl_Cal_getObjectList), ecal);
 	g_signal_connect (gdbus_object, "handle-get-free-busy", G_CALLBACK (impl_Cal_getFreeBusy), ecal);
diff --git a/calendar/libedata-cal/e-data-cal.h b/calendar/libedata-cal/e-data-cal.h
index 14923f7..ae03c9e 100644
--- a/calendar/libedata-cal/e-data-cal.h
+++ b/calendar/libedata-cal/e-data-cal.h
@@ -90,6 +90,28 @@ const gchar *e_data_cal_status_to_string (EDataCalCallStatus status);
 		}								\
 	} G_STMT_END
 
+/**
+ * e_return_data_cal_error_val_if_fail:
+ *
+ * Same as e_return_data_cal_error_if_fail(), only returns FALSE on a failure
+ *
+ * Since: 3.2
+ **/
+#define e_return_data_cal_error_val_if_fail(expr, _code)			\
+	G_STMT_START {								\
+		if (G_LIKELY (expr)) {						\
+		} else {							\
+			g_log (G_LOG_DOMAIN,					\
+				G_LOG_LEVEL_CRITICAL,				\
+				"file %s: line %d (%s): assertion `%s' failed",	\
+				__FILE__, __LINE__, G_STRFUNC, #expr);		\
+			g_set_error (error, E_DATA_CAL_ERROR, (_code),		\
+				"file %s: line %d (%s): assertion `%s' failed",	\
+				__FILE__, __LINE__, G_STRFUNC, #expr);		\
+			return FALSE;						\
+		}								\
+	} G_STMT_END
+
 typedef struct _EDataCalPrivate EDataCalPrivate;
 
 struct _EDataCal {
@@ -112,10 +134,8 @@ void		e_data_cal_respond_open				(EDataCal *cal, guint32 opid, GError *error);
 void		e_data_cal_respond_authenticate_user		(EDataCal *cal, guint32 opid, GError *error);
 void		e_data_cal_respond_remove			(EDataCal *cal, guint32 opid, GError *error);
 void		e_data_cal_respond_refresh			(EDataCal *cal, guint32 opid, GError *error);
-void		e_data_cal_respond_get_capabilities		(EDataCal *cal, guint32 opid, GError *error, const gchar *capabilities);
-void		e_data_cal_respond_get_cal_email_address	(EDataCal *cal, guint32 opid, GError *error, const gchar *address);
-void		e_data_cal_respond_get_alarm_email_address	(EDataCal *cal, guint32 opid, GError *error, const gchar *address);
-void		e_data_cal_respond_get_default_object		(EDataCal *cal, guint32 opid, GError *error, const gchar *object);
+void		e_data_cal_respond_get_backend_property		(EDataCal *cal, guint32 opid, GError *error, const gchar *prop_value);
+void		e_data_cal_respond_set_backend_property		(EDataCal *cal, guint32 opid, GError *error);
 void		e_data_cal_respond_get_object			(EDataCal *cal, guint32 opid, GError *error, const gchar *object);
 void		e_data_cal_respond_get_object_list		(EDataCal *cal, guint32 opid, GError *error, const GSList *objects);
 void		e_data_cal_respond_get_free_busy		(EDataCal *cal, guint32 opid, GError *error);
diff --git a/calendar/libegdbus/e-gdbus-cal.c b/calendar/libegdbus/e-gdbus-cal.c
index 6d0b6d1..4acf899 100644
--- a/calendar/libegdbus/e-gdbus-cal.c
+++ b/calendar/libegdbus/e-gdbus-cal.c
@@ -49,16 +49,10 @@ enum
 	__REMOVE_DONE_SIGNAL,
 	__REFRESH_METHOD,
 	__REFRESH_DONE_SIGNAL,
-	__GET_CACHE_DIR_METHOD,
-	__GET_CACHE_DIR_DONE_SIGNAL,
-	__GET_CAPABILITIES_METHOD,
-	__GET_CAPABILITIES_DONE_SIGNAL,
-	__GET_CAL_EMAIL_ADDRESS_METHOD,
-	__GET_CAL_EMAIL_ADDRESS_DONE_SIGNAL,
-	__GET_ALARM_EMAIL_ADDRESS_METHOD,
-	__GET_ALARM_EMAIL_ADDRESS_DONE_SIGNAL,
-	__GET_DEFAULT_OBJECT_METHOD,
-	__GET_DEFAULT_OBJECT_DONE_SIGNAL,
+	__GET_BACKEND_PROPERTY_METHOD,
+	__GET_BACKEND_PROPERTY_DONE_SIGNAL,
+	__SET_BACKEND_PROPERTY_METHOD,
+	__SET_BACKEND_PROPERTY_DONE_SIGNAL,
 	__GET_OBJECT_METHOD,
 	__GET_OBJECT_DONE_SIGNAL,
 	__GET_OBJECT_LIST_METHOD,
@@ -141,11 +135,8 @@ E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_CAL_INTERFACE_NAME,
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_CAL_INTERFACE_NAME, authenticate_user)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_CAL_INTERFACE_NAME, remove)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_CAL_INTERFACE_NAME, refresh)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_CAL_INTERFACE_NAME, get_cache_dir)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_CAL_INTERFACE_NAME, get_capabilities)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_CAL_INTERFACE_NAME, get_cal_email_address)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_CAL_INTERFACE_NAME, get_alarm_email_address)
-E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_CAL_INTERFACE_NAME, get_default_object)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_CAL_INTERFACE_NAME, get_backend_property)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_CAL_INTERFACE_NAME, set_backend_property)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING	(GDBUS_CAL_INTERFACE_NAME, get_object)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV	(GDBUS_CAL_INTERFACE_NAME, get_object_list)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID	(GDBUS_CAL_INTERFACE_NAME, get_free_busy)
@@ -180,11 +171,8 @@ e_gdbus_cal_default_init (EGdbusCalIface *iface)
 	E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID	(EGdbusCalIface, "authenticateUser",		authenticate_user, __AUTHENTICATE_USER_METHOD, __AUTHENTICATE_USER_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_VOID__VOID	(EGdbusCalIface, "remove",			remove, __REMOVE_METHOD, __REMOVE_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_VOID__VOID	(EGdbusCalIface, "refresh",			refresh, __REFRESH_METHOD, __REFRESH_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRING	(EGdbusCalIface, "getCacheDir",			get_cache_dir, __GET_CACHE_DIR_METHOD, __GET_CACHE_DIR_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRING	(EGdbusCalIface, "getCapabilities",		get_capabilities, __GET_CAPABILITIES_METHOD, __GET_CAPABILITIES_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRING	(EGdbusCalIface, "getCalEmailAddress",		get_cal_email_address, __GET_CAL_EMAIL_ADDRESS_METHOD, __GET_CAL_EMAIL_ADDRESS_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRING	(EGdbusCalIface, "getAlarmEmailAddress",	get_alarm_email_address, __GET_ALARM_EMAIL_ADDRESS_METHOD, __GET_ALARM_EMAIL_ADDRESS_DONE_SIGNAL)
-	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRING	(EGdbusCalIface, "getDefaultObject",		get_default_object, __GET_DEFAULT_OBJECT_METHOD, __GET_DEFAULT_OBJECT_DONE_SIGNAL)
+	E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusCalIface, "getBackendProperty",		get_backend_property, __GET_BACKEND_PROPERTY_METHOD, __GET_BACKEND_PROPERTY_DONE_SIGNAL)
+	E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID	(EGdbusCalIface, "setBackendProperty",		set_backend_property, __SET_BACKEND_PROPERTY_METHOD, __SET_BACKEND_PROPERTY_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_STRV__STRING	(EGdbusCalIface, "getObject",			get_object, __GET_OBJECT_METHOD, __GET_OBJECT_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_STRING__STRV	(EGdbusCalIface, "getObjectList",		get_object_list, __GET_OBJECT_LIST_METHOD, __GET_OBJECT_LIST_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID	(EGdbusCalIface, "getFreeBusy",			get_free_busy, __GET_FREE_BUSY_METHOD, __GET_FREE_BUSY_DONE_SIGNAL)
@@ -312,103 +300,57 @@ e_gdbus_cal_call_refresh_sync (GDBusProxy *proxy, GCancellable *cancellable, GEr
 }
 
 void
-e_gdbus_cal_call_get_cache_dir (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+e_gdbus_cal_call_get_backend_property (GDBusProxy *proxy, const gchar *in_prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_gdbus_proxy_call_void ("getCacheDir", e_gdbus_cal_call_get_cache_dir, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+	e_gdbus_proxy_call_string ("getBackendProperty", e_gdbus_cal_call_get_backend_property, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_prop_name, cancellable, callback, user_data);
 }
 
 gboolean
-e_gdbus_cal_call_get_cache_dir_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_dirname, GError **error)
+e_gdbus_cal_call_get_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_prop_value, GError **error)
 {
-	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_dirname, error, e_gdbus_cal_call_get_cache_dir);
+	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_prop_value, error, e_gdbus_cal_call_get_backend_property);
 }
 
 gboolean
-e_gdbus_cal_call_get_cache_dir_sync (GDBusProxy *proxy, gchar **out_dirname, GCancellable *cancellable, GError **error)
+e_gdbus_cal_call_get_backend_property_sync (GDBusProxy *proxy, const gchar *in_prop_name, gchar **out_prop_value, GCancellable *cancellable, GError **error)
 {
-	return e_gdbus_proxy_call_sync_void__string (proxy, out_dirname, cancellable, error,
-		e_gdbus_cal_call_get_cache_dir,
-		e_gdbus_cal_call_get_cache_dir_finish);
+	return e_gdbus_proxy_call_sync_string__string (proxy, in_prop_name, out_prop_value, cancellable, error,
+		e_gdbus_cal_call_get_backend_property,
+		e_gdbus_cal_call_get_backend_property_finish);
 }
 
-void
-e_gdbus_cal_call_get_capabilities (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
-{
-	e_gdbus_proxy_call_void ("getCapabilities", e_gdbus_cal_call_get_capabilities, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
-}
-
-gboolean
-e_gdbus_cal_call_get_capabilities_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_capabilities, GError **error)
-{
-	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_capabilities, error, e_gdbus_cal_call_get_capabilities);
-}
-
-gboolean
-e_gdbus_cal_call_get_capabilities_sync (GDBusProxy *proxy, gchar **out_capabilities, GCancellable *cancellable, GError **error)
-{
-	return e_gdbus_proxy_call_sync_void__string (proxy, out_capabilities, cancellable, error,
-		e_gdbus_cal_call_get_capabilities,
-		e_gdbus_cal_call_get_capabilities_finish);
-}
-
-void
-e_gdbus_cal_call_get_cal_email_address (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
-{
-	e_gdbus_proxy_call_void ("getCalEmailAddress", e_gdbus_cal_call_get_cal_email_address, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
-}
-
-gboolean
-e_gdbus_cal_call_get_cal_email_address_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_address, GError **error)
-{
-	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_address, error, e_gdbus_cal_call_get_cal_email_address);
-}
-
-gboolean
-e_gdbus_cal_call_get_cal_email_address_sync (GDBusProxy *proxy, gchar **out_address, GCancellable *cancellable, GError **error)
-{
-	return e_gdbus_proxy_call_sync_void__string (proxy, out_address, cancellable, error,
-		e_gdbus_cal_call_get_cal_email_address,
-		e_gdbus_cal_call_get_cal_email_address_finish);
-}
-
-void
-e_gdbus_cal_call_get_alarm_email_address (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
-{
-	e_gdbus_proxy_call_void ("getAlarmEmailAddress", e_gdbus_cal_call_get_alarm_email_address, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
-}
-
-gboolean
-e_gdbus_cal_call_get_alarm_email_address_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_address, GError **error)
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_set_backend_property (const gchar *in_prop_name, const gchar *in_prop_value)
 {
-	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_address, error, e_gdbus_cal_call_get_alarm_email_address);
+	return encode_string_string (in_prop_name, in_prop_value);
 }
 
+/* free out_prop_name and out_prop_value with g_free() */
 gboolean
-e_gdbus_cal_call_get_alarm_email_address_sync (GDBusProxy *proxy, gchar **out_address, GCancellable *cancellable, GError **error)
+e_gdbus_cal_decode_set_backend_property (const gchar * const *in_strv, gchar **out_prop_name, gchar **out_prop_value)
 {
-	return e_gdbus_proxy_call_sync_void__string (proxy, out_address, cancellable, error,
-		e_gdbus_cal_call_get_alarm_email_address,
-		e_gdbus_cal_call_get_alarm_email_address_finish);
+	return decode_string_string (in_strv, out_prop_name, out_prop_value);
 }
 
 void
-e_gdbus_cal_call_get_default_object (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+e_gdbus_cal_call_set_backend_property (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 {
-	e_gdbus_proxy_call_void ("getDefaultObject", e_gdbus_cal_call_get_default_object, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+	e_gdbus_proxy_call_strv ("setBackendProperty", e_gdbus_cal_call_set_backend_property, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_prop_name_value, cancellable, callback, user_data);
 }
 
 gboolean
-e_gdbus_cal_call_get_default_object_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_object, GError **error)
+e_gdbus_cal_call_set_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
 {
-	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_object, error, e_gdbus_cal_call_get_default_object);
+	return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_set_backend_property);
 }
 
 gboolean
-e_gdbus_cal_call_get_default_object_sync (GDBusProxy *proxy, gchar **out_object, GCancellable *cancellable, GError **error)
+e_gdbus_cal_call_set_backend_property_sync (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GError **error)
 {
-	return e_gdbus_proxy_call_sync_void__string (proxy, out_object, cancellable, error,
-		e_gdbus_cal_call_get_default_object,
-		e_gdbus_cal_call_get_default_object_finish);
+	return e_gdbus_proxy_call_sync_strv__void (proxy, in_prop_name_value, cancellable, error,
+		e_gdbus_cal_call_set_backend_property,
+		e_gdbus_cal_call_set_backend_property_finish);
 }
 
 /* free returned pointer with g_strfreev() */
@@ -911,11 +853,8 @@ DECLARE_EMIT_DONE_SIGNAL_0 (open,			__OPEN_DONE_SIGNAL)
 DECLARE_EMIT_DONE_SIGNAL_0 (authenticate_user,		__AUTHENTICATE_USER_DONE_SIGNAL)
 DECLARE_EMIT_DONE_SIGNAL_0 (remove,			__REMOVE_DONE_SIGNAL)
 DECLARE_EMIT_DONE_SIGNAL_0 (refresh,			__REFRESH_DONE_SIGNAL)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_cache_dir,		__GET_CACHE_DIR_DONE_SIGNAL, const gchar *)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_capabilities,		__GET_CAPABILITIES_DONE_SIGNAL, const gchar *)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_cal_email_address,	__GET_CAL_EMAIL_ADDRESS_DONE_SIGNAL, const gchar *)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_alarm_email_address,	__GET_ALARM_EMAIL_ADDRESS_DONE_SIGNAL, const gchar *)
-DECLARE_EMIT_DONE_SIGNAL_1 (get_default_object,		__GET_DEFAULT_OBJECT_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_backend_property,	__GET_BACKEND_PROPERTY_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_0 (set_backend_property,	__SET_BACKEND_PROPERTY_DONE_SIGNAL)
 DECLARE_EMIT_DONE_SIGNAL_1 (get_object,			__GET_OBJECT_DONE_SIGNAL, const gchar *)
 DECLARE_EMIT_DONE_SIGNAL_1 (get_object_list,		__GET_OBJECT_LIST_DONE_SIGNAL, const gchar * const *)
 DECLARE_EMIT_DONE_SIGNAL_0 (get_free_busy,		__GET_FREE_BUSY_DONE_SIGNAL)
@@ -972,15 +911,11 @@ E_DECLARE_GDBUS_ASYNC_METHOD_1			(cal, open, only_if_exists, "b")
 E_DECLARE_GDBUS_ASYNC_METHOD_1			(cal, authenticateUser, credentials, "as")
 E_DECLARE_GDBUS_ASYNC_METHOD_0			(cal, remove)
 E_DECLARE_GDBUS_ASYNC_METHOD_0			(cal, refresh)
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(cal, getCacheDir, dirname, "s")
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(cal, getCapabilities, capabilities, "s")
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(cal, getCalEmailAddress, address, "s")
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(cal, getAlarmEmailAddress, address, "s")
-E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(cal, getDefaultObject, object, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(cal, getBackendProperty, propname, "s", propvalue, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1			(cal, setBackendProperty, propnamevalue, "as")
 E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(cal, getObject, uid_rid, "as", object, "s")
 E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(cal, getObjectList, sexp, "s", objects, "as")
 E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(cal, getFreeBusy, start_stop_users, "as", freebusy, "as")
-E_DECLARE_GDBUS_ASYNC_METHOD_1			(cal, discardAlarm, uid_auid, "as")
 E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(cal, createObject, object, "s", uid, "s")
 E_DECLARE_GDBUS_ASYNC_METHOD_1			(cal, modifyObject, object_mod, "as")
 E_DECLARE_GDBUS_ASYNC_METHOD_1			(cal, removeObject, uid_rid_mod, "as")
@@ -1001,15 +936,11 @@ static const GDBusMethodInfo * const e_gdbus_cal_method_info_pointers[] =
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, authenticateUser),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, remove),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, refresh),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getCacheDir),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getCapabilities),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getCalEmailAddress),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getAlarmEmailAddress),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getDefaultObject),
+	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getBackendProperty),
+	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, setBackendProperty),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getObject),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getObjectList),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getFreeBusy),
-	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, discardAlarm),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, createObject),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, modifyObject),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, removeObject),
@@ -1037,15 +968,11 @@ static const GDBusSignalInfo * const e_gdbus_cal_signal_info_pointers[] =
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, authenticateUser_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, remove_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, refresh_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getCacheDir_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getCapabilities_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getCalEmailAddress_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getAlarmEmailAddress_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getDefaultObject_done),
+	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getBackendProperty_done),
+	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, setBackendProperty_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getObject_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getObjectList_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getFreeBusy_done),
-	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, discardAlarm_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, createObject_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, modifyObject_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, removeObject_done),
@@ -1264,11 +1191,8 @@ e_gdbus_cal_proxy_init (EGdbusCalProxy *proxy)
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID   (authenticate_user);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID   (remove);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID   (refresh);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_cache_dir);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_capabilities);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_cal_email_address);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_alarm_email_address);
-	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_default_object);
+	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_backend_property);
+	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID   (set_backend_property);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_object);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV   (get_object_list);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV   (get_free_busy);
diff --git a/calendar/libegdbus/e-gdbus-cal.h b/calendar/libegdbus/e-gdbus-cal.h
index 73b5dae..760b88e 100644
--- a/calendar/libegdbus/e-gdbus-cal.h
+++ b/calendar/libegdbus/e-gdbus-cal.h
@@ -122,20 +122,11 @@ struct _EGdbusCalIface
 	gboolean (*handle_refresh)			(EGdbusCal *object, GDBusMethodInvocation *invocation);
 	void	 (*refresh_done)			(EGdbusCal *object, guint arg_opid, const GError *arg_error);
 
-	gboolean (*handle_get_cache_dir)		(EGdbusCal *object, GDBusMethodInvocation *invocation);
-	void	 (*get_cache_dir_done)			(EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_dirname);
+	gboolean (*handle_get_backend_property)		(EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name);
+	void	 (*get_backend_property_done)		(EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_prop_value);
 
-	gboolean (*handle_get_capabilities)		(EGdbusCal *object, GDBusMethodInvocation *invocation);
-	void	 (*get_capabilities_done)		(EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_capabilities);
-
-	gboolean (*handle_get_cal_email_address)	(EGdbusCal *object, GDBusMethodInvocation *invocation);
-	void	 (*get_cal_email_address_done)		(EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_cal_address);
-
-	gboolean (*handle_get_alarm_email_address)	(EGdbusCal *object, GDBusMethodInvocation *invocation);
-	void	 (*get_alarm_email_address_done)	(EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_alarm_email_address);
-
-	gboolean (*handle_get_default_object)		(EGdbusCal *object, GDBusMethodInvocation *invocation);
-	void	 (*get_default_object_done)		(EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_default_object);
+	gboolean (*handle_set_backend_property)		(EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_prop_name_value);
+	void	 (*set_backend_property_done)		(EGdbusCal *object, guint arg_opid, const GError *arg_error);
 
 	gboolean (*handle_get_object)			(EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid);
 	void	 (*get_object_done)			(EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_object);
@@ -195,25 +186,15 @@ void		e_gdbus_cal_call_refresh			(GDBusProxy *proxy, GCancellable *cancellable,
 gboolean	e_gdbus_cal_call_refresh_finish			(GDBusProxy *proxy, GAsyncResult *result, GError **error);
 gboolean	e_gdbus_cal_call_refresh_sync			(GDBusProxy *proxy, GCancellable *cancellable, GError **error);
 
-void		e_gdbus_cal_call_get_cache_dir			(GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_cal_call_get_cache_dir_finish		(GDBusProxy *proxy, GAsyncResult *result, gchar **out_dirname, GError **error);
-gboolean	e_gdbus_cal_call_get_cache_dir_sync		(GDBusProxy *proxy, gchar **out_dirname, GCancellable *cancellable, GError **error);
-
-void		e_gdbus_cal_call_get_capabilities		(GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_cal_call_get_capabilities_finish	(GDBusProxy *proxy, GAsyncResult *result, gchar **out_capabilities, GError **error);
-gboolean	e_gdbus_cal_call_get_capabilities_sync		(GDBusProxy *proxy, gchar **out_capabilities, GCancellable *cancellable, GError **error);
-
-void		e_gdbus_cal_call_get_cal_email_address		(GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_cal_call_get_cal_email_address_finish	(GDBusProxy *proxy, GAsyncResult *result, gchar **out_address, GError **error);
-gboolean	e_gdbus_cal_call_get_cal_email_address_sync	(GDBusProxy *proxy, gchar **out_address, GCancellable *cancellable, GError **error);
-
-void		e_gdbus_cal_call_get_alarm_email_address	(GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_cal_call_get_alarm_email_address_finish	(GDBusProxy *proxy, GAsyncResult *result, gchar **out_address, GError **error);
-gboolean	e_gdbus_cal_call_get_alarm_email_address_sync	(GDBusProxy *proxy, gchar **out_address, GCancellable *cancellable, GError **error);
+void		e_gdbus_cal_call_get_backend_property		(GDBusProxy *proxy, const gchar *in_prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_gdbus_cal_call_get_backend_property_finish	(GDBusProxy *proxy, GAsyncResult *result, gchar **out_prop_value, GError **error);
+gboolean	e_gdbus_cal_call_get_backend_property_sync	(GDBusProxy *proxy, const gchar *in_prop_name, gchar **out_prop_value, GCancellable *cancellable, GError **error);
 
-void		e_gdbus_cal_call_get_default_object		(GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_gdbus_cal_call_get_default_object_finish	(GDBusProxy *proxy, GAsyncResult *result, gchar **out_object, GError **error);
-gboolean	e_gdbus_cal_call_get_default_object_sync	(GDBusProxy *proxy, gchar **out_object, GCancellable *cancellable, GError **error);
+gchar **	e_gdbus_cal_encode_set_backend_property		(const gchar *in_prop_name, const gchar *in_prop_value);
+gboolean	e_gdbus_cal_decode_set_backend_property		(const gchar * const *in_strv, gchar **out_prop_name, gchar **out_prop_value);
+void		e_gdbus_cal_call_set_backend_property		(GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_gdbus_cal_call_set_backend_property_finish	(GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean	e_gdbus_cal_call_set_backend_property_sync	(GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GError **error);
 
 gchar **	e_gdbus_cal_encode_get_object			(const gchar *in_uid, const gchar *in_rid);
 gboolean	e_gdbus_cal_decode_get_object			(const gchar * const *in_strv, gchar **out_uid, gchar **out_rid);
@@ -292,15 +273,11 @@ gboolean	e_gdbus_cal_call_close_sync			(GDBusProxy *proxy, GCancellable *cancell
 #define e_gdbus_cal_complete_authenticate_user		e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_remove			e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_refresh			e_gdbus_complete_async_method
-#define e_gdbus_cal_complete_get_cache_dir		e_gdbus_complete_async_method
-#define e_gdbus_cal_complete_get_capabilities		e_gdbus_complete_async_method
-#define e_gdbus_cal_complete_get_cal_email_address	e_gdbus_complete_async_method
-#define e_gdbus_cal_complete_get_alarm_email_address	e_gdbus_complete_async_method
-#define e_gdbus_cal_complete_get_default_object		e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_backend_property	e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_set_backend_property	e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_get_object			e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_get_object_list		e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_get_free_busy		e_gdbus_complete_async_method
-#define e_gdbus_cal_complete_discard_alarm		e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_create_object		e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_modify_object		e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_remove_object		e_gdbus_complete_async_method
@@ -318,16 +295,12 @@ void e_gdbus_cal_emit_open_done				(EGdbusCal *object, guint arg_opid, const GEr
 void e_gdbus_cal_emit_authenticate_user_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error);
 void e_gdbus_cal_emit_remove_done			(EGdbusCal *object, guint arg_opid, const GError *arg_error);
 void e_gdbus_cal_emit_refresh_done			(EGdbusCal *object, guint arg_opid, const GError *arg_error);
-void e_gdbus_cal_emit_get_cache_dir_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_dirname);
-void e_gdbus_cal_emit_get_capabilities_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_capabilities);
-void e_gdbus_cal_emit_get_cal_email_address_done	(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_address);
-void e_gdbus_cal_emit_get_alarm_email_address_done	(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_address);
-void e_gdbus_cal_emit_get_default_object_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_object);
+void e_gdbus_cal_emit_get_backend_property_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_prop_value);
+void e_gdbus_cal_emit_set_backend_property_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error);
 void e_gdbus_cal_emit_get_object_done			(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_object);
 void e_gdbus_cal_emit_get_object_list_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar * const *out_objects);
 void e_gdbus_cal_emit_get_free_busy_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error);
 void e_gdbus_cal_emit_get_free_busy_data		(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar * const *out_freebusy);
-void e_gdbus_cal_emit_discard_alarm_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error);
 void e_gdbus_cal_emit_create_object_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_uid);
 void e_gdbus_cal_emit_modify_object_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error);
 void e_gdbus_cal_emit_remove_object_done		(EGdbusCal *object, guint arg_opid, const GError *arg_error);
diff --git a/libedataserver/Makefile.am b/libedataserver/Makefile.am
index 347c2a0..056e59e 100644
--- a/libedataserver/Makefile.am
+++ b/libedataserver/Makefile.am
@@ -23,6 +23,7 @@ libedataserver_1_2_la_SOURCES =		\
 	e-account.c			\
 	e-categories.c			\
 	e-client.c			\
+	e-client-private.h		\
 	e-credentials.c			\
 	e-flag.c			\
 	e-gdbus-templates.h		\
diff --git a/libedataserver/e-client-private.h b/libedataserver/e-client-private.h
new file mode 100644
index 0000000..d32522d
--- /dev/null
+++ b/libedataserver/e-client-private.h
@@ -0,0 +1,121 @@
+/*
+ * e-client-private.h
+ *
+ * This program 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program 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 the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_CLIENT_PRIVATE_H
+#define E_CLIENT_PRIVATE_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "libedataserver/e-credentials.h"
+#include "libedataserver/e-source.h"
+#include "libedataserver/e-source-list.h"
+#include "libedataserver/e-client.h"
+
+G_BEGIN_DECLS
+
+void		e_client_set_capabilities	(EClient *client, const gchar *capabilities);
+void		e_client_set_readonly		(EClient *client, gboolean readonly);
+void		e_client_set_online		(EClient *client, gboolean is_online);
+guint32		e_client_register_op		(EClient *client, GCancellable *cancellable);
+void		e_client_unregister_op		(EClient *client, guint32 opid);
+void		e_client_process_authentication	(EClient *client, const ECredentials *credentials);
+
+gboolean	e_client_emit_authenticate	(EClient *client, ECredentials *credentials);
+void		e_client_emit_backend_error	(EClient *client, const gchar *error_msg);
+void		e_client_emit_backend_died	(EClient *client);
+
+ESource *	e_client_util_get_system_source	(ESourceList *source_list);
+gboolean	e_client_util_set_default	(ESourceList *source_list, ESource *source);
+ESource *	e_client_util_get_source_for_uri(ESourceList *source_list, const gchar *uri);
+
+/* protected functions simplifying sync/async calls */
+GDBusProxy *	e_client_get_dbus_proxy		(EClient *client);
+void		e_client_unwrap_dbus_error	(EClient *client, GError *dbus_error, GError **out_error);
+
+void		e_client_proxy_return_async_error	(EClient *client, const GError *error, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag);
+
+#define e_client_return_async_if_fail(_expr, _client, _callback, _user_data, _source_tag)	\
+	G_STMT_START {										\
+		if (!G_LIKELY (_expr)) {							\
+			GError *error;								\
+												\
+			error = g_error_new (							\
+				E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG,			\
+				"file %s:%d: %s: assertion `%s' failed",			\
+				__FILE__, __LINE__, G_STRFUNC, # _expr);			\
+												\
+			g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "%s", error->message);	\
+												\
+			e_client_proxy_return_async_error (					\
+				_client, error, _callback, _user_data, _source_tag);		\
+												\
+			g_error_free (error);							\
+		}										\
+	} G_STMT_END
+
+typedef gboolean (* EClientProxyFinishVoidFunc)		(GDBusProxy *proxy, GAsyncResult *result, GError **error);
+typedef gboolean (* EClientProxyFinishBooleanFunc)	(GDBusProxy *proxy, GAsyncResult *result, gboolean *out_boolean, GError **error);
+typedef gboolean (* EClientProxyFinishStringFunc)	(GDBusProxy *proxy, GAsyncResult *result, gchar **out_string, GError **error);
+typedef gboolean (* EClientProxyFinishStrvFunc)		(GDBusProxy *proxy, GAsyncResult *result, gchar ***out_strv, GError **error);
+typedef gboolean (* EClientProxyFinishUintFunc)		(GDBusProxy *proxy, GAsyncResult *result, guint *out_uint, GError **error);
+
+void		e_client_proxy_call_void	(EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+void		e_client_proxy_call_boolean	(EClient *client, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+void		e_client_proxy_call_string	(EClient *client, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, const gchar * in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+void		e_client_proxy_call_strv	(EClient *client, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, const gchar * const * in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+void		e_client_proxy_call_uint	(EClient *client, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+
+gboolean	e_client_proxy_call_finish_void		(EClient *client, GAsyncResult *result, GError **error, gpointer source_tag);
+gboolean	e_client_proxy_call_finish_boolean	(EClient *client, GAsyncResult *result, gboolean *out_boolean, GError **error, gpointer source_tag);
+gboolean	e_client_proxy_call_finish_string	(EClient *client, GAsyncResult *result, gchar **out_string, GError **error, gpointer source_tag);
+gboolean	e_client_proxy_call_finish_strv		(EClient *client, GAsyncResult *result, gchar ***out_strv, GError **error, gpointer source_tag);
+gboolean	e_client_proxy_call_finish_uint		(EClient *client, GAsyncResult *result, guint *out_uint, GError **error, gpointer source_tag);
+
+gboolean	e_client_proxy_call_sync_void__void		(EClient *client, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_void__boolean		(EClient *client, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_void__string		(EClient *client, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_void__strv		(EClient *client, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_void__uint		(EClient *client, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint *out_uint, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_boolean__void		(EClient *client, gboolean in_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_boolean__boolean	(EClient *client, gboolean in_boolean, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_boolean__string	(EClient *client, gboolean in_boolean, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_boolean__strv		(EClient *client, gboolean in_boolean, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_boolean__uint		(EClient *client, gboolean in_boolean, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, guint *out_uint, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_string__void		(EClient *client, const gchar *in_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_string__boolean	(EClient *client, const gchar *in_string, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_string__string		(EClient *client, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_string__strv		(EClient *client, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_string__uint		(EClient *client, const gchar *in_string, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, guint *out_uint, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_strv__void		(EClient *client, const gchar * const *in_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_strv__boolean		(EClient *client, const gchar * const *in_strv, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_strv__string		(EClient *client, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_strv__strv		(EClient *client, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_strv__uint		(EClient *client, const gchar * const *in_strv, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, guint *out_uint, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_uint__void		(EClient *client, guint in_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_uint__boolean		(EClient *client, guint in_uint, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_uint__string		(EClient *client, guint in_uint, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_uint__strv		(EClient *client, guint in_uint, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean	e_client_proxy_call_sync_uint__uint		(EClient *client, guint in_uint, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, guint *out_uint, GCancellable *cancellable, GError **error));
+
+G_END_DECLS
+
+#endif /* E_CLIENT_PRIVATE_H */
diff --git a/libedataserver/e-client.c b/libedataserver/e-client.c
index 39a0ae3..eb66a76 100644
--- a/libedataserver/e-client.c
+++ b/libedataserver/e-client.c
@@ -31,6 +31,7 @@
 #include "e-operation-pool.h"
 
 #include "e-client.h"
+#include "e-client-private.h"
 
 struct _EClientPrivate
 {
@@ -532,7 +533,7 @@ e_client_set_capabilities (EClient *client, const gchar *capabilities)
 
 	g_slist_foreach (client->priv->capabilities, (GFunc) g_free, NULL);
 	g_slist_free (client->priv->capabilities);
-	client->priv->capabilities = e_client_util_parse_capabilities (capabilities);
+	client->priv->capabilities = e_client_util_parse_comma_strings (capabilities);
 
 	g_static_rec_mutex_unlock (&client->priv->prop_mutex);
 
@@ -648,8 +649,8 @@ e_client_is_opened (EClient *client)
  * @opid: asynchronous operation ID
  *
  * Cancels particular asynchronous operation. The @opid is returned from
- * an asynchronous function, like e_client_open(). The function does nothing
- * if the asynchronous operation doesn't exist any more.
+ * an e_client_register_op(). The function does nothing if the asynchronous
+ * operation doesn't exist any more.
  *
  * Since: 3.2
  */
@@ -833,6 +834,195 @@ e_client_emit_backend_died (EClient *client)
 }
 
 /**
+ * e_client_get_backend_property:
+ * @client: an #EClient
+ * @prop_name: property name, whose value to retrieve; cannot be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Queries @client's backend for a property of name @prop_name.
+ * The call is finished by e_client_get_backend_property_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_get_backend_property (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+	EClientClass *klass;
+
+	g_return_if_fail (callback != NULL);
+	g_return_if_fail (client != NULL);
+	g_return_if_fail (E_IS_CLIENT (client));
+	g_return_if_fail (client->priv != NULL);
+	g_return_if_fail (prop_name != NULL);
+
+	klass = E_CLIENT_GET_CLASS (client);
+	g_return_if_fail (klass != NULL);
+	g_return_if_fail (klass->get_backend_property != NULL);
+
+	klass->get_backend_property (client, prop_name, cancellable, callback, user_data);
+}
+
+/**
+ * e_client_get_backend_property_finish:
+ * @client: an #EClient
+ * @result: a #GAsyncResult
+ * @prop_value: (out): Retrieved backend property value; cannot be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_get_backend_property().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_get_backend_property_finish (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error)
+{
+	EClientClass *klass;
+
+	g_return_val_if_fail (client != NULL, FALSE);
+	g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (client->priv != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	klass = E_CLIENT_GET_CLASS (client);
+	g_return_val_if_fail (klass != NULL, FALSE);
+	g_return_val_if_fail (klass->get_backend_property_finish != NULL, FALSE);
+
+	return klass->get_backend_property_finish (client, result, prop_value, error);
+}
+
+/**
+ * e_client_get_backend_property_sync:
+ * @client: an #EClient
+ * @prop_name: property name, whose value to retrieve; cannot be %NULL
+ * @prop_value: (out): Retrieved backend property value; cannot be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Queries @client's backend for a property of name @prop_name.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_get_backend_property_sync (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error)
+{
+	EClientClass *klass;
+
+	g_return_val_if_fail (client != NULL, FALSE);
+	g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (client->priv != NULL, FALSE);
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	klass = E_CLIENT_GET_CLASS (client);
+	g_return_val_if_fail (klass != NULL, FALSE);
+	g_return_val_if_fail (klass->get_backend_property_sync != NULL, FALSE);
+
+	return klass->get_backend_property_sync (client, prop_name, prop_value, cancellable, error);
+}
+
+/**
+ * e_client_set_backend_property:
+ * @client: an #EClient
+ * @prop_name: property name, whose value to change; cannot be %NULL
+ * @prop_value: property value, to set; cannot be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Sets @client's backend property of name @prop_name
+ * to value @prop_value. The call is finished
+ * by e_client_set_backend_property_finish() from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_set_backend_property (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+	EClientClass *klass;
+
+	g_return_if_fail (callback != NULL);
+	g_return_if_fail (client != NULL);
+	g_return_if_fail (E_IS_CLIENT (client));
+	g_return_if_fail (client->priv != NULL);
+	g_return_if_fail (prop_name != NULL);
+	g_return_if_fail (prop_value != NULL);
+
+	klass = E_CLIENT_GET_CLASS (client);
+	g_return_if_fail (klass != NULL);
+	g_return_if_fail (klass->set_backend_property != NULL);
+
+	klass->set_backend_property (client, prop_name, prop_value, cancellable, callback, user_data);
+}
+
+/**
+ * e_client_set_backend_property_finish:
+ * @client: an #EClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_set_backend_property().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_set_backend_property_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+	EClientClass *klass;
+
+	g_return_val_if_fail (client != NULL, FALSE);
+	g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (client->priv != NULL, FALSE);
+
+	klass = E_CLIENT_GET_CLASS (client);
+	g_return_val_if_fail (klass != NULL, FALSE);
+	g_return_val_if_fail (klass->set_backend_property_finish != NULL, FALSE);
+
+	return klass->set_backend_property_finish (client, result, error);
+}
+
+/**
+ * e_client_set_backend_property_sync:
+ * @client: an #EClient
+ * @prop_name: property name, whose value to change; cannot be %NULL
+ * @prop_value: property value, to set; cannot be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Sets @client's backend property of name @prop_name
+ * to value @prop_value.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_set_backend_property_sync (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error)
+{
+	EClientClass *klass;
+
+	g_return_val_if_fail (client != NULL, FALSE);
+	g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (client->priv != NULL, FALSE);
+	g_return_val_if_fail (prop_name != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+
+	klass = E_CLIENT_GET_CLASS (client);
+	g_return_val_if_fail (klass != NULL, FALSE);
+	g_return_val_if_fail (klass->set_backend_property_sync != NULL, FALSE);
+
+	return klass->set_backend_property_sync (client, prop_name, prop_value, cancellable, error);
+}
+
+/**
  * e_client_open:
  * @client: an #EClient
  * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
@@ -1159,40 +1349,40 @@ e_client_util_free_object_slist (GSList *objects)
 }
 
 /**
- * e_client_util_parse_capabilities:
- * @capabilitites: string of capabilities
+ * e_client_util_parse_comma_strings:
+ * @strings: string of comma-separated values
  *
- * Parse comma-separated list of capabilities into #GSList.
+ * Parses comma-separated list of values into #GSList.
  *
- * Reeturns: Newly allocated #GSList of newly allocated strings
- * corresponding to capabilities as parsed from @capabilities.
+ * Returns: Newly allocated #GSList of newly allocated strings
+ * corresponding to values parsed from @strings.
  * Free returned pointer with e_client_util_free_string_slist().
  *
  * Since: 3.2
  **/
 GSList *
-e_client_util_parse_capabilities (const gchar *capabilities)
+e_client_util_parse_comma_strings (const gchar *strings)
 {
-	GSList *caps_slist = NULL;
-	gchar **caps_strv = NULL;
+	GSList *strs_slist = NULL;
+	gchar **strs_strv = NULL;
 	gint ii;
 
-	if (!capabilities || !*capabilities)
+	if (!strings || !*strings)
 		return NULL;
 
-	caps_strv = g_strsplit (capabilities, ",", -1);
-	g_return_val_if_fail (caps_strv != NULL, NULL);
+	strs_strv = g_strsplit (strings, ",", -1);
+	g_return_val_if_fail (strs_strv != NULL, NULL);
 
-	for (ii = 0; caps_strv && caps_strv[ii]; ii++) {
-		gchar *cap = g_strstrip (caps_strv[ii]);
+	for (ii = 0; strs_strv && strs_strv[ii]; ii++) {
+		gchar *str = g_strstrip (strs_strv[ii]);
 
-		if (cap && *cap)
-			caps_slist = g_slist_prepend (caps_slist, g_strdup (cap));
+		if (str && *str)
+			strs_slist = g_slist_prepend (strs_slist, g_strdup (str));
 	}
 
-	g_strfreev (caps_strv);
+	g_strfreev (strs_strv);
 
-	return g_slist_reverse (caps_slist);
+	return g_slist_reverse (strs_slist);
 }
 
 /* for each known source calls check_func, which should return TRUE if the required
diff --git a/libedataserver/e-client.h b/libedataserver/e-client.h
index 26a6de1..e0a1dd1 100644
--- a/libedataserver/e-client.h
+++ b/libedataserver/e-client.h
@@ -76,6 +76,14 @@ struct _EClientClass {
 	GDBusProxy *	(* get_dbus_proxy) (EClient *client);
 	void		(* unwrap_dbus_error) (EClient *client, GError *dbus_error, GError **out_error);
 
+	void		(* get_backend_property) (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+	gboolean	(* get_backend_property_finish) (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error);
+	gboolean	(* get_backend_property_sync) (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error);
+
+	void		(* set_backend_property) (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+	gboolean	(* set_backend_property_finish) (EClient *client, GAsyncResult *result, GError **error);
+	gboolean	(* set_backend_property_sync) (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error);
+
 	void		(* open) (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
 	gboolean	(* open_finish) (EClient *client, GAsyncResult *result, GError **error);
 	gboolean	(* open_sync) (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error);
@@ -93,119 +101,42 @@ struct _EClientClass {
 	void		(* backend_died) (EClient *client);
 };
 
-GType		e_client_get_type		(void);
+GType		e_client_get_type			(void);
+
+ESource *	e_client_get_source			(EClient *client);
+const gchar *	e_client_get_uri			(EClient *client);
+const GSList *	e_client_get_capabilities		(EClient *client);
+gboolean	e_client_check_capability		(EClient *client, const gchar *capability);
+gboolean	e_client_is_readonly			(EClient *client);
+gboolean	e_client_is_online			(EClient *client);
+gboolean	e_client_is_opened			(EClient *client);
+
+void		e_client_cancel_all			(EClient *client);
 
-ESource *	e_client_get_source		(EClient *client);
-const gchar *	e_client_get_uri		(EClient *client);
-const GSList *	e_client_get_capabilities	(EClient *client);
-gboolean	e_client_check_capability	(EClient *client, const gchar *capability);
-gboolean	e_client_is_readonly		(EClient *client);
-gboolean	e_client_is_online		(EClient *client);
-gboolean	e_client_is_opened		(EClient *client);
+void		e_client_get_backend_property		(EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_client_get_backend_property_finish	(EClient *client, GAsyncResult *result, gchar **prop_value, GError **error);
+gboolean	e_client_get_backend_property_sync	(EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error);
 
-void		e_client_cancel_all		(EClient *client);
+void		e_client_set_backend_property		(EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_client_set_backend_property_finish	(EClient *client, GAsyncResult *result, GError **error);
+gboolean	e_client_set_backend_property_sync	(EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error);
 
-void		e_client_open			(EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_client_open_finish		(EClient *client, GAsyncResult *result, GError **error);
-gboolean	e_client_open_sync		(EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error);
+void		e_client_open				(EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_client_open_finish			(EClient *client, GAsyncResult *result, GError **error);
+gboolean	e_client_open_sync			(EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error);
 
-void		e_client_remove			(EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
-gboolean	e_client_remove_finish		(EClient *client, GAsyncResult *result, GError **error);
-gboolean	e_client_remove_sync		(EClient *client, GCancellable *cancellable, GError **error);
+void		e_client_remove				(EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_client_remove_finish			(EClient *client, GAsyncResult *result, GError **error);
+gboolean	e_client_remove_sync			(EClient *client, GCancellable *cancellable, GError **error);
 
 /* utility functions */
-gchar **	e_client_util_slist_to_strv	(const GSList *strings);
-GSList *	e_client_util_strv_to_slist	(const gchar * const *strv);
-GSList *	e_client_util_copy_string_slist	(GSList *copy_to, const GSList *strings);
-GSList *	e_client_util_copy_object_slist	(GSList *copy_to, const GSList *objects);
-void		e_client_util_free_string_slist	(GSList *strings);
-void		e_client_util_free_object_slist	(GSList *objects);
-GSList *	e_client_util_parse_capabilities(const gchar *capabilities);
-
-/* protected functions */
-void		e_client_set_capabilities	(EClient *client, const gchar *capabilities);
-void		e_client_set_readonly		(EClient *client, gboolean readonly);
-void		e_client_set_online		(EClient *client, gboolean is_online);
-guint32		e_client_register_op		(EClient *client, GCancellable *cancellable);
-void		e_client_unregister_op		(EClient *client, guint32 opid);
-void		e_client_process_authentication	(EClient *client, const ECredentials *credentials);
-
-gboolean	e_client_emit_authenticate	(EClient *client, ECredentials *credentials);
-void		e_client_emit_backend_error	(EClient *client, const gchar *error_msg);
-void		e_client_emit_backend_died	(EClient *client);
-
-ESource *	e_client_util_get_system_source	(ESourceList *source_list);
-gboolean	e_client_util_set_default	(ESourceList *source_list, ESource *source);
-ESource *	e_client_util_get_source_for_uri(ESourceList *source_list, const gchar *uri);
-
-/* protected functions simplifying sync/async calls */
-GDBusProxy *	e_client_get_dbus_proxy		(EClient *client);
-void		e_client_unwrap_dbus_error	(EClient *client, GError *dbus_error, GError **out_error);
-
-void		e_client_proxy_return_async_error	(EClient *client, const GError *error, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag);
-
-#define e_client_return_async_if_fail(_expr, _client, _callback, _user_data, _source_tag)	\
-	G_STMT_START {										\
-		if (!G_LIKELY (_expr)) {							\
-			GError *error;								\
-												\
-			error = g_error_new (							\
-				E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG,			\
-				"file %s:%d: %s: assertion `%s' failed",			\
-				__FILE__, __LINE__, G_STRFUNC, # _expr);			\
-												\
-			g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "%s", error->message);	\
-												\
-			e_client_proxy_return_async_error (					\
-				_client, error, _callback, _user_data, _source_tag);		\
-												\
-			g_error_free (error);							\
-		}										\
-	} G_STMT_END
-
-typedef gboolean (* EClientProxyFinishVoidFunc)		(GDBusProxy *proxy, GAsyncResult *result, GError **error);
-typedef gboolean (* EClientProxyFinishBooleanFunc)	(GDBusProxy *proxy, GAsyncResult *result, gboolean *out_boolean, GError **error);
-typedef gboolean (* EClientProxyFinishStringFunc)	(GDBusProxy *proxy, GAsyncResult *result, gchar **out_string, GError **error);
-typedef gboolean (* EClientProxyFinishStrvFunc)		(GDBusProxy *proxy, GAsyncResult *result, gchar ***out_strv, GError **error);
-typedef gboolean (* EClientProxyFinishUintFunc)		(GDBusProxy *proxy, GAsyncResult *result, guint *out_uint, GError **error);
-
-void		e_client_proxy_call_void	(EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
-void		e_client_proxy_call_boolean	(EClient *client, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
-void		e_client_proxy_call_string	(EClient *client, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, const gchar * in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
-void		e_client_proxy_call_strv	(EClient *client, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, const gchar * const * in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
-void		e_client_proxy_call_uint	(EClient *client, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
-
-gboolean	e_client_proxy_call_finish_void		(EClient *client, GAsyncResult *result, GError **error, gpointer source_tag);
-gboolean	e_client_proxy_call_finish_boolean	(EClient *client, GAsyncResult *result, gboolean *out_boolean, GError **error, gpointer source_tag);
-gboolean	e_client_proxy_call_finish_string	(EClient *client, GAsyncResult *result, gchar **out_string, GError **error, gpointer source_tag);
-gboolean	e_client_proxy_call_finish_strv		(EClient *client, GAsyncResult *result, gchar ***out_strv, GError **error, gpointer source_tag);
-gboolean	e_client_proxy_call_finish_uint		(EClient *client, GAsyncResult *result, guint *out_uint, GError **error, gpointer source_tag);
-
-gboolean	e_client_proxy_call_sync_void__void		(EClient *client, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_void__boolean		(EClient *client, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean *out_boolean, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_void__string		(EClient *client, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gchar **out_string, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_void__strv		(EClient *client, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gchar ***out_strv, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_void__uint		(EClient *client, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint *out_uint, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_boolean__void		(EClient *client, gboolean in_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_boolean__boolean	(EClient *client, gboolean in_boolean, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gboolean *out_boolean, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_boolean__string	(EClient *client, gboolean in_boolean, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gchar **out_string, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_boolean__strv		(EClient *client, gboolean in_boolean, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gchar ***out_strv, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_boolean__uint		(EClient *client, gboolean in_boolean, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, guint *out_uint, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_string__void		(EClient *client, const gchar *in_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_string__boolean	(EClient *client, const gchar *in_string, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gboolean *out_boolean, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_string__string		(EClient *client, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_string__strv		(EClient *client, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_string__uint		(EClient *client, const gchar *in_string, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, guint *out_uint, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_strv__void		(EClient *client, const gchar * const *in_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_strv__boolean		(EClient *client, const gchar * const *in_strv, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gboolean *out_boolean, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_strv__string		(EClient *client, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_strv__strv		(EClient *client, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_strv__uint		(EClient *client, const gchar * const *in_strv, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, guint *out_uint, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_uint__void		(EClient *client, guint in_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_uint__boolean		(EClient *client, guint in_uint, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gboolean *out_boolean, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_uint__string		(EClient *client, guint in_uint, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gchar **out_string, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_uint__strv		(EClient *client, guint in_uint, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gchar ***out_strv, GCancellable *cancellable, GError **error));
-gboolean	e_client_proxy_call_sync_uint__uint		(EClient *client, guint in_uint, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, guint *out_uint, GCancellable *cancellable, GError **error));
+gchar **	e_client_util_slist_to_strv		(const GSList *strings);
+GSList *	e_client_util_strv_to_slist		(const gchar * const *strv);
+GSList *	e_client_util_copy_string_slist		(GSList *copy_to, const GSList *strings);
+GSList *	e_client_util_copy_object_slist		(GSList *copy_to, const GSList *objects);
+void		e_client_util_free_string_slist		(GSList *strings);
+void		e_client_util_free_object_slist		(GSList *objects);
+GSList *	e_client_util_parse_comma_strings	(const gchar *capabilities);
 
 G_END_DECLS
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bb5f689..49e217f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -11,6 +11,7 @@ addressbook/libebook/e-book.c
 addressbook/libebook/e-book-client.c
 addressbook/libebook/e-contact.c
 addressbook/libebook/e-destination.c
+addressbook/libedata-book/e-book-backend.c
 addressbook/libedata-book/e-data-book-factory.c
 addressbook/libedata-book/e-data-book.c
 calendar/backends/caldav/e-cal-backend-caldav.c
@@ -27,6 +28,7 @@ calendar/libecal/e-cal-util.c
 calendar/libecal/e-cal.c
 calendar/libedata-cal/e-cal-backend-sexp.c
 calendar/libedata-cal/e-cal-backend-util.c
+calendar/libedata-cal/e-cal-backend.c
 calendar/libedata-cal/e-data-cal.c
 calendar/libedata-cal/e-data-cal-factory.c
 camel/camel-address.c
@@ -186,12 +188,12 @@ camel/providers/sendmail/camel-sendmail-transport.c
 camel/providers/smtp/camel-smtp-provider.c
 camel/providers/smtp/camel-smtp-transport.c
 libedataserver/e-categories.c
+libedataserver/e-client.c
 libedataserver/e-time-utils.c
 libedataserverui/e-book-auth-util.c
 libedataserverui/e-categories-dialog.c
 libedataserverui/e-category-completion.c
 libedataserverui/e-cell-renderer-color.c
-libedataserverui/e-client.c
 libedataserverui/e-client-authenticate.c
 libedataserverui/e-name-selector-dialog.c
 libedataserverui/e-name-selector-entry.c
diff --git a/tests/libebook/client/Makefile.am b/tests/libebook/client/Makefile.am
index f895172..774cac3 100644
--- a/tests/libebook/client/Makefile.am
+++ b/tests/libebook/client/Makefile.am
@@ -20,10 +20,7 @@ libclient_test_utils_la_LIBADD = 				\
 # Should be kept ordered approximately from least to most difficult/complex
 TESTS =								\
 	test-client-remove					\
-	test-client-get-required-fields				\
-	test-client-get-capabilities				\
-	test-client-get-supported-fields			\
-	test-client-get-supported-auth-methods			\
+	test-client-examine					\
 	test-client-add-contact					\
 	test-client-get-contact					\
 	test-client-get-book-view				\
@@ -64,18 +61,12 @@ test_client_async_LDADD=$(TEST_LIBS)
 test_client_async_CPPFLAGS=$(TEST_CPPFLAGS)
 test_client_add_contact_LDADD=$(TEST_LIBS)
 test_client_add_contact_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_examine_LDADD=$(TEST_LIBS)
+test_client_examine_CPPFLAGS=$(TEST_CPPFLAGS)
 test_client_get_book_view_LDADD=$(TEST_LIBS)
 test_client_get_book_view_CPPFLAGS=$(TEST_CPPFLAGS)
 test_client_get_contact_LDADD=$(TEST_LIBS)
 test_client_get_contact_CPPFLAGS=$(TEST_CPPFLAGS)
-test_client_get_required_fields_LDADD=$(TEST_LIBS)
-test_client_get_required_fields_CPPFLAGS=$(TEST_CPPFLAGS)
-test_client_get_capabilities_LDADD=$(TEST_LIBS)
-test_client_get_capabilities_CPPFLAGS=$(TEST_CPPFLAGS)
-test_client_get_supported_auth_methods_LDADD=$(TEST_LIBS)
-test_client_get_supported_auth_methods_CPPFLAGS=$(TEST_CPPFLAGS)
-test_client_get_supported_fields_LDADD=$(TEST_LIBS)
-test_client_get_supported_fields_CPPFLAGS=$(TEST_CPPFLAGS)
 test_client_modify_contact_LDADD=$(TEST_LIBS)
 test_client_modify_contact_CPPFLAGS=$(TEST_CPPFLAGS)
 test_client_remove_LDADD=$(TEST_LIBS)
diff --git a/tests/libebook/client/test-client-examine.c b/tests/libebook/client/test-client-examine.c
new file mode 100644
index 0000000..2f38b71
--- /dev/null
+++ b/tests/libebook/client/test-client-examine.c
@@ -0,0 +1,403 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libebook/e-book-client.h>
+#include <libedataserver/e-source-group.h>
+
+#include "client-test-utils.h"
+
+static gint running_async = 0;
+
+static GSList *
+get_known_prop_names (void)
+{
+	GSList *prop_names = NULL;
+
+	prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_LOADED);
+	prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_ONLINE);
+	prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_READONLY);
+	prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_CACHE_DIR);
+	prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_CAPABILITIES);
+	prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS);
+	prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS);
+	prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS);
+
+	return prop_names;
+}
+
+typedef struct _ExtraValues {
+	gpointer async_data;
+
+	GSList *todo_prop_names;
+	GHashTable *retrieved_props;
+} ExtraValues;
+
+static void
+extra_values_free (ExtraValues *evals)
+{
+	if (!evals)
+		return;
+
+	g_slist_free (evals->todo_prop_names);
+	g_hash_table_destroy (evals->retrieved_props);
+	g_free (evals);
+}
+
+static void
+print_each_property (gpointer prop_name, gpointer prop_value, gpointer user_data)
+{
+	g_return_if_fail (prop_name != NULL);
+
+	if (prop_value == NULL) {
+		g_print ("\t   %s: NULL\n", (const gchar *) prop_name);
+		return;
+	}
+
+	g_print ("\t   %s: ", (const gchar *) prop_name);
+
+	if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_CAPABILITIES) ||
+	    g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS) ||
+	    g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS) ||
+	    g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+		GSList *values = e_client_util_parse_comma_strings (prop_value), *v;
+
+		
+		for (v = values; v; v = v->next) {
+			if (v != values)
+				g_print (", ");
+
+			g_print ("'%s'", (const gchar *) v->data);
+		}
+
+		e_client_util_free_string_slist (values);
+	} else {
+		g_print ("'%s'", (const gchar *) prop_value);
+	}
+
+	g_print ("\n");
+}
+
+static void
+print_values (const ExtraValues *evals, EClient *client)
+{
+	const GSList *values;
+
+	g_return_if_fail (evals != NULL);
+
+	g_print ("\treadonly:%s\n", e_client_is_readonly (client) ? "yes" : "no");
+	g_print ("\tonline:%s\n", e_client_is_online (client) ? "yes" : "no");
+	g_print ("\tcapabilities: ");
+	values = e_client_get_capabilities (client);
+	if (!values) {
+		g_print ("NULL");
+	} else {
+		while (values) {
+			const gchar *cap = values->data;
+
+			g_print ("'%s'", cap);
+			if (!e_client_check_capability (client, cap))
+				g_print (" (not found in EClient)");
+
+			values = values->next;
+
+			if (values)
+				g_print (", ");
+		}
+	}
+	g_print ("\n");
+
+	g_print ("\tbackend properties:\n");
+	g_hash_table_foreach (evals->retrieved_props, print_each_property, NULL);
+}
+
+static void
+identify_source (ESource *source)
+{
+	const gchar *name, *uri;
+	gchar *abs_uri = NULL;
+
+	g_return_if_fail (source != NULL);
+
+	name = e_source_peek_name (source);
+	if (!name)
+		name = "Unknown name";
+
+	uri = e_source_peek_absolute_uri (source);
+	if (!uri) {
+		abs_uri = e_source_build_absolute_uri (source);
+		uri = abs_uri;
+	}
+	if (!uri)
+		uri = e_source_peek_relative_uri (source);
+	if (!uri)
+		uri = "Unknown uri";
+
+	g_print ("\n   Checking source '%s' (%s)\n", name, uri);
+
+	g_free (abs_uri);
+}
+
+static void
+identify_client (EBookClient *book_client)
+{
+	g_return_if_fail (book_client != NULL);
+	g_return_if_fail (E_IS_BOOK_CLIENT (book_client));
+
+	identify_source (e_client_get_source (E_CLIENT (book_client)));
+}
+
+static void client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data);
+
+static void
+continue_next_source (gpointer async_data)
+{
+	ESource *source = NULL;
+	EBookClient *book_client;
+	GError *error = NULL;
+
+	g_return_if_fail (async_data != NULL);
+
+	while (async_data && foreach_configured_source_async_next (&async_data, &source)) {
+		book_client = e_book_client_new (source, &error);
+		if (!book_client) {
+			identify_source (source);
+			report_error ("book client new", &error);
+			continue;
+		}
+
+		e_client_open (E_CLIENT (book_client), TRUE, NULL, client_opened_async, async_data);
+		break;
+	}
+
+	if (!async_data) {
+		running_async--;
+		if (!running_async)
+			stop_main_loop (0);
+	}
+}
+
+static void
+client_got_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+	ExtraValues *evals = user_data;
+	gchar *prop_value = NULL;
+	GError *error = NULL;
+	EBookClient *book_client;
+
+	g_return_if_fail (source_object != NULL);
+	g_return_if_fail (E_IS_BOOK_CLIENT (source_object));
+	g_return_if_fail (evals != NULL);
+
+	book_client = E_BOOK_CLIENT (source_object);
+
+	if (!e_client_get_backend_property_finish (E_CLIENT (book_client), result, &prop_value, &error)) {
+		identify_client (book_client);
+		report_error ("get backend property finish", &error);
+	}
+
+	g_hash_table_insert (evals->retrieved_props, evals->todo_prop_names->data, prop_value);
+	evals->todo_prop_names = g_slist_remove (evals->todo_prop_names, evals->todo_prop_names->data);
+
+	if (!evals->todo_prop_names) {
+		/* to cache them, as it can be fetched with idle as well */
+		e_client_get_capabilities (E_CLIENT (source_object));
+
+		identify_client (book_client);
+		print_values (evals, E_CLIENT (source_object));
+
+		g_object_unref (source_object);
+
+		continue_next_source (evals->async_data);
+		extra_values_free (evals);
+	} else {
+		e_client_get_backend_property (E_CLIENT (book_client), evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
+	}
+}
+
+static void
+client_set_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+	ExtraValues *evals = user_data;
+	GError *error = NULL;
+	EBookClient *book_client;
+
+	g_return_if_fail (source_object != NULL);
+	g_return_if_fail (E_IS_BOOK_CLIENT (source_object));
+	g_return_if_fail (evals != NULL);
+
+	book_client = E_BOOK_CLIENT (source_object);
+
+	if (!e_client_set_backend_property_finish (E_CLIENT (book_client), result, &error)) {
+		/* it may fail on the set_backend_property */
+		g_clear_error (&error);
+	} else {
+		identify_client (book_client);
+		g_printerr ("   Might fail on set_backend_property, but reported success\n");
+	}
+
+	e_client_get_backend_property (E_CLIENT (book_client), evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
+}
+
+static void
+client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data)
+{
+	ExtraValues *evals;
+	GError *error = NULL;
+	EBookClient *book_client;
+
+	g_return_if_fail (source_object != NULL);
+	g_return_if_fail (E_IS_BOOK_CLIENT (source_object));
+	g_return_if_fail (async_data != NULL);
+
+	book_client = E_BOOK_CLIENT (source_object);
+
+	if (!e_client_open_finish (E_CLIENT (source_object), result, &error)) {
+		identify_client (book_client);
+		report_error ("client open finish", &error);
+		g_object_unref (source_object);
+		continue_next_source (async_data);
+		return;
+	}
+
+	evals = g_new0 (ExtraValues, 1);
+	evals->async_data = async_data;
+	evals->todo_prop_names = get_known_prop_names ();
+	evals->retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+	e_client_set_backend_property (E_CLIENT (book_client), "*unknown*property*", "*value*", NULL, client_set_backend_property_async, evals);
+}
+
+static void
+check_source_sync (ESource *source)
+{
+	EBookClient *book_client;
+	GError *error = NULL;
+	GSList *properties, *p;
+	ExtraValues evals = { 0 };
+
+	g_return_if_fail (source != NULL);
+
+	identify_source (source);
+
+	book_client = e_book_client_new (source, &error);
+	if (!book_client) {
+		report_error ("book client new", &error);
+		return;
+	}
+
+	if (!e_client_open_sync (E_CLIENT (book_client), TRUE, NULL, &error)) {
+		report_error ("client open sync", &error);
+		g_object_unref (book_client);
+		return;
+	}
+
+	if (!e_client_set_backend_property_sync (E_CLIENT (book_client), "*unknown*property*", "*value*", NULL, &error)) {
+		g_clear_error (&error);
+	} else {
+		identify_client (book_client);
+		g_printerr ("   Might fail on set_backend_property, but reported success\n");
+	}
+
+	evals.retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+	properties = get_known_prop_names ();
+	for (p = properties; p != NULL; p = p->next) {
+		gchar *prop_value = NULL;
+
+		if (!e_client_get_backend_property_sync (E_CLIENT (book_client), p->data, &prop_value, NULL, &error)) {
+			identify_client (book_client);
+			report_error ("get backend property sync", &error);
+		} else {
+			g_hash_table_insert (evals.retrieved_props, p->data, prop_value);
+		}
+	}
+	g_slist_free (properties);
+
+	print_values (&evals, E_CLIENT (book_client));
+
+	g_hash_table_destroy (evals.retrieved_props);
+	g_object_unref (book_client);
+}
+
+static gboolean
+foreach_async (void)
+{
+	gpointer async_data;
+	ESource *source = NULL;
+	EBookClient *book_client;
+	GError *error = NULL;
+
+	async_data = foreach_configured_source_async_start (&source);
+	if (!async_data) {
+		stop_main_loop (1);
+		return FALSE;
+	}
+
+	running_async++;
+
+	while (book_client = e_book_client_new (source, &error), !book_client) {
+		identify_source (source);
+		report_error ("book client new", &error);
+
+		if (!foreach_configured_source_async_next (&async_data, &source)) {
+			running_async--;
+			if (!running_async)
+				stop_main_loop (0);
+			return FALSE;
+		}
+
+		identify_source (source);
+	}
+
+	e_client_open (E_CLIENT (book_client), TRUE, NULL, client_opened_async, async_data);
+
+	return TRUE;
+}
+
+static gboolean
+in_main_thread_idle_cb (gpointer unused)
+{
+	g_print ("* run in main thread with mainloop running\n");
+	foreach_configured_source (check_source_sync);
+	foreach_configured_source (check_source_sync);
+	foreach_configured_source (check_source_sync);
+	g_print ("---------------------------------------------------------\n\n");
+
+	g_print ("* run in main thread async\n");
+
+	if (!foreach_async ())
+		return FALSE;
+
+	return FALSE;
+}
+
+static gpointer
+worker_thread (gpointer unused)
+{
+	g_print ("* run in dedicated thread with mainloop running\n");
+	foreach_configured_source (check_source_sync);
+	foreach_configured_source (check_source_sync);
+	foreach_configured_source (check_source_sync);
+	g_print ("---------------------------------------------------------\n\n");
+
+	g_idle_add (in_main_thread_idle_cb, NULL);
+
+	return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+	main_initialize ();
+
+	g_print ("* run in main thread without mainloop\n");
+	foreach_configured_source (check_source_sync);
+	foreach_configured_source (check_source_sync);
+	foreach_configured_source (check_source_sync);
+	g_print ("---------------------------------------------------------\n\n");
+
+	start_in_thread_with_main_loop (worker_thread, NULL);
+
+	return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-examine.c b/tests/libecal/client/test-client-examine.c
index f32e9a1..7a0b9e5 100644
--- a/tests/libecal/client/test-client-examine.c
+++ b/tests/libecal/client/test-client-examine.c
@@ -9,12 +9,29 @@
 
 static gint running_async = 0;
 
+static GSList *
+get_known_prop_names (void)
+{
+	GSList *prop_names = NULL;
+
+	prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_LOADED);
+	prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_ONLINE);
+	prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_READONLY);
+	prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_CACHE_DIR);
+	prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_CAPABILITIES);
+	prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
+	prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS);
+	prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_DEFAULT_OBJECT);
+
+	return prop_names;
+}
+
 typedef struct _ExtraValues {
 	gpointer async_data;
 
+	GSList *todo_prop_names;
+	GHashTable *retrieved_props;
 	const gchar *cache_dir;
-	gchar *cal_address;
-	gchar *alarm_email_address;
 	icalcomponent *default_object;
 } ExtraValues;
 
@@ -26,28 +43,77 @@ extra_values_free (ExtraValues *evals)
 
 	if (evals->default_object)
 		icalcomponent_free (evals->default_object);
-	g_free (evals->cal_address);
-	g_free (evals->alarm_email_address);
+	g_slist_free (evals->todo_prop_names);
+	g_hash_table_destroy (evals->retrieved_props);
 	g_free (evals);
 }
 
 static void
-print_values (const GSList *values, const ExtraValues *evals, EClient *client)
+print_with_prefix (const gchar *str, const gchar *prefix)
+{
+	const gchar *p = str, *n;
+	while (n = strchr (p, '\n'), p) {
+		if (!n) {
+			g_print ("%s%s\n", prefix, p);
+			break;
+		} else {
+			g_print ("%s%.*s\n", prefix, (gint) (n - p), p);
+			n++;
+		}
+
+		p = n;
+	}
+}
+
+static void
+print_each_property (gpointer prop_name, gpointer prop_value, gpointer user_data)
+{
+	g_return_if_fail (prop_name != NULL);
+
+	if (prop_value == NULL) {
+		g_print ("\t   %s: NULL\n", (const gchar *) prop_name);
+		return;
+	}
+
+	g_print ("\t   %s: ", (const gchar *) prop_name);
+
+	if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAPABILITIES)) {
+		GSList *values = e_client_util_parse_comma_strings (prop_value), *v;
+
+		
+		for (v = values; v; v = v->next) {
+			if (v != values)
+				g_print (", ");
+
+			g_print ("'%s'", (const gchar *) v->data);
+		}
+
+		e_client_util_free_string_slist (values);
+	} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+		g_print ("\n");
+		print_with_prefix (prop_value, "\t\t");
+	} else {
+		g_print ("'%s'", (const gchar *) prop_value);
+	}
+
+	g_print ("\n");
+}
+
+static void
+print_values (const ExtraValues *evals, EClient *client)
 {
+	const GSList *values;
+
 	g_return_if_fail (evals != NULL);
 
-	g_print ("\treadonly:%s online:%s\n", e_client_is_readonly (client) ? "yes" : "no", e_client_is_online (client) ? "yes" : "no");
-	g_print ("\tcal address: %s%s%s\n", evals->cal_address ? "'" : "", evals->cal_address ? evals->cal_address : "none", evals->cal_address ? "'" : "");
-	g_print ("\talarm email address: %s%s%s\n", evals->alarm_email_address ? "'" : "", evals->alarm_email_address ? evals->alarm_email_address : "none", evals->alarm_email_address ? "'" : "");
+	g_print ("\treadonly:%s\n", e_client_is_readonly (client) ? "yes" : "no");
+	g_print ("\tonline:%s\n", e_client_is_online (client) ? "yes" : "no");
 	g_print ("\tcache dir: %s%s%s\n", evals->cache_dir ? "'" : "", evals->cache_dir ? evals->cache_dir : "none", evals->cache_dir ? "'" : "");
 	g_print ("\tcapabilities: ");
+	values = e_client_get_capabilities (client);
 	if (!values) {
 		g_print ("NULL");
-		if (e_client_get_capabilities (client))
-			g_print (", but client has %d capabilities", g_slist_length ((GSList *) e_client_get_capabilities (client)));
 	} else {
-		gint client_caps = g_slist_length ((GSList *) e_client_get_capabilities (client)), my_caps = g_slist_length ((GSList *) values);
-
 		while (values) {
 			const gchar *cap = values->data;
 
@@ -60,31 +126,18 @@ print_values (const GSList *values, const ExtraValues *evals, EClient *client)
 			if (values)
 				g_print (", ");
 		}
-
-		if (client_caps != my_caps) {
-			g_print ("\n\t * has different count of capabilities in EClient (%d) and returned (%d)", client_caps, my_caps);
-		}
-
 	}
 	g_print ("\n");
+
 	g_print ("\tdefault object: %s\n", evals->default_object ? "" : "none");
 	if (evals->default_object) {
 		gchar *comp_str = icalcomponent_as_ical_string_r (evals->default_object);
-		const gchar *p = comp_str, *n;
-		while (n = strchr (p, '\n'), p) {
-			if (!n) {
-				g_print ("\t   %s\n", p);
-				break;
-			} else {
-				g_print ("\t   %.*s\n", (gint) (n - p), p);
-				n++;
-			}
-
-			p = n;
-		}
-
+		print_with_prefix (comp_str, "\t   ");
 		g_free (comp_str);
 	}
+
+	g_print ("\tbackend properties:\n");
+	g_hash_table_foreach (evals->retrieved_props, print_each_property, NULL);
 }
 
 static void
@@ -130,7 +183,7 @@ identify_source (ESource *source, ECalClientSourceType source_type)
 }
 
 static void
-identify_cal_client (ECalClient *cal_client)
+identify_client (ECalClient *cal_client)
 {
 	g_return_if_fail (cal_client != NULL);
 	g_return_if_fail (E_IS_CAL_CLIENT (cal_client));
@@ -171,10 +224,10 @@ continue_next_source (gpointer async_data)
 }
 
 static void
-client_got_values_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+client_got_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
 {
 	ExtraValues *evals = user_data;
-	GSList *values = NULL;
+	gchar *prop_value = NULL;
 	GError *error = NULL;
 	ECalClient *cal_client;
 
@@ -184,58 +237,38 @@ client_got_values_async (GObject *source_object, GAsyncResult *result, gpointer
 
 	cal_client = E_CAL_CLIENT (source_object);
 
-	if (!e_cal_client_get_capabilities_finish (cal_client, result, &values, &error)) {
-		identify_cal_client (cal_client);
-		report_error ("get capabilities finish", &error);
-	} else {
-		/* to cache them, as it can be fetched with idle as well */
-		e_client_get_capabilities (E_CLIENT (source_object));
-
-		evals->cache_dir = e_cal_client_get_local_attachment_store (cal_client);
-
-		identify_cal_client (cal_client);
-		print_values (values, evals, E_CLIENT (source_object));
-
-		e_client_util_free_string_slist (values);
+	if (!e_client_get_backend_property_finish (E_CLIENT (cal_client), result, &prop_value, &error)) {
+		identify_client (cal_client);
+		report_error ("get backend property finish", &error);
 	}
 
-	g_object_unref (source_object);
-
-	continue_next_source (evals->async_data);
-	extra_values_free (evals);
-}
+	g_hash_table_insert (evals->retrieved_props, evals->todo_prop_names->data, prop_value);
+	evals->todo_prop_names = g_slist_remove (evals->todo_prop_names, evals->todo_prop_names->data);
 
-static void
-client_got_alarm_email_address_async (GObject *source_object, GAsyncResult *result, gpointer evals_data)
-{
-	ExtraValues *evals = evals_data;
-	ECalClient *cal_client;
-	GError *error = NULL;
+	if (!evals->todo_prop_names) {
+		evals->cache_dir = e_cal_client_get_local_attachment_store (cal_client);
 
-	g_return_if_fail (source_object != NULL);
-	g_return_if_fail (E_IS_CAL_CLIENT (source_object));
-	g_return_if_fail (evals != NULL);
+		/* to cache them, as it can be fetched with idle as well */
+		e_client_get_capabilities (E_CLIENT (source_object));
 
-	cal_client = E_CAL_CLIENT (source_object);
+		identify_client (cal_client);
+		print_values (evals, E_CLIENT (source_object));
 
-	if (!e_cal_client_get_alarm_email_address_finish (cal_client, result, &evals->alarm_email_address, &error)) {
-		identify_cal_client (cal_client);
-		report_error ("get alarm email address finish", &error);
 		g_object_unref (source_object);
+
 		continue_next_source (evals->async_data);
 		extra_values_free (evals);
-		return;
+	} else {
+		e_client_get_backend_property (E_CLIENT (cal_client), evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
 	}
-
-	e_cal_client_get_capabilities (cal_client, NULL, client_got_values_async, evals);
 }
 
 static void
-client_got_cal_address_async (GObject *source_object, GAsyncResult *result, gpointer evals_data)
+client_set_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
 {
-	ExtraValues *evals = evals_data;
-	ECalClient *cal_client;
+	ExtraValues *evals = user_data;
 	GError *error = NULL;
+	ECalClient *cal_client;
 
 	g_return_if_fail (source_object != NULL);
 	g_return_if_fail (E_IS_CAL_CLIENT (source_object));
@@ -243,16 +276,15 @@ client_got_cal_address_async (GObject *source_object, GAsyncResult *result, gpoi
 
 	cal_client = E_CAL_CLIENT (source_object);
 
-	if (!e_cal_client_get_cal_email_address_finish (cal_client, result, &evals->cal_address, &error)) {
-		identify_cal_client (cal_client);
-		report_error ("get cal address finish", &error);
-		g_object_unref (source_object);
-		continue_next_source (evals->async_data);
-		extra_values_free (evals);
-		return;
+	if (!e_client_set_backend_property_finish (E_CLIENT (cal_client), result, &error)) {
+		/* it may fail on the set_backend_property */
+		g_clear_error (&error);
+	} else {
+		identify_client (cal_client);
+		g_printerr ("   Might fail on set_backend_property, but reported success\n");
 	}
 
-	e_cal_client_get_alarm_email_address (cal_client, NULL, client_got_alarm_email_address_async, evals);
+	e_client_get_backend_property (E_CLIENT (cal_client), evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
 }
 
 static void
@@ -269,11 +301,11 @@ client_got_default_object_async (GObject *source_object, GAsyncResult *result, g
 	cal_client = E_CAL_CLIENT (source_object);
 
 	if (!e_cal_client_get_default_object_finish (cal_client, result, &evals->default_object, &error)) {
-		identify_cal_client (cal_client);
+		identify_client (cal_client);
 		report_error ("get default object finish", &error);
 	}
 
-	e_cal_client_get_cal_email_address (cal_client, NULL, client_got_cal_address_async, evals);
+	e_client_set_backend_property (E_CLIENT (cal_client), "*unknown*property*", "*value*", NULL, client_set_backend_property_async, evals);
 }
 
 static void
@@ -290,7 +322,7 @@ client_opened_async (GObject *source_object, GAsyncResult *result, gpointer asyn
 	cal_client = E_CAL_CLIENT (source_object);
 
 	if (!e_client_open_finish (E_CLIENT (source_object), result, &error)) {
-		identify_cal_client (cal_client);
+		identify_client (cal_client);
 		report_error ("client open finish", &error);
 		g_object_unref (source_object);
 		continue_next_source (async_data);
@@ -299,6 +331,8 @@ client_opened_async (GObject *source_object, GAsyncResult *result, gpointer asyn
 
 	evals = g_new0 (ExtraValues, 1);
 	evals->async_data = async_data;
+	evals->todo_prop_names = get_known_prop_names ();
+	evals->retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
 	
 	e_cal_client_get_default_object (cal_client, NULL, client_got_default_object_async, evals);
 }
@@ -308,7 +342,7 @@ check_source_sync (ESource *source, ECalClientSourceType source_type)
 {
 	ECalClient *cal_client;
 	GError *error = NULL;
-	GSList *values = NULL;
+	GSList *properties, *p;
 	ExtraValues evals = { 0 };
 
 	g_return_if_fail (source != NULL);
@@ -327,32 +361,38 @@ check_source_sync (ESource *source, ECalClientSourceType source_type)
 		return;
 	}
 
-	if (!e_cal_client_get_capabilities_sync (cal_client, &values, NULL, &error)) {
-		report_error ("get capabilities sync", &error);
-		g_object_unref (cal_client);
-		return;
+	if (!e_cal_client_get_default_object_sync (cal_client, &evals.default_object, NULL, &error)) {
+		report_error ("get default object sync", &error);
 	}
 
-	if (!e_cal_client_get_cal_email_address_sync (cal_client, &evals.cal_address, NULL, &error)) {
-		report_error ("get cal address sync", &error);
+	if (!e_client_set_backend_property_sync (E_CLIENT (cal_client), "*unknown*property*", "*value*", NULL, &error)) {
+		g_clear_error (&error);
+	} else {
+		identify_client (cal_client);
+		g_printerr ("   Might fail on set_backend_property, but reported success\n");
 	}
 
-	if (!e_cal_client_get_alarm_email_address_sync (cal_client, &evals.alarm_email_address, NULL, &error)) {
-		report_error ("get alarm email address sync", &error);
-	}
+	evals.retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
 
-	if (!e_cal_client_get_default_object_sync (cal_client, &evals.default_object, NULL, &error)) {
-		report_error ("get default object sync", &error);
+	properties = get_known_prop_names ();
+	for (p = properties; p != NULL; p = p->next) {
+		gchar *prop_value = NULL;
+
+		if (!e_client_get_backend_property_sync (E_CLIENT (cal_client), p->data, &prop_value, NULL, &error)) {
+			identify_client (cal_client);
+			report_error ("get backend property sync", &error);
+		} else {
+			g_hash_table_insert (evals.retrieved_props, p->data, prop_value);
+		}
 	}
+	g_slist_free (properties);
 
 	evals.cache_dir = e_cal_client_get_local_attachment_store (cal_client);
 
-	print_values (values, &evals, E_CLIENT (cal_client));
+	print_values (&evals, E_CLIENT (cal_client));
 
-	g_free (evals.cal_address);
-	g_free (evals.alarm_email_address);
+	g_hash_table_destroy (evals.retrieved_props);
 	icalcomponent_free (evals.default_object);
-	e_client_util_free_string_slist (values);
 	g_object_unref (cal_client);
 }
 



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