About WebKit, browsers and mail clients. And green cats.

Menu

Today is the day of Midori 0.5.8. Dedicated to Adblock and WebKit2. Rather than trying to meet fixed dates as we used to, we selected which goals define if the cycle is done. No more no less.

As liked, fast and efficient our Adblock extension was, the original maintainer isn’t around anymore and flaws were accumulating on a code base that wasn’t very accessible anymore. So long story short Adblock is rewritten from C to Vala, several classes and files instead of one monolithic entity, plenty unit test cases and real whitelist support. Add to that a statusbar icon for easy flipping filtering on and off and seeing whether anything was blocked on the site. If you had problems with peculiar display problems whilst using Adblock, chances are good they’ll be gone with the upgrade. Adblock is as always shipped with Midori so just be sure to enable it in the Preferences!

In other news WebKit2 is making another big jump and closer to the finish line. Text selection behavior, favicons, support for multiple rendering processes, opening new windows and setting cache and cookie paths correctly. There’s still work to do in the areas of extensions and downloads in particular, but we’re getting there.

We have working spelling corrections again. Right-click an underlined word and pick a suggestion from the menu. It’s that simple.

Two new extensions implement Ctrl+Enter to complete www. and .com and a handy little notes panel which automatically saves one or more snippets as you make changes.

Aaaaaand we’ve got a brand new file type editor (MIME type on Linux). Finally the user is in control of how files open, either via the Preferences or the right-click “Open With…” menu item.

As always see the file Changelog for more details. And stick around for a bit if your package isn’t there yet, it can take a while.

DOM touch events support

WebKitWebView now processes the touch events happening in the widget to notify the DOM, making modern websites using DOM touch API properly work. Carlos Garnacho has taken a screencast to show it in action

Plugins cache

When the first page containing plugins was loaded, the UI process got blocked for some time, while the plugins were scanned. This was one of the most annoying bugs of WebKitGTK+ introduced in 2.0. Plugins are synchronously scanned on demand during the page load, and it’s something that can’t be avoided. WebKitGTK+ 2.4 uses a persistent cache to store information about all plugins, so that plugins are only scanned the first time or when they change.

WebKit1 deprecation

There’s one last thing I would like to mention. Even when WebKit1 API has been deprecated since we released WebKitGTK+ 2.0, we have kept shipping both APIs in our tarball releases. A decision hasn’t been made yet, but this is probably the last release including the WebKit1 API, we have plans to remove the WebKit1 code from trunk and move all the build bots to run only WebKit2 tests. We encourage everybody to port their applications to WebKit2, submitting bug reports if there’s anything preventing the switch, and of course we are happy to help on IRC, mailing list, etc.

The avid user may have noticed the release is overdue, although scheduling a release over new year’s eve was probably a lost bet to begin with, so that’s why. The good news is we got some extra bug fixing time.

So what did we get done? A good amount of clean-up including a revamped notebook – this is tech jargon for the tabs UI – with the goal of reducing bugs due to different build configuration, regardless of whether one is using GTK+2, GTK+3, Granite or Windows. A good deal of dead code could be dropped and many things simplified. There’s also a new Database abstraction which you don’t see on the outside but improves error handling and reduces bugs by unifying how things are done.

Now this is all nice and boring, are there any actual changes? Yes! Session management, nicknamed tabby, again gets smarter about reacting to crashes by not loading the faulty website and running commands on the command line properly. Private browsing has also benefited from some bug fixing, such as not wrongly attempting to load favicons from disk and enabling the sidepanel, for example for downloads (or other panels from extensions, for the brave ones who use the command line to enable extensions in private browsing).

Oddly enough one very small feature we got which I find amazingly useful myself ever since it’s there: Close Tabs to the Right. You wouldn’t think it does much, but if you’re applying a workflow of search and open as many results tabs as you can, and suddenly find all but one very much obsolete, this is exactly what you need.

As always see the file Changelog for more details. And stick around for a bit if your package isn’t there yet, it can take a while.

The current experimental build has had mostly positive feedback so it will be the basis for the upcoming Midori 0.5.7 for Windows. As described in detail earlier WebKit and GStreamer were updated. This also contains the latest featureset from trunk which is entering freeze now. This includes refactored tabs, better font defaults, and a number of smaller fixes. Any testing now can help findings bugs before the next release!

