[webkit-gtk] Interface between embedded Javascript and the main GTK app

Gavin Smith gavinsmith0123 at gmail.com
Fri Jan 3 07:34:28 PST 2025


On Fri, Jan 03, 2025 at 03:22:45PM +0200, Sim Tov wrote:
> Thank you very  much Michael! Finally I was able to get to this project.
> The idea is to create a small GTK-based text editor with live preview for
> [djot](https://github.com/jgm/djot.js).

By coincidence I also came back to the project I was
using WebKitGTK for and used Michael's suggestion of
window.webkit.messageHandlers.foo.postMessage() for IPC.

It has seemed quite straightforward.  In the UI process, I initialise
the web view object and the channel:

    WebKitUserContentManager *manager1;

    manager1 = webkit_web_view_get_user_content_manager (webView);
    g_signal_connect (manager1, "script-message-received::channel",
                      G_CALLBACK (handle_script_message), NULL);
    webkit_user_content_manager_register_script_message_handler (manager1,
                                                                 "channel");

'handle_script_message' starts like:

    void
    handle_script_message (WebKitUserContentManager *manager,
                           WebKitJavascriptResult   *js_result,
                           gpointer                  user_data)
    {
      JSCValue *jscValue = webkit_javascript_result_get_js_value (js_result);
      char *message = jsc_value_to_string (jscValue);

It then processes the message send from the web process.

In the web process (with "web extensions" code), I can then send the
message:

void
send_js_message (WebKitWebPage *web_page, char *message)
{
  WebKitFrame *frame = webkit_web_page_get_main_frame (web_page);
  if (!frame)
    return;
  JSCContext *jsc = webkit_frame_get_js_context (frame);
  if (!jsc)
    return;

  JSCValue *js_string = jsc_value_new_string (jsc, message);
  jsc_context_set_value (jsc, "msgString", js_string);

  JSCValue *jscValue = jsc_context_evaluate (jsc,
    "window.webkit.messageHandlers.channel.postMessage(msgString);",
    -1);

Before, I had interpolated the string into a JavaScript literal string:

  asprintf (&js,
    "window.webkit.messageHandlers.channel.postMessage(`%s`);", message);

but this wouldn't work if the mesage contained a backtick (`) character.

It seems a bit convoluted that you start with a "page", then get a "frame",
before getting a "context" that you can finally execute JavaScript on but
I trust that it is this way for a good reason.

(This is with the WebKitGTK 4.0 API although I gather there are newer
versions now.)

I don't know what djot is and don't know how relevant this is to your
project.


More information about the webkit-gtk mailing list