Blog-o! Notes from latte.ca

Fri, 28 Jun 2013

In my previous blog post, I mentioned a tool I’m writing to make it easy for designers to link mockups to live bugs. But I didn’t mention that I had a reasonably-working version of the tool written in Backbone which I’ve decided to port to Angular. The reasons why are largely beside the point of this blog post, but I’ll try to sum them up by saying that I reached a point where Backbone seemed to be confusing me more than helping me, and Angular got a lot of good press at FluentConf this year.

So this morning’s task in the re-write was to re-hook up the Persona integration. I had read recently that when you had a lot of dom-manipulation functions, you should probably put that code in a directive, and since I hadn’t written an Angular directive yet, I figured this would be a great time to learn how. Writing the html was pretty easy, of course, and most of the code from the existing implementation (which was largely based on the code from the express-persona readme) could be ported over fairly quickly. The only tricky part I ran into was figuring out that I needed to include restrict: 'E' in the Directive Definition Object. After I was done, I noticed that there really wasn’t that much in the code that had anything to do with the tool I’m writing, and thus I pulled it out into a separate repo so that other people can use it.

And with that, I announce Angular-Tools, a repo containing one or more tools which you might find useful if you build Angular apps. As always, pull requests and bug reports welcome!

[Posted at 15:16 by Blake Winton] link
Fri, 14 Jun 2013

One of the things I’m working on as part of my job1 at Mozilla is a tool to make it easy for designers to create mockups that are linked to live bugs, similar to the ones at Are We Pretty Yet. Now, I’ve got the background showing up, and the bugs overlayed on top of it, but as it stands, I’m requiring the designers to draw the lines connecting the bugs to the various areas in the mockup right on the mockup itself! This is obviously a fairly terrible idea, since it makes it much harder than it should to move stuff around after the fact, and requires a ton of up-front planning when creating the initial image. But what are my other options?

I thought for a while about layering a canvas element over the mockup; it would let me draw whatever shapes I wanted to, but passing the click events through to the mockup seemed like it would be fairly annoying, and I don’t think the connecting lines should appear in front of the boxes showing the bug details, which adds another wrinkle. Then, over lunch, I started to wonder what it would look like if a 1px by 1px black square got stretched and rotated with CSS… So I took some time after lunch, and played around a little, and it seems like it just might work! Give it a try, let me know if you have any ideas to make it better, and feel free to take the idea anywhere you think it might be useful!

Update: In the comments, Andrew points out that I could use a 1px by 1px span instead, which would make it much easier to change the colour of the line, so I’ve linked to his jsfiddle instead. :)


  1. Sometimes I still can’t believe how lucky I am to get to do this stuff all day, and get paid for it!  

[Posted at 14:57 by Blake Winton] link
Fri, 23 Nov 2012

For a while now, I’ve been having problems with my Firefox profile. To be fair, it’s mostly because of random about:config tweaks I’ve made, but still, not being able to test the new SocialAPI stuff was pretty annoying. So I decided to try resetting my profile, to clear out all the junk, and hopefully even make it a little faster.

But, as the page I linked to just up there mentions, resetting your profile will lose your open tabs, windows and tab groups, which kinda sucks, because I have 57 open tabs, in various groups, and I really don’t want to lose them! Fortunately, I’m a programmer, so I hacked on Firefox to get it to save and restore my tabs, and now I’m a happy camper!

A couple of days later, one of my co-workers had some similar problems, and also wanted to re-set his profile to try and fix them. I hadn’t saved the results of my hacking, so I had to re-create it for him from a combination of memory and the documentation. The new code I came up with looked something like this:

var x = gBrowser.tabs
var rv = "var tabs = [\n"
for (var i = 0; i < x.length; i++) {
  rv += '  "' + x[i].linkedBrowser.contentWindow.location + '",\n';
}
rv += '];\nfor (var i = 0; i < tabs.length; i++ ) {\n'
rv += '  gBrowser.addTab(tabs[i]);\n}\n'