Known Issues

Dark shadow on inactive buttons (gtk3 style issue)

Cursor does not change appearance on links/ textarreas (webkitgtk3 issue)

As every year many ideas came up during the WebKitGTK+ hackfest presentation, but this time there was one we all were very excited about, the multiple web processes support. Apple developers already implemented the support for multiple web processes in WebKit, which is mostly cross platform, but it requires the network process support to properly work (we need a common network process where cookies, HTTP cache, etc are shared for all web processes in the same web context). Soup based WebKit ports don’t implement the network process yet, so the goal of the hackfest became to complete the network process implementation previously started by EFL and Nix guys, as a first step to enable the multiple web processes support. Around 10 people were working on this goal during the whole hackfest, meeting from time to time to track the status of the tasks and assigning new ones.

Andy updated some of the patches already waiting for a review and set up github repo with all those patches so that we all could work without dealing with individual patches.

Sergio updated the patch proposed by Balazs to implement the bits required to connect the network process with the web process using UNIX domain sockets.

After all this awesome work we managed to have the basic support, with MiniBrowser perfectly rendering pages and allowing navigation using the network process. But as expected, there were some bugs and missing features, so I ran the WebKit2 unit tests and we took failing tests to investigate why they were failing and how to fix them.

Adrian submitted a patch to add new API to select the process model that will be used when the network process support is finished. He is also working on the problems of having multiple instances of the web extensions.

So, we are actually far from having a complete and stable network process support, but it’s a huge step forward. The good news is that once we have network process implemented, the multiple web processes support will work automatically just by selecting the multiple web process model.

All this sounds like a lot of work done, but that’s only a small part of what has happened this week in Coruña:

Martin and Gustavo made moreparts of WebKit actually build with the cmake build.

And I’m sure I’m missing more great stuff done that I could not follow closely. It’s definitely been a very productive hackfest that it would haven’t been possible without the sponsors, Igalia and the GNOME Foundation. Thanks!

Our new session management nicknamed tabby need a little bit more polish so we decided to go for a double length release cycle. This is a proper rewrite of the tab loading at startup and for the first time fully aware of multiple windows, able to load most recently used websites first and smart enough to not block GUI updates. If that’s not impressive enough it designed to get a sync backend and session management GUI is already work in progress, though it’s not ready for the spot light yet.

We also made the switch from WAF to cmake. What does this mean to end users? Nothin much. But to developers and contributors it means a lot. A big motivation was frustration from package maintainers with several aspects of WAF such as compatibility and the need to ship a binary blob. And in fact most contributors never got the hang of it. cmake on the other hand seems to win people over for not so obvious reasons. It’s in many ways tailored towards doing what it does while giving decent error behavior.

We also went with GApplication aka GLib.Application. No more choice between Unique and our own custom sockets implementation, which means less bugs due to different code paths and code possibly being disabled in some builds. It’s notably not Gtk.Application because we’re still crazy enough to support GTK+2 on its last breath which mainly means no use of new features that didn’t exist before either.

As always see the file Changelog for more details. And stick around for a bit if your package isn’t there yet, it can take a while.

New Web Inspector

WebKitGTK+ now uses the new Web Inspector recently opensourced and upstreamed by Apple. We took advantage of the migration to improve the way inspector resources are distributed by compiling them in the WebKitGTK+ library as GResources. This means that resources are now always available without having to run make install or set environment variables.

Initial Wayland support

WebKitGTK+ 2.2 can be built with Wayland target if it’s available (it requires GTK+ 3.10 compiled with Wayland support). Not everything is fully supported yet, but the WebKit layout tests can be run under the Weston compositor and WebGL content works under Wayland displays too. There’s more detailed information in Žan Doberšek’s blog.

Video accelerated compositing support

When accelerated compositing is enabled, the GStreamer media player can play videos using OpenGL. You can find more details in Víctor’s blog.

Custom JavaScript injection

This was one of the major regressions in WebKit2GTK+ compared to the WebKit1 API. WebKitGTK+ 2.2 now allows to inject custom JavaScript code using the JavaScriptCore C API from a WebKit Web Process Extension. New API has been added to also allow running specific JavaScript code in isolated worlds. You can find examples about how to use this API and how to write Web Process Extensions in general in this post.

