Bounding Unicorns

How To Patch Firefox

One of the fundamental principles of firefox that led to its success was the fact that much of the browser was written in a high level and highly dynamic language, i.e., Javascript, with XML added for good measure. This is what permitted easy development of extensions - if the browser is already written in Javascript, it is simple to expose hooks to extensions also written in Javascript. Other browsers required extensions written in C or C++ which took orders of magnitude more effort.

Even as firefox focuses more on "less technical" users, often frustrating the more technical users in the process, its UI is still written in Javascript and remains relatively accessible to various tweaks.

This essay will follow the path of a typical change that has no pref for it and thus must be done in source, but - because it is a UI change - can be done in Javascript. It does not require recompiling firefox. Let's get started!

The change I want to make is to restore the old tab bar behavior when tabs are closed, where the remaining tabs expand to fill the tab bar width. In current firefox releases the tabs do not expand immediately but only when the mouse cursor leaves the tab bar.

There is no preference to obtain this behavior, however after searching the web I located this bugzilla bug which has the code that was committed to firefox to go from old to present behavior. We are going to undo this change.

Under "attachments", there is a link to the most recent version of the patch. I will call this the original patch. To undo the change I will make what I will call the nullifying patch. An important characteristic of the nullifying patch is minimal size - as firefox continues to evolve, its code changes, and minimizing the patch size is a good strategy to keep the patch applicable to newer versions. Some good strategies to use to minimize patch size are:

  • Inserting a return statement into a function to prevent the remainder of the function from executing;
  • Adding block level comments (/* ... */).

The result is addition of three return statements in each of the three functions added by the original patch. Here is the nullifying patch.

Now that we have a patch, we need to apply it to our browser. Javascript and XML files are typically located in jar files, which are zip archives with the jar extension. There are a few ways of finding these files on your computer. A good starting point is locate command:

% locate jar |grep jar$

Since I use Debian GNU/Linux, my browser is called iceweasel rather than firefox, therefore my jar is located at /usr/share/iceweasel/browser/chrome/browser.jar.

Another option for Debian-based systems is to check files installed by firefox and related packages:

% dpkg -L iceweasel
% dpkg -L xulrunner-24.0

If on your system all of the browser's files are located in a single directory, rather than scattered throughout the filesystem, you can grep the directory for the file name of the file you are trying to patch:

% grep -r tabbrowser.xml /path/to/firefox/install

Note that you should grep for the file name rather than file contents because the contents may be compressed whereas the file name will not be.

Assuming you have located the jar which contains the desired files, the rest is straightforward:

% mkdir /tmp/work
% cd /tmp/work
% unzip /usr/share/iceweasel/browser/chrome/browser.jar
% wget
% patch -p0 <firefox-24-resize-tabs-immediately-on-close.diff
% rm firefox-24-resize-tabs-immediately-on-close.diff
% zip -r browser.jar .
# cp /tmp/work/browser.jar /usr/share/iceweasel/browser/chrome/browser.jar

The last command needs to be run with superuser privileges, naturally.

Restart your firefox and enjoy a browser that is more one with you!