[evolution/gnome-3-34] I#587 - Change how Evolution talks to WebKitWebProcess



commit 89229b9bdae1a7510765ffee3b57c0f1b4fa434b
Author: Milan Crha <mcrha redhat com>
Date:   Wed Sep 11 22:46:28 2019 +0200

    I#587 - Change how Evolution talks to WebKitWebProcess
    
    Required for WebKitGTK+ 2.26.0+.
    
    Closes https://gitlab.gnome.org/GNOME/evolution/issues/587

 src/addressbook/gui/widgets/eab-contact-display.c  |   15 +-
 src/e-util/CMakeLists.txt                          |    2 +
 src/e-util/e-misc-utils.c                          |    8 +-
 src/e-util/e-util.h                                |    1 +
 src/e-util/e-web-extension-container.c             | 1280 ++++++++++++++++++++
 src/e-util/e-web-extension-container.h             |  103 ++
 src/e-util/e-web-view.c                            |  446 ++++---
 src/mail/e-mail-display.c                          |  111 +-
 src/modules/itip-formatter/CMakeLists.txt          |    2 -
 src/modules/itip-formatter/e-mail-formatter-itip.c |    2 +-
 src/modules/itip-formatter/e-mail-part-itip.c      |   29 +-
 src/modules/itip-formatter/itip-view.c             |  611 ++++++----
 src/modules/itip-formatter/itip-view.h             |    5 +-
 .../itip-formatter/web-extension/CMakeLists.txt    |   20 -
 .../module-itip-formatter-web-extension.c          |  646 ----------
 .../module-itip-formatter-web-extension.h          |   26 -
 src/modules/vcard-inline/e-mail-part-vcard.c       |  109 +-
 src/modules/webkit-editor/e-webkit-editor.c        |  699 +++++------
 .../webkit-editor/web-extension/e-editor-page.c    |   18 +
 .../webkit-editor/web-extension/e-editor-page.h    |    3 +
 .../web-extension/e-editor-web-extension-main.c    |   46 +-
 .../web-extension/e-editor-web-extension-names.h   |    1 -
 .../web-extension/e-editor-web-extension.c         |  164 ++-
 src/web-extensions/CMakeLists.txt                  |    8 +-
 .../e-itip-formatter-dom-utils.c}                  |  283 ++---
 .../e-itip-formatter-dom-utils.h}                  |   48 +-
 src/web-extensions/e-web-extension-main.c          |   52 +-
 src/web-extensions/e-web-extension-names.h         |    5 +-
 src/web-extensions/e-web-extension.c               |  776 +++++++++++-
 src/web-extensions/e-web-extension.h               |   10 +-
 30 files changed, 3552 insertions(+), 1977 deletions(-)
---
diff --git a/src/addressbook/gui/widgets/eab-contact-display.c 
b/src/addressbook/gui/widgets/eab-contact-display.c
index c1a03ae1fd..5389924d34 100644
--- a/src/addressbook/gui/widgets/eab-contact-display.c
+++ b/src/addressbook/gui/widgets/eab-contact-display.c
@@ -385,16 +385,13 @@ contact_display_link_clicked (EWebView *web_view,
 }
 
 static void
-contact_display_load_changed (WebKitWebView *web_view,
-                              WebKitLoadEvent load_event,
-                              gpointer user_data)
+contact_display_notify_web_extension_proxy_cb (GObject *web_view,
+                                              GParamSpec *param,
+                                              gpointer user_data)
 {
        GDBusProxy *web_extension;
        GVariant* result;
 
-       if (load_event != WEBKIT_LOAD_FINISHED)
-               return;
-
        web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (web_view));
        if (web_extension) {
                result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
@@ -402,7 +399,7 @@ contact_display_load_changed (WebKitWebView *web_view,
                                "EABContactFormatterBindDOM",
                                g_variant_new (
                                        "(t)",
-                                       webkit_web_view_get_page_id (web_view)),
+                                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view))),
                                NULL);
 
                if (result)
@@ -535,8 +532,8 @@ eab_contact_display_init (EABContactDisplay *display)
                G_CALLBACK (contact_display_web_process_crashed_cb), NULL);
 
        g_signal_connect (
-               web_view, "load-changed",
-               G_CALLBACK (contact_display_load_changed), NULL);
+               web_view, "notify::web-extension-proxy",
+               G_CALLBACK (contact_display_notify_web_extension_proxy_cb), NULL);
        g_signal_connect (
                web_view, "style-updated",
                G_CALLBACK (load_contact), NULL);
diff --git a/src/e-util/CMakeLists.txt b/src/e-util/CMakeLists.txt
index ceed0a45e2..81ae3cd72c 100644
--- a/src/e-util/CMakeLists.txt
+++ b/src/e-util/CMakeLists.txt
@@ -269,6 +269,7 @@ set(SOURCES
        e-url-entry.c
        e-util-private.h
        e-webdav-browser.c
+       e-web-extension-container.c
        e-web-view-preview.c
        e-web-view.c
        e-widget-undo.c
@@ -541,6 +542,7 @@ set(HEADERS
        e-url-entry.h
        e-util-enums.h
        e-webdav-browser.h
+       e-web-extension-container.h
        e-web-view-preview.h
        e-web-view.h
        e-widget-undo.h
diff --git a/src/e-util/e-misc-utils.c b/src/e-util/e-misc-utils.c
index 94831c53e4..62ce8f9378 100644
--- a/src/e-util/e-misc-utils.c
+++ b/src/e-util/e-misc-utils.c
@@ -3711,8 +3711,12 @@ e_util_claim_dbus_proxy_call_error (GDBusProxy *dbus_proxy,
        g_return_if_fail (G_IS_DBUS_PROXY (dbus_proxy));
        g_return_if_fail (method_name != NULL);
 
-       if (in_error && !g_error_matches (in_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-               g_warning ("Failed to call a DBus Proxy method %s::%s: %s",
+       if (in_error &&
+           !g_error_matches (in_error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
+           !g_error_matches (in_error, G_IO_ERROR, G_IO_ERROR_CLOSED) &&
+           !g_error_matches (in_error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED) &&
+           !g_error_matches (in_error, G_DBUS_ERROR, G_DBUS_ERROR_DISCONNECTED))
+               g_message ("Failed to call a DBus Proxy method %s::%s: %s",
                        g_dbus_proxy_get_name (dbus_proxy), method_name, in_error->message);
 }
 
diff --git a/src/e-util/e-util.h b/src/e-util/e-util.h
index c207820897..84db520bed 100644
--- a/src/e-util/e-util.h
+++ b/src/e-util/e-util.h
@@ -264,6 +264,7 @@
 #include <e-util/e-util-enums.h>
 #include <e-util/e-util-enumtypes.h>
 #include <e-util/e-webdav-browser.h>
+#include <e-util/e-web-extension-container.h>
 #ifndef E_UTIL_INCLUDE_WITHOUT_WEBKIT
 #include <e-util/e-web-view-preview.h>
 #include <e-util/e-web-view.h>
diff --git a/src/e-util/e-web-extension-container.c b/src/e-util/e-web-extension-container.c
new file mode 100644
index 0000000000..5792f9dda4
--- /dev/null
+++ b/src/e-util/e-web-extension-container.c
@@ -0,0 +1,1280 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2019 Red Hat (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/>.
+ */
+
+#include "evolution-config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+
+#include <libedataserver/libedataserver.h>
+
+#include "e-web-extension-container.h"
+
+/**
+ * SECTION: e-web-extension-container
+ * @include: e-util/e-util.h
+ * @short_description: Container of WebKitGTK+ Web Extensions
+ *
+ * #EWebExtensionContainer is a container of WebKitGTK+ Web Extensions, which
+ * runs a D-Bus server to which the Web Extensions can connect. This object
+ * is meant for the client side. It also takes care of all the connections
+ * and corresponding #GDBusProxy objects.
+ *
+ * The Web Extension part can use e_web_extension_container_utils_connect_to_server()
+ * to connect to it.
+ **/
+
+struct _EWebExtensionContainerPrivate {
+       gchar *object_path;
+       gchar *interface_name;
+       GDBusServer *dbus_server;
+       GHashTable *proxy_by_page; /* ProxyIdentData ~> ProxyPageData */
+       GSList *proxy_instances; /* ProxyInstanceData */
+
+       volatile gint current_stamp;
+       GHashTable *used_stamps; /* GINT_TO_POINTER(stamp) ~> NULL */
+};
+
+enum {
+       PROP_0,
+       PROP_INTERFACE_NAME,
+       PROP_OBJECT_PATH
+};
+
+enum {
+       PAGE_PROXY_CHANGED,
+       LAST_SIGNAL
+};
+
+static gulong signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE_WITH_PRIVATE (EWebExtensionContainer, e_web_extension_container, G_TYPE_OBJECT)
+
+static gboolean
+authorize_authenticated_peer_cb (GDBusAuthObserver *observer,
+                                GIOStream *stream,
+                                GCredentials *credentials,
+                                gpointer user_data)
+{
+       GCredentials *my_credentials;
+       GError *error = NULL;
+       gboolean res;
+
+       if (!credentials)
+               return FALSE;
+
+       my_credentials = g_credentials_new ();
+
+       res = g_credentials_is_same_user (credentials, my_credentials, &error);
+
+       if (error) {
+               g_warning ("Failed to authrorize credentials: %s", error->message);
+               g_clear_error (&error);
+       }
+
+       g_clear_object (&my_credentials);
+
+       return res;
+}
+
+static GDBusServer *
+ewec_new_server_sync (const gchar *object_path,
+                     GCancellable *cancellable,
+                     GError **error)
+{
+       GDBusAuthObserver *observer;
+       GDBusServer *server;
+       gchar *path_part, *path, *tmpdir, *address, *guid;
+       gint ii, fd;
+
+       path_part = g_strconcat ("evolution-",
+               object_path ? object_path : "",
+               object_path ? "-" : "",
+               g_get_user_name (),
+               "-XXXXXX", NULL);
+
+       for (ii = 0; path_part[ii]; ii++) {
+               if (path_part[ii] == '/' ||
+                   path_part[ii] == '\\' ||
+                   path_part[ii] == ':' ||
+                   path_part[ii] == '?' ||
+                   path_part[ii] == '*')
+                       path_part[ii] = '_';
+       }
+
+       path = g_build_filename (g_get_tmp_dir (), path_part, NULL);
+
+       fd = g_mkstemp (path);
+       if (fd == -1) {
+               tmpdir = NULL;
+       } else {
+               close (fd);
+               tmpdir = path;
+               g_unlink (tmpdir);
+       }
+
+       g_free (path_part);
+
+       if (!tmpdir) {
+               g_free (path);
+
+               g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "%s", g_strerror (errno));
+               return NULL;
+       }
+
+       address = g_strconcat ("unix:path=", path, NULL);
+
+       g_free (path);
+
+       guid = g_dbus_generate_guid ();
+       observer = g_dbus_auth_observer_new ();
+
+       g_signal_connect (observer, "authorize-authenticated-peer",
+               G_CALLBACK (authorize_authenticated_peer_cb), NULL);
+
+       server = g_dbus_server_new_sync (address, G_DBUS_SERVER_FLAGS_NONE, guid, observer, cancellable, 
error);
+
+       g_object_unref (observer);
+       g_free (address);
+       g_free (guid);
+
+       if (server)
+               g_dbus_server_start (server);
+
+       return server;
+}
+
+typedef struct _CallSimpleData {
+       gchar *method_name;
+       GVariant *params;
+} CallSimpleData;
+
+static CallSimpleData *
+call_simple_data_new (const gchar *method_name,
+                     GVariant *params)
+{
+       CallSimpleData *csd;
+
+       csd = g_new0 (CallSimpleData, 1);
+       csd->method_name = g_strdup (method_name);
+       csd->params = params ? g_variant_ref_sink (params) : NULL;
+
+       return csd;
+}
+
+static void
+call_simple_data_free (gpointer ptr)
+{
+       CallSimpleData *csd = ptr;
+
+       if (csd) {
+               g_free (csd->method_name);
+               if (csd->params)
+                       g_variant_unref (csd->params);
+               g_free (csd);
+       }
+}
+
+typedef struct _ProxyDataIdent {
+       guint64 page_id;
+       gint stamp;
+} ProxyDataIdent;
+
+static ProxyDataIdent *
+proxy_data_ident_new (guint64 page_id,
+                     gint stamp)
+{
+       ProxyDataIdent *pdi;
+
+       pdi = g_new0 (ProxyDataIdent, 1);
+       pdi->page_id = page_id;
+       pdi->stamp = stamp;
+
+       return pdi;
+}
+
+static void
+proxy_data_ident_free (gpointer ptr)
+{
+       ProxyDataIdent *pdi = ptr;
+
+       if (pdi) {
+               g_free (pdi);
+       }
+}
+
+static guint
+proxy_data_ident_hash (gconstpointer ptr)
+{
+       const ProxyDataIdent *pdi = ptr;
+       gint64 signed_page_id;
+
+       if (!pdi)
+               return 0;
+
+       signed_page_id = pdi->page_id;
+
+       return g_int64_hash (&signed_page_id) ^ g_direct_hash (GINT_TO_POINTER (pdi->stamp));
+}
+
+static gboolean
+proxy_data_ident_equal (gconstpointer aa,
+                       gconstpointer bb)
+{
+       const ProxyDataIdent *pdi1 = aa, *pdi2 = bb;
+
+       if (pdi1 == pdi2)
+               return TRUE;
+
+       if (!pdi1 || !pdi2)
+               return FALSE;
+
+       return pdi1->page_id == pdi2->page_id && pdi1->stamp == pdi2->stamp;
+}
+
+typedef struct _ProxyPageData {
+       GDBusProxy *proxy;
+       GSList *pending_calls; /* CallSimpleData * */
+} ProxyPageData;
+
+static ProxyPageData *
+proxy_page_data_new (GDBusProxy *proxy) /* can be NULL, adds its own reference if not */
+{
+       ProxyPageData *ppd;
+
+       ppd = g_new0 (ProxyPageData, 1);
+       ppd->proxy = proxy;
+       ppd->pending_calls = NULL;
+
+       if (proxy)
+               g_object_ref (proxy);
+
+       return ppd;
+}
+
+static void
+proxy_page_data_free (gpointer ptr)
+{
+       ProxyPageData *ppd = ptr;
+
+       if (ppd) {
+               g_clear_object (&ppd->proxy);
+               g_slist_free_full (ppd->pending_calls, call_simple_data_free);
+               g_free (ppd);
+       }
+}
+
+typedef struct _ProxyInstanceData {
+       GDBusConnection *connection;
+       GDBusProxy *proxy;
+       guint extension_object_ready_signal_id;
+       guint extension_handles_page_signal_id;
+       gulong connection_closed_signal_id;
+} ProxyInstanceData;
+
+static void
+proxy_instance_gone_cb (gpointer user_data,
+                       GObject *obj)
+{
+       ProxyInstanceData *pid = user_data;
+
+       g_return_if_fail (pid != NULL);
+       g_return_if_fail (pid->proxy == (GDBusProxy *) obj);
+
+       pid->proxy = NULL;
+}
+
+static ProxyInstanceData *
+proxy_instance_data_new (GDBusProxy *proxy) /* Takes ownership */
+{
+       ProxyInstanceData *pid;
+
+       g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
+
+       pid = g_new0 (ProxyInstanceData, 1);
+       pid->connection = g_object_ref (g_dbus_proxy_get_connection (proxy));
+       pid->proxy = proxy;
+
+       g_object_weak_ref (G_OBJECT (proxy), proxy_instance_gone_cb, pid);
+
+       return pid;
+}
+
+static void
+proxy_instance_data_free (gpointer ptr)
+{
+       ProxyInstanceData *pid = ptr;
+
+       if (pid) {
+               if (pid->proxy)
+                       g_object_weak_unref (G_OBJECT (pid->proxy), proxy_instance_gone_cb, pid);
+
+               if (pid->connection) {
+                       if (pid->extension_object_ready_signal_id) {
+                               g_dbus_connection_signal_unsubscribe (pid->connection, 
pid->extension_object_ready_signal_id);
+                               pid->extension_object_ready_signal_id = 0;
+                       }
+
+                       if (pid->extension_handles_page_signal_id) {
+                               g_dbus_connection_signal_unsubscribe (pid->connection, 
pid->extension_handles_page_signal_id);
+                               pid->extension_handles_page_signal_id = 0;
+                       }
+
+                       if (pid->connection_closed_signal_id) {
+                               g_signal_handler_disconnect (pid->connection, 
pid->connection_closed_signal_id);
+                               pid->connection_closed_signal_id = 0;
+                       }
+               }
+
+               g_clear_object (&pid->connection);
+               g_clear_object (&pid->proxy);
+               g_free (pid);
+       }
+}
+
+static void
+ewec_simple_call_finished_cb (GObject *source_object,
+                             GAsyncResult *async_result,
+                             gpointer user_data)
+{
+       GVariant *result;
+       GError *error = NULL;
+
+       result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), async_result, &error);
+
+       if (error) {
+               if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_DISCONNECTED) &&
+                   !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) &&
+                   !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
+                       g_warning ("%s: D-Bus call failed: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else if (result) {
+               g_variant_unref (result);
+       }
+}
+
+static void
+ewec_clain_proxy_handles_page (EWebExtensionContainer *container,
+                              GDBusProxy *proxy,
+                              guint64 page_id,
+                              gint stamp)
+{
+       ProxyDataIdent data_ident;
+       ProxyPageData *ppd;
+
+       data_ident.page_id = page_id;
+       data_ident.stamp = stamp;
+
+       ppd = g_hash_table_lookup (container->priv->proxy_by_page, &data_ident);
+
+       if (ppd && ppd->proxy != proxy) {
+               g_clear_object (&ppd->proxy);
+               ppd->proxy = g_object_ref (proxy);
+
+               if (ppd->pending_calls) {
+                       GSList *pending_calls, *link;
+
+                       pending_calls = g_slist_reverse (ppd->pending_calls);
+                       ppd->pending_calls = NULL;
+
+                       for (link = pending_calls; link; link = g_slist_next (link)) {
+                               CallSimpleData *csd = link->data;
+
+                               if (csd && !g_dbus_connection_is_closed (g_dbus_proxy_get_connection 
(ppd->proxy))) {
+                                       g_dbus_proxy_call (ppd->proxy, csd->method_name, csd->params,
+                                               G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, 
ewec_simple_call_finished_cb, NULL);
+                               }
+                       }
+
+                       g_slist_free_full (pending_calls, call_simple_data_free);
+               }
+       } else if (!ppd) {
+               ProxyDataIdent *pdi;
+
+               pdi = proxy_data_ident_new (page_id, stamp);
+               ppd = proxy_page_data_new (proxy);
+
+               g_hash_table_insert (container->priv->proxy_by_page, pdi, ppd);
+       }
+
+       g_signal_emit (container, signals[PAGE_PROXY_CHANGED], 0, page_id, stamp, proxy);
+}
+
+static void
+ewec_get_extension_handles_pages_cb (GObject *sender_object,
+                                    GAsyncResult *async_result,
+                                    gpointer user_data)
+{
+       GWeakRef *container_weak_ref = user_data;
+       GDBusProxy *proxy;
+       GVariant *result;
+       GError *error = NULL;
+
+       g_return_if_fail (container_weak_ref != NULL);
+       g_return_if_fail (G_IS_DBUS_PROXY (sender_object));
+
+       proxy = G_DBUS_PROXY (sender_object);
+       result = g_dbus_proxy_call_finish (proxy, async_result, &error);
+
+       if (error) {
+               /* This can happen when the object is not registered on the connection yet */
+               if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) &&
+                   !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_DISCONNECTED) &&
+                   !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) &&
+                   !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
+                       g_warning ("Failed to call GetExtensionHandlesPages: %s", error->message);
+               g_clear_error (&error);
+       } else if (result) {
+               EWebExtensionContainer *container;
+
+               container = g_weak_ref_get (container_weak_ref);
+
+               if (container) {
+                       GVariantIter *iter = NULL;
+                       guint64 page_id;
+                       guint64 stamp;
+
+                       g_variant_get (result, "(at)", &iter);
+
+                       while (g_variant_iter_loop (iter, "t", &page_id) &&
+                              g_variant_iter_loop (iter, "t", &stamp)) {
+                               ewec_clain_proxy_handles_page (container, proxy, page_id, (gint) stamp);
+                       }
+
+                       g_variant_iter_free (iter);
+                       g_object_unref (container);
+               }
+
+               g_variant_unref (result);
+       }
+
+       e_weak_ref_free (container_weak_ref);
+}
+
+static void
+ewec_extension_handle_signal_cb (GDBusConnection *connection,
+                                const gchar *sender_name,
+                                const gchar *object_path,
+                                const gchar *interface_name,
+                                const gchar *signal_name,
+                                GVariant *parameters,
+                                gpointer user_data)
+{
+       EWebExtensionContainer *container = user_data;
+       GSList *link;
+       GDBusProxy *proxy = NULL;
+
+       g_return_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container));
+
+       for (link = container->priv->proxy_instances; link; link = g_slist_next (link)) {
+               ProxyInstanceData *pid = link->data;
+
+               if (pid && pid->proxy &&
+                   g_dbus_proxy_get_connection (pid->proxy) == connection) {
+                       proxy = pid->proxy;
+                       break;
+               }
+       }
+
+       if (g_strcmp0 (signal_name, "ExtensionObjectReady") == 0) {
+               g_return_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container));
+
+               if (proxy && !g_dbus_connection_is_closed (g_dbus_proxy_get_connection (proxy))) {
+                       g_dbus_proxy_call (proxy, "GetExtensionHandlesPages", NULL, 
G_DBUS_CALL_FLAGS_NO_AUTO_START,
+                               -1, NULL, ewec_get_extension_handles_pages_cb, e_weak_ref_new (container));
+               }
+       } else if (g_strcmp0 (signal_name, "ExtensionHandlesPage") == 0) {
+               guint64 page_id = 0;
+               gint stamp = 0;
+
+               if (!parameters)
+                       return;
+
+               g_variant_get (parameters, "(ti)", &page_id, &stamp);
+
+               if (proxy)
+                       ewec_clain_proxy_handles_page (container, proxy, page_id, stamp);
+       }
+}
+
+static void
+ewec_connection_closed_cb (GDBusConnection *connection,
+                          gboolean remote_peer_vanished,
+                          GError *error,
+                          gpointer user_data)
+{
+       EWebExtensionContainer *container = user_data;
+       GSList *link, *prev;
+
+       g_return_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container));
+
+       prev = NULL;
+       for (link = container->priv->proxy_instances; link; prev = link, link = g_slist_next (link)) {
+               ProxyInstanceData *pid = link->data;
+
+               if (pid && pid->proxy && g_dbus_proxy_get_connection (pid->proxy) == connection) {
+                       GHashTableIter iter;
+                       gpointer key, value;
+                       GSList *to_remove = NULL, *trlink;
+
+                       link = prev;
+                       container->priv->proxy_instances = g_slist_remove (container->priv->proxy_instances, 
pid);
+
+                       if (!link)
+                               link = container->priv->proxy_instances;
+
+                       g_hash_table_iter_init (&iter, container->priv->proxy_by_page);
+
+                       while (g_hash_table_iter_next (&iter, &key, &value)) {
+                               ProxyDataIdent *pdi = key;
+                               ProxyPageData *ppd = value;
+
+                               if (ppd && ppd->proxy == pid->proxy)
+                                       to_remove = g_slist_prepend (to_remove, pdi);
+                       }
+
+                       for (trlink = to_remove; trlink; trlink = g_slist_next (trlink)) {
+                               ProxyDataIdent *pdi = trlink->data;
+                               guint64 page_id;
+                               gint stamp;
+
+                               page_id = pdi->page_id;
+                               stamp = pdi->stamp;
+
+                               if (g_hash_table_remove (container->priv->proxy_by_page, pdi)) {
+                                       g_signal_emit (container, signals[PAGE_PROXY_CHANGED], 0, page_id, 
stamp, NULL);
+                               }
+                       }
+
+                       proxy_instance_data_free (pid);
+                       g_slist_free (to_remove);
+               }
+       }
+}
+
+static void
+e_web_extension_container_proxy_created_cb (GObject *source_object,
+                                           GAsyncResult *result,
+                                           gpointer user_data)
+{
+       EWebExtensionContainer *container;
+       GWeakRef *container_weak_ref = user_data;
+       GDBusProxy *proxy;
+       ProxyInstanceData *pid;
+       GError *error = NULL;
+
+       g_return_if_fail (container_weak_ref != NULL);
+
+       container = g_weak_ref_get (container_weak_ref);
+       if (!container) {
+               e_weak_ref_free (container_weak_ref);
+               return;
+       }
+
+       proxy = g_dbus_proxy_new_finish (result, &error);
+       if (!proxy) {
+               g_warning ("Error creating web extension proxy: %s", error ? error->message : "Unknown 
error");
+
+               e_weak_ref_free (container_weak_ref);
+               g_object_unref (container);
+               g_error_free (error);
+               return;
+       }
+
+       pid = proxy_instance_data_new (proxy);
+       if (pid) {
+               container->priv->proxy_instances = g_slist_prepend (container->priv->proxy_instances, pid);
+
+               pid->extension_object_ready_signal_id =
+                       g_dbus_connection_signal_subscribe (
+                               g_dbus_proxy_get_connection (proxy),
+                               g_dbus_proxy_get_name (proxy),
+                               container->priv->interface_name,
+                               "ExtensionObjectReady",
+                               container->priv->object_path,
+                               NULL,
+                               G_DBUS_SIGNAL_FLAGS_NONE,
+                               ewec_extension_handle_signal_cb,
+                               container,
+                               NULL);
+
+               pid->extension_handles_page_signal_id =
+                       g_dbus_connection_signal_subscribe (
+                               g_dbus_proxy_get_connection (proxy),
+                               g_dbus_proxy_get_name (proxy),
+                               container->priv->interface_name,
+                               "ExtensionHandlesPage",
+                               container->priv->object_path,
+                               NULL,
+                               G_DBUS_SIGNAL_FLAGS_NONE,
+                               ewec_extension_handle_signal_cb,
+                               container,
+                               NULL);
+
+               pid->connection_closed_signal_id =
+                       g_signal_connect (g_dbus_proxy_get_connection (proxy), "closed",
+                               G_CALLBACK (ewec_connection_closed_cb), container);
+
+               g_dbus_proxy_call (proxy, "GetExtensionHandlesPages", NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START,
+                       -1, NULL, ewec_get_extension_handles_pages_cb, container_weak_ref);
+       } else {
+               e_weak_ref_free (container_weak_ref);
+       }
+
+       g_object_unref (container);
+}
+
+static gboolean
+e_web_extension_container_new_connection_cb (GDBusServer *server,
+                                            GDBusConnection *connection,
+                                            gpointer user_data)
+{
+       EWebExtensionContainer *container = user_data;
+
+       g_return_val_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container), FALSE);
+
+       g_dbus_proxy_new (
+               connection,
+               G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
+               G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+               NULL,
+               NULL,
+               container->priv->object_path,
+               container->priv->interface_name,
+               NULL,
+               e_web_extension_container_proxy_created_cb,
+               e_weak_ref_new (container));
+
+       return TRUE;
+}
+
+static void
+web_extension_container_set_object_path (EWebExtensionContainer *container,
+                                        const gchar *object_path)
+{
+       g_return_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container));
+       g_return_if_fail (object_path && *object_path);
+
+       if (g_strcmp0 (container->priv->object_path, object_path)) {
+               g_free (container->priv->object_path);
+               container->priv->object_path = g_strdup (object_path);
+       }
+}
+
+static void
+web_extension_container_set_interface_name (EWebExtensionContainer *container,
+                                           const gchar *interface_name)
+{
+       g_return_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container));
+       g_return_if_fail (interface_name && *interface_name);
+
+       if (g_strcmp0 (container->priv->interface_name, interface_name)) {
+               g_free (container->priv->interface_name);
+               container->priv->interface_name = g_strdup (interface_name);
+       }
+}
+
+static void
+web_extension_container_set_property (GObject *object,
+                                     guint property_id,
+                                     const GValue *value,
+                                     GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_INTERFACE_NAME:
+                       web_extension_container_set_interface_name (
+                               E_WEB_EXTENSION_CONTAINER (object),
+                               g_value_get_string (value));
+                       return;
+
+               case PROP_OBJECT_PATH:
+                       web_extension_container_set_object_path (
+                               E_WEB_EXTENSION_CONTAINER (object),
+                               g_value_get_string (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+web_extension_container_get_property (GObject *object,
+                                     guint property_id,
+                                     GValue *value,
+                                     GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_INTERFACE_NAME:
+                       g_value_set_string (
+                               value, e_web_extension_container_get_interface_name (
+                               E_WEB_EXTENSION_CONTAINER (object)));
+                       return;
+
+               case PROP_OBJECT_PATH:
+                       g_value_set_string (
+                               value, e_web_extension_container_get_object_path (
+                               E_WEB_EXTENSION_CONTAINER (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+web_extension_container_instance_gone_cb (gpointer user_data,
+                                         GObject *instance)
+{
+       GHashTable **pinstances = user_data;
+       GHashTableIter iter;
+       gpointer key, value;
+
+       g_return_if_fail (pinstances != NULL);
+       g_return_if_fail (*pinstances != NULL);
+
+       g_hash_table_iter_init (&iter, *pinstances);
+
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               GObject *stored_instance = value;
+
+               if (stored_instance == instance) {
+                       g_hash_table_remove (*pinstances, key);
+                       break;
+               }
+       }
+
+       if (!g_hash_table_size (*pinstances)) {
+               g_hash_table_destroy (*pinstances);
+               *pinstances = NULL;
+       }
+}
+
+static GObject *
+web_extension_container_constructor (GType type,
+                                    guint n_construct_params,
+                                    GObjectConstructParam *construct_params)
+{
+       static GHashTable *instances = NULL;
+       const gchar *object_path = NULL;
+       GObject *instance;
+       guint ii;
+
+       for (ii = 0; ii < n_construct_params; ii++) {
+               if (construct_params[ii].pspec &&
+                   g_strcmp0 (construct_params[ii].pspec->name, "object-path") == 0) {
+                       object_path = g_value_get_string (construct_params[ii].value);
+                       break;
+               }
+       }
+
+       if (!object_path)
+               object_path = "";
+
+       if (instances) {
+               instance = g_hash_table_lookup (instances, object_path);
+
+               if (instance)
+                       return g_object_ref (instance);
+       }
+
+       instance = G_OBJECT_CLASS (e_web_extension_container_parent_class)->constructor (type, 
n_construct_params, construct_params);
+
+       if (instance) {
+               if (!instances)
+                       instances = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+               g_hash_table_insert (instances, g_strdup (object_path), instance);
+
+               g_object_weak_ref (instance, web_extension_container_instance_gone_cb, &instances);
+       }
+
+       return instance;
+}
+
+static void
+web_extension_container_constructed (GObject *object)
+{
+       EWebExtensionContainer *container = E_WEB_EXTENSION_CONTAINER (object);
+       GError *error = NULL;
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_web_extension_container_parent_class)->constructed (object);
+
+       container->priv->dbus_server = ewec_new_server_sync (container->priv->object_path, NULL, &error);
+
+       if (container->priv->dbus_server) {
+               g_signal_connect_object (container->priv->dbus_server, "new-connection",
+                       G_CALLBACK (e_web_extension_container_new_connection_cb), container, 0);
+       } else {
+               g_warning ("%s: Failed to create D-Bus server for object_path '%s': %s", G_STRFUNC,
+                       container->priv->object_path ? container->priv->object_path : "[null]",
+                       error ? error->message : "Unknown error");
+       }
+
+       g_clear_error (&error);
+}
+
+static void
+web_extension_container_dispose (GObject *object)
+{
+       EWebExtensionContainer *container = E_WEB_EXTENSION_CONTAINER (object);
+       GHashTableIter iter;
+       gpointer key, value;
+
+       g_hash_table_iter_init (&iter, container->priv->proxy_by_page);
+
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               ProxyDataIdent *pdi = key;
+               ProxyPageData *ppd = value;
+
+               if (pdi && ppd && ppd->proxy)
+                       g_signal_emit (container, signals[PAGE_PROXY_CHANGED], 0, pdi->page_id, pdi->stamp, 
NULL);
+       }
+
+       g_hash_table_remove_all (container->priv->proxy_by_page);
+       g_hash_table_remove_all (container->priv->used_stamps);
+       g_slist_free_full (container->priv->proxy_instances, proxy_instance_data_free);
+       container->priv->proxy_instances = NULL;
+       g_clear_object (&container->priv->dbus_server);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_web_extension_container_parent_class)->dispose (object);
+}
+
+static void
+web_extension_container_finalize (GObject *object)
+{
+       EWebExtensionContainer *container = E_WEB_EXTENSION_CONTAINER (object);
+
+       g_clear_pointer (&container->priv->interface_name, g_free);
+       g_clear_pointer (&container->priv->object_path, g_free);
+       g_hash_table_destroy (container->priv->proxy_by_page);
+       g_hash_table_destroy (container->priv->used_stamps);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_web_extension_container_parent_class)->finalize (object);
+}
+
+static void
+e_web_extension_container_class_init (EWebExtensionContainerClass *klass)
+{
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (klass);
+       object_class->set_property = web_extension_container_set_property;
+       object_class->get_property = web_extension_container_get_property;
+       object_class->constructor = web_extension_container_constructor;
+       object_class->constructed = web_extension_container_constructed;
+       object_class->dispose = web_extension_container_dispose;
+       object_class->finalize = web_extension_container_finalize;
+
+       g_object_class_install_property (
+               object_class,
+               PROP_OBJECT_PATH,
+               g_param_spec_string (
+                       "object-path",
+                       NULL,
+                       NULL,
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT_ONLY |
+                       G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_INTERFACE_NAME,
+               g_param_spec_string (
+                       "interface-name",
+                       NULL,
+                       NULL,
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT_ONLY |
+                       G_PARAM_STATIC_STRINGS));
+
+       /**
+        * EWebExtensionContainer::page-proxy-changed:
+        * @page_id: a page ID
+        * @stamp: a stamp
+        * @proxy: (nullable): a #GDBusProxy or %NULL
+        *
+        * A signal emitted whenever a proxy for the given @page_id and
+        * @stamp changes. The @proxy can be %NULL, which means the previous
+        * proxy disappeared.
+        *
+        * Since: 3.34.1
+        **/
+       signals[PAGE_PROXY_CHANGED] = g_signal_new (
+               "page-proxy-changed",
+               G_OBJECT_CLASS_TYPE (object_class),
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (EWebExtensionContainerClass, page_proxy_changed),
+               NULL, NULL,
+               NULL,
+               G_TYPE_NONE, 3,
+               G_TYPE_UINT64,
+               G_TYPE_INT,
+               G_TYPE_DBUS_PROXY);
+}
+
+static void
+e_web_extension_container_init (EWebExtensionContainer *container)
+{
+       container->priv = e_web_extension_container_get_instance_private (container);
+       container->priv->proxy_by_page = g_hash_table_new_full (proxy_data_ident_hash, 
proxy_data_ident_equal, proxy_data_ident_free, proxy_page_data_free);
+       container->priv->used_stamps = g_hash_table_new (g_direct_hash, g_direct_equal);
+       container->priv->current_stamp = 0;
+}
+
+/**
+ * e_web_extension_container_new:
+ * @object_path: a D-Bus object path
+ * @interface_name: a D-Bus interface name
+ *
+ * Creates a new #EWebExtensionContainer, which opens a new D-Bus server
+ * for the given @object_path. If any such already exists, then it is returned
+ * instead.
+ *
+ * The @interface_name is used for the e_web_extension_container_call_simple()
+ * and for the #GDBusProxy instances managed by this object.
+ *
+ * Returns: (transfer full): a new #EWebExtensionContainer. Free it with
+ *    g_object_unref(), when no longer needed.
+ *
+ * Since: 3.34.1
+ **/
+EWebExtensionContainer *
+e_web_extension_container_new (const gchar *object_path,
+                              const gchar *interface_name)
+{
+       g_return_val_if_fail (object_path && *object_path, NULL);
+       g_return_val_if_fail (interface_name && *interface_name, NULL);
+
+       return g_object_new (E_TYPE_WEB_EXTENSION_CONTAINER,
+               "object-path", object_path,
+               "interface-name", interface_name,
+               NULL);
+}
+
+/**
+ * e_web_extension_container_get_object_path:
+ * @container: an #EWebExtensionContainer
+ *
+ * Returns: the object path the @container had been created with
+ *
+ * Since: 3.34.1
+ **/
+const gchar *
+e_web_extension_container_get_object_path (EWebExtensionContainer *container)
+{
+       g_return_val_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container), NULL);
+
+       return container->priv->object_path;
+}
+
+/**
+ * e_web_extension_container_get_interface_name:
+ * @container: an #EWebExtensionContainer
+ *
+ * Returns: the interface name the @container had been created with
+ *
+ * Since: 3.34.1
+ **/
+const gchar *
+e_web_extension_container_get_interface_name (EWebExtensionContainer *container)
+{
+       g_return_val_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container), NULL);
+
+       return container->priv->interface_name;
+}
+
+/**
+ * e_web_extension_container_get_server_guid:
+ * @container: an #EWebExtensionContainer
+ *
+ * Returns: (nullable): a GUID of the D-Bus server this @container created,
+ *    or %NULL, when no server is running.
+ *
+ * Since: 3.34.1
+ **/
+const gchar *
+e_web_extension_container_get_server_guid (EWebExtensionContainer *container)
+{
+       g_return_val_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container), NULL);
+
+       if (container->priv->dbus_server)
+               return g_dbus_server_get_guid (container->priv->dbus_server);
+
+       return NULL;
+}
+
+/**
+ * e_web_extension_container_get_server_address:
+ * @container: an #EWebExtensionContainer
+ *
+ * Returns an address of the created D-Bus server. There can be used
+ * e_web_extension_container_utils_connect_to_server() to connect to it.
+ *
+ * Returns: (nullable): an address of the D-Bus server this @container created,
+ *    or %NULL, when no server is running.
+ *
+ * Since: 3.34.1
+ **/
+const gchar *
+e_web_extension_container_get_server_address (EWebExtensionContainer *container)
+{
+       g_return_val_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container), NULL);
+
+       if (container->priv->dbus_server)
+               return g_dbus_server_get_client_address (container->priv->dbus_server);
+
+       return NULL;
+}
+
+/**
+ * e_web_extension_container_reserve_stamp:
+ * @container: an #EWebExtensionContainer
+ *
+ * Returns: a new stamp, which is used to distinguish between instances
+ *    of the Web Extensions.
+ *
+ * Since: 3.34.1
+ **/
+gint
+e_web_extension_container_reserve_stamp (EWebExtensionContainer *container)
+{
+       gint stamp, start = 0;
+
+       g_return_val_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container), 0);
+
+       do {
+               stamp = g_atomic_int_add (&container->priv->current_stamp, 1);
+               if (!stamp) {
+                       g_atomic_int_add (&container->priv->current_stamp, 1);
+               } else if (stamp < 0) {
+                       g_atomic_int_add (&container->priv->current_stamp, -stamp);
+
+                       stamp = g_atomic_int_add (&container->priv->current_stamp, 1);
+                       if (!stamp)
+                               g_atomic_int_add (&container->priv->current_stamp, 1);
+               }
+
+               if (!start) {
+                       start = stamp;
+               } else if (stamp == start) {
+                       g_warn_if_reached ();
+                       stamp = 0;
+                       break;
+               }
+       } while (stamp <= 0 || g_hash_table_contains (container->priv->used_stamps, GINT_TO_POINTER (stamp)));
+
+       if (stamp > 0)
+               g_hash_table_insert (container->priv->used_stamps, GINT_TO_POINTER (stamp), NULL);
+
+       return stamp;
+}
+
+/**
+ * e_web_extension_container_ref_proxy:
+ * @container: an #EWebExtensionContainer
+ * @page_id: a page ID, as returned by webkit_web_view_get_page_id()
+ * @stamp: a stamp of a Web Extension to look for
+ *
+ * Tries to search for a #GDBusProxy, which currently handles a Web Extension
+ * with @page_id and @stamp. The owner should listen to page-proxy-changed signal,
+ * to know when the proxy for the page changes.
+ *
+ * Free the returned proxy, if not NULL, with g_object_unref(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a #GDBusProxy for @page_id and @stamp,
+ *    or %NULL, when not found.
+ *
+ * Since: 3.34.1
+ **/
+GDBusProxy *
+e_web_extension_container_ref_proxy (EWebExtensionContainer *container,
+                                    guint64 page_id,
+                                    gint stamp)
+{
+       ProxyDataIdent pdi;
+       ProxyPageData *ppd;
+
+       g_return_val_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container), NULL);
+
+       pdi.page_id = page_id;
+       pdi.stamp = stamp;
+
+       ppd = g_hash_table_lookup (container->priv->proxy_by_page, &pdi);
+
+       if (!ppd || !ppd->proxy)
+               return NULL;
+
+       return g_object_ref (ppd->proxy);
+}
+
+/**
+ * e_web_extension_container_forget_stamp:
+ * @container: an #EWebExtensionContainer
+ * @stamp: a stamp of the Web Extension
+ *
+ * The owner of @container can call this function to free any resources
+ * related to @stamp, indicating that this @stamp is no longer used.
+ *
+ * Since: 3.34.1
+ **/
+void
+e_web_extension_container_forget_stamp (EWebExtensionContainer *container,
+                                       gint stamp)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+
+       g_return_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container));
+
+       g_hash_table_iter_init (&iter, container->priv->proxy_by_page);
+
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               ProxyDataIdent *pdi = key;
+               ProxyPageData *ppd = value;
+
+               if (pdi && ppd && pdi->stamp == stamp) {
+                       if (ppd->proxy)
+                               g_signal_emit (container, signals[PAGE_PROXY_CHANGED], 0, pdi->page_id, 
pdi->stamp, NULL);
+                       g_hash_table_remove (container->priv->proxy_by_page, pdi);
+                       break;
+               }
+       }
+
+       g_hash_table_remove (container->priv->used_stamps, GINT_TO_POINTER (stamp));
+}
+
+/**
+ * e_web_extension_container_call_simple:
+ * @container: an #EWebExtensionContainer
+ * @page_id: a page ID, as returned by webkit_web_view_get_page_id()
+ * @stamp: a stamp of a Web Extension to look for
+ * @method_name: a D-Bus method name
+ * @params: (nullable): optional parameters for the D-Bus method
+ *
+ * Either calls asynchronously the D-Bus method named @method_name with
+ * parameters @params immediately, when there exists a #GDBusProxy for
+ * the given @page_id and @stamp, or remembers this call and calls
+ * it as soon as the #GDBusProxy is created. The @method_name should
+ * be part of the interface this @container had been created for.
+ *
+ * The D-Bus call is made asynchronously. If there are more pending calls,
+ * then they are made in the order they had been added by this function.
+ *
+ * Since: 3.34.1
+ **/
+void
+e_web_extension_container_call_simple (EWebExtensionContainer *container,
+                                      guint64 page_id,
+                                      gint stamp,
+                                      const gchar *method_name,
+                                      GVariant *params)
+{
+       ProxyDataIdent pdi;
+       ProxyPageData *ppd;
+
+       g_return_if_fail (E_IS_WEB_EXTENSION_CONTAINER (container));
+       g_return_if_fail (method_name != NULL);
+
+       pdi.page_id = page_id;
+       pdi.stamp = stamp;
+
+       ppd = g_hash_table_lookup (container->priv->proxy_by_page, &pdi);
+       if (!ppd) {
+               ppd = proxy_page_data_new (NULL);
+
+               g_hash_table_insert (container->priv->proxy_by_page, proxy_data_ident_new (page_id, stamp), 
ppd);
+       }
+
+       if (ppd->proxy) {
+               if (!g_dbus_connection_is_closed (g_dbus_proxy_get_connection (ppd->proxy))) {
+                       g_dbus_proxy_call (ppd->proxy, method_name, params,
+                               G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, ewec_simple_call_finished_cb, 
NULL);
+               }
+       } else {
+               ppd->pending_calls = g_slist_prepend (ppd->pending_calls, call_simple_data_new (method_name, 
params));
+       }
+}
+
+/**
+ * e_web_extension_container_utils_connect_to_server:
+ * @server_address: a D-Bus server address to connect to
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: the user data to pass to @callback
+ *
+ * This is only a wrapper around g_dbus_connection_new_for_address(),
+ * setting a #GDBusObserver, which will authorize a peer the same
+ * way the preview or composer server expects it.
+ *
+ * Call e_web_extension_container_utils_connect_to_server_finish() to finish
+ * the request from the @callback.
+ *
+ * Since: 3.34.1
+ **/
+void
+e_web_extension_container_utils_connect_to_server (const gchar *server_address,
+                                                  GCancellable *cancellable,
+                                                  GAsyncReadyCallback callback,
+                                                  gpointer user_data)
+{
+       GDBusAuthObserver *observer;
+
+       g_return_if_fail (server_address != NULL);
+       g_return_if_fail (callback != NULL);
+
+       observer = g_dbus_auth_observer_new ();
+
+       g_signal_connect (observer, "authorize-authenticated-peer",
+               G_CALLBACK (authorize_authenticated_peer_cb), NULL);
+
+       g_dbus_connection_new_for_address (server_address,
+               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+               observer, cancellable,
+               callback, user_data);
+
+       g_object_unref (observer);
+}
+
+/**
+ * e_web_extension_container_utils_connect_to_server_finish:
+ * @result: a #GAsyncResult obtained from #GAsyncReadyCallback passed
+ *    to e_web_extension_container_utils_connect_to_server()
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes call of e_web_extension_container_utils_connect_to_server().
+ *
+ * Free the returned connection, if not %NULL, with g_object_unref(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): a newly allocated #GDBusConnection, or %NULL on error
+ *
+ * Since: 3.34.1
+ **/
+GDBusConnection *
+e_web_extension_container_utils_connect_to_server_finish (GAsyncResult *result,
+                                                         GError **error)
+{
+       return g_dbus_connection_new_for_address_finish (result, error);
+}
diff --git a/src/e-util/e-web-extension-container.h b/src/e-util/e-web-extension-container.h
new file mode 100644
index 0000000000..ecbacf0e59
--- /dev/null
+++ b/src/e-util/e-web-extension-container.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2019 Red Hat (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 (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION)
+#error "Only <e-util/e-util.h> should be included directly."
+#endif
+
+#ifndef E_WEB_EXTENSION_CONTAINER_H
+#define E_WEB_EXTENSION_CONTAINER_H
+
+/* Standard GObject macros */
+#define E_TYPE_WEB_EXTENSION_CONTAINER \
+       (e_web_extension_container_get_type ())
+#define E_WEB_EXTENSION_CONTAINER(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_WEB_EXTENSION_CONTAINER, EWebExtensionContainer))
+#define E_WEB_EXTENSION_CONTAINER_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_WEB_EXTENSION_CONTAINER, EWebExtensionContainerClass))
+#define E_IS_WEB_EXTENSION_CONTAINER(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_WEB_EXTENSION_CONTAINER))
+#define E_IS_WEB_EXTENSION_CONTAINER_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_WEB_EXTENSION_CONTAINER))
+#define E_WEB_EXTENSION_CONTAINER_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_WEB_EXTENSION_CONTAINER, EWebExtensionContainerClass))
+
+G_BEGIN_DECLS
+
+#include <gio/gio.h>
+
+typedef struct _EWebExtensionContainer EWebExtensionContainer;
+typedef struct _EWebExtensionContainerClass EWebExtensionContainerClass;
+typedef struct _EWebExtensionContainerPrivate EWebExtensionContainerPrivate;
+
+struct _EWebExtensionContainer {
+       GObject parent;
+       EWebExtensionContainerPrivate *priv;
+};
+
+struct _EWebExtensionContainerClass {
+       GObjectClass parent_class;
+
+       /* Signals */
+       void            (* page_proxy_changed)          (EWebExtensionContainer *container,
+                                                        guint64 page_id,
+                                                        gint stamp,
+                                                        GDBusProxy *proxy);
+};
+
+GType          e_web_extension_container_get_type      (void) G_GNUC_CONST;
+EWebExtensionContainer *
+               e_web_extension_container_new           (const gchar *object_path,
+                                                        const gchar *interface_name);
+const gchar *  e_web_extension_container_get_object_path
+                                                       (EWebExtensionContainer *container);
+const gchar *  e_web_extension_container_get_interface_name
+                                                       (EWebExtensionContainer *container);
+const gchar *  e_web_extension_container_get_server_guid
+                                                       (EWebExtensionContainer *container);
+const gchar *  e_web_extension_container_get_server_address
+                                                       (EWebExtensionContainer *container);
+gint           e_web_extension_container_reserve_stamp (EWebExtensionContainer *container);
+GDBusProxy *   e_web_extension_container_ref_proxy     (EWebExtensionContainer *container,
+                                                        guint64 page_id,
+                                                        gint stamp);
+void           e_web_extension_container_forget_stamp  (EWebExtensionContainer *container,
+                                                        gint stamp);
+void           e_web_extension_container_call_simple   (EWebExtensionContainer *container,
+                                                        guint64 page_id,
+                                                        gint stamp,
+                                                        const gchar *method_name,
+                                                        GVariant *params);
+
+void           e_web_extension_container_utils_connect_to_server
+                                                       (const gchar *server_address,
+                                                        GCancellable *cancellable,
+                                                        GAsyncReadyCallback callback,
+                                                        gpointer user_data);
+GDBusConnection *
+               e_web_extension_container_utils_connect_to_server_finish
+                                                       (GAsyncResult *result,
+                                                        GError **error);
+
+G_END_DECLS
+
+#endif /* E_WEB_EXTENSION_CONTAINER_H */
diff --git a/src/e-util/e-web-view.c b/src/e-util/e-web-view.c
index 61fb944fe3..c1114ef885 100644
--- a/src/e-util/e-web-view.c
+++ b/src/e-util/e-web-view.c
@@ -38,6 +38,7 @@
 #include "e-popup-action.h"
 #include "e-selectable.h"
 #include "e-stock-request.h"
+#include "e-web-extension-container.h"
 
 #include "web-extensions/e-web-extension-names.h"
 
@@ -47,6 +48,8 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_WEB_VIEW, EWebViewPrivate))
 
