Research and Development

Bringing HTML5 to the Desktop With AppJS

As we and many others are relying more and more on the Open Web Platform or HTML5 as more commonly referenced to. We want to bring some of that goodness to the our desktops too. With it we can utilize our current in house talent and existing code much more efficiently.

We decided to take shot at the new project called AppJS and try reimplementing Gnome’s good old menus with HTML5. Here we will take look on how AppJS delivered.

Background

Originally we planned to use Python, Qt and Webkit to build it like we did with Iivari. But some research showed that the best tool for the job might be The Chromium Embedded Framework which allows developers to leverage all the hard work Google and the Chrome team has done on Webkit instead of just using for example the Webkit widget from Qt. Wikipedia has a pretty convincing list applications using it which lead us to the AppJS.

AppJS

I think AppJS is best described as the bastard child of Chrome and node.js. In practice it is a node.js module which allows developers to create small browsers with just JavaScript.

1
2
3
4
5
6
7
8
9
10
11
12
var appjs = require('appjs');

appjs.serveFilesFrom(__dirname + '/content');

var window = appjs.createWindow({
  width: 640,
  height: 460
});

window.on("ready", function(){
  window.frame.show();
});

This would open up a chromeless browser window using a index.html from the content directory. This is just the beginning of course. Developers can communicate with browser code using DOM events.

Send event from node.js using dispatchEvent:

1
window.dispatchEvent(new window.Event("event-from-node"));

and receive it in the browser like any other DOM event with addEventListener:

1
2
3
window.addEventListener("event-from-node", function(e){
  document.write("got node event");
});

It’s brilliant how it reuses APIs already known to HTML5 developers.

node.js require in the browser context!

Now this is where things get really exciting or confusing depending on how you look at it.

When using the current master branch (e2ef58b872) of AppJS it exposes the node.js require function directly in the browser context. With the latest release, currently 0.0.19, you can do that manually. This means you can actually do var fs = require("fs"); and fs.readFile("./file.txt", ...); directly in the browser!

While this is quite impressive on a technology stand point I’m not too big fan of it. Why? Because this is very AppJS specific. The reason why HTML5 is so popular is because it runs just about everywhere. Writing apps with code like that won’t be able to run anywhere else but on AppJS. Using only the events for node.js api access would force developers to write operating system level code in abstract manner. Then it would be really easy to move the code to a real browser and just reimplement the event handlers.

I also have a more practical reason for not enjoying it too much. While this is a really easy way to give module system to client-side code which it really needs - it breaks others. We already use RequireJS for our client-side code and it just does not work with AppJS if there is already a require function in the global scope. Another practical issue is that some libraries which try detect whether they are in the browser or in node.js get confused by this. Luckily the AppJS developers are really responsive on the #appjs channel on freenode and they started looking for solutions to this after I mentioned this issue. For now we solved this by forking AppJS and adding an option to disable it.

Webmenu

So back to reimplementing Gnome menus. The target for this first iteration was just to reimplement the existing features of the menu. Nothing too fancy. It reads menu content from a json file and builds a menu from it. In future we plan to integrate some communication channels from schools back to us at Opinsys and a remote update mechanism for the menu content so that we and our customers can update the menu content without rebuilding the LTSP Ubuntu images.

If you want try it feel free to grab a deb package from the Webmenu Github repository’s downloads section. The package is bit hackish. It installs Webmenu to /opt/webmenu and adds couple executables to PATH. The package contains all the dependencies which cannot be found from the default Ubuntu repositories. That means it contains latest version of node.js, AppJS and bunch of other random node.js modules. But hey it should be easy to install at least.

After installation see usage.md on Github and menujson.md if you want to customize the menu content.

Webmenu itself is licensed under GPLv2+.

Conclusion

Overall I’m quite pleased with AppJS although it has some serious bugs, but that’s expected for project at this stage.

It’s nice to be able to use existing HTML5 and node.js skills and libraries to build desktop apps. I hope that AppJS developers realize that this is the most compelling feature of AppJS and work out the quirks with the require and do not go too crazy with AppJS specific features. One good example of this is that developers can use some existing web frameworks from node.js with AppJS. I hope they keep working on this aspect too. I’d love to be able to use various connect middleware extensions for precompilers and such.

Comments