Mossop Status Update: 2011-01-21

Done:

  • Changed Feedback distribution with beta 10 to be a user controlled add-on
  • General shepherding of blockers wherever possible
  • Wrote up a useful code snippet for restartless add-ons
  • Landed startup time measurement reporting

Next:

  • Write a new code snippet every week
  • See what traction is possible on the add-ons manager softblockers

Playing with windows in restartless (bootstrapped) extensions

Lots of people seem to be playing with the new support for restartless extensions (also known as bootstrapped extensions) coming in Firefox 4. Nothing could make me happier really. I’m not sure I can remember ever helping implement something which is will hopefully turn out to be a game changer for extension development in the future. The technical details of restartless extensions are talked about in a few places but one thing that is missing is what I think is probably going to be the most common code pattern in these extensions.

When you’re developing an extension it’s almost certain that you’re going to want to interact with the main browser window in some way. With the XUL based extensions this was a pretty simple process, normally your extension would be overlaying browser.xul and so any script you add there would automatically run for every new browser window and would have direct access to it (in fact this sometimes confused new developers who assumed their script would run just once and be globally available, not for every browser window opened).

In restartless extensions things are different. You have one script that runs when your extension is started and runs in its own sandbox so you have to take steps to get access to windows. Complicating matters your extension may be started when Firefox starts up and there are no browser windows or after when some already exist. The best way to go is when your extension is started to look for any existing browser windows and make your necessary modifications and then wait for new windows to open and modify those too.

Since this is such a common case (and vlad was trying to figure it out on IRC) I put together a very simple bootstrap script that just does this. It calls the setupBrowserUI function for every window that needs to be initialised by your extension and tearDownBrowserUI for every window that must be cleaned up when your extension is being disabled. This code isn’t the only way to do all this but it is fairly straightforward and works, feel free to take it and modify it for use in your own extensions. I’ll probably get it put onto MDC too.

const Cc = Components.classes;
const Ci = Components.interfaces;

var WindowListener = {
  setupBrowserUI: function(window) {
    let document = window.document;

    // Take any steps to add UI or anything to the browser window
    // document.getElementById() etc. will work here
  },

  tearDownBrowserUI: function(window) {
    let document = window.document;

    // Take any steps to remove UI or anything from the browser window
    // document.getElementById() etc. will work here
  },

  // nsIWindowMediatorListener functions
  onOpenWindow: function(xulWindow) {
    // A new window has opened
    let domWindow = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDOMWindow);

    // Wait for it to finish loading
    domWindow.addEventListener("load", function listener() {
      domWindow.removeEventListener("load", listener, false);

      // If this is a browser window then setup its UI
      if (domWindow.document.documentElement.getAttribute("windowtype") == "navigator:browser")
        WindowListener.setupBrowserUI(domWindow);
    }, false);
  },

  onCloseWindow: function(xulWindow) {
  },

  onWindowTitleChange: function(xulWindow, newTitle) {
  }
};

function startup(data, reason) {
  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
           getService(Ci.nsIWindowMediator);

  // Get the list of browser windows already open
  let windows = wm.getEnumerator("navigator:browser");
  while (windows.hasMoreElements()) {
    let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);

    WindowListener.setupBrowserUI(domWindow);
  }

  // Wait for any new browser windows to open
  wm.addListener(WindowListener);
}

function shutdown(data, reason) {
  // When the application is shutting down we normally don't have to clean
  // up any UI changes made
  if (reason == APP_SHUTDOWN)
    return;

  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
           getService(Ci.nsIWindowMediator);

  // Get the list of browser windows already open
  let windows = wm.getEnumerator("navigator:browser");
  while (windows.hasMoreElements()) {
    let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);

    WindowListener.tearDownBrowserUI(domWindow);
  }

  // Stop listening for any new browser windows to open
  wm.removeListener(WindowListener);
}

Mossop Status Update: 2011-01-14

