Mozilla ain’t easy
I’ve been making some progress on the web control I started some time ago for System.Windows.Forms. I took a little break to wait for the 2.0 release to stabilize the API and make it easier to link an existing build of Mozilla rather then do the pre-mozilla 1.8 method of embedding by forking the entire tree and building everything in you need into your build. In theory it should be possible to link the libxpcom from any Mozilla product based on 1.8 or newer. In practice its not as easy as it sounds.
In order to use the components in Mozilla (using C++) you need to have an interface that represents that class that you use to cast to the instance you get back from XPCOM’s CreateInstance function. (Whats neat is that what it returns you could be anything, including your own instance, a proxied instance from where else, or even reference to a common singleton instance of that class.)
The problem is getting the interfaces on a clean build against the flavor of xpcom you are using with whatever Mozilla product you want to use to develop off of. You can do that by using the IDL tool in Mozilla (xpidl) against the IDL file of the component you want to use. Unfortunately that usually requires you first build the source of the Mozilla product to get the IDL files and the xpidl tool. Some Linux distros package a weird “devel” package which contains the xpidl tool and the IDL files generated when they build the Mozilla product. There is nothing in any Mozilla documentation that I know of that says thats ok or even recommended thing to do. All I’m aware of that is recommend is the Gecko SDK which contains all the headers and IDL files you need as well as standalone xpidl tool. However that tool was stopped after Mozilla 1.7/Firefox 1.0. It wasn’t until recently a new version of the Gecko SDK began to get built again but as part of the XulRunner project. Right now the Windows and Mac versions are broken however because they missing dependencies for their tools (libidl 6.x and glib 1.x)
The other downside is that there are also lots of unfrozen APIs in Mozilla and they change from product to product a lot. That means a lot of #ifdefs and testing on my part to work out all the kinks. For now I’m sticking to Firefox 2.0/Seamonkey 1.0/XulRunner 1.8 api only for now (they all are based of the same branch of the tree).
What I’m thinking about doing is generating the headers with the xpidl tool and including them in the source with instructions on how to rebuild them yourself if you wish not use the included (or in case they change or are different in your case). At least until the new Gecko SDK stabilizes, I think its an ok work around for now then having everyone download and build mozilla just to get the headers to build this library (thats a lot to ask since a Mozilla build can take a few hours doing it from scratch).
The reason why gtkembedmoz is so nice is that its a standard part of every linux build of mozilla and firefox built the normal build process. For that reason it can access internal classes that are not exposed to external developers that link into XPCOM (at least not without hacking). All the public apis are frozen and there are no dependencies to any mozilla headers in the gtkmozedmoz headers. It’s nice and portable and makes it very easy to embed with GTK+. Unfortunately it doesn’t make it easy to just simply copy gtkembedmoz code and make a version that can run dynamically linked against Mozilla. Not to say it wouldn’t be impossible to make standalone gtkembedmoz.
There is a lot of code to go through in order to make it work right in every respect. DOM support is possible as well (the Mozilla activex control guys pull off mimicking Microsoft’s IHTMLDocument interfaces in COM since they work as a drop in replacement for Microsoft’s IE Active Control so I might be able to leverage some of their work).
The great part is that little to none of the actual backend binding library is not tided directly to Mono. It simply just exposes a simple basic C api to embed Mozilla that I p/invoke. For that reason it might be useful in the future for other projects doing similar things to share the same backend that I’m using, like, for example, WxMozilla or Epiphany/Galeon (if they wanted to move off of gtkembedmoz so they could things like use the editing interface). It would be nice since we could all maintain a single library that could keep up with the breaking changes of Mozilla to maintain the same basic API to the backend. That’s just a though I had (that probably might not ever be realized) but I might was well not limit the code to preclude the possibility. Its unlikely but maybe someday down the road, Mozilla could embed the library I’m developing into their normal build. Who knows
You can see the planning and research I did before here on the Mono wiki.
Tags: Mono & .NET, Personal