While it is possible to pass client-side messages to a web page right after a view has been created (with the webkit_web_view_send_message_to_page() API), there's no way for the WebView to know if the web process has created a new page (due to navigation, for example), in order to send a message to that new page, for cases when data should be available to a specific page and not to all via web extension data. There could be two independent approaches to do this, both would require some new API in WebKit: 1. For data that is immutable, one could mimic webkit_web_context_set_web_extensions_initialization_user_data() and add a webkit_web_view_set_web_page_initialization_data() method that would allow passing of initialization data to pages. Then on the web extension side, one could call a webkit_web_page_get_initialization_data() method (for example, in the "page-created" signal handler), in order to get that data. This would not allow to pass arbitrary messages any time that a new page is created, though. 2. For the latter, an alternative would be to have a WebKitWebView:page-created signal that can be used to send a new message via the existing webkit_web_view_send_message_to_page() method, if needed. These approaches are complementary and both could be implemented, for our use-case either would work, so the idea is to discuss here possible drawbacks and a course of action before starting any implementation.
This proposal that comes after a conversation with aperez (igalia.com): We could add a new signal in the webview. There is a `didReceiveSynchronousMessageFromInjectedBundle()`, when the webprocess sends a sync message to the uiprocess it will pause waiting for a reply. We could send a sync message whenever a new page is created (new page in webprocess = new page load). It would be like this: 1. When a WebKitWebPage is going to be created (which happens for every new load), send a sync message to the UIProcess. 2. In the UIProcess, receive the message, emit signal WebKitWebView::configure-web-extension-page (maybe not the best name) that it runs once per WebKitWebPage 3. If a signal handler for the signal returns a GVariant, send it back as response to the sync message. 4. Back in the WebProcess, if a GVariant is received, assign it to the WebKitWebPage.initialization-data property. 5. Emit WebKitWebExtension::page-created normally. Signal handlers in webprocess extensions can read the data returned in (2.) using the WebKitPage.initialization-data property at this point, before the load starts, or even later when WebKitScriptWorld::window-object-cleared is emitted (because signal handlers for this signal receive the WebKitWebPage, too)
Unfortunately the `WKBundlePostSynchronousMessage()` is a deprecated method of the C API nowadays: Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundle.h:WK_EXPORT void WKBundlePostSynchronousMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnRetainedData) WK_C_API_DEPRECATED;
Created attachment 459285 [details] 1st tentative patch
I just uploaded a 1st tentative but functional patch that in some how could establish the ground for this change. Example of use: - UI-process: ``` g_signal_connect(webView, "initialize-web-extensions", G_CALLBACK(onInitializeWebExtensions), nullptr); void View::onInitializeWebExtensions(WebKitWebView* webView, gpointer*) { webkit_web_view_set_web_extensions_initialization_user_data(webView, g_variant_ref_sink(g_variant_new("(s)", "foo"))); } ``` - WebProcess extension: ``` g_signal_connect( webExtension, "initialize-web-extensions", G_CALLBACK(+[](WebKitWebExtension*, GVariant* userData, WebProcessExtension* self) { // Callback }), this); ```
Created attachment 459586 [details] 2st tentative patch
Pull request: https://github.com/WebKit/WebKit/pull/891