Done:

  • Fixed a small memory and information leak
  • Kept reviews and noms down at zero
  • Multiple blockers fixed
  • Triaged hard/soft blockers
  • Came up with a better plan for Feedback extension distribution

Next:

  • Look at some intermittent failures
  • Close out all remaining add-ons manager hardblockers and then delve headlong into the other Toolkit/Firefox blockers.

Mossop Status Update: 2011-01-07

Done:

  • Reviewed patches for the Feedback extension
  • Landed a number of blockers including progress notifications for add-on downloads and support for the add-ons marketplace
  • Reviews and feedback for all!
  • Add-ons manager blockers are now down to 22

Next:

  • Look at some new test failures that have sprung up
  • Figure out how to test a leak fix
  • Check up on the state of all assigned EM blockers
  • Assign owners to all remaining EM blockers

Sad news today

As I blogged yesterday, today Ripley got a CT scan and biopsy of the mass that is growing in her left shoulder. The biopsy results won’t be back for a few days but the CT results were really all that were needed to confirm our worst fears. Ripley has cancer and it’s large and aggressive.

We got to look at the CT scan and it was frankly terrifying how large this thing is. In certain cross sections it looked to be taking up a full third of her body and it curves all down her left side and up over the top of her spine. It was taking up the contrast solution they inject which means blood is running through it. This both increases the odds of it spreading and makes it much more difficult to remove. In short, there is basically nothing we can do at this point.

In one respect the diagnosis left me a little relieved. I had pretty much prepared myself for the bad news and at least we don’t have to make a horrible decision between paying lots of money for treatment which would could itself cause her a lot of suffering with an unknown chance of success.

Thankfully, at least right now, it doesn’t bother her at all aside from a slight limp. She is in no pain and is still active and playing. The doctors said though that we probably have a couple of weeks before it starts to effect her quality of life. All we can do is try to enjoy the time we have left with her and watch out for when she starts to be in too much discomfort. To that end we let her sleep off the drugs this afternoon and then curled up on the couch to watch a movie this evening, with a few drinks to help soften the reality.

Kontemplating Kitteh Katastrophe

Well that’s certainly a nicer way of saying that you’re trying to work out just how to decide how much money and trauma it is worth putting your cat through to keep her alive.

Just before we flew home for Christmas (yes, that flight) we spotted a small lump on Ripley’s left shoulder. We rushed her to the vet’s fearing the worst but they allayed our fears, finding it was just a blood filled space, likely the result of a trauma (though what we couldn’t fathom) and blood tests showed no irregularities. They said it should shrink over the course of a few weeks. We had to put her up at the boarders while we were travelling of course but we managed to put it out of our minds and have a good trip with family.

After we got back the lump was clearly larger than it had been before we left and so we rushed back to the vet to get a second look. They were very concerned, the lump was now feeling mostly solid and spread over a large area under her shoulder blade. Although tumors in cats this young are rare they can still happen for a number of reasons and though they weren’t sure they weren’t suggesting any other options really. They couldn’t do any further diagnosis there, we had to get a surgical consult. The surgeon had basically the same opinion but wanted to do some more tests before suggesting a treatment.

Tomorrow Ripley is booked to go in for a CT scan and a biopsy to try to give a final diagnosis. This will cost us around $2k and I have to admit to feeling very conflicted. I hate to say it but a part of me is questioning how much money I’d be willing to spend on getting her healthy. If $2k is just the diagnosis then I dread to think how much the treatment could be. To complicate matters we were considering giving Ripley away to a new family as she does not get along with our first cat and they are both basically stressed out while they are living under the same roof. How much money is it worth spending on a cat that you’re thinking of giving away anyway?

I love her very much and don’t want to lose her for any reason so it feels very callous of me to be thinking like this. I guess tomorrow we’ll get some answers and have some hard decisions to make.

Shooting fireworks on New Year’s Eve

