summaryrefslogtreecommitdiff
path: root/webhelper/webextensions
diff options
context:
space:
mode:
authorPhilip Chimento <philip@endlessm.com>2015-05-21 15:26:51 -0700
committerPhilip Chimento <philip@endlessm.com>2015-05-22 12:14:08 -0700
commit6a1d8e328ffe96c3e68a468545addef6ffd15da9 (patch)
treeadc2d2a7d32d4c31571238708423d5d880c94b0f /webhelper/webextensions
parentb8d6310bfd7af2cece81c0b7e7fc71711a991871 (diff)
Export webview DBus objects when bus ready
Instead of starting an idle function when a webview page is created that waits until the bus connection object is ready before exporting an object on it, we save all page IDs that we haven't registered yet and instead register them all at once when the bus is ready. [endlessm/eos-sdk#291]
Diffstat (limited to 'webhelper/webextensions')
-rw-r--r--webhelper/webextensions/wh2extension.c90
1 files changed, 57 insertions, 33 deletions
diff --git a/webhelper/webextensions/wh2extension.c b/webhelper/webextensions/wh2extension.c
index 4da7ae4..5b4ad06 100644
--- a/webhelper/webextensions/wh2extension.c
+++ b/webhelper/webextensions/wh2extension.c
@@ -21,17 +21,18 @@
void webkit_web_extension_initialize_with_user_data (WebKitWebExtension *, const GVariant *);
typedef struct {
+ WebKitWebExtension *extension; /* unowned */
GDBusConnection *connection; /* unowned */
GDBusNodeInfo *node; /* owned */
GDBusInterfaceInfo *interface; /* owned by node */
GSList *bus_ids; /* GSList<guint>; owned */
- GSList *page_ctxts; /* GSList<PageContext *>; owned */
+ GArray *unregistered_pages; /* GArray<guint64>; owned */
gchar *main_program_name; /* owned; well-known-name of main program */
} Context;
typedef struct {
Context *ctxt; /* unowned */
- WebKitWebPage *page; /* unowned */
+ guint64 page_id;
} PageContext;
static const gchar introspection_xml[] =
@@ -46,9 +47,10 @@ context_free (Context *ctxt)
{
g_clear_pointer (&ctxt->node, g_dbus_node_info_unref);
g_clear_pointer (&ctxt->bus_ids, g_slist_free);
+ if (ctxt->unregistered_pages != NULL)
+ g_array_free (ctxt->unregistered_pages, TRUE);
+ ctxt->unregistered_pages = NULL;
g_clear_pointer (&ctxt->main_program_name, g_free);
- g_slist_free_full (ctxt->page_ctxts, (GDestroyNotify) g_free);
- ctxt->page_ctxts = NULL;
g_free (ctxt);
}
@@ -301,7 +303,13 @@ on_wh2_method_call (GDBusConnection *connection,
return;
}
- WebKitDOMDocument *document = webkit_web_page_get_dom_document (pctxt->page);
+ WebKitWebPage *page = webkit_web_extension_get_page (pctxt->ctxt->extension,
+ pctxt->page_id);
+ if (page == NULL)
+ return;
+ /* The page may have been destroyed, but WebKit doesn't let us find out. */
+
+ WebKitDOMDocument *document = webkit_web_page_get_dom_document (page);
if (document == NULL)
{
g_dbus_method_invocation_return_error_literal (invocation, G_IO_ERROR,
@@ -321,40 +329,39 @@ static GDBusInterfaceVTable dbus_impl_vtable = {
NULL /* set property */
};
-static gboolean
-register_object (PageContext *pctxt)
+static void
+register_object (guint64 page_id,
+ Context *ctxt)
{
GError *error = NULL;
- if (pctxt->ctxt->connection == NULL)
- return G_SOURCE_CONTINUE; /* Try again when the connection is ready */
-
- /* The ID is known to the main process and the web process. So we can address
- a specific web page over DBus. */
- guint64 id = webkit_web_page_get_id (pctxt->page);
+ g_assert (ctxt->connection != NULL);
gchar *object_path = g_strdup_printf("/com/endlessm/webview/%"
- G_GUINT64_FORMAT, id);
-
- guint bus_id = g_dbus_connection_register_object (pctxt->ctxt->connection,
- object_path,
- pctxt->ctxt->interface,
- &dbus_impl_vtable,
- pctxt, NULL,
- &error);
+ G_GUINT64_FORMAT, page_id);
+
+ /* This struct is owned by the registered DBus object */
+ PageContext *pctxt = g_new0 (PageContext, 1);
+ pctxt->ctxt = ctxt;
+ pctxt->page_id = page_id;
+
+ guint bus_id =
+ g_dbus_connection_register_object (ctxt->connection, object_path,
+ ctxt->interface, &dbus_impl_vtable,
+ pctxt, (GDestroyNotify) g_free, &error);
+ g_free (object_path);
if (bus_id == 0)
{
g_critical ("Failed to export webview object on bus: %s", error->message);
g_clear_error (&error);
- goto out;
+ goto fail;
}
- pctxt->ctxt->bus_ids = g_slist_prepend (pctxt->ctxt->bus_ids,
- GUINT_TO_POINTER (bus_id));
+ ctxt->bus_ids = g_slist_prepend (ctxt->bus_ids, GUINT_TO_POINTER (bus_id));
+ return;
-out:
- g_free (object_path);
- return G_SOURCE_REMOVE;
+fail:
+ g_free (pctxt);
}
static void
@@ -362,14 +369,19 @@ on_page_created (WebKitWebExtension *extension,
WebKitWebPage *page,
Context *ctxt)
{
- PageContext *pctxt = g_new0 (PageContext, 1);
- pctxt->ctxt = ctxt;
- pctxt->page = page;
+ /* The ID is known to the main process and the web process. So we can address
+ a specific web page over DBus. */
+ guint64 id = webkit_web_page_get_id (page);
- ctxt->page_ctxts = g_slist_prepend (ctxt->page_ctxts, pctxt);
+ if (ctxt->connection == NULL)
+ {
+ /* The connection is not ready yet. Save the page ID in a list of pages
+ for which we need to register objects later. */
+ g_array_append_val (ctxt->unregistered_pages, id);
+ return;
+ }
- g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc) register_object,
- pctxt, NULL);
+ register_object (id, ctxt);
}
/* window-object-cleared is the best time to define properties on the page's
@@ -436,6 +448,16 @@ on_bus_acquired (GDBusConnection *connection,
if (ctxt->interface == NULL)
goto fail;
+ /* Register DBus objects for any pages that were created before we got here */
+ guint ix;
+ for (ix = 0; ix < ctxt->unregistered_pages->len; ix++)
+ {
+ guint64 id = g_array_index (ctxt->unregistered_pages, guint64, ix);
+ register_object (id, ctxt);
+ }
+ g_array_remove_range (ctxt->unregistered_pages, 0,
+ ctxt->unregistered_pages->len);
+
return;
fail:
@@ -483,6 +505,8 @@ webkit_web_extension_initialize_with_user_data (WebKitWebExtension *extension,
const gchar *name = g_variant_get_string ((GVariant *) data_from_app, NULL);
Context *ctxt = g_new0 (Context, 1);
+ ctxt->extension = extension;
+ ctxt->unregistered_pages = g_array_new (FALSE, FALSE, sizeof (guint64));
ctxt->main_program_name = g_strdup (name);
gchar *well_known_name = g_strconcat (name, ".webhelper", NULL);