[evolution-data-server] Bug #732948 - Add backend-per-process support



commit f3f1e94faf38fa7af9ed3072461f4c5e5c6c4b30
Author: Fabiano Fidêncio <fidencio redhat com>
Date:   Mon May 26 01:19:32 2014 +0200

    Bug #732948 - Add backend-per-process support
    
    With this we can have all backends running on theirs own processes, in
    this way, if a backend crashes we don't have the whole factory crashing
    together. Also, each instance of the EBackendFactory can decide if they
    want to have all instances of the same backend (like calendar, memo list,
    and task list) running in only one process (useful for evolution-ews and
    evolution-mapi where we can share the connections between calendar, memo
    list and task list) or have each extension running on its own process.
    Apart from that, a configure option was added and, in case the user wants
    to keep the old behavior, it can be disabled by passing
    "--disable-backend-per-process" to the configure.
    
    As a side effect of these changes, we are enforcing that the hash-key
    used to keep track of the backend-factories will be built internally and
    that *always* will follow the "backend-name:extension-name" structure,
    even for ECollectionBackends.

 .../backends/file/e-book-backend-file-factory.c    |   12 +-
 .../google/e-book-backend-google-factory.c         |   11 +
 .../backends/ldap/e-book-backend-ldap-factory.c    |   12 +-
 .../webdav/e-book-backend-webdav-factory.c         |   12 +-
 addressbook/libebook/e-book-client-cursor.c        |    7 +-
 addressbook/libebook/e-book-client-view.c          |   19 +-
 addressbook/libebook/e-book-client.c               |   13 +-
 addressbook/libedata-book/Makefile.am              |   44 +
 addressbook/libedata-book/e-data-book-factory.c    |  350 +------
 .../libedata-book/e-subprocess-book-factory.c      |  422 +++++++
 .../libedata-book/e-subprocess-book-factory.h      |   68 ++
 .../evolution-addressbook-factory-subprocess.c     |  256 +++++
 addressbook/libedata-book/libedata-book.h          |    1 +
 .../backends/caldav/e-cal-backend-caldav-factory.c |   23 +
 .../contacts/e-cal-backend-contacts-factory.c      |   12 +
 .../backends/file/e-cal-backend-file-factory.c     |   23 +
 .../backends/gtasks/e-cal-backend-gtasks-factory.c |   11 +
 .../backends/http/e-cal-backend-http-factory.c     |   23 +
 .../weather/e-cal-backend-weather-factory.c        |   11 +
 calendar/libecal/e-cal-client-view.c               |   19 +-
 calendar/libecal/e-cal-client.c                    |   17 +-
 calendar/libedata-cal/Makefile.am                  |   42 +
 calendar/libedata-cal/e-data-cal-factory.c         |  146 ++--
 calendar/libedata-cal/e-subprocess-cal-factory.c   |  147 +++
 calendar/libedata-cal/e-subprocess-cal-factory.h   |   68 ++
 .../evolution-calendar-factory-subprocess.c        |  253 ++++
 calendar/libedata-cal/libedata-cal.h               |    1 +
 ....gnome.evolution.dataserver.Calendar.service.in |    3 -
 camel/providers/imapx/camel-imapx-server.c         |   28 -
 configure.ac                                       |   35 +-
 docs/reference/eds/eds-sections.txt                |   33 +-
 libebackend/Makefile.am                            |    2 +
 libebackend/e-backend-factory.c                    |   49 +
 libebackend/e-backend-factory.h                    |   10 +-
 libebackend/e-collection-backend-factory.c         |   16 +-
 libebackend/e-data-factory.c                       | 1210 ++++++++++++--------
 libebackend/e-data-factory.h                       |   43 +-
 libebackend/e-module.c                             |   39 +-
 libebackend/e-module.h                             |    1 +
 libebackend/e-source-registry-server.c             |   26 +-
 libebackend/e-subprocess-factory.c                 |  497 ++++++++
 libebackend/e-subprocess-factory.h                 |  121 ++
 libebackend/libebackend.h                          |    1 +
 libedataserver/e-client.c                          |   46 +
 libedataserver/e-client.h                          |    4 +
 .../module-gnome-online-accounts.c                 |    2 +-
 .../module-ubuntu-online-accounts.c                |    2 +-
 po/POTFILES.in                                     |    1 +
 private/Makefile.am                                |   18 +
 ...ome.evolution.dataserver.AddressBookFactory.xml |    1 +
 ....gnome.evolution.dataserver.CalendarFactory.xml |    3 +
 ...ome.evolution.dataserver.Subprocess.Backend.xml |   29 +
 52 files changed, 3250 insertions(+), 993 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file-factory.c 
b/addressbook/backends/file/e-book-backend-file-factory.c
index 2181560..3c79641 100644
--- a/addressbook/backends/file/e-book-backend-file-factory.c
+++ b/addressbook/backends/file/e-book-backend-file-factory.c
@@ -28,6 +28,8 @@
 typedef EBookBackendFactory EBookBackendFileFactory;
 typedef EBookBackendFactoryClass EBookBackendFileFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -43,6 +45,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_book_backend_file_factory_class_init (EBookBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->backend_type = E_TYPE_BOOK_BACKEND_FILE;
 }
@@ -60,11 +68,13 @@ e_book_backend_file_factory_init (EBookBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_book_backend_file_factory_register_type (type_module);
 }
 
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
-
diff --git a/addressbook/backends/google/e-book-backend-google-factory.c 
b/addressbook/backends/google/e-book-backend-google-factory.c
index 9653a95..4da22b4 100644
--- a/addressbook/backends/google/e-book-backend-google-factory.c
+++ b/addressbook/backends/google/e-book-backend-google-factory.c
@@ -26,6 +26,8 @@
 typedef EBookBackendFactory EBookBackendGoogleFactory;
 typedef EBookBackendFactoryClass EBookBackendGoogleFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -41,6 +43,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_book_backend_google_factory_class_init (EBookBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->backend_type = E_TYPE_BOOK_BACKEND_GOOGLE;
 }
@@ -58,10 +66,13 @@ e_book_backend_google_factory_init (EBookBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_book_backend_google_factory_register_type (type_module);
 }
 
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
diff --git a/addressbook/backends/ldap/e-book-backend-ldap-factory.c 
b/addressbook/backends/ldap/e-book-backend-ldap-factory.c
index 44e6d50..758d88e 100644
--- a/addressbook/backends/ldap/e-book-backend-ldap-factory.c
+++ b/addressbook/backends/ldap/e-book-backend-ldap-factory.c
@@ -31,6 +31,8 @@
 typedef EBookBackendFactory EBookBackendLDAPFactory;
 typedef EBookBackendFactoryClass EBookBackendLDAPFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -46,6 +48,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_book_backend_ldap_factory_class_init (EBookBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->backend_type = E_TYPE_BOOK_BACKEND_LDAP;
 }
@@ -63,6 +71,8 @@ e_book_backend_ldap_factory_init (EBookBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_source_ldap_type_register (type_module);
        e_book_backend_ldap_factory_register_type (type_module);
 }
@@ -70,5 +80,5 @@ e_module_load (GTypeModule *type_module)
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
-
diff --git a/addressbook/backends/webdav/e-book-backend-webdav-factory.c 
b/addressbook/backends/webdav/e-book-backend-webdav-factory.c
index 0e27eaf..fca1155 100644
--- a/addressbook/backends/webdav/e-book-backend-webdav-factory.c
+++ b/addressbook/backends/webdav/e-book-backend-webdav-factory.c
@@ -26,6 +26,8 @@
 typedef EBookBackendFactory EBookBackendWebdavFactory;
 typedef EBookBackendFactoryClass EBookBackendWebdavFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -41,6 +43,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_book_backend_webdav_factory_class_init (EBookBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->backend_type = E_TYPE_BOOK_BACKEND_WEBDAV;
 }
@@ -58,11 +66,13 @@ e_book_backend_webdav_factory_init (EBookBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_book_backend_webdav_factory_register_type (type_module);
 }
 
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
-
diff --git a/addressbook/libebook/e-book-client-cursor.c b/addressbook/libebook/e-book-client-cursor.c
index 1a6c6a6..30a1f2a 100644
--- a/addressbook/libebook/e-book-client-cursor.c
+++ b/addressbook/libebook/e-book-client-cursor.c
@@ -1103,18 +1103,23 @@ book_client_cursor_initable_init (GInitable *initable,
        EBookClientCursor        *cursor = E_BOOK_CLIENT_CURSOR (initable);
        EBookClientCursorPrivate *priv = cursor->priv;
        EDBusAddressBookCursor   *proxy;
+       gchar                    *bus_name;
 
        /* We only need a proxy for regular access, no need in DRA mode */
        if (priv->direct_cursor)
                return TRUE;
 
+       bus_name = e_client_dup_bus_name (E_CLIENT (priv->client));
+
        proxy = e_dbus_address_book_cursor_proxy_new_sync (
                priv->connection,
                G_DBUS_PROXY_FLAGS_NONE,
-               ADDRESS_BOOK_DBUS_SERVICE_NAME,
+               bus_name,
                priv->object_path,
                cancellable, error);
 
+       g_free (bus_name);
+
        if (!proxy)
                return FALSE;
 
diff --git a/addressbook/libebook/e-book-client-view.c b/addressbook/libebook/e-book-client-view.c
index 7137693..a6351d6 100644
--- a/addressbook/libebook/e-book-client-view.c
+++ b/addressbook/libebook/e-book-client-view.c
@@ -876,19 +876,36 @@ book_client_view_initable_init (GInitable *initable,
                                 GCancellable *cancellable,
                                 GError **error)
 {
+       EBookClient *book_client;
        EBookClientViewPrivate *priv;
        EGdbusBookView *gdbus_bookview;
        gulong handler_id;
+       gchar *bus_name;
 
        priv = E_BOOK_CLIENT_VIEW_GET_PRIVATE (initable);
 
+       book_client = g_weak_ref_get (&priv->client);
+       if (book_client == NULL) {
+               g_set_error (
+                       error, E_CLIENT_ERROR,
+                       E_CLIENT_ERROR_OTHER_ERROR,
+                       _("Client disappeared"));
+
+               return FALSE;
+       }
+
+       bus_name = e_client_dup_bus_name (E_CLIENT (book_client));
+       g_object_unref (book_client);
+
        gdbus_bookview = e_gdbus_book_view_proxy_new_sync (
                priv->connection,
                G_DBUS_PROXY_FLAGS_NONE,
-               ADDRESS_BOOK_DBUS_SERVICE_NAME,
+               bus_name,
                priv->object_path,
                cancellable, error);
 
+       g_free (bus_name);
+
        if (gdbus_bookview == NULL)
                return FALSE;
 
diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
index a39e262..0cd1d57 100644
--- a/addressbook/libebook/e-book-client.c
+++ b/addressbook/libebook/e-book-client.c
@@ -974,6 +974,7 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
        ESource *source;
        const gchar *uid;
        gchar *object_path = NULL;
+       gchar *bus_name = NULL;
        gulong handler_id;
        GError *local_error = NULL;
 
@@ -1017,14 +1018,14 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
        }
 
        e_dbus_address_book_factory_call_open_address_book_sync (
-               factory_proxy, uid, &object_path, cancellable, &local_error);
+               factory_proxy, uid, &object_path, &bus_name, cancellable, &local_error);
 
        g_object_unref (factory_proxy);
 
        /* Sanity check. */
        g_return_if_fail (
-               ((object_path != NULL) && (local_error == NULL)) ||
-               ((object_path == NULL) && (local_error != NULL)));
+               (((object_path != NULL) || (bus_name != NULL)) && (local_error == NULL)) ||
+               (((object_path == NULL) || (bus_name == NULL)) && (local_error != NULL)));
 
        if (local_error != NULL) {
                g_dbus_error_strip_remote_error (local_error);
@@ -1033,13 +1034,15 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
                return;
        }
 
+       e_client_set_bus_name (client, bus_name);
+
        priv->dbus_proxy = e_dbus_address_book_proxy_new_sync (
                connection,
                G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
-               ADDRESS_BOOK_DBUS_SERVICE_NAME,
-               object_path, cancellable, &local_error);
+               bus_name, object_path, cancellable, &local_error);
 
        g_free (object_path);
+       g_free (bus_name);
 
        /* Sanity check. */
        g_return_if_fail (
diff --git a/addressbook/libedata-book/Makefile.am b/addressbook/libedata-book/Makefile.am
index 75153cd..8e56a52 100644
--- a/addressbook/libedata-book/Makefile.am
+++ b/addressbook/libedata-book/Makefile.am
@@ -12,6 +12,7 @@ libedata_book_1_2_la_CPPFLAGS = \
        -DLIBEDATA_BOOK_COMPILATION \
        -DG_LOG_DOMAIN=\"libedata-book\" \
        -DBACKENDDIR=\"$(ebook_backenddir)\" \
+       -DSUBPROCESS_BOOK_BACKEND_PATH=\"$(libexecdir)/evolution-addressbook-factory-subprocess\" \
        -I$(top_srcdir) \
        -I$(top_srcdir)/addressbook \
        -I$(top_srcdir)/addressbook/libegdbus \
@@ -40,6 +41,7 @@ libedata_book_1_2_la_SOURCES = \
        e-data-book-direct.c \
        e-data-book-factory.c \
        e-data-book-view.c \
+       e-subprocess-book-factory.c \
        ximian-vcard.h \
        $(LIBDB_C_FILES) \
        $(NULL)
@@ -77,6 +79,7 @@ libedata_bookinclude_HEADERS = \
        e-book-backend-cache.h \
        e-book-backend-sqlitedb.h \
        e-book-sqlite.h \
+       e-subprocess-book-factory.h \
        $(LIBDB_H_FILES) \
        $(NULL)
 
@@ -97,6 +100,47 @@ e_book_backend_sqlitedb_test_LDADD = \
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libedata-book-$(API_VERSION).pc
 
+libexec_PROGRAMS = evolution-addressbook-factory-subprocess
+
+evolution_addressbook_factory_subprocess_CPPFLAGS= \
+       $(AM_CPPFLAGS) \
+       -DLOCALEDIR=\"$(localedir)\" \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/private \
+       -I$(top_srcdir)/addressbook \
+       -I$(top_builddir) \
+       -I$(top_builddir)/private \
+       -I$(top_builddir)/addressbook \
+       $(EVOLUTION_ADDRESSBOOK_CFLAGS) \
+       $(LIBSECRET_CFLAGS) \
+       $(FACTORY_GTK_CFLAGS) \
+       $(CAMEL_CFLAGS) \
+       $(SOUP_CFLAGS) \
+       $(GOA_CFLAGS) \
+       $(CODE_COVERAGE_CFLAGS) \
+       $(NULL)
+
+evolution_addressbook_factory_subprocess_SOURCES = \
+       evolution-addressbook-factory-subprocess.c \
+       $(NULL)
+
+evolution_addressbook_factory_subprocess_LDADD = \
+       $(top_builddir)/libebackend/libebackend-1.2.la \
+       $(top_builddir)/libedataserver/libedataserver-1.2.la \
+       libedata-book-1.2.la \
+       $(EVOLUTION_ADDRESSBOOK_LIBS) \
+       $(LIBSECRET_LIBS) \
+       $(FACTORY_GTK_LIBS) \
+       $(CAMEL_LIBS) \
+       $(SOUP_LIBS) \
+       $(GOA_LIBS) \
+       $(NULL)
+
+evolution_addressbook_factory_subprocess_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       $(CODE_COVERAGE_LDFLAGS) \
+       $(NULL)
+
 DISTCLEANFILES = $(pkgconfig_DATA)
 
 EXTRA_DIST = \
diff --git a/addressbook/libedata-book/e-data-book-factory.c b/addressbook/libedata-book/e-data-book-factory.c
index ded2432..6722dcf 100644
--- a/addressbook/libedata-book/e-data-book-factory.c
+++ b/addressbook/libedata-book/e-data-book-factory.c
@@ -42,7 +42,6 @@
 #include "e-book-backend-factory.h"
 #include "e-data-book.h"
 #include "e-data-book-factory.h"
-#include "e-dbus-localed.h"
 
 #define d(x)
 
@@ -52,16 +51,8 @@
 
 struct _EDataBookFactoryPrivate {
        EDBusAddressBookFactory *dbus_factory;
-
-       /* Watching "org.freedesktop.locale1" for locale changes */
-       guint localed_watch_id;
-       EDBusLocale1 *localed_proxy;
-       GCancellable *localed_cancel;
-       gchar *locale;
 };
 
-static GInitableIface *initable_parent_interface;
-
 /* Forward Declarations */
 static void    e_data_book_factory_initable_init
                                                (GInitableIface *iface);
@@ -84,82 +75,27 @@ data_book_factory_get_dbus_interface_skeleton (EDBusServer *server)
        return G_DBUS_INTERFACE_SKELETON (factory->priv->dbus_factory);
 }
 
-/* This is totally backwards, for some insane reason we holding
- * references to the EBookBackends and then fetching the EDataBook
- * via e_book_backend_ref_data_book(), the whole scheme should
- * be reversed and this function probably removed.
- */
-static GList *
-data_book_factory_list_books (EDataBookFactory *factory)
+static const gchar *
+data_book_get_factory_name (EBackendFactory *backend_factory)
 {
-       GList *books = NULL;
-       GSList *backends, *l;
-
-       backends = e_data_factory_list_backends (E_DATA_FACTORY (factory));
-
-       for (l = backends; l != NULL; l = g_slist_next (l)) {
-               EBookBackend *backend = l->data;
-               EDataBook *book = e_book_backend_ref_data_book (backend);
+       EBookBackendFactoryClass *class;
 
-               if (g_list_find (books, book) == NULL)
-                       books = g_list_prepend (books, book);
-               else
-                       g_object_unref (book);
-       }
+       class = E_BOOK_BACKEND_FACTORY_GET_CLASS (E_BOOK_BACKEND_FACTORY (backend_factory));
 
-       g_slist_free_full (backends, g_object_unref);
-
-       return books;
+       return class->factory_name;
 }
 
-static gchar *
-data_book_factory_open (EDataFactory *data_factory,
-                       EBackend *backend,
-                       GDBusConnection *connection,
-                       GError **error)
+static void
+data_book_complete_open (EDataFactory *data_factory,
+                        GDBusMethodInvocation *invocation,
+                        const gchar *object_path,
+                        const gchar *bus_name,
+                        const gchar *extension_name)
 {
-       EDataBookFactory *factory = E_DATA_BOOK_FACTORY (data_factory);
-       EDataBook *data_book;
-       gchar *object_path;
-
-       /* If the backend already has an EDataBook installed, return its
-        * object path.  Otherwise we need to install a new EDataBook. */
-
-       data_book = e_book_backend_ref_data_book (E_BOOK_BACKEND (backend));
-
-       if (data_book != NULL) {
-               object_path = g_strdup (
-                       e_data_book_get_object_path (data_book));
-       } else {
-               object_path = e_data_factory_construct_path (data_factory);
-
-               /* The EDataBook will attach itself to EBookBackend,
-                * so no need to call e_book_backend_set_data_book(). */
-               data_book = e_data_book_new (
-                       E_BOOK_BACKEND (backend),
-                       connection, object_path, error);
-
-               if (data_book != NULL) {
-                       e_data_factory_set_backend_callbacks (
-                               data_factory, backend);
-
-                       /* Don't set the locale on a new book if we have not
-                        * yet received a notification of a locale change
-                        */
-                       if (factory->priv->locale)
-                               e_data_book_set_locale (
-                                       data_book,
-                                       factory->priv->locale,
-                                       NULL, NULL);
-               } else {
-                       g_free (object_path);
-                       object_path = NULL;
-               }
-       }
-
-       g_clear_object (&data_book);
-
-       return object_path;
+       EDataBookFactory *data_book_factory = E_DATA_BOOK_FACTORY (data_factory);
+
+       e_dbus_address_book_factory_complete_open_address_book (
+               data_book_factory->priv->dbus_factory, invocation, object_path, bus_name);
 }
 
 static gboolean
@@ -168,26 +104,10 @@ data_book_factory_handle_open_address_book_cb (EDBusAddressBookFactory *iface,
                                                const gchar *uid,
                                                EDataBookFactory *factory)
 {
-       GDBusConnection *connection;
-       const gchar *sender;
-       gchar *object_path;
-       GError *error = NULL;
-
-       connection = g_dbus_method_invocation_get_connection (invocation);
-       sender = g_dbus_method_invocation_get_sender (invocation);
-
-       object_path = e_data_factory_open_backend (
-               E_DATA_FACTORY (factory), connection, sender,
-               uid, E_SOURCE_EXTENSION_ADDRESS_BOOK, &error);
-
-       if (object_path != NULL) {
-               e_dbus_address_book_factory_complete_open_address_book (
-                       iface, invocation, object_path);
-               g_free (object_path);
-       } else {
-               g_return_val_if_fail (error != NULL, FALSE);
-               g_dbus_method_invocation_take_error (invocation, error);
-       }
+       EDataFactory *data_factory = E_DATA_FACTORY (factory);
+
+       e_data_factory_spawn_subprocess_backend (
+               data_factory, invocation, uid, E_SOURCE_EXTENSION_ADDRESS_BOOK, SUBPROCESS_BOOK_BACKEND_PATH);
 
        return TRUE;
 }
@@ -203,233 +123,11 @@ data_book_factory_dispose (GObject *object)
 
        g_clear_object (&priv->dbus_factory);
 
-       if (priv->localed_cancel)
-               g_cancellable_cancel (priv->localed_cancel);
-
-       g_clear_object (&priv->localed_cancel);
-       g_clear_object (&priv->localed_proxy);
-
-       if (priv->localed_watch_id > 0)
-               g_bus_unwatch_name (priv->localed_watch_id);
-
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose (object);
 }
 
 static void
