[evolution-data-server/dbus: 9/13] Port libebook to DBus



commit f05a0cc1d5c1e1887b37a3fab0a99b6170ea12e2
Author: Ross Burton <ross linux intel com>
Date:   Mon Jun 15 08:36:35 2009 +0100

    Port libebook to DBus

 addressbook/libebook/Makefile.am            |   44 +-
 addressbook/libebook/e-book-listener.c      |  495 ----
 addressbook/libebook/e-book-listener.h      |  120 -
 addressbook/libebook/e-book-marshal.list    |    5 +
 addressbook/libebook/e-book-view-listener.c |  405 ---
 addressbook/libebook/e-book-view-listener.h |   93 -
 addressbook/libebook/e-book-view-private.h  |   30 +-
 addressbook/libebook/e-book-view.c          |  455 ++--
 addressbook/libebook/e-book.c               | 3850 +++++++--------------------
 addressbook/libebook/e-error.h              |   40 +
 addressbook/libebook/libebook.pc.in         |    5 +-
 11 files changed, 1275 insertions(+), 4267 deletions(-)
---
diff --git a/addressbook/libebook/Makefile.am b/addressbook/libebook/Makefile.am
index f78cf36..5ba9a49 100644
--- a/addressbook/libebook/Makefile.am
+++ b/addressbook/libebook/Makefile.am
@@ -8,37 +8,18 @@ INCLUDES =						\
 	-I$(top_builddir)/addressbook/libebook		\
         $(EVOLUTION_ADDRESSBOOK_CFLAGS)
 
-# The corba stubs and skels
-CORBA_GENERATED_C =				\
-	Evolution-DataServer-Addressbook-common.c		\
-	Evolution-DataServer-Addressbook-skels.c		\
-	Evolution-DataServer-Addressbook-stubs.c
-CORBA_GENERATED_H =			\
-	Evolution-DataServer-Addressbook.h
-
-CORBA_GENERATED = $(CORBA_GENERATED_C) $(CORBA_GENERATED_H)
-
-idls =						\
-	$(srcdir)/../idl/Evolution-DataServer-Addressbook.idl
-
-idl_flags = $(IDL_INCLUDES)
-
-$(CORBA_GENERATED_H): $(idls)
-	$(ORBIT_IDL) $(idl_flags) $(srcdir)/../idl/Evolution-DataServer-Addressbook.idl
-$(CORBA_GENERATED_C): $(CORBA_GENERATED_H)
+# The marshallers
+MARSHAL_GENERATED = e-book-marshal.c e-book-marshal.h
+ EVO_MARSHAL_RULE@
 
 # The library
 lib_LTLIBRARIES = libebook-1.2.la
 
-libebook_1_2_la_SOURCES =				\
-	$(CORBA_GENERATED_C)				\
-	$(CORBA_GENERATED_H)				\
+libebook_1_2_la_SOURCES =					\
+	$(MARSHAL_GENERATED)				\
+	$(DBUS_GENERATED_H)				\
 	e-address-western.c				\
-	e-book-listener.c				\
-	e-book-listener.h				\
 	e-book-query.c					\
-	e-book-view-listener.c				\
-	e-book-view-listener.h				\
 	e-book-view-private.h				\
 	e-book-view.c					\
 	e-book.c					\
@@ -46,7 +27,8 @@ libebook_1_2_la_SOURCES =				\
 	e-destination.c					\
 	e-name-western.c				\
 	e-name-western-tables.h                         \
-	e-vcard.c
+	e-vcard.c					\
+	e-error.h
 
 libebook_1_2_la_LIBADD =					\
 	$(top_builddir)/camel/libcamel-1.2.la			\
@@ -78,11 +60,19 @@ e-name-western-tables.h: e-name-western-tables.h.in
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libebook-$(API_VERSION).pc
 
-BUILT_SOURCES = $(CORBA_GENERATED)
+DBUS_GENERATED_H = e-data-book-factory-bindings.h e-data-book-bindings.h e-data-book-view-bindings.h
+%-glue.h: $(top_srcdir)/addressbook/libedata-book/%.xml
+	dbus-binding-tool --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
+
+%-bindings.h: $(top_srcdir)/addressbook/libedata-book/%.xml
+	dbus-binding-tool --mode=glib-client --output=$@ --prefix=$(subst -,_,$*) $^
+
+BUILT_SOURCES = $(DBUS_GENERATED_H) $(MARSHAL_GENERATED)
 CLEANFILES    = $(BUILT_SOURCES)
 DISTCLEANFILES = $(pkgconfig_DATA)
 
 EXTRA_DIST = 						\
+	e-book-marshal.list				\
 	$(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in)     \
 	e-name-western-tables.h.in                      \
 	gen-western-table.py
diff --git a/addressbook/libebook/e-book-marshal.list b/addressbook/libebook/e-book-marshal.list
new file mode 100644
index 0000000..680ea03
--- /dev/null
+++ b/addressbook/libebook/e-book-marshal.list
@@ -0,0 +1,5 @@
+NONE:NONE
+NONE:BOOL
+NONE:POINTER
+NONE:STRING
+NONE:INT
diff --git a/addressbook/libebook/e-book-view-private.h b/addressbook/libebook/e-book-view-private.h
index a8e546a..8b7db45 100644
--- a/addressbook/libebook/e-book-view-private.h
+++ b/addressbook/libebook/e-book-view-private.h
@@ -1,25 +1,31 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * The Evolution addressbook client object.
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
  *
- * Author:
- *   Nat Friedman (nat ximian com)
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
  *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
  */
 
 #ifndef __E_BOOK_VIEW_PRIVATE_H__
 #define __E_BOOK_VIEW_PRIVATE_H__
 
-#include <glib.h>
-#include <glib-object.h>
-
-#include "Evolution-DataServer-Addressbook.h"
-#include "e-book-view-listener.h"
-
-EBookView *e_book_view_new (GNOME_Evolution_Addressbook_BookView corba_book_view, EBookViewListener *listener);
+#include "e-book.h"
+#include "e-book-view.h"
 
-void e_book_view_set_book (EBookView *book_view, struct _EBook *book);
+EBookView *_e_book_view_new (EBook *book, DBusGProxy *view_proxy);
 
 G_END_DECLS
 
diff --git a/addressbook/libebook/e-book-view.c b/addressbook/libebook/e-book-view.c
index 1ebe549..56e23f0 100644
--- a/addressbook/libebook/e-book-view.c
+++ b/addressbook/libebook/e-book-view.c
@@ -1,30 +1,42 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * The Evolution addressbook client object.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
  *
- * Author:
- *   Nat Friedman (nat ximian com)
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
  *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
  */
 
-#include <config.h>
-
-#include "e-book-view-listener.h"
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "e-book.h"
 #include "e-book-view.h"
 #include "e-book-view-private.h"
-#include "e-book.h"
-
-static GObjectClass *parent_class;
-
-struct _EBookViewPrivate {
-	GNOME_Evolution_Addressbook_BookView     corba_book_view;
+#include "e-data-book-view-bindings.h"
+#include "e-book-marshal.h"
 
-	EBook                 *book;
+G_DEFINE_TYPE(EBookView, e_book_view, G_TYPE_OBJECT);
 
-	EBookViewListener     *listener;
+#define E_BOOK_VIEW_GET_PRIVATE(o)					\
+	(G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_BOOK_VIEW, EBookViewPrivate))
 
-	gint                    response_id;
+struct _EBookViewPrivate {
+	EBook *book;
+	DBusGProxy *view_proxy;
+	gboolean running;
 };
 
 enum {
@@ -36,157 +48,124 @@ enum {
 	LAST_SIGNAL
 };
 
-static guint e_book_view_signals [LAST_SIGNAL];
+static guint signals [LAST_SIGNAL];
 
 static void
-e_book_view_do_added_event (EBookView                 *book_view,
-			    EBookViewListenerResponse *resp)
+status_message_cb (DBusGProxy *proxy, const gchar *message, EBookView *book_view)
 {
-	g_signal_emit (book_view, e_book_view_signals [CONTACTS_ADDED], 0,
-		       resp->contacts);
-}
+	if (!book_view->priv->running)
+		return;
 
-static void
-e_book_view_do_modified_event (EBookView                 *book_view,
-			       EBookViewListenerResponse *resp)
-{
-	g_signal_emit (book_view, e_book_view_signals [CONTACTS_CHANGED], 0,
-		       resp->contacts);
+	g_signal_emit (book_view, signals[STATUS_MESSAGE], 0, message);
 }
 
 static void
-e_book_view_do_removed_event (EBookView                 *book_view,
-			      EBookViewListenerResponse *resp)
+contacts_added_cb (DBusGProxy *proxy, const gchar **vcards, EBookView *book_view)
 {
-	g_signal_emit (book_view, e_book_view_signals [CONTACTS_REMOVED], 0,
-		       resp->ids);
-}
+	const gchar **p;
+	GList *contacts = NULL;
 
-static void
-e_book_view_do_complete_event (EBookView                 *book_view,
-			       EBookViewListenerResponse *resp)
-{
-	g_signal_emit (book_view, e_book_view_signals [SEQUENCE_COMPLETE], 0,
-		       resp->status);
-}
+	if (!book_view->priv->running)
+		return;
 
-static void
-e_book_view_do_status_message_event (EBookView                 *book_view,
-				     EBookViewListenerResponse *resp)
-{
-	g_signal_emit (book_view, e_book_view_signals [STATUS_MESSAGE], 0,
-		       resp->message);
-}
+	for (p = vcards; *p; p++) {
+		contacts = g_list_prepend (contacts, e_contact_new_from_vcard (*p));
+	}
+	contacts = g_list_reverse (contacts);
+
+	g_signal_emit (book_view, signals[CONTACTS_ADDED], 0, contacts);
 
+	g_list_foreach (contacts, (GFunc)g_object_unref, NULL);
+	g_list_free (contacts);
+}
 
 static void