There are many blog posts on the subject of how to best set up your camera to shoot fireworks but I was so surprised at just how well it worked out for me that I thought I’d add mine to the pile. Also I wanted to make sure I remembered what I did right and wrong here for next time I try. You’re going to need three things really:

  1. A camera that is up to the job. Perhaps surprisingly you don’t need a full SLR for this, but you do need something that will let you manually adjust the aperture, ISO and exposure times. Shooting in RAW is vastly preferably. I was using a Canon Powershot S90.
  2. A basic tripod. Exposure times will need to be long so you won’t be able to manually hold it steady and you’re shooting upwards so not much other than a tripod will do the job.
  3. Lots of luck. How much really depends on the fireworks display. The longer it is the more time you’ll have to refine your timing and aim. In my case our display was at home one with just 4 fireworks going off, ridiculously I managed to get the setup pretty much right first time.

The basic setup is straightforward. You want a small aperture, apparently somewhere in the range of f/8 to f/16 is golden, my camera limits at f/8 though so that is what I used. You want a fairly low ISO value too, I shot at 100. In an ideal world you’ll want a camera where you can manually hold the shutter open for however long it takes the firework to fire off. I didn’t have that though so instead I just manually set an exposure of 10 seconds which I figured was a long enough to capture a full rocket. Then set up on the tripod, point in the direction you think the firework will go and hope. Remember that fireworks go quite far and your camera will probably capture a decent area of the sky so chances are you’ll get it in frame, whether it is way off to one side is pretty much luck the first time though.

I was astounded though that the first shot I got was pretty much perfectly framed. I started the exposure on a 3 second timer triggered just after the fuse was lit. This meant the exposure started shortly before the rocket went off. In retrospect it might have been easier to just do a longer exposure, the timer adds an additional variable into the guesswork that is really unnecessary. Still I managed to capture the launch of the rocket and the initial explosion. A longer shot might have captured more of the explosion but then I’m pretty satisfied with what I got. This is after some additional processing (this is where shooting in RAW becomes really important):

Although with no processing at all the shot showed off the firework pretty well I found that when I turned up the fill light something surprising happened. I had been shooting through trees and when the firework went off all the trees got illuminated faintly with the red glow which the camera was able to pick up. It wasn’t just the trees though, rockets let off a lot of smoke as they fly and that too had been illuminated giving the final picture something that almost looked like an aurora. Frankly I’m continually surprised at how much light even my non-SLR camera is picking up and how much Lightroom can make use of it.

The next firework we let off was a Roman candle. These shoot for long bursts so maybe it would have been better to turn down the exposure length some but I wasn’t playing with any settings while I was shooting so my shots got multiple launches and explosions in a single exposure but this still got me a fantastic result. Again pushing up the fill light revealed the trees, looking even more ghostly this time:

The second Roman candle that went off I managed to capture twice. As well as triggering off a 3 second timer I had also set to take 3 consecutive shots. In this case that paid off with two different views of the same firework however for the others it mostly got in the way as it would keep shooting long after the firework was spent and we were waiting to set off the next. It didn’t help that with long exposures my camera has a serious delay between the end of one shot and starting the next making it pretty unlikely the second exposure will be worth much.

Slightly disappointingly I only got a glimpse of the second rocket we set off. For some reason its fuse took longer to burn and so my first shot just caught the streak of its launch but ended before it exploded and due to the delay between shots the second exposure saw nothing. Still technically I managed to capture all four fireworks that we launched and I ended up with four pretty good pictures which for a first attempt I am pretty proud of.

I was at a small personal display which both meant that there were very few chances to get things right and that I didn’t really have any time to look at the result of one shot to adjust my technique for the next. However on the up side there was just a single firework going off at a time, I could watch the fuse being lit and time my shot accordingly and the others were happy to wait between fireworks while my camera stopped taking shots. Considering that at the start I didn’t expect to really get anything I’m really happy with the results. Not sure when I’ll get the chance to try this again but even if I don’t hopefully some others will get some ideas from this.