To run it, first open about:config, and make sure the devtools.chrome.enabled preference is set to true (double-click it if it isn’t, and it should switch automatically), then go to the Tools » Web Developer » Scratchpad menu item, which should open up a small new window with some javascript comments in it. While that window is focused, click on Environment » Browser, to make sure that you’re running the code in the browser’s chrome (instead of in the page’s content). Paste the code in, and click Execute » Display.

That should result in a bunch of code in grey surrounded by /* and */ that looks like:

var tabs = [
"http://weblog.latte.ca/blake",
"http://breakingtheegg.tumblr.com/",
];
for (var i = 0; i < tabs.length; i++ ) {
  gBrowser.addTab(tabs[i]);
}

Copy that out of the scratchpad into your favourite editor, remove the /* and */, and run the profile reset.

Once you’re done resetting your profile, you’ll need to change the devtools.chrome.enabled preference to true again, and then re-open the Scratchpad, paste the new code you saved back in to it, click on the Execute » Run menu item, and shazam! All your tabs should be back (although they won’t be in their original tab groups. If anyone needs me to figure out how to do that, just let me know, and I’ll give it a try).

[Posted at 13:42 by Blake Winton] link
Sun, 22 Jul 2012

The side-project I’m working on is coming along nicely, and so I figured it was time to let other people see it. Now, I could just have everyone huddle around my screen, but since many of the people who would be interested aren’t in the same city (or even same timezone) as I am, that wouldn’t work out so well. We tried screen- sharing, but a lot of what’s being worked on is animation, and the frame-rates of the screen-sharing application we were using weren’t up to the task. To get around that, I could have recorded a video, but since a lot of the value of a prototype like this is being able to play around with it, that’s also not a great solution. So, obviously, the best thing to do would be to put it on a publicly available server, and let people run it in their own web browser, whenever they wanted!

Now, I’m running a server or two that I could put it up on, but since the project is related to Mozilla, and since Mozilla offers some personal webspace on one of their servers, I figured I might as well put it up there. :)

So, to make it easy for me to remember to build and upload the code (and to prevent me from trying to figure out all the correct options to rsync every time I wanted to upload the code), I took a couple of minutes to add a command to my volofile, which lets me merely type volo deploy, and have it optimize the code, and copy only the changed files to the remote server.

[Posted at 14:04 by Blake Winton] link
Thu, 12 Jul 2012

As a side-project, I’ve been working on a prototype which is heavily based on a demo page from Stephen Horlander. Now, that page is pretty amazing, but if you look at the source (using command-u or control-u in Firefox, and command-alt-u or control-alt-u in Chrome), you’ll see a lot of code that looks like this:

<div class="menuPanelButton subscribeButton">
  <div class="button"></div>
  <div class="label">Subscribe</div>
</div>

and:

<div class="customizeToolbarItem">
  <div class="customizeToolbarItemIcon share"></div>
  <div class="customizeToolbarItemLabel">Share</div>
</div>

Now, one or two of those would be fine, but when we get into more than that, the repetition really starts to bug me, and I think “Wouldn’t it be better if I could just write stuff like:

<panel-button type="subscribe">Subscribe</panel-button><toolbar-item type="share">Share</toolbar-item>

instead?” And it turns out I can, using a new library called x-tag! The first thing I need to do is register the new tags I’ll be using. That’s done with code like this:

// These first two lines are here because I’m using require.js, which I’ll
// talk about in a future blog post…
define(function (require) {
  require(["jquery", "x-tag"], function($, xtag) {

    // And this is the meat of the functionality.
    // First, we’ll register the new "panel-button" tag.
    xtag.register("panel-button", {
      onCreate: function(){
        var self = $(this);
        // When the tag is first seen, make the innerHTML be this stuff below.
        self.html("<div class='menuPanelButton " + self.attr("type") + "'>" +
                    "<img src='images/button-" + self.attr("type") + ".png'" +
                    "     class='button'>" +
                    "<div class='label'>" + self.text() + "</div>" + 
                  "</div>");
      },
    });

    // And then, we’ll register the new "toolbar-item" tag.
    xtag.register("toolbar-item", {
      onCreate: function(){
        var self = $(this);
        // We could also replace this element with the html below, but I
        // haven’t done that here because I haven’t needed to yet.
        self.html("<div class='customizeToolbarItem'>" +
                    "<div class='customizeToolbarItemIcon " + (self.attr("type") || "") + "'></div>" +
                    "<div class='customizeToolbarItemLabel'>" + self.text() + "</div>" +
                  "</div>");
      },
    });

  });
});