-e_book_view_handle_response (EBookViewListener *listener, EBookViewListenerResponse *resp, EBookView *book_view)
+contacts_changed_cb (DBusGProxy *proxy, const gchar **vcards, EBookView *book_view)
 {
-	/* we shouldn't need this check.  EBVL only emits the signal when resp != NULL */
-	if (resp == NULL)
+	const gchar **p;
+	GList *contacts = NULL;
+
+	if (!book_view->priv->running)
 		return;
 
-	switch (resp->op) {
-	case ContactsAddedEvent:
-		e_book_view_do_added_event (book_view, resp);
-		break;
-	case ContactsModifiedEvent:
-		e_book_view_do_modified_event (book_view, resp);
-		break;
-	case ContactsRemovedEvent:
-		e_book_view_do_removed_event (book_view, resp);
-		break;
-	case SequenceCompleteEvent:
-		e_book_view_do_complete_event (book_view, resp);
-		break;
-	case StatusMessageEvent:
-		e_book_view_do_status_message_event (book_view, resp);
-		break;
-	default:
-		g_error ("EBookView: Unknown operation %d in listener queue!\n",
-			 resp->op);
-		break;
+	for (p = vcards; *p; p++) {
+		contacts = g_list_prepend (contacts, e_contact_new_from_vcard (*p));
 	}
+	contacts = g_list_reverse (contacts);
+
+	g_signal_emit (book_view, signals[CONTACTS_CHANGED], 0, contacts);
+
+	g_list_foreach (contacts, (GFunc)g_object_unref, NULL);
+	g_list_free (contacts);
 }
 
-static gboolean
-e_book_view_construct (EBookView *book_view, GNOME_Evolution_Addressbook_BookView corba_book_view, EBookViewListener *listener)
+static void
+contacts_removed_cb (DBusGProxy *proxy, const gchar **ids, EBookView *book_view)
 {
-	CORBA_Environment  ev;
-	g_return_val_if_fail (book_view != NULL,     FALSE);
-	g_return_val_if_fail (E_IS_BOOK_VIEW (book_view), FALSE);
-
-	/*
-	 * Copy in the corba_book_view.
-	 */
-	CORBA_exception_init (&ev);
-
-	book_view->priv->corba_book_view = bonobo_object_dup_ref(corba_book_view, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_book_view_construct: Exception duplicating corba_book_view.\n");
-		CORBA_exception_free (&ev);
-		book_view->priv->corba_book_view = CORBA_OBJECT_NIL;
-		return FALSE;
-	}
+	const gchar **p;
+	GList *list = NULL;
 
-	CORBA_exception_free (&ev);
+	if (!book_view->priv->running)
+		return;
 
-	/*
-	 * Create our local BookListener interface.
-	 */
-	book_view->priv->listener = listener;
-	book_view->priv->response_id = g_signal_connect (book_view->priv->listener, "response",
-							 G_CALLBACK (e_book_view_handle_response), book_view);
+	for (p = ids; *p; p++) {
+		list = g_list_prepend (list, (char*)*p);
+	}
+	list = g_list_reverse (list);
 
-	bonobo_object_ref(BONOBO_OBJECT(book_view->priv->listener));
+	g_signal_emit (book_view, signals[CONTACTS_REMOVED], 0, list);
 
-	return TRUE;
+	/* No need to free the values, our caller will */
+	g_list_free (list);
 }
 
-/**
- * e_book_view_new:
- * @corba_book_view: a CORBA BookView object
- * @listener: an #EBookViewListener
- *
- * Creates a new #EBookView based on @corba_book_view and listening to
- * @listener.  This is a private function, applications should call
- * #e_book_get_book_view or #e_book_async_get_book_view.
- *
- * Return value: A new #EBookView.
- **/
-EBookView *
-e_book_view_new (GNOME_Evolution_Addressbook_BookView corba_book_view, EBookViewListener *listener)
+static void
+complete_cb (DBusGProxy *proxy, guint status, EBookView *book_view)
 {
-	EBookView *book_view;
-
-	book_view = g_object_new (E_TYPE_BOOK_VIEW, NULL);
-
-	if (! e_book_view_construct (book_view, corba_book_view, listener)) {
-		g_object_unref (book_view);
-		return NULL;
-	}
+	if (!book_view->priv->running)
+		return;
 
-	return book_view;
+	g_signal_emit (book_view, signals[SEQUENCE_COMPLETE], 0, status);
 }
 
-/**
- * e_book_view_set_book:
- * @book_view: an #EBookView
+/*
+ * e_book_view_new:
  * @book: an #EBook
+ * @view_proxy: The #DBusGProxy to get signals from
  *
- * Makes @book_view listen to changes in @book. This function apparently
- * has no effect for the time being.
+ * Creates a new #EBookView based on #EBook and listening to @view_proxy.  This
+ * is a private function, applications should call #e_book_get_book_view or
+ * #e_book_async_get_book_view.
+ *
+ * Return value: A new #EBookView.
  **/
-void
-e_book_view_set_book (EBookView *book_view, EBook *book)
+EBookView *
+_e_book_view_new (EBook *book, DBusGProxy *view_proxy)
 {
-	g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
-	g_return_if_fail (book && E_IS_BOOK (book));
-	g_return_if_fail (book_view->priv->book == NULL);
-
-	book_view->priv->book = book;
-	g_object_ref (book);
+	EBookView *view;
+	EBookViewPrivate *priv;
+
+	view = g_object_new (E_TYPE_BOOK_VIEW, NULL);
+	priv = view->priv;
+
+	priv->book = g_object_ref (book);
+
+	/* Take ownership of the view_proxy object */
+	priv->view_proxy = view_proxy;
+	g_object_add_weak_pointer (G_OBJECT (view_proxy), (gpointer)&priv->view_proxy);
+
+	dbus_g_proxy_add_signal (view_proxy, "StatusMessage", G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (view_proxy, "StatusMessage", G_CALLBACK (status_message_cb), view, NULL);
+	dbus_g_proxy_add_signal (view_proxy, "ContactsAdded", G_TYPE_STRV, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (view_proxy, "ContactsAdded", G_CALLBACK (contacts_added_cb), view, NULL);
+	dbus_g_proxy_add_signal (view_proxy, "ContactsChanged", G_TYPE_STRV, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (view_proxy, "ContactsChanged", G_CALLBACK (contacts_changed_cb), view, NULL);
+	dbus_g_proxy_add_signal (view_proxy, "ContactsRemoved", G_TYPE_STRV, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (view_proxy, "ContactsRemoved", G_CALLBACK (contacts_removed_cb), view, NULL);
+	dbus_g_proxy_add_signal (view_proxy, "Complete", G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (view_proxy, "Complete", G_CALLBACK (complete_cb), view, NULL);
+
+	return view;
 }
 
 /**
@@ -197,10 +176,10 @@ e_book_view_set_book (EBookView *book_view, EBook *book)
  *
  * Return value: an #EBook.
  **/
-EBook*
+EBook *
 e_book_view_get_book (EBookView *book_view)
 {
-	g_return_val_if_fail (book_view && E_IS_BOOK_VIEW (book_view), NULL);
+	g_return_val_if_fail (E_IS_BOOK_VIEW (book_view), NULL);
 
 	return book_view->priv->book;
 }
@@ -214,18 +193,24 @@ e_book_view_get_book (EBookView *book_view)
 void
 e_book_view_start (EBookView *book_view)
 {
-	CORBA_Environment ev;
+	GError *error = NULL;
 
-	g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
+	g_return_if_fail (E_IS_BOOK_VIEW (book_view));
 
-	CORBA_exception_init (&ev);
+	book_view->priv->running = TRUE;
 
-	e_book_view_listener_start (book_view->priv->listener);
+	if (book_view->priv->view_proxy) {
+		org_gnome_evolution_dataserver_addressbook_BookView_start (book_view->priv->view_proxy, &error);
+		if (error) {
+			g_warning ("Cannot start book view: %s\n", error->message);
 
-	GNOME_Evolution_Addressbook_BookView_start (book_view->priv->corba_book_view, &ev);
+			/* Fake a sequence-complete so that the application knows this failed */
+			/* TODO: use get_status_from_error */
+			g_signal_emit (book_view, signals[SEQUENCE_COMPLETE], 0,
+				       E_BOOK_ERROR_CORBA_EXCEPTION);
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("corba exception._major = %d\n", ev._major);
+			g_error_free (error);
+		}
 	}
 }
 
@@ -238,69 +223,48 @@ e_book_view_start (EBookView *book_view)
 void
 e_book_view_stop (EBookView *book_view)
 {
-	CORBA_Environment ev;
-
-	g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
-
-	CORBA_exception_init (&ev);
+	GError *error = NULL;
 
-	e_book_view_listener_stop (book_view->priv->listener);
+	g_return_if_fail (E_IS_BOOK_VIEW (book_view));
 
-	GNOME_Evolution_Addressbook_BookView_stop (book_view->priv->corba_book_view, &ev);
+	book_view->priv->running = FALSE;
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("corba exception._major = %d\n", ev._major);
+	if (book_view->priv->view_proxy) {
+		org_gnome_evolution_dataserver_addressbook_BookView_stop (book_view->priv->view_proxy, &error);
+		if (error) {
+			g_warning ("Cannot stop book view: %s\n", error->message);
+			g_error_free (error);
+		}
 	}
 }
 
 static void
 e_book_view_init (EBookView *book_view)
 {
-	book_view->priv                      = g_new0 (EBookViewPrivate, 1);
-	book_view->priv->book                = NULL;
-	book_view->priv->corba_book_view     = CORBA_OBJECT_NIL;
-	book_view->priv->listener            = NULL;
-	book_view->priv->response_id = 0;
+	EBookViewPrivate *priv = E_BOOK_VIEW_GET_PRIVATE (book_view);
+
+	priv->book = NULL;
+	priv->view_proxy = NULL;
+	priv->running = FALSE;
+
+	book_view->priv = priv;
 }
 
 static void
 e_book_view_dispose (GObject *object)
 {
-	EBookView             *book_view = E_BOOK_VIEW (object);
-	CORBA_Environment  ev;
-
-	if (book_view->priv) {
-		if (book_view->priv->book) {
-			g_object_unref (book_view->priv->book);
-		}
-
-		if (book_view->priv->corba_book_view) {
-			CORBA_exception_init (&ev);
-
-			GNOME_Evolution_Addressbook_BookView_dispose (book_view->priv->corba_book_view, &ev);
+	EBookView *view = E_BOOK_VIEW (object);
 
-			bonobo_object_release_unref (book_view->priv->corba_book_view, &ev);
-
-			if (ev._major != CORBA_NO_EXCEPTION) {
-				g_warning ("EBookView: Exception while releasing BookView\n");
-			}
-
-			CORBA_exception_free (&ev);
-		}
-
-		if (book_view->priv->listener) {
-			if (book_view->priv->response_id)
-				g_signal_handler_disconnect(book_view->priv->listener,
-							    book_view->priv->response_id);
-			e_book_view_listener_stop (book_view->priv->listener);
-			bonobo_object_unref (BONOBO_OBJECT(book_view->priv->listener));
-		}
-
-		g_free (book_view->priv);
-		book_view->priv = NULL;
+	if (view->priv->view_proxy) {
+		org_gnome_evolution_dataserver_addressbook_BookView_dispose (view->priv->view_proxy, NULL);
+		g_object_unref (view->priv->view_proxy);
+		view->priv->view_proxy = NULL;
 	}
 
-	G_OBJECT_CLASS(parent_class)->dispose (object);
+	if (view->priv->book) {
+		g_object_unref (view->priv->book);
+		view->priv->book = NULL;
+	}
 }
 
 static void
@@ -308,84 +272,43 @@ e_book_view_class_init (EBookViewClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-	parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
-	e_book_view_signals [CONTACTS_CHANGED] =
-		g_signal_new ("contacts_changed",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookViewClass, contacts_changed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__POINTER,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_POINTER);
-
-	e_book_view_signals [CONTACTS_ADDED] =
-		g_signal_new ("contacts_added",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookViewClass, contacts_added),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__POINTER,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_POINTER);
-
-	e_book_view_signals [CONTACTS_REMOVED] =
-		g_signal_new ("contacts_removed",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookViewClass, contacts_removed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__POINTER,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_POINTER);
-
-	e_book_view_signals [SEQUENCE_COMPLETE] =
-		g_signal_new ("sequence_complete",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookViewClass, sequence_complete),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__INT,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_INT);
-
-	e_book_view_signals [STATUS_MESSAGE] =
-		g_signal_new ("status_message",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookViewClass, status_message),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__STRING,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_STRING);
+	g_type_class_add_private (klass, sizeof (EBookViewPrivate));
+
+	signals [CONTACTS_CHANGED] = g_signal_new ("contacts_changed",
+						   G_OBJECT_CLASS_TYPE (object_class),
+						   G_SIGNAL_RUN_LAST,
+						   G_STRUCT_OFFSET (EBookViewClass, contacts_changed),
+						   NULL, NULL,
+						   e_book_marshal_NONE__POINTER,
+						   G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals [CONTACTS_REMOVED] = g_signal_new ("contacts_removed",
+						   G_OBJECT_CLASS_TYPE (object_class),
+						   G_SIGNAL_RUN_LAST,
+						   G_STRUCT_OFFSET (EBookViewClass, contacts_removed),
+						   NULL, NULL,
+						   e_book_marshal_NONE__POINTER,
+						   G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals [CONTACTS_ADDED] = g_signal_new ("contacts_added",
+						 G_OBJECT_CLASS_TYPE (object_class),
+						 G_SIGNAL_RUN_LAST,
+						 G_STRUCT_OFFSET (EBookViewClass, contacts_added),
+						 NULL, NULL,
+						 e_book_marshal_NONE__POINTER,
+						 G_TYPE_NONE, 1, G_TYPE_POINTER);
+	signals [SEQUENCE_COMPLETE] = g_signal_new ("sequence_complete",
+						    G_OBJECT_CLASS_TYPE (object_class),
+						    G_SIGNAL_RUN_LAST,
+						    G_STRUCT_OFFSET (EBookViewClass, sequence_complete),
+						    NULL, NULL,
+						    e_book_marshal_NONE__INT,
+						    G_TYPE_NONE, 1, G_TYPE_INT);
+	signals [STATUS_MESSAGE] = g_signal_new ("status_message",
+						 G_OBJECT_CLASS_TYPE (object_class),
+						 G_SIGNAL_RUN_LAST,
+						 G_STRUCT_OFFSET (EBookViewClass, status_message),
+						 NULL, NULL,
+						 e_book_marshal_NONE__STRING,
+						 G_TYPE_NONE, 1, G_TYPE_STRING);
 
 	object_class->dispose = e_book_view_dispose;
 }
-
-/**
- * e_book_view_get_type:
- */
-GType
-e_book_view_get_type (void)
-{
-	static GType type = 0;
-
-	if (! type) {
-		GTypeInfo info = {
-			sizeof (EBookViewClass),
-			NULL, /* base_class_init */
-			NULL, /* base_class_finalize */
-			(GClassInitFunc)  e_book_view_class_init,
-			NULL, /* class_finalize */
-			NULL, /* class_data */
-			sizeof (EBookView),
-			0,    /* n_preallocs */
-			(GInstanceInitFunc) e_book_view_init
-		};
-
-		type = g_type_register_static (G_TYPE_OBJECT, "EBookView", &info, 0);
-	}
-
-	return type;
-}
diff --git a/addressbook/libebook/e-book.c b/addressbook/libebook/e-book.c
index 0e7370d..9e628bd 100644
--- a/addressbook/libebook/e-book.c
+++ b/addressbook/libebook/e-book.c
@@ -1,81 +1,55 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
+ */
 
 #include <config.h>
-
+#include <unistd.h>
 #include <string.h>
-
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <dbus/dbus-glib.h>
 #include "e-book.h"
+#include "e-error.h"
+#include "e-contact.h"
 #include "e-book-view-private.h"
-#include "e-vcard.h"
+#include "e-data-book-factory-bindings.h"
+#include "e-data-book-bindings.h"
+#include "libedata-book/e-data-book-types.h"
+#include "e-book-marshal.h"
 
-#include <bonobo-activation/bonobo-activation.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib-lowlevel.h>
 
-#include <bonobo/bonobo-exception.h>
-#include <bonobo/bonobo-main.h>
-#include <gconf/gconf-client.h>
+#define E_DATA_BOOK_FACTORY_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook"
+
+static char** flatten_stringlist(GList *list);
+static GList *array_to_stringlist (char **list);
+static gboolean unwrap_gerror(GError *error, GError **client_error);
+static EBookStatus get_status_from_error (GError *error);
+
+G_DEFINE_TYPE(EBook, e_book, G_TYPE_OBJECT)
+#define E_BOOK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_BOOK, EBookPrivate))
 
-#include <glib/gi18n-lib.h>
-#include "libedataserver/e-flag.h"
-#include "libedataserver/e-component-listener.h"
-
-#include "e-book-listener.h"
-
-#define d(x)
-
-GMainContext *_ebook_context;
-
-static GObjectClass *parent_class;
-
-#ifdef __PRETTY_FUNCTION__
-#define e_return_error_if_fail(expr,error_code,retval)	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__,						\
-		__PRETTY_FUNCTION__,					\
-		#expr);							\
-	 g_set_error (error, E_BOOK_ERROR, (error_code),                \
-		"file %s: line %d (%s): assertion `%s' failed",		\
-		__FILE__,						\
-		__LINE__,						\
-		__PRETTY_FUNCTION__,					\
-		#expr);							\
-	 return (retval);						\
-       };				}G_STMT_END
-#else
-#define e_return_error_if_fail(expr,error_code,retval)	G_STMT_START{	\
-     if G_LIKELY(expr) { } else						\
-       {								\
-	 g_log (G_LOG_DOMAIN,						\
-		G_LOG_LEVEL_CRITICAL,					\
-		"file %s: line %d: assertion `%s' failed",		\
-		__FILE__,						\
-		__LINE__,						\
-		#expr);							\
-	 g_set_error (error, E_BOOK_ERROR, (error_code),                \
-		"file %s: line %d: assertion `%s' failed",		\
-		__FILE__,						\
-		__LINE__,						\
-		#expr);							\
-	 return (retval);						\
-       };				}G_STMT_END
-#endif
-
-/* XXX we need a better error message here */
-#define E_BOOK_CHECK_STATUS(status,error) G_STMT_START{			\
-	if ((status) == E_BOOK_ERROR_OK) {				\
-		return TRUE;						\
-	}								\
-	else {								\
-		g_set_error ((error), E_BOOK_ERROR, (status), "EBookStatus returned %d", (status));	\
-		return FALSE;						\
-	}				}G_STMT_END
 
 enum {
-	OPEN_PROGRESS,
 	WRITABLE_STATUS,
 	CONNECTION_STATUS,
 	AUTH_REQUIRED,
@@ -85,280 +59,225 @@ enum {
 
 static guint e_book_signals [LAST_SIGNAL];
 
-typedef enum {
-	STATE_WAITING,
-	STATE_PROCESSING,
-	STATE_CANCELLING
-} EBookOpState;
-
-typedef struct {
-	gint32 opid;
-	EBookOpState opstate;
-	gint idle_id;
-	gboolean synchronous;
-	EFlag *flag;
-	EBook *book;
-	EBookStatus status;
-	gchar *id;
-	GList *list;
-	EList *elist;
-	EContact *contact;
-
-	EBookView *view;
-	EBookViewListener *listener;
-
-	/* callbacks/closure for async calls */
-	union {
-		EBookIdCallback id;
-		EBookCallback status;
-		EBookContactCallback contact;
-		EBookListCallback list;
-		EBookBookViewCallback book_view;
-		EBookEListCallback elist;
-	} cb;
-	gpointer closure;
-} EBookOp;
-
-typedef enum {
-	E_BOOK_SOURCE_NOT_LOADED,
-	E_BOOK_SOURCE_LOADING,
-	E_BOOK_SOURCE_LOADED
-} EBookLoadState;
-
 struct _EBookPrivate {
-	/* cached capabilites */
-	gchar *cap;
-	gboolean cap_queried;
-
-	/* cached writable status */
+	ESource *source;
+	char *uri;
+	DBusGProxy *proxy;
+	gboolean loaded;
 	gboolean writable;
 	gboolean connected;
+	char *cap;
+	gboolean cap_queried;
+};
 
-	EBookListener         *listener;
-	EComponentListener    *comp_listener;
-
-	GNOME_Evolution_Addressbook_Book         corba_book;
-
-	EBookLoadState         load_state;
-
-	GList *pending_idles;
-	GHashTable *id_to_op;
-	guint32 current_op_id;
-
-	GMutex *mutex;
-
-	/* Need to keep URI around, since the getter returns const */
-	gchar *uri;
-	ESource *source;
-
-	gulong listener_signal;
-	gulong died_signal;
+static DBusGConnection *connection = NULL;
+static DBusGProxy *factory_proxy = NULL;
 
-	gint writable_idle_id;
-	gint connection_idle_id;
-	gint auth_idle_id;
-};
+typedef struct {
+	EBook *book;
+	void *callback; /* TODO union */
+	gpointer closure;
+	gpointer data;
+} AsyncData;
 
-
-/* Error quark */
 GQuark
 e_book_error_quark (void)
 {
-  static GQuark q = 0;
-  if (q == 0)
-    q = g_quark_from_static_string ("e-book-error-quark");
+	static GQuark q = 0;
+	if (q == 0)
+		q = g_quark_from_static_string ("e-book-error-quark");
 
-  return q;
+	return q;
 }
 
-
-
-/* EBookOp calls */
-
-static EBookOp*
-e_book_new_op (EBook *book, gboolean sync)
+/*
+ * Called when the addressbook server dies.
+ */
+static void
+proxy_destroyed (gpointer data, GObject *object)
 {
-	EBookOp *op = g_new0 (EBookOp, 1);
-
-	op->flag = e_flag_new ();
-	op->opstate = STATE_WAITING;
-
-	op->synchronous = sync;
-	if (sync)
-		op->opid = 0;
-	else
-		op->opid = book->priv->current_op_id++;
+	EBook *book = data;
 
-	g_hash_table_insert (book->priv->id_to_op,
-			     &op->opid, op);
+	g_assert (E_IS_BOOK (book));
 
-	return op;
-}
+	g_warning (G_STRLOC ": e-d-s proxy died");
 
-static EBookOp*
-e_book_get_op (EBook *book, gint opid)
-{
-	return (EBookOp*)g_hash_table_lookup (book->priv->id_to_op,
-					      &opid);
-}
+	/* Ensure that everything relevant is NULL */
+	factory_proxy = NULL;
+	book->priv->proxy = NULL;
 
-static EBookOp*
-e_book_get_current_sync_op (EBook *book)
-{
-	return e_book_get_op (book, 0);
+	g_signal_emit (G_OBJECT (book), e_book_signals [BACKEND_DIED], 0);
 }
 
-static EBookOp *
-e_book_find_op (EBook *book, guint32 opid, const gchar *func_name)
+static void
+e_book_dispose (GObject *object)
 {
-	EBookOp *op;
+	EBook *book = E_BOOK (object);
 
-	op = e_book_get_op (book, opid);
+	book->priv->loaded = FALSE;
 
-	if (op == NULL) {
-		g_warning ("%s: Cannot find operation", func_name);
-	} else if (op->opstate != STATE_WAITING) {
-		/* returns only operations, which are waiting */
-		op = NULL;
-	} else {
-		/* set opstate to processing, thus it will not be canceled meanwhile */
-		op->opstate = STATE_PROCESSING;
+	if (book->priv->proxy) {
+		g_object_weak_unref (G_OBJECT (book->priv->proxy), proxy_destroyed, book);
+		org_gnome_evolution_dataserver_addressbook_Book_close (book->priv->proxy, NULL);
+	}
+	if (book->priv->source) {
+		g_object_unref (book->priv->source);
+		book->priv->source = NULL;
+	}
+	if (book->priv->proxy) {
+		g_object_unref (book->priv->proxy);
+		book->priv->proxy = NULL;
 	}
 
-	return op;
+	if (G_OBJECT_CLASS (e_book_parent_class)->dispose)
+		G_OBJECT_CLASS (e_book_parent_class)->dispose (object);
 }
 
 static void
-e_book_op_free (EBookOp *op)
+e_book_finalize (GObject *object)
 {
-	e_flag_free (op->flag);
-	g_free (op);
+	EBook *book = E_BOOK (object);
+
+	if (book->priv->uri)
+		g_free (book->priv->uri);
+
+	if (book->priv->cap)
+		g_free (book->priv->cap);
+
+	if (G_OBJECT_CLASS (e_book_parent_class)->finalize)
+		G_OBJECT_CLASS (e_book_parent_class)->finalize (object);
 }
 
 static void
-e_book_op_remove (EBook *book,
-		  EBookOp *op)
+e_book_class_init (EBookClass *e_book_class)
 {
-	g_hash_table_remove (book->priv->id_to_op,
-			     &op->opid);
-
-	if (op->idle_id && g_list_find (book->priv->pending_idles, GINT_TO_POINTER (op->idle_id))) {
-		book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-							   GINT_TO_POINTER (op->idle_id));
-		g_source_remove (op->idle_id);
-		op->idle_id = 0;
-	}
+	GObjectClass *gobject_class = G_OBJECT_CLASS (e_book_class);
+
+	e_book_signals [WRITABLE_STATUS] =
+		g_signal_new ("writable_status",
+			      G_OBJECT_CLASS_TYPE (gobject_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (EBookClass, writable_status),
+			      NULL, NULL,
+			      e_book_marshal_NONE__BOOL,
+			      G_TYPE_NONE, 1,
+			      G_TYPE_BOOLEAN);
+
+	e_book_signals [CONNECTION_STATUS] =
+		g_signal_new ("connection_status",
+			      G_OBJECT_CLASS_TYPE (gobject_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (EBookClass, connection_status),
+			      NULL, NULL,
+			      e_book_marshal_NONE__BOOL,
+			      G_TYPE_NONE, 1,
+			      G_TYPE_BOOLEAN);
+
+	e_book_signals [AUTH_REQUIRED] =
+		g_signal_new ("auth_required",
+			      G_OBJECT_CLASS_TYPE (gobject_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (EBookClass, auth_required),
+			      NULL, NULL,
+			      e_book_marshal_NONE__NONE,
+			      G_TYPE_NONE, 0);
+
+	e_book_signals [BACKEND_DIED] =
+		g_signal_new ("backend_died",
+			      G_OBJECT_CLASS_TYPE (gobject_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (EBookClass, backend_died),
+			      NULL, NULL,
+			      e_book_marshal_NONE__NONE,
+			      G_TYPE_NONE, 0);
+
+	gobject_class->dispose = e_book_dispose;
+	gobject_class->finalize = e_book_finalize;
+
+	g_type_class_add_private (e_book_class, sizeof (EBookPrivate));
 }
 
 static void
-e_book_clear_op (EBook *book,
-		 EBookOp *op)
+e_book_init (EBook *book)
 {
-	e_book_op_remove (book, op);
-	e_flag_clear (op->flag);
-	e_book_op_free (op);
+	EBookPrivate *priv = E_BOOK_GET_PRIVATE (book);
+	priv->source = NULL;
+	priv->uri = NULL;
+	priv->proxy = NULL;
+	priv->loaded = FALSE;
+	priv->writable = FALSE;
+	priv->connected = FALSE;
+	priv->cap = NULL;
+	priv->cap_queried = FALSE;
+	book->priv = priv;
 }
 
-
+/* one-time start up for libebook */
 static gboolean
-do_add_contact (gboolean          sync,
-		EBook            *book,
-		EContact         *contact,
-		GError          **error,  /* for sync case */
-		EBookIdCallback   cb, /* for async case */
-		gpointer          closure)
+e_book_activate(GError **error)
 {
-	EBookOp *our_op;
-	EBookStatus status;
-	CORBA_Environment ev;
-	gchar *vcard_str;
-
-	d(printf ("do_add_contact\n"));
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     /* translators: the placeholders will be filled by
-				      * function names, e.g.
-				      * "e_book_add_contact" on book before
-				      * "e_book_open */
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_add_contact", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_add_contact", "e_book_open");
-		}
-		return FALSE;
-	}
+	DBusError derror;
 
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
+	if (G_LIKELY (factory_proxy)) {
+		return TRUE;
 	}
 
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.id = cb;
-	our_op->closure = closure;
+	if (!connection) {
+		connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
+		if (!connection)
+			return FALSE;
+	}
 
-	/* will eventually end up calling e_book_response_add_contact */
-	GNOME_Evolution_Addressbook_Book_addContact (book->priv->corba_book, our_op->opid,
-						     (const GNOME_Evolution_Addressbook_VCard) vcard_str, &ev);
+	dbus_error_init (&derror);
+	if (!dbus_bus_start_service_by_name (dbus_g_connection_get_connection (connection),
+					     E_DATA_BOOK_FACTORY_SERVICE_NAME,
+					     0, NULL, &derror)) {
+		dbus_set_g_error (error, &derror);
+		dbus_error_free (&derror);
+		return FALSE;
+	}
 
-	g_free (vcard_str);
+	if (!factory_proxy) {
+		factory_proxy = dbus_g_proxy_new_for_name_owner (connection,
+								 E_DATA_BOOK_FACTORY_SERVICE_NAME,
+								 "/org/gnome/evolution/dataserver/addressbook/BookFactory",
+								 "org.gnome.evolution.dataserver.addressbook.BookFactory",
+								 error);
+		if (!factory_proxy) {
+			return FALSE;
+		}
+		g_object_add_weak_pointer (G_OBJECT (factory_proxy), (gpointer)&factory_proxy);
+	}
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
+	return TRUE;
+}
 
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
+static void
+writable_cb (DBusGProxy *proxy, gboolean writable, EBook *book)
+{
+	g_return_if_fail (E_IS_BOOK (book));
 
-		CORBA_exception_free (&ev);
+	book->priv->writable = writable;
 
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::addContact");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::addContact");
-		}
-		return FALSE;
-	}
+	g_signal_emit (G_OBJECT (book), e_book_signals [WRITABLE_STATUS], 0, writable);
+}
 
-	CORBA_exception_free (&ev);
+static void
+connection_cb (DBusGProxy *proxy, gboolean connected, EBook *book)
+{
+	g_return_if_fail (E_IS_BOOK (book));
 
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
+	book->priv->connected = connected;
 
-		status = our_op->status;
-		e_contact_set (contact, E_CONTACT_UID, our_op->id);
-		g_free (our_op->id);
+	g_signal_emit (G_OBJECT (book), e_book_signals [CONNECTION_STATUS], 0, connected);
+}
 
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
+static void
+auth_required_cb (DBusGProxy *proxy, EBook *book)
+{
+	g_return_if_fail (E_IS_BOOK (book));
 
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	g_signal_emit (G_OBJECT (book), e_book_signals [AUTH_REQUIRED], 0);
 }
 
 /**
@@ -376,14 +295,42 @@ e_book_add_contact (EBook           *book,
 		    EContact        *contact,
 		    GError         **error)
 {
-	d(printf ("e_book_add_contact\n"));
+	GError *err = NULL;
+	char *vcard, *uid = NULL;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
+
+	vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+	org_gnome_evolution_dataserver_addressbook_Book_add_contact (book->priv->proxy, vcard, &uid, &err);
+	g_free (vcard);
+	if (uid) {
+		e_contact_set (contact, E_CONTACT_UID, uid);
+		g_free (uid);
+	}
+	return unwrap_gerror (err, error);
+}
+
+static void
+add_contact_reply (DBusGProxy *proxy, char *uid, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookIdCallback cb = data->callback;
+
+	/* If there is an error returned the GLib bindings currently return garbage
+	   for the OUT values. This is bad. */
+	if (error)
+		uid = NULL;
+
+	if (cb)
+		cb (data->book, get_status_from_error (error), uid, data->closure);
 
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (contact && E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG, FALSE);
+	if (uid)
+		g_free (uid);
 
-	return do_add_contact (TRUE,
-			       book, contact, error,
-			       NULL, NULL);
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -403,173 +350,25 @@ e_book_async_add_contact (EBook                 *book,
 			  EBookIdCallback        cb,
 			  gpointer               closure)
 {
-	d(printf ("e_book_async_add_contact\n"));
-
-	g_return_val_if_fail (book && E_IS_BOOK (book), FALSE);
-	g_return_val_if_fail (contact && E_IS_CONTACT (contact), FALSE);
-
-	return !do_add_contact (FALSE,
-				book, contact, NULL,
-				cb, closure);
-}
-
-static gboolean
-emit_async_add_contact_response (gpointer data)
-{
-	EBookOp *op = data;
-	EBook *book = op->book;
-
-	if (op->cb.id)
-		op->cb.id (book, op->status, op->id, op->closure);
-
-	g_mutex_lock (book->priv->mutex);
-
-	g_free (op->id);
-
-	book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-						   GINT_TO_POINTER (op->idle_id));
-
-	e_book_clear_op (book, op);
-
-	g_mutex_unlock (book->priv->mutex);
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static void
-e_book_response_add_contact (EBook       *book,
-			     guint32      opid,
-			     EBookStatus  status,
-			     gchar        *id)
-{
-	EBookOp *op;
-
-	d(printf ("e_book_response_add_contact\n"));
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->id = g_strdup (id);
-	op->status = status;
-
-	if (op->synchronous)
-		e_flag_set (op->flag);
-	else {
-		op->book = g_object_ref (book);
-
-		op->idle_id = g_idle_add (emit_async_add_contact_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-}
-
-
-
-static gboolean
-do_commit_contact (gboolean        sync,
-		   EBook          *book,
-		   EContact       *contact,
-		   GError        **error,
-		   EBookCallback   cb,
-		   gpointer        closure)
-{
-	EBookOp *our_op;
-	EBookStatus status;
-	CORBA_Environment ev;
-	gchar *vcard_str;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_commit_contact", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_commit_contact", "e_book_open");
-		}
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.status = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling _e_book_response_generic */
-	GNOME_Evolution_Addressbook_Book_modifyContact (book->priv->corba_book, our_op->opid,
-							(const GNOME_Evolution_Addressbook_VCard) vcard_str, &ev);
-
-	g_free (vcard_str);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::modifyContact");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::modifyContact");
-		}
-		return FALSE;
-	}
-
-	CORBA_exception_free (&ev);
+	gchar *vcard;
+	AsyncData *data;
 
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
+	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_async_error_val_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
 
-		status = our_op->status;
-		g_free (our_op->id);
+	vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
 
-		/* remove the op from the book's hash of operations */
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	org_gnome_evolution_dataserver_addressbook_Book_add_contact_async (book->priv->proxy, vcard, add_contact_reply, data);
+	g_free (vcard);
+	return 0;
 }
 
-
 /**
  * e_book_commit_contact:
  * @book: an #EBook
@@ -586,13 +385,30 @@ e_book_commit_contact (EBook           *book,
 		       EContact        *contact,
 		       GError         **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (contact && E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	gchar *vcard;
 
-	return do_commit_contact (TRUE,
-				  book, contact, error,
-				  NULL, NULL);
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
 
+	vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+	org_gnome_evolution_dataserver_addressbook_Book_modify_contact (book->priv->proxy, vcard, &err);
+	g_free (vcard);
+	return unwrap_gerror (err, error);
+}
+
+static void
+modify_contact_reply (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookCallback cb = data->callback;
+
+	if (cb)
+		cb (data->book, get_status_from_error (error), data->closure);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -613,192 +429,25 @@ e_book_async_commit_contact (EBook                 *book,
 			     EBookCallback          cb,
 			     gpointer               closure)
 {
-	return !do_commit_contact (FALSE,
-				   book, contact, NULL,
-				   cb, closure);
-}
-
-static gboolean
-do_get_required_fields (gboolean             sync,
-			 EBook               *book,
-			 GList              **fields,
-			 GError             **error,
-			 EBookEListCallback   cb,
-			 gpointer             closure)
-{
-	EBookOp *our_op;
-	EBookStatus status;
-	CORBA_Environment ev;
+	char *vcard;
+	AsyncData *data;
 
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_get_required_fields", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_get_required_fields", "e_book_open");
-		}
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.elist = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling
-	   _e_book_response_get_supported_fields */
-	GNOME_Evolution_Addressbook_Book_getRequiredFields(book->priv->corba_book, our_op->opid, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::getRequiredFields");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::getRequiredFields");
-		}
-
-		return FALSE;
-	}
+	e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_async_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
 