Improved accessibility support in WebKit2

Accessibility support in WebKit2 has been reworked to not depend on pango and gail, which resulted in several bugs fixed and a much better accessibility support. Check Mario’s blog for all the details.

The multiprocess architecture of WebKit2 brought us a lot of advantages, but it also introduced important challenges, like how to expose some features that now live in the Web Process (DOM, JavaScript, etc.). The UI process API is fully asynchronous to make sure the UI is never blocked, but some APIs like the DOM bindings are synchronous by design. To expose those features that live in the Web Process, WebKit2GTK+ provides a Web Extensions mechanism. A Web Extension is like a plugin for the Web Process, that is loaded at start up, similar to a GTK module or gio extension, but that runs in the Web Process. WebKit2GTK+ exposes a simple low level API that at the moment provides access to three main features:

GObject DOM bindings: The exactly same API used in WebKit1 is available in WebKit2.

WebKitWebPage::send-request signal: It allows to change any request before it is sent to the server, or even simply prevent it from being sent.

Custom JavaScript injection: It provides a signal, equivalent to WebKitWebView::window-object-cleared in WebKit1, to inject custom JavaScript using the JavaScriptCore API. (Since 2.2)

This simple API doesn’t provide any way of communication with the UI Process, so that the user can use any IPC mechanism without interfering with the internal WebKit IPC traffic. Epiphany currently installs a Web Extension to implement some of its features such us pre-filled forms, ads blocker or Do Not Track using D-BUS for the communication between the Web Extension and the UI Process.

How to write a Web Extension?

Web Extensions are shared libraries loaded at run time by the Web Process, so they don’t have a main function, but they have an entry point called by the WebProcess right after the extension is loaded. The initialization function must be called webkit_web_extension_initialize() and it receives a WebKitWebExtension object as parameter. It should also be public, so make sure to use the G_MODULE_EXPORT macro. This is the function to initialize the Web Extension and can be used, for example, to be notified when a web page is created.

The extension will be installed in $(libdir)/MyApp/web-extension so we need to tell WebKit where to find web extensions before the Web Process is spawned. Call webkit_web_context_set_web_extensions_directory() as soon as possible in your application, before any other WebKit call to make sure it’s called before a Web Process is launched. You can create a preprocessor macro in the Makefile.am to pass the value of the Web Extensions directory.

This should be enough. You should be able to build and install the Web Extension with you program and see the printf message every time a page is created. But that’s a useless example, let’s see how to use the Web Extensions API to do something useful.

Accessing the DOM

The GObject DOM bindings API available in WebKit1 is also exposed in WebKit2 from the Web Extensions API. We only need to call webkit_web_page_get_dom_document() to get the WebKitDOMDocument of the given web page.

Using WebKitWebPage::send-request signal

Using the Web Extensions API it’s possible to modify the request of any resource before it’s sent to the server, adding HTTP headers or modifying the URI. You can also make WebKit ignore a request, for example to block resources depending on the URI, by simply connecting to the signal and returning TRUE.

Extending JavaScript

Using the JavaScriptCore API it’s possible to inject custom JavaScript code by connecting to the window-object-cleared signal of the default WebKitScriptWorld. You can get the global JavaScript execution context by calling webkit_frame_get_javascript_context_for_script_world() for the WebKitFrame passed as parameter of the window-object-cleared signal.

Upgrading time for our Windows build. While all of these are pretty much under-the-hood changes it has a big impact on your browsing experience. We’re going for the latest stable WebKit with JIT-enabled javascript and WebP support. And we’re switching to a more recent maintained set of GStreamer plugins – in the past these weren’t easily available and always required extra work to add.

See below for the technical overview and currently known issues. The build still needs some rigorous testing to move from experimental to stable – if it works well it will be used for the next Midori version.

Build details

WebkitGtk 2.0.4

Spellcheck (you need to install dicts yourself for now)

JIT for javascript enabled

WebP support

GStreamer 1.0 plugins

Known Issues

Dark shadow on inactive buttons (gtk3 style issue)

Cursor does not change appearance on links/ textarreas (webkitgtk3 issue)