-data_book_factory_finalize (GObject *object)
-{
-       EDataBookFactory *factory;
-
-       factory = E_DATA_BOOK_FACTORY (object);
-
-       g_free (factory->priv->locale);
-
-       /* Chain up to parent's finalize() method. */
-       G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize (object);
-}
-
-static gchar *
-data_book_factory_interpret_locale_value (const gchar *value)
-{
-       gchar *interpreted_value = NULL;
-       gchar **split;
-
-       split = g_strsplit (value, "=", 2);
-
-       if (split && split[0] && split[1])
-               interpreted_value = g_strdup (split[1]);
-
-       g_strfreev (split);
-
-       if (!interpreted_value)
-               g_warning ("Failed to interpret locale value: %s", value);
-
-       return interpreted_value;
-}
-
-static gchar *
-data_book_factory_interpret_locale (const gchar * const * locale)
-{
-       gint i;
-       gchar *interpreted_locale = NULL;
-
-       /* Prioritize LC_COLLATE and then LANG values
-        * in the 'locale' specified by localed.
-        *
-        * If localed explicitly specifies no locale, then
-        * default to checking system locale.
-        */
-       if (locale) {
-               for (i = 0; locale[i] != NULL && interpreted_locale == NULL; i++) {
-                       if (strncmp (locale[i], "LC_COLLATE", 10) == 0)
-                               interpreted_locale =
-                                       data_book_factory_interpret_locale_value (locale[i]);
-               }
-
-               for (i = 0; locale[i] != NULL && interpreted_locale == NULL; i++) {
-                       if (strncmp (locale[i], "LANG", 4) == 0)
-                               interpreted_locale =
-                                       data_book_factory_interpret_locale_value (locale[i]);
-               }
-       }
-
-       if (!interpreted_locale) {
-               const gchar *system_locale = setlocale (LC_COLLATE, NULL);
-
-               interpreted_locale = g_strdup (system_locale);
-       }
-
-       return interpreted_locale;
-}
-
-static void
-data_book_factory_set_locale (EDataBookFactory *factory,
-                              const gchar *locale)
-{
-       EDataBookFactoryPrivate *priv = factory->priv;
-       GError *error = NULL;
-       GList *books, *l;
-
-       if (g_strcmp0 (priv->locale, locale) != 0) {
-
-               g_free (priv->locale);
-               priv->locale = g_strdup (locale);
-
-               books = data_book_factory_list_books (factory);
-               for (l = books; l; l = l->next) {
-                       EDataBook *book = l->data;
-
-                       if (!e_data_book_set_locale (book, locale, NULL, &error)) {
-                               g_warning (
-                                       "Failed to set locale on addressbook: %s",
-                                       error->message);
-                               g_clear_error (&error);
-                       }
-               }
-               g_list_free_full (books, g_object_unref);
-       }
-}
-
-static void
-data_book_factory_locale_changed (GObject *object,
-                                  GParamSpec *pspec,
-                                  gpointer user_data)
-{
-       EDBusLocale1 *locale_proxy = E_DBUS_LOCALE1 (object);
-       EDataBookFactory *factory = (EDataBookFactory *) user_data;
-       const gchar * const *locale;
-       gchar *interpreted_locale;
-
-       locale = e_dbus_locale1_get_locale (locale_proxy);
-       interpreted_locale = data_book_factory_interpret_locale (locale);
-
-       data_book_factory_set_locale (factory, interpreted_locale);
-
-       g_free (interpreted_locale);
-}
-
-static void
-data_book_factory_localed_ready (GObject *source_object,
-                                 GAsyncResult *res,
-                                 gpointer user_data)
-{
-       EDataBookFactory *factory = (EDataBookFactory *) user_data;
-       GError *error = NULL;
-
-       factory->priv->localed_proxy = e_dbus_locale1_proxy_new_finish (res, &error);
-
-       if (factory->priv->localed_proxy == NULL) {
-               g_warning ("Error fetching localed proxy: %s", error->message);
-               g_error_free (error);
-       }
-
-       if (factory->priv->localed_cancel) {
-               g_object_unref (factory->priv->localed_cancel);
-               factory->priv->localed_cancel = NULL;
-       }
-
-       if (factory->priv->localed_proxy) {
-               g_signal_connect (
-                       factory->priv->localed_proxy, "notify::locale",
-                       G_CALLBACK (data_book_factory_locale_changed), factory);
-
-               /* Initial refresh of the locale */
-               data_book_factory_locale_changed (G_OBJECT (factory->priv->localed_proxy), NULL, factory);
-       }
-}
-
-static void
-data_book_factory_localed_appeared (GDBusConnection *connection,
-                                    const gchar *name,
-                                    const gchar *name_owner,
-                                    gpointer user_data)
-{
-       EDataBookFactory *factory = (EDataBookFactory *) user_data;
-
-       factory->priv->localed_cancel = g_cancellable_new ();
-
-       e_dbus_locale1_proxy_new (
-               connection,
-               G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
-               "org.freedesktop.locale1",
-               "/org/freedesktop/locale1",
-               factory->priv->localed_cancel,
-               data_book_factory_localed_ready,
-               factory);
-}
-
-static void
-data_book_factory_localed_vanished (GDBusConnection *connection,
-                                    const gchar *name,
-                                    gpointer user_data)
-{
-       EDataBookFactory *factory = (EDataBookFactory *) user_data;
-
-       if (factory->priv->localed_cancel) {
-               g_cancellable_cancel (factory->priv->localed_cancel);
-               g_object_unref (factory->priv->localed_cancel);
-               factory->priv->localed_cancel = NULL;
-       }
-
-       if (factory->priv->localed_proxy) {
-               g_object_unref (factory->priv->localed_proxy);
-               factory->priv->localed_proxy = NULL;
-       }
-}
-
-static gboolean
-data_book_factory_initable_init (GInitable *initable,
-                                 GCancellable *cancellable,
-                                 GError **error)
-{
-       EDataBookFactory *factory;
-       GBusType bus_type = G_BUS_TYPE_SYSTEM;
-
-       factory = E_DATA_BOOK_FACTORY (initable);
-
-       /* When running tests, we pretend to be the "org.freedesktop.locale1" service
-        * on the session bus instead of the real location on the system bus.
-        */
-       if (g_getenv ("EDS_TESTING") != NULL)
-               bus_type = G_BUS_TYPE_SESSION;
-
-       /* Watch system bus for locale change notifications */
-       factory->priv->localed_watch_id =
-               g_bus_watch_name (
-                       bus_type,
-                       "org.freedesktop.locale1",
-                       G_BUS_NAME_WATCHER_FLAGS_NONE,
-                       data_book_factory_localed_appeared,
-                       data_book_factory_localed_vanished,
-                       initable,
-                       NULL);
-
-       /* Chain up to parent interface's init() method. */
-       return initable_parent_interface->init (initable, cancellable, error);
-}
-
-static void
 e_data_book_factory_class_init (EDataBookFactoryClass *class)
 {
        GObjectClass *object_class;
@@ -447,7 +145,6 @@ e_data_book_factory_class_init (EDataBookFactoryClass *class)
 
        object_class = G_OBJECT_CLASS (class);
        object_class->dispose = data_book_factory_dispose;
-       object_class->finalize = data_book_factory_finalize;
 
        dbus_server_class = E_DBUS_SERVER_CLASS (class);
        dbus_server_class->bus_name = ADDRESS_BOOK_DBUS_SERVICE_NAME;
@@ -456,17 +153,16 @@ e_data_book_factory_class_init (EDataBookFactoryClass *class)
        data_factory_class = E_DATA_FACTORY_CLASS (class);
        data_factory_class->backend_factory_type = E_TYPE_BOOK_BACKEND_FACTORY;
        data_factory_class->factory_object_path = "/org/gnome/evolution/dataserver/AddressBookFactory";
-       data_factory_class->data_object_path_prefix = "/org/gnome/evolution/dataserver/Addressbook";
+       data_factory_class->subprocess_object_path_prefix = 
"/org/gnome/evolution/dataserver/Subprocess/Backend/AddressBook";
+       data_factory_class->subprocess_bus_name_prefix = 
"org.gnome.evolution.dataserver.Subprocess.Backend.AddressBook";
        data_factory_class->get_dbus_interface_skeleton = data_book_factory_get_dbus_interface_skeleton;
-       data_factory_class->data_open = data_book_factory_open;
+       data_factory_class->get_factory_name = data_book_get_factory_name;
+       data_factory_class->complete_open = data_book_complete_open;
 }
 
 static void
 e_data_book_factory_initable_init (GInitableIface *iface)
 {
-       initable_parent_interface = g_type_interface_peek_parent (iface);
-
-       iface->init = data_book_factory_initable_init;
 }
 
 static void
diff --git a/addressbook/libedata-book/e-subprocess-book-factory.c 
b/addressbook/libedata-book/e-subprocess-book-factory.c
new file mode 100644
index 0000000..a1868bb
--- /dev/null
+++ b/addressbook/libedata-book/e-subprocess-book-factory.c
@@ -0,0 +1,422 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Fabiano Fidêncio <fidencio redhat com>
+ */
+
+/**
+ * SECTION: e-subprocess-book-factory
+ * @include: libedata-book/libedata-book.h
+ * @short_description: Responsible for #EBackend objects
+ *
+ * This class handles and creates #EBackend objects from inside
+ * their own subprocesses and also serves as the layer that does
+ * the communication between #EDataBookFactory and #EBackend
+ **/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib/gi18n-lib.h>
+
+#include "e-book-backend.h"
+#include "e-book-backend-factory.h"
+#include "e-data-book.h"
+#include "e-dbus-localed.h"
+#include "e-subprocess-book-factory.h"
+
+#include <e-dbus-subprocess-backend.h>
+
+#define E_SUBPROCESS_BOOK_FACTORY_GET_PRIVATE(obj) \
+       (G_TYPE_INSTANCE_GET_PRIVATE \
+       ((obj), E_TYPE_SUBPROCESS_BOOK_FACTORY, ESubprocessBookFactoryPrivate))
+
+struct _ESubprocessBookFactoryPrivate {
+       /* Watching "org.freedesktop.locale1" for locale changes */
+       guint localed_watch_id;
+       guint subprocess_watch_id;
+       EDBusLocale1 *localed_proxy;
+       GCancellable *localed_cancel;
+       gchar *locale;
+};
+
+static GInitableIface *initable_parent_interface;
+
+/* Forward Declarations */
+static void    e_subprocess_book_factory_initable_init
+                                               (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (
+       ESubprocessBookFactory,
+       e_subprocess_book_factory,
+       E_TYPE_SUBPROCESS_FACTORY,
+       G_IMPLEMENT_INTERFACE (
+               G_TYPE_INITABLE,
+               e_subprocess_book_factory_initable_init))
+
+static gchar *
+subprocess_book_factory_open (ESubprocessFactory *subprocess_factory,
+                             EBackend *backend,
+                             GDBusConnection *connection,
+                             gpointer data,
+                             GCancellable *cancellable,
+                             GError **error)
+{
+       ESubprocessBookFactory *subprocess_book_factory = E_SUBPROCESS_BOOK_FACTORY (subprocess_factory);
+       EDataBook *data_book;
+       gchar *object_path;
+
+       /* If the backend already has an EDataBook installed, return its
+        * object path.  Otherwise we need to install a new EDataBook. */
+       data_book = e_book_backend_ref_data_book (E_BOOK_BACKEND (backend));
+
+       if (data_book != NULL) {
+               object_path = g_strdup (e_data_book_get_object_path (data_book));
+       } else {
+               object_path = e_subprocess_factory_construct_path ();
+
+               /* The EDataBook will attach itself to EBookBackend,
+                * so no need to call e_book_backend_set_data_book(). */
+               data_book = e_data_book_new (
+                       E_BOOK_BACKEND (backend),
+                       connection, object_path, error);
+
+               if (data_book != NULL) {
+                       e_subprocess_factory_set_backend_callbacks (
+                               subprocess_factory, backend, data);
+
+                       /* Don't set the locale on a new book if we have not
+                        * yet received a notification of a locale change
+                        */
+                       if (subprocess_book_factory->priv->locale)
+                               e_data_book_set_locale (
+                                       data_book,
+                                       subprocess_book_factory->priv->locale,
+                                       NULL, NULL);
+               } else {
+                       g_free (object_path);
+                       object_path = NULL;
+               }
+       }
+
+       g_clear_object (&data_book);
+
+       return object_path;
+}
+
+static EBackend *
+subprocess_book_factory_ref_backend (ESourceRegistry *registry,
+                                    ESource *source,
+                                    const gchar *backend_factory_type_name)
+{
+       EBookBackend *backend;
+       EBookBackendFactoryClass *backend_factory_class;
+       GType backend_factory_type;
+
+       backend_factory_type = g_type_from_name (backend_factory_type_name);
+       backend_factory_class = g_type_class_ref (backend_factory_type);
+
+       backend = g_object_new (
+               backend_factory_class->backend_type,
+               "registry", registry,
+               "source", source, NULL);
+
+       return E_BACKEND (backend);
+}
+
+static void
+subprocess_book_factory_dispose (GObject *object)
+{
+       ESubprocessBookFactory *subprocess_factory;
+       ESubprocessBookFactoryPrivate *priv;
+
+       subprocess_factory = E_SUBPROCESS_BOOK_FACTORY (object);
+       priv = subprocess_factory->priv;
+
+       if (priv->localed_cancel)
+               g_cancellable_cancel (priv->localed_cancel);
+
+       g_clear_object (&priv->localed_cancel);
+       g_clear_object (&priv->localed_proxy);
+
+       if (priv->localed_watch_id > 0)
+               g_bus_unwatch_name (priv->localed_watch_id);
+
+       if (priv->subprocess_watch_id > 0)
+               g_bus_unwatch_name (priv->subprocess_watch_id);
+
+       /* Chain up to parent's dispose() method. */
+       G_OBJECT_CLASS (e_subprocess_book_factory_parent_class)->dispose (object);
+}
+
+static void
+subprocess_book_factory_finalize (GObject *object)
+{
+       ESubprocessBookFactory *subprocess_factory;
+
+       subprocess_factory = E_SUBPROCESS_BOOK_FACTORY (object);
+
+       g_free (subprocess_factory->priv->locale);
+
+       /* Chain up to parent's finalize() method. */
+       G_OBJECT_CLASS (e_subprocess_book_factory_parent_class)->finalize (object);
+}
+
+static gchar *
+subprocess_book_factory_interpret_locale_value (const gchar *value)
+{
+       gchar *interpreted_value = NULL;
+       gchar **split;
+
+       split = g_strsplit (value, "=", 2);
+
+       if (split && split[0] && split[1])
+               interpreted_value = g_strdup (split[1]);
+
+       g_strfreev (split);
+
+       if (!interpreted_value)
+               g_warning ("Failed to interpret locale value: %s", value);
+
+       return interpreted_value;
+}
+
+static gchar *
+subprocess_book_factory_interpret_locale (const gchar * const * locale)
+{
+       gint i;
+       gchar *interpreted_locale = NULL;
+
+       /* Prioritize LC_COLLATE and then LANG values
+        * in the 'locale' specified by localed.
+        *
+        * If localed explicitly specifies no locale, then
+        * default to checking system locale.
+        */
+       if (locale) {
+               for (i = 0; locale[i] != NULL && interpreted_locale == NULL; i++) {
+                       if (strncmp (locale[i], "LC_COLLATE", 10) == 0)
+                               interpreted_locale =
+                                       subprocess_book_factory_interpret_locale_value (locale[i]);
+               }
+
+               for (i = 0; locale[i] != NULL && interpreted_locale == NULL; i++) {
+                       if (strncmp (locale[i], "LANG", 4) == 0)
+                               interpreted_locale =
+                                       subprocess_book_factory_interpret_locale_value (locale[i]);
+               }
+       }
+
+       if (!interpreted_locale) {
+               const gchar *system_locale = setlocale (LC_COLLATE, NULL);
+
+               interpreted_locale = g_strdup (system_locale);
+       }
+
+       return interpreted_locale;
+}
+
+static void
+subprocess_book_factory_set_locale (ESubprocessBookFactory *subprocess_factory,
+                                   const gchar *locale)
+{
+       ESubprocessBookFactoryPrivate *priv = subprocess_factory->priv;
+       GError *error = NULL;
+
+       if (g_strcmp0 (priv->locale, locale) != 0) {
+               GList *backends, *l;
+
+               g_free (priv->locale);
+               priv->locale = g_strdup (locale);
+
+               backends = e_subprocess_factory_get_backends_list (E_SUBPROCESS_FACTORY (subprocess_factory));
+
+               for (l = backends; l != NULL; l = g_list_next (l)) {
+                       EBackend *backend = l->data;
+                       EDataBook *data_book;
+
+                       data_book = e_book_backend_ref_data_book (E_BOOK_BACKEND (backend));
+
+                       if (!e_data_book_set_locale (data_book, locale, NULL, &error)) {
+                               g_warning (
+                                       "Failed to set locale on addressbook: %s",
+                                       error->message);
+                               g_clear_error (&error);
+                       }
+
+                       g_object_unref (data_book);
+               }
+
+               g_list_free_full (backends, g_object_unref);
+       }
+}
+
+static void
+subprocess_book_factory_locale_changed (GObject *object,
+                                       GParamSpec *pspec,
+                                       gpointer user_data)
+{
+       EDBusLocale1 *locale_proxy = E_DBUS_LOCALE1 (object);
+       ESubprocessBookFactory *factory = (ESubprocessBookFactory *) user_data;
+       const gchar * const *locale;
+       gchar *interpreted_locale;
+
+       locale = e_dbus_locale1_get_locale (locale_proxy);
+       interpreted_locale = subprocess_book_factory_interpret_locale (locale);
+
+       subprocess_book_factory_set_locale (factory, interpreted_locale);
+
+       g_free (interpreted_locale);
+}
+
+static void
+subprocess_book_factory_localed_ready (GObject *source_object,
+                                      GAsyncResult *res,
+                                      gpointer user_data)
+{
+       ESubprocessBookFactory *subprocess_factory = (ESubprocessBookFactory *) user_data;
+       GError *error = NULL;
+
+       subprocess_factory->priv->localed_proxy = e_dbus_locale1_proxy_new_finish (res, &error);
+
+       if (subprocess_factory->priv->localed_proxy == NULL) {
+               g_warning ("Error fetching localed proxy: %s", error->message);
+               g_error_free (error);
+       }
+
+       g_clear_object (&subprocess_factory->priv->localed_cancel);
+
+       if (subprocess_factory->priv->localed_proxy) {
+               g_signal_connect (
+                       subprocess_factory->priv->localed_proxy, "notify::locale",
+                       G_CALLBACK (subprocess_book_factory_locale_changed), subprocess_factory);
+
+               /* Initial refresh of the locale */
+               subprocess_book_factory_locale_changed (
+                       G_OBJECT (subprocess_factory->priv->localed_proxy), NULL, subprocess_factory);
+       }
+}
+
+static void
+subprocess_book_factory_localed_appeared (GDBusConnection *connection,
+                                         const gchar *name,
+                                         const gchar *name_owner,
+                                         gpointer user_data)
+{
+       ESubprocessBookFactory *subprocess_factory = (ESubprocessBookFactory *) user_data;
+
+       subprocess_factory->priv->localed_cancel = g_cancellable_new ();
+
+       e_dbus_locale1_proxy_new (
+               connection,
+               G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+               "org.freedesktop.locale1",
+               "/org/freedesktop/locale1",
+               subprocess_factory->priv->localed_cancel,
+               subprocess_book_factory_localed_ready,
+               subprocess_factory);
+}
+
+static void
+subprocess_book_factory_localed_vanished (GDBusConnection *connection,
+                                         const gchar *name,
+                                         gpointer user_data)
+{
+       ESubprocessBookFactory *subprocess_factory = (ESubprocessBookFactory *) user_data;
+
+       if (subprocess_factory->priv->localed_cancel) {
+               g_cancellable_cancel (subprocess_factory->priv->localed_cancel);
+               g_clear_object (&subprocess_factory->priv->localed_cancel);
+       }
+
+       g_clear_object (&subprocess_factory->priv->localed_proxy);
+}
+
+static void
+e_subprocess_book_factory_class_init (ESubprocessBookFactoryClass *class)
+{
+       GObjectClass *object_class;
+       ESubprocessFactoryClass *subprocess_factory_class;
+
+       g_type_class_add_private (class, sizeof (ESubprocessBookFactoryPrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->dispose = subprocess_book_factory_dispose;
+       object_class->finalize = subprocess_book_factory_finalize;
+
+       subprocess_factory_class = E_SUBPROCESS_FACTORY_CLASS (class);
+       subprocess_factory_class->ref_backend = subprocess_book_factory_ref_backend;
+       subprocess_factory_class->open_data = subprocess_book_factory_open;
+}
+
+static gboolean
+subprocess_book_factory_initable_init (GInitable *initable,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+       ESubprocessBookFactory *subprocess_factory;
+       GBusType bus_type = G_BUS_TYPE_SYSTEM;
+
+       subprocess_factory = E_SUBPROCESS_BOOK_FACTORY (initable);
+
+       /* When running tests, we pretend to be the "org.freedesktop.locale1" service
+        * on the session bus instead of the real location on the system bus.
+        */
+       if (g_getenv ("EDS_TESTING") != NULL)
+               bus_type = G_BUS_TYPE_SESSION;
+
+       /* Watch system bus for locale change notifications */
+       subprocess_factory->priv->localed_watch_id =
+               g_bus_watch_name (
+                       bus_type,
+                       "org.freedesktop.locale1",
+                       G_BUS_NAME_WATCHER_FLAGS_NONE,
+                       subprocess_book_factory_localed_appeared,
+                       subprocess_book_factory_localed_vanished,
+                       initable,
+                       NULL);
+
+       /* Chain up to parent interface's init() method. */
+       return initable_parent_interface->init (initable, cancellable, error);
+}
+
+static void
+e_subprocess_book_factory_initable_init (GInitableIface *iface)
+{
+       initable_parent_interface = g_type_interface_peek_parent (iface);
+
+       iface->init = subprocess_book_factory_initable_init;
+}
+
+static void
+e_subprocess_book_factory_init (ESubprocessBookFactory *subprocess_factory)
+{
+       subprocess_factory->priv = E_SUBPROCESS_BOOK_FACTORY_GET_PRIVATE (subprocess_factory);
+}
+
+ESubprocessBookFactory *
+e_subprocess_book_factory_new (GCancellable *cancellable,
+                              GError **error)
+{
+       return g_initable_new (
+               E_TYPE_SUBPROCESS_BOOK_FACTORY,
+               cancellable, error, NULL);
+}
diff --git a/addressbook/libedata-book/e-subprocess-book-factory.h 
b/addressbook/libedata-book/e-subprocess-book-factory.h
new file mode 100644
index 0000000..b5c1ebc
--- /dev/null
+++ b/addressbook/libedata-book/e-subprocess-book-factory.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__LIBEDATA_BOOK_H_INSIDE__) && !defined (LIBEDATA_BOOK_COMPILATION)
+#error "Only <libedata-book/libedata-book.h> should be included directly."
+#endif
+
+#ifndef E_SUBPROCESS_BOOK_FACTORY_H
+#define E_SUBPROCESS_BOOK_FACTORY_H
+
+#include <libebackend/libebackend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SUBPROCESS_BOOK_FACTORY \
+       (e_subprocess_book_factory_get_type ())
+#define E_SUBPROCESS_BOOK_FACTORY(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_SUBPROCESS_BOOK_FACTORY, ESubprocessBookFactory))
+#define E_SUBPROCESS_BOOK_FACTORY_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_SUBPROCESS_BOOK_FACTORY, ESubprocessBookFactoryClass))
+#define E_IS_SUBPROCESS_BOOK_FACTORY(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_SUBPROCESS_BOOK_FACTORY))
+#define E_IS_SUBPROCESS_BOOK_FACTORY_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_SUBPROCESS_BOOK_FACTORY))
+#define E_SUBPROCESS_BOOK_FACTORY_GET_CLASS(cls) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_SUBPROCESS_BOOK_FACTORY, ESubprocessBookFactoryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESubprocessBookFactory ESubprocessBookFactory;
+typedef struct _ESubprocessBookFactoryClass ESubprocessBookFactoryClass;
+typedef struct _ESubprocessBookFactoryPrivate ESubprocessBookFactoryPrivate;
+
+struct _ESubprocessBookFactory {
+       ESubprocessFactory parent;
+       ESubprocessBookFactoryPrivate *priv;
+};
+
+struct _ESubprocessBookFactoryClass {
+       ESubprocessFactoryClass parent_class;
+};
+
+GType          e_subprocess_book_factory_get_type      (void) G_GNUC_CONST;
+ESubprocessBookFactory *
+               e_subprocess_book_factory_new           (GCancellable *cancellable,
+                                                        GError **error);
+
+G_END_DECLS
+
+#endif /* E_SUBPROCESS_BOOK_FACTORY_H */
diff --git a/addressbook/libedata-book/evolution-addressbook-factory-subprocess.c 
b/addressbook/libedata-book/evolution-addressbook-factory-subprocess.c
new file mode 100644
index 0000000..2f20dcd
--- /dev/null
+++ b/addressbook/libedata-book/evolution-addressbook-factory-subprocess.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <locale.h>
+#include <stdlib.h>
+#include <glib/gi18n.h>
+
+#if defined (ENABLE_MAINTAINER_MODE) && defined (HAVE_GTK)
+#include <gtk/gtk.h>
+#endif
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+#include <conio.h>
+#ifndef PROCESS_DEP_ENABLE
+#define PROCESS_DEP_ENABLE 0x00000001
+#endif
+#ifndef PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
+#define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
+#endif
+#endif
+
+#include <e-dbus-subprocess-backend.h>
+#include <libebackend/libebackend.h>
+#include <libedata-book/libedata-book.h>
+
+typedef struct _SubprocessData SubprocessData;
+
+struct _SubprocessData {
+       GMainLoop *loop;
+       GDBusObjectManagerServer *manager;
+       ESubprocessBookFactory *subprocess_book_factory;
+};
+
+static const gchar *bus_name = NULL;
+static const gchar *path = NULL;
+
+static GOptionEntry entries[] = {
+       { "bus-name", 'b', 0, G_OPTION_ARG_STRING, &bus_name, NULL, NULL },
+       { "own-path", 'p', 0, G_OPTION_ARG_STRING, &path, NULL, NULL },
+       { NULL }
+};
+
+static void
+prepare_shutdown_and_quit (ESubprocessBookFactory *subprocess_book_factory,
+                          GMainLoop *loop)
+{
+       e_subprocess_factory_call_backends_prepare_shutdown (E_SUBPROCESS_FACTORY (subprocess_book_factory));
+
+       g_main_loop_quit (loop);
+}
+
+static gboolean
+subprocess_backend_handle_create_cb (EDBusSubprocessBackend *proxy,
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar *uid,
+                                    const gchar *backend_factory_type_name,
+                                    const gchar *module_filename,
+                                    ESubprocessBookFactory *subprocess_book_factory)
+{
+       gchar *object_path = NULL;
+       GDBusConnection *connection;
+       GError *error = NULL;
+
+       connection = g_dbus_method_invocation_get_connection (invocation);
+
+       object_path = e_subprocess_factory_open_backend (
+               E_SUBPROCESS_FACTORY (subprocess_book_factory),
+               connection,
+               uid,
+               backend_factory_type_name,
+               module_filename,
+               G_DBUS_INTERFACE_SKELETON (proxy),
+               NULL,
+               &error);
+
+       if (object_path != NULL) {
+               e_dbus_subprocess_backend_complete_create (proxy, invocation, object_path);
+               g_free (object_path);
+       } else {
+               g_dbus_method_invocation_take_error (invocation, error);
+       }
+
+       return TRUE;
+}
+
+static gboolean
+subprocess_backend_handle_close_cb (EDBusSubprocessBackend *proxy,
+                                   GDBusMethodInvocation *invocation,
+                                   SubprocessData *sd)
+{
+       prepare_shutdown_and_quit (sd->subprocess_book_factory, sd->loop);
+
+       return TRUE;
+}
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+                const gchar *name,
+                SubprocessData *sd)
+{
+       EDBusSubprocessBackend *proxy;
+       EDBusSubprocessObjectSkeleton *object;
+
+       object = e_dbus_subprocess_object_skeleton_new (path);
+
+       proxy = e_dbus_subprocess_backend_skeleton_new ();
+       e_dbus_subprocess_object_skeleton_set_backend (object, proxy);
+
+       g_signal_connect (
+               proxy, "handle-create",
+               G_CALLBACK (subprocess_backend_handle_create_cb),
+               sd->subprocess_book_factory);
+
+       g_signal_connect (
+               proxy, "handle-close",
+               G_CALLBACK (subprocess_backend_handle_close_cb),
+               sd);
+
+       g_dbus_object_manager_server_export (sd->manager, G_DBUS_OBJECT_SKELETON (object));
+       g_object_unref (proxy);
+       g_object_unref (object);
+
+       g_dbus_object_manager_server_set_connection (sd->manager, connection);
+}
+
+static void
+vanished_cb (GDBusConnection *connection,
+            const gchar *name,
+            SubprocessData *sd)
+{
+       prepare_shutdown_and_quit (sd->subprocess_book_factory, sd->loop);
+}
+
+gint
+main (gint argc,
+      gchar **argv)
+{
+       guint id;
+       guint watched_id;
+       ESubprocessBookFactory *subprocess_book_factory;
+       GMainLoop *loop;
+       GDBusObjectManagerServer *manager;
+       GOptionContext *context;
+       SubprocessData sd;
+       GError *error = NULL;
+
+#ifdef G_OS_WIN32
+       /* Reduce risks */
+       {
+               typedef BOOL (WINAPI *t_SetDllDirectoryA) (LPCSTR lpPathName);
+               t_SetDllDirectoryA p_SetDllDirectoryA;
+
+               p_SetDllDirectoryA = GetProcAddress (
+                       GetModuleHandle ("kernel32.dll"),
+                       "SetDllDirectoryA");
+
+               if (p_SetDllDirectoryA != NULL)
+                       p_SetDllDirectoryA ("");
+       }
+#ifndef _WIN64
+       {
+               typedef BOOL (WINAPI *t_SetProcessDEPPolicy) (DWORD dwFlags);
+               t_SetProcessDEPPolicy p_SetProcessDEPPolicy;
+
+               p_SetProcessDEPPolicy = GetProcAddress (
+                       GetModuleHandle ("kernel32.dll"),
+                       "SetProcessDEPPolicy");
+
+               if (p_SetProcessDEPPolicy != NULL)
+                       p_SetProcessDEPPolicy (
+                               PROCESS_DEP_ENABLE |
+                               PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION);
+       }
+#endif
+#endif
+
+       setlocale (LC_ALL, "");
+       bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+#if defined (ENABLE_MAINTAINER_MODE) && defined (HAVE_GTK)
+       if (g_getenv ("EDS_TESTING") == NULL)
+               /* This is only to load gtk-modules, like
+                * bug-buddy's gnomesegvhandler, if possible */
+               gtk_init_check (&argc, &argv);
+#endif
+
+       context = g_option_context_new (NULL);
+       g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+       g_option_context_parse (context, &argc, &argv, &error);
+       g_option_context_free (context);
+
+       if (error != NULL) {
+               g_printerr ("%s\n", error->message);
+               exit (EXIT_FAILURE);
+       }
+
+       loop = g_main_loop_new (NULL, FALSE);
+
+       manager = g_dbus_object_manager_server_new ("/org/gnome/evolution/dataserver/Subprocess/Backend");
+
+       subprocess_book_factory = e_subprocess_book_factory_new (NULL, NULL);
+
+       sd.loop = loop;
+       sd.manager = manager;
+       sd.subprocess_book_factory = subprocess_book_factory;
+
+       /* Watch the factory name and close the subprocess if the factory dies/crashes */
+       watched_id = g_bus_watch_name (
+               G_BUS_TYPE_SESSION,
+               ADDRESS_BOOK_DBUS_SERVICE_NAME,
+               G_BUS_NAME_WATCHER_FLAGS_NONE,
+               NULL,
+               (GBusNameVanishedCallback) vanished_cb,
+               &sd,
+               NULL);
+
+       id = g_bus_own_name (
+               G_BUS_TYPE_SESSION,
+               bus_name,
+               G_BUS_NAME_OWNER_FLAGS_NONE,
+               (GBusAcquiredCallback) on_bus_acquired,
+               NULL,
+               NULL,
+               &sd,
+               NULL);
+
+       g_main_loop_run (loop);
+       g_bus_unown_name (id);
+       g_main_loop_unref (loop);
+
+       g_clear_object (&subprocess_book_factory);
+       g_clear_object (&manager);
+       g_bus_unwatch_name (watched_id);
+
+       return 0;
+}
diff --git a/addressbook/libedata-book/libedata-book.h b/addressbook/libedata-book/libedata-book.h
index cd98350..ff070ec 100644
--- a/addressbook/libedata-book/libedata-book.h
+++ b/addressbook/libedata-book/libedata-book.h
@@ -36,6 +36,7 @@
 #include <libedata-book/e-data-book-factory.h>
 #include <libedata-book/e-data-book-view.h>
 #include <libedata-book/e-data-book.h>
+#include <libedata-book/e-subprocess-book-factory.h>
 
 #undef __LIBEDATA_BOOK_H_INSIDE__
 
diff --git a/calendar/backends/caldav/e-cal-backend-caldav-factory.c 
b/calendar/backends/caldav/e-cal-backend-caldav-factory.c
index 3ce36e7..8957951 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav-factory.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav-factory.c
@@ -33,6 +33,8 @@ typedef ECalBackendFactoryClass ECalBackendCalDAVJournalFactoryClass;
 typedef ECalBackendFactory ECalBackendCalDAVTodosFactory;
 typedef ECalBackendFactoryClass ECalBackendCalDAVTodosFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -60,6 +62,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_cal_backend_caldav_events_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VEVENT_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_CALDAV;
@@ -78,6 +86,12 @@ e_cal_backend_caldav_events_factory_init (ECalBackendFactory *factory)
 static void
 e_cal_backend_caldav_journal_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VJOURNAL_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_CALDAV;
@@ -96,6 +110,12 @@ e_cal_backend_caldav_journal_factory_init (ECalBackendFactory *factory)
 static void
 e_cal_backend_caldav_todos_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VTODO_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_CALDAV;
@@ -114,6 +134,8 @@ e_cal_backend_caldav_todos_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_cal_backend_caldav_events_factory_register_type (type_module);
        e_cal_backend_caldav_journal_factory_register_type (type_module);
        e_cal_backend_caldav_todos_factory_register_type (type_module);
@@ -122,5 +144,6 @@ e_module_load (GTypeModule *type_module)
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
 
diff --git a/calendar/backends/contacts/e-cal-backend-contacts-factory.c 
b/calendar/backends/contacts/e-cal-backend-contacts-factory.c
index 5d2d9cb..fa806a2 100644
--- a/calendar/backends/contacts/e-cal-backend-contacts-factory.c
+++ b/calendar/backends/contacts/e-cal-backend-contacts-factory.c
@@ -27,6 +27,8 @@
 typedef ECalBackendFactory ECalBackendContactsEventsFactory;
 typedef ECalBackendFactoryClass ECalBackendContactsEventsFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -42,9 +44,16 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_cal_backend_contacts_events_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VEVENT_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_CONTACTS;
+
 }
 
 static void