+	vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
 
-	CORBA_exception_free (&ev);
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notify us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-		*fields = our_op->list;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	org_gnome_evolution_dataserver_addressbook_Book_modify_contact_async (book->priv->proxy, vcard, modify_contact_reply, data);
+	g_free (vcard);
+	return 0;
 }
 
-static gboolean
-do_get_supported_fields (gboolean             sync,
-			 EBook               *book,
-			 GList              **fields,
-			 GError             **error,
-			 EBookEListCallback   cb,
-			 gpointer             closure)
-{
-	EBookOp *our_op;
-	EBookStatus status;
-	CORBA_Environment ev;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_get_supported_fields", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_get_supported_fields", "e_book_open");
-		}
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.elist = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling
-	   _e_book_response_get_supported_fields */
-	GNOME_Evolution_Addressbook_Book_getSupportedFields(book->priv->corba_book, our_op->opid, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::getSupportedFields");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::getSupportedFields");
-		}
-
-		return FALSE;
-	}
-
-
-	CORBA_exception_free (&ev);
-
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notify us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-		*fields = our_op->list;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
-}
 
 /**
  * e_book_get_required_fields:
@@ -818,12 +467,42 @@ e_book_get_required_fields  (EBook            *book,
 			      GList           **fields,
 			      GError          **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (fields,                   E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	char **list = NULL;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	org_gnome_evolution_dataserver_addressbook_Book_get_required_fields (book->priv->proxy, &list, &err);
+	if (list) {
+		*fields = array_to_stringlist (list);
+		return TRUE;
+	} else {
+		return unwrap_gerror (err, error);
+	}
+}
+
+static void
+get_required_fields_reply(DBusGProxy *proxy, char **fields, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookEListCallback cb = data->callback;
+	char **i = fields;
+	EList *efields = e_list_new (NULL,
+				     (EListFreeFunc) g_free,
+				     NULL);
+
+	while (*i != NULL) {
+		e_list_append (efields, (*i++));
+	}
 
-	return do_get_required_fields (TRUE,
-					book, fields, error,
-					NULL, NULL);
+	if (cb)
+		cb (data->book, get_status_from_error (error), efields, data->closure);
+
+	g_object_unref (efields);
+	g_free (fields);
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -842,11 +521,18 @@ e_book_async_get_required_fields (EBook              *book,
 				   EBookEListCallback  cb,
 				   gpointer            closure)
 {
-	g_return_val_if_fail (E_IS_BOOK (book), FALSE);
+	AsyncData *data;
+
+	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	return !do_get_required_fields (FALSE,
-					 book, NULL, NULL,
-					 cb, closure);
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
+
+	org_gnome_evolution_dataserver_addressbook_Book_get_required_fields_async (book->priv->proxy, get_required_fields_reply, data);
+	return 0;
 }
 
 /**
@@ -867,12 +553,41 @@ e_book_get_supported_fields  (EBook            *book,
 			      GList           **fields,
 			      GError          **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (fields,                   E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	char **list = NULL;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	org_gnome_evolution_dataserver_addressbook_Book_get_supported_fields (book->priv->proxy, &list, &err);
+	if (list) {
+		*fields = array_to_stringlist (list);
+		return TRUE;
+	} else {
+		return unwrap_gerror (err, error);
+	}
+}
+
+static void
+get_supported_fields_reply(DBusGProxy *proxy, char **fields, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookEListCallback cb = data->callback;
+	char **i = fields;
+	EList *efields = e_list_new (NULL,  (EListFreeFunc) g_free, NULL);
+
+	while (*i != NULL) {
+		e_list_append (efields, (*i++));
+	}
+
+	if (cb)
+		cb (data->book, get_status_from_error (error), efields, data->closure);
+
+	g_object_unref (efields);
+	g_free (fields);
 
-	return do_get_supported_fields (TRUE,
-					book, fields, error,
-					NULL, NULL);
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -892,209 +607,18 @@ e_book_async_get_supported_fields (EBook              *book,
 				   EBookEListCallback  cb,
 				   gpointer            closure)
 {
-	g_return_val_if_fail (E_IS_BOOK (book), FALSE);
-
-	return !do_get_supported_fields (FALSE,
-					 book, NULL, NULL,
-					 cb, closure);
-}
-
-static gboolean
-emit_async_elist_response (gpointer data)
-{
-	EBookOp *op = data;
-	EBook *book = op->book;
-
-	if (op->cb.elist)
-		op->cb.elist (book, op->status, op->elist, op->closure);
+	AsyncData *data;
 
-	g_mutex_lock (book->priv->mutex);
+	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	g_object_unref (op->elist);
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-						   GINT_TO_POINTER (op->idle_id));
-
-	e_book_clear_op (book, op);
-
-	g_mutex_unlock (book->priv->mutex);
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static void
-e_book_response_get_required_fields (EBook       *book,
-				      guint32      opid,
-				      EBookStatus  status,
-				      GList       *fields)
-
-{
-	EBookOp *op;
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->status = status;
-	if (op->synchronous) {
-		op->list = fields;
-		e_flag_set (op->flag);
-	} else {
-		GList *l;
-		EList *efields = e_list_new ((EListCopyFunc) g_strdup,
-					     (EListFreeFunc) g_free,
-					     NULL);
-
-		for (l = fields; l; l = l->next)
-			e_list_append (efields, l->data);
-
-		op->book = g_object_ref (book);
-		op->elist = efields;
-
-		op->idle_id = g_idle_add (emit_async_elist_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-}
-
-static void
-e_book_response_get_supported_fields (EBook       *book,
-				      guint32      opid,
-				      EBookStatus  status,
-				      GList       *fields)
-{
-	EBookOp *op;
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->status = status;
-	if (op->synchronous) {
-		op->list = fields;
-		e_flag_set (op->flag);
-	} else {
-		GList *l;
-		EList *efields = e_list_new ((EListCopyFunc) g_strdup,
-					     (EListFreeFunc) g_free,
-					     NULL);
-
-		for (l = fields; l; l = l->next)
-			e_list_append (efields, l->data);
-
-		op->book = g_object_ref (book);
-		op->elist = efields;
-
-		op->idle_id = g_idle_add (emit_async_elist_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-}
-
-
-static gboolean
-do_get_supported_auth_methods (gboolean             sync,
-			       EBook               *book,
-			       GList              **auth_methods,
-			       GError             **error,
-			       EBookEListCallback   cb,
-			       gpointer             closure)
-{
-	EBookOp *our_op;
-	EBookStatus status;
-	CORBA_Environment ev;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_get_supported_auth_methods",
-				     "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_get_supported_auth_methods",
-				   "e_book_open");
-		}
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.elist = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling
-	   e_book_response_get_supported_fields */
-	GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods(book->priv->corba_book, our_op->opid, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error)
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::getSupportedAuthMethods");
-		else
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::getSupportedAuthMethods");
-		return FALSE;
-	}
-
-
-	CORBA_exception_free (&ev);
-
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-		*auth_methods = our_op->list;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	org_gnome_evolution_dataserver_addressbook_Book_get_supported_fields_async (book->priv->proxy, get_supported_fields_reply, data);
+	return 0;
 }
 
 /**
@@ -1114,12 +638,43 @@ e_book_get_supported_auth_methods (EBook            *book,
 				   GList           **auth_methods,
 				   GError          **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (auth_methods,             E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	char **list = NULL;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	return do_get_supported_auth_methods (TRUE,
-					      book, auth_methods, error,
-					      NULL, NULL);
+	org_gnome_evolution_dataserver_addressbook_Book_get_supported_auth_methods (book->priv->proxy, &list, &err);
+	if (list) {
+		*auth_methods = array_to_stringlist (list);
+		return TRUE;
+	} else {
+		return unwrap_gerror (err, error);
+	}
+}
+
+static void
+get_supported_auth_methods_reply(DBusGProxy *proxy, char **methods, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookEListCallback cb = data->callback;
+	char **i = methods;
+	EList *emethods = e_list_new (NULL,
+				      (EListFreeFunc) g_free,
+				      NULL);
+
+	while (*i != NULL) {
+		e_list_append (emethods, (*i++));
+	}
+
+	if (cb)
+		cb (data->book, get_status_from_error (error), emethods, data->closure);
+
+	g_object_unref (emethods);
+	g_free (methods);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -1132,154 +687,25 @@ e_book_get_supported_auth_methods (EBook            *book,
  * This function does not block.
  *
  * Return value: %TRUE if successful, %FALSE otherwise.
- **/
+**/
 guint
 e_book_async_get_supported_auth_methods (EBook              *book,
 					 EBookEListCallback  cb,
 					 gpointer            closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
-
-	return !do_get_supported_auth_methods (FALSE,
-					       book, NULL, NULL,
-					       cb, closure);
-}
-
-static void
-e_book_response_get_supported_auth_methods (EBook                 *book,
-					    guint32                opid,
-					    EBookStatus            status,
-					    GList                 *auth_methods)
-{
-	EBookOp *op;
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->status = status;
-	if (op->synchronous) {
-		op->list = auth_methods;
-		e_flag_set (op->flag);
-	} else {
-		GList *l;
-		EList *emethods = e_list_new ((EListCopyFunc) g_strdup,
-					      (EListFreeFunc) g_free,
-					      NULL);
-
-		for (l = auth_methods; l; l = l->next)
-			e_list_append (emethods, l->data);
-
-		op->book = g_object_ref (book);
-		op->elist = emethods;
-
-		op->idle_id = g_idle_add (emit_async_elist_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-}
-
-
-
-static gboolean
-do_authenticate_user (gboolean        sync,
-		      EBook          *book,
-		      const gchar     *user,
-		      const gchar     *passwd,
-		      const gchar     *auth_method,
-		      GError        **error,
-		      EBookCallback   cb,
-		      gpointer        closure)
-{
-	EBookOp *our_op;
-	EBookStatus status;
-	CORBA_Environment ev;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_authenticate_user", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_authenticate_user", "e_book_open");
-		}
-
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
+	 AsyncData *data;
 
-	our_op->cb.status = cb;
-	our_op->closure = closure;
+	 e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	 e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	/* will eventually end up calling
-	   e_book_response_generic */
-	GNOME_Evolution_Addressbook_Book_authenticateUser (book->priv->corba_book, our_op->opid,
-							   user, passwd,
-							   auth_method,
-							   &ev);
+	 data = g_slice_new0 (AsyncData);
+	 data->book = g_object_ref (book);
+	 data->callback = cb;
+	 data->closure = closure;
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error)
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::authenticateUser");
-		else
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::authenticateUser");
-
-		return FALSE;
-	}
-
-	CORBA_exception_free (&ev);
-
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
-}
+	 org_gnome_evolution_dataserver_addressbook_Book_get_supported_auth_methods_async (book->priv->proxy, get_supported_auth_methods_reply, data);
+	 return 0;
+ }
 
 /**
  * e_book_authenticate_user:
@@ -1302,14 +728,26 @@ e_book_authenticate_user (EBook         *book,
 			  const gchar    *auth_method,
 			  GError       **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (user,                     E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (passwd,                   E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (auth_method,              E_BOOK_ERROR_INVALID_ARG, FALSE);
-
-	return do_authenticate_user (TRUE,
-				     book, user, passwd, auth_method, error,
-				     NULL, NULL);
+	GError *err = NULL;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	org_gnome_evolution_dataserver_addressbook_Book_authenticate_user (book->priv->proxy, user, passwd, auth_method, &err);
+	return unwrap_gerror (err, error);
+}
+
+static void
+authenticate_user_reply(DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookCallback cb = data->callback;
+
+	if (cb)
+		cb (data->book, get_status_from_error (error), data->closure);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -1336,107 +774,21 @@ e_book_async_authenticate_user (EBook                 *book,
 				EBookCallback         cb,
 				gpointer              closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
-	g_return_val_if_fail (user,                     TRUE);
-	g_return_val_if_fail (passwd,                   TRUE);
-	g_return_val_if_fail (auth_method,              TRUE);
-
-	return !do_authenticate_user (FALSE,
-				      book, user, passwd, auth_method, NULL,
-				      cb, closure);
-}
-
-
-
-static gboolean
-do_get_contact (gboolean sync,
-		EBook *book,
-		const gchar *id,
-		EContact **contact,
-		GError **error,
-		EBookContactCallback cb,
-		gpointer closure)
-{
-	EBookOp *our_op;
-	EBookStatus status;
-	CORBA_Environment ev;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_get_contact", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_get_contact", "e_book_open");
-		}
+	AsyncData *data;
 
-		return FALSE;
-	}
+	e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_async_error_if_fail (user, E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_if_fail (passwd, E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_if_fail (auth_method, E_BOOK_ERROR_INVALID_ARG);
 
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.contact = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling e_book_response_generic */
-	GNOME_Evolution_Addressbook_Book_getContact (book->priv->corba_book, our_op->opid,
-						     (const GNOME_Evolution_Addressbook_VCard) id, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::getContact");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::getContact");
-		}
-		return FALSE;
-	}
-
-	CORBA_exception_free (&ev);
-
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-		*contact = our_op->contact;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	org_gnome_evolution_dataserver_addressbook_Book_authenticate_user_async (book->priv->proxy, user, passwd, auth_method, authenticate_user_reply, data);
+	return 0;
 }
 
 /**
@@ -1457,13 +809,46 @@ e_book_get_contact (EBook       *book,
 		    EContact   **contact,
 		    GError     **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (id,                       E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (contact,                  E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	gchar *vcard = NULL;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	org_gnome_evolution_dataserver_addressbook_Book_get_contact (book->priv->proxy, id, &vcard, &err);
+	if (vcard) {
+		*contact = e_contact_new_from_vcard (vcard);
+		g_free (vcard);
+	}
+	return unwrap_gerror (err, error);
+}
+
+static void
+get_contact_reply(DBusGProxy *proxy, char *vcard, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookContactCallback cb = data->callback;
+	EBookStatus status = get_status_from_error (error);
+
+	/* Protect against garbage return values on error */
+	if (error)
+		vcard = NULL;
+
+	if (cb) {
+		if (error == NULL) {
+			cb (data->book, status, e_contact_new_from_vcard (vcard), data->closure);
+		} else {
+			cb (data->book, status, NULL, data->closure);
+		}
+	} else {
+		g_warning (G_STRLOC ": cannot get contact: %s", error->message);
+	}
 