The second step is to replace all the old html with the new tags. (I did that, too, of course.) And there we go. That’s it. In the file I was modifying, the combination of that and moving the javascript out into a separate file took the html from 275 lines down to 146 lines, and let me more easily change the buttons around, and add new ones. I call that a win, and from now on, whenever I see large blocks of repeated html, I’m going to be seriously tempted to switch them to an x-tag!

One caveat I will mention is that in my first attempt, I tried to use both the content property, and the onCreate method, and that totally didn’t work, since the content would be replaced by the value of the content property long before I had a chance to muck around with it in the onCreate. So in the future, I think I’ll just jump straight into using the onCreate method, since it’s not that much harder.

[Posted at 21:39 by Blake Winton] link
Sun, 08 Jul 2012

Yesterday afternoon, I watched a video from James Long about Mortar, which is a template for making HTML 5 Open Web Apps. Now, coincidentally, I’m starting a new project (in my spare time, obviously, since it’s a Sunday), and while it’s not an Open Web App, I saw no reason not to use the same tools they were using.

Of course, since nothing’s easy, I ran into a problem pretty quickly. My problem was that every time I tried to require("jquery-ui");, I got an error of “ReferenceError: jQuery is not defined”. There wasn’t a lot of information about how to fix it, so after most of an afternoon mucking around, I finally came up with something that seems to work, and thought I would post it.

  1. Go into your www/js/lib directory.
  2. curl -O https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.js
  3. Edit the jquery-ui.js file. At the top add the line define(["jquery"], function (jQuery) {, and at the bottom, add the line });.
  4. That’s it. From there you should be good to go!

Now, I suspect there’s a better way to do this, and hopefully James or Bryan will jump in the comments and tell me what it is, but for now, at least this works.

[Posted at 18:14 by Blake Winton] link
Sun, 25 Mar 2012

I think what I want is pretty simple, or at least, reasonably common. I’m just looking for a couple of programs.

An SMTP server which will accept mail for the accounts at latte.ca, and deliver it to a Maildir of my choosing, and let me send mail through it if, and only if, I’ve logged in with the password to that account. (Being able to define a few aliases would also be nice.)

And an IMAP server which will expose the previously-mentioned Maildir, after I’ve logged in with the password to that account.

And yet, every time I try to set that up, something completely falls over for no particularly understandable reason, and I end up wasting an afternoon (or more) of my life. I had hoped this time would be different, since I decided not to install and configure everything myself, but instead bought a copy of OS X Lion Server which was supposed to do all the hard work for me. I’m not going to enumerate all the problems I ran into, but I will say that I still haven’t managed to get there. I’m just done for tonight.

Anyways, if anyone reading this has a working setup that meets the requirements (and the added requirement of needing to use Dovecot and Postfix, since those are what’s installed), I would love to get a copy of their config files. And in the meantime, I might seriously look into getting a refund for Lion Server, given how badly it’s failed me. :P

[Posted at 21:52 by Blake Winton] link
Tue, 06 Mar 2012

A few people recently asked me about building Thunderbird on the latest version of Mac OS X. Since I have it working, and to give myself a place to point to the next time they ask, I figured it would be a good idea to blog about it.

So, here’s my .mozconfig.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Debug .mozconfig
mk_add_options MOZ_MAKE_FLAGS=-j4
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/../objdir-`basename \`pwd\``-`hg branch`
# mk_add_options AUTOCONF=autoconf213
ac_add_options --enable-application=mail
ac_add_options --enable-extensions=default,inspector
ac_add_options --enable-inspector-apis