+static void e_web_view_set_web_extension_proxy (EWebView *web_view, GDBusProxy *proxy);
+
 typedef struct _AsyncContext AsyncContext;
 
 typedef struct _ElementClickedData {
@@ -80,8 +83,9 @@ struct _EWebViewPrivate {
 
        GHashTable *old_settings;
 
-       GDBusProxy *web_extension;
-       guint web_extension_watch_name_id;
+       EWebExtensionContainer *container;
+       GDBusProxy *web_extension_proxy;
+       gint stamp; /* Changed only in the main thread, doesn't need locking */
 
        WebKitFindController *find_controller;
        gulong found_text_handler_id;
@@ -124,7 +128,8 @@ enum {
        PROP_PASTE_TARGET_LIST,
        PROP_PRINT_PROXY,
        PROP_SAVE_AS_PROXY,
-       PROP_SELECTED_URI
+       PROP_SELECTED_URI,
+       PROP_WEB_EXTENSION_PROXY
 };
 
 enum {
@@ -208,6 +213,19 @@ action_copy_clipboard_cb (GtkAction *action,
        e_web_view_copy_clipboard (web_view);
 }
 
+static gint
+e_web_view_assign_new_stamp (EWebView *web_view)
+{
+       g_return_val_if_fail (E_IS_WEB_VIEW (web_view), 0);
+
+       if (web_view->priv->stamp)
+               e_web_extension_container_forget_stamp (web_view->priv->container, web_view->priv->stamp);
+
+       web_view->priv->stamp = e_web_extension_container_reserve_stamp (web_view->priv->container);
+
+       return web_view->priv->stamp;
+}
+
 static void
 e_web_view_search_web_get_selection_cb (GObject *source,
                                        GAsyncResult *result,
@@ -731,22 +749,16 @@ web_view_decide_policy_cb (EWebView *web_view,
 static void
 e_web_view_ensure_body_class (EWebView *web_view)
 {
-       GDBusProxy *web_extension;
+       guint64 page_id;
 
        g_return_if_fail (E_IS_WEB_VIEW (web_view));
 
-       web_extension = e_web_view_get_web_extension_proxy (web_view);
-       if (!web_extension)
-               return;
+       page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               web_extension,
+       e_web_extension_container_call_simple (web_view->priv->container,
+               page_id, web_view->priv->stamp,
                "EWebViewEnsureBodyClass",
-               g_variant_new (
-                       "(ts)",
-                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view)),
-                       "-e-web-view-background-color -e-web-view-text-color"),
-               NULL);
+               g_variant_new ("(ts)", page_id, "-e-web-view-background-color -e-web-view-text-color"));
 }
 
 static void
@@ -855,11 +867,30 @@ web_view_constructor (GType type,
                param_spec = g_object_class_find_property(object_class, "user-content-manager");
                if ((param = find_property (n_construct_properties, construct_properties, param_spec)))
                        g_value_take_object (param->value, webkit_user_content_manager_new ());
+               param_spec = g_object_class_find_property (object_class, "web-context");
+               if ((param = find_property (n_construct_properties, construct_properties, param_spec))) {
+                       /* Share one web_context between all editors, thus there is one WebProcess
+                          for all the editors (and one for the preview). */
+                       static gpointer web_context = NULL;
+
+                       if (!web_context) {
+                               web_context = webkit_web_context_new ();
+
+                               webkit_web_context_set_cache_model (web_context, 
WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER);
+                               webkit_web_context_set_web_extensions_directory (web_context, 
EVOLUTION_WEB_EXTENSIONS_DIR);
+
+                               g_object_add_weak_pointer (G_OBJECT (web_context), &web_context);
+                       } else {
+                               g_object_ref (web_context);
+                       }
+
+                       g_value_take_object (param->value, web_context);
+               }
        }
 
        g_type_class_unref (object_class);
 
-       return G_OBJECT_CLASS (e_web_view_parent_class)->constructor(type, n_construct_properties, 
construct_properties);
+       return G_OBJECT_CLASS (e_web_view_parent_class)->constructor (type, n_construct_properties, 
construct_properties);
 }
 
 static void
@@ -1019,6 +1050,11 @@ web_view_get_property (GObject *object,
                                E_WEB_VIEW (object)));
                        return;
 
+               case PROP_WEB_EXTENSION_PROXY:
+                       g_value_set_object (
+                               value, e_web_view_get_web_extension_proxy (
+                               E_WEB_VIEW (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1057,11 +1093,6 @@ web_view_dispose (GObject *object)
                priv->antialiasing_changed_handler_id = 0;
        }
 
-       if (priv->web_extension_watch_name_id > 0) {
-               g_bus_unwatch_name (priv->web_extension_watch_name_id);
-               priv->web_extension_watch_name_id = 0;
-       }
-
        if (priv->found_text_handler_id > 0) {
                g_signal_handler_disconnect (
                        priv->find_controller,
@@ -1076,39 +1107,23 @@ web_view_dispose (GObject *object)
                priv->failed_to_find_text_handler_id = 0;
        }
 
-       if (priv->web_extension && priv->web_extension_clipboard_flags_changed_signal_id) {
-               g_dbus_connection_signal_unsubscribe (
-                       g_dbus_proxy_get_connection (priv->web_extension),
-                       priv->web_extension_clipboard_flags_changed_signal_id);
-               priv->web_extension_clipboard_flags_changed_signal_id = 0;
-       }
-
-       if (priv->web_extension && priv->web_extension_need_input_changed_signal_id) {
-               g_dbus_connection_signal_unsubscribe (
-                       g_dbus_proxy_get_connection (priv->web_extension),
-                       priv->web_extension_need_input_changed_signal_id);
-               priv->web_extension_need_input_changed_signal_id = 0;
-       }
-
-       if (priv->web_extension && priv->web_extension_element_clicked_signal_id) {
-               g_dbus_connection_signal_unsubscribe (
-                       g_dbus_proxy_get_connection (priv->web_extension),
-                       priv->web_extension_element_clicked_signal_id);
-               priv->web_extension_element_clicked_signal_id = 0;
-       }
-
        g_hash_table_remove_all (priv->element_clicked_cbs);
 
        g_slist_free_full (priv->content_requests, g_object_unref);
        priv->content_requests = NULL;
 
+       e_web_view_set_web_extension_proxy (E_WEB_VIEW (object), NULL);
+
+       if (priv->container && priv->stamp)
+               e_web_extension_container_forget_stamp (priv->container, priv->stamp);
+
        g_clear_object (&priv->ui_manager);
        g_clear_object (&priv->open_proxy);
        g_clear_object (&priv->print_proxy);
        g_clear_object (&priv->save_as_proxy);
        g_clear_object (&priv->aliasing_settings);
        g_clear_object (&priv->font_settings);
-       g_clear_object (&priv->web_extension);
+       g_clear_object (&priv->container);
 
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (e_web_view_parent_class)->dispose (object);
@@ -1252,16 +1267,11 @@ e_web_view_register_content_request_for_scheme (EWebView *web_view,
 static void
 web_view_initialize (WebKitWebView *web_view)
 {
-       WebKitWebContext *web_context;
        EContentRequest *content_request;
        const gchar *id = "org.gnome.settings-daemon.plugins.xsettings";
        GSettings *settings = NULL, *font_settings;
        GSettingsSchema *settings_schema;
 
-       web_context = webkit_web_view_get_context (web_view);
-
-       webkit_web_context_set_cache_model (web_context, WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER);
-
        content_request = e_file_request_new ();
        e_web_view_register_content_request_for_scheme (E_WEB_VIEW (web_view), "evo-file", content_request);
        g_object_unref (content_request);
@@ -1291,11 +1301,27 @@ web_view_initialize (WebKitWebView *web_view)
                g_object_unref (settings);
 }
 
+static void
+e_web_view_initialize_web_extensions_cb (WebKitWebContext *web_context,
+                                        gpointer user_data)
+{
+       EWebView *web_view = user_data;
+
+       g_return_if_fail (E_IS_WEB_VIEW (web_view));
+       g_return_if_fail (web_view->priv->container);
+
+       webkit_web_context_set_web_extensions_directory (web_context, EVOLUTION_WEB_EXTENSIONS_DIR);
+       webkit_web_context_set_web_extensions_initialization_user_data (web_context,
+               g_variant_new ("(ss)",
+                       e_web_extension_container_get_server_guid (web_view->priv->container),
+                       e_web_extension_container_get_server_address (web_view->priv->container)));
+}
 
 static void
 web_view_constructed (GObject *object)
 {
        WebKitSettings *web_settings;
+       EWebView *web_view = E_WEB_VIEW (object);
 #ifndef G_OS_WIN32
        GSettings *settings;
 
@@ -1314,11 +1340,14 @@ web_view_constructed (GObject *object)
        g_object_unref (settings);
 #endif
 
-       e_extensible_load_extensions (E_EXTENSIBLE (object));
+       g_signal_connect_object (webkit_web_view_get_context (WEBKIT_WEB_VIEW (web_view)), 
"initialize-web-extensions",
+               G_CALLBACK (e_web_view_initialize_web_extensions_cb), web_view, 0);
 
        /* Chain up to parent's constructed() method. */
        G_OBJECT_CLASS (e_web_view_parent_class)->constructed (object);
 
+       e_extensible_load_extensions (E_EXTENSIBLE (object));
+
        web_settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (object));
 
        g_object_set (
@@ -1334,7 +1363,7 @@ web_view_constructed (GObject *object)
 
        web_view_initialize (WEBKIT_WEB_VIEW (object));
 
-       web_view_set_find_controller (E_WEB_VIEW (object));
+       web_view_set_find_controller (web_view);
 }
 
 static void
@@ -1520,25 +1549,40 @@ static void
 web_view_load_string (EWebView *web_view,
                       const gchar *string)
 {
+       gchar *uri_with_stamp;
+
+       uri_with_stamp = g_strdup_printf ("evo-file:///?evo-stamp=%d", e_web_view_assign_new_stamp 
(web_view));
+
        if (!string || !*string) {
-               webkit_web_view_load_html (WEBKIT_WEB_VIEW (web_view), "", "evo-file://");
+               webkit_web_view_load_html (WEBKIT_WEB_VIEW (web_view), "", uri_with_stamp);
        } else {
                GBytes *bytes;
 
                bytes = g_bytes_new (string, strlen (string));
-               webkit_web_view_load_bytes (WEBKIT_WEB_VIEW (web_view), bytes, NULL, NULL, "evo-file://");
+               webkit_web_view_load_bytes (WEBKIT_WEB_VIEW (web_view), bytes, NULL, NULL, uri_with_stamp);
                g_bytes_unref (bytes);
        }
+
+       g_free (uri_with_stamp);
 }
 
 static void
 web_view_load_uri (EWebView *web_view,
                    const gchar *uri)
 {
+       gchar *uri_with_stamp;
+
        if (uri == NULL)
                uri = "about:blank";
 
-       webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), uri);
+       if (strchr (uri, '?'))
+               uri_with_stamp = g_strdup_printf ("%s&evo-stamp=%d", uri, e_web_view_assign_new_stamp 
(web_view));
+       else
+               uri_with_stamp = g_strdup_printf ("%s?evo-stamp=%d", uri, e_web_view_assign_new_stamp 
(web_view));
+
+       webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), uri_with_stamp);
+
+       g_free (uri_with_stamp);
 }
 
 static gchar *
@@ -1585,21 +1629,17 @@ web_view_register_element_clicked_hfunc (gpointer key,
 {
        const gchar *elem_class = key;
        EWebView *web_view = user_data;
+       guint64 page_id;
 
        g_return_if_fail (elem_class && *elem_class);
        g_return_if_fail (E_IS_WEB_VIEW (web_view));
 
-       if (!web_view->priv->web_extension)
-               return;
+       page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               web_view->priv->web_extension,
+       e_web_extension_container_call_simple (web_view->priv->container,
+               page_id, web_view->priv->stamp,
                "RegisterElementClicked",
-               g_variant_new (
-                       "(ts)",
-                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view)),
-                       elem_class),
-               NULL);
+               g_variant_new ("(ts)", page_id, elem_class));
 }
 
 static void
@@ -1704,31 +1744,50 @@ web_view_element_clicked_signal_cb (GDBusConnection *connection,
 }
 
 static void