-	return do_get_contact (TRUE,
-			       book, id, contact, error,
-			       NULL, NULL);
+	if (error)
+		g_error_free (error);
+	g_free (vcard);
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -1483,172 +868,19 @@ e_book_async_get_contact (EBook                 *book,
 			  EBookContactCallback   cb,
 			  gpointer               closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
-	g_return_val_if_fail (id,                       TRUE);
-
-	return !do_get_contact (FALSE,
-				book, id, NULL, NULL,
-				cb, closure);
-}
-
-static gboolean
-emit_async_get_contact_response (gpointer data)
-{
-	EBookOp *op = data;
-	EBook *book = op->book;
-
-	if (op->cb.contact)
-		op->cb.contact (book, op->status, op->contact, op->closure);
-
-	g_mutex_lock (book->priv->mutex);
-
-	g_object_unref (op->contact);
-
-	book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-						   GINT_TO_POINTER (op->idle_id));
-
-	e_book_clear_op (book, op);
-
-	g_mutex_unlock (book->priv->mutex);
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static void
-e_book_response_get_contact (EBook       *book,
-			     guint32      opid,
-			     EBookStatus  status,
-			     EContact    *contact)
-{
-	EBookOp *op;
-
-	d(printf ("e_book_response_get_contact\n"));
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->status = status;
-	op->contact = contact;
-
-	if (op->synchronous)
-		e_flag_set (op->flag);
-	else {
-		op->book = g_object_ref (book);
-
-		op->idle_id = g_idle_add (emit_async_get_contact_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-}
-
-
-static gboolean
-do_remove_contacts (gboolean sync,
-		    EBook *book,
-		    GList *ids,
-		    GError **error,
-		    EBookCallback cb,
-		    gpointer closure)
-{
-	GNOME_Evolution_Addressbook_ContactIdList idlist;
-	CORBA_Environment ev;
-	GList *iter;
-	gint num_ids, i;
-	EBookOp *our_op;
-	EBookStatus status;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_remove_contacts", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_remove_contacts", "e_book_open");
-		}
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	num_ids = g_list_length (ids);
-	idlist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_ContactId_allocbuf (num_ids);
-	idlist._maximum = num_ids;
-	idlist._length = num_ids;
-
-	for (iter = ids, i = 0; iter; iter = iter->next)
-		idlist._buffer[i++] = CORBA_string_dup (iter->data);
+	AsyncData *data;
 
-	our_op->cb.status = cb;
-	our_op->closure = closure;
+	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_async_error_val_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
 
-	/* will eventually end up calling e_book_response_generic */
-	GNOME_Evolution_Addressbook_Book_removeContacts (book->priv->corba_book, our_op->opid, &idlist, &ev);
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	CORBA_free(idlist._buffer);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::removeContacts");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::removeContacts");
-		}
-		return FALSE;
-	}
-
-	CORBA_exception_free (&ev);
-
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	org_gnome_evolution_dataserver_addressbook_Book_get_contact_async (book->priv->proxy, id, get_contact_reply, data);
+	return 0;
 }
 
 /**
@@ -1666,19 +898,31 @@ e_book_remove_contact (EBook       *book,
 		       const gchar  *id,
 		       GError     **error)
 {
-	GList *list;
-	gboolean rv;
+	GError *err = NULL;
+	const gchar *l[2];
 
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (id,                       E_BOOK_ERROR_INVALID_ARG, FALSE);
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
 
-	list = g_list_append (NULL, (gchar *)id);
+	l[0] = id;
+	l[1] = NULL;
 
-	rv = e_book_remove_contacts (book, list, error);
+	org_gnome_evolution_dataserver_addressbook_Book_remove_contacts (book->priv->proxy, l, &err);
+	return unwrap_gerror (err, error);
+}
 
-	g_list_free (list);
+static void
+remove_contact_reply (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookCallback cb = data->callback;
 
-	return rv;
+	if (cb)
+		cb (data->book, get_status_from_error (error), data->closure);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -1699,12 +943,18 @@ e_book_remove_contacts (EBook    *book,
 			GList    *ids,
 			GError  **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (ids,                      E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	char **l;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_error_if_fail (ids, E_BOOK_ERROR_INVALID_ARG);
 
-	return do_remove_contacts (TRUE,
-				   book, ids, error,
-				   NULL, NULL);
+	l = flatten_stringlist (ids);
+
+	org_gnome_evolution_dataserver_addressbook_Book_remove_contacts (book->priv->proxy, (const char **) l, &err);
+	g_free (l);
+	return unwrap_gerror (err, error);
 }
 
 /**
@@ -1724,14 +974,36 @@ e_book_async_remove_contact (EBook                 *book,
 			     EBookCallback          cb,
 			     gpointer               closure)
 {
-	const gchar *id;
+	 AsyncData *data;
+	 const gchar *l[2];
+
+	 e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	 e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	 e_return_async_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
+
+	 l[0] = e_contact_get_const (contact, E_CONTACT_UID);
+	 l[1] = NULL;
+
+	 data = g_slice_new0 (AsyncData);
+	 data->book = g_object_ref (book);
+	 data->callback = cb;
+	 data->closure = closure;
+
+	 org_gnome_evolution_dataserver_addressbook_Book_remove_contacts_async (book->priv->proxy, l, remove_contact_reply, data);
+	 return 0;
+ }
 
-	g_return_val_if_fail (E_IS_BOOK (book), TRUE);
-	g_return_val_if_fail (E_IS_CONTACT (contact), TRUE);
+static void
+remove_contact_by_id_reply (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookCallback cb = data->callback;
 
-	id = e_contact_get_const (contact, E_CONTACT_UID);
+	if (cb)
+		cb (data->book, get_status_from_error (error), data->closure);
 
-	return e_book_async_remove_contact_by_id (book, id, cb, closure);
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -1751,14 +1023,36 @@ e_book_async_remove_contact_by_id (EBook                 *book,
 				   EBookCallback          cb,
 				   gpointer               closure)
 {
-	GList *list;
+	AsyncData *data;
+	const gchar *l[2];
+
+	e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_async_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
+
+	l[0] = id;
+	l[1] = NULL;
+
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	g_return_val_if_fail (E_IS_BOOK (book), TRUE);
-	g_return_val_if_fail (id != NULL, TRUE);
+	org_gnome_evolution_dataserver_addressbook_Book_remove_contacts_async (book->priv->proxy, l, remove_contact_by_id_reply, data);
+	return 0;
+}
 
-	list = g_list_append (NULL, g_strdup (id));
+static void
+remove_contacts_reply (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookCallback cb = data->callback;
 
-	return e_book_async_remove_contacts (book, list, cb, closure);
+	if (cb)
+		cb (data->book, get_status_from_error (error), data->closure);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -1781,130 +1075,28 @@ e_book_async_remove_contacts (EBook                 *book,
 			      EBookCallback          cb,
 			      gpointer               closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
-	g_return_val_if_fail (ids,                      TRUE);
+	AsyncData *data;
+	gchar **l;
 
-	return !do_remove_contacts (FALSE,
-				    book, ids, NULL,
-				    cb, closure);
-}
+	e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-
-static gboolean
-do_get_book_view (gboolean sync,
-		  EBook *book,
-		  EBookQuery *query,
-		  GList *requested_fields,
-		  gint max_results,
-		  EBookView **book_view,
-		  GError **error,
-		  EBookBookViewCallback cb,
-		  gpointer closure)
-{
-	GNOME_Evolution_Addressbook_stringlist stringlist;
-	CORBA_Environment ev;
-	EBookOp *our_op;
-	EBookStatus status;
-	gint num_fields, i;
-	GList *iter;
-	gchar *query_string;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_get_book_view", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_get_book_view", "e_book_open");
-		}
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->listener = e_book_view_listener_new();
-
-	num_fields = g_list_length (requested_fields);
-
-	stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_fields);
-	stringlist._maximum = num_fields;
-	stringlist._length = num_fields;
-
-	for (i = 0, iter = requested_fields; iter; iter = iter->next, i ++) {
-		stringlist._buffer[i] = CORBA_string_dup ((gchar *)iter->data);
-	}
-
-	query_string = e_book_query_to_string (query);
-
-	our_op->cb.book_view = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling e_book_response_get_book_view */
-	GNOME_Evolution_Addressbook_Book_getBookView (book->priv->corba_book,
-						      our_op->opid,
-						      bonobo_object_corba_objref(BONOBO_OBJECT(our_op->listener)),
-						      query_string,
-						      &stringlist, max_results, &ev);
-
-	CORBA_free(stringlist._buffer);
-	g_free (query_string);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::authenticateUser");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::authenticateUser");
-		}
-
-		return FALSE;
+	if (ids == NULL) {
+		if (cb)
+			cb (book, E_BOOK_ERROR_OK, closure);
+		return 0;
 	}
 