@@ -60,6 +69,8 @@ e_cal_backend_contacts_events_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_source_contacts_type_register (type_module);
        e_cal_backend_contacts_events_factory_register_type (type_module);
 }
@@ -67,5 +78,6 @@ e_module_load (GTypeModule *type_module)
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
 
diff --git a/calendar/backends/file/e-cal-backend-file-factory.c 
b/calendar/backends/file/e-cal-backend-file-factory.c
index fbed4cd..27a3d7a 100644
--- a/calendar/backends/file/e-cal-backend-file-factory.c
+++ b/calendar/backends/file/e-cal-backend-file-factory.c
@@ -35,6 +35,8 @@ typedef ECalBackendFactoryClass ECalBackendFileJournalFactoryClass;
 typedef ECalBackendFactory ECalBackendFileTodosFactory;
 typedef ECalBackendFactoryClass ECalBackendFileTodosFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -62,6 +64,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_cal_backend_file_events_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VEVENT_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_FILE_EVENTS;
@@ -80,6 +88,12 @@ e_cal_backend_file_events_factory_init (ECalBackendFactory *factory)
 static void
 e_cal_backend_file_journal_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VJOURNAL_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_FILE_JOURNAL;
@@ -98,6 +112,12 @@ e_cal_backend_file_journal_factory_init (ECalBackendFactory *factory)
 static void
 e_cal_backend_file_todos_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VTODO_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_FILE_TODOS;
@@ -116,6 +136,8 @@ e_cal_backend_file_todos_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_source_local_type_register (type_module);
        e_cal_backend_file_events_factory_register_type (type_module);
        e_cal_backend_file_journal_factory_register_type (type_module);
@@ -125,5 +147,6 @@ e_module_load (GTypeModule *type_module)
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
 
diff --git a/calendar/backends/gtasks/e-cal-backend-gtasks-factory.c 
b/calendar/backends/gtasks/e-cal-backend-gtasks-factory.c
index c0eeab9..6888faa 100644
--- a/calendar/backends/gtasks/e-cal-backend-gtasks-factory.c
+++ b/calendar/backends/gtasks/e-cal-backend-gtasks-factory.c
@@ -25,6 +25,8 @@
 typedef ECalBackendFactory ECalBackendGTasksFactory;
 typedef ECalBackendFactoryClass ECalBackendGTasksFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -40,6 +42,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_cal_backend_gtasks_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VTODO_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_GTASKS;
@@ -58,10 +66,13 @@ e_cal_backend_gtasks_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_cal_backend_gtasks_factory_register_type (type_module);
 }
 
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
diff --git a/calendar/backends/http/e-cal-backend-http-factory.c 
b/calendar/backends/http/e-cal-backend-http-factory.c
index 094f34e..4701c59 100644
--- a/calendar/backends/http/e-cal-backend-http-factory.c
+++ b/calendar/backends/http/e-cal-backend-http-factory.c
@@ -32,6 +32,8 @@ typedef ECalBackendFactoryClass ECalBackendHttpJournalFactoryClass;
 typedef ECalBackendFactory ECalBackendHttpTodosFactory;
 typedef ECalBackendFactoryClass ECalBackendHttpTodosFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -59,6 +61,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_cal_backend_http_events_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VEVENT_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_HTTP;
@@ -77,6 +85,12 @@ e_cal_backend_http_events_factory_init (ECalBackendFactory *factory)
 static void
 e_cal_backend_http_journal_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VJOURNAL_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_HTTP;
@@ -95,6 +109,12 @@ e_cal_backend_http_journal_factory_init (ECalBackendFactory *factory)
 static void
 e_cal_backend_http_todos_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VTODO_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_HTTP;
@@ -113,6 +133,8 @@ e_cal_backend_http_todos_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_cal_backend_http_events_factory_register_type (type_module);
        e_cal_backend_http_journal_factory_register_type (type_module);
        e_cal_backend_http_todos_factory_register_type (type_module);
@@ -121,5 +143,6 @@ e_module_load (GTypeModule *type_module)
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
 
diff --git a/calendar/backends/weather/e-cal-backend-weather-factory.c 
b/calendar/backends/weather/e-cal-backend-weather-factory.c
index 746899e..e1cfa0c 100644
--- a/calendar/backends/weather/e-cal-backend-weather-factory.c
+++ b/calendar/backends/weather/e-cal-backend-weather-factory.c
@@ -27,6 +27,8 @@
 typedef ECalBackendFactory ECalBackendWeatherEventsFactory;
 typedef ECalBackendFactoryClass ECalBackendWeatherEventsFactoryClass;
 