# Compilation options
ac_add_options --disable-optimize
ac_add_options --enable-debug
ac_add_options --enable-tests
ac_add_options --disable-jemalloc
#ac_add_options --enable-trace-malloc
ac_add_options --enable-chrome-format=symlink

ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.7.sdk
ac_add_options --enable-macos-target=10.7

# For NSS symbols
export MOZ_DEBUG_SYMBOLS=1
#ac_add_options --enable-debug-symbols="-gdwarf-2"

#Use ccache
#ac_add_options --with-ccache=/usr/local/bin/ccache

# We don't have GCC anymore, since XCode 4.2, so use clang instead.
CC=clang
CXX=clang++

There are probably a bunch of things I don’t really need in there, so if anyone wants to take it, and cut it down to the minimal set, I would definitely appreciate it. But in the meantime, this works for me, and will probably work for you, too.

[Posted at 10:34 by Blake Winton] link
Thu, 08 Dec 2011

Much of the new work I’m doing these days is being stored in git repositories. Now, I’m not the biggest fan of git, particularly its UI, but the advantages of GitHub and GitX are hard to ignore. Despite that, I still really missed being able to type hg out to see which patches I would be pushing, so, after a short chat with (and demo from) Ben, I came up with the following:

Somewhere in your path, add a file named git-outgoing which contains the following contents:

# !/bin/sh
# Uh, there shouldn’t be a space between the # and ! in the previous
# line, but the highlighter I’m using seems to require it…
git push --dry-run $1 2>&1 | awk '/^ / {print $1}' | xargs git log

(Make sure it’s executable by whomever needs to use it!)

Then, in your git config, add the following section:

[alias]
    out = outgoing

And finally, you should be able to type git out, and see something like:

commit 7d4c9b89a4663a07bed030669bae2d3c73ec78dc
Author: Blake Winton <bwinton@latte.ca>
Date:   Thu Dec 8 12:22:41 2011 -0500

    Blear 2

commit a4e8c6627bc26d7371fb2614a1c47aaf694957bd
Author: Blake Winton <bwinton@latte.ca>
Date:   Thu Dec 8 12:18:04 2011 -0500

    Bleah.

So, hopefully some of the rest of you will find this helpful, too, and if you know of a better way to do this, please let me know in the comments!

[Posted at 13:04 by Blake Winton] link
Tue, 27 Sep 2011

On a previous post in a different blog, some commenters were asking us if we were considering doing things that we have planned to do for a while now, and that led me to realize that I haven’t been communicating the future of Thunderbird’s UI nearly well enough. I mainly blame it on my trying to do too many other things, and thus failing to cover all the bases. So, having said all that, here is the list of things, in no particular order, that I would like to see worked on in the next few versions of Thunderbird. But first, I’ld like to say a little bit about why I want them.