-	CORBA_exception_free (&ev);
+	l = flatten_stringlist (ids);
 
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-		status = our_op->status;
-		*book_view = our_op->view;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	org_gnome_evolution_dataserver_addressbook_Book_remove_contacts_async (book->priv->proxy, (const char **) l, remove_contacts_reply, data);
+	g_free (l);
+	return 0;
 }
 
 /**
@@ -1930,13 +1122,70 @@ e_book_get_book_view (EBook       *book,
 		      EBookView  **book_view,
 		      GError     **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book),       E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (query,                          E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (book_view,                      E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	DBusGProxy *view_proxy;
+	char *sexp, *view_path;
+	gboolean ret = TRUE;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	return do_get_book_view (TRUE,
-				 book, query, requested_fields, max_results, book_view, error,
-				 NULL, NULL);
+	sexp = e_book_query_to_string (query);
+
+	if (!org_gnome_evolution_dataserver_addressbook_Book_get_book_view (book->priv->proxy, sexp, max_results, &view_path, &err)) {
+		*book_view = NULL;
+		g_free (sexp);
+		return unwrap_gerror (err, error);
+	}
+	view_proxy = dbus_g_proxy_new_for_name_owner (connection,
+						      E_DATA_BOOK_FACTORY_SERVICE_NAME, view_path,
+						      "org.gnome.evolution.dataserver.addressbook.BookView", error);
+
+	if (view_proxy) {
+		*book_view = _e_book_view_new (book, view_proxy);
+	} else {
+		*book_view = NULL;
+		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+			     "Cannot get connection to view");
+		ret = FALSE;
+	}
+
+	g_free (view_path);
+	g_free (sexp);
+
+	return ret;
+}
+
+static void
+get_book_view_reply (DBusGProxy *proxy, gchar *view_path, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	GError *err = NULL;
+	EBookView *view = NULL;
+	EBookBookViewCallback cb = data->callback;
+	DBusGProxy *view_proxy;
+	EBookStatus status;
+
+	if (view_path) {
+		view_proxy = dbus_g_proxy_new_for_name_owner (connection, E_DATA_BOOK_FACTORY_SERVICE_NAME, view_path,
+							      "org.gnome.evolution.dataserver.addressbook.BookView", &err);
+		if (view_proxy) {
+			view = _e_book_view_new (data->book, view_proxy);
+			status = E_BOOK_ERROR_OK;
+		} else {
+			g_warning (G_STRLOC ": cannot get connection to view: %s", err->message);
+			g_error_free (err);
+			status = E_BOOK_ERROR_CORBA_EXCEPTION;
+		}
+	} else {
+		status = get_status_from_error (error);
+	}
+
+	if (cb)
+		cb (data->book, status, view, data->closure);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -1961,173 +1210,25 @@ e_book_async_get_book_view (EBook                 *book,
 			    EBookBookViewCallback  cb,
 			    gpointer               closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book),       TRUE);
-	g_return_val_if_fail (query,                          TRUE);
-
-	return !do_get_book_view (FALSE,
-				  book, query, requested_fields, max_results, NULL, NULL,
-				  cb, closure);
-}
-
-static gboolean
-emit_async_get_book_view_response (gpointer data)
-{
-	EBookOp *op = data;
-	EBook *book = op->book;
-
-	if (op->cb.book_view)
-		op->cb.book_view (book, op->status, op->view, op->closure);
-
-	g_mutex_lock (book->priv->mutex);
-
-	g_object_unref (op->view);
-
-	book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-						   GINT_TO_POINTER (op->idle_id));
-
-	e_book_clear_op (book, op);
-
-	g_mutex_unlock (book->priv->mutex);
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static void
-e_book_response_get_book_view (EBook       *book,
-			       guint32      opid,
-			       EBookStatus  status,
-			       GNOME_Evolution_Addressbook_BookView corba_book_view)
-{
-
-	EBookOp *op;
-
-	d(printf ("e_book_response_get_book_view\n"));
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
+	AsyncData *data;
+	gchar *sexp;
 
-	op->status = status;
-	op->view = e_book_view_new (corba_book_view, op->listener);
-	e_book_view_set_book (op->view, book);
+	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_async_error_val_if_fail (query, E_BOOK_ERROR_INVALID_ARG);
 
-	bonobo_object_unref(BONOBO_OBJECT(op->listener));
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	if (op->synchronous)
-		e_flag_set (op->flag);
-	else {
-		op->book = g_object_ref (book);
+	sexp = e_book_query_to_string (query);
 
-		op->idle_id = g_idle_add (emit_async_get_book_view_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
+	org_gnome_evolution_dataserver_addressbook_Book_get_book_view_async (book->priv->proxy, sexp, max_results, get_book_view_reply, data);
 
-	g_mutex_unlock (book->priv->mutex);
+	g_free (sexp);
+	return 0;
 }
-
-static gboolean
-do_get_contacts (gboolean sync,
-		 EBook *book,
-		 EBookQuery *query,
-		 GList **contacts,
-		 GError **error,
-		 EBookListCallback cb,
-		 gpointer closure)
-{
-	CORBA_Environment ev;
-	EBookOp *our_op;
-	EBookStatus status;
-	gchar *query_string;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_get_contacts", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_get_contacts", "e_book_open");
-		}
-
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	query_string = e_book_query_to_string (query);
-
-	our_op->cb.list = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling e_book_response_get_contacts */
-	GNOME_Evolution_Addressbook_Book_getContactList (book->priv->corba_book, our_op->opid, query_string, &ev);
-
-	g_free (query_string);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::getContactList");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::getContactList");
-		}
-
-		return FALSE;
-	}
-
-	CORBA_exception_free (&ev);
-
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-		*contacts = our_op->list;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
-}
-
 /**
  * e_book_get_contacts:
  * @book: an #EBook
@@ -2146,13 +1247,50 @@ e_book_get_contacts (EBook       *book,
 		     GList      **contacts,
 		     GError     **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book),       E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (query,                          E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (contacts,                       E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	char **list = NULL;
+	char *sexp;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	sexp = e_book_query_to_string (query);
+	org_gnome_evolution_dataserver_addressbook_Book_get_contact_list (book->priv->proxy, sexp, &list, &err);
+	g_free (sexp);
+	if (!err) {
+		GList *l = NULL;
+		char **i = list;
+		while (*i != NULL) {
+			l = g_list_prepend (l, e_contact_new_from_vcard (*i++));
+		}
+		*contacts = g_list_reverse (l);
+		g_strfreev (list);
+		return TRUE;
+	} else {
+		return unwrap_gerror (err, error);
+	}
+}
 
-	return do_get_contacts (TRUE,
-				book, query, contacts, error,
-				NULL, NULL);
+static void
+get_contacts_reply(DBusGProxy *proxy, char **vcards, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	GList *list = NULL;
+	EBookListCallback cb = data->callback;
+	if (vcards) {
+		char **i = vcards;
+		while (*i != NULL) {
+			list = g_list_prepend (list, e_contact_new_from_vcard (*i++));
+		}
+	}
+	list = g_list_reverse (list);
+
+	if (cb)
+		cb (data->book, get_status_from_error (error), list, data->closure);
+	g_strfreev (vcards);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -2172,163 +1310,52 @@ e_book_async_get_contacts (EBook             *book,
 			   EBookListCallback  cb,
 			   gpointer           closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book),       TRUE);
-	g_return_val_if_fail (query,                          TRUE);
-
-	return !do_get_contacts (FALSE,
-				 book, query, NULL, NULL,
-				 cb, closure);
-}
-
-static gboolean
-emit_async_get_contacts_response (gpointer data)
-{
-	EBookOp *op = data;
-	EBook *book = op->book;
-
-	if (op->cb.list)
-		op->cb.list (book, op->status, op->list, op->closure);
-
-	g_mutex_lock (book->priv->mutex);
-
-	g_list_foreach (op->list, (GFunc)g_object_unref, NULL);
-	g_list_free (op->list);
+	AsyncData *data;
+	gchar *sexp;
 
-	book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-						   GINT_TO_POINTER (op->idle_id));
+	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+	e_return_async_error_val_if_fail (query, E_BOOK_ERROR_INVALID_ARG);
 
-	e_book_clear_op (book, op);
+	sexp = e_book_query_to_string (query);
 
-	g_mutex_unlock (book->priv->mutex);
-	g_object_unref (book);
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	return FALSE;
-}
-
-
-static void
-e_book_response_get_contacts (EBook       *book,
-			      guint32      opid,
-			      EBookStatus  status,
-			      GList       *contact_list)
-{
-
-	EBookOp *op;
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->list = g_list_copy (contact_list);
-	g_list_foreach (op->list, (GFunc)g_object_ref, NULL);
-	op->status = status;
-
-	if (op->synchronous)
-		e_flag_set (op->flag);
-	else {
-		op->book = g_object_ref (book);
-		op->idle_id = g_idle_add (emit_async_get_contacts_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
+	org_gnome_evolution_dataserver_addressbook_Book_get_contact_list_async (book->priv->proxy, sexp, get_contacts_reply, data);
+	g_free (sexp);
+	return 0;
 }
 
-
-static gboolean
-do_get_changes (gboolean sync,
-		EBook *book,
-		const gchar *changeid,
-		GList **changes,
-		GError **error,
-		EBookListCallback cb,
-		gpointer closure)
+static GList *
+parse_changes_array (GPtrArray *array)
 {
-	CORBA_Environment ev;
-	EBookOp *our_op;
-	EBookStatus status;
-
-	g_mutex_lock (book->priv->mutex);
+	GList *l = NULL;
+	int i;
 
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_get_changes", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book before \"%s\""),
-				   "e_book_get_changes", "e_book_open");
-		}
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.list = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling e_book_response_get_changes */
-	GNOME_Evolution_Addressbook_Book_getChanges (book->priv->corba_book, our_op->opid, changeid, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
+	if (array == NULL)
+		return NULL;
 
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
+	for (i = 0; i < array->len; i++) {
+		EBookChange *change;
+		GValueArray *vals;
 
-		CORBA_exception_free (&ev);
+		vals = g_ptr_array_index (array, i);
 
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::getChanges");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::getChanges");
-		}
+		change = g_slice_new (EBookChange);
+		change->change_type = g_value_get_uint (g_value_array_get_nth (vals, 0));
+		change->contact = e_contact_new_from_vcard
+			(g_value_get_string (g_value_array_get_nth (vals, 1)));
 
