Konqueror/Embedded: An Open-Source Web Browser For EmbeddedLinux Systems

by Simon Hausmann

The Konqueror/Embedded Project is a derivative of the popular KDE browser, Konqueror (http://www.konqueror.org/). The Konqueror/Embedded Project was created with the goal of providing an open-source and standards-compliant web browser and file manager for embedded Linux systems. Both versions of the browser are based on the Qt GUI Toolkit from Trolltech, as is the whole K Desktop Environment. Due to the portable nature of Qt, Konqueror/Embedded runs under Qt/X11 as well as under Qt/Embedded, which is a special version of Qt for embedded systems.

As with Konqueror, Konqueror/Embedded supports full HTML4, CSS1 and partial CSS2; JavaScript (ECMAScript 262); cookies; SSL; IPv6; and full XBEL-compatible bookmark support and management. Documentation, a FAQ and download links to Konqueror/Embedded can be found at http://www.konqueror.org/embedded.html.

Back in November 2000, when the project started, basically only two browsers were available for embedded Linux environments. The first one was ViewML by Censoft. It was, and still is, based on the old khtmlw-rendering engine from KDE version 1.X. At the time of its release ViewML was certainly the most advanced and smallest free browser available. Censoft ported the rendering engine to the FLTK toolkit, added a custom HTTP client implementation and wrote a small graphical interface around it. Today it is still one of the smallest browsers, but it lacks support for popular current web standards.

The other browser was Opera, a commercial product from Opera Software. Opera Software also based their Linux and embedded Linux-based browsers on Qt. While Opera is quite fast, it is not open source.

Therefore, the lack of availability of a free and standards-compliant web browser for embedded systems was the main motivation behind the Konqueror/Embedded Project.

The Initial Port

I am the developer on the Konqueror team, and this simplified my choice when deciding on a browser with which to work. The project started by toying around with the idea of stripping down the HTML-rendering component. I started to establish what the main goals and requirements of the project would be.

One static binary was needed, giving the user enough room to optimize the size considerably, without compromising features. Everything the user can access from the big browser should be available in the embedded browser as well. We also wanted to include a graphical interface optimized for small resolutions. Finally, we wanted to avoid forking the codebase of the relevant parts of KDE.

The goal of having one static binary is quite contrary to Konqueror's design. Konqueror has many components, with lots of shared libraries and external communication processes. The difficulty here was less about linking the sources together in one piece and more about making the code actually run in one process. This process had the potential to cut off one of the key features of Konqueror: the nonblocking user interface. That is, no network hangup should lock up the GUI. The solution here was to fork off the networking code (called I/O-Slave) at runtime and communicate with it through a pipe.

The most difficult task, however, turned out to be achieving the fourth goal: no fork of the codebase. A fork in an open-source project is one of the worst things that can happen. Knowing the speed with which the HTML-rendering engine and the JavaScript implementation develop, a fork would simply have been a nonsense decision, design-wise.

So I tried to find an approach that would allow me to use as much of the original sources as possible, without any modification, so I could easily update them to the latest development version. The search resulted in a fundamental design decision for the project: make the copying of the original khtml, javascript, ssl, etc., sources to the Konqueror/Embedded build process a part of the actual build process.

So it all started with the attempt to make this code compile and work. Of course only the really necessary sources are copied over. For a lot of classes, simplified versions have been written. There is no need to implement the level of generic functionality that code in kdelibs needs in order to support many hardware and software platforms, environments and standards. Quite a bit of code can be eliminated once one accepts the fact that it only needs to run inside an embedded environment.

An example of this reduction can be found in the JavaScript implementation, with support for a property-of-the-screen object called availLeft. It represents the left-most x coordinate on the screen, available for application windows. In KDE this value can be queried from the window manager using the NET standard. It is not necessarily zero but can be constrained by a panel or any other client changing the work-area geometry. In an embedded environment with, for example, a touchscreen running a limited resolution and applications always running on full-screen windows, it is safe to simplify this code to always return zero. This simplification, however, cannot be done by simply modifying the JavaScript implementation, as it is copied from the original KDE source tree. Any change to it would get lost the next time the build process starts. The actual code retrieves the values for this and related properties, such as availTop and availWidth, from a class called KWinModule. So I needed to write a class capable of doing what the original KWinModule class did. This new class is surprisingly simple, while still acceptable as a drop-in replacement. The only necessary method is the one and only method of returning the work-area rectangle, which contains the values for those JavaScript properties:

#include <qapplication.h>
class KWinModule
{
public:
    KWinModule() {}
    QRect workArea()
    { return QApplication::desktop()->rect(); }
};

A lot of code needed to be written, along with parts that needed a far more complex rewrite. For example, the cookie manager in KDE runs in a separate process, and it talks with the I/O-slaves--those are small processes doing only the I/O work for listing directories or retrieving files from the Web--over the DCOP (desktop communications protocol) interprocess communication mechanism. In Konqueror/Embedded these I/O-slaves also run in a separate process that is forked from the main process. It is not possible to use the real DCOP though, because it depends on the X11 ICE library. Independence from the X11 system is mandatory. Thus, a simplified version of the interprocess communication mechanism needed to be written. This version is specialized and limited to message exchange through pipes between the main process and each forked I/O-slave process.

Setting up Konqueror/Embedded

The basic steps to set up the software are similar to any other UNIX software:

  • Download the source package or check out the development sources from the public CVS repository (see the web site for links and more information).

  • Unpack source package using tar xzf.

  • Set your cross-compiler environment variables, QTDIR and QPEDIR. The latter is used for special integration into the Qt Palmtop Environment.

  • Run make -f Makefile.cvs if you are using a development snapshot.

  • Running the configure script (./configure), possibly with options for enabling or disabling certain features. Type ./configure --help for a list of options.

  • Run make and finally make install.

You should now have a working version of Konqueror/Embedded, just waiting for joyful embedded web surfing.

Case Study: Konqueror/Embedded on a Handheld

The Compaq iPAQ H3600 handheld is probably one of the most advanced handhelds available. It is also capable of running Linux. The machine runs on a StrongARM processor, has 32MB or 64MB of SDRAM (depending on the model), 16MB Flash ROM and a 12-bit touch-sensitive LCD display. It can communicate with the outside world through serial, USB, infrared or various other channels (including Ethernet) using an expansion pack.

The standard Linux setup on the iPAQ consists of the familiar distribution, which can be found at http://familiar.handhelds.org/. It provides a robust base system including advanced package management and the X Window System running Blackbox as window manager.

An alternative to running X on the iPAQ is the Qt Palmtop Environment or QPE (http://qpe.sourceforge.net/). QPE is primarily developed by Trolltech, the makers of Qt and is a collection of integrated applications that constitute a useful handheld environment. Among the applications available in QPE, one finds: Address Book, Date Book, File Browser, Text Editor, To-do List, games and much more. The QPE components all use Qt/Embedded to paint directly onto the Linux framebuffer and can send information to other components using a message exchange protocol built into Qt/Embedded.

Konqueror/Embedded can be cross-compiled for this platform and integrates seamlessly into the QPE. The integration is accomplished code-wise by making use of the QPE base library. For example, by making the application class inherit from the QPEApplication class, Konqueror automatically gains support for the QPE color schemes and styles. In addition, the QPE API provides access to the bar area at the bottom of the screen. This allows Konqueror/Embedded to display a status message temporarily, instead of wasting screen space with an additional status bar in the application window.

Also, if you configure Konqueror with --enable-qpe and have the QPEDIR environment variable set to the base QPE directory, then make install will automatically install into the QPE directory structure and will provide an icon and an entry in the QPE application menu.

In order to make pseudo links like ``mailto:'' in web sites that work with Konqueror/Embedded, it is possible to edit the file $installation_prefix/share/config/konq-embedrc and add external protocol-handling applications. This is an ini-style config file. Here is an example of what can be added:

[External Protocols]
mailto=mailclient
ftp=myexternalftpclient
...

In the case of a QPE installation, the mailto protocol handler is set to mailit, which is the QPE mail user agent.

The application indicated as external protocol handler gets executed with the full URL as argument on the command line. If QPE support is enabled in Konqueror, then a special function of the QPE API is used instead to launch the external application. This is because in QPE all applications are usually instantiated only once. So by using this magic function, called ``Global::execute( application, document )''--with mailit, for example--the framework automatically takes care of either re-using an existing mailit instance by bringing up its main window, starting a new composer or starting a new mailit process.

Internationalization

Konqueror's user-visible strings, such as in message boxes or menus, can be localized. You can make it show up completely with German messages, for example. The standard Konqueror/Embedded package does not ship with translations, but it is fairly easy to translate the software if you decide you want a translated browser on your platform. The basic steps are:

  • Enter the konq-embed/ directory in the source tree.

  • Run make messages. This will extract the translatable strings using xgettext, the GNU translation utility detected at configure time. The extracted strings are written to konqueror.pot, which is a standard PO (portable object) template for use with the GNU translation tools.

entry. If it doesn't fit, break it either before "existingmess.." or before "konqueror.pot".

  • If you already have a translation and want to update it to new messages without losing existing translations, then you can run msgmerge -o newmessagefile.po existingmessagefile.po konqueror.pot. More about this can be found in the GNU gettext manual at http://www.gnu.org/manual/gettext/index.html.

  • Now you can translate the PO file.

  • In order to make Konqueror pick up a translation, you have to convert it to a Qt message file, which has a binary format. You can convert a PO file into a so-called .qm file using the msg2qm tool. It is part of the Qt distribution and is located in the tools/ directory.

  • Copy the final .qm file for each language into the share/locale/ directory of the Konqueror installation prefix, and name it ``konqueror_<languagecode>.qm''.

  • Konqueror will pick up the right .qm file on the base of the LANG environment variable at runtime.

On the subject of which translation tool to use, I strongly recommend KDE's KBabel tool. You can find it at http://i18n.kde.org/tools/kbabel/. It's probably the most advanced GUI translation tool available, providing lots of options and aid for the tedious work of translating messages. Features include dictionary and translation database support for often-repeated translations.
Fine-Tuning the Package

The software provides many options for customization within a certain environment, most of which can be enabled or disabled using environment variables and options to the configure script. There are basically three major types of configuration flags: optimization for size (this usually means enabling or disabling certain features, like JavaScript or SSL), integration, window-system-specific switches and development flags.

When it comes to having a browser in a resource-limited environment, where the list of available web documents is also fixed (like in an intranet) you might consider disabling certain features. For instance, if you know that the sites you're browsing are always going to be located on plain HTTP servers and the documents are made of clean HTML with stylesheets, without any JavaScript, then you could make use of the --without-ssl and --disable-javascript configure switches. This can reduce the size of the resulting binary up to 30%.

If you want to run Konqueror/Embedded inside the Qt Palmtop Environment, setting the QPEDIR environment variable and specifying --enable-qpe at configure time will make it automatically use QPE features for a seamless integration. You can turn on the compilation options for using Qt/Embedded with the --enable-qt-embedded configure flag.

In the development phase you might want to turn on the debug output option using the --enable-debug flag. This also enables the -g flag on the compiler, for use with the GNU debugger. Also, specifying --disable-closure speeds up the process of linking the sublibraries. If you want to do some performance tuning, you might want to turn on profiling support for the GNU profiler (gprof) with the --enable-profile flag.

If you have an idea for a certain feature or how to optimize an existing option, and you feel comfortable with Qt and C++, then don't hesitate to get involved in the development. The project follows the rules of free software and lives on volunteer work. Development takes place in the KDE CVS repository and on the Konqueror/Embedded mailing list (see http://www.konqueror.org/embedded.html).

If you have access to an embedded Linux platform where a browser is missing, join the list, and let's see how we can solve the problem.

Simon Hausmann (hausmann@kde.org) is currently a student at the University of Erlangen, Germany, where he is working toward a Bachelor degree in Computational Engineering. In his free time he's a KDE developer and enjoys playing jazz on his saxophone.

Load Disqus comments