-web_extension_proxy_created_cb (GDBusProxy *proxy,
-                                GAsyncResult *result,
-                                GWeakRef *web_view_ref)
+e_web_view_set_web_extension_proxy (EWebView *web_view,
+                                   GDBusProxy *proxy)
 {
-       EWebView *web_view;
-       GError *error = NULL;
+       g_return_if_fail (E_IS_WEB_VIEW (web_view));
 
-       g_return_if_fail (web_view_ref != NULL);
+       if (web_view->priv->web_extension_proxy == proxy)
+               return;
 
-       web_view = g_weak_ref_get (web_view_ref);
+       if (web_view->priv->web_extension_proxy) {
+               GDBusConnection *connection;
 
-       if (!web_view) {
-               e_weak_ref_free (web_view_ref);
-               return;
+               connection = g_dbus_proxy_get_connection (web_view->priv->web_extension_proxy);
+
+               if (connection && g_dbus_connection_is_closed (connection))
+                       connection = NULL;
+
+               if (web_view->priv->web_extension_clipboard_flags_changed_signal_id) {
+                       if (connection)
+                               g_dbus_connection_signal_unsubscribe (connection, 
web_view->priv->web_extension_clipboard_flags_changed_signal_id);
+                       web_view->priv->web_extension_clipboard_flags_changed_signal_id = 0;
+               }
+
+               if (web_view->priv->web_extension_need_input_changed_signal_id) {
+                       if (connection)
+                               g_dbus_connection_signal_unsubscribe (connection, 
web_view->priv->web_extension_need_input_changed_signal_id);
+                       web_view->priv->web_extension_need_input_changed_signal_id = 0;
+               }
+
+               if (web_view->priv->web_extension_element_clicked_signal_id) {
+                       if (connection)
+                               g_dbus_connection_signal_unsubscribe (connection, 
web_view->priv->web_extension_element_clicked_signal_id);
+                       web_view->priv->web_extension_element_clicked_signal_id = 0;
+               }
+
+               g_clear_object (&web_view->priv->web_extension_proxy);
        }
 
-       web_view->priv->web_extension = g_dbus_proxy_new_finish (result, &error);
-       if (!web_view->priv->web_extension) {
-               g_warning ("Error creating web extension proxy: %s\n", error->message);
-               g_error_free (error);
-       } else {
+       if (proxy) {
+               web_view->priv->web_extension_proxy = g_object_ref (proxy);
+
                web_view->priv->web_extension_clipboard_flags_changed_signal_id =
                        g_dbus_connection_signal_subscribe (
-                               g_dbus_proxy_get_connection (web_view->priv->web_extension),
-                               g_dbus_proxy_get_name (web_view->priv->web_extension),
+                               g_dbus_proxy_get_connection (proxy),
+                               g_dbus_proxy_get_name (proxy),
                                E_WEB_EXTENSION_INTERFACE,
                                "ClipboardFlagsChanged",
                                E_WEB_EXTENSION_OBJECT_PATH,
@@ -1740,8 +1799,8 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
 
                web_view->priv->web_extension_need_input_changed_signal_id =
                        g_dbus_connection_signal_subscribe (
-                               g_dbus_proxy_get_connection (web_view->priv->web_extension),
-                               g_dbus_proxy_get_name (web_view->priv->web_extension),
+                               g_dbus_proxy_get_connection (proxy),
+                               g_dbus_proxy_get_name (proxy),
                                E_WEB_EXTENSION_INTERFACE,
                                "NeedInputChanged",
                                E_WEB_EXTENSION_OBJECT_PATH,
@@ -1753,8 +1812,8 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
 
                web_view->priv->web_extension_element_clicked_signal_id =
                        g_dbus_connection_signal_subscribe (
-                               g_dbus_proxy_get_connection (web_view->priv->web_extension),
-                               g_dbus_proxy_get_name (web_view->priv->web_extension),
+                               g_dbus_proxy_get_connection (proxy),
+                               g_dbus_proxy_get_name (proxy),
                                E_WEB_EXTENSION_INTERFACE,
                                "ElementClicked",
                                E_WEB_EXTENSION_OBJECT_PATH,
@@ -1763,77 +1822,31 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
                                web_view_element_clicked_signal_cb,
                                web_view,
                                NULL);
-
-               g_hash_table_foreach (web_view->priv->element_clicked_cbs, 
web_view_register_element_clicked_hfunc, web_view);
-
-               e_web_view_ensure_body_class (web_view);
-               style_updated_cb (web_view);
        }
 
-       g_clear_object (&web_view);
-       e_weak_ref_free (web_view_ref);
+       g_object_notify (G_OBJECT (web_view), "web-extension-proxy");
 }
 
 static void
-web_extension_appeared_cb (GDBusConnection *connection,
-                           const gchar *name,
-                           const gchar *name_owner,
-                           GWeakRef *web_view_ref)
+e_web_view_page_proxy_changed_cb (EWebExtensionContainer *container,
+                                 guint64 page_id,
+                                 gint stamp,
+                                 GDBusProxy *proxy,
+                                 gpointer user_data)
 {
-       EWebView *web_view;
-
-       g_return_if_fail (web_view_ref != NULL);
-
-       web_view = g_weak_ref_get (web_view_ref);
-
-       if (!web_view)
-               return;
-
-       g_dbus_proxy_new (
-               connection,
-               G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
-               G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
-               NULL,
-               name,
-               E_WEB_EXTENSION_OBJECT_PATH,
-               E_WEB_EXTENSION_INTERFACE,
-               NULL,
-               (GAsyncReadyCallback) web_extension_proxy_created_cb,
-               e_weak_ref_new (web_view));
-
-       g_clear_object (&web_view);
-}
-
-static void
-web_extension_vanished_cb (GDBusConnection *connection,
-                           const gchar *name,
-                           GWeakRef *web_view_ref)
-{
-       EWebView *web_view;
-
-       g_return_if_fail (web_view_ref != NULL);
+       EWebView *web_view = user_data;
 
-       web_view = g_weak_ref_get (web_view_ref);
+       g_return_if_fail (E_IS_WEB_VIEW (web_view));
 
-       if (!web_view)
-               return;
+       if (stamp == web_view->priv->stamp &&
+           page_id == webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view))) {
+               e_web_view_set_web_extension_proxy (web_view, proxy);
 
-       g_clear_object (&web_view->priv->web_extension);
-       g_clear_object (&web_view);
-}
+               g_hash_table_foreach (web_view->priv->element_clicked_cbs, 
web_view_register_element_clicked_hfunc, web_view);
 
-static void
-web_view_watch_web_extension (EWebView *web_view)
-{
-       web_view->priv->web_extension_watch_name_id =
-               g_bus_watch_name (
-                       G_BUS_TYPE_SESSION,
-                       E_WEB_EXTENSION_SERVICE_NAME,
-                       G_BUS_NAME_WATCHER_FLAGS_NONE,
-                       (GBusNameAppearedCallback) web_extension_appeared_cb,
-                       (GBusNameVanishedCallback) web_extension_vanished_cb,
-                       e_weak_ref_new (web_view),
-                       (GDestroyNotify) e_weak_ref_free);
+               e_web_view_ensure_body_class (web_view);
+               style_updated_cb (web_view);
+       }
 }
 
 GDBusProxy *
@@ -1841,7 +1854,7 @@ e_web_view_get_web_extension_proxy (EWebView *web_view)
 {
        g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
 
-       return web_view->priv->web_extension;
+       return web_view->priv->web_extension_proxy;
 }
 
 static void
@@ -2348,6 +2361,16 @@ e_web_view_class_init (EWebViewClass *class)
                        NULL,
                        G_PARAM_READWRITE));
 
+       g_object_class_install_property (
+               object_class,
+               PROP_WEB_EXTENSION_PROXY,
+               g_param_spec_object (
+                       "web-extension-proxy",
+                       "Web Extension Proxy",
+                       NULL,
+                       G_TYPE_DBUS_PROXY,
+                       G_PARAM_READABLE));
+
        signals[NEW_ACTIVITY] = g_signal_new (
                "new-activity",
                G_TYPE_FROM_CLASS (class),
@@ -2433,14 +2456,6 @@ e_web_view_selectable_init (ESelectableInterface *iface)
        iface->select_all = web_view_selectable_select_all;
 }
 
-static void
-initialize_web_extensions_cb (WebKitWebContext *web_context)
-{
-       /* Set the web extensions dir before the process is launched */
-       webkit_web_context_set_web_extensions_directory (
-               web_context, EVOLUTION_WEB_EXTENSIONS_DIR);
-}
-
 static void
 e_web_view_init (EWebView *web_view)
 {
@@ -2456,8 +2471,12 @@ e_web_view_init (EWebView *web_view)
 
        web_view->priv = E_WEB_VIEW_GET_PRIVATE (web_view);
 
+       web_view->priv->container = e_web_extension_container_new (E_WEB_EXTENSION_OBJECT_PATH, 
E_WEB_EXTENSION_INTERFACE);
        web_view->priv->old_settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
(GDestroyNotify) g_variant_unref);
 
+       g_signal_connect_object (web_view->priv->container, "page-proxy-changed",
+               G_CALLBACK (e_web_view_page_proxy_changed_cb), web_view, 0);
+
        g_signal_connect (
                web_view, "context-menu",
                G_CALLBACK (web_view_context_menu_cb), NULL);
@@ -2471,10 +2490,6 @@ e_web_view_init (EWebView *web_view)
                G_CALLBACK (web_view_decide_policy_cb),
                NULL);
 
-       g_signal_connect (
-               webkit_web_context_get_default (), "initialize-web-extensions",
-               G_CALLBACK (initialize_web_extensions_cb), NULL);
-
        g_signal_connect (
                web_view, "load-changed",
                G_CALLBACK (web_view_load_changed_cb), NULL);
@@ -2494,8 +2509,6 @@ e_web_view_init (EWebView *web_view)
                ui_manager, "connect-proxy",
                G_CALLBACK (web_view_connect_proxy_cb), web_view);
 
-       web_view_watch_web_extension (web_view);
-
        settings = e_util_ref_settings ("org.gnome.desktop.interface");
        web_view->priv->font_settings = g_object_ref (settings);
        handler_id = g_signal_connect_swapped (
@@ -4580,23 +4593,17 @@ void
 e_web_view_create_and_add_css_style_sheet (EWebView *web_view,
                                            const gchar *style_sheet_id)
 {
-       GDBusProxy *web_extension;
+       guint64 page_id;
 
        g_return_if_fail (E_IS_WEB_VIEW (web_view));
        g_return_if_fail (style_sheet_id && *style_sheet_id);
 
-       web_extension = e_web_view_get_web_extension_proxy (web_view);
-       if (web_extension) {
-               e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       web_extension,
-                       "CreateAndAddCSSStyleSheet",
-                       g_variant_new (
-                               "(ts)",
-                               webkit_web_view_get_page_id (
-                                       WEBKIT_WEB_VIEW (web_view)),
-                               style_sheet_id),
-                       NULL);
-       }
+       page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
+
+       e_web_extension_container_call_simple (web_view->priv->container,
+               page_id, web_view->priv->stamp,
+               "CreateAndAddCSSStyleSheet",
+               g_variant_new ("(ts)", page_id, style_sheet_id));
 }
 
 /**
@@ -4618,27 +4625,19 @@ e_web_view_add_css_rule_into_style_sheet (EWebView *web_view,
                                           const gchar *selector,
                                           const gchar *style)
 {
-       GDBusProxy *web_extension;
+       guint64 page_id;
 
        g_return_if_fail (E_IS_WEB_VIEW (web_view));
        g_return_if_fail (style_sheet_id && *style_sheet_id);
        g_return_if_fail (selector && *selector);
        g_return_if_fail (style && *style);
 
-       web_extension = e_web_view_get_web_extension_proxy (web_view);
-       if (web_extension) {
-               e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       web_extension,
-                       "AddCSSRuleIntoStyleSheet",
-                       g_variant_new (
-                               "(tsss)",
-                               webkit_web_view_get_page_id (
-                                       WEBKIT_WEB_VIEW (web_view)),
-                               style_sheet_id,
-                               selector,
-                               style),
-                       NULL);
-       }
+       page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
+
+       e_web_extension_container_call_simple (web_view->priv->container,
+               page_id, web_view->priv->stamp,
+               "AddCSSRuleIntoStyleSheet",
+               g_variant_new ("(tsss)", page_id, style_sheet_id, selector, style));
 }
 
 /**
@@ -4719,26 +4718,20 @@ e_web_view_set_document_iframe_src (EWebView *web_view,
                                    const gchar *document_uri,
                                    const gchar *new_iframe_src)
 {
-       GDBusProxy *web_extension;
+       guint64 page_id;
 
        g_return_if_fail (E_IS_WEB_VIEW (web_view));
 
-       web_extension = e_web_view_get_web_extension_proxy (web_view);
-       if (!web_extension)
-               return;
-
        /* Cannot call this synchronously, blocking the local main loop, because the reload
           can on the WebProcess side can be asking for a redirection policy, waiting
           for a response which may be waiting in the blocked main loop. */
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               web_extension,
+
+       page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
+
+       e_web_extension_container_call_simple (web_view->priv->container,
+               page_id, web_view->priv->stamp,
                "SetDocumentIFrameSrc",
-               g_variant_new (
-                       "(tss)",
-                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view)),
-                       document_uri,
-                       new_iframe_src),
-               NULL);
+               g_variant_new ("(tss)", page_id, document_uri, new_iframe_src));
 }
 
 /**
@@ -4867,24 +4860,17 @@ e_web_view_set_element_hidden (EWebView *web_view,
                               const gchar *element_id,
                               gboolean hidden)
 {
-       GDBusProxy *web_extension;
+       guint64 page_id;
 
        g_return_if_fail (E_IS_WEB_VIEW (web_view));
        g_return_if_fail (element_id && *element_id);
 
-       web_extension = e_web_view_get_web_extension_proxy (web_view);
-       if (!web_extension)
-               return;
+       page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               web_extension,
+       e_web_extension_container_call_simple (web_view->priv->container,
+               page_id, web_view->priv->stamp,
                "SetElementHidden",
-               g_variant_new (
-                       "(tsb)",
-                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view)),
-                       element_id,
-                       hidden),
-               NULL);
+               g_variant_new ("(tsb)", page_id, element_id, hidden));
 }
 
 void
@@ -4894,27 +4880,18 @@ e_web_view_set_element_style_property (EWebView *web_view,
                                       const gchar *value,
                                       const gchar *priority)
 {
-       GDBusProxy *web_extension;
+       guint64 page_id;
 
        g_return_if_fail (E_IS_WEB_VIEW (web_view));
        g_return_if_fail (element_id && *element_id);
        g_return_if_fail (property_name && *property_name);
 
-       web_extension = e_web_view_get_web_extension_proxy (web_view);
-       if (!web_extension)
-               return;
+       page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               web_extension,
+       e_web_extension_container_call_simple (web_view->priv->container,
+               page_id, web_view->priv->stamp,
                "SetElementStyleProperty",
-               g_variant_new (
-                       "(tssss)",
-                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view)),
-                       element_id,
-                       property_name,
-                       value ? value : "",
-                       priority ? priority : ""),
-               NULL);
+               g_variant_new ("(tssss)", page_id, element_id, property_name, value ? value : "", priority ? 
priority : ""));
 }
 
 void
@@ -4924,25 +4901,16 @@ e_web_view_set_element_attribute (EWebView *web_view,
                                  const gchar *qualified_name,
                                  const gchar *value)
 {
-       GDBusProxy *web_extension;
+       guint64 page_id;
 
        g_return_if_fail (E_IS_WEB_VIEW (web_view));
        g_return_if_fail (element_id && *element_id);
        g_return_if_fail (qualified_name && *qualified_name);
 
-       web_extension = e_web_view_get_web_extension_proxy (web_view);
-       if (!web_extension)
-               return;
+       page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               web_extension,
+       e_web_extension_container_call_simple (web_view->priv->container,
+               page_id, web_view->priv->stamp,
                "SetElementAttribute",
-               g_variant_new (
-                       "(tssss)",
-                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view)),
-                       element_id,
-                       namespace_uri ? namespace_uri : "",
-                       qualified_name,
-                       value ? value : ""),
-               NULL);
+               g_variant_new ("(tssss)", page_id, element_id, namespace_uri ? namespace_uri : "", 
qualified_name, value ? value : ""));
 }
diff --git a/src/mail/e-mail-display.c b/src/mail/e-mail-display.c
index e7b5d7be91..76e2c9189a 100644
--- a/src/mail/e-mail-display.c
+++ b/src/mail/e-mail-display.c
@@ -85,6 +85,7 @@ struct _EMailDisplayPrivate {
        EMailRemoteContent *remote_content;
        GHashTable *skipped_remote_content_sites;
 
+       GDBusConnection *web_extension_connection;
        guint web_extension_headers_collapsed_signal_id;
        guint web_extension_mail_part_appeared_signal_id;
 };
@@ -586,37 +587,49 @@ setup_dom_bindings (EMailDisplay *display)
 
        web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (display));
 
-       if (web_extension) {
-               if (display->priv->web_extension_headers_collapsed_signal_id == 0) {
-                       display->priv->web_extension_headers_collapsed_signal_id =
-                               g_dbus_connection_signal_subscribe (
-                                       g_dbus_proxy_get_connection (web_extension),
-                                       g_dbus_proxy_get_name (web_extension),
-                                       E_WEB_EXTENSION_INTERFACE,
-                                       "HeadersCollapsed",
-                                       E_WEB_EXTENSION_OBJECT_PATH,
-                                       NULL,
-                                       G_DBUS_SIGNAL_FLAGS_NONE,
-                                       (GDBusSignalCallback) headers_collapsed_signal_cb,
-                                       display,
-                                       NULL);
+       if (display->priv->web_extension_connection) {
+               if (display->priv->web_extension_headers_collapsed_signal_id) {
+                       g_dbus_connection_signal_unsubscribe (display->priv->web_extension_connection, 
display->priv->web_extension_headers_collapsed_signal_id);
+                       display->priv->web_extension_headers_collapsed_signal_id = 0;
                }
 
-               if (display->priv->web_extension_mail_part_appeared_signal_id == 0) {
-                       display->priv->web_extension_mail_part_appeared_signal_id =
-                               g_dbus_connection_signal_subscribe (
-                                       g_dbus_proxy_get_connection (web_extension),
-                                       g_dbus_proxy_get_name (web_extension),
-                                       E_WEB_EXTENSION_INTERFACE,
-                                       "MailPartAppeared",
-                                       E_WEB_EXTENSION_OBJECT_PATH,
-                                       NULL,
-                                       G_DBUS_SIGNAL_FLAGS_NONE,
-                                       mail_display_mail_part_appeared_signal_cb,
-                                       display,
-                                       NULL);
+               if (display->priv->web_extension_mail_part_appeared_signal_id) {
+                       g_dbus_connection_signal_unsubscribe (display->priv->web_extension_connection, 
display->priv->web_extension_mail_part_appeared_signal_id);
+                       display->priv->web_extension_mail_part_appeared_signal_id = 0;
                }
 
+               g_clear_object (&display->priv->web_extension_connection);
+       }
+
+       if (web_extension) {
+               display->priv->web_extension_connection = g_object_ref (g_dbus_proxy_get_connection 
(web_extension));
+
+               display->priv->web_extension_headers_collapsed_signal_id =
+                       g_dbus_connection_signal_subscribe (
+                               display->priv->web_extension_connection,
+                               g_dbus_proxy_get_name (web_extension),
+                               E_WEB_EXTENSION_INTERFACE,
+                               "HeadersCollapsed",
+                               E_WEB_EXTENSION_OBJECT_PATH,
+                               NULL,
+                               G_DBUS_SIGNAL_FLAGS_NONE,
+                               (GDBusSignalCallback) headers_collapsed_signal_cb,
+                               display,
+                               NULL);
+
+               display->priv->web_extension_mail_part_appeared_signal_id =
+                       g_dbus_connection_signal_subscribe (
+                               display->priv->web_extension_connection,
+                               g_dbus_proxy_get_name (web_extension),
+                               E_WEB_EXTENSION_INTERFACE,
+                               "MailPartAppeared",
+                               E_WEB_EXTENSION_OBJECT_PATH,
+                               NULL,
+                               G_DBUS_SIGNAL_FLAGS_NONE,
+                               mail_display_mail_part_appeared_signal_cb,
+                               display,
+                               NULL);
+
                e_util_invoke_g_dbus_proxy_call_with_error_check (
                        web_extension,
                        "EMailDisplayBindDOM",
@@ -1303,6 +1316,21 @@ mail_display_load_changed_cb (WebKitWebView *wk_web_view,
        }
 }
 
+static void
+mail_display_web_extension_proxy_notify_cb (GObject *object,
+                                           GParamSpec *param,
+                                           gpointer user_data)
+{
+       EMailDisplay *display;
+
+       g_return_if_fail (E_IS_MAIL_DISPLAY (object));
+
+       display = E_MAIL_DISPLAY (object);
+
+       setup_dom_bindings (display);
+       mail_parts_bind_dom (display);
+}
+
 static void
 mail_display_set_property (GObject *object,
                            guint property_id,
@@ -1429,26 +1457,18 @@ mail_display_dispose (GObject *object)
                        0, 0, NULL, NULL, object);
        }
 
-       if (priv->web_extension_headers_collapsed_signal_id > 0) {
-               GDBusProxy *web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (object));
-
-               if (web_extension != NULL) {
-                       g_dbus_connection_signal_unsubscribe (
-                               g_dbus_proxy_get_connection (web_extension),
-                               priv->web_extension_headers_collapsed_signal_id);
+       if (priv->web_extension_connection) {
+               if (priv->web_extension_headers_collapsed_signal_id) {
+                       g_dbus_connection_signal_unsubscribe (priv->web_extension_connection, 
priv->web_extension_headers_collapsed_signal_id);
+                       priv->web_extension_headers_collapsed_signal_id = 0;
                }
-               priv->web_extension_headers_collapsed_signal_id = 0;
-       }
-
-       if (priv->web_extension_mail_part_appeared_signal_id > 0) {
-               GDBusProxy *web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (object));
 
-               if (web_extension != NULL) {
-                       g_dbus_connection_signal_unsubscribe (
-                               g_dbus_proxy_get_connection (web_extension),
-                               priv->web_extension_mail_part_appeared_signal_id);
+               if (priv->web_extension_mail_part_appeared_signal_id) {
+                       g_dbus_connection_signal_unsubscribe (priv->web_extension_connection, 
priv->web_extension_mail_part_appeared_signal_id);
+                       priv->web_extension_mail_part_appeared_signal_id = 0;
                }
-               priv->web_extension_mail_part_appeared_signal_id = 0;
+
+               g_clear_object (&priv->web_extension_connection);
        }
 
        if (priv->attachment_store) {
@@ -2296,6 +2316,9 @@ e_mail_display_init (EMailDisplay *display)
                        g_clear_error (&error);
                }
        }
+
+       g_signal_connect (display, "notify::web-extension-proxy",
+               G_CALLBACK (mail_display_web_extension_proxy_notify_cb), NULL);
 }
 
 static void
diff --git a/src/modules/itip-formatter/CMakeLists.txt b/src/modules/itip-formatter/CMakeLists.txt
index b6f8e19c72..faa2a7524b 100644
--- a/src/modules/itip-formatter/CMakeLists.txt
+++ b/src/modules/itip-formatter/CMakeLists.txt
@@ -32,5 +32,3 @@ add_evolution_module(module-itip-formatter
        extra_incdirs
        extra_ldflags
 )
-
-add_subdirectory(web-extension)
diff --git a/src/modules/itip-formatter/e-mail-formatter-itip.c 
b/src/modules/itip-formatter/e-mail-formatter-itip.c
index 551a5771d4..ea3d9878f7 100644
--- a/src/modules/itip-formatter/e-mail-formatter-itip.c
+++ b/src/modules/itip-formatter/e-mail-formatter-itip.c
@@ -71,7 +71,7 @@ emfe_itip_format (EMailFormatterExtension *extension,
 
                buffer = g_string_sized_new (1024);
 
-               itip_view = itip_view_new (0, e_mail_part_get_id (part),
+               itip_view = itip_view_new (e_mail_part_get_id (part),
                        itip_part,
                        itip_part->folder,
                        itip_part->message_uid,
diff --git a/src/modules/itip-formatter/e-mail-part-itip.c b/src/modules/itip-formatter/e-mail-part-itip.c
index e991da01ae..03672cc1db 100644
--- a/src/modules/itip-formatter/e-mail-part-itip.c
+++ b/src/modules/itip-formatter/e-mail-part-itip.c
@@ -86,20 +86,21 @@ mail_part_itip_bind_dom_element (EMailPart *part,
 
        pitip = E_MAIL_PART_ITIP (part);
 
-       itip_view = itip_view_new (
-               page_id,
-               e_mail_part_get_id (part),
-               pitip,
-               pitip->folder,
-               pitip->message_uid,
-               pitip->message,
-               pitip->itip_mime_part,
-               pitip->vcalendar,
-               pitip->cancellable);
-
-       itip_view_set_web_view (itip_view, web_view);
-
-       pitip->priv->views = g_slist_prepend (pitip->priv->views, itip_view);
+       if (pitip->folder && pitip->message_uid && pitip->message) {
+               itip_view = itip_view_new (
+                       e_mail_part_get_id (part),
+                       pitip,
+                       pitip->folder,
+                       pitip->message_uid,
+                       pitip->message,
+                       pitip->itip_mime_part,
+                       pitip->vcalendar,
+                       pitip->cancellable);
+
+               itip_view_set_web_view (itip_view, web_view);
+
+               pitip->priv->views = g_slist_prepend (pitip->priv->views, itip_view);
+       }
 }
 
 static void
diff --git a/src/modules/itip-formatter/itip-view.c b/src/modules/itip-formatter/itip-view.c
index 16d55739d1..52e694c15c 100644
--- a/src/modules/itip-formatter/itip-view.c
+++ b/src/modules/itip-formatter/itip-view.c
@@ -32,6 +32,8 @@
 #include "calendar/gui/comp-util.h"
 #include "calendar/gui/itip-utils.h"
 
+#include "web-extensions/e-web-extension-names.h"
+
 #include <mail/em-config.h>
 #include <mail/em-utils.h>
 #include <em-format/e-mail-formatter-utils.h>
@@ -41,8 +43,6 @@
 
 #include "itip-view-elements-defines.h"
 
-#include "web-extension/module-itip-formatter-web-extension.h"
-
 #define d(x)
 
 #define MEETING_ICON "stock_people"
@@ -110,12 +110,10 @@ struct _ItipViewPrivate {
 
         gpointer itip_part_ptr; /* not referenced, only for a "reference" to which part this belongs */
 
-       GDBusProxy *web_extension;
-       guint web_extension_watch_name_id;
+       GDBusConnection *dbus_connection;
        guint web_extension_source_changed_cb_signal_id;
        guint web_extension_recur_toggled_signal_id;
 
-       guint64 page_id;
        gchar *part_id;
 
         gchar *error;
@@ -201,6 +199,27 @@ enum {
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
+static GDBusProxy *
+itip_view_ref_web_extension_proxy (ItipView *view)
+{
+       EWebView *web_view;
+       GDBusProxy *proxy = NULL;
+
+       g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
+
+       web_view = g_weak_ref_get (view->priv->web_view_weakref);
+       if (!web_view)
+               return NULL;
+
+       proxy = e_web_view_get_web_extension_proxy (web_view);
+       if (proxy)
+               g_object_ref (proxy);
+
+       g_object_unref (web_view);
+
+       return proxy;
+}
+
 static void
 format_date_and_time_x (struct tm *date_tm,
                         struct tm *current_tm,
@@ -644,33 +663,60 @@ set_journal_sender_text (ItipView *view)
        return sender;
 }
 
+static guint64
+itip_view_get_page_id (ItipView *view)
+{
+       EWebView *web_view;
+       guint64 page_id = 0;
+
+       web_view = g_weak_ref_get (view->priv->web_view_weakref);
+       if (web_view) {
+               page_id = webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view));
+               g_object_unref (web_view);
+       }
+
+       return page_id;
+}
+
 static void
 enable_button (ItipView *view,
               const gchar *button_id,
                gboolean enable)
 {
-       if (!view->priv->web_extension)
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "EnableButton",
-               g_variant_new ("(tssb)", view->priv->page_id, view->priv->part_id, button_id, enable),
+               proxy,
+               "ItipEnableButton",
+               g_variant_new ("(tssb)", itip_view_get_page_id (view), view->priv->part_id, button_id, 
enable),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 static void
 show_button (ItipView *view,
              const gchar *id)
 {
-       if (!view->priv->web_extension)
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "ShowButton",
-               g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, id),
+               proxy,
+               "ItipShowButton",
+               g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, id),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 static void
@@ -678,14 +724,20 @@ hide_element (ItipView *view,
              const gchar *element_id,
               gboolean hide)
 {
-       if (!view->priv->web_extension)
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "HideElement",
-               g_variant_new ("(tssb)", view->priv->page_id, view->priv->part_id, element_id, hide),
+               proxy,
+               "ItipHideElement",
+               g_variant_new ("(tssb)", itip_view_get_page_id (view), view->priv->part_id, element_id, hide),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 static gboolean
@@ -694,22 +746,28 @@ element_is_hidden (ItipView *view,
 {
        GVariant *result;
        gboolean hidden;
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
 
-       if (!view->priv->web_extension)
+       if (!proxy)
                return FALSE;
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-                       view->priv->web_extension,
-                       "ElementIsHidden",
-                       g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, element_id),
+                       proxy,
+                       "ItipElementIsHidden",
+                       g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, 
element_id),
                        NULL);
 
        if (result) {
                g_variant_get (result, "(b)", &hidden);
                g_variant_unref (result);
+               g_object_unref (proxy);
                return hidden;
        }
 
+       g_object_unref (proxy);
+
        return FALSE;
 }
 
@@ -718,14 +776,20 @@ set_inner_html (ItipView *view,
                const gchar *element_id,
                 const gchar *inner_html)
 {
-       if (!view->priv->web_extension)
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "ElementSetInnerHTML",
-               g_variant_new ("(tsss)", view->priv->page_id, view->priv->part_id, element_id, inner_html),
+               proxy,
+               "ItipElementSetInnerHTML",
+               g_variant_new ("(tsss)", itip_view_get_page_id (view), view->priv->part_id, element_id, 
inner_html),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 static void
@@ -733,14 +797,20 @@ input_set_checked (ItipView *view,
                    const gchar *input_id,
                    gboolean checked)
 {
-       if (!view->priv->web_extension)
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "InputSetChecked",
-               g_variant_new ("(tssb)", view->priv->page_id, view->priv->part_id, input_id, checked),
+               proxy,
+               "ItipInputSetChecked",
+               g_variant_new ("(tssb)", itip_view_get_page_id (view), view->priv->part_id, input_id, 
checked),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 static gboolean
@@ -749,22 +819,28 @@ input_is_checked (ItipView *view,
 {
        GVariant *result;
        gboolean checked;
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
 
-       if (!view->priv->web_extension)
+       if (!proxy)
                return FALSE;
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-                       view->priv->web_extension,
-                       "InputIsChecked",
-                       g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, input_id),
+                       proxy,
+                       "ItipInputIsChecked",
+                       g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, input_id),
                        NULL);
 
        if (result) {
                g_variant_get (result, "(b)", &checked);
                g_variant_unref (result);
+               g_object_unref (proxy);
                return checked;
        }
 
+       g_object_unref (proxy);
+
        return FALSE;
 }
 
@@ -774,16 +850,20 @@ show_checkbox (ItipView *view,
                gboolean show,
               gboolean update_second)
 {
-       g_return_if_fail (ITIP_IS_VIEW (view));
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
 
-       if (!view->priv->web_extension)
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "ShowCheckbox",
-               g_variant_new ("(tssbb)", view->priv->page_id, view->priv->part_id, id, show, update_second),
+               proxy,
+               "ItipShowCheckbox",
+               g_variant_new ("(tssbb)", itip_view_get_page_id (view), view->priv->part_id, id, show, 
update_second),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 static void
@@ -791,16 +871,20 @@ set_area_text (ItipView *view,
                const gchar *id,
                const gchar *text)
 {
-       g_return_if_fail (ITIP_IS_VIEW (view));
+       GDBusProxy *proxy;
 
-       if (!view->priv->web_extension)
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "SetAreaText",
-               g_variant_new ("(tsss)", view->priv->page_id, view->priv->part_id, id, text ? text : ""),
+               proxy,
+               "ItipSetAreaText",
+               g_variant_new ("(tsss)", itip_view_get_page_id (view), view->priv->part_id, id, text ? text : 
""),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 static void
@@ -827,7 +911,7 @@ set_sender_text (ItipView *view)
                break;
        }
 
-       if (priv->sender && priv->web_extension)
+       if (priv->sender)
                set_inner_html (view, TEXT_ROW_SENDER, priv->sender);
 }
 
