One little button for Firefox: XUL is cool
Introduction
This post summarizes some of my findings while attempting to make a descent single-button Firefox extension. I’ve tested the code shown below with Firefox 1.5 and 3.0 under Windows, and Firefox 3.0 under Linux, and there were zero portability issues.
I would suggest reading a tutorial about toolbars and possibly Mozilla’s own tutorial about XUL before the notes below.
The magic
All I wanted was to put a little button on my Firefox browser. At some point I realized that I won’t get things working like I want unless I understand what I’m doing. So I dived into the thing called XUL.
I have to admit, that it looks terrible at first glance. I started to change my mind when I realized, that XUL is a format for describing GUI items. That my case of toolbar extensions is a very narrowminded one. To get an idea what XUL can do, just have a look on the so-called periodic table. But that’s really nothing compared with the simple fact, the all of Firefox’ GUI (menus, buttons, dialogs) is implemented in XUL and JavaScript.
But my the real enlightment came to me at page 391-392 of Programming Firefox. That’s where I realized that I should unzip the browser.jar file, which is exactly where one could expect to find it: In the Mozilla Firefox/chrome directory (where the application is installed, not where it puts its cache data etc.)
Also, unzipping classic.jar is useful to see the names of the image files used, so that the relevant place can be found easily in browser.jar’s files. It’s much easier to find the place at which the reload button is defined when its image file’s name is known.
Reverse engineering
Let’s investigate the reload button, then. It wasn’t too difficult to realize that its icon can be found in the classic.jar, in a file named Toolbar.png (find the directory yourself). Searching for that string in all of classic.jar’s files, the next clue was in browser.css (same directory as Toolbar.png).
Now, I won’t pretend to really understand what’s going on in that CSS file, and neither did I make a real effort to do so. All I needed was to come across a CSS definition like:
#reload-button { -moz-image-region: rect(0px 96px 24px 72px); }
If you’re not so good in CSS, that’s a definition for an object with ID ‘reload-button’. I wonder what that object could be…
So now I had my next clue: Look for reload-button in browser.jar’s files. Surprise, surprise, it’s in browser.xul. The button is declared as
<toolbarbutton id="reload-button" class="toolbarbutton-1 chromeclass-toolbar-additional" label="&reloadCmd.label;" command="Browser:Reload" tooltiptext="&reloadButton.tooltip;"/>
Which, to tell the truth, is not so interesting. What I’m really looking for, is the ID of the enclosing XML tag. Scrolling up a bit, I found it:
<toolbarpalette id="BrowserToolbarPalette">
This is all I could ask for. But what is a “toolbarpalette”, I asked myself. Google took me straight to Mozilla’s documentation, which spelled it out for me.
The aftermath is, of course, that there was no need for reverse engineering, since the documentation tells me exactly how to get the button at the desired position. On the other hand, I didn’t find that information before.
I see no point in telling the whole story of going back and forth from searching the jar files for strings, then trying Google and/or trying to squeeze in an element of my own. The bottom line is that once I understood how the XUL represents the GUI itself, it became fairly easy to find the right magic words.
So I’ll go on with the bottom line of how to put the button in some interesting places.
The skeleton
I’ll skip the framework, since it’s documented all over. You can always unzip any Firefox extension XPI file to get an idea of what should be in it.
I assume that we already have a Javascript file, testingbutton.js. In that file, we have a function called testing_doit(), which we want executed every time our button is pushed.
Basically, the XUL file has the following format:
<?xml version="1.0"?> <?xml-stylesheet href="chrome://testingbutton/skin/testingbutton.css" type="text/css"?> <overlay id="Testing-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/x-javascript" src="chrome://testingbutton/content/testingbutton.js" /> ... One or more element definitions come here ... </overlay>
The important magic word here is <overlay>. What it means is that we can add elements to existing GUI elements by using their ID. For example (shown in detail below), if I want to add an element to the toolbarpalette with ID “BrowserToolbarPalette”, I simply repeat its opening tag, and put my things there. This will not override the existing definition, but rather append new elements.
Note that any number of snippets from the examples below can be inserted to add several controls to the browser window.
And just before starting, here’s the CSS that comes along: Basically, it defines the image to use on the buttons, which are pinpointed through their IDs (using classes may have been more elegant?)
#Testing-Toolbar-Button { list-style-image: url("chrome://testingbutton/skin/logo.png"); } #Testing-Doit-Button { list-style-image: url("chrome://testingbutton/skin/logo.png"); } #Testing-Doit-Button2 { list-style-image: url("chrome://testingbutton/skin/logo.png"); }
In the toolbar (not)
I’ll start with a spoiler: The code below will add the button to the Toolbar Palette and not to the toolbar itself. In other words, after installing the extension, nothing will happen until the user manually puts the button in place. Not very impressive. I suppose there is a way to get the button there automatically, but given the alternatives, I didn’t bother to check how to do that.
Here’s the code:
<toolbarpalette id="BrowserToolbarPalette"> <toolbarbutton id="Testing-Doit-Button" label="Testing button" tooltiptext="Do it!" oncommand="testing_doit();" /> </toolbarpalette>
The only really interesting thing here is that the ‘toolbarpalette’ tag shares its ID with the one defined in browser.xul. That’s the point, after all.
In a toolbar of its own (ugly)
I’m showing this one, only because it’s popular in examples I’ve seen, and it turns out ugly for a single button. The code below creates a full toolbar, from left to right, and puts one little button in it. Looks pathetic. Makes sense if you have a lot of buttons (and users who love your application a lot).
<toolbox id="navigator-toolbox"> <toolbaritem flex="0"> <toolbarbutton id="Testing-Toolbar-Button" tooltiptext="Do it!" oncommand="testing_doit();" /> </toolbaritem> </toolbox>
Note that ‘toolbarbutton’ has an ID which is mentioned in the CSS file. This is how the graphical icon appears.
In the existing toolbar (bingo!)
Well, I’m not sure if this is exactly where you would expect it, but the code below puts the button at the rightmost position next to the toolbar the user drags bookmarks to. The purely logic place might have been next to the address bar, but the actual position is excellent. Code follows:
<toolbar id="PersonalToolbar"> <toolbarbutton id="Testing-Doit-Button2" tooltiptext="Do it!" oncommand="testing_doit();" /> </toolbar>
(By the way, I found the magic ‘PersonalToolbar’ ID simply by looking at browser.xul and trying it out. The name sounded promising, after all)
In the status bar (So cool!)
At the bottom-right corner, with minimal distraction:
<statusbar id="status-bar"> <statusbarpanel class="statusbarpanel-iconic" id="Testing-status-button" onclick="testing_doit();" tooltiptext="Do it!" src="chrome://testingbutton/skin/logo.png" /> </statusbar>
An entry in the context menu
For users who don’t like to travel much with their mouse (laptops?), we have the menu which pops up when you right-click. How to add an entry to the context menu is described here. Note that the executed script can get some info about what was right-clicked (it’s called a context menu, after all).
Anyhow, this is what I made of it:
<popup id="contentAreaContextMenu"> <menuitem id="Testing-menu-entry" label="Do it!" oncommand="testing_doit();"/> </popup>
Conclusion
This XUL framework takes some time to get used to, but it’s a fantastic demonstration of how an open-source project can expose its internals without needing to compile anything. Despite some difficulty, working with Firefox’ internals is far more enjoyable than its well-known counterpart. Which shouldn’t surprise anyone.
Reader Comments
Some pretty useful information is in here. Thank you dude
Very simple yet effective tutorial to get started with creating own firefox extensions. I really appreciate it.
Thanks,
You’ve answered a lot of questions for me with this entry. Thanks for documenting your experience.
Although I think writing XUL extensions like this has become a little dated, this post was super useful. Took me 30 minutes of googling to finally find your straight forward answer on adding to the context menu. Appreciate it.
Pair