-		return FALSE;
+		l = g_list_prepend (l, change);
 	}
 
-	CORBA_exception_free (&ev);
-
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-		*changes = our_op->list;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
+	g_ptr_array_foreach (array, (GFunc)g_value_array_free, NULL);
+	g_ptr_array_free (array, TRUE);
 
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	return g_list_reverse (l);
 }
 
 /**
@@ -2349,13 +1376,36 @@ e_book_get_changes (EBook       *book,
 		    GList      **changes,
 		    GError     **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book),       E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (changeid,                       E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (changes,                        E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	GPtrArray *array = NULL;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	org_gnome_evolution_dataserver_addressbook_Book_get_changes (book->priv->proxy, changeid, &array, &err);
+	if (!err) {
+		*changes = parse_changes_array (array);
+		return TRUE;
+	} else {
+		return unwrap_gerror (err, error);
+	}
+}
+
+static void
+get_changes_reply (DBusGProxy *proxy, GPtrArray *changes, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookListCallback cb = data->callback;
+	GList *list = NULL;
+
+	if (changes)
+		list = parse_changes_array (changes);
 
-	return do_get_changes (TRUE,
-			       book, changeid, changes, error,
-			       NULL, NULL);
+	if (cb)
+		cb (data->book, get_status_from_error (error), list, data->closure);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -2376,69 +1426,18 @@ e_book_async_get_changes (EBook             *book,
 			  EBookListCallback  cb,
 			  gpointer           closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book),       TRUE);
-	g_return_val_if_fail (changeid,                       TRUE);
-
-	return !do_get_changes (FALSE,
-				book, changeid, NULL, NULL,
-				cb, closure);
-}
+	AsyncData *data;
 
-static gboolean
-emit_async_get_changes_response (gpointer data)
-{
-	EBookOp *op = data;
-	EBook *book = op->book;
+	e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-	if (op->cb.list)
-		op->cb.list (book, op->status, op->list, op->closure);
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	g_mutex_lock (book->priv->mutex);
-
-	e_book_free_change_list (op->list);
-
-	book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-						   GINT_TO_POINTER (op->idle_id));
-
-	e_book_clear_op (book, op);
-
-	g_mutex_unlock (book->priv->mutex);
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static void
-e_book_response_get_changes (EBook       *book,
-			     guint32      opid,
-			     EBookStatus  status,
-			     GList       *change_list)
-{
-
-	EBookOp *op;
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->status = status;
-	op->list = change_list;
-
-	if (op->synchronous)
-		e_flag_set (op->flag);
-	else {
-		op->book = g_object_ref (book);
-		op->idle_id = g_idle_add (emit_async_get_changes_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
+	org_gnome_evolution_dataserver_addressbook_Book_get_changes_async (book->priv->proxy, changeid, get_changes_reply, data);
+	return 0;
 }
 
 /**
@@ -2455,117 +1454,12 @@ e_book_free_change_list (GList *change_list)
 		EBookChange *change = l->data;
 
 		g_object_unref (change->contact);
-		g_free (change);
+		g_slice_free (EBookChange, change);
 	}
 
 	g_list_free (change_list);
 }
 
-
-
-static gboolean
-emit_async_generic_response (gpointer data)
-{
-	EBookOp *op = data;
-	EBook *book = op->book;
-
-	if (op->cb.status)
-		op->cb.status (book, op->status, op->closure);
-
-	g_mutex_lock (book->priv->mutex);
-
-	book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-						   GINT_TO_POINTER (op->idle_id));
-
-	e_book_clear_op (book, op);
-
-	g_mutex_unlock (book->priv->mutex);
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static void
-e_book_response_generic (EBook       *book,
-			 guint32      opid,
-			 EBookStatus  status)
-{
-	EBookOp *op;
-	d(printf("e_book_response_generic\n"));
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->status = status;
-	if (op->synchronous)
-		e_flag_set (op->flag);
-	else {
-		op->book = g_object_ref (book);
-		op->idle_id = g_idle_add (emit_async_generic_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-}
-
-static gboolean
-do_cancel (EBook *book, GError **error, EBookOp *op, const gchar *func_name)
-{
-	EBookStatus status;
-	gboolean rv;
-	CORBA_Environment ev;
-
-	if (op == NULL) {
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
-			     _("%s: there is no current operation"), func_name);
-		return FALSE;
-	}
-
-	status = GNOME_Evolution_Addressbook_Book_cancelOperation(book->priv->corba_book, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		CORBA_exception_free (&ev);
-
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-			     _("CORBA exception making \"%s\" call"),
-			     "Book::cancelOperation");
-		e_flag_set (op->flag);
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, op);
-		g_mutex_unlock (book->priv->mutex);
-		return FALSE;
-	}
-
-	CORBA_exception_free (&ev);
-
-	if (status == E_BOOK_ERROR_OK) {
-		op->status = E_BOOK_ERROR_CANCELLED;
-		rv = TRUE;
-	}
-	else {
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
-			     _("%s: could not cancel"), func_name);
-		rv = FALSE;
-	}
-	/* Always trigger the operation, we cannot put it back to queue, because
-	   the result could come just few ticks before, in the other thread. */
-	e_flag_set (op->flag);
-
-	g_mutex_lock (book->priv->mutex);
-	e_book_clear_op (book, op);
-	g_mutex_unlock (book->priv->mutex);
-
-	return rv;
-}
-
 /**
  * e_book_cancel:
  * @book: an #EBook
@@ -2587,25 +1481,10 @@ gboolean
 e_book_cancel (EBook   *book,
 	       GError **error)
 {
-	EBookOp *op;
-
-	e_return_error_if_fail (book && E_IS_BOOK (book),       E_BOOK_ERROR_INVALID_ARG, FALSE);
-
-	g_mutex_lock (book->priv->mutex);
-	op = e_book_get_current_sync_op (book);
-	if (op) {
-		if (op->opstate != STATE_WAITING) {
-			g_mutex_unlock (book->priv->mutex);
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
-				_("%s: could not cancel"), G_STRFUNC);
-			return FALSE;
-		}
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-		op->opstate = STATE_CANCELLING;
-	}
-	g_mutex_unlock (book->priv->mutex);
-
-	return do_cancel (book, error, op, "e_book_cancel");
+	return org_gnome_evolution_dataserver_addressbook_Book_cancel_operation (book->priv->proxy, error);
 }
 
 /**
@@ -2616,140 +1495,12 @@ e_book_cancel (EBook   *book,
 gboolean
 e_book_cancel_async_op (EBook *book, GError **error)
 {
-	EBookOp *op;
-	guint32 opid;
-
-	e_return_error_if_fail (book && E_IS_BOOK (book),       E_BOOK_ERROR_INVALID_ARG, FALSE);
-
-	g_mutex_lock (book->priv->mutex);
-
-	/* find nearest unfinished async op to cancel */
-	op = NULL;
-	for (opid = book->priv->current_op_id; opid > 0 && !op; opid--) {
-		op = e_book_get_op (book, opid);
-
-		if (op && op->synchronous)
-			op = NULL;
-	}
-
-	if (op) {
-		if (op->opstate != STATE_WAITING) {
-			g_mutex_unlock (book->priv->mutex);
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
-				_("%s: could not cancel"), G_STRFUNC);
-			return FALSE;
-		}
-
-		op->opstate = STATE_CANCELLING;
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-
-	return do_cancel (book, error, op, "e_book_cancel_async_op");
-}
-
-
-
-static gboolean
-do_open (gboolean sync,
-	 EBook *book,
-	 gboolean only_if_exists,
-	 GError **error,
-	 EBookCallback cb,
-	 gpointer closure)
-{
-	CORBA_Environment ev;
-	EBookOp *our_op;
-	EBookStatus status;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (book->priv->load_state != E_BOOK_SOURCE_NOT_LOADED) {
-		g_mutex_unlock (book->priv->mutex);
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_ALREADY_LOADED,
-				     _("\"%s\" on book after \"%s\""),
-				     "e_book_open", "e_book_open");
-		}
-		else {
-			g_warning (_("\"%s\" on book after \"%s\""),
-				   "e_book_open", "e_book_open");
-		}
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-		return FALSE;
-	}
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
+	g_debug ("TODO: implement e_book_cancel_async_op");
 
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.status = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling e_book_response_remove */
-	GNOME_Evolution_Addressbook_Book_open (book->priv->corba_book, our_op->opid, only_if_exists, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::open");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::open");
-		}
-
-		return FALSE;
-	}
-
-	CORBA_exception_free (&ev);
-
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
-
-		status = our_op->status;
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		if (status == E_BOOK_ERROR_CANCELLED) {
-			/* Cancelled */
-			book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CANCELLED,
-				     _("%s: canceled"), "e_book_open");
-			return FALSE;
-		}
-		else if (status == E_BOOK_ERROR_OK) {
-			book->priv->load_state = E_BOOK_SOURCE_LOADED;
-			return TRUE;
-		}
-		else {
-			E_BOOK_CHECK_STATUS (status, error);
-		}
-	}
-	else {
-		return TRUE;
-	}
+	return org_gnome_evolution_dataserver_addressbook_Book_cancel_operation (book->priv->proxy, error);
 }
 
 /**
@@ -2767,11 +1518,44 @@ e_book_open (EBook     *book,
 	     gboolean   only_if_exists,
 	     GError   **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
+	EBookStatus status;
+
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	if (!org_gnome_evolution_dataserver_addressbook_Book_open (book->priv->proxy, only_if_exists, &err)) {
+		g_propagate_error (error, err);
+		return FALSE;
+	}
+
+	status = get_status_from_error (err);
+
+	if (status == E_BOOK_ERROR_OK) {
+		book->priv->loaded = TRUE;
+		return TRUE;
+	} else {
+		g_propagate_error (error, err);
+		return FALSE;
+	}
+}
+
+static void
+open_reply(DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookCallback cb = data->callback;
+	EDataBookStatus status;
+
+	status = get_status_from_error (error);
+
+	data->book->priv->loaded = (status == E_BOOK_ERROR_OK);
 
-	return do_open (TRUE,
-			book, only_if_exists, error,
-			NULL, NULL);
+	if (cb)
+		cb (data->book, status, data->closure);
+
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -2789,152 +1573,21 @@ e_book_open (EBook     *book,
 guint
 e_book_async_open (EBook                 *book,
 		   gboolean               only_if_exists,
-		   EBookCallback          open_response,
+		   EBookCallback          cb,
 		   gpointer               closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), FALSE);
-
-	return !do_open (FALSE,
-			 book, only_if_exists, NULL,
-			 open_response, closure);
-}
-
-static gboolean
-emit_async_open_response (gpointer data)
-{
-	EBookOp *op = data;
-	EBook *book = op->book;
-
-	d(printf ("in async_open_response\n"));
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (op->status == E_BOOK_ERROR_OK)
-		book->priv->load_state = E_BOOK_SOURCE_LOADED;
-	else
-		book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
-
-	g_mutex_unlock (book->priv->mutex);
-
-	if (op->cb.status)
-		op->cb.status (book, op->status, op->closure);
-
-	g_mutex_lock (book->priv->mutex);
-
-	book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
-						   GINT_TO_POINTER (op->idle_id));
-
-	e_book_clear_op (book, op);
-
-	g_mutex_unlock (book->priv->mutex);
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static void
-e_book_response_open (EBook       *book,
-		      guint32      opid,
-		      EBookStatus  status)
-{
-	EBookOp *op;
-
-	d(printf ("in e_book_response_open\n"));
-
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->status = status;
-	if (op->synchronous)
-		e_flag_set (op->flag);
-	else {
-		op->book = g_object_ref (book);
-		op->idle_id = g_idle_add (emit_async_open_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-}
-
-
-static gboolean
-do_remove (gboolean sync,
-	   EBook *book,
-	   GError **error,
-	   EBookCallback cb,
-	   gpointer closure)
-{
-	CORBA_Environment ev;
-	EBookOp *our_op;
-	EBookStatus status;
-
-	g_mutex_lock (book->priv->mutex);
-
-	if (sync && e_book_get_current_sync_op (book) != NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
-			     _("book busy"));
-		return FALSE;
-	}
-
-	our_op = e_book_new_op (book, sync);
-
-	g_mutex_unlock (book->priv->mutex);
-
-	CORBA_exception_init (&ev);
-
-	our_op->cb.status = cb;
-	our_op->closure = closure;
-
-	/* will eventually end up calling e_book_response_remove */
-	GNOME_Evolution_Addressbook_Book_remove (book->priv->corba_book, our_op->opid, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		CORBA_exception_free (&ev);
-
-		if (error) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::remove");
-		}
-		else {
-			g_warning (_("CORBA exception making \"%s\" call"),
-				   "Book::remove");
-		}
-
-		return FALSE;
-	}
-
-	CORBA_exception_free (&ev);
+	AsyncData *data;
 
