diff options
author | Philip Chimento <philip@endlessm.com> | 2015-05-21 15:26:51 -0700 |
---|---|---|
committer | Philip Chimento <philip@endlessm.com> | 2015-05-22 12:14:08 -0700 |
commit | 6a1d8e328ffe96c3e68a468545addef6ffd15da9 (patch) | |
tree | adc2d2a7d32d4c31571238708423d5d880c94b0f /webhelper/webextensions | |
parent | b8d6310bfd7af2cece81c0b7e7fc71711a991871 (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.c | 90 |
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); |