@@ -835,6 +919,7 @@ static void
 update_start_end_times (ItipView *view)
 {
        ItipViewPrivate *priv;
+       GDBusProxy *proxy;
        gchar buffer[256];
        time_t now;
        struct tm *now_tm;
@@ -879,16 +964,18 @@ update_start_end_times (ItipView *view)
        }
        #undef is_same
 
-       if (!priv->web_extension)
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        if (priv->start_header && priv->start_label) {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       priv->web_extension,
-                       "UpdateTimes",
+                       proxy,
+                       "ItipUpdateTimes",
                        g_variant_new (
                                "(tssss)",
-                               view->priv->page_id,
+                               itip_view_get_page_id (view),
                                view->priv->part_id,
                                TABLE_ROW_START_DATE,
                                priv->start_header,
@@ -899,11 +986,11 @@ update_start_end_times (ItipView *view)
 
        if (priv->end_header && priv->end_label) {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       priv->web_extension,
-                       "UpdateTimes",
+                       proxy,
+                       "ItipUpdateTimes",
                        g_variant_new (
                                "(tssss)",
-                               view->priv->page_id,
+                               itip_view_get_page_id (view),
                                view->priv->part_id,
                                TABLE_ROW_END_DATE,
                                priv->end_header,
@@ -911,6 +998,8 @@ update_start_end_times (ItipView *view)
                        NULL);
        } else
                hide_element (view, TABLE_ROW_END_DATE, TRUE);
+
+       g_object_unref (proxy);
 }
 
 static void
@@ -972,12 +1061,12 @@ recur_toggled_signal_cb (GDBusConnection *connection,
 
        g_return_if_fail (ITIP_IS_VIEW (view));
 
-       if (g_strcmp0 (signal_name, "RecurToggled") != 0)
+       if (g_strcmp0 (signal_name, "ItipRecurToggled") != 0)
                return;
 
        g_variant_get (parameters, "(t&s)", &page_id, &part_id);
 
-       if (view->priv->page_id == page_id &&
+       if (itip_view_get_page_id (view) == page_id &&
            g_strcmp0 (view->priv->part_id, part_id) == 0)
                itip_view_set_mode (view, view->priv->mode);
 }
@@ -1012,12 +1101,12 @@ source_changed_cb_signal_cb (GDBusConnection *connection,
 
        g_return_if_fail (ITIP_IS_VIEW (view));
 
-       if (g_strcmp0 (signal_name, "SourceChanged") != 0)
+       if (g_strcmp0 (signal_name, "ItipSourceChanged") != 0)
                return;
 
        g_variant_get (parameters, "(t&s)", &page_id, &part_id);
 
-       if (view->priv->page_id == page_id &&
+       if (itip_view_get_page_id (view) == page_id &&
            g_strcmp0 (view->priv->part_id, part_id) == 0)
                source_changed_cb (view);
 }
@@ -1088,9 +1177,15 @@ append_info_item_row (ItipView *view,
                       const gchar *table_id,
                       ItipViewInfoItem *item)
 {
+       GDBusProxy *proxy;
        const gchar *icon_name;
        gchar *row_id;
 
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
+               return;
+
        switch (item->type) {
                case ITIP_VIEW_INFO_ITEM_TYPE_INFO:
                        icon_name = "dialog-information";
@@ -1105,21 +1200,19 @@ append_info_item_row (ItipView *view,
                        icon_name = "edit-find";
                        break;
                case ITIP_VIEW_INFO_ITEM_TYPE_NONE:
-                       default:
+               default:
                        icon_name = NULL;
+                       break;
        }
 
        row_id = g_strdup_printf ("%s_row_%d", table_id, item->id);
 
-       if (!view->priv->web_extension)
-               return;
-
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "AppendInfoItemRow",
+               proxy,
+               "ItipAppendInfoItemRow",
                g_variant_new (
                        "(tsssss)",
-                       view->priv->page_id,
+                       itip_view_get_page_id (view),
                        view->priv->part_id,
                        table_id,
                        row_id,
@@ -1127,6 +1220,7 @@ append_info_item_row (ItipView *view,
                        item->message),
                NULL);
 
+       g_object_unref (proxy);
        g_free (row_id);
 
        d (printf ("Added row %s_row_%d ('%s')\n", table_id, item->id, item->message));
@@ -1138,18 +1232,22 @@ remove_info_item_row (ItipView *view,
                       guint id)
 {
        gchar *row_id;
+       GDBusProxy *proxy;
 
-       row_id = g_strdup_printf ("%s_row_%d", table_id, id);
+       proxy = itip_view_ref_web_extension_proxy (view);
 
-       if (!view->priv->web_extension)
+       if (!proxy)
                return;
 
+       row_id = g_strdup_printf ("%s_row_%d", table_id, id);
+
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "RemoveElement",
-               g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, row_id),
+               proxy,
+               "ItipRemoveElement",
+               g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, row_id),
                NULL);
 
+       g_object_unref (proxy);
        g_free (row_id);
 
        d (printf ("Removed row %s_row_%d\n", table_id, id));
@@ -1247,24 +1345,29 @@ static void
 itip_view_rebuild_source_list (ItipView *view)
 {
        ESourceRegistry *registry;
+       GDBusProxy *proxy;
        GList *list, *link;
        const gchar *extension_name;
 
        d (printf ("Assigning a new source list!\n"));
 
-       if (!view->priv->web_extension)
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        registry = view->priv->registry;
        extension_name = itip_view_get_extension_name (view);
 
-       if (extension_name == NULL)
+       if (!extension_name) {
+               g_object_unref (proxy);
                return;
+       }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "ElementRemoveChildNodes",
-               g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, SELECT_ESOURCE),
+               proxy,
+               "ItipElementRemoveChildNodes",
+               g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, SELECT_ESOURCE),
                NULL);
 
        list = e_source_registry_list_enabled (registry, extension_name);
@@ -1277,11 +1380,11 @@ itip_view_rebuild_source_list (ItipView *view)
                        registry, e_source_get_parent (source));
 
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       view->priv->web_extension,
-                       "RebuildSourceList",
+                       proxy,
+                       "ItipRebuildSourceList",
                        g_variant_new (
                                "(tsssssb)",
-                               view->priv->page_id,
+                               itip_view_get_page_id (view),
                                view->priv->part_id,
                                e_source_get_uid (parent),
                                e_source_get_display_name (parent),
@@ -1294,6 +1397,7 @@ itip_view_rebuild_source_list (ItipView *view)
        }
 
        g_list_free_full (list, (GDestroyNotify) g_object_unref);
+       g_object_unref (proxy);
 
        source_changed_cb (view);
 }
@@ -1334,6 +1438,25 @@ itip_view_source_removed_cb (ESourceRegistry *registry,
                itip_view_rebuild_source_list (view);
 }
 
+static void
+itip_view_unregister_dbus_signals (ItipView *view)
+{
+       g_return_if_fail (ITIP_IS_VIEW (view));
+
+       if (view->priv->dbus_connection && !g_dbus_connection_is_closed (view->priv->dbus_connection)) {
+               if (view->priv->web_extension_recur_toggled_signal_id)
+                       g_dbus_connection_signal_unsubscribe (view->priv->dbus_connection, 
view->priv->web_extension_recur_toggled_signal_id);
+
+               if (view->priv->web_extension_source_changed_cb_signal_id)
+                       g_dbus_connection_signal_unsubscribe (view->priv->dbus_connection, 
view->priv->web_extension_source_changed_cb_signal_id);
+       }
+
+       view->priv->web_extension_recur_toggled_signal_id = 0;
+       view->priv->web_extension_source_changed_cb_signal_id = 0;
+
+       g_clear_object (&view->priv->dbus_connection);
+}
+
 static void
 itip_view_set_client_cache (ItipView *view,
                             EClientCache *client_cache)
@@ -1413,28 +1536,11 @@ itip_view_dispose (GObject *object)
                priv->source_removed_handler_id = 0;
        }
 
-       if (priv->web_extension_watch_name_id > 0) {
-               g_bus_unwatch_name (priv->web_extension_watch_name_id);
-               priv->web_extension_watch_name_id = 0;
-       }
-
-       if (priv->web_extension_recur_toggled_signal_id > 0) {
-               g_dbus_connection_signal_unsubscribe (
-                       g_dbus_proxy_get_connection (priv->web_extension),
-                       priv->web_extension_recur_toggled_signal_id);
-               priv->web_extension_recur_toggled_signal_id = 0;
-       }
-
-       if (priv->web_extension_source_changed_cb_signal_id > 0) {
-               g_dbus_connection_signal_unsubscribe (
-                       g_dbus_proxy_get_connection (priv->web_extension),
-                       priv->web_extension_source_changed_cb_signal_id);
-               priv->web_extension_source_changed_cb_signal_id = 0;
-       }
+       itip_view_unregister_dbus_signals (ITIP_VIEW (object));
 
        g_clear_object (&priv->client_cache);
        g_clear_object (&priv->registry);
-       g_clear_object (&priv->web_extension);
+       g_clear_object (&priv->dbus_connection);
        g_clear_object (&priv->cancellable);
        g_clear_object (&priv->comp);
 
@@ -1814,127 +1920,62 @@ itip_view_write_for_printing (ItipView *view,
 }
 
 static void
-web_extension_proxy_created_cb (GDBusProxy *proxy,
-                                GAsyncResult *result,
-                                GWeakRef *view_wr)
+itip_view_web_extension_proxy_notify_cb (GObject *web_view,
+                                        GParamSpec *param,
+                                        gpointer user_data)
 {
-       ItipView *view;
-       GError *error = NULL;
-
-       view = g_weak_ref_get (view_wr);
-
-       if (!view) {
-               e_weak_ref_free (view_wr);
-               return;
-       }
-
-       view->priv->web_extension = g_dbus_proxy_new_finish (result, &error);
-       if (!view->priv->web_extension) {
-               g_warning ("Error creating web extension proxy: %s\n", error ? error->message : "Unknown 
error");
-               g_clear_error (&error);
-       } else {
-               view->priv->web_extension_source_changed_cb_signal_id =
-                       g_dbus_connection_signal_subscribe (
-                               g_dbus_proxy_get_connection (view->priv->web_extension),
-                               g_dbus_proxy_get_name (view->priv->web_extension),
-                               MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
-                               "SourceChanged",
-                               MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
-                               NULL,
-                               G_DBUS_SIGNAL_FLAGS_NONE,
-                               source_changed_cb_signal_cb,
-                               view,
-                               NULL);
-
-               view->priv->web_extension_recur_toggled_signal_id =
-                       g_dbus_connection_signal_subscribe (
-                               g_dbus_proxy_get_connection (view->priv->web_extension),
-                               g_dbus_proxy_get_name (view->priv->web_extension),
-                               MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
-                               "RecurToggled",
-                               MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
-                               NULL,
-                               G_DBUS_SIGNAL_FLAGS_NONE,
-                               (GDBusSignalCallback) recur_toggled_signal_cb,
-                               view,
-                               NULL);
-
-               e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       view->priv->web_extension,
-                       "CreateDOMBindings",
-                       g_variant_new ("(ts)", view->priv->page_id, view->priv->part_id),
-                       NULL);
-       }
-
-       itip_view_init_view (view);
-
-       e_weak_ref_free (view_wr);
-       g_object_unref (view);
-}
-
-static void
-web_extension_appeared_cb (GDBusConnection *connection,
-                           const gchar *name,
-                           const gchar *name_owner,
-                           GWeakRef *view_wr)
-{
-       ItipView *view;
-
-       view = g_weak_ref_get (view_wr);
+       ItipView *view = user_data;
+       GDBusConnection *connection;
+       GDBusProxy *proxy;
 
        if (!view)
                return;
 
-       g_dbus_proxy_new (
-               connection,
-               G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
-               G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
-               G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
-               NULL,
-               name,
-               MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
-               MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
-               NULL,
-               (GAsyncReadyCallback)web_extension_proxy_created_cb,
-               e_weak_ref_new (view));
+       itip_view_unregister_dbus_signals (view);
 
-       g_object_unref (view);
-}
+       proxy = e_web_view_get_web_extension_proxy (E_WEB_VIEW (web_view));
+       if (!proxy)
+               return;
 
-static void
-web_extension_vanished_cb (GDBusConnection *connection,
-                           const gchar *name,
-                           GWeakRef *view_wr)
-{
-       ItipView *view;
+       connection = g_dbus_proxy_get_connection (proxy);
+       if (!connection || g_dbus_connection_is_closed (connection))
+               return;
 
-       view = g_weak_ref_get (view_wr);
+       view->priv->dbus_connection = g_object_ref (connection);
 
-       if (view) {
-               g_clear_object (&view->priv->web_extension);
-               g_object_unref (view);
-       }
-}
+       view->priv->web_extension_source_changed_cb_signal_id =
+               g_dbus_connection_signal_subscribe (
+                       view->priv->dbus_connection,
+                       g_dbus_proxy_get_name (proxy),
+                       E_WEB_EXTENSION_INTERFACE,
+                       "ItipSourceChanged",
+                       E_WEB_EXTENSION_OBJECT_PATH,
+                       NULL,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       source_changed_cb_signal_cb,
+                       view,
+                       NULL);
 
-static void
-itip_view_watch_web_extension (ItipView *view)
-{
-       view->priv->web_extension_watch_name_id =
-               g_bus_watch_name (
-                       G_BUS_TYPE_SESSION,
-                       MODULE_ITIP_FORMATTER_WEB_EXTENSION_SERVICE_NAME,
-                       G_BUS_NAME_WATCHER_FLAGS_NONE,
-                       (GBusNameAppearedCallback) web_extension_appeared_cb,
-                       (GBusNameVanishedCallback) web_extension_vanished_cb,
-                       e_weak_ref_new (view), (GDestroyNotify) e_weak_ref_free);
-}
+       view->priv->web_extension_recur_toggled_signal_id =
+               g_dbus_connection_signal_subscribe (
+                       view->priv->dbus_connection,
+                       g_dbus_proxy_get_name (proxy),
+                       E_WEB_EXTENSION_INTERFACE,
+                       "ItipRecurToggled",
+                       E_WEB_EXTENSION_OBJECT_PATH,
+                       NULL,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       (GDBusSignalCallback) recur_toggled_signal_cb,
+                       view,
+                       NULL);
 
-GDBusProxy *
-itip_view_get_web_extension_proxy (ItipView *view)
-{
-       g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
+       e_util_invoke_g_dbus_proxy_call_with_error_check (
+               proxy,
+               "ItipCreateDOMBindings",
+               g_variant_new ("(ts)", itip_view_get_page_id (view), view->priv->part_id),
+               NULL);
 
-       return view->priv->web_extension;
+       itip_view_init_view (view);
 }
 
 static void
@@ -1953,8 +1994,7 @@ itip_view_init (ItipView *view)
 }
 
 ItipView *
-itip_view_new (guint64 page_id,
-               const gchar *part_id,
+itip_view_new (const gchar *part_id,
               gpointer itip_part_ptr,
               CamelFolder *folder,
               const gchar *message_uid,
@@ -1966,18 +2006,15 @@ itip_view_new (guint64 page_id,
        ItipView *view;
 
        view = ITIP_VIEW (g_object_new (ITIP_TYPE_VIEW, NULL));
-       view->priv->page_id = page_id;
        view->priv->part_id = g_strdup (part_id);
        view->priv->itip_part_ptr = itip_part_ptr;
-       view->priv->folder = g_object_ref (folder);
+       view->priv->folder = folder ? g_object_ref (folder) : NULL;
        view->priv->message_uid = g_strdup (message_uid);
-       view->priv->message = g_object_ref (message);
+       view->priv->message = message ? g_object_ref (message) : NULL;
        view->priv->itip_mime_part = g_object_ref (itip_mime_part);
        view->priv->vcalendar = g_strdup (vcalendar);
        view->priv->cancellable = g_object_ref (cancellable);
 
-       itip_view_watch_web_extension (view);
-
        return view;
 }
 
@@ -1985,19 +2022,22 @@ void
 itip_view_set_mode (ItipView *view,
                     ItipViewMode mode)
 {
+       GDBusProxy *proxy;
        g_return_if_fail (ITIP_IS_VIEW (view));
 
        view->priv->mode = mode;
 
        set_sender_text (view);
 
-       if (!view->priv->web_extension)
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "ElementHideChildNodes",
-               g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, TABLE_ROW_BUTTONS),
+               proxy,
+               "ItipElementHideChildNodes",
+               g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, TABLE_ROW_BUTTONS),
                NULL);
 
        view->priv->is_recur_set = itip_view_get_recur_check_state (view);
@@ -2042,6 +2082,8 @@ itip_view_set_mode (ItipView *view,
        default:
                break;
        }
+
+       g_object_unref (proxy);
 }
 
 ItipViewMode
@@ -2056,14 +2098,16 @@ void
 itip_view_set_item_type (ItipView *view,
                          ECalClientSourceType type)
 {
+       GDBusProxy *proxy;
        const gchar *header;
        gchar *access_key, *html_label;
 
        g_return_if_fail (ITIP_IS_VIEW (view));
 
        view->priv->type = type;
+       proxy = itip_view_ref_web_extension_proxy (view);
 
-       if (!view->priv->web_extension)
+       if (!proxy)
                return;
 
        switch (view->priv->type) {
@@ -2083,19 +2127,21 @@ itip_view_set_item_type (ItipView *view,
 
        if (!header) {
                set_sender_text (view);
+               g_object_unref (proxy);
                return;
        }
 
        html_label = e_mail_formatter_parse_html_mnemonics (header, &access_key);
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "ElementSetAccessKey",
-               g_variant_new ("(tsss)", view->priv->page_id, view->priv->part_id, TABLE_ROW_ESCB_LABEL, 
access_key),
+               proxy,
+               "ItipElementSetAccessKey",
+               g_variant_new ("(tsss)", itip_view_get_page_id (view), view->priv->part_id, 
TABLE_ROW_ESCB_LABEL, access_key),
                NULL);
 
        set_inner_html (view, TABLE_ROW_ESCB_LABEL, html_label);
 
+       g_object_unref (proxy);
        g_free (html_label);
 
        if (access_key)
@@ -2604,9 +2650,6 @@ itip_view_add_upper_info_item (ItipView *view,
 
        priv->upper_info_items = g_slist_append (priv->upper_info_items, item);
 
-       if (!view->priv->web_extension)
-               return item->id;
-
        append_info_item_row (view, TABLE_UPPER_ITIP_INFO, item);
 
        return item->id;
@@ -2704,9 +2747,6 @@ itip_view_add_lower_info_item (ItipView *view,
 
        priv->lower_info_items = g_slist_append (priv->lower_info_items, item);
 
-       if (!view->priv->web_extension)
-               return item->id;
-
        append_info_item_row (view, TABLE_LOWER_ITIP_INFO, item);
 
        return item->id;
@@ -2789,6 +2829,7 @@ itip_view_set_source (ItipView *view,
                       ESource *source)
 {
        ESource *selected_source;
+       GDBusProxy *proxy;
 
        g_return_if_fail (ITIP_IS_VIEW (view));
 
@@ -2811,22 +2852,25 @@ itip_view_set_source (ItipView *view,
        if (selected_source != NULL)
                g_object_unref (selected_source);
 
-       if (!view->priv->web_extension)
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "EnableSelect",
-               g_variant_new ("(tssb)", view->priv->page_id, view->priv->part_id, SELECT_ESOURCE, TRUE),
+               proxy,
+               "ItipEnableSelect",
+               g_variant_new ("(tssb)", itip_view_get_page_id (view), view->priv->part_id, SELECT_ESOURCE, 
TRUE),
                NULL);
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "SelectSetSelected",
-               g_variant_new ("(tsss)", view->priv->page_id, view->priv->part_id, SELECT_ESOURCE, 
e_source_get_uid (source)),
+               proxy,
+               "ItipSelectSetSelected",
+               g_variant_new ("(tsss)", itip_view_get_page_id (view), view->priv->part_id, SELECT_ESOURCE, 
e_source_get_uid (source)),
                NULL);
 
        source_changed_cb (view);
+       g_object_unref (proxy);
 }
 
 ESource *
@@ -2834,17 +2878,20 @@ itip_view_ref_source (ItipView *view)
 {
        ESource *source = NULL;
        gboolean disable = FALSE, enabled = FALSE;
+       GDBusProxy *proxy;
        GVariant *result;
 
        g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-       if (!view->priv->web_extension)
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return NULL;
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-                       view->priv->web_extension,
-                       "SelectIsEnabled",
-                       g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, SELECT_ESOURCE),
+                       proxy,
+                       "ItipSelectIsEnabled",
+                       g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, 
SELECT_ESOURCE),
                        NULL);
 
        if (result) {
@@ -2854,18 +2901,18 @@ itip_view_ref_source (ItipView *view)
 
        if (!enabled) {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       view->priv->web_extension,
-                       "EnableSelect",
-                       g_variant_new ("(tssb)", view->priv->page_id, view->priv->part_id, SELECT_ESOURCE, 
TRUE),
+                       proxy,
+                       "ItipEnableSelect",
+                       g_variant_new ("(tssb)", itip_view_get_page_id (view), view->priv->part_id, 
SELECT_ESOURCE, TRUE),
                        NULL);
 
                disable = TRUE;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               view->priv->web_extension,
-               "SelectGetValue",
-               g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, SELECT_ESOURCE),
+               proxy,
+               "ItipSelectGetValue",
+               g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, SELECT_ESOURCE),
                NULL);
 
        if (result) {
@@ -2878,12 +2925,14 @@ itip_view_ref_source (ItipView *view)
 
        if (disable) {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       view->priv->web_extension,
-                       "EnableSelect",
-                       g_variant_new ("(tssb)", view->priv->page_id, view->priv->part_id, SELECT_ESOURCE, 
FALSE),
+                       proxy,
+                       "ItipEnableSelect",
+                       g_variant_new ("(tssb)", itip_view_get_page_id (view), view->priv->part_id, 
SELECT_ESOURCE, FALSE),
                        NULL);
        }
 
+       g_object_unref (proxy);
+
        return source;
 }
 
@@ -2891,18 +2940,22 @@ void
 itip_view_set_rsvp (ItipView *view,
                     gboolean rsvp)
 {
-       g_return_if_fail (ITIP_IS_VIEW (view));
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
 
-       if (!view->priv->web_extension)
+       if (!proxy)
                return;
 
        input_set_checked (view, CHECKBOX_RSVP, rsvp);
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "EnableTextArea",
-               g_variant_new ("(tssb)", view->priv->page_id, view->priv->part_id, TEXTAREA_RSVP_COMMENT, 
!rsvp),
+               proxy,
+               "ItipEnableTextArea",
+               g_variant_new ("(tssb)", itip_view_get_page_id (view), view->priv->part_id, 
TEXTAREA_RSVP_COMMENT, !rsvp),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 gboolean
@@ -2969,37 +3022,46 @@ void
 itip_view_set_rsvp_comment (ItipView *view,
                             const gchar *comment)
 {
-       g_return_if_fail (ITIP_IS_VIEW (view));
+       GDBusProxy *proxy;
+
+       proxy = itip_view_ref_web_extension_proxy (view);
 
-       if (!view->priv->web_extension)
+       if (!proxy)
                return;
 
        if (comment) {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       view->priv->web_extension,
-                       "TextAreaSetValue",
-                       g_variant_new ("(tsss)", view->priv->page_id, view->priv->part_id, 
TEXTAREA_RSVP_COMMENT, comment),
+                       proxy,
+                       "ItipTextAreaSetValue",
+                       g_variant_new ("(tsss)", itip_view_get_page_id (view), view->priv->part_id, 
TEXTAREA_RSVP_COMMENT, comment),
                        NULL);
        }
+
+       g_object_unref (proxy);
 }
 
 gchar *
 itip_view_get_rsvp_comment (ItipView *view)
 {
+       GDBusProxy *proxy;
        GVariant *result;
 
        g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-       if (!view->priv->web_extension)
+       proxy = itip_view_ref_web_extension_proxy (view);
+
+       if (!proxy)
                return NULL;
 
-       if (element_is_hidden (view, TEXTAREA_RSVP_COMMENT))
+       if (element_is_hidden (view, TEXTAREA_RSVP_COMMENT)) {
+               g_object_unref (proxy);
                return NULL;
+       }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               view->priv->web_extension,
-               "TextAreaGetValue",
-               g_variant_new ("(tss)", view->priv->page_id, view->priv->part_id, TEXTAREA_RSVP_COMMENT),
+               proxy,
+               "ItipTextAreaGetValue",
+               g_variant_new ("(tss)", itip_view_get_page_id (view), view->priv->part_id, 
TEXTAREA_RSVP_COMMENT),
                NULL);
 
        if (result) {
@@ -3007,9 +3069,12 @@ itip_view_get_rsvp_comment (ItipView *view)
 
                g_variant_get (result, "(s)", &value);
                g_variant_unref (result);
+               g_object_unref (proxy);
                return value;
        }
 
+       g_object_unref (proxy);
+
        return NULL;
 }
 
@@ -3026,20 +3091,25 @@ void
 itip_view_set_buttons_sensitive (ItipView *view,
                                  gboolean sensitive)
 {
+       GDBusProxy *proxy;
+
        g_return_if_fail (ITIP_IS_VIEW (view));
 
        d (printf ("Settings buttons %s\n", sensitive ? "sensitive" : "insensitive"));
 
        view->priv->buttons_sensitive = sensitive;
+       proxy = itip_view_ref_web_extension_proxy (view);
 
-       if (!view->priv->web_extension)
+       if (!proxy)
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "SetButtonsSensitive",
-               g_variant_new ("(tsb)", view->priv->page_id, view->priv->part_id, sensitive),
+               proxy,
+               "ItipSetButtonsSensitive",
+               g_variant_new ("(tsb)", itip_view_get_page_id (view), view->priv->part_id, sensitive),
                NULL);
+
+       g_object_unref (proxy);
 }
 
 gboolean
@@ -3156,9 +3226,6 @@ itip_view_set_error (ItipView *view,
 
        view->priv->error = g_string_free (str, FALSE);
 
-       if (!view->priv->web_extension)
-               return;
-
        hide_element (view, DIV_ITIP_CONTENT, TRUE);
        hide_element (view, DIV_ITIP_ERROR, FALSE);
        set_inner_html (view, DIV_ITIP_ERROR, view->priv->error);
@@ -6866,7 +6933,7 @@ itip_view_init_view (ItipView *view)
                        find_server (view, view->priv->comp);
                        set_buttons_sensitive (view);
                }
-       } else if (view->priv->web_extension) {
+       } else {
                /* The Open Calendar button can be shown, thus enable it */
                enable_button (view, BUTTON_OPEN_CALENDAR, TRUE);
        }
@@ -6882,6 +6949,16 @@ itip_view_set_web_view (ItipView *view,
 
        g_weak_ref_set (view->priv->web_view_weakref, web_view);
 
+       if (web_view) {
+               g_signal_connect_object (web_view, "notify::web-extension-proxy",
+                       G_CALLBACK (itip_view_web_extension_proxy_notify_cb), view, 0);
+
+               if (e_web_view_get_web_extension_proxy (web_view))
+                       itip_view_web_extension_proxy_notify_cb (G_OBJECT (web_view), NULL, view);
+       } else {
+               itip_view_unregister_dbus_signals (view);
+       }
+
        itip_view_register_clicked_listener (view);
 }
 
diff --git a/src/modules/itip-formatter/itip-view.h b/src/modules/itip-formatter/itip-view.h
index 7b220f88a4..696f614d33 100644
--- a/src/modules/itip-formatter/itip-view.h
+++ b/src/modules/itip-formatter/itip-view.h
@@ -106,8 +106,7 @@ struct _ItipViewClass {
 };
 
 GType          itip_view_get_type              (void);