+static EModule *e_module;
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -42,6 +44,12 @@ G_DEFINE_DYNAMIC_TYPE (
 static void
 e_cal_backend_weather_events_factory_class_init (ECalBackendFactoryClass *class)
 {
+       EBackendFactoryClass *backend_factory_class;
+
+       backend_factory_class = E_BACKEND_FACTORY_CLASS (class);
+       backend_factory_class->e_module = e_module;
+       backend_factory_class->share_subprocess = FALSE;
+
        class->factory_name = FACTORY_NAME;
        class->component_kind = ICAL_VEVENT_COMPONENT;
        class->backend_type = E_TYPE_CAL_BACKEND_WEATHER;
@@ -60,6 +68,8 @@ e_cal_backend_weather_events_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_module = E_MODULE (type_module);
+
        e_source_weather_type_register (type_module);
        e_cal_backend_weather_events_factory_register_type (type_module);
 }
@@ -67,5 +77,6 @@ e_module_load (GTypeModule *type_module)
 G_MODULE_EXPORT void
 e_module_unload (GTypeModule *type_module)
 {
+       e_module = NULL;
 }
 
diff --git a/calendar/libecal/e-cal-client-view.c b/calendar/libecal/e-cal-client-view.c
index 77d3377..58dbb9e 100644
--- a/calendar/libecal/e-cal-client-view.c
+++ b/calendar/libecal/e-cal-client-view.c
@@ -689,19 +689,36 @@ cal_client_view_initable_init (GInitable *initable,
                                GCancellable *cancellable,
                                GError **error)
 {
+       ECalClient *cal_client;
        ECalClientViewPrivate *priv;
        EGdbusCalView *gdbus_calview;
        gulong handler_id;
+       gchar *bus_name;
 
        priv = E_CAL_CLIENT_VIEW_GET_PRIVATE (initable);
 
+       cal_client = g_weak_ref_get (&priv->client);
+       if (cal_client == NULL) {
+               g_set_error (
+                       error, E_CLIENT_ERROR,
+                       E_CLIENT_ERROR_OTHER_ERROR,
+                       _("Client disappeared"));
+
+               return FALSE;
+       }
+
+       bus_name = e_client_dup_bus_name (E_CLIENT (cal_client));
+       g_object_unref (cal_client);
+
        gdbus_calview = e_gdbus_cal_view_proxy_new_sync (
                priv->connection,
                G_DBUS_PROXY_FLAGS_NONE,
-               CALENDAR_DBUS_SERVICE_NAME,
+               bus_name,
                priv->object_path,
                cancellable, error);
 
+       g_free (bus_name);
+
        if (gdbus_calview == NULL)
                return FALSE;
 
diff --git a/calendar/libecal/e-cal-client.c b/calendar/libecal/e-cal-client.c
index f84eb39..8657dde 100644
--- a/calendar/libecal/e-cal-client.c
+++ b/calendar/libecal/e-cal-client.c
@@ -1105,6 +1105,7 @@ cal_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
        ESource *source;
        const gchar *uid;
        gchar *object_path = NULL;
+       gchar *bus_name = NULL;
        gulong handler_id;
        GError *local_error = NULL;
 
@@ -1150,17 +1151,17 @@ cal_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
        switch (e_cal_client_get_source_type (E_CAL_CLIENT (client))) {
                case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
                        e_dbus_calendar_factory_call_open_calendar_sync (
-                               factory_proxy, uid, &object_path,
+                               factory_proxy, uid, &object_path, &bus_name,
                                cancellable, &local_error);
                        break;
                case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
                        e_dbus_calendar_factory_call_open_task_list_sync (
-                               factory_proxy, uid, &object_path,
+                               factory_proxy, uid, &object_path, &bus_name,
                                cancellable, &local_error);
                        break;
                case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
                        e_dbus_calendar_factory_call_open_memo_list_sync (
-                               factory_proxy, uid, &object_path,
+                               factory_proxy, uid, &object_path, &bus_name,
                                cancellable, &local_error);
                        break;
                default:
@@ -1171,8 +1172,8 @@ cal_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
 
        /* Sanity check. */
        g_return_if_fail (
-               ((object_path != NULL) && (local_error == NULL)) ||
-               ((object_path == NULL) && (local_error != NULL)));
+               (((object_path != NULL) || (bus_name != NULL)) && (local_error == NULL)) ||
+               (((object_path == NULL) || (bus_name == NULL)) && (local_error != NULL)));
 
        if (object_path == NULL) {
                g_dbus_error_strip_remote_error (local_error);
@@ -1181,13 +1182,15 @@ cal_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
                return;
        }
 
+       e_client_set_bus_name (client, bus_name);
+
        priv->dbus_proxy = e_dbus_calendar_proxy_new_sync (
                connection,
                G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
-               CALENDAR_DBUS_SERVICE_NAME,
-               object_path, cancellable, &local_error);
+               bus_name, object_path, cancellable, &local_error);
 
        g_free (object_path);
+       g_free (bus_name);
 
        /* Sanity check. */
        g_return_if_fail (
diff --git a/calendar/libedata-cal/Makefile.am b/calendar/libedata-cal/Makefile.am
index 7467c34..98d19d2 100644
--- a/calendar/libedata-cal/Makefile.am
+++ b/calendar/libedata-cal/Makefile.am
@@ -7,6 +7,7 @@ libedata_cal_1_2_la_CPPFLAGS = \
        -DLIBEDATA_CAL_COMPILATION \
        -DG_LOG_DOMAIN=\"libedata-cal\" \
        -DBACKENDDIR=\"$(ecal_backenddir)\" \
+       -DSUBPROCESS_CAL_BACKEND_PATH=\"$(libexecdir)/evolution-calendar-factory-subprocess\" \
        -I$(top_srcdir) \
        -I$(top_srcdir)/calendar \
        -I$(top_srcdir)/calendar/libegdbus \
@@ -31,6 +32,7 @@ libedata_cal_1_2_la_SOURCES = \
        e-data-cal.c \
        e-data-cal-factory.c \
        e-data-cal-view.c \
+       e-subprocess-cal-factory.c \
        $(NULL)
 
 libedata_cal_1_2_la_LIBADD = \
@@ -62,6 +64,7 @@ libedata_calinclude_HEADERS = \
        e-data-cal-factory.h \
        e-cal-backend-store.h \
        e-data-cal-view.h \
+       e-subprocess-cal-factory.h \
        $(NULL)
 
 %-$(API_VERSION).pc: %.pc
@@ -70,6 +73,45 @@ libedata_calinclude_HEADERS = \
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libedata-cal-$(API_VERSION).pc
 
+libexec_PROGRAMS = evolution-calendar-factory-subprocess
+
+evolution_calendar_factory_subprocess_CPPFLAGS= \
+       $(AM_CPPFLAGS) \
+       -DLOCALEDIR=\"$(localedir)\" \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/private \
+       -I$(top_srcdir)/calendar \
+       -I$(top_builddir) \
+       -I$(top_builddir)/private \
+       -I$(top_builddir)/calendar \
+       $(EVOLUTION_CALENDAR_CFLAGS) \
+       $(LIBSECRET_CFLAGS) \
+       $(FACTORY_GTK_CFLAGS) \
+       $(CAMEL_CFLAGS) \
+       $(SOUP_CFLAGS) \
+       $(CODE_COVERAGE_CFLAGS) \
+       $(NULL)
+
+evolution_calendar_factory_subprocess_SOURCES = \
+       evolution-calendar-factory-subprocess.c \
+       $(NULL)
+
+evolution_calendar_factory_subprocess_LDADD = \
+       $(top_builddir)/libebackend/libebackend-1.2.la \
+       $(top_builddir)/libedataserver/libedataserver-1.2.la \
+       libedata-cal-1.2.la \
+       $(EVOLUTION_CALENDAR_LIBS) \
+       $(LIBSECRET_LIBS) \
+       $(FACTORY_GTK_LIBS) \
+       $(CAMEL_CFLAGS) \
+       $(SOUP_LIBS) \
+       $(NULL)
+
+evolution_calendar_factory_subprocess_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       $(CODE_COVERAGE_LDFLAGS) \
+       $(NULL)
+
 DISTCLEANFILES = $(pkgconfig_DATA)
 
 EXTRA_DIST = \
diff --git a/calendar/libedata-cal/e-data-cal-factory.c b/calendar/libedata-cal/e-data-cal-factory.c
index 4dffcb0..b03fd7b 100644
--- a/calendar/libedata-cal/e-data-cal-factory.c
+++ b/calendar/libedata-cal/e-data-cal-factory.c
@@ -82,44 +82,65 @@ data_cal_factory_get_dbus_interface_skeleton (EDBusServer *server)
        return G_DBUS_INTERFACE_SKELETON (factory->priv->dbus_factory);
 }
 
-static gchar *
-data_cal_factory_open (EDataFactory *data_factory,
-                      EBackend *backend,
-                      GDBusConnection *connection,
-                      GError **error)
+static const gchar *
+data_cal_get_factory_name (EBackendFactory *backend_factory)
 {
-       EDataCal *data_cal;
-       gchar *object_path;
-
-       /* If the backend already has an EDataCal installed, return its
-        * object path.  Otherwise we need to install a new EDataCal. */
-
-       data_cal = e_cal_backend_ref_data_cal (E_CAL_BACKEND (backend));
-
-       if (data_cal != NULL) {
-               object_path = g_strdup (
-                       e_data_cal_get_object_path (data_cal));
-       } else {
-               object_path = e_data_factory_construct_path (data_factory);
-
-               /* The EDataCal will attach itself to ECalBackend,
-                * so no need to call e_cal_backend_set_data_cal(). */
-               data_cal = e_data_cal_new (
-                       E_CAL_BACKEND (backend),
-                       connection, object_path, error);
-
-               if (data_cal != NULL) {
-                       e_data_factory_set_backend_callbacks (
-                               data_factory, backend);
-               } else {
-                       g_free (object_path);
-                       object_path = NULL;
-               }
-       }
+       ECalBackendFactoryClass *class;
+
+       class = E_CAL_BACKEND_FACTORY_GET_CLASS (E_CAL_BACKEND_FACTORY (backend_factory));
+
+       return class->factory_name;
+}
+
+static void
+data_cal_complete_calendar_open (EDataFactory *data_factory,
+                                GDBusMethodInvocation *invocation,
+                                const gchar *object_path,
+                                const gchar *bus_name)
+{
+       EDataCalFactory *data_cal_factory = E_DATA_CAL_FACTORY (data_factory);
+
+       e_dbus_calendar_factory_complete_open_calendar (
+               data_cal_factory->priv->dbus_factory, invocation, object_path, bus_name);
+}
+
+static void
+data_cal_complete_task_list_open (EDataFactory *data_factory,
+                                 GDBusMethodInvocation *invocation,
+                                 const gchar *object_path,
+                                 const gchar *bus_name)
+{
+       EDataCalFactory *data_cal_factory = E_DATA_CAL_FACTORY (data_factory);
 
-       g_clear_object (&data_cal);
+       e_dbus_calendar_factory_complete_open_task_list (
+               data_cal_factory->priv->dbus_factory, invocation, object_path, bus_name);
+}
+
+static void
+data_cal_complete_memo_list_open (EDataFactory *data_factory,
+                                 GDBusMethodInvocation *invocation,
+                                 const gchar *object_path,
+                                 const gchar *bus_name)
+{
+       EDataCalFactory *data_cal_factory = E_DATA_CAL_FACTORY (data_factory);
 
-       return object_path;
+       e_dbus_calendar_factory_complete_open_memo_list (
+               data_cal_factory->priv->dbus_factory, invocation, object_path, bus_name);
+}
+
+static void
+data_cal_complete_open (EDataFactory *data_factory,
+                       GDBusMethodInvocation *invocation,
+                       const gchar *object_path,
+                       const gchar *bus_name,
+                       const gchar *extension_name)
+{
+       if (g_strcmp0 (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
+               data_cal_complete_calendar_open (data_factory, invocation, object_path, bus_name);
+       else if (g_strcmp0 (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
+               data_cal_complete_task_list_open (data_factory, invocation, object_path, bus_name);
+       else if (g_strcmp0 (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
+               data_cal_complete_memo_list_open (data_factory, invocation, object_path, bus_name);
 }
 
 static gboolean
@@ -161,42 +182,25 @@ e_data_cal_factory_class_init (EDataCalFactoryClass *class)
        data_factory_class = E_DATA_FACTORY_CLASS (class);
        data_factory_class->backend_factory_type = E_TYPE_CAL_BACKEND_FACTORY;
        data_factory_class->factory_object_path = "/org/gnome/evolution/dataserver/CalendarFactory";
-       data_factory_class->data_object_path_prefix = "/org/gnome/evolution/dataserver/Calendar";
+       data_factory_class->subprocess_object_path_prefix = 
"/org/gnome/evolution/dataserver/Subprocess/Backend/Calendar";
+       data_factory_class->subprocess_bus_name_prefix = 
"org.gnome.evolution.dataserver.Subprocess.Backend.Calendar";
        data_factory_class->get_dbus_interface_skeleton = data_cal_factory_get_dbus_interface_skeleton;
-       data_factory_class->data_open = data_cal_factory_open;
+       data_factory_class->get_factory_name = data_cal_get_factory_name;
+       data_factory_class->complete_open = data_cal_complete_open;
 }
 
-#define HANDLE_OPEN_CB(extension_name, minus)                                  \
-       GDBusConnection *connection;                                            \
-       const gchar *sender;                                                    \
-       gchar *object_path;                                                     \
-       GError *error = NULL;                                                   \
-                                                                               \
-       connection = g_dbus_method_invocation_get_connection (invocation);      \
-       sender = g_dbus_method_invocation_get_sender (invocation);              \
-                                                                               \
-       object_path = e_data_factory_open_backend (                             \
-               E_DATA_FACTORY (factory), connection, sender,                   \
-               uid, extension_name, &error);                                   \
-                                                                               \
-       if (object_path != NULL) {                                              \
-               e_dbus_calendar_factory_complete_open_##minus (                 \
-                       dbus_interface, invocation, object_path);               \
-               g_free (object_path);                                           \
-       } else {                                                                \
-               g_return_val_if_fail (error != NULL, FALSE);                    \
-               g_dbus_method_invocation_take_error (invocation, error);        \
-       }                                                                       \
-                                                                               \
-       return TRUE;
-
 static gboolean
 data_cal_factory_handle_open_calendar_cb (EDBusCalendarFactory *dbus_interface,
                                          GDBusMethodInvocation *invocation,
                                          const gchar *uid,
                                          EDataCalFactory *factory)
 {
-       HANDLE_OPEN_CB (E_SOURCE_EXTENSION_CALENDAR, calendar);
+       EDataFactory *data_factory = E_DATA_FACTORY (factory);
+
+       e_data_factory_spawn_subprocess_backend (
+               data_factory, invocation, uid, E_SOURCE_EXTENSION_CALENDAR, SUBPROCESS_CAL_BACKEND_PATH);
+
+       return TRUE;
 }
 
 static gboolean
@@ -205,7 +209,12 @@ data_cal_factory_handle_open_task_list_cb (EDBusCalendarFactory *dbus_interface,
                                           const gchar *uid,
                                           EDataCalFactory *factory)
 {
-       HANDLE_OPEN_CB (E_SOURCE_EXTENSION_TASK_LIST, task_list);
+       EDataFactory *data_factory = E_DATA_FACTORY (factory);
+
+       e_data_factory_spawn_subprocess_backend (
+               data_factory, invocation, uid, E_SOURCE_EXTENSION_TASK_LIST, SUBPROCESS_CAL_BACKEND_PATH);
+
+       return TRUE;
 }
 
 static gboolean
@@ -214,10 +223,13 @@ data_cal_factory_handle_open_memo_list_cb (EDBusCalendarFactory *dbus_interface,
                                           const gchar *uid,
                                           EDataCalFactory *factory)
 {
-       HANDLE_OPEN_CB (E_SOURCE_EXTENSION_MEMO_LIST, memo_list);
-}
+       EDataFactory *data_factory = E_DATA_FACTORY (factory);
 
+       e_data_factory_spawn_subprocess_backend (
+               data_factory, invocation, uid, E_SOURCE_EXTENSION_MEMO_LIST, SUBPROCESS_CAL_BACKEND_PATH);
 
+       return TRUE;
+}
 
 static void
 e_data_cal_factory_init (EDataCalFactory *factory)
diff --git a/calendar/libedata-cal/e-subprocess-cal-factory.c 
b/calendar/libedata-cal/e-subprocess-cal-factory.c
new file mode 100644
index 0000000..3dffb4b
--- /dev/null
+++ b/calendar/libedata-cal/e-subprocess-cal-factory.c
@@ -0,0 +1,147 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Fabiano Fidêncio <fidencio redhat com>
+ */
+
+/**
+ * SECTION: e-subprocess-cal-factory
+ * @include: libedata-cal/libedata-cal.h
+ * @short_description: Responsible for #EBackend objects.
+ *
+ * This class handles and creates #EBackend objects from inside
+ * their own subprocesses and also serves as the layer that does
+ * the communication between #EDataCalFactory and #EBackend
+ **/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib/gi18n-lib.h>
+
+#include "e-cal-backend.h"
+#include "e-cal-backend-factory.h"
+#include "e-data-cal.h"
+#include "e-subprocess-cal-factory.h"
+
+#include <e-dbus-subprocess-backend.h>
+
+/* Forward Declarations */
+static void    e_subprocess_cal_factory_initable_init
+                                               (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (
+       ESubprocessCalFactory,
+       e_subprocess_cal_factory,
+       E_TYPE_SUBPROCESS_FACTORY,
+       G_IMPLEMENT_INTERFACE (
+               G_TYPE_INITABLE,
+               e_subprocess_cal_factory_initable_init))
+
+static gchar *
+subprocess_cal_factory_open (ESubprocessFactory *subprocess_factory,
+                            EBackend *backend,
+                            GDBusConnection *connection,
+                            gpointer data,
+                            GCancellable *cancellable,
+                            GError **error)
+{
+       EDataCal *data_cal;
+       gchar *object_path;
+
+       /* If the backend already has an EDataCal installed, return its
+        * object path.  Otherwise we need to install a new EDataCal. */
+       data_cal = e_cal_backend_ref_data_cal (E_CAL_BACKEND (backend));
+
+       if (data_cal != NULL) {
+               object_path = g_strdup (e_data_cal_get_object_path (data_cal));
+       } else {
+               object_path = e_subprocess_factory_construct_path ();
+
+               /* The EDataCal will attach itself to ECalBackend,
+                * so no need to call e_cal_backend_set_data_cal(). */
+               data_cal = e_data_cal_new (
+                       E_CAL_BACKEND (backend),
+                       connection, object_path, error);
+
+               if (data_cal != NULL) {
+                       e_subprocess_factory_set_backend_callbacks (
+                               subprocess_factory, backend, data);
+               } else {
+                       g_free (object_path);
+                       object_path = NULL;
+               }
+       }
+
+       g_clear_object (&data_cal);
+
+       return object_path;
+}
+
+static EBackend *
+subprocess_cal_factory_ref_backend (ESourceRegistry *registry,
+                                    ESource *source,
+                                    const gchar *backend_factory_type_name)
+{
+       ECalBackend *backend;
+       ECalBackendFactoryClass *backend_factory_class;
+       GType backend_factory_type;
+
+       backend_factory_type = g_type_from_name (backend_factory_type_name);
+       backend_factory_class = g_type_class_ref (backend_factory_type);
+
+       backend = g_object_new (
+               backend_factory_class->backend_type,
+               "kind", backend_factory_class->component_kind,
+               "registry", registry,
+               "source", source, NULL);
+
+       return E_BACKEND (backend);
+}
+
+static void
+e_subprocess_cal_factory_class_init (ESubprocessCalFactoryClass *class)
+{
+       ESubprocessFactoryClass *subprocess_factory_class;
+
+       subprocess_factory_class = E_SUBPROCESS_FACTORY_CLASS (class);
+       subprocess_factory_class->ref_backend = subprocess_cal_factory_ref_backend;
+       subprocess_factory_class->open_data = subprocess_cal_factory_open;
+}
+
+static void
+e_subprocess_cal_factory_initable_init (GInitableIface *iface)
+{
+}
+
+static void
+e_subprocess_cal_factory_init (ESubprocessCalFactory *subprocess_factory)
+{
+}
+
+ESubprocessCalFactory *
+e_subprocess_cal_factory_new (GCancellable *cancellable,
+                              GError **error)
+{
+       return g_initable_new (
+               E_TYPE_SUBPROCESS_CAL_FACTORY,
+               cancellable, error, NULL);
+}
diff --git a/calendar/libedata-cal/e-subprocess-cal-factory.h 
b/calendar/libedata-cal/e-subprocess-cal-factory.h
new file mode 100644
index 0000000..c8f4735
--- /dev/null
+++ b/calendar/libedata-cal/e-subprocess-cal-factory.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__LIBEDATA_CAL_H_INSIDE__) && !defined (LIBEDATA_CAL_COMPILATION)
+#error "Only <libedata-cal/libedata-cal.h> should be included directly."
+#endif
+
+#ifndef E_SUBPROCESS_CAL_FACTORY_H
+#define E_SUBPROCESS_CAL_FACTORY_H
+
+#include <libebackend/libebackend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SUBPROCESS_CAL_FACTORY \
+       (e_subprocess_cal_factory_get_type ())
+#define E_SUBPROCESS_CAL_FACTORY(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_SUBPROCESS_CAL_FACTORY, ESubprocessCalFactory))
+#define E_SUBPROCESS_CAL_FACTORY_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_SUBPROCESS_CAL_FACTORY, ESubprocessCalFactoryClass))
+#define E_IS_SUBPROCESS_CAL_FACTORY(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_SUBPROCESS_CAL_FACTORY))
+#define E_IS_SUBPROCESS_CAL_FACTORY_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_SUBPROCESS_CAL_FACTORY))
+#define E_SUBPROCESS_CAL_FACTORY_GET_CLASS(cls) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_SUBPROCESS_CAL_FACTORY, ESubprocessCalFactoryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESubprocessCalFactory ESubprocessCalFactory;
+typedef struct _ESubprocessCalFactoryClass ESubprocessCalFactoryClass;
+typedef struct _ESubprocessCalFactoryPrivate ESubprocessCalFactoryPrivate;
+
+struct _ESubprocessCalFactory {
+       ESubprocessFactory parent;
+       ESubprocessCalFactoryPrivate *priv;
+};
+
+struct _ESubprocessCalFactoryClass {
+       ESubprocessFactoryClass parent_class;
+};
+
+GType          e_subprocess_cal_factory_get_type       (void) G_GNUC_CONST;
+ESubprocessCalFactory *
+               e_subprocess_cal_factory_new            (GCancellable *cancellable,
+                                                        GError **error);
+
+G_END_DECLS
+
+#endif /* E_SUBPROCESS_CAL_FACTORY_H */
diff --git a/calendar/libedata-cal/evolution-calendar-factory-subprocess.c 
b/calendar/libedata-cal/evolution-calendar-factory-subprocess.c
new file mode 100644
index 0000000..64c55d5
--- /dev/null
+++ b/calendar/libedata-cal/evolution-calendar-factory-subprocess.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <glib/gi18n.h>
+
+#if defined (ENABLE_MAINTAINER_MODE) && defined (HAVE_GTK)
+#include <gtk/gtk.h>
+#endif
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+#include <conio.h>
+#ifndef PROCESS_DEP_ENABLE
+#define PROCESS_DEP_ENABLE 0x00000001
+#endif
+#ifndef PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
+#define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
+#endif
+#endif
+
+#include <e-dbus-subprocess-backend.h>
+#include <libebackend/libebackend.h>
+#include <libedata-cal/libedata-cal.h>
+
+typedef struct _SubprocessData SubprocessData;
+
+struct _SubprocessData {
+       GMainLoop *loop;
+       GDBusObjectManagerServer *manager;
+       ESubprocessCalFactory *subprocess_cal_factory;
+};
+
+static const gchar *bus_name = NULL;
+static const gchar *path = NULL;
+
+static GOptionEntry entries[] = {
+       { "bus-name", 'b', 0, G_OPTION_ARG_STRING, &bus_name, NULL, NULL },
+       { "own-path", 'p', 0, G_OPTION_ARG_STRING, &path, NULL, NULL },
+       { NULL }
+};
+
+static void
+prepare_shutdown_and_quit (ESubprocessCalFactory *subprocess_cal_factory,
+                          GMainLoop *loop)
+{
+       e_subprocess_factory_call_backends_prepare_shutdown (E_SUBPROCESS_FACTORY (subprocess_cal_factory));
+
+       g_main_loop_quit (loop);
+}
+
+static gboolean
+subprocess_backend_handle_create_cb (EDBusSubprocessBackend *proxy,
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar *uid,
+                                    const gchar *backend_factory_type_name,
+                                    const gchar *module_filename,
+                                    ESubprocessCalFactory *subprocess_cal_factory)
+{
+       gchar *object_path = NULL;
+       GDBusConnection *connection;
+       GError *error = NULL;
+
+       connection = g_dbus_method_invocation_get_connection (invocation);
+
+       object_path = e_subprocess_factory_open_backend (
+               E_SUBPROCESS_FACTORY (subprocess_cal_factory),
+               connection,
+               uid,
+               backend_factory_type_name,
+               module_filename,
+               G_DBUS_INTERFACE_SKELETON (proxy),
+               NULL,
+               &error);
+
+       if (object_path != NULL) {
+               e_dbus_subprocess_backend_complete_create (proxy, invocation, object_path);
+               g_free (object_path);
+       } else {
+               g_dbus_method_invocation_take_error (invocation, error);
+       }
+
+       return TRUE;
+}
+
+static gboolean
+subprocess_backend_handle_close_cb (EDBusSubprocessBackend *proxy,
+                                   GDBusMethodInvocation *invocation,
+                                   SubprocessData *sd)
+{
+       prepare_shutdown_and_quit (sd->subprocess_cal_factory, sd->loop);
+
+       return TRUE;
+}
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+                const gchar *name,
+                SubprocessData *sd)
+{
+       EDBusSubprocessBackend *proxy;
+       EDBusSubprocessObjectSkeleton *object;
+
+       object = e_dbus_subprocess_object_skeleton_new (path);
+
+       proxy = e_dbus_subprocess_backend_skeleton_new ();
+       e_dbus_subprocess_object_skeleton_set_backend (object, proxy);
+
+       g_signal_connect (
+               proxy, "handle-create",
+               G_CALLBACK (subprocess_backend_handle_create_cb),
+               sd->subprocess_cal_factory);
+
+       g_signal_connect (
+               proxy, "handle-close",
+               G_CALLBACK (subprocess_backend_handle_close_cb),
+               sd);
+
+       g_dbus_object_manager_server_export (sd->manager, G_DBUS_OBJECT_SKELETON (object));
+       g_object_unref (proxy);
+       g_object_unref (object);
+
+       g_dbus_object_manager_server_set_connection (sd->manager, connection);
+}
+
+static void
+vanished_cb (GDBusConnection *connection,
+            const gchar *name,
+            SubprocessData *sd)
+{
+       prepare_shutdown_and_quit (sd->subprocess_cal_factory, sd->loop);
+}
+
+gint
+main (gint argc,
+      gchar **argv)
+{
+       guint id;
+       guint watched_id;
+       ESubprocessCalFactory *subprocess_cal_factory;
+       GMainLoop *loop;
+       GDBusObjectManagerServer *manager;
+       GOptionContext *context;
+       SubprocessData sd;
+       GError *error = NULL;
+
+#ifdef G_OS_WIN32
+       /* Reduce risks */
+       {
+               typedef BOOL (WINAPI *t_SetDllDirectoryA) (LPCSTR lpPathName);
+               t_SetDllDirectoryA p_SetDllDirectoryA;
+
+               p_SetDllDirectoryA = GetProcAddress (
+                       GetModuleHandle ("kernel32.dll"),
+                       "SetDllDirectoryA");
+
+               if (p_SetDllDirectoryA != NULL)
+                       p_SetDllDirectoryA ("");
+       }
+#ifndef _WIN64
+       {
+               typedef BOOL (WINAPI *t_SetProcessDEPPolicy) (DWORD dwFlags);
+               t_SetProcessDEPPolicy p_SetProcessDEPPolicy;
+
+               p_SetProcessDEPPolicy = GetProcAddress (
+                       GetModuleHandle ("kernel32.dll"),
+                       "SetProcessDEPPolicy");
+
+               if (p_SetProcessDEPPolicy != NULL)
+                       p_SetProcessDEPPolicy (
+                               PROCESS_DEP_ENABLE |
+                               PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION);
+       }
+#endif
+#endif
+
+       setlocale (LC_ALL, "");
+       bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+#if defined (ENABLE_MAINTAINER_MODE) && defined (HAVE_GTK)
+       if (g_getenv ("EDS_TESTING") == NULL)
+               /* This is only to load gtk-modules, like
+                * bug-buddy's gnomesegvhandler, if possible */
+               gtk_init_check (&argc, &argv);
+#endif
+
+       context = g_option_context_new (NULL);
+       g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+       g_option_context_parse (context, &argc, &argv, &error);
+       g_option_context_free (context);
+
+       if (error != NULL) {
+               g_printerr ("%s\n", error->message);
+               exit (EXIT_FAILURE);
+       }
+
+       loop = g_main_loop_new (NULL, FALSE);
+
+       manager = g_dbus_object_manager_server_new ("/org/gnome/evolution/dataserver/Subprocess/Backend");
+
+       subprocess_cal_factory = e_subprocess_cal_factory_new (NULL, NULL);
+
+       sd.loop = loop;
+       sd.manager = manager;
+       sd.subprocess_cal_factory = subprocess_cal_factory;
+
+       /* Watch the factory name and close the subprocess if the factory dies/crashes */
+       watched_id = g_bus_watch_name (
+               G_BUS_TYPE_SESSION,
+               CALENDAR_DBUS_SERVICE_NAME,
+               G_BUS_NAME_WATCHER_FLAGS_NONE,
+               NULL,
+               (GBusNameVanishedCallback) vanished_cb,
+               &sd,
+               NULL);
+
+       id = g_bus_own_name (
+               G_BUS_TYPE_SESSION,
+               bus_name,
+               G_BUS_NAME_OWNER_FLAGS_NONE,
+               (GBusAcquiredCallback) on_bus_acquired,
+               NULL,
+               NULL,
+               &sd,
+               NULL);
+
+       g_main_loop_run (loop);
+       g_bus_unown_name (id);
+       g_main_loop_unref (loop);
+
+       g_clear_object (&subprocess_cal_factory);
+       g_clear_object (&manager);
+       g_bus_unwatch_name (watched_id);
+
+       return 0;
+}
diff --git a/calendar/libedata-cal/libedata-cal.h b/calendar/libedata-cal/libedata-cal.h
index 6a3044b..c37bef9 100644
--- a/calendar/libedata-cal/libedata-cal.h
+++ b/calendar/libedata-cal/libedata-cal.h
@@ -34,6 +34,7 @@
 #include <libedata-cal/e-data-cal-factory.h>
 #include <libedata-cal/e-data-cal.h>
 #include <libedata-cal/e-data-cal-view.h>
+#include <libedata-cal/e-subprocess-cal-factory.h>
 
 #undef __LIBEDATA_CAL_H_INSIDE__
 
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 9151eb1..033759b 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -20,13 +20,6 @@
 #include <config.h>
 #endif
 
-/* XXX Disable deprecation warnings until we require GLib 2.40.
- *
- *     This silences warnings for using GSubprocess functions, which are
- *     only available as of GLib 2.39.  But we do so conditionally, with
- *     GLIB_CHECK_VERSION macros. */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
-
 #include <errno.h>
 #include <fcntl.h>
 #include <time.h>
@@ -343,9 +336,7 @@ struct _CamelIMAPXServerPrivate {
        GInputStream *input_stream;
        GOutputStream *output_stream;
        GIOStream *connection;
-#if GLIB_CHECK_VERSION(2,39,0)
        GSubprocess *subprocess;
-#endif
        GMutex stream_lock;
 
        GThread *parser_thread;
@@ -4192,7 +4183,6 @@ imapx_server_set_streams (CamelIMAPXServer *is,
        g_mutex_unlock (&is->priv->stream_lock);
 }
 
-#if GLIB_CHECK_VERSION(2,39,0)
 static void
 imapx_server_child_process_setup (gpointer user_data)
 {
@@ -4212,14 +4202,12 @@ imapx_server_child_process_setup (gpointer user_data)
        }
 #endif /* TIOCNOTTY */
 }
-#endif
 
 static gboolean
 connect_to_server_process (CamelIMAPXServer *is,
                            const gchar *cmd,
                            GError **error)
 {
-#if GLIB_CHECK_VERSION(2,39,0)
        GSubprocessLauncher *launcher;
        GSubprocess *subprocess = NULL;
        CamelNetworkSettings *network_settings;
@@ -4369,16 +4357,6 @@ connect_to_server_process (CamelIMAPXServer *is,
        }
 
        return TRUE;
-
-#else /* GLIB_CHECK_VERSION(2,39,0) */
-
-       g_set_error_literal (
-               error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-               "GLib 2.39 or later is required to connect "
-               "to an IMAP server through a shell command");
-
-       return FALSE;
-#endif
 }
 
 gboolean
@@ -4631,9 +4609,7 @@ exit:
                g_clear_object (&is->priv->input_stream);
                g_clear_object (&is->priv->output_stream);
                g_clear_object (&is->priv->connection);
-#if GLIB_CHECK_VERSION(2,39,0)
                g_clear_object (&is->priv->subprocess);
-#endif
 
                if (is->cinfo != NULL) {
                        imapx_free_capability (is->cinfo);
@@ -7760,9 +7736,7 @@ imapx_server_dispose (GObject *object)
 
        g_weak_ref_set (&server->priv->store, NULL);
 
-#if GLIB_CHECK_VERSION(2,39,0)
        g_clear_object (&server->priv->subprocess);
-#endif
 
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (camel_imapx_server_parent_class)->dispose (object);
@@ -8140,9 +8114,7 @@ imapx_disconnect (CamelIMAPXServer *is)
        g_clear_object (&is->priv->input_stream);
        g_clear_object (&is->priv->output_stream);
        g_clear_object (&is->priv->connection);
-#if GLIB_CHECK_VERSION(2,39,0)
        g_clear_object (&is->priv->subprocess);
-#endif
 
        g_mutex_unlock (&is->priv->stream_lock);
 
diff --git a/configure.ac b/configure.ac
index d931e2f..e03aaa2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,8 +35,8 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 dnl Required Package Versions
 
 dnl Keep these two definitions in agreement.
-m4_define([glib_minimum_version], [2.36])
-m4_define([glib_encoded_version], [GLIB_VERSION_2_36])
+m4_define([glib_minimum_version], [2.40])
+m4_define([glib_encoded_version], [GLIB_VERSION_2_40])
 
 dnl Keep these two definitions in agreement.
 m4_define([gdk_minimum_version], [3.2])
@@ -73,8 +73,8 @@ GLIB_GSETTINGS
 dnl ******************************
 dnl D-Bus versioning
 dnl ******************************
-ADDRESS_BOOK_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.AddressBook7"
-CALENDAR_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.Calendar5"
+ADDRESS_BOOK_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.AddressBook8"
+CALENDAR_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.Calendar6"
 SOURCES_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.Sources3"
 USER_PROMPTER_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.UserPrompter0"
 
@@ -106,23 +106,23 @@ AC_SUBST(USER_PROMPTER_DBUS_SERVICE_NAME)
 dnl ******************************
 dnl Libtool versioning
 dnl ******************************
-LIBEDATASERVER_CURRENT=18
+LIBEDATASERVER_CURRENT=19
 LIBEDATASERVER_REVISION=0
 LIBEDATASERVER_AGE=0
 
-LIBECAL_CURRENT=16
+LIBECAL_CURRENT=17
 LIBECAL_REVISION=0
 LIBECAL_AGE=0
 
-LIBEDATACAL_CURRENT=25
+LIBEDATACAL_CURRENT=26
 LIBEDATACAL_REVISION=0
 LIBEDATACAL_AGE=0
 
-LIBEDATABOOK_CURRENT=23
+LIBEDATABOOK_CURRENT=24
 LIBEDATABOOK_REVISION=0
 LIBEDATABOOK_AGE=0
 
-LIBEBOOK_CURRENT=17
+LIBEBOOK_CURRENT=18
 LIBEBOOK_REVISION=1
 LIBEBOOK_AGE=3
 
@@ -134,7 +134,7 @@ LIBCAMEL_CURRENT=50
 LIBCAMEL_REVISION=0
 LIBCAMEL_AGE=0
 
-LIBEBACKEND_CURRENT=8
+LIBEBACKEND_CURRENT=9
 LIBEBACKEND_REVISION=0
 LIBEBACKEND_AGE=0
 
@@ -567,6 +567,20 @@ if test "x$enable_uoa" = xyes; then
 fi
 AM_CONDITIONAL(HAVE_UOA, [test x$enable_uoa = xyes])
 
+dnl **********************************************
+dnl Check if backend per process should be enabled
+dnl **********************************************
+AC_ARG_ENABLE([backend-per-process],
+       [AS_HELP_STRING([--enable-backend-per-process],
+       [enable backend per process support (default=yes)])],
+       [enable_backend_per_process=$enableval], [enable_backend_per_process=yes])
+AC_MSG_CHECKING([if backend per process is enabled])
+AC_MSG_RESULT([$enable_backend_per_process])
+if test "x$enable_backend_per_process" = xyes; then
+       AC_DEFINE(ENABLE_BACKEND_PER_PROCESS, 1, [If backend-per-process is enabled])
+fi
+AM_CONDITIONAL(ENABLE_BACKEND_PER_PROCESS, [test x$enable_backend_per_process = xyes])
+
 dnl ***********************************
 dnl Check for GNOME Keyring.
 dnl ***********************************
@@ -1838,4 +1852,5 @@ echo "
        Examples:               $enable_examples
        Code coverage (gcov):   $enable_code_coverage
        Installed tests:        $enable_installed_tests
+       Backend per process     $enable_backend_per_process
 "
diff --git a/docs/reference/eds/eds-sections.txt b/docs/reference/eds/eds-sections.txt
index 9b5b15f..eeea8a1 100644
--- a/docs/reference/eds/eds-sections.txt
+++ b/docs/reference/eds/eds-sections.txt
@@ -138,6 +138,8 @@ EBackendFactory
 EBackendFactoryClass
 e_backend_factory_get_hash_key
 e_backend_factory_new_backend
+e_backend_factory_get_module_filename
+e_backend_factory_share_subprocess
 <SUBSECTION Standard>
 EBackendFactoryPrivate
 E_BACKEND_FACTORY
@@ -1600,6 +1602,8 @@ e_client_refresh
 e_client_refresh_finish
 e_client_refresh_sync
 e_client_util_parse_comma_strings
+e_client_dup_bus_name
+e_client_set_bus_name
 CLIENT_BACKEND_PROPERTY_OPENED
 CLIENT_BACKEND_PROPERTY_OPENING
 e_client_error_create
@@ -2085,13 +2089,10 @@ e_data_cal_view_get_type
 <TITLE>EDataFactory</TITLE>
 EDataFactory
 EDataFactoryClass
-e_data_factory_ref_backend
-e_data_factory_ref_initable_backend
 e_data_factory_ref_backend_factory
 e_data_factory_get_registry
-e_data_factory_open
 e_data_factory_construct_path
-e_data_factory_set_backend_callbacks
+e_data_factoru_spawn_subprocess_backend
 <SUBSECTION Standard>
 EDataFactoryPrivate
 E_DATA_FACTORY
@@ -2104,6 +2105,29 @@ e_data_factory_get_type
 </SECTION>
 
 <SECTION>
+<FILE>e-subprocess-factory</FILE>
+<TITLE>ESubprocessFactory</TITLE>
+ESubprocessFactory
+ESubprocessFactoryClass
+e_subprocess_factory_ref_initable_backend
+e_subprocess_factory_get_registry
+e_subprocess_factory_open_baclkend
+e_subprocess_factory_constrcut_path
+e_subprocess_factory_set_backend_callbacks
+e_subprocess_factory_call_backends_prepare_shutdown
+e_subprocess_factory_get_backends_list
+<SUBSECTION Standard>
+ESubprocessFactoryPrivate
+E_SUBPROCESS_FACTORY
+E_SUBPROCESS_FACTORY_CLASS
+E_SUBPROCESS_FACTORY_GET_CLASS
+E_IS_SUBPROCESS_FACTORY
+E_IS_SUBPROCESS_FACTORY_CLASS
+E_TYPE_DATA_FACTORY
+e_subprocess_factory_get_type
+</SECTION>
+
+<SECTION>
 <FILE>e-data-server-util</FILE>
 <TITLE>Main Utility Toolbox</TITLE>
 e_get_user_cache_dir
@@ -2630,6 +2654,7 @@ EModuleClass
 e_module_new
 e_module_get_filename
 e_module_load_all_in_directory
+e_module_load_file
 ETypeFunc
 e_type_traverse
 <SUBSECTION Standard>
diff --git a/libebackend/Makefile.am b/libebackend/Makefile.am
index 49887c7..afc1ab5 100644
--- a/libebackend/Makefile.am
+++ b/libebackend/Makefile.am
@@ -73,6 +73,7 @@ libebackend_1_2_la_SOURCES = \
        e-soup-ssl-trust.c \
        e-source-registry-server.c \
        e-sqlite3-vfs.c \
+       e-subprocess-factory.c \
        e-user-prompter.c \
        e-user-prompter-server.c \
        e-user-prompter-server-extension.c \
@@ -121,6 +122,7 @@ libebackendinclude_HEADERS = \
        e-soup-ssl-trust.h \
        e-source-registry-server.h \
        e-sqlite3-vfs.h \
+       e-subprocess-factory.h \
        e-user-prompter.h \
        e-user-prompter-server.h \
        e-user-prompter-server-extension.h \
diff --git a/libebackend/e-backend-factory.c b/libebackend/e-backend-factory.c
index e70f58e..ec95d26 100644
--- a/libebackend/e-backend-factory.c
+++ b/libebackend/e-backend-factory.c
@@ -38,6 +38,7 @@
 #include <config.h>
 
 #include <libebackend/e-data-factory.h>
+#include "e-module.h"
 
 G_DEFINE_ABSTRACT_TYPE (EBackendFactory, e_backend_factory, E_TYPE_EXTENSION)
 
@@ -107,3 +108,51 @@ e_backend_factory_new_backend (EBackendFactory *factory,
 
        return class->new_backend (factory, source);
 }
+
+/**
+ * e_backend_factory_get_module_filename:
+ * @factory: an #EBackendFactory
+ *
+ * Returns the filename of the shared library for the module used
+ * to load the backends provided by @factory.
+ *
+ * Returns: the filename for the module associated to the @factory
+ *
+ * Since: 3.14
+ **/
+const gchar *
+e_backend_factory_get_module_filename (EBackendFactory *factory)
+{
+       EBackendFactoryClass *class;
+
+       g_return_val_if_fail (E_IS_BACKEND_FACTORY (factory), NULL);
+
+       class = E_BACKEND_FACTORY_GET_CLASS (factory);
+       g_return_val_if_fail (class->e_module != NULL, NULL);
+
+       return e_module_get_filename (class->e_module);
+}
+
+/**
+ * e_backend_factory_share_subprocess:
+ * @factory: an #EBackendFactory
+ *
+ * Returns TRUE if the @factory wants to share the subprocess
+ * for all backends provided by itself. Otherwise, returns FALSE.
+ *
+ * Returns: TRUE if the @factory shares the subprocess for all its
+ *          backends. Otherwise, FALSE.
+ *
+ * Since: 3.14
+ **/
+gboolean
+e_backend_factory_share_subprocess (EBackendFactory *factory)
+{
+       EBackendFactoryClass *class;
+
+       g_return_val_if_fail (E_IS_BACKEND_FACTORY (factory), FALSE);
+
+       class = E_BACKEND_FACTORY_GET_CLASS (factory);
+
+       return class->share_subprocess;
+}
diff --git a/libebackend/e-backend-factory.h b/libebackend/e-backend-factory.h
index 6af9702..6fa61ca 100644
--- a/libebackend/e-backend-factory.h
+++ b/libebackend/e-backend-factory.h
@@ -83,14 +83,22 @@ struct _EBackendFactoryClass {
        EBackend *      (*new_backend)          (EBackendFactory *factory,
                                                 ESource *source);
 
+       struct _EModule *e_module;
+       gboolean        share_subprocess;
+
        /*< private >*/
-       gpointer reserved[16];
+       gpointer reserved[15];
 };
 
 GType          e_backend_factory_get_type      (void) G_GNUC_CONST;
 const gchar *  e_backend_factory_get_hash_key  (EBackendFactory *factory);
 EBackend *     e_backend_factory_new_backend   (EBackendFactory *factory,
                                                 ESource *source);
+const gchar *  e_backend_factory_get_module_filename
+                                               (EBackendFactory *factory);
+gboolean       e_backend_factory_share_subprocess
+                                               (EBackendFactory *factory);
+
 
 G_END_DECLS
 
diff --git a/libebackend/e-collection-backend-factory.c b/libebackend/e-collection-backend-factory.c
index 41b1658..122f065 100644
--- a/libebackend/e-collection-backend-factory.c
+++ b/libebackend/e-collection-backend-factory.c
@@ -25,6 +25,8 @@
  * #ECollectionBackend instances.
  **/
 
+#include <string.h>
+
 #include "e-collection-backend-factory.h"
 
 #include <libedataserver/libedataserver.h>
@@ -51,11 +53,23 @@ static const gchar *
 collection_backend_factory_get_hash_key (EBackendFactory *factory)
 {
        ECollectionBackendFactoryClass *class;
+       const gchar *component_name;
+       gchar *hash_key;
+       gsize length;
 
        class = E_COLLECTION_BACKEND_FACTORY_GET_CLASS (factory);
        g_return_val_if_fail (class->factory_name != NULL, NULL);
 
-       return class->factory_name;
+       component_name = E_SOURCE_EXTENSION_COLLECTION;
+
+       /* Hash key: FACTORY ´:' COMPONENT_NAME */
+       length = strlen (class->factory_name) + strlen (component_name) + 2;
+       hash_key = g_alloca (length);
+       g_snprintf (
+               hash_key, length, "%s:%s",
+               class->factory_name, component_name);
+
+       return g_intern_string (hash_key);
 }
 
 static EBackend *
diff --git a/libebackend/e-data-factory.c b/libebackend/e-data-factory.c
index e57985a..3e2bdb2 100644
--- a/libebackend/e-data-factory.c
+++ b/libebackend/e-data-factory.c
@@ -30,27 +30,40 @@
 #include <libebackend/e-backend-factory.h>
 #include <libebackend/e-dbus-server.h>
 
+#include <e-dbus-subprocess-backend.h>
+
 #define E_DATA_FACTORY_GET_PRIVATE(obj) \
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_DATA_FACTORY, EDataFactoryPrivate))
 
+typedef enum {
+       DATA_FACTORY_SPAWN_SUBPROCESS_NONE = 0,
+       DATA_FACTORY_SPAWN_SUBPROCESS_BLOCKED,
+       DATA_FACTORY_SPAWN_SUBPROCESS_READY
+} DataFactorySpawnSubprocessStates;
+
 struct _EDataFactoryPrivate {
        ESourceRegistry *registry;
 
-       /* The mutex guards the 'backends' hash table.  The
-        * 'backend_factories' hash table doesn't really need
+       /* The mutex guards the 'subprocess_helpers' hash table.
+        * The 'backend_factories' hash table doesn't really need
         * guarding since it gets populated during construction
         * and is read-only thereafter. */
        GMutex mutex;
 
-       /* ESource UID -> GWeakRef (EBackend) */
-       GHashTable *backends;
+       /* Factory Name -> DataFactorySubprocessFactoryHelper */
+       GHashTable *subprocess_helpers;
+
+       /* Bus Name -> Watched Name */
+       GHashTable *subprocess_watched_ids;
+       GMutex subprocess_watched_ids_lock;
 
        /* Hash Key -> EBackendFactory */
        GHashTable *backend_factories;
 
        /* This is a hash table of client bus names to an array of
-        * EBackend references; one for every connection opened. */
+        * EDBusSubprocessBackend references; one for every connection
+        * opened. */
        GHashTable *connections;
        GRecMutex connections_lock;
 
@@ -58,11 +71,15 @@ struct _EDataFactoryPrivate {
         * The value is the watcher ID for g_bus_unwatch_name(). */
        GHashTable *watched_names;
        GMutex watched_names_lock;
-};
 
-enum {
-       BACKEND_CREATED,
-       LAST_SIGNAL
+       /* This is a GCond used to guarantee that in case of two
+        * instances of the same backend are created at the same
+        * time, the second instance will wait the first one be
+        * created and then will use that instance, instead of
+        * creating it twice. */
+       GCond spawn_subprocess_cond;
+       GMutex spawn_subprocess_lock;
+       DataFactorySpawnSubprocessStates spawn_subprocess_state;
 };
 
 enum {
@@ -70,8 +87,6 @@ enum {
        PROP_REGISTRY
 };
 
-static guint signals[LAST_SIGNAL];
-
 /* Forward Declarations */
 static void    e_data_factory_initable_init    (GInitableIface *iface);
 
@@ -83,97 +98,205 @@ G_DEFINE_TYPE_WITH_CODE (
                G_TYPE_INITABLE,
                e_data_factory_initable_init))
 
-static GWeakRef *
-data_factory_backends_lookup (EDataFactory *data_factory,
-                              const gchar *uid)
-{
-       GHashTable *backends;
-       GWeakRef *weak_ref;
+typedef struct _DataFactorySpawnSubprocessBackendThreadData DataFactorySpawnSubprocessBackendThreadData;
 
-       backends = data_factory->priv->backends;
-       weak_ref = g_hash_table_lookup (backends, uid);
+struct _DataFactorySpawnSubprocessBackendThreadData {
+       EDataFactory *data_factory;
+       GDBusMethodInvocation *invocation;
+       gchar *uid;
+       gchar *extension_name;
+       gchar *subprocess_path;
+};
 
-       if (weak_ref == NULL) {
-               weak_ref = e_weak_ref_new (NULL);
-               g_hash_table_insert (backends, g_strdup (uid), weak_ref);
-       }
+static DataFactorySpawnSubprocessBackendThreadData *
+data_factory_spawn_subprocess_backend_thread_data_new (EDataFactory *data_factory,
+                                                      GDBusMethodInvocation *invocation,
+                                                      const gchar *uid,
+                                                      const gchar *extension_name,
+                                                      const gchar *subprocess_path)
+{
+       DataFactorySpawnSubprocessBackendThreadData *data;
+
+       data = g_new0 (DataFactorySpawnSubprocessBackendThreadData, 1);
+       data->data_factory = g_object_ref (data_factory);
+       data->invocation = g_object_ref (invocation);
+       data->uid = g_strdup (uid);
+       data->extension_name = g_strdup (extension_name);
+       data->subprocess_path = g_strdup (subprocess_path);
 
-       return weak_ref;
+       return data;
 }
 
 static void
-watched_names_value_free (gpointer value)
+data_factory_spawn_subprocess_backend_thread_data_free (DataFactorySpawnSubprocessBackendThreadData *data)
 {
-       g_bus_unwatch_name (GPOINTER_TO_UINT (value));
+       if (data != NULL) {
+               g_clear_object (&data->data_factory);
+               g_clear_object (&data->invocation);
+               g_free (data->uid);
+               g_free (data->extension_name);
+               g_free (data->subprocess_path);
+
+               g_free (data);
+       }
+}
+
+typedef struct _DataFactorySubprocessHelper DataFactorySubprocessHelper;
+
+struct _DataFactorySubprocessHelper {
+       EDBusSubprocessBackend *proxy;
+       gchar *bus_name;
+};
+
+static DataFactorySubprocessHelper *
+data_factory_subprocess_helper_new (EDBusSubprocessBackend *proxy,
+                                   const gchar *bus_name)
+{
+       DataFactorySubprocessHelper *helper;
+
+       helper = g_new0 (DataFactorySubprocessHelper, 1);
+       helper->proxy = g_object_ref (proxy);
+       helper->bus_name = g_strdup (bus_name);
+
+       return helper;
 }
 
 static void
-data_factory_bus_acquired (EDBusServer *server,
-                          GDBusConnection *connection)
+data_factory_subprocess_helper_free (DataFactorySubprocessHelper *helper)
 {
-       GDBusInterfaceSkeleton *skeleton_interface;
-       EDataFactoryClass *class;
-       GError *error = NULL;
+       if (helper != NULL) {
+               g_clear_object (&helper->proxy);
+               g_free (helper->bus_name);
 
-       class = E_DATA_FACTORY_GET_CLASS (E_DATA_FACTORY (server));
+               g_free (helper);
+       }
+}
 
-       skeleton_interface = class->get_dbus_interface_skeleton (server);
+static gchar *
+data_factory_construct_subprocess_path (EDataFactory *data_factory)
+{
+       EDataFactoryClass *class;
+       static volatile gint counter = 1;
 
-       g_dbus_interface_skeleton_export (
-               skeleton_interface,
-               connection,
-               class->factory_object_path,
-               &error);
+       g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
 
-       if (error != NULL) {
-               g_warning ("%s: %s", G_STRFUNC, error->message);
-               e_dbus_server_quit (server, E_DBUS_SERVER_EXIT_NORMAL);
-               g_error_free (error);
+       g_atomic_int_inc (&counter);
 
-               return;
-       }
+       class = E_DATA_FACTORY_GET_CLASS (data_factory);
+       g_return_val_if_fail (class->subprocess_object_path_prefix != NULL, NULL);
 
-       /* Chain up to parent's bus_acquired() method. */
-       E_DBUS_SERVER_CLASS (e_data_factory_parent_class)->
-               bus_acquired (server, connection);
+       return g_strdup_printf (
+               "%s/%d/%u",
+               class->subprocess_object_path_prefix, getpid (), counter);
 }
 
-static void
-data_factory_connections_add (EDataFactory *data_factory,
-                             const gchar *name,
-                             EBackend *backend)
+static gchar *
+data_factory_construct_subprocess_bus_name (EDataFactory *data_factory)
 {
-       GHashTable *connections;
-       GPtrArray *array;
+       EDataFactoryClass *class;
+       static volatile gint counter = 1;
 
-       g_return_if_fail (name != NULL);
-       g_return_if_fail (backend != NULL);
+       g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
 
-       g_rec_mutex_lock (&data_factory->priv->connections_lock);
+       g_atomic_int_inc (&counter);
 
-       connections = data_factory->priv->connections;
+       class = E_DATA_FACTORY_GET_CLASS (data_factory);
+       g_return_val_if_fail (class->subprocess_bus_name_prefix != NULL, NULL);
+
+       /* We use the format "%sx%d%u" because we want to be really safe about
+        * the GDBus bus names used. When we create an object path we follow
+        * the same pattern %s/%d/%u, but bus names are quite more restrictive
+        * about its format, not allowing ".", "-", "/" or whatever that could
+        * be used in a more descriptive way. And that's the reason the "x" is
+        * being used here. */
+       return g_strdup_printf (
+               "%sx%dx%u",
+               class->subprocess_bus_name_prefix, getpid(), counter);
+}
 
-       if (g_hash_table_size (connections) == 0)
-               e_dbus_server_hold (E_DBUS_SERVER (data_factory));
+typedef struct _DataFactorySubprocessData DataFactorySubprocessData;
 
-       array = g_hash_table_lookup (connections, name);
+struct _DataFactorySubprocessData {
+       EDataFactory *data_factory;
+       GDBusMethodInvocation *invocation;
+       gchar *bus_name;
+       gchar *extension_name;
+       gchar *factory_name;
+       gchar *path;
+       gchar *type_name;
+       gchar *uid;
+       gchar *module_filename;
+       gchar *subprocess_helpers_hash_key;
+};
 
-       if (array == NULL) {
-               array = g_ptr_array_new_with_free_func (
-                       (GDestroyNotify) g_object_unref);
-               g_hash_table_insert (
-                       connections, g_strdup (name), array);
+static DataFactorySubprocessData *
+data_factory_subprocess_data_new (EDataFactory *data_factory,
+                                 GDBusMethodInvocation *invocation,
+                                 const gchar *uid,
+                                 const gchar *factory_name,
+                                 const gchar *type_name,
+                                 const gchar *extension_name,
+                                 const gchar *module_filename,
+                                 const gchar *subprocess_helpers_hash_key)
+{
+       DataFactorySubprocessData *sd;
+
+       sd = g_new0 (DataFactorySubprocessData, 1);
+       sd->data_factory = g_object_ref (data_factory);
+       sd->invocation = g_object_ref (invocation);
+       sd->uid = g_strdup (uid);
+       sd->factory_name = g_strdup (factory_name);
+       sd->type_name = g_strdup (type_name);
+       sd->extension_name = g_strdup (extension_name);
+       sd->module_filename = g_strdup (module_filename);
+       sd->subprocess_helpers_hash_key = g_strdup (subprocess_helpers_hash_key);
+       sd->path = data_factory_construct_subprocess_path (data_factory);
+       sd->bus_name = data_factory_construct_subprocess_bus_name (data_factory);
+
+       return sd;
+}
+
+static void
+data_factory_subprocess_data_free (DataFactorySubprocessData *sd)
+{
+       if (sd != NULL) {
+               g_clear_object (&sd->data_factory);
+               g_clear_object (&sd->invocation);
+               g_free (sd->uid);
+               g_free (sd->path);
+               g_free (sd->bus_name);
+               g_free (sd->type_name);
+               g_free (sd->factory_name);
+               g_free (sd->extension_name);
+               g_free (sd->module_filename);
+               g_free (sd->subprocess_helpers_hash_key);
+
+               g_free (sd);
        }
+}
 
-       g_ptr_array_add (array, g_object_ref (backend));
+static gchar *
+data_factory_dup_subprocess_helper_hash_key (const gchar *factory_name,
+                                            const gchar *extension_name,
+                                            const gchar *uid,
+                                            gboolean backend_factory_share_subprocess)
+{
+       gchar *helper_hash_key;
 
-       g_rec_mutex_unlock (&data_factory->priv->connections_lock);
+#ifdef ENABLE_BACKEND_PER_PROCESS
+       helper_hash_key = backend_factory_share_subprocess ?
+               g_strdup (factory_name) : g_strdup_printf ("%s:%s:%s", factory_name, extension_name, uid);
+#else
+       helper_hash_key = g_strdup ("not-using-bacend-per-process");
+#endif
+
+       return helper_hash_key;
 }
 
 static gboolean
-data_factory_verify_backend_is_used (EDataFactory *data_factory,
-                                    const gchar *except_bus_name,
-                                    EBackend *backend)
+data_factory_verify_subprocess_backend_proxy_is_used (EDataFactory *data_factory,
+                                                     const gchar *except_bus_name,
+                                                     EDBusSubprocessBackend *proxy)
 {
        GHashTable *connections;
        GList *names, *l;
@@ -191,16 +314,34 @@ data_factory_verify_backend_is_used (EDataFactory *data_factory,
                const gchar *client_bus_name = l->data;
                gint ii;
 
-               if (g_strcmp0 (client_bus_name, except_bus_name) == 0)
+               /* Check if we don't have more connections from the same client */
+               if (g_strcmp0 (client_bus_name, except_bus_name) == 0) {
+                       guint used = 0;
+                       array = g_hash_table_lookup (connections, client_bus_name);
+
+                       for (ii = 0; ii < array->len; ii++) {
+                               EDBusSubprocessBackend *proxy_in_use;
+
+                               proxy_in_use = g_ptr_array_index (array, ii);
+
+                               if (proxy == proxy_in_use)
+                                       used++;
+
+                               if (used > 1) {
+                                       is_used = TRUE;
+                                       break;
+                               }
+                       }
                        continue;
+               }
 
                array = g_hash_table_lookup (connections, client_bus_name);
                for (ii = 0; ii < array->len; ii++) {
-                       EBackend *backend_in_use;
+                       EDBusSubprocessBackend *proxy_in_use;
 
-                       backend_in_use = g_ptr_array_index (array, ii);
+                       proxy_in_use = g_ptr_array_index (array, ii);
 
-                       if (backend_in_use == backend) {
+                       if (proxy == proxy_in_use) {
                                is_used = TRUE;
                                break;
                        }
@@ -216,13 +357,13 @@ data_factory_verify_backend_is_used (EDataFactory *data_factory,
 static gboolean
 data_factory_connections_remove (EDataFactory *data_factory,
                                 const gchar *name,
-                                EBackend *backend)
+                                EDBusSubprocessBackend *proxy)
 {
        GHashTable *connections;
        GPtrArray *array;
        gboolean removed = FALSE;
 
-       /* If backend is NULL, we remove all backends for name. */
+       /* If proxy is NULL, we remove all proxies for name. */
        g_return_val_if_fail (name != NULL, FALSE);
 
        g_rec_mutex_lock (&data_factory->priv->connections_lock);
@@ -231,24 +372,30 @@ data_factory_connections_remove (EDataFactory *data_factory,
        array = g_hash_table_lookup (connections, name);
 
        if (array != NULL) {
-               if (backend != NULL) {
-                       if (!data_factory_verify_backend_is_used (data_factory, name, backend))
-                               e_backend_prepare_shutdown (backend);
+               if (proxy != NULL) {
+                       if (!data_factory_verify_subprocess_backend_proxy_is_used (data_factory, name, proxy))
+                               e_dbus_subprocess_backend_call_close_sync (proxy, NULL, NULL);
 
-                       removed = g_ptr_array_remove_fast (array, backend);
+                       removed = g_ptr_array_remove_fast (array, proxy);
                } else if (array->len > 0) {
-                       gint ii;
-
-                       for (ii = 0; ii < array->len; ii++) {
-                               EBackend *backend;
-
-                               backend = g_ptr_array_index (array, ii);
-
-                               if (!data_factory_verify_backend_is_used (data_factory, name, backend))
-                                       e_backend_prepare_shutdown (backend);
+                       /*
+                        * As we can have more than one proxy being used by the same name,
+                        * in the same array, we must remove the connections one by one
+                        * and then notify the subprocess to quit itself when it's the last
+                        * one being used. AKA: do *not* try to optimize this code to use
+                        * g_ptr_array_set_size (array, 0).
+                        */
+                       while (array->len != 0) {
+                               EDBusSubprocessBackend *proxy1;
+
+                               proxy1 = g_ptr_array_index (array, 0);
+
+                               if (!data_factory_verify_subprocess_backend_proxy_is_used (data_factory, 
name, proxy1))
+                                       e_dbus_subprocess_backend_call_close_sync (proxy1, NULL, NULL);
+
+                               g_ptr_array_remove_fast (array, proxy1);
                        }
 
-                       g_ptr_array_set_size (array, 0);
                        removed = TRUE;
                }
 
@@ -265,41 +412,6 @@ data_factory_connections_remove (EDataFactory *data_factory,
 }
 
 static void
-data_factory_connections_remove_all (EDataFactory *data_factory)
-{
-       GHashTable *connections;
-
-       g_rec_mutex_lock (&data_factory->priv->connections_lock);
-
-       connections = data_factory->priv->connections;
-
-       if (g_hash_table_size (connections) > 0) {
-               GSList *backends, *l;
-               backends = e_data_factory_list_backends (data_factory);
-
-               for (l = backends; l != NULL; l = g_slist_next (l)) {
-                       EBackend *backend = l->data;
-                       e_backend_prepare_shutdown (backend);
-               }
-
-               g_slist_free_full (backends, g_object_unref);
-
-               g_hash_table_remove_all (connections);
-               e_dbus_server_release (E_DBUS_SERVER (data_factory));
-       }
-
-       g_rec_mutex_unlock (&data_factory->priv->connections_lock);
-}
-
-static void
-data_factory_closed_cb (EBackend *backend,
-                        const gchar *sender,
-                        EDataFactory *data_factory)
-{
-       data_factory_connections_remove (data_factory, sender, backend);
-}
-
-static void
 data_factory_name_vanished_cb (GDBusConnection *connection,
                               const gchar *name,
                               gpointer user_data)
@@ -366,6 +478,288 @@ data_factory_watched_names_add (EDataFactory *data_factory,
 }
 
 static void
+data_factory_connections_add (EDataFactory *data_factory,
+                             const gchar *name,
+                             EDBusSubprocessBackend *proxy)
+{
+       GHashTable *connections;
+       GPtrArray *array;
+
+       g_return_if_fail (name != NULL);
+       g_return_if_fail (proxy != NULL);
+
+       g_rec_mutex_lock (&data_factory->priv->connections_lock);
+
+       connections = data_factory->priv->connections;
+
+       if (g_hash_table_size (connections) == 0)
+               e_dbus_server_hold (E_DBUS_SERVER (data_factory));
+
+       array = g_hash_table_lookup (connections, name);
+
+       if (array == NULL) {
+               array = g_ptr_array_new_with_free_func (
+                       (GDestroyNotify) g_object_unref);
+               g_hash_table_insert (
+                       connections, g_strdup (name), array);
+       }
+
+       g_ptr_array_add (array, g_object_ref (proxy));
+
+       g_rec_mutex_unlock (&data_factory->priv->connections_lock);
+}
+
+static void
+data_factory_call_subprocess_backend_create_sync (EDataFactory *data_factory,
+                                                 EDBusSubprocessBackend *proxy,
+                                                 GDBusMethodInvocation *invocation,
+                                                 const gchar *uid,
+                                                 const gchar *bus_name,
+                                                 const gchar *type_name,
+                                                 const gchar *extension_name,
+                                                 const gchar *module_filename)
+{
+       GError *error = NULL;
+       gchar *object_path = NULL;
+
+       e_dbus_subprocess_backend_call_create_sync (
+               proxy, uid, type_name, module_filename, &object_path, NULL, &error);
+
+       if (object_path != NULL) {
+               EDataFactoryClass *class;
+               GDBusConnection *connection;
+               const gchar *sender;
+
+               connection = g_dbus_method_invocation_get_connection (invocation);
+               sender = g_dbus_method_invocation_get_sender (invocation);
+
+               data_factory_watched_names_add (
+                       data_factory, connection, sender);
+
+               data_factory_connections_add (
+                       data_factory, sender, proxy);
+
+               class = E_DATA_FACTORY_GET_CLASS (data_factory);
+               g_return_if_fail (class->complete_open != NULL);
+
+               class->complete_open (data_factory, invocation, object_path, bus_name, extension_name);
+
+               g_free (object_path);
+       } else {
+               g_return_if_fail (error != NULL);
+               g_dbus_method_invocation_take_error (invocation, error);
+       }
+}
+
+static void
+data_factory_backend_closed_cb (EDBusSubprocessBackend *proxy,
+                               const gchar *sender,
+                               GWeakRef *factory_weak_ref)
+{
+       EDataFactory *data_factory;
+
+       data_factory = g_weak_ref_get (factory_weak_ref);
+       data_factory_connections_remove (data_factory, sender, proxy);
+       g_object_unref (data_factory);
+}
+
+static void
+data_factory_subprocess_appeared_cb (GDBusConnection *connection,
+                                    const gchar *name,
+                                    const gchar *name_owner,
+                                    gpointer user_data)
+{
+       EDBusSubprocessBackend *proxy;
+       EDataFactoryPrivate *priv;
+       DataFactorySubprocessData *sd;
+       DataFactorySubprocessHelper *helper;
+
+       sd = user_data;
+
+       proxy = e_dbus_subprocess_backend_proxy_new_sync (
+               connection,
+               G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+               sd->bus_name,
+               sd->path, NULL, NULL);
+
+       g_signal_connect_data (
+               proxy, "backend-closed",
+               G_CALLBACK (data_factory_backend_closed_cb),
+               e_weak_ref_new (sd->data_factory),
+               (GClosureNotify) e_weak_ref_free,
+               0);
+
+       data_factory_call_subprocess_backend_create_sync (
+               sd->data_factory,
+               proxy,
+               sd->invocation,
+               sd->uid,
+               sd->bus_name,
+               sd->type_name,
+               sd->extension_name,
+               sd->module_filename);
+
+       helper = data_factory_subprocess_helper_new (proxy, sd->bus_name);
+
+       priv = sd->data_factory->priv;
+       g_mutex_lock (&priv->mutex);
+       g_hash_table_insert (
+               priv->subprocess_helpers,
+               g_strdup (sd->subprocess_helpers_hash_key),
+               helper);
+       g_mutex_unlock (&priv->mutex);
+
+       g_mutex_lock (&priv->spawn_subprocess_lock);
+       priv->spawn_subprocess_state = DATA_FACTORY_SPAWN_SUBPROCESS_READY;
+       g_cond_signal (&priv->spawn_subprocess_cond);
+       g_mutex_unlock (&priv->spawn_subprocess_lock);
+
+       g_object_unref (proxy);
+}
+
+static void
+data_factory_subprocess_vanished_cb (GDBusConnection *connection,
+                                    const gchar *name,
+                                    gpointer user_data)
+{
+       DataFactorySubprocessData *sd;
+       DataFactorySubprocessHelper *helper;
+       EDataFactoryPrivate *priv;
+       const gchar *sender;
+       guint watched_id;
+
+       sd = user_data;
+       priv = sd->data_factory->priv;
+
+       g_mutex_lock (&priv->mutex);
+       helper = g_hash_table_lookup (
+               priv->subprocess_helpers,
+               sd->subprocess_helpers_hash_key);
+       g_mutex_unlock (&priv->mutex);
+
+       if (helper == NULL)
+               return;
+
+       sender = g_dbus_method_invocation_get_sender (sd->invocation);
+       data_factory_connections_remove (sd->data_factory, sender, helper->proxy);
+
+       g_mutex_lock (&priv->mutex);
+       g_hash_table_remove (
+               priv->subprocess_helpers,
+               sd->subprocess_helpers_hash_key);
+       g_mutex_unlock (&priv->mutex);
+
+       g_mutex_lock (&priv->subprocess_watched_ids_lock);
+       watched_id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->subprocess_watched_ids, sd->bus_name));
+       g_hash_table_remove (priv->subprocess_watched_ids, sd->bus_name);
+
+       if (watched_id > 0)
+               g_bus_unwatch_name (watched_id);
+       g_mutex_unlock (&priv->subprocess_watched_ids_lock);
+}
+
+static void
+watched_names_value_free (gpointer value)
+{
+       g_bus_unwatch_name (GPOINTER_TO_UINT (value));
+}
+
+static void
+data_factory_bus_acquired (EDBusServer *server,
+                          GDBusConnection *connection)
+{
+       GDBusInterfaceSkeleton *skeleton_interface;
+       EDataFactoryClass *class;
+       GError *error = NULL;
+
+       class = E_DATA_FACTORY_GET_CLASS (E_DATA_FACTORY (server));
+
+       skeleton_interface = class->get_dbus_interface_skeleton (server);
+
+       g_dbus_interface_skeleton_export (
+               skeleton_interface,
+               connection,
+               class->factory_object_path,
+               &error);
+
+       if (error != NULL) {
+               g_warning ("%s: %s", G_STRFUNC, error->message);
+               e_dbus_server_quit (server, E_DBUS_SERVER_EXIT_NORMAL);
+               g_error_free (error);
+
+               return;
+       }
+
+       /* Chain up to parent's bus_acquired() method. */
+       E_DBUS_SERVER_CLASS (e_data_factory_parent_class)->
+               bus_acquired (server, connection);
+}
+
+static GList *
+data_factory_list_proxies (EDataFactory *data_factory)
+{
+       GList *proxies = NULL;
+       GHashTable *connections;
+       GHashTable *proxies_hash;
+       GHashTableIter iter;
+       gpointer key, value;
+
+       g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
+
+       g_rec_mutex_lock (&data_factory->priv->connections_lock);
+
+       connections = data_factory->priv->connections;
+       proxies_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+       g_hash_table_iter_init (&iter, connections);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               GPtrArray *array = value;
+               gint ii;
+
+               for (ii = 0; ii < array->len; ii++) {
+                       EDBusSubprocessBackend *proxy = g_ptr_array_index (array, ii);
+                       if (!g_hash_table_contains (proxies_hash, proxy)) {
+                               g_hash_table_insert (proxies_hash, proxy, GINT_TO_POINTER (1));
+                               proxies = g_list_prepend (proxies, g_object_ref (proxy));
+                       }
+               }
+       }
+
+       g_hash_table_destroy (proxies_hash);
+       proxies = g_list_reverse (proxies);
+       g_rec_mutex_unlock (&data_factory->priv->connections_lock);
+
+       return proxies;
+}
+
+static void
+data_factory_connections_remove_all (EDataFactory *data_factory)
+{
+       GHashTable *connections;
+
+       g_rec_mutex_lock (&data_factory->priv->connections_lock);
+
+       connections = data_factory->priv->connections;
+
+       if (g_hash_table_size (connections) > 0) {
+               GList *proxies, *l;
+               proxies = data_factory_list_proxies (data_factory);
+
+               for (l = proxies; l != NULL; l = g_list_next (l)) {
+                       EDBusSubprocessBackend *proxy = l->data;
+                       e_dbus_subprocess_backend_call_close_sync (proxy, NULL, NULL);
+               }
+
+               g_list_free_full (proxies, g_object_unref);
+
+               g_hash_table_remove_all (connections);
+               e_dbus_server_release (E_DBUS_SERVER (data_factory));
+       }
+
+       g_rec_mutex_unlock (&data_factory->priv->connections_lock);
+}
+
+static void
 data_factory_bus_name_lost (EDBusServer *server,
                            GDBusConnection *connection)
 {
@@ -431,8 +825,9 @@ data_factory_dispose (GObject *object)
        data_factory = E_DATA_FACTORY (object);
        priv = data_factory->priv;
 
-       g_hash_table_remove_all (priv->backends);
        g_hash_table_remove_all (priv->backend_factories);
+       g_hash_table_remove_all (priv->subprocess_helpers);
+       g_hash_table_remove_all (priv->subprocess_watched_ids);
 
        g_clear_object (&priv->registry);
 
@@ -454,8 +849,11 @@ data_factory_finalize (GObject *object)
 
        g_mutex_clear (&priv->mutex);
 
-       g_hash_table_destroy (priv->backends);
        g_hash_table_destroy (priv->backend_factories);
+       g_hash_table_destroy (priv->subprocess_helpers);
+
+       g_hash_table_destroy (priv->subprocess_watched_ids);
+       g_mutex_clear (&priv->subprocess_watched_ids_lock);
 
        g_hash_table_destroy (priv->connections);
        g_rec_mutex_clear (&priv->connections_lock);
@@ -559,26 +957,6 @@ e_data_factory_class_init (EDataFactoryClass *class)
                        E_TYPE_SOURCE_REGISTRY,
                        G_PARAM_READABLE |
                        G_PARAM_STATIC_STRINGS));
-
-       /**
-        * EDataFactory::backend-created:
-        * @data_factory: the #EDataFactory which emitted the signal
-        * @backend: the newly-created #EBackend
-        *
-        * Emitted when a new #EBackend is instantiated by way of
-        * e_data_factory_ref_backend().  Extensions can connect to this
-        * signal to perform additional initialization on the #EBackend.
-        *
-        * Since: 3.8
-        **/
-       signals[BACKEND_CREATED] = g_signal_new (
-               "backend-created",
-               G_OBJECT_CLASS_TYPE (object_class),
-               G_SIGNAL_RUN_LAST,
-               G_STRUCT_OFFSET (EDataFactoryClass, backend_created),
-               NULL, NULL, NULL,
-               G_TYPE_NONE, 1,
-               E_TYPE_BACKEND);
 }
 
 static void
@@ -587,20 +965,28 @@ e_data_factory_init (EDataFactory *data_factory)
        data_factory->priv = E_DATA_FACTORY_GET_PRIVATE (data_factory);
 
        g_mutex_init (&data_factory->priv->mutex);
+       g_mutex_init (&data_factory->priv->subprocess_watched_ids_lock);
        g_rec_mutex_init (&data_factory->priv->connections_lock);
        g_mutex_init (&data_factory->priv->watched_names_lock);
+       g_mutex_init (&data_factory->priv->spawn_subprocess_lock);
 
-       data_factory->priv->backends = g_hash_table_new_full (
+       data_factory->priv->backend_factories = g_hash_table_new_full (
                (GHashFunc) g_str_hash,
                (GEqualFunc) g_str_equal,
                (GDestroyNotify) g_free,
-               (GDestroyNotify) e_weak_ref_free);
+               (GDestroyNotify) g_object_unref);
 
-       data_factory->priv->backend_factories = g_hash_table_new_full (
+       data_factory->priv->subprocess_helpers = g_hash_table_new_full (
                (GHashFunc) g_str_hash,
                (GEqualFunc) g_str_equal,
                (GDestroyNotify) g_free,
-               (GDestroyNotify) g_object_unref);
+               (GDestroyNotify) data_factory_subprocess_helper_free);
+
+       data_factory->priv->subprocess_watched_ids = g_hash_table_new_full (
+               (GHashFunc) g_str_hash,
+               (GEqualFunc) g_str_equal,
+               (GDestroyNotify) g_free,
+               (GDestroyNotify) NULL);
 
        data_factory->priv->connections = g_hash_table_new_full (
                (GHashFunc) g_str_hash,
@@ -613,148 +999,18 @@ e_data_factory_init (EDataFactory *data_factory)
                (GEqualFunc) g_str_equal,
                (GDestroyNotify) g_free,
                (GDestroyNotify) watched_names_value_free);
-}
-
-/**
- * e_data_factory_ref_backend:
- * @data_factory: an #EDataFactory
- * @hash_key: hash key for an #EBackendFactory
- * @source: an #ESource
- * @error: return location for a #GError, or %NULL
- *
- * Returns either a newly-created or existing #EBackend for #ESource.
- * The returned #EBackend is referenced for thread-safety and must be
- * unreferenced with g_object_unref() when finished with it.
- *
- * The @data_factory retains a weak reference to @backend so it can return
- * the same instance while @backend is in use.  When the last strong reference
- * to @backend is dropped, @data_factory will lose its weak reference and will
- * have to create a new #EBackend instance the next time the same @hash_key
- * and @source are requested.
- *
- * If no suitable #EBackendFactory exists, the function returns %NULL.
- *
- * Returns: an #EBackend for @source, or %NULL
- *
- * Since: 3.6
- **/
-EBackend *
-e_data_factory_ref_backend (EDataFactory *data_factory,
-                            const gchar *hash_key,
-                            ESource *source)
-{
-       return e_data_factory_ref_initable_backend (
-               data_factory, hash_key, source, NULL, NULL);
-}
-
-/**
- * e_data_factory_ref_initable_backend:
- * @data_factory: an #EDataFactory
- * @hash_key: hash key for an #EBackendFactory
- * @source: an #ESource
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Similar to e_data_factory_ref_backend(), but allows for backends that
- * implement the #GInitable interface so they can fail gracefully if they
- * are unable to initialize critical resources, such as a cache database.
- *
- * Returns either a newly-created or existing #EBackend for #ESource.
- * The returned #EBackend is referenced for thread-safety and must be
- * unreferenced with g_object_unref() when finished with it.
- *
- * If the newly-created backend implements the #GInitable interface, then
- * g_initable_init() is also called on it using @cancellable and @error.
- *
- * The @data_factory retains a weak reference to @backend so it can return
- * the same instance while @backend is in use.  When the last strong reference
- * to @backend is dropped, @data_factory will lose its weak reference and will
- * have to create a new #EBackend instance the next time the same @hash_key
- * and @source are requested.
- *
- * If no suitable #EBackendFactory exists, or if the #EBackend fails to
- * initialize, the function sets @error and returns %NULL.
- *
- * Returns: an #EBackend for @source, or %NULL
- *
- * Since: 3.8
- **/
-EBackend *
-e_data_factory_ref_initable_backend (EDataFactory *data_factory,
-                                     const gchar *hash_key,
-                                     ESource *source,
-                                     GCancellable *cancellable,
-                                     GError **error)
-{
-       EBackendFactory *backend_factory;
-       GWeakRef *weak_ref;
-       EBackend *backend;
-       const gchar *uid;
-
-       g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
-       g_return_val_if_fail (hash_key != NULL, NULL);
-       g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-
-       uid = e_source_get_uid (source);
-       g_return_val_if_fail (uid != NULL, NULL);
-
-       g_mutex_lock (&data_factory->priv->mutex);
-
-       /* The weak ref is already inserted in the hash table. */
-       weak_ref = data_factory_backends_lookup (data_factory, uid);
-
-       /* Check if we already have a backend for the given source. */
-       backend = g_weak_ref_get (weak_ref);
-
-       if (backend != NULL)
-               goto exit;
-
-       /* Find a suitable backend factory using the hash key. */
-       backend_factory =
-               e_data_factory_ref_backend_factory (data_factory, hash_key);
-
-       if (backend_factory == NULL) {
-               g_set_error (
-                       error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
-                       _("No backend factory for hash key '%s'"),
-                       hash_key);
-               goto exit;
-       }
 
-       /* Create a new backend for the given source and store it. */
-       backend = e_backend_factory_new_backend (backend_factory, source);
-
-       if (G_IS_INITABLE (backend)) {
-               GInitable *initable = G_INITABLE (backend);
-
-               if (!g_initable_init (initable, cancellable, error)) {
-                       g_object_unref (backend);
-                       backend = NULL;
-               }
-       }
-
-       /* This still does the right thing if backend is NULL. */
-       g_weak_ref_set (weak_ref, backend);
-
-       g_object_unref (backend_factory);
-
-       if (backend != NULL)
-               g_signal_emit (
-                       data_factory, signals[BACKEND_CREATED], 0, backend);
-
-exit:
-       g_mutex_unlock (&data_factory->priv->mutex);
-
-       return backend;
+       data_factory->priv->spawn_subprocess_state = DATA_FACTORY_SPAWN_SUBPROCESS_NONE;
 }
 
 /**
  * e_data_factory_ref_backend_factory:
  * @data_factory: an #EDataFactory
- * @hash_key: hash key for an #EBackendFactory
+ * @backend_name: a backend name
+ * @extension_name: an extension name
  *
- * Returns the #EBackendFactory for @hash_key, or %NULL if no such factory
- * is registered.
+ * Returns the #EBackendFactory for "@backend_name:@extension_name", or
+ * %NULL if no such factory is registered.
  *
  * The returned #EBackendFactory is referenced for thread-safety.
  * Unreference the #EBackendFactory with g_object_unref() when finished
@@ -766,13 +1022,16 @@ exit:
  **/
 EBackendFactory *
 e_data_factory_ref_backend_factory (EDataFactory *data_factory,
-                                    const gchar *hash_key)
+                                   const gchar *backend_name,
+                                   const gchar *extension_name)
 {
        GHashTable *backend_factories;
        EBackendFactory *backend_factory;
+       gchar *hash_key;
 
        g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
-       g_return_val_if_fail (hash_key != NULL, NULL);
+       g_return_val_if_fail (backend_name != NULL && *backend_name != '\0', NULL);
+       g_return_val_if_fail (extension_name != NULL && *extension_name != '\0', NULL);
 
        /* It should be safe to lookup backend factories without a mutex
         * because once initially populated the hash table remains fixed.
@@ -781,8 +1040,10 @@ e_data_factory_ref_backend_factory (EDataFactory *data_factory,
         *     to be referenced for thread-safety, but better to do it when
         *     not really needed than wish we had in the future. */
 
+       hash_key =  g_strdup_printf ("%s:%s", backend_name, extension_name);
        backend_factories = data_factory->priv->backend_factories;
        backend_factory = g_hash_table_lookup (backend_factories, hash_key);
+       g_free (hash_key);
 
        if (backend_factory != NULL)
                g_object_ref (backend_factory);
@@ -790,58 +1051,6 @@ e_data_factory_ref_backend_factory (EDataFactory *data_factory,
        return backend_factory;
 }
 
-static void
-data_factory_toggle_notify_cb (gpointer data,
-                              GObject *backend,
-                              gboolean is_last_ref)
-{
-       if (is_last_ref) {
-               /* Take a strong reference before removing the
-                * toggle reference, to keep the backend alive. */
-               g_object_ref (backend);
-
-               g_object_remove_toggle_ref (
-                       backend, data_factory_toggle_notify_cb, data);
-
-               g_signal_emit_by_name (backend, "shutdown");
-
-               g_object_unref (backend);
-       }
-}
-
-/**
- * e_data_factory_get_registry:
- * @data_factory: an #EDataFactory
- * @backend: an #EBackend
- *
- * Install a toggle reference on the backend, that can receive a signal to
- * shutdown once all client connections are closed.
- *
- * Since: 3.14
- **/
-void
-e_data_factory_set_backend_callbacks (EDataFactory *data_factory,
-                                     EBackend *backend)
-{
-       g_return_if_fail (E_IS_DATA_FACTORY (data_factory));
-       g_return_if_fail (data_factory != NULL);
-       g_return_if_fail (backend != NULL);
-
-       /* Install a toggle reference on the backend
-        * so we can signal it to shut down once all
-        * client connections are closed.
-        */
-       g_object_add_toggle_ref (
-               G_OBJECT (backend),
-               data_factory_toggle_notify_cb,
-               NULL);
-
-       g_signal_connect_object (
-               backend, "closed",
-               G_CALLBACK (data_factory_closed_cb),
-               data_factory, 0);
-}
-
 /**
  * e_data_factory_get_registry:
  * @data_factory: an #EDataFactory
@@ -861,201 +1070,224 @@ e_data_factory_get_registry (EDataFactory *data_factory)
 }
 
 /**
- * e_data_factory_list_backends:
+ * e_data_factory_construct_path:
  * @data_factory: an #EDataFactory
  *
- * Returns a list of backends connected to the @data_factory
+ * Returns a new and unique object path for a D-Bus interface based
+ * in the data object path prefix of the @data_factory
  *
- * Returns: a #GSList of backends connected to the @data_factory.
- *          The list should be freed using
- *          g_slist_free_full (backends, g_object_unref)
+ * Returns: a newly allocated string, representing the object path for
+ *          the D-Bus interface.
  *
  * Since: 3.14
  **/
-GSList *
-e_data_factory_list_backends (EDataFactory *data_factory)
+gchar *
+e_data_factory_construct_path (EDataFactory *data_factory)
 {
-       GSList *backends = NULL;
-       GHashTable *connections;
-       GHashTable *backends_hash;
-       GHashTableIter iter;
-       gpointer key, value;
+       EDataFactoryClass *class;
+       static volatile gint counter = 1;
 
        g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
 
-       g_rec_mutex_lock (&data_factory->priv->connections_lock);
-
-       connections = data_factory->priv->connections;
-       backends_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-       g_hash_table_iter_init (&iter, connections);
-       while (g_hash_table_iter_next (&iter, &key, &value)) {
-               GPtrArray *array = value;
-               gint ii;
-
-               for (ii = 0; ii < array->len; ii++) {
-                       EBackend *backend = g_ptr_array_index (array, ii);
-                       if (!g_hash_table_contains (backends_hash, backend)) {
-                               g_hash_table_insert (backends_hash, backend, GINT_TO_POINTER (1));
-                               backends = g_slist_prepend (backends, g_object_ref (backend));
-                       }
-               }
-       }
+       g_atomic_int_inc (&counter);
 
-       g_hash_table_destroy (backends_hash);
-       backends = g_slist_reverse (backends);
-       g_rec_mutex_unlock (&data_factory->priv->connections_lock);
+       class = E_DATA_FACTORY_GET_CLASS (data_factory);
+       g_return_val_if_fail (class->data_object_path_prefix != NULL, NULL);
 
-       return backends;
+       return g_strdup_printf (
+               "%s/%d/%u",
+               class->data_object_path_prefix, getpid (), counter);
 }
 
-static EBackend *
-data_factory_ref_backend (EDataFactory *data_factory,
-                         ESource *source,
-                         const gchar *extension_name,
-                         GError **error)
+static void
+data_factory_spawn_subprocess_backend (EDataFactory *data_factory,
+                                      GDBusMethodInvocation *invocation,
+                                      const gchar *uid,
+                                      const gchar *extension_name,
+                                      const gchar *subprocess_path)
 {
-       EBackend *backend;
+       DataFactorySubprocessHelper *helper;
+       DataFactorySubprocessData *sd;
+       EBackendFactory *backend_factory;
+       EDataFactoryClass *class;
+       ESource *source;
        ESourceBackend *extension;
+       EDataFactoryPrivate *priv;
+       GError *error = NULL;
+       GSubprocess *subprocess;
+       guint watched_id;
        gchar *backend_name;
-       gchar *hash_key = NULL;
+       gchar *subprocess_helpers_hash_key;
+       const gchar *factory_name;
+       const gchar *filename;
+       const gchar *type_name;
 
-       g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
+       g_return_if_fail (E_IS_DATA_FACTORY (data_factory));
+       g_return_if_fail (invocation != NULL);
+       g_return_if_fail (uid  != NULL && *uid != '\0');
+       g_return_if_fail (extension_name != NULL && *extension_name != '\0');
+       g_return_if_fail (subprocess_path != NULL && *subprocess_path != '\0');
+
+       priv = data_factory->priv;
 
+       source = e_source_registry_ref_source (priv->registry, uid);
        extension = e_source_get_extension (source, extension_name);
        backend_name = e_source_backend_dup_backend_name (extension);
+       g_object_unref (source);
+
+       backend_factory = e_data_factory_ref_backend_factory (
+               data_factory, backend_name, extension_name);
+
+       g_free (backend_name);
+
+       type_name = G_OBJECT_TYPE_NAME (backend_factory);
+
+       class = E_DATA_FACTORY_GET_CLASS (data_factory);
+       factory_name = class->get_factory_name (backend_factory);
 
-       if (backend_name == NULL || *backend_name == '\0') {
-               g_set_error (
-                       error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
-                       _("No backend name in source '%s'"),
-                       e_source_get_display_name (source));
-               g_free (backend_name);
-               return NULL;
+       subprocess_helpers_hash_key = data_factory_dup_subprocess_helper_hash_key (
+               factory_name, extension_name, uid, e_backend_factory_share_subprocess (backend_factory));
+
+       g_mutex_lock (&priv->mutex);
+       helper = g_hash_table_lookup (
+               priv->subprocess_helpers,
+               subprocess_helpers_hash_key);
+       g_mutex_unlock (&priv->mutex);
+
+       filename = e_backend_factory_get_module_filename (backend_factory);
+
+       if (helper != NULL) {
+               data_factory_call_subprocess_backend_create_sync (
+                       data_factory,
+                       helper->proxy,
+                       invocation,
+                       uid,
+                       helper->bus_name,
+                       type_name,
+                       extension_name,
+                       filename);
+
+               g_object_unref (backend_factory);
+               g_free (subprocess_helpers_hash_key);
+
+               return;
        }
 
-       hash_key = g_strdup_printf ("%s:%s", backend_name, extension_name);
+       g_mutex_lock (&priv->spawn_subprocess_lock);
+       if (priv->spawn_subprocess_state != DATA_FACTORY_SPAWN_SUBPROCESS_BLOCKED)
+               priv->spawn_subprocess_state = DATA_FACTORY_SPAWN_SUBPROCESS_BLOCKED;
+       g_mutex_unlock (&priv->spawn_subprocess_lock);
 
-       backend = e_data_factory_ref_initable_backend (
+       sd = data_factory_subprocess_data_new (
                data_factory,
-               hash_key,
-               source,
-               NULL,
-               error);
+               invocation,
+               uid,
+               factory_name,
+               type_name,
+               extension_name,
+               filename,
+               subprocess_helpers_hash_key);
 
-       g_free (hash_key);
-       g_free (backend_name);
+       g_object_unref (backend_factory);
+       g_free (subprocess_helpers_hash_key);
+
+       watched_id = g_bus_watch_name (
+               G_BUS_TYPE_SESSION,
+               sd->bus_name,
+               G_BUS_NAME_WATCHER_FLAGS_NONE,
+               data_factory_subprocess_appeared_cb,
+               data_factory_subprocess_vanished_cb,
+               sd,
+               (GDestroyNotify) data_factory_subprocess_data_free);
+
+       g_mutex_lock (&priv->subprocess_watched_ids_lock);
+       g_hash_table_insert (priv->subprocess_watched_ids, g_strdup (sd->bus_name), GUINT_TO_POINTER 
(watched_id));
+       g_mutex_unlock (&priv->subprocess_watched_ids_lock);
+
+       subprocess = g_subprocess_new (
+               G_SUBPROCESS_FLAGS_NONE,
+               &error,
+               subprocess_path,
+               "--bus-name", sd->bus_name,
+               "--own-path", sd->path,
+               NULL);
+
+       g_object_unref (subprocess);
 
-       return backend;
+       if (error != NULL) {
+               g_mutex_lock (&priv->subprocess_watched_ids_lock);
+               g_hash_table_remove (priv->subprocess_watched_ids, sd->bus_name);
+               g_mutex_unlock (&priv->subprocess_watched_ids_lock);
+
+               g_bus_unwatch_name (watched_id);
+               g_dbus_method_invocation_take_error (invocation, error);
+
+               g_mutex_lock (&priv->spawn_subprocess_lock);
+               priv->spawn_subprocess_state = DATA_FACTORY_SPAWN_SUBPROCESS_NONE;
+               g_cond_signal (&priv->spawn_subprocess_cond);
+               g_mutex_unlock (&priv->spawn_subprocess_lock);
+       }
 }
 
-/**
- * e_data_factory_construct_path:
- * @data_factory: an #EDataFactory
- *
- * Returns a new and unique object path for a D-Bus interface based
- * in the data object path prefix of the @data_factory
- *
- * Returns: a newly allocated string, representing the object path for
- *          the D-Bus interface.
- *
- * Since: 3.14
- **/
-gchar *
-e_data_factory_construct_path (EDataFactory *data_factory)
+static gpointer
+data_factory_spawn_subprocess_backend_in_thread (gpointer user_data)
 {
-       EDataFactoryClass *class;
-       static volatile gint counter = 1;
+       DataFactorySpawnSubprocessBackendThreadData *data = user_data;
+       EDataFactory *data_factory = data->data_factory;
+       GDBusMethodInvocation *invocation = data->invocation;
+       const gchar *uid = data->uid;
+       const gchar *extension_name = data->extension_name;
+       const gchar *subprocess_path = data->subprocess_path;
+
+       g_mutex_lock (&data_factory->priv->spawn_subprocess_lock);
+       while (data_factory->priv->spawn_subprocess_state == DATA_FACTORY_SPAWN_SUBPROCESS_BLOCKED) {
+               g_cond_wait (
+                       &data_factory->priv->spawn_subprocess_cond,
+                       &data_factory->priv->spawn_subprocess_lock);
+       }
 
-       g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
+       if (data_factory->priv->spawn_subprocess_state == DATA_FACTORY_SPAWN_SUBPROCESS_NONE)
+               data_factory->priv->spawn_subprocess_state = DATA_FACTORY_SPAWN_SUBPROCESS_BLOCKED;
+       g_mutex_unlock (&data_factory->priv->spawn_subprocess_lock);
 
-       g_atomic_int_inc (&counter);
+       data_factory_spawn_subprocess_backend (
+               data_factory, invocation, uid, extension_name, subprocess_path);
 
-       class = E_DATA_FACTORY_GET_CLASS (data_factory);
-       g_return_val_if_fail (class->data_object_path_prefix != NULL, NULL);
+       data_factory_spawn_subprocess_backend_thread_data_free (data);
 
-       return g_strdup_printf (
-               "%s/%d/%u",
-               class->data_object_path_prefix, getpid (), counter);
+       return NULL;
 }
 
 /**
- * e_data_factory_open_backend:
+ * e_data_factory_spawn_subprocess_backend:
  * @data_factory: an #EDataFactory
- * @connection: a #GDBusConnection
- * @sender: a string
- * @uid: UID of an #ESource to open
+ * @invocation: a #GDBusMethodInvcation
+ * @uid: an #ESource UID
  * @extension_name: an extension name
- * @error: return location for a #GError, or %NULL
+ * @subprocess_path: a path of an executable responsible for running the subprocess
  *
- * Returns the #EBackend data D-Bus object path
- *
- * Returns: a newly allocated string that represents the #EBackend
- *          data D-Bus object path.
+ * Spawns a new subprocess for a backend type and returns the object path
+ * of the new subprocess to the client, in the way the client can talk
+ * directly to the running backend. If the backend already has a subprocess
+ * running, the used object path is returned to the client.
  *
  * Since: 3.14
  **/
-gchar *
-e_data_factory_open_backend (EDataFactory *data_factory,
-                            GDBusConnection *connection,
-                            const gchar *sender,
-                            const gchar *uid,
-                            const gchar *extension_name,
-                            GError **error)
+void
+e_data_factory_spawn_subprocess_backend (EDataFactory *data_factory,
+                                        GDBusMethodInvocation *invocation,
+                                        const gchar *uid,
+                                        const gchar *extension_name,
+                                        const gchar *subprocess_path)
 {
-       EDataFactoryClass *class;
-       EBackend *backend;
-       ESourceRegistry *registry;
-       ESource *source;
-       gchar *object_path;
-
-       g_return_val_if_fail (E_IS_DATA_FACTORY (data_factory), NULL);
-
-       if (uid == NULL || *uid == '\0') {
-               g_set_error (
-                       error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
-                       _("Missing source UID"));
-               return NULL;
-       }
-
-       registry = e_data_factory_get_registry (data_factory);
-       source = e_source_registry_ref_source (registry, uid);
-
-       if (source == NULL) {
-               g_set_error (
-                       error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
-                       _("No such source for UID '%s'"), uid);
-               return NULL;
-       }
+       GThread *thread;
+       DataFactorySpawnSubprocessBackendThreadData *data;
 
-       backend = data_factory_ref_backend (
-               data_factory, source, extension_name, error);
-
-       g_object_unref (source);
-
-       if (backend == NULL)
-               return NULL;
-
-       class = E_DATA_FACTORY_GET_CLASS (data_factory);
-       object_path = class->data_open (
-               data_factory, backend, connection, error);
-
-       if (object_path != NULL) {
-               /* Watch the sender's bus name so we can clean
-                * up its connections if the bus name vanishes.
-                */
-               data_factory_watched_names_add (
-                       data_factory, connection, sender);
-
-               /* A client my create multiple Eclient instances for the
-                * same ESource, each of which calls close() individually.
-                * So we must track each and every connection made.
-                */
-               data_factory_connections_add (
-                       data_factory, sender, backend);
-       }
+       data = data_factory_spawn_subprocess_backend_thread_data_new (
+               data_factory, invocation, uid, extension_name, subprocess_path);
 
-       g_clear_object (&backend);
+       thread = g_thread_new ("Spawn-Subprocess-Backend",
+               data_factory_spawn_subprocess_backend_in_thread, data);
 
-       return object_path;
+       g_thread_unref (thread);
 }
diff --git a/libebackend/e-data-factory.h b/libebackend/e-data-factory.h
index daece1b..08faaa5 100644
--- a/libebackend/e-data-factory.h
+++ b/libebackend/e-data-factory.h
@@ -70,51 +70,38 @@ struct _EDataFactoryClass {
 
        const gchar *factory_object_path;
        const gchar *data_object_path_prefix;
-
-       /* Signals */
-       void            (*backend_created)      (EDataFactory *data_factory,
-                                                EBackend *backend);
+       const gchar *subprocess_object_path_prefix;
+       const gchar *subprocess_bus_name_prefix;
 
        /* Virtual methods */
        GDBusInterfaceSkeleton *
                        (*get_dbus_interface_skeleton)
                                                (EDBusServer *server);
-
-       gchar *         (*data_open)            (EDataFactory *data_factory,
-                                                EBackend *backend,
-                                                GDBusConnection *connection,
-                                                GError **error);
+       const gchar *   (*get_factory_name)     (EBackendFactory *backend_factory);
+       void            (*complete_open)        (EDataFactory *data_factory,
+                                                GDBusMethodInvocation *invocation,
+                                                const gchar *object_path,
+                                                const gchar *bus_name,
+                                                const gchar *extension_name);
 
        gpointer reserved[15];
 };
 
 GType          e_data_factory_get_type         (void) G_GNUC_CONST;
-EBackend *     e_data_factory_ref_backend      (EDataFactory *data_factory,
-                                                const gchar *hash_key,
-                                                ESource *source);
-EBackend *     e_data_factory_ref_initable_backend
-                                               (EDataFactory *data_factory,
-                                                const gchar *hash_key,
-                                                ESource *source,
-                                                GCancellable *cancellable,
-                                                GError **error);
 EBackendFactory *
                e_data_factory_ref_backend_factory
                                                (EDataFactory *data_factory,
-                                                const gchar *hash_key);
+                                                const gchar *backend_name,
+                                                const gchar *extension_name);
 ESourceRegistry *
                e_data_factory_get_registry     (EDataFactory *data_factory);
-GSList *       e_data_factory_list_backends    (EDataFactory *data_factory);
-gchar *                e_data_factory_open_backend     (EDataFactory *data_factory,
-                                                GDBusConnection *connection,
-                                                const gchar *sender,
-                                                const gchar *uid,
-                                                const gchar *extension_name,
-                                                GError **error);
 gchar *                e_data_factory_construct_path   (EDataFactory *data_factory);
-void           e_data_factory_set_backend_callbacks
+void           e_data_factory_spawn_subprocess_backend
                                                (EDataFactory *data_factory,
-                                                EBackend *backend);
+                                                GDBusMethodInvocation *invocation,
+                                                const gchar *uid,
+                                                const gchar *extension_name,
+                                                const gchar *subprocess_path);
 
 G_END_DECLS
 
diff --git a/libebackend/e-module.c b/libebackend/e-module.c
index 54290d9..c5c81f2 100644
--- a/libebackend/e-module.c
+++ b/libebackend/e-module.c
@@ -302,18 +302,12 @@ e_module_load_all_in_directory (const gchar *dirname)
 
                filename = g_build_filename (dirname, basename, NULL);
 
-               module = e_module_new (filename);
-
-               if (!g_type_module_use (G_TYPE_MODULE (module))) {
-                       g_printerr ("Failed to load module: %s\n", filename);
-                       g_object_unref (module);
-                       g_free (filename);
-                       continue;
-               }
+               module = e_module_load_file (filename);
 
                g_free (filename);
 
-               loaded_modules = g_list_prepend (loaded_modules, module);
+               if (module != NULL)
+                       loaded_modules = g_list_prepend (loaded_modules, module);
        }
 
        g_dir_close (dir);
@@ -322,6 +316,33 @@ e_module_load_all_in_directory (const gchar *dirname)
 }
 
 /**
+ * e_module_load_file:
+ * @dirname: filename of the module to load
+ *
+ * Load the module from the specified filename into memory. If
+ * you want to unload it (enabling on-demand loading) you must call
+ * g_type_module_unuse() on the module.
+ *
+ * Returns: an #EModule loaded from @filename
+ *
+ * Since: 3.14
+ **/
+EModule *
+e_module_load_file (const gchar *filename)
+{
+       EModule *module;
+
+       module = e_module_new (filename);
+
+       if (!g_type_module_use (G_TYPE_MODULE (module))) {
+               g_printerr ("Failed to load module: %s\n", filename);
+               g_clear_object (&module);
+       }
+
+       return module;
+}
+
+/**
  * e_type_traverse:
  * @parent_type: the root #GType to traverse from
  * @func: the function to call for each visited #GType
diff --git a/libebackend/e-module.h b/libebackend/e-module.h
index 9878764..af6471e 100644
--- a/libebackend/e-module.h
+++ b/libebackend/e-module.h
@@ -70,6 +70,7 @@ struct _EModuleClass {
 GType          e_module_get_type               (void) G_GNUC_CONST;
 EModule *      e_module_new                    (const gchar *filename);
 const gchar *  e_module_get_filename           (EModule *module);
+EModule *      e_module_load_file              (const gchar *filename);
 GList *                e_module_load_all_in_directory  (const gchar *dirname);
 
 /* This is here for lack of a better place for it. */
diff --git a/libebackend/e-source-registry-server.c b/libebackend/e-source-registry-server.c
index abd9333..2e72304 100644
--- a/libebackend/e-source-registry-server.c
+++ b/libebackend/e-source-registry-server.c
@@ -1146,9 +1146,11 @@ source_registry_server_source_added (ESourceRegistryServer *server,
 
        extension_name = E_SOURCE_EXTENSION_COLLECTION;
        if (e_source_has_extension (source, extension_name)) {
-               EBackend *backend;
+               EBackend *backend = NULL;
+               ECollectionBackendFactory *backend_factory;
                ESourceBackend *extension;
                const gchar *backend_name;
+               GError *error = NULL;
 
                extension = e_source_get_extension (source, extension_name);
                backend_name = e_source_backend_get_backend_name (extension);
@@ -1157,8 +1159,18 @@ source_registry_server_source_added (ESourceRegistryServer *server,
                 * itself, which creates a reference cycle.  The cycle is
                 * explicitly broken when the ESource is removed from the
                 * 'sources' hash table (see unref_data_source() above). */
-               backend = e_data_factory_ref_backend (
-                       E_DATA_FACTORY (server), backend_name, source);
+               backend_factory = e_source_registry_server_ref_backend_factory (server, source);
+               backend = e_backend_factory_new_backend (E_BACKEND_FACTORY (backend_factory), source);
+
+               if (G_IS_INITABLE (backend)) {
+                       GInitable *initable = G_INITABLE (backend);
+
+                       if (!g_initable_init (initable, NULL, &error))
+                               g_clear_object (&backend);
+               }
+
+               g_object_unref (backend_factory);
+
                if (backend != NULL) {
                        g_object_set_data_full (
                                G_OBJECT (source),
@@ -1166,8 +1178,10 @@ source_registry_server_source_added (ESourceRegistryServer *server,
                                (GDestroyNotify) g_object_unref);
                } else {
                        g_warning (
-                               "No collection backend '%s' for %s",
-                               backend_name, e_source_get_uid (source));
+                               "No collection backend '%s' for %s: %s",
+                               backend_name, e_source_get_uid (source), error->message);
+
+                       g_clear_error (&error);
                }
        }
 
@@ -2296,7 +2310,7 @@ e_source_registry_server_ref_backend_factory (ESourceRegistryServer *server,
        backend_name = e_source_backend_get_backend_name (extension);
 
        factory = e_data_factory_ref_backend_factory (
-               E_DATA_FACTORY (server), backend_name);
+               E_DATA_FACTORY (server), backend_name, extension_name);
 
        if (factory == NULL)
                return NULL;
diff --git a/libebackend/e-subprocess-factory.c b/libebackend/e-subprocess-factory.c
new file mode 100644
index 0000000..1fbca51
--- /dev/null
+++ b/libebackend/e-subprocess-factory.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Fabiano Fidêncio <fidencio redhat com>
+ */
+
+/**
+ * SECTION: e-subprocess-factory
+ * @include: libebackend/libebackend.h
+ * @short_description: An abstract base class for a backend-subprocess server
+ **/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+#include <libebackend/e-backend-factory.h>
+#include <libebackend/e-module.h>
+
+#include <e-dbus-subprocess-backend.h>
+
+#include "e-subprocess-factory.h"
+
+#define E_SUBPROCESS_FACTORY_GET_PRIVATE(obj) \
+       (G_TYPE_INSTANCE_GET_PRIVATE \
+       ((obj), E_TYPE_SUBPROCESS_FACTORY, ESubprocessFactoryPrivate))
+
+struct _ESubprocessFactoryPrivate {
+       ESourceRegistry *registry;
+
+       /*
+        * As backends and modules HashTables are used basically
+        * in the same places, we use the same mutex to guard
+        * both of them.
+        */
+       GMutex mutex;
+
+       /* ESource UID -> EBackend */
+       GHashTable *backends;
+       /* Module filename -> EModule */
+       GHashTable *modules;
+};
+
+enum {
+       PROP_0,
+       PROP_REGISTRY,
+};
+
+/* Forward Declarations */
+static void    e_subprocess_factory_initable_init              (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (
+       ESubprocessFactory,
+       e_subprocess_factory,
+       G_TYPE_OBJECT,
+       G_IMPLEMENT_INTERFACE (
+               G_TYPE_INITABLE,
+               e_subprocess_factory_initable_init))
+
+static void
+subprocess_factory_toggle_notify_cb (gpointer data,
+                                    GObject *backend,
+                                    gboolean is_last_ref)
+{
+       if (is_last_ref) {
+               g_object_ref (backend);
+
+               g_object_remove_toggle_ref (
+                       backend, subprocess_factory_toggle_notify_cb, data);
+
+               g_signal_emit_by_name (backend, "shutdown");
+
+               g_object_unref (backend);
+       }
+}
+
+static void
+subprocess_factory_closed_cb (EBackend *backend,
+                             const gchar *sender,
+                             EDBusSubprocessBackend *proxy)
+{
+       e_dbus_subprocess_backend_emit_backend_closed (proxy, sender);
+}
+
+static void
+e_subprocess_factory_get_property (GObject *object,
+                                  guint property_id,
+                                  GValue *value,
+                                  GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_REGISTRY:
+                       g_value_set_object (
+                               value,
+                               e_subprocess_factory_get_registry (
+                               E_SUBPROCESS_FACTORY (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+subprocess_factory_dispose (GObject *object)
+{
+       ESubprocessFactory *subprocess_factory;
+       ESubprocessFactoryPrivate *priv;
+
+       subprocess_factory = E_SUBPROCESS_FACTORY (object);
+       priv = subprocess_factory->priv;
+
+       g_hash_table_remove_all (priv->backends);
+       g_hash_table_remove_all (priv->modules);
+       g_clear_object (&priv->registry);
+
+       /* Chain up to parent's dispose() method */
+       G_OBJECT_CLASS (e_subprocess_factory_parent_class)->dispose (object);
+}
+
+static void
+subprocess_factory_finalize (GObject *object)
+{
+       ESubprocessFactory *subprocess_factory;
+       ESubprocessFactoryPrivate *priv;
+
+       subprocess_factory = E_SUBPROCESS_FACTORY (object);
+       priv = subprocess_factory->priv;
+
+       g_mutex_clear (&priv->mutex);
+
+       g_hash_table_destroy (priv->backends);
+       g_hash_table_destroy (priv->modules);
+
+       /* Chain up to parent's finalize() method */
+       G_OBJECT_CLASS (e_subprocess_factory_parent_class)->finalize (object);
+}
+
+static gboolean
+subprocess_factory_initable_init (GInitable *initable,
+                                 GCancellable *cancellable,
+                                 GError **error)
+{
+       ESubprocessFactory *subprocess_factory;
+
+       subprocess_factory = E_SUBPROCESS_FACTORY (initable);
+
+       subprocess_factory->priv->registry = e_source_registry_new_sync (
+               cancellable, error);
+
+       return (subprocess_factory->priv->registry != NULL);
+}
+
+static void
+e_subprocess_factory_initable_init (GInitableIface *iface)
+{
+       iface->init = subprocess_factory_initable_init;
+}
+
+static void
+e_subprocess_factory_class_init (ESubprocessFactoryClass *class)
+{
+       GObjectClass *object_class;
+
+       g_type_class_add_private (class, sizeof (ESubprocessFactoryPrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->get_property = e_subprocess_factory_get_property;
+       object_class->dispose = subprocess_factory_dispose;
+       object_class->finalize = subprocess_factory_finalize;
+
+       g_object_class_install_property (
+               object_class,
+               PROP_REGISTRY,
+               g_param_spec_object (
+                       "registry",
+                       "Registry",
+                       "Data source registry",
+                       E_TYPE_SOURCE_REGISTRY,
+                       G_PARAM_READABLE |
+                       G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_subprocess_factory_init (ESubprocessFactory *subprocess_factory)
+{
+       subprocess_factory->priv = E_SUBPROCESS_FACTORY_GET_PRIVATE (subprocess_factory);
+
+       g_mutex_init (&subprocess_factory->priv->mutex);
+
+       subprocess_factory->priv->backends = g_hash_table_new_full (
+               (GHashFunc) g_str_hash,
+               (GEqualFunc) g_str_equal,
+               (GDestroyNotify) g_free,
+               (GDestroyNotify) g_object_unref);
+
+       subprocess_factory->priv->modules = g_hash_table_new_full (
+               (GHashFunc) g_str_hash,
+               (GEqualFunc) g_str_equal,
+               (GDestroyNotify) g_free,
+               (GDestroyNotify) g_type_module_unuse);
+}
+
+/**
+ * e_subprocess_factory_ref_initable_backend:
+ * @subprocess_factory: an #ESubprocessFactory
+ * @uid: UID of an #ESource to open
+ * @backend_factory_type_name: the name of the backend factory type
+ * @module_filename: the name (full-path) of the backend module to be loaded
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Returns either a newly-created or existing #EBackend for #ESource.
+ * The returned #EBackend is referenced for thread-safety and must be
+ * unreferenced with g_object_unref() when finished with it.
+ *
+ * If the newly-created backend implements the #GInitable interface, then
+ * g_initable_init() is also called on it using @cancellable and @error.
+ *
+ * The @subprocess_factory retains a strong reference to @backend.
+ *
+ * If no suitable #EBackendFactory exists, or if the #EBackend fails to
+ * initialize, the function sets @error and returns %NULL.
+ *
+ * Returns: an #EBackend for @source, or %NULL
+ *
+ * Since: 3.14
+ **/
+EBackend *
+e_subprocess_factory_ref_initable_backend (ESubprocessFactory *subprocess_factory,
+                                          const gchar *uid,
+                                          const gchar *backend_factory_type_name,
+                                          const gchar *module_filename,
+                                          GCancellable *cancellable,
+                                          GError **error)
+{
+       EBackend *backend;
+       EModule *module;
+       ESource *source;
+       ESourceRegistry *registry;
+       ESubprocessFactoryPrivate *priv;
+       ESubprocessFactoryClass *class;
+
+       g_return_val_if_fail (E_IS_SUBPROCESS_FACTORY (subprocess_factory), NULL);
+       g_return_val_if_fail (uid != NULL && *uid != '\0', NULL);
+       g_return_val_if_fail (backend_factory_type_name != NULL && *backend_factory_type_name != '\0', NULL);
+       g_return_val_if_fail (module_filename != NULL && *module_filename != '\0', NULL);
+
+       priv = subprocess_factory->priv;
+
+       g_mutex_lock (&priv->mutex);
+
+       backend = g_hash_table_lookup (priv->backends, uid);
+       if (backend != NULL) {
+               g_object_ref (backend);
+
+               goto exit;
+       }
+
+       module = g_hash_table_lookup (priv->modules, module_filename);
+       if (module == NULL) {
+               module = e_module_load_file (module_filename);
+               g_hash_table_insert (priv->modules, g_strdup (module_filename), module);
+       }
+
+       registry = e_subprocess_factory_get_registry (subprocess_factory);
+       source = e_source_registry_ref_source (registry, uid);
+       if (source == NULL) {
+               g_set_error (
+                       error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+                       _("No such source for UID '%s'"), uid);
+               goto exit;
+       }
+
+       class = E_SUBPROCESS_FACTORY_GET_CLASS (subprocess_factory);
+
+       backend = class->ref_backend (
+               registry, source, backend_factory_type_name);
+
+       if (backend == NULL)
+               goto exit;
+
+       if (G_IS_INITABLE (backend)) {
+               GInitable *initable = G_INITABLE (backend);
+
+               if (!g_initable_init (initable, cancellable, error))
+                       g_clear_object (&backend);
+       }
+
+       if (backend != NULL)
+               g_hash_table_insert (priv->backends, g_strdup (uid), g_object_ref (backend));
+
+exit:
+       g_mutex_unlock (&priv->mutex);
+       return backend;
+}
+
+/**
+ * e_subprocess_factory_get_registry:
+ * @subprocess_factory: an #ESubprocessFactory
+ *
+ * Returns the #ESourceRegistry owned by @subprocess_factory.
+ *
+ * Returns: the #ESourceRegistry
+ *
+ * Since: 3.14
+ **/
+ESourceRegistry *
+e_subprocess_factory_get_registry (ESubprocessFactory *subprocess_factory)
+{
+       g_return_val_if_fail (E_IS_SUBPROCESS_FACTORY (subprocess_factory), NULL);
+
+       return subprocess_factory->priv->registry;
+}
+
+/**
+ * e_subprocess_factory_construct_path:
+ *
+ * Returns a new and unique object path for a D-Bus interface based
+ * in the data object path prefix of the @subprocess_factory
+ *
+ * Returns: a newly allocated string, representing the object path for
+ *          the D-Bus interface.
+ *
+ * This function is here for a lack of a better place
+ *
+ * Since: 3.14
+ **/
+gchar *
+e_subprocess_factory_construct_path (void)
+{
+       static volatile gint counter = 1;
+
+       g_atomic_int_inc (&counter);
+
+       return g_strdup_printf (
+               "/org/gnome/evolution/dataserver/Subprocess/%d/%u", getpid (), counter);
+}
+
+/**
+ * e_subprocess_factory_open_backend:
+ * @subprocess_factory: an #ESubprocessFactory
+ * @connection: a #GDBusConnection
+ * @uid: UID of an #ESource to open
+ * @backend_factory_type_name: the name of the backend factory type
+ * @module_filename: the name (full-path) of the backend module to be loaded
+ * @proxy: a #GDBusInterfaceSkeleton, used to communicate to the subprocess backend
+ * @cancellable: a #GCancellable
+ * @error: return location for a #GError, or %NULL
+ *
+ * Returns the #EBackend data D-Bus object path
+ *
+ * Returns: a newly allocated string that represents the #EBackend
+ *          data D-Bus object path.
+ *
+ * Since: 3.14
+ **/
+gchar *
+e_subprocess_factory_open_backend (ESubprocessFactory *subprocess_factory,
+                                  GDBusConnection *connection,
+                                  const gchar *uid,
+                                  const gchar *backend_factory_type_name,
+                                  const gchar *module_filename,
+                                  GDBusInterfaceSkeleton *proxy,
+                                  GCancellable *cancellable,
+                                  GError **error)
+{
+       ESubprocessFactoryClass *class;
+       EBackend *backend;
+       gchar *object_path = NULL;
+
+       g_return_val_if_fail (E_IS_SUBPROCESS_FACTORY (subprocess_factory), NULL);
+       g_return_val_if_fail (connection != NULL, NULL);
+       g_return_val_if_fail (uid != NULL && *uid != '\0', NULL);
+       g_return_val_if_fail (backend_factory_type_name != NULL && *backend_factory_type_name != '\0', NULL);
+       g_return_val_if_fail (module_filename != NULL && *module_filename != '\0', NULL);
+       g_return_val_if_fail (E_DBUS_SUBPROCESS_IS_BACKEND (proxy), NULL);
+
+       backend = e_subprocess_factory_ref_initable_backend (
+               subprocess_factory, uid, backend_factory_type_name, module_filename, cancellable, error);
+
+       if (backend == NULL)
+               return NULL;
+
+       class = E_SUBPROCESS_FACTORY_GET_CLASS (subprocess_factory);
+       object_path = class->open_data (
+               subprocess_factory, backend, connection, proxy, cancellable, error);
+
+       g_clear_object (&backend);
+
+       return object_path;
+}
+
+/**
+ * e_subprocess_factory_get_backends_list:
+ * @subprocess_factory: an #ESubprocessFactory
+ *
+ * Returns a list of used backends.
+ *
+ * Returns: A #GList that contains a list of used backends. The list should be freed
+ * by the caller using: g_list_free_full (backends, g_object_unref).
+ *
+ * Since: 3.14
+ **/
+GList *
+e_subprocess_factory_get_backends_list (ESubprocessFactory *subprocess_factory)
+{
+       GList *backends;
+       ESubprocessFactoryPrivate *priv;
+
+       g_return_val_if_fail (E_IS_SUBPROCESS_FACTORY (subprocess_factory), NULL);
+
+       priv = subprocess_factory->priv;
+
+       g_mutex_lock (&priv->mutex);
+       backends = g_hash_table_get_values (subprocess_factory->priv->backends);
+       g_list_foreach (backends, (GFunc) g_object_ref, NULL);
+       g_mutex_unlock (&priv->mutex);
+
+       return backends;
+}
+
+/**
+ * e_subprocess_factory_call_backends_prepare_shutdown:
+ * @subprocess_factory: an #ESubprocessFactory
+ *
+ * Calls e_backend_prepare_shutdown() for the list of used backends.
+ *
+ * Since: 3.14
+ */
+void
+e_subprocess_factory_call_backends_prepare_shutdown (ESubprocessFactory *subprocess_factory)
+{
+       GList *backends, *l;
+
+       g_return_if_fail (E_IS_SUBPROCESS_FACTORY (subprocess_factory));
+
+       backends = e_subprocess_factory_get_backends_list (subprocess_factory);
+
+       for (l = backends; l != NULL; l = g_list_next (l)) {
+               EBackend *backend = l->data;
+
+               e_backend_prepare_shutdown (backend);
+       }
+
+       g_list_free_full (backends, g_object_unref);
+}
+
+/**
+ * e_subprocess_factory_set_backend_callbacks:
+ * @subprocess_factory: an #ESubprocessFactory
+ * @backend: an #EBackend
+ * @proxy: a #GDBusInterfaceSkeleton, used to communicate to the subprocess backend
+ *
+ * Installs a toggle reference on the backend, that can receive a signal to
+ * shutdown once all client connections are closed.
+ *
+ * Since: 3.14
+ **/
+void
+e_subprocess_factory_set_backend_callbacks (ESubprocessFactory *subprocess_factory,
+                                           EBackend *backend,
+                                           GDBusInterfaceSkeleton *proxy)
+{
+       g_return_if_fail (E_IS_SUBPROCESS_FACTORY (subprocess_factory));
+       g_return_if_fail (backend != NULL);
+       g_return_if_fail (E_DBUS_SUBPROCESS_IS_BACKEND (proxy));
+
+       /**
+        * Install a toggle reference on the backend
+        * so we can signal it to shutdown once all
+        * client connections are closed
+        **/
+       g_object_add_toggle_ref (
+               G_OBJECT (backend),
+               subprocess_factory_toggle_notify_cb,
+               NULL);
+
+       g_signal_connect_object (
+               backend, "closed",
+               G_CALLBACK (subprocess_factory_closed_cb),
+               proxy, 0);
+}
diff --git a/libebackend/e-subprocess-factory.h b/libebackend/e-subprocess-factory.h
new file mode 100644
index 0000000..0c27fa5
--- /dev/null
+++ b/libebackend/e-subprocess-factory.h
@@ -0,0 +1,121 @@
+/*
+ * e-data-factory.h
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined (__LIBEBACKEND_H_INSIDE__) && !defined (LIBEBACKEND_COMPILATION)
+#error "Only <libebackend/libebackend.h> should be included directly."
+#endif
+
+#ifndef E_SUBPROCESS_FACTORY_H
+#define E_SUBPROCESS_FACTORY_H
+
+#include <libebackend/e-backend-factory.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SUBPROCESS_FACTORY \
+       (e_subprocess_factory_get_type ())
+#define E_SUBPROCESS_FACTORY(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_SUBPROCESS_FACTORY, ESubprocessFactory))
+#define E_SUBPROCESS_FACTORY_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_SUBPROCESS_FACTORY, ESubprocessFactoryClass))
+#define E_IS_SUBPROCESS_FACTORY(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_SUBPROCESS_FACTORY))
+#define E_IS_SUBPROCESS_FACTORY_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_SUBPROCESS_FACTORY))
+#define E_SUBPROCESS_FACTORY_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_SUBPROCESS_FACTORY, ESubprocessFactoryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESubprocessFactory ESubprocessFactory;
+typedef struct _ESubprocessFactoryClass ESubprocessFactoryClass;
+typedef struct _ESubprocessFactoryPrivate ESubprocessFactoryPrivate;
+
+/**
+ * ESubprocessFactory:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ *
+ * Since: 3.14
+ **/
+struct _ESubprocessFactory {
+       GObject parent;
+       ESubprocessFactoryPrivate *priv;
+};
+
+struct _ESubprocessFactoryClass {
+       GObjectClass parent_class;
+
+       EBackend *      (*ref_backend)          (ESourceRegistry *registry,
+                                                ESource *source,
+                                                const gchar *backend_factory_type_name);
+       gchar *         (*open_data)            (ESubprocessFactory *subprocess_factory,
+                                                EBackend *backend,
+                                                GDBusConnection *connection,
+                                                gpointer data,
+                                                GCancellable *cancellable,
+                                                GError **error);
+
+       /* Signals */
+       void            (*backend_created)      (ESubprocessFactory *subprocess_factory,
+                                                EBackend *backend);
+       void            (*backend_closed)       (ESubprocessFactory *subprocess_factory,
+                                                EBackend *backend);
+
+};
+
+GType          e_subprocess_factory_get_type
+                                               (void) G_GNUC_CONST;
+
+EBackend *     e_subprocess_factory_ref_initable_backend
+                                               (ESubprocessFactory *subprocess_factory,
+                                                const gchar *uid,
+                                                const gchar *type_name,
+                                                const gchar *module_file_name,
+                                                GCancellable *cancellable,
+                                                GError **error);
+ESourceRegistry *
+               e_subprocess_factory_get_registry
+                                               (ESubprocessFactory *subprocess_factory);
+gchar *                e_subprocess_factory_open_backend
+                                               (ESubprocessFactory *subprocess_factory,
+                                                GDBusConnection *connection,
+                                                const gchar *uid,
+                                                const gchar *type_name,
+                                                const gchar *module_file_name,
+                                                GDBusInterfaceSkeleton *proxy,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gchar *                e_subprocess_factory_construct_path
+                                               (void);
+void           e_subprocess_factory_set_backend_callbacks
+                                               (ESubprocessFactory *subprocess_factory,
+                                                EBackend *backend,
+                                                GDBusInterfaceSkeleton *proxy);
+void           e_subprocess_factory_call_backends_prepare_shutdown
+                                               (ESubprocessFactory *subprocess_factory);
+GList *                e_subprocess_factory_get_backends_list
+                                               (ESubprocessFactory *subprocess_factory);
+
+G_END_DECLS
+
+#endif /* E_SUBPROCESS_FACTORY_H */
diff --git a/libebackend/libebackend.h b/libebackend/libebackend.h
index 0708fef..f4f6feb 100644
--- a/libebackend/libebackend.h
+++ b/libebackend/libebackend.h
@@ -43,6 +43,7 @@
 #include <libebackend/e-soup-ssl-trust.h>
 #include <libebackend/e-source-registry-server.h>
 #include <libebackend/e-sqlite3-vfs.h>
+#include <libebackend/e-subprocess-factory.h>
 #include <libebackend/e-user-prompter.h>
 #include <libebackend/e-user-prompter-server.h>
 #include <libebackend/e-user-prompter-server-extension.h>
diff --git a/libedataserver/e-client.c b/libedataserver/e-client.c
index 8f9a13b..901724b 100644
--- a/libedataserver/e-client.c
+++ b/libedataserver/e-client.c
@@ -60,6 +60,7 @@ struct _EClientPrivate {
        gboolean readonly;
        GSList *capabilities;
        GMainContext *main_context;
+       gchar *bus_name;
 };
 
 struct _AsyncContext {
@@ -310,6 +311,9 @@ client_dispose (GObject *object)
 
        g_clear_object (&priv->source);
 
+       g_free (priv->bus_name);
+       priv->bus_name = NULL;
+
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (e_client_parent_class)->dispose (object);
 }
@@ -2124,3 +2128,45 @@ e_client_util_unwrap_dbus_error (GError *dbus_error,
        return TRUE;
 }
 
+/**
+ * e_client_dup_bus_name:
+ * @client: an #EClient
+ *
+ * Returns a D-Bus bus name that will be used to connect the
+ * client to the backend subprocess.
+ *
+ * Returns: a newly-allocated string representing a D-Bus bus
+ *          name that will be used to connect the client to
+ *          the backend subprocess. The string should be
+ *          freed by the caller using g_free().
+ *
+ * Since: 3.14
+ **/
+gchar *
+e_client_dup_bus_name (EClient *client)
+{
+       g_return_val_if_fail (E_IS_CLIENT (client), NULL);
+
+       return g_strdup (client->priv->bus_name);
+}
+
+/**
+ * e_client_set_bus_name:
+ * @client: an #EClient
+ * @bus_name: a string representing a D-Bus bus name
+ *
+ * Sets a D-Bus bus name that will be used to connect the client
+ * to the backend subprocess.
+ *
+ * Since: 3.14
+ **/
+void
+e_client_set_bus_name (EClient *client,
+                      const gchar *bus_name)
+{
+       g_return_if_fail (E_IS_CLIENT (client));
+       g_return_if_fail (client->priv->bus_name == NULL);
+       g_return_if_fail (bus_name != NULL && *bus_name != '\0');
+
+       client->priv->bus_name = g_strdup (bus_name);
+}
diff --git a/libedataserver/e-client.h b/libedataserver/e-client.h
index 33c513a..a808e0f 100644
--- a/libedataserver/e-client.h
+++ b/libedataserver/e-client.h
@@ -415,6 +415,10 @@ GSList *   e_client_util_copy_object_slist (GSList *copy_to,
                                                 const GSList *objects);
 void           e_client_util_free_string_slist (GSList *strings);
 void           e_client_util_free_object_slist (GSList *objects);
+gchar *                e_client_dup_bus_name           (EClient *client);
+void           e_client_set_bus_name           (EClient *client,
+                                                const gchar *bus_name);
+
 
 typedef struct _EClientErrorsList EClientErrorsList;
 
diff --git a/modules/gnome-online-accounts/module-gnome-online-accounts.c 
b/modules/gnome-online-accounts/module-gnome-online-accounts.c
index 17524a1..b5940ec 100644
--- a/modules/gnome-online-accounts/module-gnome-online-accounts.c
+++ b/modules/gnome-online-accounts/module-gnome-online-accounts.c
@@ -915,7 +915,7 @@ gnome_online_accounts_account_added_cb (EGoaClient *goa_client,
 
        if (source_uid == NULL && backend_name != NULL)
                backend_factory = e_data_factory_ref_backend_factory (
-                       E_DATA_FACTORY (server), backend_name);
+                       E_DATA_FACTORY (server), backend_name, E_SOURCE_EXTENSION_COLLECTION);
 
        if (backend_factory != NULL) {
                gnome_online_accounts_create_collection (
diff --git a/modules/ubuntu-online-accounts/module-ubuntu-online-accounts.c 
b/modules/ubuntu-online-accounts/module-ubuntu-online-accounts.c
index 6d41e72..b573630 100644
--- a/modules/ubuntu-online-accounts/module-ubuntu-online-accounts.c
+++ b/modules/ubuntu-online-accounts/module-ubuntu-online-accounts.c
@@ -707,7 +707,7 @@ ubuntu_online_accounts_account_created_cb (AgManager *ag_manager,
 
        if (source_uid == NULL && backend_name != NULL)
                backend_factory = e_data_factory_ref_backend_factory (
-                       E_DATA_FACTORY (server), backend_name);
+                       E_DATA_FACTORY (server), backend_name, E_SOURCE_EXTENSION_COLLECTION);
 
        if (backend_factory != NULL) {
                ubuntu_online_accounts_collect_userinfo (
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 43e9145..8c78a8d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -180,6 +180,7 @@ libebackend/e-collection-backend.c
 libebackend/e-data-factory.c
 libebackend/e-server-side-source.c
 libebackend/e-source-registry-server.c
+libebackend/e-subprocess-factory.c
 libebackend/e-user-prompter-server.c
 libedataserver/e-categories.c
 libedataserver/e-client.c
diff --git a/private/Makefile.am b/private/Makefile.am
index f8c2ccf..ec27561 100644
--- a/private/Makefile.am
+++ b/private/Makefile.am
@@ -99,6 +99,16 @@ $(GENERATED_DBUS_USER_PROMPTER) : Makefile.am org.gnome.evolution.dataserver.Use
        $(top_srcdir)/private/org.gnome.evolution.dataserver.UserPrompter.xml \
        $(NULL)
 
+$(GENERATED_DBUS_SUBPROCESS_BACKEND) : Makefile.am org.gnome.evolution.dataserver.Subprocess.Backend.xml
+       $(AM_V_GEN) gdbus-codegen \
+       --interface-prefix org.gnome.evolution.dataserver.Subprocess \
+       --c-namespace E_DBus_Subprocess \
+       --c-generate-object-manager \
+       --generate-c-code e-dbus-subprocess-backend \
+       --generate-docbook e-dbus-subprocess-backend \
+       $(top_srcdir)/private/org.gnome.evolution.dataserver.Subprocess.Backend.xml \
+       $(NULL)
+
 GENERATED_DBUS_LOCALE = \
        e-dbus-localed.c \
        e-dbus-localed.h \
@@ -169,6 +179,12 @@ GENERATED_DBUS_CALENDAR_FACTORY = \
        e-dbus-calendar-factory-org.gnome.evolution.dataserver.CalendarFactory.xml \
        $(NULL)
 
+GENERATED_DBUS_SUBPROCESS_BACKEND = \
+       e-dbus-subprocess-backend.c \
+       e-dbus-subprocess-backend.h \
+       e-dbus-subprocess-backend-org.gnome.evolution.dataserver.Subprocess.Backend.xml \
+       $(NULL)
+
 BUILT_SOURCES = \
        $(GENERATED_DBUS_LOCALE) \
        $(GENERATED_DBUS_SOURCE) \
@@ -181,6 +197,7 @@ BUILT_SOURCES = \
        $(GENERATED_DBUS_CALENDAR) \
        $(GENERATED_DBUS_CALENDAR_FACTORY) \
        $(GENERATED_DBUS_USER_PROMPTER) \
+       $(GENERATED_DBUS_SUBPROCESS_BACKEND) \
        $(NULL)
 
 noinst_LTLIBRARIES = libedbus-private.la
@@ -224,6 +241,7 @@ EXTRA_DIST = \
        org.gnome.evolution.dataserver.Calendar.xml \
        org.gnome.evolution.dataserver.CalendarFactory.xml \
        org.gnome.evolution.dataserver.UserPrompter.xml \
+       org.gnome.evolution.dataserver.Subprocess.Backend.xml \
        $(NULL)
 
 CLEANFILES = \
diff --git a/private/org.gnome.evolution.dataserver.AddressBookFactory.xml 
b/private/org.gnome.evolution.dataserver.AddressBookFactory.xml
index 46a7f53..38c9848 100644
--- a/private/org.gnome.evolution.dataserver.AddressBookFactory.xml
+++ b/private/org.gnome.evolution.dataserver.AddressBookFactory.xml
@@ -22,6 +22,7 @@
   <method name="OpenAddressBook">
     <arg name="source_uid" direction="in" type="s"/>
     <arg name="object_path" direction="out" type="s"/>
+    <arg name="bus_name" direction="out" type="s"/>
   </method>
 </interface>
 
diff --git a/private/org.gnome.evolution.dataserver.CalendarFactory.xml 
b/private/org.gnome.evolution.dataserver.CalendarFactory.xml
index d64ded4..0b8be9e 100644
--- a/private/org.gnome.evolution.dataserver.CalendarFactory.xml
+++ b/private/org.gnome.evolution.dataserver.CalendarFactory.xml
@@ -22,6 +22,7 @@
   <method name="OpenCalendar">
     <arg name="source_uid" direction="in" type="s"/>
     <arg name="object_path" direction="out" type="s"/>
+    <arg name="bus_name" direction="out" type="s"/>
   </method>
 
   <!--
@@ -36,6 +37,7 @@
   <method name="OpenTaskList">
     <arg name="source_uid" direction="in" type="s"/>
     <arg name="object_path" direction="out" type="s"/>
+    <arg name="bus_name" direction="out" type="s"/>
   </method>
 
   <!--
@@ -49,6 +51,7 @@
   <method name="OpenMemoList">
     <arg name="source_uid" direction="in" type="s"/>
     <arg name="object_path" direction="out" type="s"/>
+    <arg name="bus_name" direction="out" type="s"/>
   </method>
 </interface>
 
diff --git a/private/org.gnome.evolution.dataserver.Subprocess.Backend.xml 
b/private/org.gnome.evolution.dataserver.Subprocess.Backend.xml
new file mode 100644
index 0000000..b204eef
--- /dev/null
+++ b/private/org.gnome.evolution.dataserver.Subprocess.Backend.xml
@@ -0,0 +1,29 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd";>
+
+<!--
+    org.gnome.evolution.dataserver.Subprocess.Backend:
+    @short_description: Subprocess for backends objects
+    @since: 3.14
+
+    This interface provides access to the subprocess responsible to
+    create a backend instance
+-->
+<interface name="org.gnome.evolution.dataserver.Subprocess.Backend">
+
+  <signal name="BackendClosed">
+    <arg name="sender" type="s"/>
+  </signal>
+
+  <method name="Create">
+    <arg name="source_id" direction="in" type="s"/>
+    <arg name="backend_factory_type_name" direction="in" type="s"/>
+    <arg name="module_filename" direction="in" type="s"/>
+    <arg name="object_path" direction="out" type="s"/>
+  </method>
+
+  <method name="Close"/>
+
+</interface>


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