Attempt to start dbus server from ui.
authorDaniel Carl <danielcarl@gmx.de>
Sat, 22 Oct 2016 21:30:24 +0000 (23:30 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Sat, 28 Jan 2017 00:17:16 +0000 (01:17 +0100)
Makefile
README.md
src/ext-proxy.c
src/ext-proxy.h
src/main.c
src/main.h
src/webextension/ext-main.c

index 9cb1bf0..a554a39 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,10 +4,11 @@ all: vimb
 
 options:
        @echo "vimb build options:"
-       @echo "LIBS    = $(LIBS)"
-       @echo "CFLAGS  = $(CFLAGS)"
-       @echo "LDFLAGS = $(LDFLAGS)"
-       @echo "CC      = $(CC)"
+       @echo "LIBS      = $(LIBS)"
+       @echo "CFLAGS    = $(CFLAGS)"
+       @echo "LDFLAGS   = $(LDFLAGS)"
+       @echo "EXTCFLAGS = $(EXTCFLAGS)"
+       @echo "CC        = $(CC)"
 
 vimb: $(SUBDIRS:%=%.subdir-all)
 
index 087a139..3b4d73f 100644 (file)
--- a/README.md
+++ b/README.md
@@ -85,6 +85,7 @@ project directory.
           this is now available with the `RUNPREFIX` option for the make
   - [x] establish communication channel between the vimb instance and the now
         required webextension (dbus)
+    - [ ] use propper authorization for dbus peers
 2. migrate as many of the features of the webkit1 vimb
   - [x] starting with custom config file `--config,-c` option
   - [ ] running multiple ex-commands during startup `--cmd,-C` options
index 0fe07b8..2e7fb5b 100644 (file)
 #include "main.h"
 #include "webextension/ext-main.h"
 
+static gboolean on_authorize_authenticated_peer(GDBusAuthObserver *observer,
+        GIOStream *stream, GCredentials *credentials, gpointer data);
+static gboolean on_new_connection(GDBusServer *server,
+        GDBusConnection *connection, gpointer data);
+static void on_proxy_created (GDBusProxy *proxy, GAsyncResult *result,
+        gpointer data);
 static void dbus_call(Client *c, const char *method, GVariant *param,
         GAsyncReadyCallback callback);
 static void on_editable_change_focus(GDBusConnection *connection,
         const char *sender_name, const char *object_path,
         const char *interface_name, const char *signal_name,
         GVariant *parameters, gpointer data);
-static void on_name_appeared(GDBusConnection *connection, const char *name,
-        const char *owner, gpointer data);
-static void on_proxy_created(GDBusProxy *new_proxy, GAsyncResult *result,
-        gpointer data);
 static void on_web_extension_page_created(GDBusConnection *connection,
         const char *sender_name, const char *object_path,
         const char *interface_name, const char *signal_name,
@@ -43,34 +45,125 @@ static void on_web_extension_page_created(GDBusConnection *connection,
  * vimb may hold multiple clients which may use more than one webprocess and
  * therefore multiple webextension instances. */
 extern struct Vimb vb;
+static GDBusServer *dbusserver;
 
 
 /**
- * Request the web extension to focus first editable element.
- * Returns whether an focusable element was found or not.
+ * Initialize the dbus proxy by watching for appearing dbus name.
  */
-void ext_proxy_focus_input(Client *c)
+const char *ext_proxy_init(void)
 {
-    dbus_call(c, "FocusInput", NULL, NULL);
+    char *address, *guid;
+    GDBusAuthObserver *observer;
+    GError *error = NULL;
+
+    address  = g_strdup_printf("unix:tmpdir=%s", g_get_tmp_dir());
+    guid     = g_dbus_generate_guid();
+    observer = g_dbus_auth_observer_new();
+
+    g_signal_connect(observer, "authorize-authenticated-peer",
+            G_CALLBACK(on_authorize_authenticated_peer), NULL);
+
+    /* Use sync call because server must be starte before the web extension
+     * attempt to connect */
+    dbusserver = g_dbus_server_new_sync(address, G_DBUS_SERVER_FLAGS_NONE,
+            guid, observer, NULL, &error);
+
+    if (error) {
+        g_warning("Failed to start web extension server on %s: %s", address, error->message);
+        g_error_free(error);
+        goto out;
+    }
+
+    g_signal_connect(dbusserver, "new-connection", G_CALLBACK(on_new_connection), NULL);
+    g_dbus_server_start(dbusserver);
+
+out:
+    g_free(address);
+    g_free(guid);
+    g_object_unref(observer);
+
+    return g_dbus_server_get_client_address(dbusserver);
 }
 
-/**
- * Initialize the dbus proxy by watching for appearing dbus name.
- */
-void ext_proxy_init(const char *id)
+/* TODO move this to a lib or somthing that can be used from ui and web
+ * process together */
+static gboolean on_authorize_authenticated_peer(GDBusAuthObserver *observer,
+        GIOStream *stream, GCredentials *credentials, gpointer data)
 {
-    char *service_name;
-
-    service_name = g_strdup_printf("%s-%s", VB_WEBEXTENSION_SERVICE_NAME, id);
-    g_bus_watch_name(
-            G_BUS_TYPE_SESSION,
-            service_name,
-            G_BUS_NAME_WATCHER_FLAGS_NONE,
-            (GBusNameAppearedCallback)on_name_appeared,
+    static GCredentials *own_credentials = NULL;
+    GError *error = NULL;
+
+    if (!own_credentials) {
+        own_credentials = g_credentials_new();
+    }
+
+    if (credentials && g_credentials_is_same_user(credentials, own_credentials, &error)) {
+        return TRUE;
+    }
+
+    if (error) {
+        g_warning("Failed to authorize web extension connection: %s", error->message);
+        g_error_free(error);
+    }
+
+    return FALSE;
+}
+
+static gboolean on_new_connection(GDBusServer *server,
+        GDBusConnection *connection, gpointer data)
+{
+    /* Create dbus proxy. */
+    g_return_val_if_fail(G_IS_DBUS_CONNECTION(connection), FALSE);
+
+    /*g_signal_connect(connection, "closed", G_CALLBACK(connection_closed_cb), NULL);*/
+
+    g_dbus_proxy_new(connection,
+            G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+            NULL,
             NULL,
+            VB_WEBEXTENSION_OBJECT_PATH,
+            VB_WEBEXTENSION_INTERFACE,
             NULL,
+            (GAsyncReadyCallback)on_proxy_created,
             NULL);
-    g_free(service_name);
+
+    return TRUE;
+}
+
+static void on_proxy_created(GDBusProxy *new_proxy, GAsyncResult *result,
+        gpointer data)
+{
+    GError *error = NULL;
+    GDBusProxy *proxy;
+    GDBusConnection *connection;
+
+    proxy = g_dbus_proxy_new_finish(result, &error);
+    if (!proxy) {
+        if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+            g_warning("Error creating web extension proxy: %s", error->message);
+        }
+        g_error_free(error);
+
+        /* TODO cancel the dbus connection - use cancelable */
+        return;
+    }
+
+    connection = g_dbus_proxy_get_connection(proxy);
+    g_dbus_connection_signal_subscribe(connection, NULL,
+            VB_WEBEXTENSION_INTERFACE, "PageCreated",
+            VB_WEBEXTENSION_OBJECT_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
+            (GDBusSignalCallback)on_web_extension_page_created, proxy,
+            NULL);
+}
+
+/**
+ * Request the web extension to focus first editable element.
+ * Returns whether an focusable element was found or not.
+ */
+void ext_proxy_focus_input(Client *c)
+{
+    dbus_call(c, "FocusInput", NULL, NULL);
 }
 
 /**
@@ -90,6 +183,7 @@ static void dbus_call(Client *c, const char *method, GVariant *param,
     /* TODO add function to queue calls until the proxy connection is
      * established */
     if (!c->dbusproxy) {
+        g_message("dbus_call without proxy: %s", method);
         return;
     }
     g_dbus_proxy_call(c->dbusproxy, method, param, G_DBUS_CALL_FLAGS_NONE, -1, NULL, callback, c);
@@ -116,53 +210,6 @@ static void on_editable_change_focus(GDBusConnection *connection,
     /* TODO allo strict-focus to ignore focus event for initial set focus */
 }
 
-/**
- * Called when the name of the webextension appeared on the dbus session bus.
- */
-static void on_name_appeared(GDBusConnection *connection, const char *name,
-        const char *owner, gpointer data)
-{
-    int flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START
-        | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
-        | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
-
-    /* Create the proxy to communicate over dbus. */
-    g_dbus_proxy_new(connection, flags, NULL, name,
-            VB_WEBEXTENSION_OBJECT_PATH, VB_WEBEXTENSION_INTERFACE, NULL,
-            (GAsyncReadyCallback)on_proxy_created, NULL);
-}
-
-/**
- * Callback called when the dbus proxy is created.
- */
-static void on_proxy_created(GDBusProxy *new_proxy, GAsyncResult *result, gpointer data)
-{
-    GDBusConnection *connection;
-    GDBusProxy *proxy;
-    GError *error = NULL;
-
-    proxy      = g_dbus_proxy_new_finish(result, &error);
-    connection = g_dbus_proxy_get_connection(proxy);
-
-    if (!proxy) {
-        g_warning("Error creating web extension proxy: %s", error->message);
-        g_error_free(error);
-        return;
-    }
-    g_dbus_proxy_set_default_timeout(proxy, 100);
-    g_dbus_connection_signal_subscribe(
-            connection,
-            NULL,
-            VB_WEBEXTENSION_INTERFACE,
-            "PageCreated",
-            VB_WEBEXTENSION_OBJECT_PATH,
-            NULL,
-            G_DBUS_SIGNAL_FLAGS_NONE,
-            (GDBusSignalCallback)on_web_extension_page_created,
-            proxy,
-            NULL);
-}
-
 /**
  * Listen to the VerticalScroll signal of the webextension and set the scroll
  * percent value on the client to update the statusbar.
@@ -200,7 +247,7 @@ static void on_web_extension_page_created(GDBusConnection *connection,
 
     if (p) {
         /* Set the dbus proxy on the right client based on page id. */
-        p->dbusproxy = data;
+        p->dbusproxy = (GDBusProxy*)data;
 
         g_dbus_connection_signal_subscribe(connection, NULL,
                 VB_WEBEXTENSION_INTERFACE, "VerticalScroll",
index 3d6ae14..8258df9 100644 (file)
@@ -22,8 +22,8 @@
 
 #include "main.h"
 
+const char *ext_proxy_init(void);
 void ext_proxy_focus_input(Client *c);
-void ext_proxy_init(const char *id);
 void ext_proxy_set_header(Client *c, const char *headers);
 
 #endif /* end of include guard: _EXT_PROXY_H */
index d3588d7..f7187ce 100644 (file)
@@ -754,20 +754,15 @@ static void on_webctx_download_started(WebKitWebContext *webctx,
  */
 static void on_webctx_init_web_extension(WebKitWebContext *webctx, gpointer data)
 {
-    char *name;
-    static guint ext_count = 0;
+    const char *name;
     GVariant *vdata;
 
     /* Setup the extension directory. */
     webkit_web_context_set_web_extensions_directory(webctx, EXTPREFIX);
 
-    name = g_strdup_printf("%u-%u", getpid(), ++ext_count);
-    ext_proxy_init(name);
-
-    vdata = g_variant_new("(s)", name);
+    name  = ext_proxy_init();
+    vdata = g_variant_new("(ms)", name);
     webkit_web_context_set_web_extensions_initialization_user_data(webctx, vdata);
-
-    g_free(name);
 }
 
 /**
index 9b93c6a..212cd38 100644 (file)
@@ -219,6 +219,7 @@ struct Client {
     guint64             page_id;                /* page id of the webview */
     GtkTextBuffer       *buffer;
     GDBusProxy          *dbusproxy;
+    GDBusServer         *dbusserver;
     struct {
         /* TODO split in global setting definitions and set values on a per
          * client base. */
index a3a8a83..cfc8e01 100644 (file)
 #include "ext-dom.h"
 #include "ext-util.h"
 
-static void add_onload_event_observers(WebKitDOMDocument *doc);
-static void dbus_emit_signal(const char *name, GVariant *data);
+static gboolean on_authorize_authenticated_peer(GDBusAuthObserver *observer,
+        GIOStream *stream, GCredentials *credentials, gpointer extension);
+static void on_dbus_connection_created(GObject *source_object,
+        GAsyncResult *result, gpointer data);
+static void add_onload_event_observers(WebKitDOMDocument *doc,
+        WebKitWebExtension *extension);
+static void emit_page_created(GDBusConnection *connection, guint64 pageid);
+static void emit_page_created_pending(GDBusConnection *connection);
+static void queue_page_created_signal(guint64 pageid);
+static void dbus_emit_signal(const char *name, WebKitWebExtension* extension,
+        GVariant *data);
 static void dbus_handle_method_call(GDBusConnection *conn, const char *sender,
         const char *object_path, const char *interface_name, const char *method,
         GVariant *parameters, GDBusMethodInvocation *invocation, gpointer data);
-static gboolean dbus_own_name_sync(GDBusConnection *connection, const char *name,
-        GBusNameOwnerFlags flags);
-static void on_dbus_name_acquire(GDBusConnection *connection, const char *name, gpointer data);
-static void on_editable_change_focus(WebKitDOMEventTarget *target, WebKitDOMEvent *event);
-static void on_page_created(WebKitWebExtension *ext, WebKitWebPage *page, gpointer data);
-static void on_web_page_document_loaded(WebKitWebPage *page, gpointer data);
-static gboolean on_web_page_send_request(WebKitWebPage *page, WebKitURIRequest *request,
-        WebKitURIResponse *response, gpointer data);
+static void on_editable_change_focus(WebKitDOMEventTarget *target,
+        WebKitDOMEvent *event, WebKitWebExtension *extension);
+static void on_page_created(WebKitWebExtension *ext, WebKitWebPage *webpage, gpointer data);
+static void on_web_page_document_loaded(WebKitWebPage *webpage, gpointer extension);
+static gboolean on_web_page_send_request(WebKitWebPage *webpage, WebKitURIRequest *request,
+        WebKitURIResponse *response, gpointer extension);
 
 static const GDBusInterfaceVTable interface_vtable = {
     dbus_handle_method_call,
@@ -73,6 +80,7 @@ struct Ext {
     GHashTable          *headers;
     GHashTable          *documents;
     gboolean            input_focus;
+    GArray              *page_created_signals;
 };
 struct Ext ext = {0};
 
@@ -83,32 +91,79 @@ struct Ext ext = {0};
 G_MODULE_EXPORT
 void webkit_web_extension_initialize_with_user_data(WebKitWebExtension *extension, GVariant *data)
 {
-    char *extid, *service_name;
-    g_variant_get(data, "(s)", &extid);
+    char *server_address;
+    GDBusAuthObserver *observer;
 
-    /* Get the DBus connection for the bus type. It would be a better to use
-     * the async g_bus_own_name for this, but this leads to cases where pages
-     * are created and documents are loaded before we get a name and are able
-     * to call to the UI process. */
-    ext.connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
+    g_variant_get(data, "(ms)", &server_address);
+    if (!server_address) {
+        g_warning("UI process did not start D-Bus server");
+        return;
+    }
+
+    g_signal_connect(extension, "page-created", G_CALLBACK(on_page_created), NULL);
+
+    observer = g_dbus_auth_observer_new();
+    g_signal_connect(observer, "authorize-authenticated-peer",
+            G_CALLBACK(on_authorize_authenticated_peer), extension);
+
+    g_dbus_connection_new_for_address(server_address,
+            G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, observer, NULL,
+            (GAsyncReadyCallback)on_dbus_connection_created, extension);
+    g_object_unref(observer);
+}
+
+static gboolean on_authorize_authenticated_peer(GDBusAuthObserver *observer,
+        GIOStream *stream, GCredentials *credentials, gpointer extension)
+{
+    /* FIXME require authentication logic */
+    return TRUE;
+}
 
-    service_name = g_strdup_printf("%s-%s", VB_WEBEXTENSION_SERVICE_NAME, extid);
+static void on_dbus_connection_created(GObject *source_object,
+        GAsyncResult *result, gpointer data)
+{
+    static GDBusNodeInfo *node_info = NULL;
+    GDBusConnection *connection;
+    GError *error = NULL;
 
-    /* Try to own name synchronously. */
-    if (ext.connection && dbus_own_name_sync(ext.connection, service_name, G_BUS_NAME_OWNER_FLAGS_NONE)) {
-        on_dbus_name_acquire(ext.connection, service_name, extension);
+    if (!node_info) {
+        node_info = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
     }
 
-    g_free(service_name);
+    connection = g_dbus_connection_new_for_address_finish(result, &error);
+    if (error) {
+        g_warning("Failed to connect to UI process: %s", error->message);
+        g_error_free(error);
+        return;
+    }
 
-    g_signal_connect(extension, "page-created", G_CALLBACK(on_page_created), NULL);
+    /* register the webextension object */
+    ext.regid = g_dbus_connection_register_object(
+            connection,
+            VB_WEBEXTENSION_OBJECT_PATH,
+            node_info->interfaces[0],
+            &interface_vtable,
+            WEBKIT_WEB_EXTENSION(data),
+            NULL,
+            &error);
+
+    if (!ext.regid) {
+        g_warning("Failed to register web extension object: %s", error->message);
+        g_error_free(error);
+        g_object_unref(connection);
+        return;
+    }
+
+    emit_page_created_pending(connection);
+    ext.connection = connection;
 }
 
 /**
  * Add observers to doc event for given document and all the contained iframes
  * too.
  */
-static void add_onload_event_observers(WebKitDOMDocument *doc)
+static void add_onload_event_observers(WebKitDOMDocument *doc,
+        WebKitWebExtension *extension)
 {
     WebKitDOMEventTarget *target;
 
@@ -117,20 +172,72 @@ static void add_onload_event_observers(WebKitDOMDocument *doc)
     if (!g_hash_table_add(ext.documents, doc)) {
         return;
     }
-   
+
     /* We have to use default view instead of the document itself in case this
      * function is called with content document of an iframe. Else the event
      * observing does not work. */
-    target = WEBKIT_DOM_EVENT_TARGET(webkit_dom_document_get_default_view(doc)); 
+    target = WEBKIT_DOM_EVENT_TARGET(webkit_dom_document_get_default_view(doc));
 
     webkit_dom_event_target_add_event_listener(target, "focus",
-            G_CALLBACK(on_editable_change_focus), TRUE, NULL);
+            G_CALLBACK(on_editable_change_focus), TRUE, extension);
     webkit_dom_event_target_add_event_listener(target, "blur",
-            G_CALLBACK(on_editable_change_focus), TRUE, NULL);
+            G_CALLBACK(on_editable_change_focus), TRUE, extension);
     /* Check for focused editable elements also if they where focused before
      * the event observer where set up. */
     /* TODO this is not needed for strict-focus=on */
-    on_editable_change_focus(target, NULL);
+    on_editable_change_focus(target, NULL, extension);
+}
+
+/**
+ * Emit the page created signal that is used in the ui process to finish the
+ * dbus proxy connection.
+ */
+static void emit_page_created(GDBusConnection *connection, guint64 pageid)
+{
+    GError *error = NULL;
+
+    /* propagate the signal over dbus */
+    g_dbus_connection_emit_signal(G_DBUS_CONNECTION(connection), NULL,
+            VB_WEBEXTENSION_OBJECT_PATH, VB_WEBEXTENSION_INTERFACE,
+            "PageCreated", g_variant_new("(t)", pageid), &error);
+
+    if (error) {
+        g_warning("Failed to emit signal PageCreated: %s", error->message);
+        g_error_free(error);
+    }
+}
+
+/**
+ * Emit queued page created signals.
+ */
+static void emit_page_created_pending(GDBusConnection *connection)
+{
+    int i;
+    guint64 pageid;
+
+    if (!ext.page_created_signals) {
+        return;
+    }
+
+    for (i = 0; i < ext.page_created_signals->len; i++) {
+        pageid = g_array_index(ext.page_created_signals, guint64, i);
+        emit_page_created(connection, pageid);
+    }
+
+    g_array_free(ext.page_created_signals, TRUE);
+    ext.page_created_signals = NULL;
+}
+
+/**
+ * Write the page id of the created page to a queue to send them to the ui
+ * process when the dbus connection is established.
+ */
+static void queue_page_created_signal(guint64 pageid)
+{
+    if (!ext.page_created_signals) {
+        ext.page_created_signals = g_array_new(FALSE, FALSE, sizeof(guint64));
+    }
+    ext.page_created_signals = g_array_append_val(ext.page_created_signals, pageid);
 }
 
 /**
@@ -139,11 +246,11 @@ static void add_onload_event_observers(WebKitDOMDocument *doc)
  * @name:   Signal name to emit.
  * @data:   GVariant value used as value for the signal or NULL.
  */
-static void dbus_emit_signal(const char *name, GVariant *data)
+static void dbus_emit_signal(const char *name, WebKitWebExtension* extension,
+        GVariant *data)
 {
     GError *error = NULL;
 
-    /* Don't do anythings if the dbus connection was not established. */
     if (!ext.connection) {
         return;
     }
@@ -152,8 +259,6 @@ static void dbus_emit_signal(const char *name, GVariant *data)
     g_dbus_connection_emit_signal(ext.connection, NULL,
             VB_WEBEXTENSION_OBJECT_PATH, VB_WEBEXTENSION_INTERFACE, name,
             data, &error);
-
-    /* check for error */
     if (error) {
         g_warning("Failed to emit signal '%s': %s", name, error->message);
         g_error_free(error);
@@ -165,7 +270,7 @@ static void dbus_emit_signal(const char *name, GVariant *data)
  */
 static void dbus_handle_method_call(GDBusConnection *conn, const char *sender,
         const char *object_path, const char *interface_name, const char *method,
-        GVariant *parameters, GDBusMethodInvocation *invocation, gpointer data)
+        GVariant *parameters, GDBusMethodInvocation *invocation, gpointer extension)
 {
     char *value;
 
@@ -184,84 +289,13 @@ static void dbus_handle_method_call(GDBusConnection *conn, const char *sender,
     }
 }
 
-/**
- * The synchronous and blocking pendent to the g_bus_own_name().
- *
- * @bus_type: The type of bus to own a name on.
- * @name:     The well-known name to own.
- * @flags:    A set of flags from the #GBusNameOwnerFlags enumeration.
- */
-static gboolean dbus_own_name_sync(GDBusConnection *connection, const char *name,
-        GBusNameOwnerFlags flags)
-{
-    GError *error = NULL;
-    guint32 request_name_reply = 0;
-    GVariant *result;
-
-    result = g_dbus_connection_call_sync(
-            connection,
-            "org.freedesktop.DBus",
-            "/org/freedesktop/DBus",
-            "org.freedesktop.DBus",
-            "RequestName",
-            g_variant_new("(su)", name, flags),
-            G_VARIANT_TYPE("(u)"),
-            G_DBUS_CALL_FLAGS_NONE,
-            -1,
-            NULL,
-            &error);
-
-    if (result) {
-        g_variant_get(result, "(u)", &request_name_reply);
-        g_variant_unref(result);
-
-        if (1 == request_name_reply) {
-            return TRUE;
-        }
-    } else {
-        g_warning("Failed to acquire DBus name: %s", error->message);
-        g_error_free(error);
-    }
-    return FALSE;
-}
-
-/**
- * Called when the dbus name is aquired and registers our object.
- */
-static void on_dbus_name_acquire(GDBusConnection *connection, const char *name, gpointer data)
-{
-    GError *error = NULL;
-    static GDBusNodeInfo *node_info = NULL;
-
-    g_return_if_fail(G_IS_DBUS_CONNECTION(connection));
-
-    if (!node_info) {
-        node_info = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
-    }
-
-    /* register the webextension object */
-    ext.connection = connection;
-    ext.regid      = g_dbus_connection_register_object(
-            connection,
-            VB_WEBEXTENSION_OBJECT_PATH,
-            node_info->interfaces[0],
-            &interface_vtable,
-            WEBKIT_WEB_EXTENSION(data),
-            NULL,
-            &error);
-
-    if (!ext.regid) {
-        g_warning("Failed to register web extension object: %s", error->message);
-        g_error_free(error);
-    }
-}
-
 /**
  * Callback called if a editable element changes it focus state.
  * Event target may be a WebKitDOMDocument (in case of iframe) or a
  * WebKitDOMDOMWindow.
  */
-static void on_editable_change_focus(WebKitDOMEventTarget *target, WebKitDOMEvent *event)
+static void on_editable_change_focus(WebKitDOMEventTarget *target,
+        WebKitDOMEvent *event, WebKitWebExtension *extension)
 {
     gboolean input_focus;
     WebKitDOMDocument *doc;
@@ -285,7 +319,7 @@ static void on_editable_change_focus(WebKitDOMEventTarget *target, WebKitDOMEven
 
         iframe = WEBKIT_DOM_HTML_IFRAME_ELEMENT(active);
         subdoc = webkit_dom_html_iframe_element_get_content_document(iframe);
-        add_onload_event_observers(subdoc);
+        add_onload_event_observers(subdoc, extension);
         return;
     }
 
@@ -296,30 +330,36 @@ static void on_editable_change_focus(WebKitDOMEventTarget *target, WebKitDOMEven
     if (input_focus != ext.input_focus) {
         ext.input_focus = input_focus;
 
-        dbus_emit_signal("EditableChangeFocus", g_variant_new("(b)", input_focus));
+        dbus_emit_signal("EditableChangeFocus", extension,
+                g_variant_new("(b)", input_focus));
     }
 }
 
 /**
  * Callback for web extensions page-created signal.
  */
-static void on_page_created(WebKitWebExtension *extension, WebKitWebPage *page, gpointer data)
+static void on_page_created(WebKitWebExtension *extension, WebKitWebPage *webpage, gpointer data)
 {
+    guint64 pageid = webkit_web_page_get_id(webpage);
+
     /* Save the new created page in the extension data for later use. */
-    ext.webpage = page;
+    ext.webpage = webpage;
+    if (ext.connection) {
+        emit_page_created(ext.connection, pageid);
+    } else {
+        queue_page_created_signal(pageid);
+    }
 
-    g_object_connect(page,
-            "signal::send-request", G_CALLBACK(on_web_page_send_request), NULL,
-            "signal::document-loaded", G_CALLBACK(on_web_page_document_loaded), NULL,
+    g_object_connect(webpage,
+            "signal::send-request", G_CALLBACK(on_web_page_send_request), extension,
+            "signal::document-loaded", G_CALLBACK(on_web_page_document_loaded), extension,
             NULL);
-
-    dbus_emit_signal("PageCreated", g_variant_new("(t)", webkit_web_page_get_id(page)));
 }
 
 /**
  * Callback for web pages document-loaded signal.
  */
-static void on_web_page_document_loaded(WebKitWebPage *page, gpointer data)
+static void on_web_page_document_loaded(WebKitWebPage *webpage, gpointer extension)
 {
     /* If there is a hashtable of known document - detroy this and create a
      * new hashtable. */
@@ -328,31 +368,38 @@ static void on_web_page_document_loaded(WebKitWebPage *page, gpointer data)
     }
     ext.documents = g_hash_table_new(g_direct_hash, g_direct_equal);
 
-    add_onload_event_observers(webkit_web_page_get_dom_document(page));
+    add_onload_event_observers(webkit_web_page_get_dom_document(webpage),
+            WEBKIT_WEB_EXTENSION(extension));
 }
 
 /**
  * Callback for web pages send-request signal.
  */
-static gboolean on_web_page_send_request(WebKitWebPage *page, WebKitURIRequest *request,
-        WebKitURIResponse *response, gpointer data)
+static gboolean on_web_page_send_request(WebKitWebPage *webpage, WebKitURIRequest *request,
+        WebKitURIResponse *response, gpointer extension)
 {
+    char *name, *value;
+    SoupMessageHeaders *headers;
+    GHashTableIter iter;
+
+    if (!ext.headers) {
+        return FALSE;
+    }
+
     /* Change request headers according to the users preferences. */
-    if (ext.headers) {
-        char *name, *value;
-        SoupMessageHeaders *headers;
-        GHashTableIter iter;
-
-        headers = webkit_uri_request_get_http_headers(request);
-        g_hash_table_iter_init(&iter, ext.headers);
-        while (g_hash_table_iter_next(&iter, (gpointer*)&name, (gpointer*)&value)) {
-            /* Null value is used to indicate that the header should be
-             * removed completely. */
-            if (value == NULL) {
-                soup_message_headers_remove(headers, name);
-            } else {
-                soup_message_headers_replace(headers, name, value);
-            }
+    headers = webkit_uri_request_get_http_headers(request);
+    if (!headers) {
+        return FALSE;
+    }
+
+    g_hash_table_iter_init(&iter, ext.headers);
+    while (g_hash_table_iter_next(&iter, (gpointer*)&name, (gpointer*)&value)) {
+        /* Null value is used to indicate that the header should be
+         * removed completely. */
+        if (value == NULL) {
+            soup_message_headers_remove(headers, name);
+        } else {
+            soup_message_headers_replace(headers, name, value);
         }
     }