And it was awesome.
Now, I know that I had originally told you that I’d be working on Thunderbird + Unity integration. That’s still on my TODO list, but today, I put some contributions in with the Firefox team for the upcoming Firefox 4 release. There are still a few bugs that need to be squashed before Firefox 4 is ready for the prime-time, and we’re all psyched to see it happen, so I lent a hand.
This was the bug I decided to tackle today. Basically, in the new add-ons manager, add-ons are listed alphabetically, regardless of their state (and by state, I mean enabled, disabled, incompatible, blocked, etc). This leads to kind of a strip-ey look for large numbers of add-ons.
What we’d like instead is to have the add-ons grouped by state, and then sorted alphabetically within that state. Here’s a mock-up by bug-reporter (and Firefox UX team member) Jennifer Boriss:
I got to work around 8:45AM this morning. Around 10:13AM, I had finished most of my introductions, had my tour, had my accounts set up, found my desk, and started work.
The first thing I did was locate where exactly the code was for listing the add-ons. Blake pointed out a particularly useful resource called MXR (Mozilla Cross Reference), which lets me search through the source code very quickly. I had originally been using grep, but this was way better.
My approach to finding the code: I find a string in the interface that seems unique to the area I’m working in (in this case, it was “Search all add-ons”, which is found in the search text input of the add-ons manager). I did a search for that string, and it returned the file mozilla-central/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd.
But this only takes us half-way. Since Firefox is translated, the strings are stored separately from where they’re used. In extensions.dtd, the string I searched for is given the key “search.placeholder”.
Searching for “search.placeholder” with MXR gives me paydirt: mozilla-central/toolkit/mozapps/extensions/content/ holds the files extensions.css, extensions.js, extensions.xul and extensions.xml.
So I tool around in extensions.js a bit, reading the developer documentation, and getting to know the code. The code contains quite a few classes, including something called gViewController. Digging deeper into it, it looks like gViewController controls (brings up, shuts down) the various “views” available in the add-ons manager. Cool – so now I just need to find the view that lists the user’s add-ons.
Ah hah! Found it: gListView. gListView grabs all of the installed (or to-be-installed) add-ons, and populates the interface. So this is where the sorting needs to happen. I tested to make sure I was in the right place in the code by using dump calls to a terminal. Bonus: edits in this portion of the code do not require a full browser restart – instead, I just close and reopen the add-ons manager to see my changes. Nice!
Initially, my idea was to have 4 “buckets”, one for each of the 4 states (“enabled”, “incompatible”, “disabled”, “blocked”). I’d divide up the add-ons into those 4 buckets, and then sort each bucket, and then join the 4 buckets for the final result.
Blake came up with a better solution: the Schwartzian Transform (straight out of Space Balls, I know). The idea is that, instead of having separate buckets like before, we just go through the entire collection of add-ons, and “label” them based on what bucket they belong to. Then we sort the entire collection, giving the bucket-label a high-order sorting priority. It sounds complicated, but it actually wasn’t that difficult to code. It’s a tiny piece of code, its readable, and quite elegant. So kudos to Blake for that solution.
Anyhow, I wrote my patch. I just figured out how to run the interface tests for Firefox (they use something called Mochitest). I set those tests off on one of the fast machines in the office, packed up my gear, and headed home.
It was a solid days work. Tomorrow, I hope to write some new tests for the Schwartzian transform, and submit my patch to Bugzilla. Woop!