-	if (sync) {
-		/* wait for something to happen (both cancellation and a
-		   successful response will notity us via our cv */
-		e_flag_wait (our_op->flag);
+	e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-		status = our_op->status;
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-		g_mutex_lock (book->priv->mutex);
-		e_book_clear_op (book, our_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		E_BOOK_CHECK_STATUS (status, error);
-	}
-	else {
-		return TRUE;
-	}
+	org_gnome_evolution_dataserver_addressbook_Book_open_async (book->priv->proxy, only_if_exists, open_reply, data);
+	return 0;
 }
 
 /**
@@ -2951,12 +1604,25 @@ gboolean
 e_book_remove (EBook   *book,
 	       GError **error)
 {
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
+	GError *err = NULL;
 
-	return do_remove (TRUE,
-			  book, error,
-			  NULL, NULL);
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+	org_gnome_evolution_dataserver_addressbook_Book_remove (book->priv->proxy, &err);
+	return unwrap_gerror (err, error);
+}
+
+static void
+remove_reply(DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+	AsyncData *data = user_data;
+	EBookCallback cb = data->callback;
+	if (cb)
+		cb (data->book, get_status_from_error (error), data->closure);
 
+	g_object_unref (data->book);
+	g_slice_free (AsyncData, data);
 }
 
 /**
@@ -2975,424 +1641,18 @@ e_book_async_remove (EBook   *book,
 		     EBookCallback cb,
 		     gpointer closure)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
+	AsyncData *data;
 
-	return !do_remove (FALSE,
-			   book, NULL,
-			   cb, closure);
+	e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
-}
-
-static void
-e_book_response_remove (EBook       *book,
-			guint32      opid,
-			EBookStatus  status)
-{
-	EBookOp *op;
-
-	d(printf ("e_book_response_remove\n"));
+	data = g_slice_new0 (AsyncData);
+	data->book = g_object_ref (book);
+	data->callback = cb;
+	data->closure = closure;
 
-	g_mutex_lock (book->priv->mutex);
-
-	op = e_book_find_op (book, opid, G_STRFUNC);
-
-	if (op == NULL) {
-		g_mutex_unlock (book->priv->mutex);
-		return;
-	}
-
-	op->status = status;
-	if (op->synchronous)
-		e_flag_set (op->flag);
-	else {
-		op->book = g_object_ref (book);
-		op->idle_id = g_idle_add (emit_async_generic_response, op);
-		book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
-							    GINT_TO_POINTER (op->idle_id));
-	}
-
-	g_mutex_unlock (book->priv->mutex);
-}
-
-static gboolean
-e_book_idle_writable (gpointer data)
-{
-	EBook *book = data;
-	gboolean writable;
-
-	g_mutex_lock (book->priv->mutex);
-	writable = book->priv->writable;
-	book->priv->writable_idle_id = 0;
-	g_mutex_unlock (book->priv->mutex);
-
-	g_signal_emit (G_OBJECT (book), e_book_signals [WRITABLE_STATUS], 0, writable);
-
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static gboolean
-e_book_idle_connection (gpointer data)
-{
-	EBook *book = data;
-	gboolean connected;
-
-	if (!book->priv)
-		return FALSE;
-
-	g_mutex_lock (book->priv->mutex);
-	connected = book->priv->connected;
-	book->priv->connection_idle_id = 0;
-	g_mutex_unlock (book->priv->mutex);
-
-	g_signal_emit (G_OBJECT (book), e_book_signals [CONNECTION_STATUS], 0, connected);
-
-	g_object_unref (book);
-
-	return FALSE;
-}
-
-static gboolean
-e_book_idle_auth_required (gpointer data)
-{
-	EBook *book = data;
-	gboolean connected;
-
-	if (!book->priv)
-		return FALSE;
-
-	g_mutex_lock (book->priv->mutex);
-	connected = book->priv->connected;
-	book->priv->auth_idle_id = 0;
-	g_mutex_unlock (book->priv->mutex);
-
-	g_signal_emit (G_OBJECT (book), e_book_signals [AUTH_REQUIRED], 0);
-
-	g_object_unref (book);
-
-	return FALSE;
-
-
-}
-
-static void
-e_book_handle_response (EBookListener *listener, EBookListenerResponse *resp, EBook *book)
-{
-	EContact *contact;
-
-	switch (resp->op) {
-	case CreateContactResponse:
-		e_book_response_add_contact (book, resp->opid, resp->status, resp->id);
-		break;
-	case RemoveContactResponse:
-	case ModifyContactResponse:
-	case AuthenticationResponse:
-		e_book_response_generic (book, resp->opid, resp->status);
-		break;
-	case GetContactResponse:
-		contact = e_contact_new_from_vcard (resp->vcard);
-		e_book_response_get_contact (book, resp->opid, resp->status, contact);
-		break;
-	case GetContactListResponse:
-		e_book_response_get_contacts (book, resp->opid, resp->status, resp->list);
-		break;
-	case GetBookViewResponse:
-		e_book_response_get_book_view(book, resp->opid, resp->status, resp->book_view);
-		break;
-	case GetChangesResponse:
-		e_book_response_get_changes(book, resp->opid, resp->status, resp->list);
-		break;
-	case OpenBookResponse:
-		e_book_response_open (book, resp->opid, resp->status);
-		break;
-	case RemoveBookResponse:
-		e_book_response_remove (book, resp->opid, resp->status);
-		break;
-	case GetSupportedFieldsResponse:
-		e_book_response_get_supported_fields (book, resp->opid, resp->status, resp->list);
-		break;
-	case GetRequiredFieldsResponse:
-		e_book_response_get_required_fields (book, resp->opid, resp->status, resp->list);
-		break;
-	case GetSupportedAuthMethodsResponse:
-		e_book_response_get_supported_auth_methods (book, resp->opid, resp->status, resp->list);
-		break;
-	case WritableStatusEvent:
-		book->priv->writable = resp->writable;
-
-		g_mutex_lock (book->priv->mutex);
-		if (book->priv->writable_idle_id == 0) {
-			g_object_ref (book);
-			book->priv->writable_idle_id = g_idle_add (e_book_idle_writable, book);
-		}
-		g_mutex_unlock (book->priv->mutex);
-
-		break;
-	case LinkStatusEvent:
-		book->priv->connected = resp->connected;
-		g_mutex_lock (book->priv->mutex);
-		if (book->priv->connection_idle_id == 0) {
-			g_object_ref (book);
-			book->priv->connection_idle_id = g_idle_add (e_book_idle_connection, book);
-		}
-		g_mutex_unlock (book->priv->mutex);
-		break;
-	case AuthRequiredEvent:
-		g_mutex_lock (book->priv->mutex);
-		if (book->priv->auth_idle_id == 0) {
-			g_object_ref (book);
-			book->priv->auth_idle_id = g_idle_add (e_book_idle_auth_required, book);
-		}
-		g_mutex_unlock (book->priv->mutex);
-		break;
-
-	default:
-		g_error ("EBook: Unknown response code %d!\n",
-			 resp->op);
-	}
-}
-
-
-
-/**
- * e_book_unload_uri:
- * @book: an #EBook
- * @error: an #GError to set on failure
- *
- * Unload the URI that this book had previously loaded.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-static gboolean
-e_book_unload_uri (EBook   *book,
-		   GError **error)
-{
-	CORBA_Environment ev;
-
-	e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (book->priv->load_state != E_BOOK_SOURCE_NOT_LOADED, E_BOOK_ERROR_SOURCE_NOT_LOADED, FALSE);
-
-	if (book->priv->load_state == E_BOOK_SOURCE_LOADED) {
-		/* Release the remote GNOME_Evolution_Addressbook_Book in the PAS. */
-		CORBA_exception_init (&ev);
-
-		bonobo_object_release_unref  (book->priv->corba_book, &ev);
-		if (ev._major != CORBA_NO_EXCEPTION) {
-			g_warning ("e_book_unload_uri: Exception releasing "
-				   "remote book interface!\n");
-		}
-
-		CORBA_exception_free (&ev);
-
-		book->priv->corba_book = CORBA_OBJECT_NIL;
-		e_book_listener_stop (book->priv->listener);
-		bonobo_object_unref (BONOBO_OBJECT (book->priv->listener));
-
-		book->priv->listener   = NULL;
-		book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
-		g_free (book->priv->cap);
-		book->priv->cap = NULL;
-		book->priv->cap_queried = FALSE;
-		book->priv->writable = FALSE;
-	}
-	else if (book->priv->load_state == E_BOOK_SOURCE_LOADING) {
-		e_book_cancel (book, error);
-	}
-
-	return TRUE;
-}
-
-
-
-
-/* Set a flag for operation from the operation hash table */
-static void
-find_key_value (gpointer key, gpointer value, gpointer data)
-{
-	EBookOp *op;
-
-	op = value;
-
-	if (op == NULL) {
-		g_warning ("find_key_value: Cannot find operation ");
-		return;
-	}
-
-	op->status = E_BOOK_ERROR_SOURCE_NOT_LOADED;
-	if (op->synchronous)
-		e_flag_set (op->flag);
-}
-
-/**
- * e_book_load_uri:
- */
-
-static void
-backend_died_cb (EComponentListener *cl, gpointer user_data)
-{
-	EBook *book = (EBook *)user_data;
-
-	d(printf ("backend_died_cb\n"));
-
-	g_mutex_lock (book->priv->mutex);
-	g_hash_table_foreach (book->priv->id_to_op, find_key_value, NULL);
-	g_mutex_unlock (book->priv->mutex);
-
-	book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
-        g_signal_emit (book, e_book_signals [BACKEND_DIED], 0);
-}
-
-static GList *
-activate_factories_for_uri (EBook *book, const gchar *uri)
-{
-	CORBA_Environment ev;
-	Bonobo_ServerInfoList *info_list = NULL;
-	gint i;
-	const gchar *query;
-	GList *factories = NULL;
-
-	query = "repo_ids.has ('IDL:GNOME/Evolution/DataServer/BookFactory:" API_VERSION "')";
-
-	CORBA_exception_init (&ev);
-
-	info_list = bonobo_activation_query (query, NULL, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		gchar *exc_text = bonobo_exception_get_text (&ev);
-		g_warning ("Cannot perform bonobo-activation query for book factories: %s", exc_text);
-		g_free (exc_text);
-		CORBA_exception_free (&ev);
-		goto done;
-		return NULL;
-	}
-
-	if (info_list->_length == 0) {
-		g_warning ("Can't find installed BookFactories");
-		CORBA_exception_free (&ev);
-		goto done;
-	}
-
-	CORBA_exception_free (&ev);
-
-	for (i = 0; i < info_list->_length; i ++) {
-		const Bonobo_ServerInfo *info;
-		GNOME_Evolution_Addressbook_BookFactory factory;
-
-		info = info_list->_buffer + i;
-
-		factory = bonobo_activation_activate_from_id (info->iid, 0, NULL, NULL);
-
-		if (factory == CORBA_OBJECT_NIL)
-			g_warning ("e_book_construct: Could not obtain a handle "
-				   "to the Personal Addressbook Server with IID `%s'\n", info->iid);
-		else
-			factories = g_list_append (factories, factory);
-	}
-
- done:
-	if (info_list)
-		CORBA_free (info_list);
-
-	return factories;
-}
-
-/* XXX hm, should this function hold a lock on book->priv->mutex?  It
-   doesn't seem to require it, but there are unlocked writes to
-   book->priv->load_state, which other functions read.. */
-static gboolean
-fetch_corba_book (EBook       *book,
-		  ESource     *source,
-		  GError     **error)
-{
-	GNOME_Evolution_Addressbook_Book corba_book = CORBA_OBJECT_NIL;
-	gchar *uri;
-	gchar *source_xml;
-	GList *factories;
-	GList *l;
-	gboolean rv = FALSE;
-
-	uri = e_source_get_uri (source);
-	if (!uri) {
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_OTHER_ERROR,
-			     _("%s: Invalid source."), "e_book_load_uri");
-		return FALSE;
-	}
-
-	/* try to find a list of factories that can handle the protocol */
-	factories = activate_factories_for_uri (book, uri);
-	if (!factories) {
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED,
-			     _("%s: no factories available for URI `%s'"), "e_book_load_uri", uri);
-		return FALSE;
-	}
-
-
-	/*
-	 * Create our local BookListener interface.
-	 */
-	book->priv->listener = e_book_listener_new ();
-	if (book->priv->listener == NULL) {
-		g_warning ("e_book_load_uri: Could not create EBookListener!\n");
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_OTHER_ERROR,
-			     _("%s: Could not create EBookListener"), "e_book_load_uri");
-		return FALSE;
-	}
-	book->priv->listener_signal = g_signal_connect_object (book->priv->listener, "response",
-							       G_CALLBACK (e_book_handle_response),
-							       book, 0);
-
-	g_free (book->priv->uri);
-	book->priv->uri = uri;
-
-	g_object_ref (source);
-	if (book->priv->source)
-		g_object_unref (book->priv->source);
-	book->priv->source = source;
-
-	source_xml = e_source_to_standalone_xml (source);
-
-	for (l = factories; l; l = l->next) {
-		GNOME_Evolution_Addressbook_BookFactory factory = l->data;
-		CORBA_Environment ev;
-
-		CORBA_exception_init (&ev);
-
-		corba_book = GNOME_Evolution_Addressbook_BookFactory_getBook (factory, source_xml,
-									      bonobo_object_corba_objref (BONOBO_OBJECT (book->priv->listener)),
-									      &ev);
-
-		if (ev._major != CORBA_NO_EXCEPTION) {
-			CORBA_exception_free (&ev);
-			continue;
-		}
-		else if (corba_book != CORBA_OBJECT_NIL) {
-			rv = TRUE;
-			break;
-		}
-	}
-
-	g_free (source_xml);
-
-	/* free up the factories */
-	for (l = factories; l; l = l->next)
-		CORBA_Object_release ((CORBA_Object)l->data, NULL);
-
-	g_list_free (factories);
-
-	if (rv == TRUE) {
-		book->priv->corba_book = corba_book;
-		book->priv->comp_listener = e_component_listener_new (book->priv->corba_book);
-		book->priv->died_signal = g_signal_connect (book->priv->comp_listener,
-							    "component_died",
-							    G_CALLBACK (backend_died_cb), book);
-	}
-	else {
-		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED,
-			     _("%s: no factories available for URI `%s'"), "e_book_new", uri);
-	}
-
-	return rv;
+	org_gnome_evolution_dataserver_addressbook_Book_remove_async (book->priv->proxy, remove_reply, data);
+	return 0;
 }
 
 /**
@@ -3406,7 +1666,7 @@ fetch_corba_book (EBook       *book,
 const gchar *
 e_book_get_uri (EBook *book)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), NULL);
+	g_return_val_if_fail (E_IS_BOOK (book), NULL);
 
 	return book->priv->uri;
 }
@@ -3422,7 +1682,7 @@ e_book_get_uri (EBook *book)
 ESource *
 e_book_get_source (EBook *book)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), NULL);
+	g_return_val_if_fail (E_IS_BOOK (book), NULL);
 
 	return book->priv->source;
 }
@@ -3441,37 +1701,18 @@ const gchar *
 e_book_get_static_capabilities (EBook   *book,
 				GError **error)
 {
-	g_return_val_if_fail (book && E_IS_BOOK (book), NULL);
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
 
 	if (!book->priv->cap_queried) {
-		CORBA_Environment ev;
-		gchar *temp;
+		char *cap = NULL;
 
-		CORBA_exception_init (&ev);
-
-		if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
-				     _("\"%s\" on book before \"%s\""),
-				     "e_book_get_static_capabilities", "e_book_open");
-			return g_strdup ("");
+		if (!org_gnome_evolution_dataserver_addressbook_Book_get_static_capabilities (book->priv->proxy, &cap, error)) {
+			return NULL;
 		}
 
-		temp = GNOME_Evolution_Addressbook_Book_getStaticCapabilities(book->priv->corba_book, &ev);
-
-		if (ev._major != CORBA_NO_EXCEPTION) {
-			g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
-				     _("CORBA exception making \"%s\" call"),
-				     "Book::getStaticCapabilities");
-			CORBA_exception_free (&ev);
-			return g_strdup ("");
-		}
-
-		book->priv->cap = g_strdup(temp);
+		book->priv->cap = cap;
 		book->priv->cap_queried = TRUE;
-
-		CORBA_free(temp);
-
-		CORBA_exception_free (&ev);
 	}
 
 	return book->priv->cap;
@@ -3517,10 +1758,7 @@ e_book_is_opened (EBook *book)
 {
 	g_return_val_if_fail (E_IS_BOOK (book), FALSE);
 
-	if (book->priv->load_state != E_BOOK_SOURCE_LOADED)
-		return FALSE;
-
-	return TRUE;
+	return book->priv->loaded;
 }
 
 /**
@@ -3635,8 +1873,8 @@ e_book_set_self (EBook *book, EContact *contact, GError **error)
 {
 	GConfClient *gconf;
 
-	e_return_error_if_fail (book && E_IS_BOOK (book),          E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (contact && E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG, FALSE);
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
 
 	gconf = gconf_client_get_default();
 	gconf_client_set_string (gconf, SELF_UID_KEY, e_contact_get_const (contact, E_CONTACT_UID), NULL);
@@ -3675,8 +1913,6 @@ e_book_is_self (EContact *contact)
 	return rv;
 }
 
-
-
 /**
  * e_book_set_default_addressbook:
  * @book: An #EBook pointer
@@ -3692,8 +1928,8 @@ e_book_set_default_addressbook (EBook *book, GError **error)
 {
 	ESource *source;
 
-	e_return_error_if_fail (book && E_IS_BOOK (book),                        E_BOOK_ERROR_INVALID_ARG, FALSE);
-	e_return_error_if_fail (book->priv->load_state == E_BOOK_SOURCE_NOT_LOADED, E_BOOK_ERROR_SOURCE_ALREADY_LOADED, FALSE);
+	e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+	e_return_error_if_fail (book->priv->loaded == FALSE, E_BOOK_ERROR_SOURCE_ALREADY_LOADED);
 
 	source = e_book_get_source (book);
 
@@ -3719,7 +1955,7 @@ e_book_set_default_source (ESource *source, GError **error)
 	GError *err = NULL;
 	GSList *g;
 
-	e_return_error_if_fail (source && E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG, FALSE);
+	e_return_error_if_fail (source && E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG);
 
 	uid = e_source_peek_uid (source);
 
@@ -3776,7 +2012,7 @@ e_book_get_addressbooks (ESourceList **addressbook_sources, GError **error)
 {
 	GConfClient *gconf;
 
-	e_return_error_if_fail (addressbook_sources, E_BOOK_ERROR_INVALID_ARG, FALSE);
+	e_return_error_if_fail (addressbook_sources, E_BOOK_ERROR_INVALID_ARG);
 
 	gconf = gconf_client_get_default();
 	*addressbook_sources = e_source_list_new_for_gconf (gconf, "/apps/evolution/addressbook/sources");
@@ -3785,38 +2021,6 @@ e_book_get_addressbooks (ESourceList **addressbook_sources, GError **error)
 	return TRUE;
 }
 
-
-static gpointer
-startup_mainloop (gpointer arg)
-{
-	GMainLoop *loop = g_main_loop_new (_ebook_context, FALSE);
-	g_main_loop_run (loop);
-	return NULL;
-}
-
-/* one-time start up for libebook */
-static void
-e_book_activate(void)
-{
-	static GStaticMutex e_book_lock = G_STATIC_MUTEX_INIT;
-	static gboolean activated = FALSE;
-
-	g_static_mutex_lock (&e_book_lock);
-	if (!activated) {
-		GThread *ebook_mainloop_thread;
-		activated = TRUE;
-
-		_ebook_context = g_main_context_new ();
-
-		if (!bonobo_is_initialized ())
-			bonobo_init (NULL, NULL);
-
-		ebook_mainloop_thread = g_thread_create(startup_mainloop, NULL, FALSE, NULL);
-	}
-	g_static_mutex_unlock (&e_book_lock);
-}
-
-
 /**
  * e_book_new:
  * @source: An #ESource pointer
@@ -3831,20 +2035,51 @@ e_book_activate(void)
 EBook*
 e_book_new (ESource *source, GError **error)
 {
+	GError *err = NULL;
 	EBook *book;
+	char *path;
 
-	e_return_error_if_fail (source && E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG, NULL);
+	e_return_error_if_fail (E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG);
 
-	e_book_activate ();
+	if (!e_book_activate (&err)) {
+		g_warning (G_STRLOC ": cannot activate book: %s\n", err->message);
+		g_propagate_error (error, err);
+		return NULL;
+	}
 
 	book = g_object_new (E_TYPE_BOOK, NULL);
 
 	book->priv->source = g_object_ref (source);
+	book->priv->uri = e_source_get_uri (source);
+
+	if (!org_gnome_evolution_dataserver_addressbook_BookFactory_get_book (factory_proxy, book->priv->uri, &path, &err)) {
+		g_warning (G_STRLOC ": cannot get book from factory: %s", err ? err->message : "[no error]");
+		g_propagate_error (error, err);
+		g_object_unref (book);
+		return NULL;
+	}
 
-	if (!fetch_corba_book (book, source, error)) {
+	book->priv->proxy = dbus_g_proxy_new_for_name_owner (connection,
+							     E_DATA_BOOK_FACTORY_SERVICE_NAME, path,
+							     "org.gnome.evolution.dataserver.addressbook.Book",
+							     &err);
+	if (!book->priv->proxy) {
+		g_warning (G_STRLOC ": cannot get proxy for book %s: %s", path, err->message);
+		g_propagate_error (error, err);
+		g_free (path);
 		g_object_unref (book);
 		return NULL;
 	}
+	g_free (path);
+
+	g_object_weak_ref (G_OBJECT (book->priv->proxy), proxy_destroyed, book);
+
+	dbus_g_proxy_add_signal (book->priv->proxy, "writable", G_TYPE_BOOLEAN, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (book->priv->proxy, "writable", G_CALLBACK (writable_cb), book, NULL);
+	dbus_g_proxy_add_signal (book->priv->proxy, "connection", G_TYPE_BOOLEAN, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (book->priv->proxy, "connection", G_CALLBACK (connection_cb), book, NULL);
+	dbus_g_proxy_add_signal (book->priv->proxy, "auth_required", G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (book->priv->proxy, "auth_required", G_CALLBACK (auth_required_cb), book, NULL);
 
 	return book;
 }
@@ -3862,21 +2097,16 @@ e_book_new (ESource *source, GError **error)
 EBook*
 e_book_new_from_uri (const gchar *uri, GError **error)
 {
-	ESourceGroup *group;
 	ESource *source;
 	EBook *book;
 
-	e_return_error_if_fail (uri, E_BOOK_ERROR_INVALID_ARG, NULL);
+	e_return_error_if_fail (uri, E_BOOK_ERROR_INVALID_ARG);
 
-	group = e_source_group_new ("", uri);
-	source = e_source_new ("", "");
-	e_source_set_group (source, group);
-	e_source_set_relative_uri (source, NULL);
+	source = e_source_new_with_absolute_uri ("", uri);
 
 	book = e_book_new (source, error);
 
 	g_object_unref (source);
-	g_object_unref (group);
 
 	return book;
 }
@@ -4007,168 +2237,98 @@ e_book_new_default_addressbook   (GError **error)
 	return book;
 }
 
-static void
-kill_remaining_ops (gpointer key, gpointer value, gpointer user_data)
-{
-	EBookOp *op = value;
-	EBook *book = user_data;
-
-	if (!op)
-		return;
-
-	find_key_value (key, value, NULL);
-	e_book_clear_op (book, op);
-}
-
-static void
-e_book_init (EBook *book)
-{
-	book->priv                = g_new0 (EBookPrivate, 1);
-	book->priv->load_state    = E_BOOK_SOURCE_NOT_LOADED;
-	book->priv->uri           = NULL;
-	book->priv->source        = NULL;
-	book->priv->mutex         = g_mutex_new ();
-	book->priv->id_to_op      = g_hash_table_new (g_int_hash, g_int_equal);
-	book->priv->current_op_id = 1;
-}
-
-static void
-e_book_dispose (GObject *object)
+/**
+ * If the specified GError is a remote error, then create a new error
+ * representing the remote error.  If the error is anything else, then leave it
+ * alone.
+ */
+static gboolean
+unwrap_gerror (GError *error, GError **client_error)
 {
-	EBook             *book = E_BOOK (object);
-
-	if (book->priv) {
-		if (book->priv->comp_listener) {
-			g_signal_handler_disconnect (book->priv->comp_listener, book->priv->died_signal);
-			g_object_unref (book->priv->comp_listener);
-			book->priv->comp_listener = NULL;
-		}
-
-		if (book->priv->load_state == E_BOOK_SOURCE_LOADED)
-			e_book_unload_uri (book, NULL);
-
-		if (book->priv->corba_book) {
-			CORBA_Environment  ev;
+	if (error == NULL)
+		return TRUE;
 
-			CORBA_exception_init (&ev);
-			bonobo_object_release_unref  (book->priv->corba_book, &ev);
-			if (ev._major != CORBA_NO_EXCEPTION)
-				g_warning ("%s: Exception releasing remote book interface!\n", G_STRFUNC);
-			CORBA_exception_free (&ev);
+	if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
+		GError *new;
+		gint code;
+		if (client_error) {
+			code = get_status_from_error (error);
+			new = g_error_new_literal (E_BOOK_ERROR, code, error->message);
+			*client_error = new;
 		}
+		g_error_free (error);
+	} else {
+		if (client_error)
+			*client_error = error;
+	}
+	return FALSE;
+}
 
-		if (book->priv->listener) {
-			e_book_listener_stop (book->priv->listener);
-
-			/* GLib bug compatibility */
-			if (g_signal_handler_is_connected (book->priv->listener, book->priv->listener_signal))
-				g_signal_handler_disconnect (book->priv->listener, book->priv->listener_signal);
-			bonobo_object_unref (book->priv->listener);
-			book->priv->listener = NULL;
+/**
+ * If the GError is a remote error, extract the EBookStatus embedded inside.
+ * Otherwise return CORBA_EXCEPTION (I know this is DBus...).
+ */
+static EBookStatus
+get_status_from_error (GError *error)
+{
+	if G_LIKELY (error == NULL)
+			    return E_BOOK_ERROR_OK;
+	if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
+		const char *name;
+		name = dbus_g_error_get_name (error);
+		if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.contactnotfound") == 0) {
+			return E_BOOK_ERROR_CONTACT_NOT_FOUND;
+		} else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.invalidquery") == 0) {
+			return E_BOOK_ERROR_INVALID_ARG;
+		} else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.cancelled") == 0) {
+			return E_BOOK_ERROR_CANCELLED;
+		} else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.permissiondenied") == 0) {
+			return E_BOOK_ERROR_PERMISSION_DENIED;
+		} else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.nospace") == 0) {
+			return E_BOOK_ERROR_NO_SPACE;
+		} else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.repositoryoffline") == 0) {
+			return E_BOOK_ERROR_REPOSITORY_OFFLINE;
+		} else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.othererror") == 0) {
+			return E_BOOK_ERROR_OTHER_ERROR;
+		} else {
+			g_warning (G_STRLOC ": unmatched error name %s", name);
+			return E_BOOK_ERROR_OTHER_ERROR;
 		}