I recently heard about someone who said “Thunderbird looks like iTunes”, and while that’s rather complimentary given the amount of time Apple puts into making things look good, it doesn’t really lead me to believe that people can pick our product out of a screenshot. And so one of the overall goals is to make Thunderbird iconic. You can always tell when a screenshot is of Apple mail, based on the layout and the lack of colour, and Firefox is similarly immediately recognizable because of the big circular back button and smaller rectangular forward button. Similarly, I’m hoping to have Thunderbird look different to other apps, while still fitting in on the platform, and maintaining a little consistency with Firefox. Of course, that’s not the only goal, nor even the main goal. My main idea for Thunderbird is to let you focus on the content that’s important to you, and not be distracted by things you don’t care about. Hopefully most of the changes I talk about here will help that, and as a side benefit also help to give us a more unique style.

  • A simple thing that will make the product nicer to use is just to line things up. We’re all over the place, and it should be fairly simple to make this better. There are a couple of bugs that are related to this, and I suspect we could file a few more for various other parts.

  • We want to put the tabs on top, because they let us put the compose and address book into tabs, while still having the appropriate toolbars. (As well, having everything be a tab makes the application more consistent, as described in the next point.)

  • This leads into removing the standalone Compose and Address Book windows. You’ll still be able to open a window for those functions, but it will just be a regular window with a Compose or Address Book tab. (No bugs for this yet. Removals are sensitive things, and we want to get the replacement UI working well before we remove the existing UI.)

  • We really want the Thunderbird button, so that we can hide the menus, and have less Glass on Windows, and make the most common actions easier to find and use.

  • But, to add that button, we first need to see what the most common menu items people use are, therefore we need Test Pilot.

  • We would like to add a HomeTab, to give people a personalized place to land when they start Thunderbird, or open a new window.

  • We would like to merge the Gloda bar and Quick Filter bar, cause duh.

  • Having two different settings locations is too confusing for me, let alone people who don’t care about the details of the product. We want to merge those into a single searchable place for all the settings, a la Mac System Prefs.

  • This next change is more a small, personal thing, rather than part of a grand plan. It was originally suggested by Mike Beltzner, and while I’ve had some time to work on it, I haven’t had enough to push it through to completion. Basically, I’ld like to be able to order my email by date, while grouping it by subject. (This is different than threading, because I don’t care about which replies are to which messages. I just want a single group for the subject, with the messages ordered by date within that group, and the groups ordered by the date of the most recent message.) There’s no bug for this yet, but as mentioned, I started to write an extension, before hitting some annoying bugs that made it hard.

  • Compactify the header. It’s really too big. Well, that’s a bit of a lie. What I really mean here is that we should move the buttons and their toolbar out of the header, to float just above it. This would allow people to easily turn them off (by removing the entire toolbar), and for those of us who like to keep them, it would make them more visually distinct. As an added bonus, in vertical mode, we could merge that toolbar with the other toolbars, to get something like the pictures of what Thunderbird could look like posted by Asa Dotzler.

  • And finally, I think we should remove the Migration Assistant. It was very useful in the 2.0⇒3.0 transition, but it’s been less and less useful as time goes on, and as people have moved more and more onto Thunderbird 3, and 4, and 5… (No bug for this one either, again, because removals are sensitive things.)

See all the bugs in one big list.

Many thank-yous to Alex Faaborg, and areweprettyyet for the code to link the bugs, and the basis of the styling to make them stand out.

[Posted at 11:02 by Blake Winton] link
Thu, 08 Sep 2011

Add-ons are an important part of many Mozilla products, and many people have noticed that they’ve taken a hit as we’ve switched to the Rapid Release process. To help users have a little more control over how well their Firefox works, I would like to propose the following slight modification to the automatic Update process:

It all starts when Firefox (and Thunderbird) notice an update is available.

We immediately check the user’s add-ons to see if they are compatible, or if there are compatible versions we haven’t downloaded yet.

If all the add-ons are compatible (or will be made so at the next download), we show the NoAddons dialog:

NoAddons dialog

It‘s the same as the current Firefox or Thunderbird update dialog, and as you would expect, the “Ask Later” and “Update Firefox” buttons do the same things that they do now.

On the other hand, if there are in-compatible add-ons, we show the Addons dialog:

Addons dialog

As you can see, we let the user know which add-ons are incompatible, and give the user an extra button at the bottom to do something different.

The new “Update when my add-ons work” button (wording to be clarified later) will check the add-ons periodically, and automatically update Firefox when all the add-ons are compatible. If the add-ons aren’t compatible after a week (period of time to be configurable), the user will be shown this dialog again, with the (hopefully smaller) list of incompatible add-ons.

Showing the user which add-ons are incompatible will let them decide whether the add-ons are important enough to not upgrade, or whether they can live with the (hopefully short) period of reduced functionality.

As always, comments welcome, but keep them polite or they’ll be deleted.

[Posted at 14:49 by Blake Winton] link
Wed, 15 Jun 2011

A friend of mine recently said:

EVERY behavior aspect of EVERY application should be user-settable if the user is prepared to drill down far enough. No exceptions. Even if the user will be shooting his own foot by messing with it.

I, obviously, disagree with him, and wanted to explain why in a few more characters than Twitter would allow.

While giving the user complete control over every aspect of an application seems like a good idea, there are two slightly-hidden downsides to it.

