4 Hugues Ross - Blog: 07/01/2016 - 08/01/2016
Hugues Ross

7/13/16

Listening to Your Javascript

It's been a while, but I haven't been idle. I've made a great amount of progress on Singularity, and I've finally discovered a secret that has eluded me for years!

The Problem

These stories always have to start with a problem. In this case, the problem was a seemingly simple one:

"When the user interacts with Singularity's WebKitGTK viewport, how do I make the app react to it?"

This used to be really easy, back in the days of Webkit 1. However, when Webkit2 changed the API and moved some functionality to it's web extension API, Javascript support followed suit. For a long time, the only solution was to simply create an 'extension' that used some form of IPC to communicate with the main app, but I didn't want to do that in Singularity. Instead, I used a crude hack by encoding messages in URL requests.

A Tentative Solution

Needless to say, this solution is slow and terrible, but I've found a better answer. At some point since my work on Singularity started, WebKit introduced the UserContentManager, which can apply custom CSS and Javascript to web pages. This is a really awesome feature that I plan on using in future projects, but it also provides me with a new tool, a signal for handling certain Javascript calls. According to valadoc.org:

public signal void script_message_received (JavascriptResult js_result)
"This signal is emitted when JavaScript in a web view calls
window.webkit.messageHandlers.name.postMessage()
after registering name using register_script_message_handler"

In other words, it lets you set up a callback that is called whenever a script calls a certain function, sending arbitrary data from the web page to the application displaying it. This is a really powerful feature.

So powerful, in fact, that you can't actually use it in Vala.

What Gives?

As it turns out, Vala's JavascriptResult class has no useful functions or properties. I'm not entirely certain why, given the solution that I'm about to provide.

While WebKitGTK's JavascriptResult does contain the necessary functions, no Vala bindings exist for them. Instead, you need to access them from C and return whatever result your app is expecting. This seems really odd, and I hope I don't have to find out the hard way later on, but for now I'm feeling pretty good about this.

I'll be posting an update with a more thorough rundown of my work on Singularity soon.