Last week I decided to try my hand at contributing my first patch to the Mozilla source code repository, and I thought it might be useful to chronicle what went into it, as well as what I learned from the process.
This particular contribution was actually motivated in part by a blog post by Mike Beltzner on the need for Mac-specific improvements to Firefox 3, and also by my own work on the Mac port of open-source Enso.
The functionality that Firefox—and, I believe, any Mozilla-based software like Thunderbird—currently lacks is the ability to import and export clipboard and drag-and-drop content in HTML format. What this means in plain english is that, for instance, if you copy “this text” from Firefox and paste it into Mail.app, it gets pasted in as merely “this text”, losing the hyperlink and the bold formatting.
Not only was this inconvenient from an end-user standpoint—Safari and other native OS X widgets deal with this situation fine, as does Firefox on Windows, so it’s entirely expected behavior—but it also prohibited some of Enso’s more interesting commands like map and tex from working with Firefox on OS X. So I thought fixing the problem would be a fun way to get my feet wet with the Mozilla source code, as well as a way to get a first-hand understanding of how the code contribution process works in the Mozilla community.
It should first be noted that before I could embark on this quest, I first had to get the source for Mozilla and figure out how to build it, which involved obtaining a basic understanding of how its build system actually worked. I chronicled this back in January with A Simple Mozilla Build Script and Tutorial.
Having set this up, I first asked Myk Melez who I should talk to about fixing the bug. Myk sets at a desk opposite from mine, which makes it really easy for me to completely derail his train of thought with questions like “so, who would I talk to if I wanted to fix this HTML clipboard bug on the Mac?” and “what’s the best Mexican restaurant in Mountain View?”.
Sorry about that, Myk.
In response to that first question, though, Myk told me to talk to Josh Aas, an OS X Mozilla engineer who lives in Philadelphia. I emailed him, and he promptly (and I mean promptly) replied to me and told me exactly what files to look at in Mozilla’s behemoth of a source code tree. Which was extremely helpful.
After browsing the source files for a bit, I had a decent idea of how to proceed, but the first thing I wanted to do was figure out how to display and add logging messages, so that I could easily see what code was being executed. This turned out to be an entire sub-quest in and of itself.
The Logging Sub-quest
My logging sub-quest started by asking Dan Mills—who sits next to Myk and is another hapless victim of my inane questions—how to do it. Dan wasn’t entirely sure, but he told me to check out this page on HTTP debugging for some leads. The clues I needed were there; enabling logging in the Netscape Portable Runtime appeared to involve setting two environment variables like so:
bash$ export NSPR_LOG_MODULES=nsHttp:5,nsSocketTransport:5,nsHostResolver:5
bash$ export NSPR_LOG_FILE=/tmp/log.txt
Except I had to figure out what the name of the module was that I wanted to log to. After trying out a few educated guesses—the name of the directory my source files were in, its parent directory, et cetera—I basically decided to do an Mozilla Cross-Reference search on sCocoaLog, which was the name of a variable used by one pre-existing logging statement in the source file I wanted to edit. This ultimately led me to a line of source code that mentioned the code sCocoaLog = PR_NewLogModule("nsCocoaWidgets"); there was my answer.
Once I had seen my first logging message actually get written to my logfile—and I have to admit that I actually got a really small surge of adrenaline from seeing this—I then had to embark on another sub-quest, which is one I’d never considered before.
The Makefile Sub-quest
As mentioned in my blog post on Mozilla’s build system, Mozilla uses a system of makefiles to build itself. What this means is that if you change or add a single line in Mozilla’s several million lines of code, you just type make and the build system automatically figures out the smallest amount of work it has to do to make a new program that incorporates your change. Now, with any previous project I’ve worked on, whose codebase was well under a million lines of code, the process of “figuring out the smallest amount of work to be done” is fairly quick—only several seconds at most. With Mozilla, though, it took several minutes, which meant that my compile-test-debug-recompile cycle was going to be really long, despite the fact that the actual amount of work (compilation and linking) being done in the compile phase was quite low. I had to short-circuit this process of figuring out what to recompile and just tell the Mozilla build system what to actually compile.
Ordinarily, as the Mozilla Build FAQ says, this would be done by simply giving make the name of the directory containing the source file I had changed. Through trial and error I learned that the code I was changing actually required a two-stage build; by investigating the full output of a standard make, I determined that the command I actually had to use to rebuild Mozilla was this:
make --directory=widget/src && make --directory=toolkit/library
Thankfully, this build command only took a few seconds to execute.
Actually adding HTML clipboard and drag-and-drop functionality to Mozilla was pretty easy, thanks in part to what I’d learned about Cocoa programming from porting Enso to OS X in December, as well as the invaluable Mozilla Cross-Reference and a blog post on nsITransferable. Once I submitted bug 428096 and my patch for it, Josh did some very vigilant review, noticed some very bad mistakes on my part, and eventually approved the patch once I fixed them.
What I Learned
Let me give you some background.
I’m an only child, and until fairly late in my childhood, I was always one of the only people I knew who was really interested in computer programming. I never had a mentor in this field, so virtually everything I learned was from books and experimentation; it’s unsurprising, then, that I grew up having a strong affinity towards software and development tools that were really well-documented and easy to use on one’s own. This is a big part of why python is my favorite language.
Beyond that, though, there’s also the hacker mantra of “RTFM”, or Read the Fucking Manual, which, while not feedback that I’ve ever given anyone, is nonetheless something I’ve always asked myself before seeking help on a topic. Self-reliance, in other words, is so entrenched in the programming community at large that it’s considered something of a faux pas to ask a question that could be gleaned from experimentation, doing some web research, or reading a book. Since I can discover the answer to pretty much anything on my own through these means—provided I have enough time at my disposal—I rarely ask coding questions in public areas.
What has struck me most about Mozilla since I’ve joined is its unrelenting focus on the concept of community. The thing I really learned while writing my patch was that, through their actions, the people I’ve met in the Mozilla community actually actively encourage inquisitiveness. They constantly ask each other questions; if they know the answer to something, they say so, or they say where the answer can be found, or they say who else in the community might know the answer, or they admit that they have no idea whatsoever. They never say “RTFM”.
Perhaps this openness is simply an extension of the community’s general spirit, or perhaps the community members understand that everyone is a “noob” in some sense because no one single person could possibly be intimately familiar with every component of this enormous project. Whatever the rationale, while I’m not particularly fond of the amount of pre-requisites and knowledge it takes to get to the point of really “getting things done” with the Mozilla codebase, and while the lack of up-to-date documentation for some areas of the source is certainly less than perfect, I am immensely grateful to the developer community for being as helpful, patient, and polite as they are.