First, every choice you give the user doubles the amount of testing you have to do. (Okay, it doesn’t exactly double it, but it certainly adds a testing, maintenance, and support burden.) Is it a responsible use of your time to implement these options if less than 1% of your users will ever change them (and risk shooting their own feet), or would it be better for everyone to implement a feature that more people would use?

Second, Emacs notwithstanding, you’ll never get to a great text editor by customizing a mail reader. The whole Unix (and iOS, oddly) philosophy is to write each app to do one thing, and do it well. Not to do a whole bunch of optional things. And if you’re doing only one thing, presenting an option to the user to do it or not doesn’t make a lot of sense.

And finally, because I can’t count, if you offer people too much choice, it imposes a cognitive burden on them which can lead to their making no choices at all, or at least not making them any happier than when they had fewer choices.

To bring this back to the product I’m working on, we are going out of our way to make Thunderbird more usable and part of that is simplifying it by offering fewer, more meaningful choices.

[Posted at 10:13 by Blake Winton] link
Wed, 01 Jun 2011

One of the big questions I had when I started writing patches was who I should ask to review them. Now that I’ve been in the community for a while, I’ve got a much better sense of who I should be talking to for the type of things I’m likely to write, but there are still times when I want to make a change in a part of the code that I haven’t touched before, and I’m not sure who to ask. In those cases, I usually fall back to a fairly simple (if non-obvious) set of steps to try and figure out who to pick.

  1. Get the list of files I’ve changed.
  2. Get the hg log for those files.
  3. Check through the log for “r=”, and “sr=”.

Of course, that’s a fairly easy set of steps to automate, and so I present my first cut at the automated reviewer chooser!

Of course, there are a lot of things I’ld like to do with this, such as:

  • Improving the documentation.
  • Checking to see how well this script would have done on previous commits.
  • Taking into account the length of the queues for the reviewers.
  • Adding some sort of recent-ness calculations.

But I think that this tool is useful enough in its current state that releasing it and getting feedback on what to actually work on would be a win.

To use it, be in a mercurial source repo, and type getReviewer.py to get a list of suggested reviewers for the current differences, or getReviewer.py temp.diff or getReviewer.py https://bugzilla.mozilla.org/attachment.cgi\?id\=536017 to specify a different set of changes.

[Posted at 20:13 by Blake Winton] link
Thu, 31 Mar 2011
New GetAnAccount UI.

Since we released the GetAnAccount addon, we’ve had a lot of feedback. Many of the people who commented were looking for the option of getting an ad-supported account instead of paying for email access. We were always planning on integrating ad-supported services, as soon as we could, but of course, doing this required a redesign.

One important note before we get to the good stuff: I’ve used GMail soley as an example of a well-known ad-supported email provider here. We may or may not be partnering with them, and you should not take these screenshots as proof of our intentions one way or another.

As you can see from this first mockup, the initial view makes it much more obvious that you don’t need to create a new account just to use Thunderbird.

Initial View