-ItipView *     itip_view_new                   (guint64 page_id,
-                                                const gchar *part_id,
+ItipView *     itip_view_new                   (const gchar *part_id,
                                                 gpointer itip_part_ptr,
                                                 CamelFolder *folder,
                                                 const gchar *message_uid,
@@ -250,8 +249,6 @@ void                itip_view_set_show_inherit_alarm_check
 void           itip_view_set_error             (ItipView *view,
                                                 const gchar *error_html,
                                                 gboolean show_save_btn);
-GDBusProxy *   itip_view_get_web_extension_proxy
-                                               (ItipView *view);
 
 G_END_DECLS
 
diff --git a/src/modules/vcard-inline/e-mail-part-vcard.c b/src/modules/vcard-inline/e-mail-part-vcard.c
index bf8498d008..72cea885f3 100644
--- a/src/modules/vcard-inline/e-mail-part-vcard.c
+++ b/src/modules/vcard-inline/e-mail-part-vcard.c
@@ -229,6 +229,71 @@ display_mode_toggle_cb (GDBusConnection *connection,
        g_free (uri);
 }
 
+static void
+mail_part_vcard_set_web_extension_proxy (EMailPartVCard *part,
+                                        GDBusProxy *proxy)
+{
+       g_return_if_fail (E_IS_MAIL_PART_VCARD (part));
+
+       if (part->priv->web_extension) {
+               GDBusConnection *connection;
+
+               connection = g_dbus_proxy_get_connection (part->priv->web_extension);
+
+               if (connection && g_dbus_connection_is_closed (connection))
+                       connection = NULL;
+
+               if (connection && part->priv->display_mode_toggled_signal_id)
+                       g_dbus_connection_signal_unsubscribe (connection, 
part->priv->display_mode_toggled_signal_id);
+               part->priv->display_mode_toggled_signal_id = 0;
+
+               if (connection && part->priv->save_vcard_button_pressed_signal_id)
+                       g_dbus_connection_signal_unsubscribe (connection, 
part->priv->save_vcard_button_pressed_signal_id);
+               part->priv->save_vcard_button_pressed_signal_id = 0;
+
+               g_clear_object (&part->priv->web_extension);
+       }
+
+       if (proxy) {
+               GDBusConnection *connection;
+
+               part->priv->web_extension = g_object_ref (proxy);
+
+               connection = g_dbus_proxy_get_connection (proxy);
+
+               if (connection && g_dbus_connection_is_closed (connection))
+                       connection = NULL;
+
+               if (connection) {
+                       part->priv->display_mode_toggled_signal_id =
+                               g_dbus_connection_signal_subscribe (
+                                       connection,
+                                       g_dbus_proxy_get_name (proxy),
+                                       g_dbus_proxy_get_interface_name (proxy),
+                                       "VCardInlineDisplayModeToggled",
+                                       g_dbus_proxy_get_object_path (proxy),
+                                       NULL,
+                                       G_DBUS_SIGNAL_FLAGS_NONE,
+                                       (GDBusSignalCallback) display_mode_toggle_cb,
+                                       part,
+                                       NULL);
+
+                       part->priv->save_vcard_button_pressed_signal_id =
+                               g_dbus_connection_signal_subscribe (
+                                       connection,
+                                       g_dbus_proxy_get_name (proxy),
+                                       g_dbus_proxy_get_interface_name (proxy),
+                                       "VCardInlineSaveButtonPressed",
+                                       g_dbus_proxy_get_object_path (proxy),
+                                       NULL,
+                                       G_DBUS_SIGNAL_FLAGS_NONE,
+                                       (GDBusSignalCallback) save_vcard_cb,
+                                       part,
+                                       NULL);
+               }
+       }
+}
+
 static void
 mail_part_vcard_dispose (GObject *object)
 {
@@ -239,21 +304,7 @@ mail_part_vcard_dispose (GObject *object)
        g_clear_object (&part->formatter);
        g_clear_object (&part->folder);
 
-       if (part->priv->display_mode_toggled_signal_id > 0) {
-               g_dbus_connection_signal_unsubscribe (
-                       g_dbus_proxy_get_connection (part->priv->web_extension),
-                       part->priv->display_mode_toggled_signal_id);
-               part->priv->display_mode_toggled_signal_id = 0;
-       }
-
-       if (part->priv->save_vcard_button_pressed_signal_id > 0) {
-               g_dbus_connection_signal_unsubscribe (
-                       g_dbus_proxy_get_connection (part->priv->web_extension),
-                       part->priv->save_vcard_button_pressed_signal_id);
-               part->priv->save_vcard_button_pressed_signal_id = 0;
-       }
-
-       g_clear_object (&part->priv->web_extension);
+       mail_part_vcard_set_web_extension_proxy (part, NULL);
 
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (e_mail_part_vcard_parent_class)->dispose (object);
@@ -313,35 +364,9 @@ mail_part_vcard_bind_dom_element (EMailPart *part,
                return;
 
        vcard_part = E_MAIL_PART_VCARD (part);
-
-       vcard_part->priv->web_extension = g_object_ref (web_extension);
        vcard_part->priv->page_id = page_id;
 
-       vcard_part->priv->display_mode_toggled_signal_id =
-               g_dbus_connection_signal_subscribe (
-                       g_dbus_proxy_get_connection (web_extension),
-                       g_dbus_proxy_get_name (web_extension),
-                       g_dbus_proxy_get_interface_name (web_extension),
-                       "VCardInlineDisplayModeToggled",
-                       g_dbus_proxy_get_object_path (web_extension),
-                       NULL,
-                       G_DBUS_SIGNAL_FLAGS_NONE,
-                       (GDBusSignalCallback) display_mode_toggle_cb,
-                       vcard_part,
-                       NULL);
-
-       vcard_part->priv->save_vcard_button_pressed_signal_id =
-               g_dbus_connection_signal_subscribe (
-                       g_dbus_proxy_get_connection (web_extension),
-                       g_dbus_proxy_get_name (web_extension),
-                       g_dbus_proxy_get_interface_name (web_extension),
-                       "VCardInlineSaveButtonPressed",
-                       g_dbus_proxy_get_object_path (web_extension),
-                       NULL,
-                       G_DBUS_SIGNAL_FLAGS_NONE,
-                       (GDBusSignalCallback) save_vcard_cb,
-                       vcard_part,
-                       NULL);
+       mail_part_vcard_set_web_extension_proxy (vcard_part, web_extension);
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
                web_extension,
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index a98b8dde7f..5cb78d692d 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -75,9 +75,9 @@ struct _EWebKitEditorPrivate {
        gpointer initialized_user_data;
 
        GCancellable *cancellable;
-       GDBusProxy *web_extension;
-       GDBusConnection *dbus_connection;
-       guint web_extension_watch_name_id;
+       EWebExtensionContainer *container;
+       GDBusProxy *web_extension_proxy;
+       gint stamp; /* Changed only in the main thread, doesn't need locking */
        guint web_extension_selection_changed_cb_id;
        guint web_extension_content_changed_cb_id;
        guint web_extension_undo_redo_state_changed_cb_id;
@@ -166,6 +166,7 @@ typedef struct {
        GDestroyNotify data_free_func;
 } PostReloadOperation;
 
+static void e_webkit_editor_set_web_extension_proxy (EWebKitEditor *wk_editor, GDBusProxy *proxy);
 static void e_webkit_editor_content_editor_init (EContentEditorInterface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (
@@ -510,19 +511,11 @@ web_extension_user_changed_default_colors_cb (GDBusConnection *connection,
                g_variant_get (parameters, "(b)", &wk_editor->priv->suppress_color_changes);
 }
 
-static gchar *
-webkit_editor_create_service_name_for_web_context (WebKitWebContext *web_context)
-{
-       g_warn_if_fail (WEBKIT_IS_WEB_CONTEXT (web_context));
-
-       return g_strdup_printf ("%s.WC%p", E_WEBKIT_EDITOR_WEB_EXTENSION_SERVICE_NAME_PREFIX, web_context);
-}
-
 static void
 dispatch_pending_operations (EWebKitEditor *wk_editor)
 {
        if (wk_editor->priv->webkit_load_event != WEBKIT_LOAD_FINISHED ||
-           !wk_editor->priv->web_extension)
+           !wk_editor->priv->web_extension_proxy)
                return;
 
        /* Dispatch queued operations - as we are using this just for load
@@ -551,46 +544,95 @@ dispatch_pending_operations (EWebKitEditor *wk_editor)
 }
 
 static void
-web_extension_proxy_created_cb (GDBusProxy *proxy,
-                                GAsyncResult *result,
-                                GWeakRef *wk_editor_rf)
+e_webkit_editor_page_proxy_changed_cb (EWebExtensionContainer *container,
+                                      guint64 page_id,
+                                      gint stamp,
+                                      GDBusProxy *proxy,
+                                      gpointer user_data)
 {
-       EWebKitEditor *wk_editor;
-       GError *error = NULL;
+       EWebKitEditor *wk_editor = user_data;
 
-       wk_editor = g_weak_ref_get (wk_editor_rf);
+       g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
 
-       if (!wk_editor) {
-               e_weak_ref_free (wk_editor_rf);
-               return;
+       if (stamp == wk_editor->priv->stamp &&
+           page_id == webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (wk_editor))) {
+               e_webkit_editor_set_web_extension_proxy (wk_editor, proxy);
+
+               if (proxy) {
+                       dispatch_pending_operations (wk_editor);
+
+                       if (wk_editor->priv->emit_load_finished_when_extension_is_ready) {
+                               e_content_editor_emit_load_finished (E_CONTENT_EDITOR (wk_editor));
+
+                               wk_editor->priv->emit_load_finished_when_extension_is_ready = FALSE;
+                       }
+
+                       g_object_notify (G_OBJECT (wk_editor), "web-extension");
+
+                       if (wk_editor->priv->initialized_callback) {
+                               EContentEditorInitializedCallback initialized_callback;
+                               gpointer initialized_user_data;
+
+                               initialized_callback = wk_editor->priv->initialized_callback;
+                               initialized_user_data = wk_editor->priv->initialized_user_data;
+
+                               wk_editor->priv->initialized_callback = NULL;
+                               wk_editor->priv->initialized_user_data = NULL;
+
+                               initialized_callback (E_CONTENT_EDITOR (wk_editor), initialized_user_data);
+                       }
+               }
        }
+}
 
-       wk_editor->priv->web_extension = g_dbus_proxy_new_finish (result, &error);
-       if (!wk_editor->priv->web_extension) {
-               g_warning ("Error creating web extension proxy: %s\n", error ? error->message : "Unknown 
error");
-               g_clear_error (&error);
+static void
+e_webkit_editor_set_web_extension_proxy (EWebKitEditor *wk_editor,
+                                        GDBusProxy *proxy)
+{
+       g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
 
-               if (wk_editor->priv->initialized_callback) {
-                       wk_editor->priv->initialized_callback (E_CONTENT_EDITOR (wk_editor), 
wk_editor->priv->initialized_user_data);
+       if (wk_editor->priv->web_extension_proxy) {
+               GDBusConnection *connection;
 
-                       wk_editor->priv->initialized_callback = NULL;
-                       wk_editor->priv->initialized_user_data = NULL;
+               connection = g_dbus_proxy_get_connection (wk_editor->priv->web_extension_proxy);
+
+               if (connection && g_dbus_connection_is_closed (connection))
+                       connection = NULL;
+
+               if (wk_editor->priv->web_extension_content_changed_cb_id) {
+                       if (connection)
+                               g_dbus_connection_signal_unsubscribe (connection, 
wk_editor->priv->web_extension_content_changed_cb_id);
+                       wk_editor->priv->web_extension_content_changed_cb_id = 0;
                }
 
-               e_weak_ref_free (wk_editor_rf);
-               g_object_unref (wk_editor);
+               if (wk_editor->priv->web_extension_selection_changed_cb_id) {
+                       if (connection)
+                               g_dbus_connection_signal_unsubscribe (connection, 
wk_editor->priv->web_extension_selection_changed_cb_id);
+                       wk_editor->priv->web_extension_selection_changed_cb_id = 0;
+               }
 
-               return;
+               if (wk_editor->priv->web_extension_undo_redo_state_changed_cb_id) {
+                       if (connection)
+                               g_dbus_connection_signal_unsubscribe (connection, 
wk_editor->priv->web_extension_undo_redo_state_changed_cb_id);
+                       wk_editor->priv->web_extension_undo_redo_state_changed_cb_id = 0;
+               }
+
+               if (wk_editor->priv->web_extension_user_changed_default_colors_cb_id) {
+                       if (connection)
+                               g_dbus_connection_signal_unsubscribe (connection, 
wk_editor->priv->web_extension_user_changed_default_colors_cb_id);
+                       wk_editor->priv->web_extension_user_changed_default_colors_cb_id = 0;
+               }
+
+               g_clear_object (&wk_editor->priv->web_extension_proxy);
        }
 
-       g_clear_object (&wk_editor->priv->dbus_connection);
-       wk_editor->priv->dbus_connection = g_object_ref (g_dbus_proxy_get_connection 
(wk_editor->priv->web_extension));
+       if (proxy) {
+               wk_editor->priv->web_extension_proxy = g_object_ref (proxy);
 
-       if (wk_editor->priv->web_extension_selection_changed_cb_id == 0) {
                wk_editor->priv->web_extension_selection_changed_cb_id =
                        g_dbus_connection_signal_subscribe (
-                               wk_editor->priv->dbus_connection,
-                               g_dbus_proxy_get_name (wk_editor->priv->web_extension),
+                               g_dbus_proxy_get_connection (wk_editor->priv->web_extension_proxy),
+                               g_dbus_proxy_get_name (wk_editor->priv->web_extension_proxy),
                                E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE,
                                "SelectionChanged",
                                E_WEBKIT_EDITOR_WEB_EXTENSION_OBJECT_PATH,
@@ -599,13 +641,11 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
                                (GDBusSignalCallback) web_extension_selection_changed_cb,
                                wk_editor,
                                NULL);
-       }
 
-       if (wk_editor->priv->web_extension_content_changed_cb_id == 0) {
                wk_editor->priv->web_extension_content_changed_cb_id =
                        g_dbus_connection_signal_subscribe (
-                               wk_editor->priv->dbus_connection,
-                               g_dbus_proxy_get_name (wk_editor->priv->web_extension),
+                               g_dbus_proxy_get_connection (wk_editor->priv->web_extension_proxy),
+                               g_dbus_proxy_get_name (wk_editor->priv->web_extension_proxy),
                                E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE,
                                "ContentChanged",
                                E_WEBKIT_EDITOR_WEB_EXTENSION_OBJECT_PATH,
@@ -614,13 +654,11 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
                                (GDBusSignalCallback) web_extension_content_changed_cb,
                                wk_editor,
                                NULL);
-       }
 
-       if (wk_editor->priv->web_extension_undo_redo_state_changed_cb_id == 0) {
                wk_editor->priv->web_extension_undo_redo_state_changed_cb_id =
                        g_dbus_connection_signal_subscribe (
-                               wk_editor->priv->dbus_connection,
-                               g_dbus_proxy_get_name (wk_editor->priv->web_extension),
+                               g_dbus_proxy_get_connection (wk_editor->priv->web_extension_proxy),
+                               g_dbus_proxy_get_name (wk_editor->priv->web_extension_proxy),
                                E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE,
                                "UndoRedoStateChanged",
                                E_WEBKIT_EDITOR_WEB_EXTENSION_OBJECT_PATH,
@@ -629,13 +667,11 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
                                (GDBusSignalCallback) web_extension_undo_redo_state_changed_cb,
                                wk_editor,
                                NULL);
-       }
 
-       if (wk_editor->priv->web_extension_user_changed_default_colors_cb_id == 0) {
                wk_editor->priv->web_extension_user_changed_default_colors_cb_id =
                        g_dbus_connection_signal_subscribe (
-                               wk_editor->priv->dbus_connection,
-                               g_dbus_proxy_get_name (wk_editor->priv->web_extension),
+                               g_dbus_proxy_get_connection (wk_editor->priv->web_extension_proxy),
+                               g_dbus_proxy_get_name (wk_editor->priv->web_extension_proxy),
                                E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE,
                                "UserChangedDefaultColors",
                                E_WEBKIT_EDITOR_WEB_EXTENSION_OBJECT_PATH,
@@ -645,99 +681,6 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
                                wk_editor,
                                NULL);
        }
-
-       dispatch_pending_operations (wk_editor);
-
-       if (wk_editor->priv->emit_load_finished_when_extension_is_ready) {
-               e_content_editor_emit_load_finished (E_CONTENT_EDITOR (wk_editor));
-
-               wk_editor->priv->emit_load_finished_when_extension_is_ready = FALSE;
-       }
-
-       g_object_notify (G_OBJECT (wk_editor), "web-extension");
-
-       if (wk_editor->priv->initialized_callback) {
-               wk_editor->priv->initialized_callback (E_CONTENT_EDITOR (wk_editor), 
wk_editor->priv->initialized_user_data);
-
-               wk_editor->priv->initialized_callback = NULL;
-               wk_editor->priv->initialized_user_data = NULL;
-       }
-
-       e_weak_ref_free (wk_editor_rf);
-       g_object_unref (wk_editor);
-}
-
-static void
-web_extension_appeared_cb (GDBusConnection *connection,
-                           const gchar *name,
-                           const gchar *name_owner,
-                           GWeakRef *wk_editor_wr)
-{
-       EWebKitEditor *wk_editor;
-
-       wk_editor = g_weak_ref_get (wk_editor_wr);
-
-       if (!wk_editor)
-               return;
-
-       g_dbus_proxy_new (
-               connection,
-               G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
-               G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
-               NULL,
-               name,
-               E_WEBKIT_EDITOR_WEB_EXTENSION_OBJECT_PATH,
-               E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE,
-               NULL,
-               (GAsyncReadyCallback) web_extension_proxy_created_cb,
-               e_weak_ref_new (wk_editor));
-
-       g_object_unref (wk_editor);
-}
-
-static void
-web_extension_vanished_cb (GDBusConnection *connection,
-                           const gchar *name,
-                           GWeakRef *wk_editor_wr)
-{
-       EWebKitEditor *wk_editor;
-
-       wk_editor = g_weak_ref_get (wk_editor_wr);
-
-       if (!wk_editor)
-               return;
-
-       /* The vanished callback can be sometimes called before the appeared
-          callback, in which case it doesn't make sense to unwatch the name. */
-       if (wk_editor->priv->web_extension) {
-               g_clear_object (&wk_editor->priv->web_extension);
-
-               if (wk_editor->priv->web_extension_watch_name_id > 0) {
-                       g_bus_unwatch_name (wk_editor->priv->web_extension_watch_name_id);
-                       wk_editor->priv->web_extension_watch_name_id = 0;
-               }
-       }
-
-       g_object_unref (wk_editor);
-}
-
-static void
-webkit_editor_watch_web_extension (EWebKitEditor *wk_editor)
-{
-       gchar *service_name;
-
-       service_name = webkit_editor_create_service_name_for_web_context (webkit_web_view_get_context 
(WEBKIT_WEB_VIEW (wk_editor)));
-
-       wk_editor->priv->web_extension_watch_name_id =
-               g_bus_watch_name (
-                       G_BUS_TYPE_SESSION,
-                       service_name,
-                       G_BUS_NAME_WATCHER_FLAGS_NONE,
-                       (GBusNameAppearedCallback) web_extension_appeared_cb,
-                       (GBusNameVanishedCallback) web_extension_vanished_cb,
-                       e_weak_ref_new (wk_editor), (GDestroyNotify) e_weak_ref_free);
-
-       g_free (service_name);
 }
 
 static guint64
@@ -745,20 +688,21 @@ current_page_id (EWebKitEditor *wk_editor)
 {
        return webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (wk_editor));
 }
+
 static void
 webkit_editor_call_simple_extension_function_sync (EWebKitEditor *wk_editor,
-                                                   const gchar *function)
+                                                  const gchar *method_name)
 {
        GVariant *result;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
-               function,
+               wk_editor->priv->web_extension_proxy,
+               method_name,
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
 
@@ -768,18 +712,14 @@ webkit_editor_call_simple_extension_function_sync (EWebKitEditor *wk_editor,
 
 static void
 webkit_editor_call_simple_extension_function (EWebKitEditor *wk_editor,
-                                              const gchar *function)
+                                              const gchar *method_name)
 {
-       if (!wk_editor->priv->web_extension) {
-               g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
-               return;
-       }
+       guint64 page_id;
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
-               function,
-               g_variant_new ("(t)", current_page_id (wk_editor)),
-               wk_editor->priv->cancellable);
+       page_id = current_page_id (wk_editor);
+
+       e_web_extension_container_call_simple (wk_editor->priv->container, page_id, wk_editor->priv->stamp,
+               method_name, g_variant_new ("(t)", page_id));
 }
 
 static GVariant *
@@ -789,13 +729,13 @@ webkit_editor_get_element_attribute (EWebKitEditor *wk_editor,
 {
        GVariant *result;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return NULL;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ElementGetAttributeBySelector",
                g_variant_new ("(tss)", current_page_id (wk_editor), selector, attribute),
                NULL);
@@ -809,17 +749,12 @@ webkit_editor_set_element_attribute (EWebKitEditor *wk_editor,
                                      const gchar *attribute,
                                      const gchar *value)
 {
-       if (!wk_editor->priv->web_extension) {
-               g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
-               return;
-       }
+       guint64 page_id;
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
-               "ElementSetAttributeBySelector",
-               g_variant_new (
-                       "(tsss)", current_page_id (wk_editor), selector, attribute, value),
-               wk_editor->priv->cancellable);
+       page_id = current_page_id (wk_editor);
+
+       e_web_extension_container_call_simple (wk_editor->priv->container, page_id, wk_editor->priv->stamp,
+               "ElementSetAttributeBySelector", g_variant_new ("(tsss)", page_id, selector, attribute, 
value));
 }
 
 static void
@@ -827,16 +762,12 @@ webkit_editor_remove_element_attribute (EWebKitEditor *wk_editor,
                                         const gchar *selector,
                                         const gchar *attribute)
 {
-       if (!wk_editor->priv->web_extension) {
-               g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
-               return;
-       }
+       guint64 page_id;
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
-               "ElementRemoveAttributeBySelector",
-               g_variant_new ("(tss)", current_page_id (wk_editor), selector, attribute),
-               wk_editor->priv->cancellable);
+       page_id = current_page_id (wk_editor);
+
+       e_web_extension_container_call_simple (wk_editor->priv->container, page_id, wk_editor->priv->stamp,
+               "ElementRemoveAttributeBySelector", g_variant_new ("(tss)", page_id, selector, attribute));
 }
 
 static void
@@ -844,16 +775,12 @@ webkit_editor_set_format_boolean (EWebKitEditor *wk_editor,
                                   const gchar *format_dom_function,
                                   gboolean format_value)
 {
-       if (!wk_editor->priv->web_extension) {
-               g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
-               return;
-       }
+       guint64 page_id;
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
-               format_dom_function,
-               g_variant_new ("(tb)", current_page_id (wk_editor), format_value),
-               wk_editor->priv->cancellable);
+       page_id = current_page_id (wk_editor);
+
+       e_web_extension_container_call_simple (wk_editor->priv->container, page_id, wk_editor->priv->stamp,
+               format_dom_function, g_variant_new ("(tb)", page_id, format_value));
 }
 
 static void
@@ -861,16 +788,12 @@ webkit_editor_set_format_int (EWebKitEditor *wk_editor,
                               const gchar *format_dom_function,
                               gint32 format_value)
 {
-       if (!wk_editor->priv->web_extension) {
-               g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
-               return;
-       }
+       guint64 page_id;
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
-               format_dom_function,
-               g_variant_new ("(ti)", current_page_id (wk_editor), format_value),
-               wk_editor->priv->cancellable);
+       page_id = current_page_id (wk_editor);
+
+       e_web_extension_container_call_simple (wk_editor->priv->container, page_id, wk_editor->priv->stamp,
+               format_dom_function, g_variant_new ("(ti)", page_id, format_value));
 }
 
 static void
@@ -879,21 +802,17 @@ webkit_editor_set_format_string (EWebKitEditor *wk_editor,
                                  const gchar *format_dom_function,
                                  const gchar *format_value)
 {
-       if (!wk_editor->priv->web_extension) {
-               g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
-               return;
-       }
+       guint64 page_id;
 
        if (!wk_editor->priv->html_mode)
                return;
 
        webkit_editor_set_changed (wk_editor, TRUE);
 
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
-               format_dom_function,
-               g_variant_new ("(ts)", current_page_id (wk_editor), format_value),
-               wk_editor->priv->cancellable);
+       page_id = current_page_id (wk_editor);
+
+       e_web_extension_container_call_simple (wk_editor->priv->container, page_id, wk_editor->priv->stamp,
+               format_dom_function, g_variant_new ("(ts)", page_id, format_value));
 
        g_object_notify (G_OBJECT (wk_editor), format_name);
 }
@@ -945,7 +864,7 @@ webkit_editor_initialize (EContentEditor *content_editor,
 
        wk_editor = E_WEBKIT_EDITOR (content_editor);
 
-       if (wk_editor->priv->web_extension) {
+       if (wk_editor->priv->web_extension_proxy) {
                callback (content_editor, user_data);
        } else {
                g_return_if_fail (wk_editor->priv->initialized_callback == NULL);
@@ -1784,7 +1703,7 @@ webkit_editor_set_html_mode (EWebKitEditor *wk_editor,
 
        g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -1793,7 +1712,7 @@ webkit_editor_set_html_mode (EWebKitEditor *wk_editor,
                return;
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMCheckIfConversionNeeded",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -1815,7 +1734,7 @@ webkit_editor_set_html_mode (EWebKitEditor *wk_editor,
        wk_editor->priv->html_mode = html_mode;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "SetEditorHTMLMode",
                g_variant_new ("(tbb)", current_page_id (wk_editor), html_mode, convert),
                wk_editor->priv->cancellable);
@@ -1834,7 +1753,7 @@ set_convert_in_situ (EWebKitEditor *wk_editor,
        GVariant *result;
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "SetConvertInSitu",
                g_variant_new ("(tbnn)", current_page_id (wk_editor), value,
                        e_webkit_editor_three_state_to_int16 (e_content_editor_get_start_bottom 
(E_CONTENT_EDITOR (wk_editor))),
@@ -1845,6 +1764,26 @@ set_convert_in_situ (EWebKitEditor *wk_editor,
                g_variant_unref (result);
 }
 
+static void
+e_webkit_editor_load_data (EWebKitEditor *wk_editor,
+                          const gchar *html)
+{
+       gchar *uri_with_stamp;
+
+       g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
+
+       if (!html)
+               html = "";
+
+       /* Make WebKit think we are displaying a local file, so that it
+        * does not block loading resources from file:// protocol */
+       uri_with_stamp = g_strdup_printf ("file:///?evo-stamp=%d", wk_editor->priv->stamp);
+
+       webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), html, uri_with_stamp);
+
+       g_free (uri_with_stamp);
+}
+
 static void
 webkit_editor_insert_content (EContentEditor *editor,
                               const gchar *content,
@@ -1869,7 +1808,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                return;
        }
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                /* If the operation needs a web extension and it is not ready yet
                 * we need to schedule the current operation again a dispatch it
                 * when the extension is ready */
@@ -1893,7 +1832,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                   e_html_editor_view_convert_and_insert_html_to_plain_text
                   e_html_editor_view_insert_text */
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "DOMConvertAndInsertHTMLIntoSelection",
                        g_variant_new (
                                "(tsb)",
@@ -1906,14 +1845,14 @@ webkit_editor_insert_content (EContentEditor *editor,
                if ((strstr (content, "data-evo-draft") ||
                     strstr (content, "data-evo-signature-plain-text-mode"))) {
                        wk_editor->priv->reload_in_progress = TRUE;
-                       webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), content, "file://");
+                       e_webkit_editor_load_data (wk_editor, content);
                        return;
                }
 
                if (strstr (content, "data-evo-draft") && !(wk_editor->priv->html_mode)) {
                        set_convert_in_situ (wk_editor, TRUE);
                        wk_editor->priv->reload_in_progress = TRUE;
-                       webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), content, "file://");
+                       e_webkit_editor_load_data (wk_editor, content);
                        return;
                }
 
@@ -1925,7 +1864,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                                        set_convert_in_situ (wk_editor, FALSE);
                                        wk_editor->priv->reload_in_progress = TRUE;
                                        webkit_editor_set_html_mode (wk_editor, TRUE);
-                                       webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), content, 
"file://");
+                                       e_webkit_editor_load_data (wk_editor, content);
                                        return;
                                }
                        }
@@ -1933,11 +1872,11 @@ webkit_editor_insert_content (EContentEditor *editor,
                }
 
                wk_editor->priv->reload_in_progress = TRUE;
