Lately at Collabora I have been working on helping Mozilla with the GTK+ 3 port of Firefox.
The problem
The issue we had to solve is that GTK+ 2 and GTK+ 3 cannot be loaded in the same address space. Moving Firefox from GTK+ 2 to GTK+ 3 isn’t a problem, as only GTK+ 3 gets loaded in its address space, and everything is fine. The problem comes when you load a plugin that links to GTK+ 2, e.g. Flash. Then, GTK+ 2 and GTK+ 3 get both loaded, GTK+ detects that, and aborts to avoid bigger problems. This was tracked as bug #624422.
More specifically, Firefox links to libxul.so, which in turn links to GTK+. These days, the plugins are loaded in a separate process, plugin-container, which communicates with the Firefox process through IPC. If plugin-container didn’t link to GTK+, there would be absolutely no problem, as the browser (Firefox) process could link to GTK+ 3 and plugin-container could load any plugin, including GTK+ 2 ones. However, although plugin-container doesn’t directly use GTK+, it links to libxul.so for IPC, which brings GTK+ into its address space.
The solution
In order to solve this, we evaluated various options. The first one was to split libxul.so in two parts, one with the IPC code and lower level stuff, which wouldn’t link to GTK+, and another side with the rest of the code, including all the widget and toolkit integration, which would obviously link to GTK+. However this turned not to be possible as the libxul code was too intricate.
In the end, we decided to add a thin layer between libxul and GTK+, which we called libmozgtk.so. This small layer links to GTK+ 3, and provides stubs for GTK+ 2 specific symbols. Additionally, there is a libmozgtk2.so with SONAME “libmozgtk.so”, which links to GTK+ 2 and provides stubs for GTK+ 3 symbols. We made libxul link against libmozgtk.so, and so when Firefox runs, libxul.so, libmozgtk.so, and GTK+ 3 are loaded, and Firefox uses GTK+ 3. However when plugin-container is executed, we add LD_PRELOAD=libmozgtk2.so in the environment. Since libmozgtk2.so has a libmozgtk.so SONAME, the libxul.so dependency is satisfied, and the plugin-container process ends with GTK+ 2. Since plugin-container doesn’t make use of the GTK+ code in libxul, this is safe, and we end up with a GTK+ 3 Firefox that can load GTK+ 2 plugins. The end result is that you can watch Youtube videos again!
While this solution is somewhat hacky, it means we didn’t need to mess with libxul, splitting it in two just for the Linux/GTK+ port’s sake. And when the GTK+ 2 plugins become irrelevant, or NPAPI support is removed (as it recently happened in Chrome), we should be able to easily revert this and use GTK+ 3 everywhere.
Wayland
On an unrelated note, we have looked a bit at porting Firefox to Wayland. Wayland is designed to be a replacement for X11, and is becoming very popular in the digital TV and set top box space. Those obviously need HTML engines and web browsers, and with WebKit and Chrome already having Wayland ports, we think Firefox shouldn’t fall behind.
For this, the GTK+ 3 port was a prerequisite, but that isn’t enough. There are many X11 uses on the Firefox codebase, most of which are guarded by #ifdef MOZ_X11, though not all of them are. We got Firefox to start on Weston (the Wayland reference compositor) with a bunch of hacks, one of which broke keyboard input (but avoided a segfault). As you can see from the screenshot, things aren’t perfect, but it’s at least a good start!
Well done!
Well, another option could have been to just make gtk use proper symbol versioning.
Non X11 Firefox? I demand Firefox in Firefox screenshots using the Broadway backend!
… and these kinds of hacks are exactly the reason I stopped using firefox once I looked into the code deeply enough to provide a couple of patches …
With so many non-Gnome projects jumping off GTK in favor of Qt (Audacious being the most recent one I’m aware of), why not do the same? Jolla already paved the way:
http://blog.idempotent.info/posts/whats-behind-sailfish-browser.html
Getting a rationally-designed file-selection dialog would justify switching from GTK to QT all by itself, in my opinion (admittedly, this is the opinion of someone who wouldn’t be doing the porting work…)
Wow, this is amazing work. They splitted moz Ui off and designed an emedding API modeled after WebKit. So, why was that never merged?
How are plugins going to work in Wayland with no XEmbed?
> How are plugins going to work in Wayland with no XEmbed?
XWayland could support XEmbed. Or plugins could just not work, and nothing of value would be lost.
Sharing a image buffer (software or hardware) most likely, similar to how Windows and OS X versions handle hardware accelerated plugins.
It lets plugins integrate better into the page (They’re affected by things like CSS transforms), and allow for plugins ti render directly via OpenGL if they need to. Actually matches how Wayland works fairly closely.
That’s be a sensible architecture to redesign plugins, but that would only help with new plugins, and we don’t need or want any of those. Existing plugins rely on NPAPI and X.
s/That’s/That’d/
Does the Wayland port imply Firefox running on pure GTK+, such that it’ll work with any GTK+ backend, or did you replace the X-specific code with Wayland-specific code?
Can you give an overview of what kinds of things Firefox uses X for directly, and why it can’t use GTK+ for that functionality? (Apart from plugins.) That might give a good overview of things that GTK+ ought to support in the future.
Thanks all for your comments!
@Josh: There is no Wayland port per se yet. What I did was to take advantage of the existing non-X11 paths that exist in libxul. In theory, Firefox could run on other GTK+ backends as well. There are some paths that need fixing in libxul, so that the Wayland port (or any other you may think of) would work well, e.g. widget/gtk/nsGtkKeyUtils.cpp (see the X calls) or widget/gtk/nsWindow.cpp (see all the gdk_x11_* calls). I don’t have a through list at this point, but for example one thing that GTK+ could abstract that would make things simpler is having a backend-independent API call to get the DPI for a screen (e.g. gdk_screen_get_dpi()). That would immediately simplify nsWindow::GetDPI(), and avoid having to add #ifdefs for each platform. I’m sure we could find many more cases. Let me know if you have any further questions.
So, looking at the missing «*get_dpi*» call, he didn’t have any further questions.
@Waldi: Actually, it’s not solvable just with symbol versioning because of GObject’s run-time type registration system. You can’t load Gtk+ 2 and Gtk+ 3 in the same copy of GObject because then two libraries try to register eg “GtkWidget” and one of them will fail. Nobody has really tried to change that behaviour because if you thought having a Gtk+ 2 to 3 ABI break was inconvenient, a GObject ABI break would hurt so many more projects.
Keep it simple with GTK, Qt is better to use. Opera, Chrome, do not use GTK and look perfect on any desktop. I think Firefox should do the same, but definitely not use GTK would be the best option.
Chrome and Opera is not using qt. Chrome and opera is using auro
You mean skia no? https://www.chromium.org/developers/design-documents/graphics-and-skia
Its easy to embed that using https://code.google.com/p/chromiumembedded/
Seems thats exactly the model followed by https://github.com/tmeshkova/qtmozembed
Keep up the good work! Not enough people are working on supporting Linux at the moment, and we might get to a place where that’s more important than Windows. Hopefully.
Anyways, thanks for the good job you’re doing!
Just wanted to thank you for this work and that I, like many others, are eagerly awaiting this.
Again, thanks and keep it up!
Client Side Decorations on linux please.
GK+3.12 Client Side Decorations suck big time and break both functionality and visual consistency in non Gnome 3 DEs so: No CSDs
It works great in a modern window manager.
Keep up the good work on Firefox
Great read, thanks for the updates!
Could you give an ETA and how much work is required for porting FF to WL. We are nearly there with most Desktop Environments and FF is one of (if not) the most important apps.
Thanks for your work. It is extremely important.
Nearly there? I haven’t seen a proper DE using Wayland flawlessly.
Oh, sure, it’s only been developed for 8 years, how can we expect it to run flawlessly after such a short period of developent?
Wayland will hit Linux hard and have a big destructive impact, but I am sure that’s well planned by Intel, RedHat, Gnome and Microsoft
Pingback: Firefox, Rewrittein In GTK+3, Almost Runs On Wayland | LinuxG.net
Please, no GTK3. It has lots of weird dependencies (including runtime daemons), and exceedingly ugly default themes (and other themes don’t work properly or break on updates), forces client side decorations (using ancient Motif hints, hilarious), and is all in all worse than GTK2, while solving no real problems.
If you want to do it for Wayland… well, Wayland will not be ready for another couple of years, and even then X emulation with XWayland works well enough. There’s no reason to switch.
If you want to put up some effort porting the GUI code, at least port it to Qt. It’s probably considerably more effort, but also has a considerable gain.
A lot of people, never written a line code apparently is very convinced qt is heaven and gtk is crap. Could it be for a a company with a operating system as product and has a lot of fan boys, is planning to switch to qt….
As someone who has definitely written a lot of code (not much GUI code though) I agree that there’s lots of awfulness in the Qt API, while the GTK API looks cleaner (even though suffering from the terrible OOP-in-C stuff and gobject, which must have been created by someone with terminal brain cancer). But for me as a user, Qt is definitely better.
>Could it be for a a company with a operating system as product and has a lot of fan boys, is planning to switch to qt….
Some kind of conspiracy theory? Which one?
Pingback: Les nouveautés de Firefox 31, 32 et 33 » MozillaZine-fr
Reading this description, it sounds like (NPAPI) plugins that link against GTK+3 would be unsupported, since there’s no way to tell ahead of time to load the GTK+ 3 version of the shim libxul?
There’s a lot of hate for plugins, but I think it’s misplaced. I’m no fan of closed binary plugins like flash, it’s a security disaster, but I do not see what exactly is the problem with open source plugins except for the horrible NPAPI ABI/API. Preventing new NPAPI plugins from using gtk3 without providing a new plugin interface would be unfortunate IMHO.
Being linked here from planet-debian, I read the stuff with interest, because I am a firefox-user, but currently I am neither using GNOME3 on Jessie-testing, nor the gtk3-firefox-version.
It seems I am not enough alpha-dog to do that, and I do not even know, whether gtk3-engines-xfce has anything to do with it or not.
It is probaly going to be a bit thrilling to see if Wayland manages to become the default in Debian before the Jessie-release happens. X11 has received great improvements like DRI3, so it’s not necessary in my opinion, but it would be a nice to have option.
So what is the latest status about this development? Can we get it to work if Flash is not installed?
Pingback: Firefox and GTK+ 3 | Dring Drong
Since the plugin container links to libmozgtk2.so which only has stubs for gtk3 symbols, does this mean that plugins that link against gtk3 would not work?
Pingback: Wayland: in arrivo il supporto per Mozilla Firefox e Cairo-Dock – Gda Tech
Pingback: Firefox, Rewrittein In GTK+3, Almost Runs On Wayland - LinuxG.net