If you click in the bottom half, it expands up to make it more obvious that that’s what you want to do, and to allow us to display more information (although we don’t have any extra information to display there yet.

Existing Address

On the other hand, if you click on the top, we do have more information that you probably want to see before continuing on.

New Address

And this is something like what we hope to show you when the results have been returned. (Note: the Terms of Service, Existing Account, and Do It Later buttons are still there, but have been scrolled off the bottom of the dialog in this mockup.)

Search Results

And finally, once you pick one of the providers, we expand that list to show you all of the results for that provider.

Provider Chosen

Feedback, as always, is welcome, either here or in the forum.

[Posted at 21:41 by Blake Winton] link
Fri, 25 Mar 2011

A co-worker of mine recently mentioned that he had a problem where he all-too-often accidentally quit his applications by hitting ⌘-q (command-q). Since he has been having problems with Thunderbird that I can’t fix, I thought I might do a little digging and see if I could come up with some way of helping him. And so here’s what I found:

In the System Preferences application, there’s a “Keyboard” section.

The Keyboard Preference Pane

One of the things you can choose in that section is “Keyboard Shortcuts”.

The Keyboard Shortcuts

Pick a relatively innocuous function, like turning Zoom on and off.

(Note: DO NOT choose Front Row for this!)

The Access Shortcuts

And assign that function to ⌘-q.

The New Shortcut

Now, whenever you hit ⌘-q, it will do whatever you selected, instead of quitting the application. Ta-da!

[Posted at 17:48 by Blake Winton] link
Fri, 25 Feb 2011

Over the past week, I’ve been working on fixing some of the reported bugs in the OpenSearch add-on for Thunderbird, and now I think I’ve fixed enough of them to release a new version.

You can find the full details on the Mozilla Labs blog, or you could just jump straight to the OpenSearch add-on page to install it. And please leave your feedback about the add-on on our Google group!

[Posted at 11:25 by Blake Winton] link
Fri, 24 Dec 2010

I was reading Making Software by Andy Oram and Greg Wilson, and got to the chapter about An Automated Fault Prediction System. It’s a pretty neat chapter, and it got me wondering which files in the Thunderbird code base had the most bugs. Now, I don’t have all the info I need, but I figured an easy first pass would be to go through the commit logs, and for each commit that started with “bug ”, add one to the files changed in that commit. Hmm, that sounded unintuitive. Let me just paste (and link) the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from mercurial import ui, hg
import operator
import re

ext = re.compile("(\.c(pp)?|\.js|\.xml)$")

repo = hg.repository(ui.ui(), ".")
changes = [repo[i] for i in repo
                   if repo[i].description().lower().startswith("bug ")]

master = {}

for change in changes:
  files = [f for f in change.files() if ext.search(f)]
  for f in files:
    master[f] = master.get(f, 0) + 1

files = master.items()
files.sort()
counts = master.items()
counts.sort(key=operator.itemgetter(1))
counts.reverse()
print "\n".join([c[0] + ":" + str(c[1]) for c in counts[:10]])

And so, without further ado, here are the files that have been changed the most in bug fixes, and the number of times they've been changed:

  • mail/base/content/mailWindowOverlay.js:109
  • suite/browser/browser-prefs.js:73
  • suite/browser/navigator.js:70
  • mail/base/content/msgMail3PaneWindow.js:69
  • mail/app/profile/all-thunderbird.js:67
  • suite/common/src/nsSessionStore.js:66
  • mail/components/compose/content/MsgComposeCommands.js:60
  • mailnews/imap/src/nsImapMailFolder.cpp:56
  • suite/browser/tabbrowser.xml:53
  • mail/base/content/msgHdrViewOverlay.js:52

As a side note, for the mozilla repo it looks like this:

  • js/src/jstracer.cpp:780
  • browser/base/content/browser.js:654
  • layout/base/nsCSSFrameConstructor.cpp:410
  • layout/base/nsPresShell.cpp:400
  • js/src/jsobj.cpp:399
  • browser/base/content/tabbrowser.xml:397
  • widget/src/windows/nsWindow.cpp:390
  • toolkit/components/places/src/nsNavHistory.cpp:374
  • js/src/jsinterp.cpp:345
  • js/src/jsapi.cpp:343
[Posted at 14:59 by Blake Winton] link
Sat, 04 Dec 2010

I’ve created a couple of checklists, and would like to hear any feedback on them. They are a Review Checklist, and a Commit Checklist.

They came about after I had been working mostly on experimental add-ons for a while, and then attempted to push a couple of reviewed fixes. Since I was out of practice, I managed to get something minor wrong on both of the pushes. (The first one failed to attribute the patch to the proper author; The second one failed to mention the bug number in the commit message.) Since I’m a bit of a perfectionist, this really annoyed me, and so I vowed to write up the steps that I go through when I need to commit and push a patch, so that I could refer to them later, since if checklists can save lives, then I figure they can probably also help me do my job better. But before I go to that, I needed to review a patch, so I wrote up some of the things I look for when I review a patch too.

[Posted at 19:49 by Blake Winton] link
Tue, 30 Nov 2010

I was recently modifying an add-on for the upcoming Thunderbird 3.3, and part of what I wanted to do was to run some javascript in a chrome context that added some DOM nodes to a document in a content context. But when I ran the following code:

1
2
3
4
5
6
7
8
9
let browser = document.getElementById('tabmail').getBrowserForSelectedTab();
let doc = browser.contentDocument;
dump("\n\n\n\nXXXXXXXXXX\n");
dump("DOM Content loaded for " + doc.location + "\n");
var topBar = document.createElement("div");
topBar.innerHTML = "We got it!!!!!";
dump("iB = "+doc.body.insertBefore+"\n");
dump("fC = "+doc.body.firstChild+"\n");
doc.body.insertBefore(topBar, doc.body.firstChild);

I got the following error:

WARNING: NS_ENSURE_SUCCESS(rv, rv) failed with result 0x80530009: file /Volumes/Devel/thunderbird/src-central/mozilla/content/base/src/nsNodeUtils.h, line 304
WARNING: NS_ENSURE_SUCCESS(rv, rv) failed with result 0x80530009: file /Volumes/Devel/thunderbird/src-central/mozilla/content/base/src/nsGenericElement.cpp, line 4077
-- Exception object --
[snip…]
+ message (string) 'Operation is not supported'
+ result (number) 2152923145
+ name (string) 'NS_ERROR_DOM_NOT_SUPPORTED_ERR'

Poking around a little, it seemed like I had reasonable things for the insertBefore method, the firstChild attribute, and the topBar variable, and so since it was late, and I couldn't see what I had done wrong, I went to bed.

That turned out to be a the best thing for me to do, because this morning Jonathan Protzenko came to the rescue, saying (in response to a similar problem with a Firefox 4.0 beta 7 extension):

If you're modifying some content DOM from chrome code, you need to make sure the child you're appending was created using the unprivileged document, not the global document.

// This is chrome code, this is wrong because the span is now chrome
// and you're trying to insert it into content
myContentNode.appendChild(document.createElement("span"))

// This is right, appending a content node to another content node
myContentNode.appendChild(myContentNode.ownerDocument.createElement("span"))

I've hit this issue at least three times when upgrading stuff for Gecko 2.0. Might be what you're looking for .

And sure enough, when I changed var topBar = document.createElement("div"); to var topBar = doc.createElement("div"); , it all started working beautifully.

Thank you, Jonathan!

[Posted at 10:58 by Blake Winton] link
Sun, 17 Oct 2010

This morning a friend mine tweeted that even with a bunch of high-quality newspapers around him, he was ignoring them in favour of reading twitter.

Earlier this month, I was reading Clay Shirky’s “Cognitive Surplus”. One his assertions is that it was largely a historical accident that people used to passively consume media, and now that people can produce things just as easily, we’re going to see an explosion of “participatory culture”, as they use those products to socialize with each other.

For some reason, this morning those two ideas really came together in my mind, and it hit me that messaging on the internet is going to be huge. Like, really, really huge. Even bigger than you think. And I believe that it will end up going one of two ways.1

One of the two futures I can imagine is full of places like Facebook, where you can only communicate with people who are on the same service as you, and every service is trying to own your online identity. I’ve lived in that environment with instant messaging clients, and I’m not a huge fan. Having to check five or ten different websites is almost as much of a pain as having to run five or ten different instant messenger programs. (Or having the one multi-protocol client frequently lose service on one or more of the networks when the provider decides to cut them off.)

The other is one where all the services can interoperate, and you can communicate with all your friends, relatives, and co-workers from a single program which will go out and get the messgages, sort them, collate them, maybe even rank them in terms of importance, or do a million other things that I can’t even think of. A world where if one messaging service provider decides to cancel your account for some reason, you’re not cut off from the people you knew there, and you still have all the images you uploaded, and messages you posted, and can send them all to a new provider, without losing anything.

That second world is the one I want to help make happen, and I’m very fortunate that people are paying me to do just that. I’ll stop talking now, but only after saying that you can help, too.


  1. Well, to be honest I think it’s far more likely to be some combination of those two futures, and perhaps some other things that I can’t predict. Stuff rarely ends up as just one thing or another.  

[Posted at 12:09 by Blake Winton] link