-               webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), content, "file://");
+               e_webkit_editor_load_data (wk_editor, content);
        } else if ((flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL) &&
                   (flags & E_CONTENT_EDITOR_INSERT_TEXT_PLAIN)) {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "DOMConvertContent",
                        g_variant_new ("(tsnn)", current_page_id (wk_editor), content,
                                e_webkit_editor_three_state_to_int16 (e_content_editor_get_start_bottom 
(editor)),
@@ -1948,7 +1887,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                    !(flags & E_CONTENT_EDITOR_INSERT_QUOTE_CONTENT)) {
                /* e_html_editor_view_paste_as_text */
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "DOMConvertAndInsertHTMLIntoSelection",
                        g_variant_new (
                                "(tsb)", current_page_id (wk_editor), content, TRUE),
@@ -1957,7 +1896,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                   !(flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL)) {
                /* e_html_editor_view_paste_clipboard_quoted */
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "DOMQuoteAndInsertTextIntoSelection",
                        g_variant_new (
                                "(tsb)", current_page_id (wk_editor), content, (flags & 
E_CONTENT_EDITOR_INSERT_TEXT_HTML) != 0),
@@ -1966,7 +1905,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                   !(flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL)) {
                /* e_html_editor_view_insert_html */
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "DOMInsertHTML",
                        g_variant_new (
                                "(ts)", current_page_id (wk_editor), content),
@@ -2064,14 +2003,14 @@ webkit_editor_get_content (EContentEditor *editor,
        GError *local_error = NULL;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension)
+       if (!wk_editor->priv->web_extension_proxy)
                return NULL;
 
        if ((flags & E_CONTENT_EDITOR_GET_TEXT_HTML) &&
            !(flags & E_CONTENT_EDITOR_GET_PROCESSED) &&
             !(flags & E_CONTENT_EDITOR_GET_BODY))
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "DOMEmbedStyleSheet",
                        g_variant_new (
                                "(ts)",
@@ -2080,7 +2019,7 @@ webkit_editor_get_content (EContentEditor *editor,
                        wk_editor->priv->cancellable);
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMGetContent",
                g_variant_new (
                        "(tsi)",
@@ -2166,13 +2105,13 @@ webkit_editor_move_caret_on_coordinates (EContentEditor *editor,
        GVariant *result;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMMoveSelectionOnPoint",
                g_variant_new (
                        "(tiib)", current_page_id (wk_editor), x, y, cancel_if_not_collapsed),
@@ -2189,13 +2128,13 @@ webkit_editor_insert_emoticon (EContentEditor *editor,
        EWebKitEditor *wk_editor;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMInsertSmiley",
                g_variant_new (
                        "(ts)", current_page_id (wk_editor), e_emoticon_get_name (emoticon)),
@@ -2214,7 +2153,7 @@ webkit_editor_insert_image_from_mime_part (EContentEditor *editor,
        const gchar *cid, *name;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -2248,7 +2187,7 @@ webkit_editor_insert_image_from_mime_part (EContentEditor *editor,
        cid_uri = g_strdup_printf ("cid:%s", cid);
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMAddNewInlineImageIntoList",
                g_variant_new ("(tsss)", current_page_id (wk_editor), name ? name : "", cid_uri, src),
                wk_editor->priv->cancellable);
@@ -2356,13 +2295,13 @@ webkit_editor_get_caret_word (EContentEditor *editor)
        GVariant *result;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return NULL;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMGetCaretWord",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -2511,13 +2450,13 @@ webkit_editor_get_current_signature_uid (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return NULL;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMGetActiveSignatureUid",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -2542,7 +2481,7 @@ webkit_editor_is_ready (EContentEditor *editor)
         * and the web extension for the editor is created. */
        return !webkit_web_view_is_loading (WEBKIT_WEB_VIEW (wk_editor)) &&
                !wk_editor->priv->reload_in_progress &&
-               wk_editor->priv->web_extension &&
+               wk_editor->priv->web_extension_proxy &&
                (!wk_editor->priv->post_reload_operations || g_queue_is_empty 
(wk_editor->priv->post_reload_operations));
 }
 
@@ -2561,13 +2500,13 @@ webkit_editor_insert_signature (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return NULL;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMInsertSignature",
                g_variant_new (
                        "(tsbsbbbnn)",
@@ -2605,13 +2544,13 @@ webkit_editor_get_caret_position (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMGetCaretPosition",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -2633,13 +2572,13 @@ webkit_editor_get_caret_offset (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMGetCaretOffset",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -2659,13 +2598,13 @@ webkit_editor_clear_undo_redo_history (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMClearUndoRedoHistory",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                wk_editor->priv->cancellable);
@@ -2679,13 +2618,13 @@ webkit_editor_replace_caret_word (EContentEditor *editor,
        GVariant *result;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMReplaceCaretWord",
                g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
                wk_editor->priv->cancellable);
@@ -2747,13 +2686,13 @@ webkit_editor_replace (EContentEditor *editor,
        GVariant *result;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMSelectionReplace",
                g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
                wk_editor->priv->cancellable);
@@ -2785,7 +2724,7 @@ webkit_find_controller_found_text_cb (WebKitFindController *find_controller,
                 * 'replacement'. Repeat until there's at least one occurrence of
                 * 'word' in the document */
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "DOMSelectionReplace",
                        g_variant_new ("(ts)", current_page_id (wk_editor), wk_editor->priv->replace_with),
                        wk_editor->priv->cancellable);
@@ -2806,13 +2745,13 @@ webkit_find_controller_failed_to_find_text_cb (WebKitFindController *find_contro
                guint replaced_count = wk_editor->priv->replaced_count;
 
                if (replaced_count > 0) {
-                       if (!wk_editor->priv->web_extension) {
+                       if (!wk_editor->priv->web_extension_proxy) {
                                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                        } else {
                                GVariant *result;
 
                                result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-                                       wk_editor->priv->web_extension,
+                                       wk_editor->priv->web_extension_proxy,
                                        "DOMInsertReplaceAllHistoryEvent",
                                        g_variant_new ("(tss)",
                                                current_page_id (wk_editor),
@@ -3037,13 +2976,13 @@ webkit_editor_on_h_rule_dialog_open (EContentEditor *editor)
        GVariant *result;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return FALSE;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorHRuleDialogFindHRule",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -3198,7 +3137,7 @@ webkit_editor_h_rule_set_no_shade (EContentEditor *editor,
        EWebKitEditor *wk_editor;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -3219,13 +3158,13 @@ webkit_editor_h_rule_get_no_shade (EContentEditor *editor)
        gboolean no_shade = FALSE;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return FALSE;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ElementHasAttribute",
                g_variant_new ("(tss)", current_page_id (wk_editor), "-x-evo-current-hr", "noshade"),
                NULL);
@@ -3268,13 +3207,13 @@ webkit_editor_insert_image (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMSelectionInsertImage",
                g_variant_new ("(ts)", current_page_id (wk_editor), image_uri),
                wk_editor->priv->cancellable);
@@ -3286,13 +3225,13 @@ webkit_editor_replace_image_src (EWebKitEditor *wk_editor,
                                  const gchar *image_uri)
 {
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "DOMReplaceImageSrc",
                g_variant_new ("(tss)", current_page_id (wk_editor), selector, image_uri),
                wk_editor->priv->cancellable);
@@ -3370,13 +3309,13 @@ webkit_editor_image_set_url (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorImageDialogSetElementUrl",
                g_variant_new ("(ts)", current_page_id (wk_editor), value),
                wk_editor->priv->cancellable);
@@ -3391,13 +3330,13 @@ webkit_editor_image_get_url (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return NULL;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorImageDialogGetElementUrl",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -3418,13 +3357,13 @@ webkit_editor_image_set_vspace (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementSetVSpace",
                g_variant_new (
                        "(tsi)", current_page_id (wk_editor), "-x-evo-current-img", value),
@@ -3440,13 +3379,13 @@ webkit_editor_image_get_vspace (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementGetVSpace",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-img"),
                NULL);
@@ -3467,13 +3406,13 @@ webkit_editor_image_set_hspace (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementSetHSpace",
                g_variant_new (
                        "(tsi)", current_page_id (wk_editor), "-x-evo-current-img", value),
@@ -3489,13 +3428,13 @@ webkit_editor_image_get_hspace (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementGetHSpace",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-img"),
                NULL);
@@ -3589,13 +3528,13 @@ webkit_editor_image_get_natural_width (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementGetNaturalWidth",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-img"),
                NULL);
@@ -3617,13 +3556,13 @@ webkit_editor_image_get_natural_height (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementGetNaturalHeight",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-img"),
                NULL);
@@ -3644,13 +3583,13 @@ webkit_editor_image_set_height (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementSetHeight",
                g_variant_new (
                        "(tsi)", current_page_id (wk_editor), "-x-evo-current-img", value),
@@ -3665,13 +3604,13 @@ webkit_editor_image_set_width (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementSetWidth",
                g_variant_new (
                        "(tsi)", current_page_id (wk_editor), "-x-evo-current-img", value),
@@ -3719,13 +3658,13 @@ webkit_editor_image_get_width (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementGetWidth",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-img"),
                NULL);
@@ -3747,13 +3686,13 @@ webkit_editor_image_get_height (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ImageElementGetHeight",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-img"),
                NULL);
@@ -3808,13 +3747,13 @@ webkit_editor_link_set_values (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorLinkDialogOk",
                g_variant_new ("(tss)", current_page_id (wk_editor), href, text),
                wk_editor->priv->cancellable);
@@ -3830,13 +3769,13 @@ webkit_editor_link_get_values (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorLinkDialogShow",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -3918,7 +3857,7 @@ webkit_editor_get_background_color (EWebKitEditor *wk_editor)
 {
        g_return_val_if_fail (E_IS_WEBKIT_EDITOR (wk_editor), NULL);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return NULL;
        }
@@ -3981,7 +3920,7 @@ webkit_editor_get_font_color (EWebKitEditor *wk_editor)
 {
        g_return_val_if_fail (E_IS_WEBKIT_EDITOR (wk_editor), NULL);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return NULL;
        }
@@ -4099,7 +4038,7 @@ webkit_editor_page_set_background_image_uri (EContentEditor *editor,
                webkit_editor_replace_image_src (wk_editor, "body", uri);
        else {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "RemoveImageAttributesFromElementBySelector",
                        g_variant_new ("(ts)", current_page_id (wk_editor), "body"),
                        wk_editor->priv->cancellable);
@@ -4113,13 +4052,13 @@ webkit_editor_on_cell_dialog_open (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogMarkCurrentCellElement",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-cell"),
                wk_editor->priv->cancellable);
@@ -4148,13 +4087,13 @@ webkit_editor_cell_set_v_align (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogSetElementVAlign",
                g_variant_new ("(tsi)", current_page_id (wk_editor), value, (gint32) scope),
                wk_editor->priv->cancellable);
@@ -4194,13 +4133,13 @@ webkit_editor_cell_set_align (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogSetElementAlign",
                g_variant_new ("(tsi)", current_page_id (wk_editor), value, (gint32) scope),
                wk_editor->priv->cancellable);
@@ -4240,13 +4179,13 @@ webkit_editor_cell_set_wrap (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogSetElementNoWrap",
                g_variant_new ("(tbi)", current_page_id (wk_editor), !value, (gint32) scope),
                wk_editor->priv->cancellable);
@@ -4264,13 +4203,13 @@ webkit_editor_cell_get_wrap (EContentEditor *editor)
        if (!wk_editor->priv->html_mode)
                return FALSE;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return FALSE;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "TableCellElementGetNoWrap",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-cell"),
                NULL);
@@ -4293,7 +4232,7 @@ webkit_editor_cell_set_header_style (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -4302,7 +4241,7 @@ webkit_editor_cell_set_header_style (EContentEditor *editor,
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogSetElementHeaderStyle",
                g_variant_new ("(tbi)", current_page_id (wk_editor), value, (gint32) scope),
                wk_editor->priv->cancellable);
@@ -4320,13 +4259,13 @@ webkit_editor_cell_is_header (EContentEditor *editor)
        if (!wk_editor->priv->html_mode)
                return FALSE;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return FALSE;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "ElementGetTagName",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-cell"),
                NULL);
@@ -4389,13 +4328,13 @@ webkit_editor_cell_get_row_span (EContentEditor *editor)
        if (!wk_editor->priv->html_mode)
                return 0;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "TableCellElementGetRowSpan",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-cell"),
                NULL);
@@ -4420,13 +4359,13 @@ webkit_editor_cell_get_col_span (EContentEditor *editor)
        if (!wk_editor->priv->html_mode)
                return 0;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "TableCellElementGetColSpan",
                g_variant_new ("(ts)", current_page_id (wk_editor), "-x-evo-current-cell"),
                NULL);
@@ -4504,13 +4443,13 @@ webkit_editor_cell_set_row_span (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogSetElementRowSpan",
                g_variant_new ("(tii)", current_page_id (wk_editor), value, (gint32) scope),
                wk_editor->priv->cancellable);
@@ -4528,13 +4467,13 @@ webkit_editor_cell_set_col_span (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogSetElementColSpan",
                g_variant_new ("(tii)", current_page_id (wk_editor), value, (gint32) scope),
                wk_editor->priv->cancellable);
@@ -4554,7 +4493,7 @@ webkit_editor_cell_set_width (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -4568,7 +4507,7 @@ webkit_editor_cell_set_width (EContentEditor *editor,
                        (unit == E_CONTENT_EDITOR_UNIT_PIXEL) ? "px" : "%");
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogSetElementWidth",
                g_variant_new ("(tsi)", current_page_id (wk_editor), width, (gint32) scope),
                wk_editor->priv->cancellable);
@@ -4586,7 +4525,7 @@ webkit_editor_cell_set_background_color (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -4597,7 +4536,7 @@ webkit_editor_cell_set_background_color (EContentEditor *editor,
                color = g_strdup ("");
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorCellDialogSetElementBgColor",
                g_variant_new ("(tsi)", current_page_id (wk_editor), color, (gint32) scope),
                wk_editor->priv->cancellable);
@@ -4613,7 +4552,7 @@ webkit_editor_cell_set_background_image_uri (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -4625,7 +4564,7 @@ webkit_editor_cell_set_background_image_uri (EContentEditor *editor,
                webkit_editor_replace_image_src (wk_editor, "#-x-evo-current-cell", uri);
        else {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "RemoveImageAttributesFromElementBySelector",
                        g_variant_new ("(ts)", current_page_id (wk_editor), "#-x-evo-current-cell"),
                        wk_editor->priv->cancellable);
@@ -4643,13 +4582,13 @@ webkit_editor_table_set_row_count (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorTableDialogSetRowCount",
                g_variant_new ("(tu)", current_page_id (wk_editor), value),
                wk_editor->priv->cancellable);
@@ -4667,13 +4606,13 @@ webkit_editor_table_get_row_count (EContentEditor *editor)
        if (!wk_editor->priv->html_mode)
                return 0;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorTableDialogGetRowCount",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -4697,13 +4636,13 @@ webkit_editor_table_set_column_count (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorTableDialogSetColumnCount",
                g_variant_new ("(tu)", current_page_id (wk_editor), value),
                wk_editor->priv->cancellable);
@@ -4721,13 +4660,13 @@ webkit_editor_table_get_column_count (EContentEditor *editor)
        if (!wk_editor->priv->html_mode)
                return 0;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return 0;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorTableDialogGetColumnCount",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -4753,7 +4692,7 @@ webkit_editor_table_set_width (EContentEditor *editor,
        if (!wk_editor->priv->html_mode)
                return;
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -5006,7 +4945,7 @@ webkit_editor_table_set_background_color (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -5052,7 +4991,7 @@ webkit_editor_table_set_background_image_uri (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return;
        }
@@ -5064,7 +5003,7 @@ webkit_editor_table_set_background_image_uri (EContentEditor *editor,
                webkit_editor_replace_image_src (wk_editor, "#-x-evo-current-table", uri);
        else {
                e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension,
+                       wk_editor->priv->web_extension_proxy,
                        "RemoveImageAttributesFromElementBySelector",
                        g_variant_new ("(ts)", current_page_id (wk_editor), "#-x-evo-current-table"),
                        wk_editor->priv->cancellable);
@@ -5080,13 +5019,13 @@ webkit_editor_on_table_dialog_open (EContentEditor *editor)
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return FALSE;
        }
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "EEditorTableDialogShow",
                g_variant_new ("(t)", current_page_id (wk_editor)),
                NULL);
@@ -5135,7 +5074,7 @@ move_to_another_word (EContentEditor *editor,
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (!wk_editor->priv->web_extension) {
+       if (!wk_editor->priv->web_extension_proxy) {
                g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
                return NULL;
        }
@@ -5146,7 +5085,7 @@ move_to_another_word (EContentEditor *editor,
                return NULL;
 
        result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                dom_function,
                g_variant_new (
                        "(ts^as)", current_page_id (wk_editor), word ? word : "", active_languages),
@@ -5203,7 +5142,7 @@ webkit_editor_get_web_extension (EWebKitEditor *wk_editor)
 {
        g_return_val_if_fail (E_IS_WEBKIT_EDITOR (wk_editor), NULL);
 
-       return wk_editor->priv->web_extension;
+       return wk_editor->priv->web_extension_proxy;
 }
 
 static void
@@ -5267,6 +5206,22 @@ webkit_editor_process_uri_request_cb (WebKitURISchemeRequest *request,
                webkit_editor_uri_request_done_cb, g_object_ref (request));
 }
 
+static void
+e_webkit_editor_initialize_web_extensions_cb (WebKitWebContext *web_context,
+                                             gpointer user_data)
+{
+       EWebKitEditor *wk_editor = user_data;
+
+       g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
+       g_return_if_fail (wk_editor->priv->container);
+
+       webkit_web_context_set_web_extensions_directory (web_context, 
EVOLUTION_WEB_EXTENSIONS_WEBKIT_EDITOR_DIR);
+       webkit_web_context_set_web_extensions_initialization_user_data (web_context,
+               g_variant_new ("(ss)",
+                       e_web_extension_container_get_server_guid (wk_editor->priv->container),
+                       e_web_extension_container_get_server_address (wk_editor->priv->container)));
+}
+
 static void
 webkit_editor_constructed (GObject *object)
 {
@@ -5277,17 +5232,21 @@ webkit_editor_constructed (GObject *object)
        WebKitSettings *web_settings;
        WebKitWebView *web_view;
 
-       G_OBJECT_CLASS (e_webkit_editor_parent_class)->constructed (object);
-
        wk_editor = E_WEBKIT_EDITOR (object);
        web_view = WEBKIT_WEB_VIEW (wk_editor);
 
-       webkit_editor_watch_web_extension (wk_editor);
+       web_context = webkit_web_view_get_context (web_view);
+
+       /* Do this before calling the parent's constructed(), because
+          that can emit the web_context's signal */
+       g_signal_connect_object (web_context, "initialize-web-extensions",
+               G_CALLBACK (e_webkit_editor_initialize_web_extensions_cb), wk_editor, 0);
+
+       G_OBJECT_CLASS (e_webkit_editor_parent_class)->constructed (object);
 
        /* Give spell check languages to WebKit */
        languages = e_spell_checker_list_active_languages (wk_editor->priv->spell_checker, NULL);
 
-       web_context = webkit_web_view_get_context (web_view);
        webkit_web_context_set_spell_checking_enabled (web_context, TRUE);
        webkit_web_context_set_spell_checking_languages (web_context, (const gchar * const *) languages);
        g_strfreev (languages);
@@ -5305,10 +5264,7 @@ webkit_editor_constructed (GObject *object)
        webkit_settings_set_allow_file_access_from_file_urls (web_settings, TRUE);
        webkit_settings_set_enable_developer_extras (web_settings, e_util_get_webkit_developer_mode_enabled 
());
 
-       /* Make WebKit think we are displaying a local file, so that it
-        * does not block loading resources from file:// protocol */
-       webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), "", "file://");
-
+       e_webkit_editor_load_data (wk_editor, "");
 }
 
 static GObjectConstructParam*
@@ -5351,20 +5307,12 @@ webkit_editor_constructor (GType type,
                        static gpointer web_context = NULL;
 
                        if (!web_context) {
-                               gchar *service_name;
-
                                web_context = webkit_web_context_new ();
 
-                               service_name = webkit_editor_create_service_name_for_web_context 
(web_context);
-
                                webkit_web_context_set_cache_model (web_context, 
WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER);
                                webkit_web_context_set_web_extensions_directory (web_context, 
EVOLUTION_WEB_EXTENSIONS_WEBKIT_EDITOR_DIR);
-                               webkit_web_context_set_web_extensions_initialization_user_data (web_context,
-                                       g_variant_new_string (service_name));
 
                                g_object_add_weak_pointer (G_OBJECT (web_context), &web_context);
-
-                               g_free (service_name);
                        } else {
                                g_object_ref (web_context);
                        }
@@ -5411,38 +5359,10 @@ webkit_editor_dispose (GObject *object)
                priv->mail_settings = NULL;
        }
 
-       if (priv->web_extension_content_changed_cb_id > 0 && priv->dbus_connection) {
-               g_dbus_connection_signal_unsubscribe (
-                       priv->dbus_connection,
-                       priv->web_extension_content_changed_cb_id);
-               priv->web_extension_content_changed_cb_id = 0;
-       }
-
-       if (priv->web_extension_selection_changed_cb_id > 0 && priv->dbus_connection) {
-               g_dbus_connection_signal_unsubscribe (
-                       priv->dbus_connection,
-                       priv->web_extension_selection_changed_cb_id);
-               priv->web_extension_selection_changed_cb_id = 0;
-       }
-
-       if (priv->web_extension_undo_redo_state_changed_cb_id > 0 && priv->dbus_connection) {
-               g_dbus_connection_signal_unsubscribe (
-                       priv->dbus_connection,
-                       priv->web_extension_undo_redo_state_changed_cb_id);
-               priv->web_extension_undo_redo_state_changed_cb_id = 0;
-       }
+       e_webkit_editor_set_web_extension_proxy (E_WEBKIT_EDITOR (object), NULL);
 
-       if (priv->web_extension_user_changed_default_colors_cb_id > 0 && priv->dbus_connection) {
-               g_dbus_connection_signal_unsubscribe (
-                       priv->dbus_connection,
-                       priv->web_extension_user_changed_default_colors_cb_id);
-               priv->web_extension_user_changed_default_colors_cb_id = 0;
-       }
-
-       if (priv->web_extension_watch_name_id > 0) {
-               g_bus_unwatch_name (priv->web_extension_watch_name_id);
-               priv->web_extension_watch_name_id = 0;
-       }
+       if (priv->container && priv->stamp)
+               e_web_extension_container_forget_stamp (priv->container, priv->stamp);
 
        if (priv->owner_change_clipboard_cb_id > 0) {
                g_signal_handler_disconnect (
@@ -5460,8 +5380,7 @@ webkit_editor_dispose (GObject *object)
 
        webkit_editor_finish_search (E_WEBKIT_EDITOR (object));
 
-       g_clear_object (&priv->web_extension);
-       g_clear_object (&priv->dbus_connection);
+       g_clear_object (&priv->container);
 
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (e_webkit_editor_parent_class)->dispose (object);
@@ -5965,7 +5884,7 @@ webkit_editor_clipboard_owner_change_cb (GtkClipboard *clipboard,
        if (!E_IS_WEBKIT_EDITOR (wk_editor))
                return;
 
-       if (!wk_editor->priv->web_extension)
+       if (!wk_editor->priv->web_extension_proxy)
                return;
 
        if (wk_editor->priv->copy_cut_actions_triggered && event->owner)
@@ -5977,7 +5896,7 @@ webkit_editor_clipboard_owner_change_cb (GtkClipboard *clipboard,
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "SetPastingContentFromItself",
                g_variant_new (
                        "(tb)",
@@ -5996,7 +5915,7 @@ webkit_editor_primary_clipboard_owner_change_cb (GtkClipboard *clipboard,
                                                  EWebKitEditor *wk_editor)
 {
        if (!E_IS_WEBKIT_EDITOR (wk_editor) ||
-           !wk_editor->priv->web_extension)
+           !wk_editor->priv->web_extension_proxy)
                return;
 
        if (!event->owner || !wk_editor->priv->can_copy)
@@ -6006,7 +5925,7 @@ webkit_editor_primary_clipboard_owner_change_cb (GtkClipboard *clipboard,
                return;
 
        e_util_invoke_g_dbus_proxy_call_with_error_check (
-               wk_editor->priv->web_extension,
+               wk_editor->priv->web_extension_proxy,
                "SetPastingContentFromItself",
                g_variant_new (
                        "(tb)",
@@ -6611,6 +6530,14 @@ e_webkit_editor_init (EWebKitEditor *wk_editor)
        wk_editor->priv->spell_checker = e_spell_checker_new ();
        wk_editor->priv->old_settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
(GDestroyNotify) g_variant_unref);
        wk_editor->priv->visually_wrap_long_lines = FALSE;
+       wk_editor->priv->container = e_web_extension_container_new 
(E_WEBKIT_EDITOR_WEB_EXTENSION_OBJECT_PATH, E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE);
+
+       /* Do not change assigned stamp on every content load. It can have issues like when
+          loading new content into already initialized editor. */
+       wk_editor->priv->stamp = e_web_extension_container_reserve_stamp (wk_editor->priv->container);
+
+       g_signal_connect_object (wk_editor->priv->container, "page-proxy-changed",
+               G_CALLBACK (e_webkit_editor_page_proxy_changed_cb), wk_editor, 0);
 
        g_signal_connect (
                wk_editor, "load-changed",
diff --git a/src/modules/webkit-editor/web-extension/e-editor-page.c 
b/src/modules/webkit-editor/web-extension/e-editor-page.c
index 09b02359bc..18d50837b6 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-page.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-page.c
@@ -31,6 +31,7 @@
 struct _EEditorPagePrivate {
        WebKitWebPage *web_page; /* not referenced */
        EEditorWebExtension *web_extension; /* not referenced */
+       gint stamp;
 
        EEditorUndoRedoManager *undo_redo_manager;
        ESpellChecker *spell_checker;
@@ -307,6 +308,23 @@ e_editor_page_get_page_id (EEditorPage *editor_page)
        return webkit_web_page_get_id (editor_page->priv->web_page);
 }
 
+gint
+e_editor_page_get_stamp (EEditorPage *editor_page)
+{
+       g_return_val_if_fail (E_IS_EDITOR_PAGE (editor_page), 0);
+
+       return editor_page->priv->stamp;
+}
+
+void
+e_editor_page_set_stamp (EEditorPage *editor_page,
+                        gint stamp)
+{
+       g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+       editor_page->priv->stamp = stamp;
+}
+
 WebKitDOMDocument *
 e_editor_page_get_document (EEditorPage *editor_page)
 {
diff --git a/src/modules/webkit-editor/web-extension/e-editor-page.h 
b/src/modules/webkit-editor/web-extension/e-editor-page.h
index c6767ccaca..8365149ee8 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-page.h
+++ b/src/modules/webkit-editor/web-extension/e-editor-page.h
@@ -69,6 +69,9 @@ WebKitWebPage *       e_editor_page_get_web_page      (EEditorPage *editor_page);
 struct _EEditorWebExtension *
                e_editor_page_get_web_extension (EEditorPage *editor_page);
 guint64                e_editor_page_get_page_id       (EEditorPage *editor_page);
+gint           e_editor_page_get_stamp         (EEditorPage *editor_page);
+void           e_editor_page_set_stamp         (EEditorPage *editor_page,
+                                                gint stamp);
 WebKitDOMDocument *
                e_editor_page_get_document      (EEditorPage *editor_page);
 struct _EEditorUndoRedoManager *
diff --git a/src/modules/webkit-editor/web-extension/e-editor-web-extension-main.c 
b/src/modules/webkit-editor/web-extension/e-editor-web-extension-main.c
index 418346f122..a10c233f47 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-web-extension-main.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-web-extension-main.c
@@ -20,14 +20,35 @@
 
 #include <camel/camel.h>
 
+#define E_UTIL_INCLUDE_WITHOUT_WEBKIT
+#include <e-util/e-util.h>
+#undef E_UTIL_INCLUDE_WITHOUT_WEBKIT
+
 #include "e-editor-web-extension.h"
 
 static void
-bus_acquired_cb (GDBusConnection *connection,
-                 const gchar *name,
-                 EEditorWebExtension *extension)
+connected_to_server_cb (GObject *source_object,
+                       GAsyncResult *result,
+                       gpointer user_data)
 {
+       EEditorWebExtension *extension = user_data;
+       GDBusConnection *connection;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_EDITOR_WEB_EXTENSION (extension));
+
+       connection = e_web_extension_container_utils_connect_to_server_finish (result, &error);
+       if (!connection) {
+               g_warning ("%d %s: Failed to connect to the UI D-Bus server: %s", getpid (), G_STRFUNC,
+                       error ? error->message : "Unknown error");
+               g_clear_error (&error);
+               return;
+       }
+
        e_editor_web_extension_dbus_register (extension, connection);
+
+       g_object_unref (connection);
+       g_object_unref (extension);
 }
 
 /* Forward declaration */
@@ -39,24 +60,21 @@ webkit_web_extension_initialize_with_user_data (WebKitWebExtension *wk_extension
                                                GVariant *user_data)
 {
        EEditorWebExtension *extension;
-       const gchar *service_name;
+       const gchar *guid = NULL, *server_address = NULL;
 
        g_return_if_fail (user_data != NULL);
 
-       service_name = g_variant_get_string (user_data, NULL);
+       g_variant_get (user_data, "(&s&s)", &guid, &server_address);
+
+       if (!server_address) {
+               g_warning ("%d %s: The UI process didn't provide server address", getpid (), G_STRFUNC);
+               return;
+       }
 
        camel_debug_init ();
 
        extension = e_editor_web_extension_get_default ();
        e_editor_web_extension_initialize (extension, wk_extension);
 
-       g_bus_own_name (
-               G_BUS_TYPE_SESSION,
-               service_name,
-               G_BUS_NAME_OWNER_FLAGS_NONE,
-               (GBusAcquiredCallback) bus_acquired_cb,
-               NULL, /* GBusNameAcquiredCallback */
-               NULL, /* GBusNameLostCallback */
-               g_object_ref (extension),
-               (GDestroyNotify) g_object_unref);
+       e_web_extension_container_utils_connect_to_server (server_address, NULL, connected_to_server_cb, 
g_object_ref (extension));
 }
diff --git a/src/modules/webkit-editor/web-extension/e-editor-web-extension-names.h 
b/src/modules/webkit-editor/web-extension/e-editor-web-extension-names.h
index 9aee4aba97..f16a9aec52 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-web-extension-names.h
+++ b/src/modules/webkit-editor/web-extension/e-editor-web-extension-names.h
@@ -19,7 +19,6 @@
 #ifndef E_EDITOR_WEB_EXTENSION_NAMES_H
 #define E_EDITOR_WEB_EXTENSION_NAMES_H
 
-#define E_WEBKIT_EDITOR_WEB_EXTENSION_SERVICE_NAME_PREFIX "org.gnome.Evolution.WebExtension.EWebKitEditor"
 #define E_WEBKIT_EDITOR_WEB_EXTENSION_OBJECT_PATH  "/org/gnome/Evolution/WebExtension/EWebKitEditor"
 #define E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE    "org.gnome.Evolution.WebExtension.EWebKitEditor"
 
diff --git a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c 
b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
index eed7701c01..3138556dcd 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
@@ -52,7 +52,7 @@ struct _EEditorWebExtensionPrivate {
        GDBusConnection *dbus_connection;
        guint registration_id;
 
-       GHashTable *editor_pages; /* guint64 *webpage_id ~> EEditorPage * */
+       GSList *pages; /* EEditorPage * */
 };
 
 static CamelDataCache *emd_global_http_cache = NULL;
@@ -60,6 +60,15 @@ static CamelDataCache *emd_global_http_cache = NULL;
 static const gchar *introspection_xml =
 "<node>"
 "  <interface name='" E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE "'>"
+"    <signal name='ExtensionObjectReady'>"
+"    </signal>"
+"    <method name='GetExtensionHandlesPages'>"
+"      <arg type='at' name='array' direction='out'/>"
+"    </method>"
+"    <signal name='ExtensionHandlesPage'>"
+"      <arg type='t' name='page_id' direction='out'/>"
+"      <arg type='i' name='stamp' direction='out'/>"
+"    </signal>"
 "<!-- ********************************************************* -->"
 "<!--                          SIGNALS                          -->"
 "<!-- ********************************************************* -->"
@@ -617,9 +626,18 @@ static EEditorPage *
 get_editor_page (EEditorWebExtension *extension,
                  guint64 page_id)
 {
+       GSList *link;
+
        g_return_val_if_fail (E_IS_EDITOR_WEB_EXTENSION (extension), NULL);
 
-       return g_hash_table_lookup (extension->priv->editor_pages, &page_id);
+       for (link = extension->priv->pages; link; link = g_slist_next (link)) {
+               EEditorPage *page = link->data;
+
+               if (page && e_editor_page_get_page_id (page) == page_id)
+                       return page;
+       }
+
+       return NULL;
 }
 
 static EEditorPage *
@@ -672,7 +690,26 @@ handle_method_call (GDBusConnection *connection,
        if (camel_debug ("webkit:editor"))
                printf ("EEditorWebExtension - %s - %s\n", G_STRFUNC, method_name);
 
-       if (g_strcmp0 (method_name, "TestHTMLEqual") == 0) {
+       if (g_strcmp0 (method_name, "GetExtensionHandlesPages") == 0) {
+               GVariantBuilder *builder;
+               GSList *link;
+
+               builder = g_variant_builder_new (G_VARIANT_TYPE ("at"));
+
+               for (link = extension->priv->pages; link; link = g_slist_next (link)) {
+                       EEditorPage *page = link->data;
+
+                       if (page) {
+                               g_variant_builder_add (builder, "t", e_editor_page_get_page_id (page));
+                               g_variant_builder_add (builder, "t", (guint64) e_editor_page_get_stamp 
(page));
+                       }
+               }
+
+               g_dbus_method_invocation_return_value (invocation,
+                       g_variant_new ("(at)", builder));
+
+               g_variant_builder_unref (builder);
+       } else if (g_strcmp0 (method_name, "TestHTMLEqual") == 0) {
                gboolean equal = FALSE;
                const gchar *html1 = NULL, *html2 = NULL;
 
@@ -2255,18 +2292,17 @@ web_page_gone_cb (gpointer user_data,
                   GObject *gone_web_page)
 {
        EEditorWebExtension *extension = user_data;
-       GHashTableIter iter;
-       gpointer key, value;
+       GSList *link;
 
        g_return_if_fail (E_IS_EDITOR_WEB_EXTENSION (extension));
 
-       g_hash_table_iter_init (&iter, extension->priv->editor_pages);
-       while (g_hash_table_iter_next (&iter, &key, &value)) {
-               EEditorPage *editor_page = E_EDITOR_PAGE (value);
+       for (link = extension->priv->pages; link; link = g_slist_next (link)) {
+               EEditorPage *editor_page = link->data;
                WebKitWebPage *web_page = e_editor_page_get_web_page (editor_page);
 
                if ((gpointer) web_page == gone_web_page) {
-                       g_hash_table_remove (extension->priv->editor_pages, key);
+                       extension->priv->pages = g_slist_remove (extension->priv->pages, editor_page);
+                       g_object_unref (editor_page);
                        break;
                }
        }
@@ -2288,10 +2324,12 @@ e_editor_web_extension_dispose (GObject *object)
                        extension->priv->dbus_connection,
                        extension->priv->registration_id);
                extension->priv->registration_id = 0;
-               extension->priv->dbus_connection = NULL;
+
+               g_clear_object (&extension->priv->dbus_connection);
        }
 
-       g_hash_table_remove_all (extension->priv->editor_pages);
+       g_slist_free_full (extension->priv->pages, g_object_unref);
+       extension->priv->pages = NULL;
 
        g_clear_object (&extension->priv->wk_extension);
 
@@ -2299,27 +2337,12 @@ e_editor_web_extension_dispose (GObject *object)
        G_OBJECT_CLASS (e_editor_web_extension_parent_class)->dispose (object);
 }
 
-static void
-e_editor_web_extension_finalize (GObject *object)
-{
-       EEditorWebExtension *extension = E_EDITOR_WEB_EXTENSION (object);
-
-       if (extension->priv->editor_pages) {
-               g_hash_table_destroy (extension->priv->editor_pages);
-               extension->priv->editor_pages = NULL;
-       }
-
-       /* Chain up to parent's finalize() method. */
-       G_OBJECT_CLASS (e_editor_web_extension_parent_class)->finalize (object);
-}
-
 static void
 e_editor_web_extension_class_init (EEditorWebExtensionClass *class)
 {
        GObjectClass *object_class = G_OBJECT_CLASS (class);
 
        object_class->dispose = e_editor_web_extension_dispose;
-       object_class->finalize = e_editor_web_extension_finalize;
 
        g_type_class_add_private (object_class, sizeof(EEditorWebExtensionPrivate));
 }
@@ -2328,7 +2351,6 @@ static void
 e_editor_web_extension_init (EEditorWebExtension *extension)
 {
        extension->priv = E_EDITOR_WEB_EXTENSION_GET_PRIVATE (extension);
-       extension->priv->editor_pages = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, 
g_object_unref);
 }
 
 static gpointer
@@ -2478,22 +2500,90 @@ web_page_document_loaded_cb (WebKitWebPage *web_page,
        g_clear_object (&dom_window);
 }
 
+static void
+web_page_notify_uri_cb (GObject *object,
+                       GParamSpec *param,
+                       gpointer user_data)
+{
+       EEditorWebExtension *extension = user_data;
+       WebKitWebPage *web_page;
+       GSList *link;
+       const gchar *uri;
+
+       g_return_if_fail (E_IS_EDITOR_WEB_EXTENSION (extension));
+
+       web_page = WEBKIT_WEB_PAGE (object);
+       uri = webkit_web_page_get_uri (web_page);
+
+       for (link = extension->priv->pages; link; link = g_slist_next (link)) {
+               EEditorPage *page = link->data;
+
+               if (page && e_editor_page_get_web_page (page) == web_page) {
+                       gint new_stamp = 0;
+
+                       if (uri && *uri) {
+                               SoupURI *suri;
+
+                               suri = soup_uri_new (uri);
+                               if (suri) {
+                                       if (soup_uri_get_query (suri)) {
+                                               GHashTable *form;
+
+                                               form = soup_form_decode (soup_uri_get_query (suri));
+                                               if (form) {
+                                                       const gchar *evo_stamp;
+
+                                                       evo_stamp = g_hash_table_lookup (form, "evo-stamp");
+                                                       if (evo_stamp)
+                                                               new_stamp = (gint) g_ascii_strtoll 
(evo_stamp, NULL, 10);
+
+                                                       g_hash_table_destroy (form);
+                                               }
+                                       }
+
+                                       soup_uri_free (suri);
+                               }
+                       }
+
+                       e_editor_page_set_stamp (page, new_stamp);
+
+                       if (extension->priv->dbus_connection) {
+                               GError *error = NULL;
+
+                               g_dbus_connection_emit_signal (
+                                       extension->priv->dbus_connection,
+                                       NULL,
+                                       E_WEBKIT_EDITOR_WEB_EXTENSION_OBJECT_PATH,
+                                       E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE,
+                                       "ExtensionHandlesPage",
+                                       g_variant_new ("(ti)", webkit_web_page_get_id (web_page), new_stamp),
+                                       &error);
+
+                               if (error) {
+                                       g_warning ("Error emitting signal ExtensionHandlesPage: %s", 
error->message);
+                                       g_error_free (error);
+                               }
+                       }
+
+                       return;
+               }
+       }
+
+       g_warning ("%s: Cannot find web_page %p\n", G_STRFUNC, web_page);
+}
+
 static void
 web_page_created_cb (WebKitWebExtension *wk_extension,
                      WebKitWebPage *web_page,
                      EEditorWebExtension *extension)
 {
        EEditorPage *editor_page;
-       guint64 *ppage_id;
 
        g_return_if_fail (WEBKIT_IS_WEB_PAGE (web_page));
        g_return_if_fail (E_IS_EDITOR_WEB_EXTENSION (extension));
 
-       ppage_id = g_new (guint64, 1);
-       *ppage_id = webkit_web_page_get_id (web_page);
-
        editor_page = e_editor_page_new (web_page, extension);
-       g_hash_table_insert (extension->priv->editor_pages, ppage_id, editor_page);
+       extension->priv->pages = g_slist_prepend (extension->priv->pages, editor_page);
 
        g_object_weak_ref (G_OBJECT (web_page), web_page_gone_cb, extension);
 
@@ -2504,6 +2594,11 @@ web_page_created_cb (WebKitWebExtension *wk_extension,
        g_signal_connect (
                web_page, "document-loaded",
                G_CALLBACK (web_page_document_loaded_cb), NULL);
+
+       g_signal_connect_object (
+               web_page, "notify::uri",
+               G_CALLBACK (web_page_notify_uri_cb),
+               extension, 0);
 }
 
 void
@@ -2560,10 +2655,7 @@ e_editor_web_extension_dbus_register (EEditorWebExtension *extension,
                        g_warning ("Failed to register object: %s\n", error->message);
                        g_error_free (error);
                } else {
-                       extension->priv->dbus_connection = connection;
-                       g_object_add_weak_pointer (
-                               G_OBJECT (connection),
-                               (gpointer *) &extension->priv->dbus_connection);
+                       extension->priv->dbus_connection = g_object_ref (connection);
                }
        }
 }
diff --git a/src/web-extensions/CMakeLists.txt b/src/web-extensions/CMakeLists.txt
index 9e5c03d187..82ba059de0 100644
--- a/src/web-extensions/CMakeLists.txt
+++ b/src/web-extensions/CMakeLists.txt
@@ -45,12 +45,14 @@ install(TARGETS edomutils
 )
 
 set(SOURCES
-       e-web-extension.h
-       e-web-extension-names.h
        e-dom-utils.h
+       e-dom-utils.c
+       e-itip-formatter-dom-utils.h
+       e-itip-formatter-dom-utils.c
+       e-web-extension.h
        e-web-extension.c
        e-web-extension-main.c
-       e-dom-utils.c
+       e-web-extension-names.h
 )
 
 add_library(ewebextension MODULE
diff --git a/src/modules/itip-formatter/web-extension/module-itip-formatter-dom-utils.c 
b/src/web-extensions/e-itip-formatter-dom-utils.c
similarity index 62%
rename from src/modules/itip-formatter/web-extension/module-itip-formatter-dom-utils.c
rename to src/web-extensions/e-itip-formatter-dom-utils.c
index edde0c3220..dc4c7c26e5 100644
--- a/src/modules/itip-formatter/web-extension/module-itip-formatter-dom-utils.c
+++ b/src/web-extensions/e-itip-formatter-dom-utils.c
@@ -1,5 +1,5 @@
 /*
- * module-itip-formatter-dom-utils.c
+ * e-itip-formatter-dom-utils.c
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,14 +16,15 @@
  *
  */
 
-#include "module-itip-formatter-dom-utils.h"
+#include "evolution-config.h"
 
 #include <webkitdom/webkitdom.h>
+#include <e-util/e-util.h>
 
-#include "module-itip-formatter-web-extension.h"
-#include "../itip-view-elements-defines.h"
+#include "../modules/itip-formatter/itip-view-elements-defines.h"
+#include "e-web-extension-names.h"
 
-#include <e-util/e-util.h>
+#include "e-itip-formatter-dom-utils.h"
 
 #define ITIP_WEB_EXTENSION_PAGE_ID_KEY "itip-web-extension-page-id"
 #define ITIP_WEB_EXTENSION_PART_ID_KEY "itip-web-extension-part-id"
@@ -47,14 +48,14 @@ recur_toggled_cb (WebKitDOMHTMLInputElement *input,
        g_dbus_connection_emit_signal (
                connection,
                NULL,
-               MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
-               MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
-               "RecurToggled",
+               E_WEB_EXTENSION_OBJECT_PATH,
+               E_WEB_EXTENSION_INTERFACE,
+               "ItipRecurToggled",
                g_variant_new ("(ts)", *ppage_id, part_id),
                &error);
 
        if (error) {
-               g_warning ("Error emitting signal RecurToggled: %s\n", error->message);
+               g_warning ("Error emitting signal ItipRecurToggled: %s\n", error->message);
                g_error_free (error);
        }
 }
@@ -78,14 +79,14 @@ source_changed_cb (WebKitDOMElement *element,
        g_dbus_connection_emit_signal (
                connection,
                NULL,
-               MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
-               MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
-               "SourceChanged",
+               E_WEB_EXTENSION_OBJECT_PATH,
+               E_WEB_EXTENSION_INTERFACE,
+               "ItipSourceChanged",
                g_variant_new ("(ts)", *ppage_id, part_id),
                &error);
 
        if (error) {
-               g_warning ("Error emitting signal SourceChanged: %s\n", error->message);
+               g_warning ("Error emitting signal ItipSourceChanged: %s\n", error->message);
                g_error_free (error);
        }
 }
@@ -101,10 +102,9 @@ rsvp_toggled_cb (WebKitDOMHTMLInputElement *input,
 
        document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (input));
        rsvp = webkit_dom_html_input_element_get_checked (input);
-       el = webkit_dom_document_get_element_by_id (
-               document, TEXTAREA_RSVP_COMMENT);
-       webkit_dom_html_text_area_element_set_disabled (
-               WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), !rsvp);
+       el = webkit_dom_document_get_element_by_id (document, TEXTAREA_RSVP_COMMENT);
+       if (el)
+               webkit_dom_html_text_area_element_set_disabled (WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), 
!rsvp);
 }
 
 /**
@@ -137,18 +137,20 @@ alarm_check_toggled_cb (WebKitDOMHTMLInputElement *check1,
 
        g_free (id);
 
-       webkit_dom_html_input_element_set_disabled (
-               WEBKIT_DOM_HTML_INPUT_ELEMENT (check2),
-               (webkit_dom_html_element_get_hidden (
-                               WEBKIT_DOM_HTML_ELEMENT (check1)) &&
-                       webkit_dom_html_input_element_get_checked (check1)));
+       if (check2) {
+               webkit_dom_html_input_element_set_disabled (
+                       WEBKIT_DOM_HTML_INPUT_ELEMENT (check2),
+                       (webkit_dom_html_element_get_hidden (
+                                       WEBKIT_DOM_HTML_ELEMENT (check1)) &&
+                               webkit_dom_html_input_element_get_checked (check1)));
+       }
 }
 
 void
-module_itip_formatter_dom_utils_create_dom_bindings (WebKitDOMDocument *document,
-                                                    guint64 page_id,
-                                                    const gchar *part_id,
-                                                     GDBusConnection *connection)
+e_itip_formatter_dom_utils_create_dom_bindings (WebKitDOMDocument *document,
+                                               guint64 page_id,
+                                               const gchar *part_id,
+                                               GDBusConnection *connection)
 {
        WebKitDOMElement *el;
 
@@ -207,30 +209,31 @@ module_itip_formatter_dom_utils_create_dom_bindings (WebKitDOMDocument *document
 }
 
 void
-module_itip_formatter_dom_utils_show_button (WebKitDOMDocument *document,
-                                             const gchar *button_id)
+e_itip_formatter_dom_utils_show_button (WebKitDOMDocument *document,
+                                       const gchar *button_id)
 {
        WebKitDOMElement *button;
 
        button = webkit_dom_document_get_element_by_id (document, button_id);
-       webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (button), FALSE);
+       if (button)
+               webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (button), FALSE);
 }
 
 void
-module_itip_formatter_dom_utils_enable_button (WebKitDOMDocument *document,
-                                               const gchar *button_id,
-                                               gboolean enable)
+e_itip_formatter_dom_utils_enable_button (WebKitDOMDocument *document,
+                                         const gchar *button_id,
+                                         gboolean enable)
 {
        WebKitDOMElement *el;
 
        el = webkit_dom_document_get_element_by_id (document, button_id);
-       webkit_dom_html_button_element_set_disabled (
-               WEBKIT_DOM_HTML_BUTTON_ELEMENT (el), !enable);
+       if (el)
+               webkit_dom_html_button_element_set_disabled (WEBKIT_DOM_HTML_BUTTON_ELEMENT (el), !enable);
 }
 
 gboolean
-module_itip_formatter_dom_utils_input_is_checked (WebKitDOMDocument *document,
-                                                  const gchar *input_id)
+e_itip_formatter_dom_utils_input_is_checked (WebKitDOMDocument *document,
+                                            const gchar *input_id)
 {
        WebKitDOMElement *element;
 
@@ -244,9 +247,9 @@ module_itip_formatter_dom_utils_input_is_checked (WebKitDOMDocument *document,
 }
 
 void
-module_itip_formatter_dom_utils_input_set_checked (WebKitDOMDocument *document,
-                                                   const gchar *input_id,
-                                                   gboolean checked)
+e_itip_formatter_dom_utils_input_set_checked (WebKitDOMDocument *document,
+                                             const gchar *input_id,
+                                             gboolean checked)
 {
        WebKitDOMElement *element;
 
@@ -260,10 +263,10 @@ module_itip_formatter_dom_utils_input_set_checked (WebKitDOMDocument *document,
 }
 
 void
-module_itip_formatter_dom_utils_show_checkbox (WebKitDOMDocument *document,
-                                               const gchar *id,
-                                               gboolean show,
-                                              gboolean update_second)
+e_itip_formatter_dom_utils_show_checkbox (WebKitDOMDocument *document,
+                                         const gchar *id,
+                                         gboolean show,
+                                         gboolean update_second)
 {
        WebKitDOMElement *label;
        WebKitDOMElement *el;
@@ -293,84 +296,83 @@ module_itip_formatter_dom_utils_show_checkbox (WebKitDOMDocument *document,
 
        row_id = g_strconcat ("table_row_", id, NULL);
        el = webkit_dom_document_get_element_by_id (document, row_id);
-       webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
+       if (el)
+               webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
        g_free (row_id);
 }
 
 void
-module_itip_formatter_dom_utils_set_buttons_sensitive (WebKitDOMDocument *document,
-                                                       gboolean sensitive)
+e_itip_formatter_dom_utils_set_buttons_sensitive (WebKitDOMDocument *document,
+                                                 gboolean sensitive)
 {
        WebKitDOMElement *el, *cell;
 
-       el = webkit_dom_document_get_element_by_id (
-               document, CHECKBOX_UPDATE);
-       webkit_dom_html_input_element_set_disabled (
-               WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
-
-       el = webkit_dom_document_get_element_by_id (
-               document, CHECKBOX_RECUR);
-       webkit_dom_html_input_element_set_disabled (
-               WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
-
-       el = webkit_dom_document_get_element_by_id (
-               document, CHECKBOX_FREE_TIME);
-       webkit_dom_html_input_element_set_disabled (
-               WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
-
-       el = webkit_dom_document_get_element_by_id (
-               document, CHECKBOX_KEEP_ALARM);
-       webkit_dom_html_input_element_set_disabled (
-               WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
-
-       el = webkit_dom_document_get_element_by_id (
-               document, CHECKBOX_INHERIT_ALARM);
-       webkit_dom_html_input_element_set_disabled (
-               WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
-
-       el = webkit_dom_document_get_element_by_id (
-               document, CHECKBOX_RSVP);
-       webkit_dom_html_input_element_set_disabled (
-               WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
-
-       el = webkit_dom_document_get_element_by_id (
-               document, TEXTAREA_RSVP_COMMENT);
-       webkit_dom_html_text_area_element_set_disabled (
-               WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), !sensitive);
-
-       el = webkit_dom_document_get_element_by_id (
-               document, TABLE_ROW_BUTTONS);
+       el = webkit_dom_document_get_element_by_id (document, CHECKBOX_UPDATE);
+       if (el)
+               webkit_dom_html_input_element_set_disabled (WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+       el = webkit_dom_document_get_element_by_id (document, CHECKBOX_RECUR);
+       if (el)
+               webkit_dom_html_input_element_set_disabled (WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+       el = webkit_dom_document_get_element_by_id (document, CHECKBOX_FREE_TIME);
+       if (el)
+               webkit_dom_html_input_element_set_disabled (WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+       el = webkit_dom_document_get_element_by_id (document, CHECKBOX_KEEP_ALARM);
+       if (el)
+               webkit_dom_html_input_element_set_disabled (WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+       el = webkit_dom_document_get_element_by_id (document, CHECKBOX_INHERIT_ALARM);
+       if (el)
+               webkit_dom_html_input_element_set_disabled (WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+       el = webkit_dom_document_get_element_by_id (document, CHECKBOX_RSVP);
+       if (el)
+               webkit_dom_html_input_element_set_disabled (WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+       el = webkit_dom_document_get_element_by_id (document, TEXTAREA_RSVP_COMMENT);
+       if (el)
+               webkit_dom_html_text_area_element_set_disabled (WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), 
!sensitive);
+
+       el = webkit_dom_document_get_element_by_id (document, TABLE_ROW_BUTTONS);
+       if (!el)
+               return;
+
        cell = webkit_dom_element_get_first_element_child (el);
+       if (!cell)
+               return;
        do {
                WebKitDOMElement *btn;
                btn = webkit_dom_element_get_first_element_child (cell);
-               if (!webkit_dom_html_element_get_hidden (
-                       WEBKIT_DOM_HTML_ELEMENT (btn))) {
-                       webkit_dom_html_button_element_set_disabled (
-                               WEBKIT_DOM_HTML_BUTTON_ELEMENT (btn), !sensitive);
+               if (btn && !webkit_dom_html_element_get_hidden (WEBKIT_DOM_HTML_ELEMENT (btn))) {
+                       webkit_dom_html_button_element_set_disabled (WEBKIT_DOM_HTML_BUTTON_ELEMENT (btn), 
!sensitive);
                }
        } while ((cell = webkit_dom_element_get_next_element_sibling (cell)) != NULL);
 }
 
 void
-module_itip_formatter_dom_utils_set_area_text (WebKitDOMDocument *document,
-                                               const gchar *area_id,
-                                               const gchar *text)
+e_itip_formatter_dom_utils_set_area_text (WebKitDOMDocument *document,
+                                         const gchar *area_id,
+                                         const gchar *text)
 {
        WebKitDOMElement *row, *col;
 
        row = webkit_dom_document_get_element_by_id (document, area_id);
-       webkit_dom_html_element_set_hidden (
-               WEBKIT_DOM_HTML_ELEMENT (row), (g_strcmp0 (text, "") == 0));
+       if (!row)
+               return;
+
+       webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (row), (g_strcmp0 (text, "") == 0));
 
        col = webkit_dom_element_get_last_element_child (row);
-       webkit_dom_element_set_inner_html (col, text, NULL);
+       if (col)
+               webkit_dom_element_set_inner_html (col, text, NULL);
 }
 
 void
-module_itip_formatter_dom_utils_element_set_access_key (WebKitDOMDocument *document,
-                                                        const gchar *element_id,
-                                                        const gchar *access_key)
+e_itip_formatter_dom_utils_element_set_access_key (WebKitDOMDocument *document,
+                                                  const gchar *element_id,
+                                                  const gchar *access_key)
 {
        WebKitDOMElement *element;
 
@@ -384,8 +386,8 @@ module_itip_formatter_dom_utils_element_set_access_key (WebKitDOMDocument *docum
 }
 
 void
-module_itip_formatter_dom_utils_element_hide_child_nodes (WebKitDOMDocument *document,
-                                                          const gchar *element_id)
+e_itip_formatter_dom_utils_element_hide_child_nodes (WebKitDOMDocument *document,
+                                                    const gchar *element_id)
 {
        WebKitDOMElement *element, *cell, *button;
 
@@ -394,19 +396,20 @@ module_itip_formatter_dom_utils_element_hide_child_nodes (WebKitDOMDocument *doc
        if (!element)
                return;
 
-       element = webkit_dom_document_get_element_by_id (document, element_id);
        cell = webkit_dom_element_get_first_element_child (element);
+       if (!cell)
+               return;
        do {
                button = webkit_dom_element_get_first_element_child (cell);
-               webkit_dom_html_element_set_hidden (
-                       WEBKIT_DOM_HTML_ELEMENT (button), TRUE);
+               if (button)
+                       webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (button), TRUE);
        } while ((cell = webkit_dom_element_get_next_element_sibling (cell)) != NULL);
 }
 
 void
-module_itip_formatter_dom_utils_enable_select (WebKitDOMDocument *document,
-                                               const gchar *select_id,
-                                               gboolean enabled)
+e_itip_formatter_dom_utils_enable_select (WebKitDOMDocument *document,
+                                         const gchar *select_id,
+                                         gboolean enabled)
 {
        WebKitDOMElement *element;
 
@@ -420,8 +423,8 @@ module_itip_formatter_dom_utils_enable_select (WebKitDOMDocument *document,
 }
 
 gboolean
-module_itip_formatter_dom_utils_select_is_enabled (WebKitDOMDocument *document,
-                                                   const gchar *select_id)
+e_itip_formatter_dom_utils_select_is_enabled (WebKitDOMDocument *document,
+                                             const gchar *select_id)
 {
        WebKitDOMElement *element;
 
@@ -435,8 +438,8 @@ module_itip_formatter_dom_utils_select_is_enabled (WebKitDOMDocument *document,
 }
 
 gchar *
-module_itip_formatter_dom_utils_select_get_value (WebKitDOMDocument *document,
-                                                  const gchar *select_id)
+e_itip_formatter_dom_utils_select_get_value (WebKitDOMDocument *document,
+                                            const gchar *select_id)
 {
        WebKitDOMElement *element;
 
@@ -450,9 +453,9 @@ module_itip_formatter_dom_utils_select_get_value (WebKitDOMDocument *document,
 }
 
 void
-module_itip_formatter_dom_utils_select_set_selected (WebKitDOMDocument *document,
-                                                     const gchar *select_id,
-                                                     const gchar *option)
+e_itip_formatter_dom_utils_select_set_selected (WebKitDOMDocument *document,
+                                               const gchar *select_id,
+                                               const gchar *option)
 {
        WebKitDOMElement *element;
        gint length, ii;
@@ -487,10 +490,10 @@ module_itip_formatter_dom_utils_select_set_selected (WebKitDOMDocument *document
 }
 
 void
-module_itip_formatter_dom_utils_update_times (WebKitDOMDocument *document,
-                                              const gchar *element_id,
-                                              const gchar *header,
-                                              const gchar *label)
+e_itip_formatter_dom_utils_update_times (WebKitDOMDocument *document,
+                                        const gchar *element_id,
+                                        const gchar *header,
+                                        const gchar *label)
 {
        WebKitDOMElement *element, *col;
 
@@ -510,11 +513,11 @@ module_itip_formatter_dom_utils_update_times (WebKitDOMDocument *document,
 }
 
 void
-module_itip_formatter_dom_utils_append_info_item_row (WebKitDOMDocument *document,
-                                                      const gchar *table_id,
-                                                      const gchar *row_id,
-                                                      const gchar *icon_name,
-                                                      const gchar *message)
+e_itip_formatter_dom_utils_append_info_item_row (WebKitDOMDocument *document,
+                                               const gchar *table_id,
+                                               const gchar *row_id,
+                                               const gchar *icon_name,
+                                               const gchar *message)
 {
        WebKitDOMElement *table;
         WebKitDOMHTMLElement *cell, *row;
@@ -524,7 +527,6 @@ module_itip_formatter_dom_utils_append_info_item_row (WebKitDOMDocument *documen
        if (!table)
                return;
 
-       table = webkit_dom_document_get_element_by_id (document, table_id);
        row = webkit_dom_html_table_element_insert_row (
                WEBKIT_DOM_HTML_TABLE_ELEMENT (table), -1, NULL);
 
@@ -558,47 +560,50 @@ module_itip_formatter_dom_utils_append_info_item_row (WebKitDOMDocument *documen
 }
 
 void
-module_itip_formatter_dom_utils_enable_text_area (WebKitDOMDocument *document,
-                                                  const gchar *area_id,
-                                                  gboolean enable)
+e_itip_formatter_dom_utils_enable_text_area (WebKitDOMDocument *document,
+                                            const gchar *area_id,
+                                            gboolean enable)
 {
        WebKitDOMElement *el;
 
        el = webkit_dom_document_get_element_by_id (document, area_id);
-       webkit_dom_html_text_area_element_set_disabled (
-               WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), !enable);
+       if (el)
+               webkit_dom_html_text_area_element_set_disabled (WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), 
!enable);
 }
 
 void
-module_itip_formatter_dom_utils_text_area_set_value (WebKitDOMDocument *document,
-                                                     const gchar *area_id,
-                                                     const gchar *value)
+e_itip_formatter_dom_utils_text_area_set_value (WebKitDOMDocument *document,
+                                               const gchar *area_id,
+                                               const gchar *value)
 {
        WebKitDOMElement *el;
 
        el = webkit_dom_document_get_element_by_id (document, area_id);
-       webkit_dom_html_text_area_element_set_value (
-               WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), value);
+       if (el)
+               webkit_dom_html_text_area_element_set_value (WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), value);
 }
 
 gchar *
-module_itip_formatter_dom_utils_text_area_get_value (WebKitDOMDocument *document,
-                                                     const gchar *area_id)
+e_itip_formatter_dom_utils_text_area_get_value (WebKitDOMDocument *document,
+                                               const gchar *area_id)
 {
        WebKitDOMElement *el;
 
        el = webkit_dom_document_get_element_by_id (document, area_id);
+       if (!el)
+               return NULL;
+
        return webkit_dom_html_text_area_element_get_value (
                WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el));
 }
 
 void
-module_itip_formatter_dom_utils_rebuild_source_list (WebKitDOMDocument *document,
-                                                     const gchar *optgroup_id,
-                                                     const gchar *optgroup_label,
-                                                     const gchar *option_id,
-                                                     const gchar *option_label,
-                                                    gboolean writable)
+e_itip_formatter_dom_utils_rebuild_source_list (WebKitDOMDocument *document,
+                                               const gchar *optgroup_id,
+                                               const gchar *optgroup_label,
+                                               const gchar *option_id,
+                                               const gchar *option_label,
+                                               gboolean writable)
 {
        WebKitDOMElement *option;
        WebKitDOMElement *select;
diff --git a/src/modules/itip-formatter/web-extension/module-itip-formatter-dom-utils.h 
b/src/web-extensions/e-itip-formatter-dom-utils.h
similarity index 67%
rename from src/modules/itip-formatter/web-extension/module-itip-formatter-dom-utils.h
rename to src/web-extensions/e-itip-formatter-dom-utils.h
index 8fab80fa5a..2607ba32c2 100644
--- a/src/modules/itip-formatter/web-extension/module-itip-formatter-dom-utils.h
+++ b/src/web-extensions/e-itip-formatter-dom-utils.h
@@ -1,5 +1,5 @@
 /*
- * module-itip-formatter-dom-utils.h
+ * e-itip-formatter-dom-utils.h
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,8 +16,8 @@
  *
  */
 
-#ifndef MODULE_ITIP_FORMATTER_DOM_UTILS_H
-#define MODULE_ITIP_FORMATTER_DOM_UTILS_H
+#ifndef E_ITIP_FORMATTER_DOM_UTILS_H
+#define E_ITIP_FORMATTER_DOM_UTILS_H
 
 #include <webkitdom/webkitdom.h>
 
@@ -25,81 +25,81 @@
 
 G_BEGIN_DECLS
 
-void           module_itip_formatter_dom_utils_create_dom_bindings
+void           e_itip_formatter_dom_utils_create_dom_bindings
                                                (WebKitDOMDocument *document,
                                                 guint64 page_id,
                                                 const gchar *part_id,
                                                 GDBusConnection *connection);
-void           module_itip_formatter_dom_utils_show_button
+void           e_itip_formatter_dom_utils_show_button
                                                (WebKitDOMDocument *document,
                                                 const gchar *button_id);
-void           module_itip_formatter_dom_utils_enable_button
+void           e_itip_formatter_dom_utils_enable_button
                                                (WebKitDOMDocument *document,
                                                 const gchar *button_id,
                                                 gboolean enable);
-void           module_itip_formatter_dom_utils_input_set_checked
+void           e_itip_formatter_dom_utils_input_set_checked
                                                (WebKitDOMDocument *document,
                                                 const gchar *input_id,
                                                 gboolean checked);
-gboolean       module_itip_formatter_dom_utils_input_is_checked
+gboolean       e_itip_formatter_dom_utils_input_is_checked
                                                (WebKitDOMDocument *document,
                                                 const gchar *input_id);
-void           module_itip_formatter_dom_utils_show_checkbox
+void           e_itip_formatter_dom_utils_show_checkbox
                                                (WebKitDOMDocument *document,
                                                 const gchar *id,
                                                 gboolean show,
                                                 gboolean update_second);
-void           module_itip_formatter_dom_utils_set_buttons_sensitive
+void           e_itip_formatter_dom_utils_set_buttons_sensitive
                                                (WebKitDOMDocument *document,
                                                 gboolean sensitive);
-void           module_itip_formatter_dom_utils_set_area_text
+void           e_itip_formatter_dom_utils_set_area_text
                                                (WebKitDOMDocument *document,
                                                 const gchar *area_id,
                                                 const gchar *text);
-void           module_itip_formatter_dom_utils_element_set_access_key
+void           e_itip_formatter_dom_utils_element_set_access_key
                                                (WebKitDOMDocument *document,
                                                 const gchar *element_id,
                                                 const gchar *access_key);
-void           module_itip_formatter_dom_utils_element_hide_child_nodes
+void           e_itip_formatter_dom_utils_element_hide_child_nodes
                                                (WebKitDOMDocument *document,
                                                 const gchar *element_id);
-void           module_itip_formatter_dom_utils_enable_select
+void           e_itip_formatter_dom_utils_enable_select
                                                (WebKitDOMDocument *document,
                                                 const gchar *select_id,
                                                 gboolean enabled);
-gboolean       module_itip_formatter_dom_utils_select_is_enabled
+gboolean       e_itip_formatter_dom_utils_select_is_enabled
                                                (WebKitDOMDocument *document,
                                                 const gchar *select_id);
-gchar *                module_itip_formatter_dom_utils_select_get_value
+gchar *                e_itip_formatter_dom_utils_select_get_value
                                                (WebKitDOMDocument *document,
                                                 const gchar *select_id);
-void           module_itip_formatter_dom_utils_select_set_selected
+void           e_itip_formatter_dom_utils_select_set_selected
                                                (WebKitDOMDocument *document,
                                                 const gchar *select_id,
                                                 const gchar *option);
-void           module_itip_formatter_dom_utils_update_times
+void           e_itip_formatter_dom_utils_update_times
                                                (WebKitDOMDocument *document,
                                                 const gchar *element_id,
                                                 const gchar *header,
                                                 const gchar *label);
-void           module_itip_formatter_dom_utils_append_info_item_row
+void           e_itip_formatter_dom_utils_append_info_item_row
                                                (WebKitDOMDocument *document,
                                                 const gchar *table_id,
                                                 const gchar *row_id,
                                                 const gchar *icon_name,
                                                 const gchar *message);
-void           module_itip_formatter_dom_utils_enable_text_area
+void           e_itip_formatter_dom_utils_enable_text_area
                                                (WebKitDOMDocument *document,
                                                 const gchar *area_id,
                                                 gboolean enable);
-void           module_itip_formatter_dom_utils_text_area_set_value
+void           e_itip_formatter_dom_utils_text_area_set_value
                                                (WebKitDOMDocument *document,
                                                 const gchar *area_id,
                                                 const gchar *value);
-gchar *                module_itip_formatter_dom_utils_text_area_get_value
+gchar *                e_itip_formatter_dom_utils_text_area_get_value
                                                (WebKitDOMDocument *document,
                                                 const gchar *area_id);
-void           module_itip_formatter_dom_utils_rebuild_source_list
+void           e_itip_formatter_dom_utils_rebuild_source_list
                                                (WebKitDOMDocument *document,
                                                 const gchar *optgroup_id,
                                                 const gchar *optgroup_label,
@@ -108,4 +108,4 @@ void                module_itip_formatter_dom_utils_rebuild_source_list
                                                 gboolean writable);
 G_END_DECLS
 
-#endif /* MODULE_ITIP_FORMATTER_DOM_UTILS_H */
+#endif /* E_ITIP_FORMATTER_DOM_UTILS_H */
diff --git a/src/web-extensions/e-web-extension-main.c b/src/web-extensions/e-web-extension-main.c
index 28a25d40ad..cb09f246ee 100644
--- a/src/web-extensions/e-web-extension-main.c
+++ b/src/web-extensions/e-web-extension-main.c
@@ -20,24 +20,56 @@
 
 #include <camel/camel.h>
 
+#define E_UTIL_INCLUDE_WITHOUT_WEBKIT
+#include <e-util/e-util.h>
+#undef E_UTIL_INCLUDE_WITHOUT_WEBKIT
+
 #include "e-web-extension.h"
 #include "e-web-extension-names.h"
 
 static void
-bus_acquired_cb (GDBusConnection *connection,
-                 const gchar *name,
-                 EWebExtension *extension)
+connected_to_server_cb (GObject *source_object,
+                       GAsyncResult *result,
+                       gpointer user_data)
 {
+       EWebExtension *extension = user_data;
+       GDBusConnection *connection;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+
+       connection = e_web_extension_container_utils_connect_to_server_finish (result, &error);
+       if (!connection) {
+               g_warning ("%d %s: Failed to connect to the UI D-Bus server: %s", getpid (), G_STRFUNC,
+                       error ? error->message : "Unknown error");
+               g_clear_error (&error);
+               return;
+       }
+
        e_web_extension_dbus_register (extension, connection);
+       g_object_unref (connection);
+       g_object_unref (extension);
 }
 
 /* Forward declaration */
-G_MODULE_EXPORT void webkit_web_extension_initialize (WebKitWebExtension *wk_extension);
+G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data (WebKitWebExtension *wk_extension,
+                                                                    GVariant *user_data);
 
 G_MODULE_EXPORT void
-webkit_web_extension_initialize (WebKitWebExtension *wk_extension)
+webkit_web_extension_initialize_with_user_data (WebKitWebExtension *wk_extension,
+                                               GVariant *user_data)
 {
        EWebExtension *extension;
+       const gchar *guid = NULL, *server_address = NULL;
+
+       g_return_if_fail (user_data != NULL);
+
+       g_variant_get (user_data, "(&s&s)", &guid, &server_address);
+
+       if (!server_address) {
+               g_warning ("%d %s: The UI process didn't provide server address", getpid (), G_STRFUNC);
+               return;
+       }
 
        camel_debug_init ();
 
@@ -47,13 +79,5 @@ webkit_web_extension_initialize (WebKitWebExtension *wk_extension)
        extension = e_web_extension_get ();
        e_web_extension_initialize (extension, wk_extension);
 
-       g_bus_own_name (
-               G_BUS_TYPE_SESSION,
-               E_WEB_EXTENSION_SERVICE_NAME,
-               G_BUS_NAME_OWNER_FLAGS_NONE,
-               (GBusAcquiredCallback) bus_acquired_cb,
-               NULL, /* GBusNameAcquiredCallback */
-               NULL, /* GBusNameLostCallback */
-               g_object_ref (extension),
-               (GDestroyNotify) g_object_unref);
+       e_web_extension_container_utils_connect_to_server (server_address, NULL, connected_to_server_cb, 
g_object_ref (extension));
 }
diff --git a/src/web-extensions/e-web-extension-names.h b/src/web-extensions/e-web-extension-names.h
index eedf271e2b..96d178ba97 100644
--- a/src/web-extensions/e-web-extension-names.h
+++ b/src/web-extensions/e-web-extension-names.h
@@ -19,8 +19,7 @@
 #ifndef E_WEB_EXTENSION_NAMES_H
 #define E_WEB_EXTENSION_NAMES_H
 
-#define E_WEB_EXTENSION_SERVICE_NAME "org.gnome.Evolution.WebExtension"
-#define E_WEB_EXTENSION_OBJECT_PATH  "/org/gnome/Evolution/WebExtension"
-#define E_WEB_EXTENSION_INTERFACE    "org.gnome.Evolution.WebExtension"
+#define E_WEB_EXTENSION_OBJECT_PATH            "/org/gnome/Evolution/WebExtension"
+#define E_WEB_EXTENSION_INTERFACE              "org.gnome.Evolution.WebExtension"
 
 #endif /* E_WEB_EXTENSION_NAMES_H */
diff --git a/src/web-extensions/e-web-extension.c b/src/web-extensions/e-web-extension.c
index f18e73c37b..9d85388a13 100644
--- a/src/web-extensions/e-web-extension.c
+++ b/src/web-extensions/e-web-extension.c
@@ -29,6 +29,7 @@
 
 #include "e-web-extension.h"
 #include "e-dom-utils.h"
+#include "e-itip-formatter-dom-utils.h"
 #include "e-web-extension-names.h"
 
 #include <webkitdom/webkitdom.h>
@@ -41,6 +42,7 @@
 
 typedef struct _EWebPageData {
        WebKitWebPage *web_page; /* not referenced */
+       gint stamp;
        gboolean need_input;
        guint32 clipboard_flags;
 } EWebPageData;
@@ -53,12 +55,28 @@ struct _EWebExtensionPrivate {
 
        gboolean initialized;
 
-       GHashTable *pages; /* guint64 *webpage_id ~> EWebPageData * */
+       GSList *pages; /* EWebPageData * */
 };
 
+enum {
+       REGISTER_DBUS_CONNECTION,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
 static const char introspection_xml[] =
 "<node>"
 "  <interface name='" E_WEB_EXTENSION_INTERFACE "'>"
+"    <signal name='ExtensionObjectReady'>"
+"    </signal>"
+"    <method name='GetExtensionHandlesPages'>"
+"      <arg type='at' name='array' direction='out'/>"
+"    </method>"
+"    <signal name='ExtensionHandlesPage'>"
+"      <arg type='t' name='page_id' direction='out'/>"
+"      <arg type='i' name='stamp' direction='out'/>"
+"    </signal>"
 "    <method name='RegisterElementClicked'>"
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='s' name='element_class' direction='in'/>"
@@ -198,10 +216,169 @@ static const char introspection_xml[] =
 "      <arg type='t' name='page_id' direction='out'/>"
 "      <arg type='s' name='part_id' direction='out'/>"
 "    </signal>"
+"    <signal name='ItipRecurToggled'>"
+"      <arg type='t' name='page_id' direction='out'/>"
+"      <arg type='s' name='part_id' direction='out'/>"
+"    </signal>"
+"    <signal name='ItipSourceChanged'>"
+"      <arg type='t' name='page_id' direction='out'/>"
+"      <arg type='s' name='part_id' direction='out'/>"
+"    </signal>"
+"    <method name='ItipCreateDOMBindings'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"    </method>"
+"    <method name='ItipShowButton'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='button_id' direction='in'/>"
+"    </method>"
+"    <method name='ItipElementSetInnerHTML'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='element_id' direction='in'/>"
+"      <arg type='s' name='inner_html' direction='in'/>"
+"    </method>"
+"    <method name='ItipRemoveElement'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='element_id' direction='in'/>"
+"    </method>"
+"    <method name='ItipElementRemoveChildNodes'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='element_id' direction='in'/>"
+"    </method>"
+"    <method name='ItipEnableButton'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='button_id' direction='in'/>"
+"      <arg type='b' name='enable' direction='in'/>"
+"    </method>"
+"    <method name='ItipElementIsHidden'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='element_id' direction='in'/>"
+"      <arg type='b' name='is_hidden' direction='out'/>"
+"    </method>"
+"    <method name='ItipHideElement'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='element_id' direction='in'/>"
+"      <arg type='b' name='hide' direction='in'/>"
+"    </method>"
+"    <method name='ItipInputSetChecked'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='input_id' direction='in'/>"
+"      <arg type='b' name='checked' direction='in'/>"
+"    </method>"
+"    <method name='ItipInputIsChecked'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='input_id' direction='in'/>"
+"      <arg type='b' name='checked' direction='out'/>"
+"    </method>"
+"    <method name='ItipShowCheckbox'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='id' direction='in'/>"
+"      <arg type='b' name='show' direction='in'/>"
+"      <arg type='b' name='update_second' direction='in'/>"
+"    </method>"
+"    <method name='ItipSetButtonsSensitive'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='b' name='sensitive' direction='in'/>"
+"    </method>"
+"    <method name='ItipSetAreaText'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='id' direction='in'/>"
+"      <arg type='s' name='text' direction='in'/>"
+"    </method>"
+"    <method name='ItipElementSetAccessKey'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='element_id' direction='in'/>"
+"      <arg type='s' name='access_key' direction='in'/>"
+"    </method>"
+"    <method name='ItipElementHideChildNodes'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='element_id' direction='in'/>"
+"    </method>"
+"    <method name='ItipEnableSelect'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='select_id' direction='in'/>"
+"      <arg type='b' name='enable' direction='in'/>"
+"    </method>"
+"    <method name='ItipSelectIsEnabled'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='select_id' direction='in'/>"
+"      <arg type='b' name='enable' direction='out'/>"
+"    </method>"
+"    <method name='ItipSelectGetValue'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='select_id' direction='in'/>"
+"      <arg type='s' name='value' direction='out'/>"
+"    </method>"
+"    <method name='ItipSelectSetSelected'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='select_id' direction='in'/>"
+"      <arg type='s' name='option' direction='in'/>"
+"    </method>"
+"    <method name='ItipUpdateTimes'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='element_id' direction='in'/>"
+"      <arg type='s' name='header' direction='in'/>"
+"      <arg type='s' name='label' direction='in'/>"
+"    </method>"
+"    <method name='ItipAppendInfoItemRow'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='table_id' direction='in'/>"
+"      <arg type='s' name='row_id' direction='in'/>"
+"      <arg type='s' name='icon_name' direction='in'/>"
+"      <arg type='s' name='message' direction='in'/>"
+"    </method>"
+"    <method name='ItipEnableTextArea'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='area_id' direction='in'/>"
+"      <arg type='b' name='enable' direction='in'/>"
+"    </method>"
+"    <method name='ItipTextAreaSetValue'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='area_id' direction='in'/>"
+"      <arg type='s' name='value' direction='in'/>"
+"    </method>"
+"    <method name='ItipTextAreaGetValue'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='area_id' direction='in'/>"
+"      <arg type='s' name='value' direction='out'/>"
+"    </method>"
+"    <method name='ItipRebuildSourceList'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='s' name='part_id' direction='in'/>"
+"      <arg type='s' name='optgroup_id' direction='in'/>"
+"      <arg type='s' name='optgroup_label' direction='in'/>"
+"      <arg type='s' name='option_id' direction='in'/>"
+"      <arg type='s' name='option_label' direction='in'/>"
+"      <arg type='b' name='writable' direction='in'/>"
+"    </method>"
 "  </interface>"
 "</node>";
 
-G_DEFINE_TYPE (EWebExtension, e_web_extension, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_CODE (EWebExtension, e_web_extension, G_TYPE_OBJECT,
+       G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL))
 
 static WebKitWebPage *
 get_webkit_web_page_or_return_dbus_error (GDBusMethodInvocation *invocation,
@@ -217,6 +394,61 @@ get_webkit_web_page_or_return_dbus_error (GDBusMethodInvocation *invocation,
        return web_page;
 }
 
+static WebKitDOMDocument *
+get_webkit_document_or_return_dbus_error (GDBusMethodInvocation *invocation,
+                                          WebKitWebExtension *web_extension,
+                                          guint64 page_id)
+{
+       WebKitDOMDocument *document;
+       WebKitWebPage *web_page;
+
+       web_page = webkit_web_extension_get_page (web_extension, page_id);
+       if (!web_page) {
+               g_dbus_method_invocation_return_error (
+                       invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                       "Invalid page ID: %" G_GUINT64_FORMAT, page_id);
+               return NULL;
+       }
+
+       document = webkit_web_page_get_dom_document (web_page);
+       if (!document) {
+               g_dbus_method_invocation_return_error (
+                       invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                       "No document for page ID: %" G_GUINT64_FORMAT, page_id);
+               return NULL;
+       }
+
+       return document;
+}
+
+static WebKitDOMDocument *
+find_webkit_document_for_partid_or_return_dbus_error (GDBusMethodInvocation *invocation,
+                                                     WebKitDOMDocument *owner,
+                                                     const gchar *part_id)
+{
+       WebKitDOMElement *element;
+
+       g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
+       g_return_val_if_fail (WEBKIT_DOM_IS_DOCUMENT (owner), NULL);
+       g_return_val_if_fail (part_id && *part_id, NULL);
+
+       element = e_dom_utils_find_element_by_id (owner, part_id);
+       if (element && WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (element)) {
+               WebKitDOMDocument *document = webkit_dom_html_iframe_element_get_content_document 
(WEBKIT_DOM_HTML_IFRAME_ELEMENT (element));
+               return document;
+       }
+
+       if (element)
+               g_dbus_method_invocation_return_error (
+                       invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                       "Part ID '%s' is not IFRAME, but %s", part_id, G_OBJECT_TYPE_NAME (element));
+       else
+               g_dbus_method_invocation_return_error (
+                       invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                       "Part ID '%s' not found", part_id);
+       return NULL;
+}
+
 static void
 element_clicked_cb (WebKitDOMElement *element,
                    WebKitDOMEvent *event,
@@ -394,6 +626,22 @@ e_web_extension_find_page_id_from_document (WebKitDOMDocument *document)
        return 0;
 }
 
+static EWebPageData *
+e_web_extension_get_page_data (EWebExtension *extension,
+                              guint64 page_id)
+{
+       GSList *link;
+
+       for (link = extension->priv->pages; link; link = g_slist_next (link)) {
+               EWebPageData *page_data = link->data;
+
+               if (page_data && webkit_web_page_get_id (page_data->web_page) == page_id)
+                       return page_data;
+       }
+
+       return NULL;
+}
+
 static void
 e_web_extension_set_need_input (EWebExtension *extension,
                                guint64 page_id,
@@ -405,7 +653,7 @@ e_web_extension_set_need_input (EWebExtension *extension,
        g_return_if_fail (E_IS_WEB_EXTENSION (extension));
        g_return_if_fail (page_id != 0);
 
-       page_data = g_hash_table_lookup (extension->priv->pages, &page_id);
+       page_data = e_web_extension_get_page_data (extension, page_id);
 
        if (!page_data || (!page_data->need_input) == (!need_input))
                return;
@@ -673,7 +921,26 @@ handle_method_call (GDBusConnection *connection,
        if (camel_debug ("webkit:preview"))
                printf ("EWebExtension - %s - %s\n", G_STRFUNC, method_name);
 
-       if (g_strcmp0 (method_name, "RegisterElementClicked") == 0) {
+       if (g_strcmp0 (method_name, "GetExtensionHandlesPages") == 0) {
+               GVariantBuilder *builder;
+               GSList *link;
+
+               builder = g_variant_builder_new (G_VARIANT_TYPE ("at"));
+
+               for (link = extension->priv->pages; link; link = g_slist_next (link)) {
+                       EWebPageData *page_data = link->data;
+
+                       if (page_data) {
+                               g_variant_builder_add (builder, "t", webkit_web_page_get_id 
(page_data->web_page));
+                               g_variant_builder_add (builder, "t", (guint64) page_data->stamp);
+                       }
+               }
+
+               g_dbus_method_invocation_return_value (invocation,
+                       g_variant_new ("(at)", builder));
+
+               g_variant_builder_unref (builder);
+       } else if (g_strcmp0 (method_name, "RegisterElementClicked") == 0) {
                const gchar *element_class = NULL;
 
                g_variant_get (parameters, "(t&s)", &page_id, &element_class);
@@ -1213,6 +1480,332 @@ handle_method_call (GDBusConnection *connection,
                        webkit_dom_element_set_class_name (WEBKIT_DOM_ELEMENT (body), body_class);
 
                g_dbus_method_invocation_return_value (invocation, NULL);
+       } else if (g_strcmp0 (method_name, "ItipCreateDOMBindings") == 0) {
+               const gchar *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s)", &page_id, &part_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_create_dom_bindings (document, page_id, part_id, 
connection);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipShowButton") == 0) {
+               const gchar *button_id, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &button_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_show_button (document, button_id);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipEnableButton") == 0) {
+               const gchar *button_id, *part_id = NULL;
+               gboolean enable;
+
+               g_variant_get (parameters, "(t&s&sb)", &page_id, &part_id, &button_id, &enable);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_enable_button (document, button_id, enable);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipElementSetInnerHTML") == 0) {
+               const gchar *element_id, *inner_html, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s&s)", &page_id, &part_id, &element_id, &inner_html);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_dom_utils_element_set_inner_html (document, element_id, inner_html);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipRemoveElement") == 0) {
+               const gchar *element_id, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &element_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_dom_utils_remove_element (document, element_id);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipElementRemoveChildNodes") == 0) {
+               const gchar *element_id, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &element_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_dom_utils_element_remove_child_nodes (document, element_id);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipHideElement") == 0) {
+               const gchar *element_id, *part_id = NULL;
+               gboolean hide;
+
+               g_variant_get (parameters, "(t&s&sb)", &page_id, &part_id, &element_id, &hide);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_dom_utils_hide_element (document, element_id, hide);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipElementIsHidden") == 0) {
+               const gchar *element_id, *part_id = NULL;
+               gboolean hidden;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &element_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       hidden = e_dom_utils_element_is_hidden (document, element_id);
+                       g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", hidden));
+               }
+       } else if (g_strcmp0 (method_name, "ItipInputSetChecked") == 0) {
+               const gchar *input_id, *part_id = NULL;
+               gboolean checked;
+
+               g_variant_get (parameters, "(t&s&sb)", &page_id, &part_id, &input_id, &checked);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_input_set_checked (document, input_id, checked);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipInputIsChecked") == 0) {
+               const gchar *input_id, *part_id = NULL;
+               gboolean checked;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &input_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       checked = e_itip_formatter_dom_utils_input_is_checked (document, input_id);
+                       g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", checked));
+               }
+       } else if (g_strcmp0 (method_name, "ItipShowCheckbox") == 0) {
+               const gchar *id, *part_id = NULL;
+               gboolean show, update_second;
+
+               g_variant_get (parameters, "(t&s&sbb)", &page_id, &part_id, &id, &show, &update_second);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_show_checkbox (document, id, show, update_second);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipSetButtonsSensitive") == 0) {
+               const gchar *part_id = NULL;
+               gboolean sensitive;
+
+               g_variant_get (parameters, "(t&sb)", &page_id, &part_id, &sensitive);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_set_buttons_sensitive (document, sensitive);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipSetAreaText") == 0) {
+               const gchar *id, *text, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s&s)", &page_id, &part_id, &id, &text);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_set_area_text (document, id, text);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipElementSetAccessKey") == 0) {
+               const gchar *element_id, *access_key, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s&s)", &page_id, &part_id, &element_id, &access_key);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_element_set_access_key (document, element_id, access_key);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipElementHideChildNodes") == 0) {
+               const gchar *element_id, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &element_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_element_hide_child_nodes (document, element_id);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipEnableSelect") == 0) {
+               const gchar *select_id, *part_id = NULL;
+               gboolean enable;
+
+               g_variant_get (parameters, "(t&s&sb)", &page_id, &part_id, &select_id, &enable);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_enable_select (document, select_id, enable);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipSelectIsEnabled") == 0) {
+               const gchar *select_id, *part_id = NULL;
+               gboolean enabled;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &select_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       enabled = e_itip_formatter_dom_utils_select_is_enabled (document, select_id);
+                       g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", enabled));
+               }
+       } else if (g_strcmp0 (method_name, "ItipSelectGetValue") == 0) {
+               const gchar *select_id, *part_id = NULL;
+               gchar *value;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &select_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       value = e_itip_formatter_dom_utils_select_get_value (document, select_id);
+                       g_dbus_method_invocation_return_value (invocation,
+                               g_variant_new (
+                                       "(@s)",
+                                       g_variant_new_take_string (value ? value : g_strdup (""))));
+               }
+       } else if (g_strcmp0 (method_name, "ItipSelectSetSelected") == 0) {
+               const gchar *select_id, *option, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s&s)", &page_id, &part_id, &select_id, &option);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_select_set_selected (document, select_id, option);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipUpdateTimes") == 0) {
+               const gchar *element_id, *header, *label, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s&s&s)", &page_id, &part_id, &element_id, &header, &label);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_update_times (document, element_id, header, label);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipAppendInfoItemRow") == 0) {
+               const gchar *table_id, *row_id, *icon_name, *message, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s&s&s&s)", &page_id, &part_id, &table_id, &row_id, 
&icon_name, &message);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_append_info_item_row (document, table_id, row_id, 
icon_name, message);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipEnableTextArea") == 0) {
+               const gchar *area_id, *part_id = NULL;
+               gboolean enable;
+
+               g_variant_get (parameters, "(t&s&sb)", &page_id, &part_id, &area_id, &enable);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_enable_text_area (document, area_id, enable);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipTextAreaSetValue") == 0) {
+               const gchar *area_id, *value, *part_id = NULL;
+
+               g_variant_get (parameters, "(t&s&s&s)", &page_id, &part_id, &area_id, &value);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_text_area_set_value (document, area_id, value);
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
+       } else if (g_strcmp0 (method_name, "ItipTextAreaGetValue") == 0) {
+               const gchar *area_id, *part_id = NULL;
+               gchar *value;
+
+               g_variant_get (parameters, "(t&s&s)", &page_id, &part_id, &area_id);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       value = e_itip_formatter_dom_utils_text_area_get_value (document, area_id);
+                       g_dbus_method_invocation_return_value (invocation,
+                               g_variant_new (
+                                       "(@s)",
+                                       g_variant_new_take_string (value ? value : g_strdup (""))));
+               }
+       } else if (g_strcmp0 (method_name, "ItipRebuildSourceList") == 0) {
+               const gchar *optgroup_id, *optgroup_label, *option_id, *option_label, *part_id = NULL;
+               gboolean writable;
+
+               g_variant_get (parameters,"(t&s&s&s&s&sb)", &page_id, &part_id, &optgroup_id, 
&optgroup_label, &option_id, &option_label, &writable);
+
+               document = get_webkit_document_or_return_dbus_error (invocation, web_extension, page_id);
+               if (document)
+                       document = find_webkit_document_for_partid_or_return_dbus_error (invocation, 
document, part_id);
+               if (document) {
+                       e_itip_formatter_dom_utils_rebuild_source_list (
+                               document,
+                               optgroup_id,
+                               optgroup_label,
+                               option_id,
+                               option_label,
+                               writable);
+
+                       g_dbus_method_invocation_return_value (invocation, NULL);
+               }
        }
 }
 
@@ -1261,22 +1854,29 @@ web_page_gone_cb (gpointer user_data,
                   GObject *gone_web_page)
 {
        EWebExtension *extension = user_data;
-       GHashTableIter iter;
-       gpointer key, value;
+       GSList *link;
 
        g_return_if_fail (E_IS_WEB_EXTENSION (extension));
 
-       g_hash_table_iter_init (&iter, extension->priv->pages);
-       while (g_hash_table_iter_next (&iter, &key, &value)) {
-               EWebPageData *page_data = value;
+       for (link = extension->priv->pages; link; link = g_slist_next (link)) {
+               EWebPageData *page_data = link->data;
 
-               if (page_data->web_page == (gpointer) gone_web_page) {
-                       g_hash_table_remove (extension->priv->pages, key);
+               if (page_data && page_data->web_page == (gpointer) gone_web_page) {
+                       extension->priv->pages = g_slist_remove (extension->priv->pages, page_data);
+                       g_free (page_data);
                        break;
                }
        }
 }
 
+static void
+e_web_extension_constructed (GObject *object)
+{
+       G_OBJECT_CLASS (e_web_extension_parent_class)->constructed (object);
+
+       e_extensible_load_extensions (E_EXTENSIBLE (object));
+}
+
 static void
 e_web_extension_dispose (GObject *object)
 {
@@ -1287,29 +1887,17 @@ e_web_extension_dispose (GObject *object)
                        extension->priv->dbus_connection,
                        extension->priv->registration_id);
                extension->priv->registration_id = 0;
-               extension->priv->dbus_connection = NULL;
+               g_clear_object (&extension->priv->dbus_connection);
        }
 
-       g_hash_table_remove_all (extension->priv->pages);
+       g_slist_free_full (extension->priv->pages, g_free);
+       extension->priv->pages = NULL;
 
        g_clear_object (&extension->priv->wk_extension);
 
        G_OBJECT_CLASS (e_web_extension_parent_class)->dispose (object);
 }
 
-static void
-e_web_extension_finalize (GObject *object)
-{
-       EWebExtension *extension = E_WEB_EXTENSION (object);
-
-       if (extension->priv->pages) {
-               g_hash_table_destroy (extension->priv->pages);
-               extension->priv->pages = NULL;
-       }
-
-       G_OBJECT_CLASS (e_web_extension_parent_class)->finalize (object);
-}
-
 static void
 e_web_extension_class_init (EWebExtensionClass *class)
 {
@@ -1317,8 +1905,17 @@ e_web_extension_class_init (EWebExtensionClass *class)
 
        g_type_class_add_private (object_class, sizeof (EWebExtensionPrivate));
 
+       object_class->constructed = e_web_extension_constructed;
        object_class->dispose = e_web_extension_dispose;
-       object_class->finalize = e_web_extension_finalize;
+
+       signals[REGISTER_DBUS_CONNECTION] = g_signal_new (
+               "register-dbus-connection",
+               G_TYPE_FROM_CLASS (class),
+               G_SIGNAL_RUN_LAST,
+               0,
+               NULL, NULL,
+               NULL,
+               G_TYPE_NONE, 1, G_TYPE_DBUS_CONNECTION);
 }
 
 static void
@@ -1327,7 +1924,6 @@ e_web_extension_init (EWebExtension *extension)
        extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension, E_TYPE_WEB_EXTENSION, EWebExtensionPrivate);
 
        extension->priv->initialized = FALSE;
-       extension->priv->pages = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, g_free);
 }
 
 static gpointer
@@ -1424,7 +2020,7 @@ e_web_extension_set_clipboard_flags (EWebExtension *extension,
                                     WebKitDOMDocument *document,
                                     guint32 clipboard_flags)
 {
-       EWebPageData *page_data;
+       EWebPageData *page_data = NULL;
        guint64 page_id;
        GError *error = NULL;
 
@@ -1434,7 +2030,7 @@ e_web_extension_set_clipboard_flags (EWebExtension *extension,
        page_id = e_web_extension_find_page_id_from_document (document);
        g_return_if_fail (page_id != 0);
 
-       page_data = g_hash_table_lookup (extension->priv->pages, &page_id);
+       page_data = e_web_extension_get_page_data (extension, page_id);
 
        if (!page_data || page_data->clipboard_flags == clipboard_flags)
                return;
@@ -1474,25 +2070,93 @@ web_editor_selection_changed_cb (WebKitWebEditor *web_editor,
        e_web_extension_set_clipboard_flags (extension, document, clipboard_flags);
 }
 
+static void
+web_page_notify_uri_cb (GObject *object,
+                       GParamSpec *param,
+                       gpointer user_data)
+{
+       EWebExtension *extension = user_data;
+       WebKitWebPage *web_page;
+       GSList *link;
+       const gchar *uri;
+
+       g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+
+       web_page = WEBKIT_WEB_PAGE (object);
+       uri = webkit_web_page_get_uri (web_page);
+
+       for (link = extension->priv->pages; link; link = g_slist_next (link)) {
+               EWebPageData *page_data = link->data;
+
+               if (page_data && page_data->web_page == web_page) {
+                       gint new_stamp = 0;
+
+                       if (uri && *uri) {
+                               SoupURI *suri;
+
+                               suri = soup_uri_new (uri);
+                               if (suri) {
+                                       if (soup_uri_get_query (suri)) {
+                                               GHashTable *form;
+
+                                               form = soup_form_decode (soup_uri_get_query (suri));
+                                               if (form) {
+                                                       const gchar *evo_stamp;
+
+                                                       evo_stamp = g_hash_table_lookup (form, "evo-stamp");
+                                                       if (evo_stamp)
+                                                               new_stamp = (gint) g_ascii_strtoll 
(evo_stamp, NULL, 10);
+
+                                                       g_hash_table_destroy (form);
+                                               }
+                                       }
+
+                                       soup_uri_free (suri);
+                               }
+                       }
+
+                       if (extension->priv->dbus_connection) {
+                               GError *error = NULL;
+
+                               g_dbus_connection_emit_signal (
+                                       extension->priv->dbus_connection,
+                                       NULL,
+                                       E_WEB_EXTENSION_OBJECT_PATH,
+                                       E_WEB_EXTENSION_INTERFACE,
+                                       "ExtensionHandlesPage",
+                                       g_variant_new ("(ti)", webkit_web_page_get_id (web_page), new_stamp),
+                                       &error);
+
+                               if (error) {
+                                       g_warning ("Error emitting signal ExtensionHandlesPage: %s", 
error->message);
+                                       g_error_free (error);
+                               }
+                       }
+
+                       page_data->stamp = new_stamp;
+                       return;
+               }
+       }
+
+       g_warning ("%s: Cannot find web_page %p\n", G_STRFUNC, web_page);
+}
+
 static void
 web_page_created_cb (WebKitWebExtension *wk_extension,
                      WebKitWebPage *web_page,
                      EWebExtension *extension)
 {
        EWebPageData *page_data;
-       guint64 *ppage_id;
-
-       ppage_id = g_new (guint64, 1);
-       *ppage_id = webkit_web_page_get_id (web_page);
 
        page_data = g_new0 (EWebPageData, 1);
        page_data->web_page = web_page;
        page_data->need_input = FALSE;
        page_data->clipboard_flags = 0;
+       page_data->stamp = 0;
 
        e_web_extension_store_page_id_on_document (web_page);
 
-       g_hash_table_insert (extension->priv->pages, ppage_id, page_data);
+       extension->priv->pages = g_slist_prepend (extension->priv->pages, page_data);
 
        g_object_weak_ref (G_OBJECT (web_page), web_page_gone_cb, extension);
 
@@ -1506,6 +2170,11 @@ web_page_created_cb (WebKitWebExtension *wk_extension,
                G_CALLBACK (web_page_document_loaded_cb),
                extension, 0);
 
+       g_signal_connect_object (
+               web_page, "notify::uri",
+               G_CALLBACK (web_page_notify_uri_cb),
+               extension, 0);
+
        g_signal_connect_object (
                webkit_web_page_get_editor (web_page), "selection-changed",
                G_CALLBACK (web_editor_selection_changed_cb),
@@ -1558,10 +2227,39 @@ e_web_extension_dbus_register (EWebExtension *extension,
                        g_warning ("Failed to register object: %s\n", error->message);
                        g_error_free (error);
                } else {
-                       extension->priv->dbus_connection = connection;
-                       g_object_add_weak_pointer (
-                               G_OBJECT (connection),
-                               (gpointer *)&extension->priv->dbus_connection);
+                       extension->priv->dbus_connection = g_object_ref (connection);
+
+                       g_signal_emit (extension, signals[REGISTER_DBUS_CONNECTION], 0, connection);
+
+                       g_dbus_connection_emit_signal (
+                               extension->priv->dbus_connection,
+                               NULL,
+                               E_WEB_EXTENSION_OBJECT_PATH,
+                               E_WEB_EXTENSION_INTERFACE,
+                               "ExtensionObjectReady",
+                               NULL,
+                               &error);
+
+                       if (error) {
+                               g_warning ("Error emitting signal ExtensionObjectReady: %s", error->message);
+                               g_error_free (error);
+                       }
                }
        }
 }
+
+WebKitWebExtension *
+e_web_extension_get_webkit_extension (EWebExtension *extension)
+{
+       g_return_val_if_fail (E_IS_WEB_EXTENSION (extension), NULL);
+
+       return extension->priv->wk_extension;
+}
+
+GDBusConnection *
+e_web_extension_get_dbus_connection (EWebExtension *extension)
+{
+       g_return_val_if_fail (E_IS_WEB_EXTENSION (extension), NULL);
+
+       return extension->priv->dbus_connection;
+}
diff --git a/src/web-extensions/e-web-extension.h b/src/web-extensions/e-web-extension.h
index a1f5837f92..834b63c7fd 100644
--- a/src/web-extensions/e-web-extension.h
+++ b/src/web-extensions/e-web-extension.h
@@ -19,8 +19,9 @@
 #ifndef E_WEB_EXTENSION_H
 #define E_WEB_EXTENSION_H
 
-#include <webkit2/webkit-web-extension.h>
 #include <glib-object.h>
+#include <gio/gio.h>
+#include <webkit2/webkit-web-extension.h>
 
 /* Standard GObject macros */
 #define E_TYPE_WEB_EXTENSION \
@@ -66,7 +67,12 @@ void         e_web_extension_initialize      (EWebExtension *extension,
 
 void           e_web_extension_dbus_register   (EWebExtension *extension,
                                                 GDBusConnection *connection);
-
+WebKitWebExtension *
+               e_web_extension_get_webkit_extension
+                                               (EWebExtension *extension);
+GDBusConnection *
+               e_web_extension_get_dbus_connection
+                                               (EWebExtension *extension);
 G_END_DECLS
 
 #endif /* E_WEB_EXTENSION_H */


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