-
-		g_free (book->priv->cap);
-
-		g_free (book->priv->uri);
-
-		if (book->priv->source)
-			g_object_unref (book->priv->source);
-
-		g_mutex_lock (book->priv->mutex);
-		g_hash_table_foreach (book->priv->id_to_op, kill_remaining_ops, book);
-		g_hash_table_destroy (book->priv->id_to_op);
-		g_mutex_unlock (book->priv->mutex);
-
-		g_mutex_free (book->priv->mutex);
-
-		if (book->priv->connection_idle_id)
-			g_source_remove (book->priv->connection_idle_id);
-
-		if (book->priv->auth_idle_id)
-			g_source_remove (book->priv->auth_idle_id);
-
-		if (book->priv->writable_idle_id)
-			g_source_remove (book->priv->writable_idle_id);
-
-		g_free (book->priv);
-		book->priv = NULL;
+	} else {
+		/* In this case the error was caused by DBus. Dump the message to the
+		   console as otherwise we have no idea what the problem is. */
+		g_warning ("DBus error: %s", error->message);
+		return E_BOOK_ERROR_CORBA_EXCEPTION;
 	}
-
-	if (G_OBJECT_CLASS (parent_class)->dispose)
-		G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
-static void
-e_book_class_init (EBookClass *klass)
+/**
+ * Turn a GList of strings into an array of strings.
+ */
+static char **
+flatten_stringlist (GList *list)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
-	e_book_signals [WRITABLE_STATUS] =
-		g_signal_new ("writable_status",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookClass, writable_status),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__BOOLEAN,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_BOOLEAN);
-
-	e_book_signals [CONNECTION_STATUS] =
-		g_signal_new ("connection_status",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookClass, connection_status),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__BOOLEAN,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_BOOLEAN);
-
-	e_book_signals [AUTH_REQUIRED] =
-		g_signal_new ("auth_required",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookClass, auth_required),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
-
-	e_book_signals [BACKEND_DIED] =
-		g_signal_new ("backend_died",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EBookClass, backend_died),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
-
-	object_class->dispose = e_book_dispose;
+	char **array = g_new0 (char *, g_list_length (list) + 1);
+	GList *l = list;
+	int i = 0;
+	while (l != NULL) {
+		array[i++] = l->data;
+		l = l->next;
+	}
+	return array;
 }
 
 /**
- * e_book_get_type:
+ * Turn an array of strings into a GList.
  */
-GType
-e_book_get_type (void)
+static GList *
+array_to_stringlist (char **list)
 {
-	static GType type = 0;
-
-	if (! type) {
-		GTypeInfo info = {
-			sizeof (EBookClass),
-			NULL, /* base_class_init */
-			NULL, /* base_class_finalize */
-			(GClassInitFunc)  e_book_class_init,
-			NULL, /* class_finalize */
-			NULL, /* class_data */
-			sizeof (EBook),
-			0,    /* n_preallocs */
-			(GInstanceInitFunc) e_book_init
-		};
-
-		type = g_type_register_static (G_TYPE_OBJECT, "EBook", &info, 0);
+	GList *l = NULL;
+	char **i = list;
+	while (*i != NULL) {
+		l = g_list_prepend (l, (*i++));
 	}
-
-	return type;
+	g_free (list);
+	return g_list_reverse(l);
 }
diff --git a/addressbook/libebook/e-error.h b/addressbook/libebook/e-error.h
new file mode 100644
index 0000000..5d137f0
--- /dev/null
+++ b/addressbook/libebook/e-error.h
@@ -0,0 +1,40 @@
+#define e_return_error_if_fail(expr,error_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__,						\
+		__PRETTY_FUNCTION__,					\
+		#expr);							\
+	 g_set_error (error, E_BOOK_ERROR, (error_code),                \
+		"file %s: line %d (%s): assertion `%s' failed",		\
+		__FILE__,						\
+		__LINE__,						\
+		__PRETTY_FUNCTION__,					\
+		#expr);							\
+	 return FALSE;							\
+       };				}G_STMT_END
+
+
+#define e_return_async_error_if_fail(expr, error) 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__, __PRETTY_FUNCTION__, #expr);    \
+      cb (book, error, closure);                           \
+      return 0;                                                  \
+    }                                                            \
+  } G_STMT_END                                                   \
+
+#define e_return_async_error_val_if_fail(expr, error) 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__, __PRETTY_FUNCTION__, #expr);    \
+      cb (book, error, NULL, closure);                           \
+      return 0;                                                  \
+    }                                                            \
+  } G_STMT_END                                                   \
+
diff --git a/addressbook/libebook/libebook.pc.in b/addressbook/libebook/libebook.pc.in
index 49a497a..3d098d5 100644
--- a/addressbook/libebook/libebook.pc.in
+++ b/addressbook/libebook/libebook.pc.in
@@ -5,14 +5,11 @@ includedir= includedir@
 datarootdir= datarootdir@
 datadir= datadir@
 
-idldir= idldir@
-IDL_INCLUDES=-I${idldir} @IDL_INCLUDES@
-
 privincludedir= privincludedir@
 
 Name: libebook
 Description: Client library for evolution address books
 Version: @VERSION@
-Requires: libbonobo-2.0 >= @LIBBONOBO_REQUIRED@ libedataserver-1.2
+Requires: libedataserver-1.2 dbus-glib-1
 Libs: -L${libdir} -lebook-1.2
 Cflags: -I${privincludedir}



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