Escaped Thoughts

A Follow-Up Comment on Camino's Future

Several people have asked (as people have from time to time even in less uncertain times): Why don't we all just work on Firefox for the Mac instead? I understand why people think that makes sense. Camino is a browser in the Mozilla family, Firefox is a browser in the Mozilla family. Both run on the Mac. Basically the same thing, right?

What the question is missing is an understanding of the sorts of things that motivate people to contribute to open-source software in their free time. I don't know everyone's motivations for working on Camino, but of those I do, none picked it by deciding that they wanted to work on a Mozilla-family browser and then flipping a coin. Even if it were entirely a question of project goals, Camino and Firefox don't have the same goals, once you get beyond the “make a browser” part. But speaking for myself, the project goals are only a small part of why I'm here.

Off the top of my head, major reasons I work on Camino:

  • I want to work on software I care about personally.
  • I want to build Mac-focused software.
  • I want to write Cocoa/Objective-C code.
  • I like working with a small group where I know everyone, and interpersonal politics aren't an issue.
  • I like having significant influence over the development of the project.
  • I like being able to reach decisions quickly, without bureaucracy.

Firefox offers me exactly zero of those things. So the simple answer to the question of why I don't just go work on Firefox is that it wouldn't be rewarding for me. And since since we're talking about my free time, that's the only reason that matters. And while I don't speak for everyone else, I'd be surprised if my list doesn't overlap heavily with most of the other Camino developers.

(I could also list several reasons I would specifically not want to do it, personally, but those are probably not as generalizable to others.)

Category: Camino

Comments (2)

Thoughts on Today's Camino Announcement

Today a major hurdle for the long-term future of Camino was announced on one of the Mozilla newsgroups. As our blog post suggests, there's a chance that Camino 2.1 will be our last release. It all depends on whether this new direction is something that will attract enough new developers for the work involved. And while our dwindling developer population has been sad on one hand, I think it is actually a side effect of something very positive: a huge improvement in the Mac browser landscape.

Pretty much everyone who worked on Camino (and before that, Chimera) did so because they wanted to build the browser they wanted to use, but couldn't find. We worked on Camino because it was the best browser out there (in our opinions), and we wanted to make it even better. And frankly, for a long time there wasn't much competition. Mac IE became more and more out of date until it faded into history. Safari started out anemic even by Camino's “keep it simple” standards, and didn't see a lot of change at first. Firefox felt like what it mostly was: a Windows app that happened to run on the Mac (and it was the only other open-source option). A small group of volunteers was, for a long time, able to keep up with—and even beat in many users' opinions—the other browsers.

But now we live in a very different world; one where there are good browsers pushing eachother to get even better, faster. Safari has closed the compatibilty gap and is focusing more on features. Mac Firefox (while still not my favorite) is now more of a Mac app built with a cross-platform toolkit than a Windows port. Chrome has come along and (in my totally unbiased opinion) made a compelling case as a browser that both offers power users power, while holding close to some of the same principles that are at Camino's core (and added another major open-source player to the field to boot).

On the web technology side, things are moving much faster these days too. We've fallen behind Firefox in shipping major Gecko revisions (not least because of the issues mentioned in our blog post); we're only now about to come to par with Firefox 3.6. Being a year behind wouldn't have been such a big deal for much of Camino's lifetime, but recently a year is a very long time in the web world. It's already reasonably common to see sites that don't support Firefox 3.0 (and thus Camino 2.0).

So while I am sad to see what could be the beginning of the end for the Camino project, I have to cheer at the underlying causes. And even if Camino does end with 2.1, there's no question that its legacy will live on. A number of Camino alumni are hard at work building those browsers that have changed the landscape. It's clear to me that without Josh Aas the Mac version of Firefox would not have seen the improvement that it has, and it's certainly no coincidence that Mike Pinkerton helped craft the browser that won my daily usage away from Camino. And let's not forget that Firefox started out as, essentially, the Windows version of what was to become Camino.

So whether or not there is a Camino 3, there's no doubt that Camino helped create the browser world that we live in now. I'm proud to have been a small part of that, and thankful to everyone who helped us along the way.

Category: Camino

Comments (0)

So You Want to Write a Mac NPAPI Plugin

Or, Everything You Wanted to Know About Mac Browser Plugins, and Are About to Wish You Hadn't Asked

I've answered enough questions about this topic, and corrected enough slightly (or grossly) inaccurate information, that I finally decided it would be easier to just write it all out once, and refer people to that. If you are just getting started with writing an NPAPI plugin for the Mac and are trying to figure out what all this drawing model and event model stuff is all about, you've come to the right place.

(If, on the other hand, you are reading this because you are a regular reader here, you probably want to skip this one. The audience for this post is very specific.)

First, a Bit of History

In the beginning, there was QuickDraw and Carbon. Until recently, that was all there was for plugins, because NPAPI predates all the fancy new technologies these kids today take for granted (full disclosure: I am such a kid).

The first problem was QuickDraw, which was officially deprecated in 10.4; Apple needed a migration path for all the existing QuickDraw-based plugins. Making up a new plugin format from scratch would be problematic, since it would be harder for people making cross-platform plugins to support, harder for all the existing plugins to transition to, and only really be viable if all the browser vendors adopted it. Even then, it would be a pain for plugin vendors, since they would have to ship two copies of their plugins for as long as they needed to support browsers that didn't support the new plugin. (Sidenote: Apple did in fact try this in the form of the .webplugin format, but no non-WebKit.framework-based browsers ever supported it, or likely ever will.)

Enter the CoreGraphics drawing model, and runtime drawing model negotiation. The idea is that the plugin can ask the browser at runtime what drawing models it supports and, depending on the answer, tell it which one to use. Any browser that doesn't even understand the question can be assumed to support only QuickDraw. The differences between the old and new models are hidden behind part of a structure that is already a void* that means different things on different platforms, so binary compatibility is preserved. This allowed a single plugin to support old and new browsers, and browsers to roll out support for the new model, all without end users having to worry about any of it.

Next on the hit list was Carbon. With the trail already blazed, this was pretty straightforward in principle: the same negotiation system is used for the plugin to decide whether to use the old Carbon event model, or the new Cocoa event model. In terms of understandability though, things is where things start to get confusing. At this point there were three possible combinations of models (the fourth, QuickDraw+Cocoa, doesn't make sense, so is disallowed), and some of the differences overlap. For example, the NPWindow structure is different in each of the three cases.

But having replaced both the deprecated technologies, that was the end of it, right? Well, no. Because the CoreGraphics model doesn't allow for an end-to-end hardware-accelerated drawing pipeline, which some plugins really want. So now there's another drawing model, Core Animation, to address that. And that model as spec'd has some technical issues for some browser implementations, leading to its closely related cousin the invalidating Core Animation model—although these are so similar that I'll consider them as one model for most of this discussion. Oh, and Core Animation requires the Cocoa event model, adding another wrinkle to the matrix of possibilities.

(Eagle-eyed readers of the NPAPI headers might notice that there appears to be yet another model, called, temptingly, OpenGL. All you need to know about that model is that for all practical purposes it doesn't exist, and never will, so you should just ignore it.)

Aaaand a Bit of Recent History

But then things got really exciting. And by exciting, I of course mean confusing. Because before things could settle down, two new related developments came along: 64-bit apps, and out-of-process plugins. I say related because making a browser 64-bit is problematic in that you can't load 32-bit plugins into a 64-bit browser directly, and all the plugins lying around were 32-bit. Everyone had just gone through the PPC-to-Intel transition, which was painful enough for plugin vendors and required quite a bit of lead time. Rather than do it all again, Apple released 64-bit Safari with the ability to run plugins out of process, allowing it to keep using the 32-bit plugins. There was a catch though: it doesn't support QuickDraw out of process.

At around the same time, Chrome for Mac came out, and it runs all plugins out of process (even though it's still 32-bit) for philosophical reasons. It has minimal support for QuickDraw, but it's kind of a crapshoot whether a QuickDraw+Carbon plugin will work in it, and the performance will be very poor. It's bad enough, in fact, that when negotiating Chrome will claim that it doesn't support QuickDraw, because the support is really only there for a few specific legacy plugins and shouldn't be used by anyone writing new plugins.

And now Firefox 4 for Mac is about to come out, and it too is 64-bit, so needs to support out-of-process plugins. Mozilla went one step further than Apple, in that it doesn't support either QuickDraw or Carbon out of process.

And no matter the browser, if you want your plugin to compile as a 64-bit binary you can't use either QuickDraw or Carbon, since they don't exist in 64-bit.

Enough History; What Can You Use?

The landscape of supported options is confusing at this point:

32-bit Safari (on 10.5+)
Any valid combo (QuickDraw+Carbon, CoreGraphics+Carbon, CoreGraphics+Cocoa, Core Animation+Cocoa)
64-bit Safari
Anything but QuickDraw (CoreGraphics+Carbon, CoreGraphics+Cocoa, Core Animation+Cocoa)
Chrome
Same as 64-bit Safari (CoreGraphics+Carbon, CoreGraphics+Cocoa, Core Animation+Cocoa)
Firefox 3.6 and earlier (and any other pre-Gecko-2 Gecko browsers, such as Camino)
Anything Carbon (QuickDraw+Carbon, CoreGraphics+Carbon)
32-bit Firefox 4
Any valid combo (QuickDraw+Carbon, CoreGraphics+Carbon, CoreGraphics+Cocoa, Core Animation+Cocoa)
64-bit Firefox 4
Anything Cocoa (CoreGraphics+Cocoa, Core Animation+Cocoa)

Before we move on, three important points that many people get confused about:

  1. 10.6 != 64-bit. It's true that browsers can only be 64-bit on 10.6+, but there are plenty of people with 32-bit machines running 10.6.
  2. More importantly, out-of-process != 64-bit (or 10.6+). Chrome runs all plugin out-of-process even on 32-bit, even on 10.5. That means that having a 32-bit binary that only uses QuickDraw+Carbon and a 64-bit binary that uses the newer models is not a good solution. The runtime negotiation exists for a reason—use it!
  3. QuickDraw can't be assumed just because your plugin is 32-bit. You can only assume that QuickDraw is present if the browser either says yes when you ask, or returns an error (meaning it doesn't understand negotiation at all).

Okay, So What Should You Use?

The more you support the more forward and backward compatible you'll be, of course, but it's also more work. Here are some rules of thumb for each pairing.

Core Animation+Cocoa

If you want hardware-accelerated drawing, or you want to do OpenGL without having to manually draw your OpenGL surface into a CoreGraphics context, you should support this. See the note about invalidating Core Animation below.

One caveat is that Safari 4, and Chrome up to at least Chrome 10, do not composite Core Animation plugins correctly. For those of you coming from a Windows or Linux NPAPI background, it's akin to windowed-mode plugins, drawing above all web content regardless of z-index. If that's deal-breaker, you'll need to use CoreGraphics and do a readback from an off-screen OpenGL buffer. Hopefully this will be fixed within a couple more releases of Chrome (it already works in Safari 5).

CoreGraphics+Cocoa

If you don't care about hardware acceleration or OpenGL, you should support this. While you could use Core Animation, the advantage is that if you are in this case you will likely also want to support...

CoreGraphics+Carbon

If you want to support Firefox 3.6 or earlier (so, if you want to support 10.4, and/or PPC), and don't care about hardware-accelerated drawing, you should support this model.

QuickDraw+Carbon

If you need to support browsers that don't support Core Animation, and you really, really need hardware acceleration, then you have to support this. It will be painful though, because the way to get hardware acceleration isn't so much to use QuickDraw, as to do sketchy things with the WindowRef you get from using the Carbon event model, attaching your own OpenGL surface to the window at the right location. You will have to debug this carefully in any browser you do it in, because it's a hack, and thus fragile. If you screw up you'll create nasty bugs like plugins that keep showing even after the user changes tabs. It will also not composite correctly since it bypasses the browser's drawing system, so it will be like a windowed Windows or Linux plugin (except even the iframe hack won't work).

In short, if you are writing a new plugin, please just don't do this. Use CoreGraphics and do a buffer readback for the legacy support. Despite the performance cost, it's almost certainly the better choice.

(If you do feel the need for that kind of hackery though, whatever you do don't negotiate CoreGraphics+Carbon and do it there. It won't actually help, because in browsers that don't support QuickDraw, it won't work anyway. It will just confuse any browser developer debugging issues with your plugin.)

The Bottom Line

If you don't need to support users of Firefox 3.6 or earlier (or Camino), just support whichever of the Cocoa options makes the most sense for you. Not having to implement the Carbon model will save you a lot of work (especially since the Cocoa model is more consistent across browsers, due to its clear spec).

If you need to support Firefox 3.6, support either both flavors of CoreGraphics, or Core Animation and CoreGraphics, depending on your need for things like OpenGL and hardware acceleration.

If you need to support Firefox 3.6, really want accelerated graphics, and are crazy, support Core Animation+Cocoa and QuickDraw+Carbon.

Core Animation's Strange Duality

Why are there two different Core Animation models? In a nutshell, Gecko and Chrome need to know when the plugin's CALayer has changed in order to work right, and WebKit.framework-based browsers (like Safari) don't. There's no way the browser can find out from the layer itself though, so Gecko and Chrome have to assume that it has always changed. That means running the drawing pipeline on a high-frequency timer, which is not so efficient. The solution is for the plugin to tell the browser when it draws instead—that's how the invalidating version of the Core Amination model works, and it's literally the only difference. But that's less efficient in browsers using WebKit.framework, where the calls are unnecessary, so those browsers only implement the original.

The good news is that if you support one, supporting the other should be trivial: just treat them the same except for making one extra call in the invaliating version each time you draw. When negotiating, prefer the invalidating version, since any browser that supports it will be more efficient when using it.

(As of the time of writing, Chrome supports both versions (although the non-invalidating version only on 10.6+), and it looks like Firefox 4 will as well. You shouldn't rely on that, however, as support for the non-invalidating version may be removed from one or both to ensure that plugins aren't accidentally opting into the version that requires the wasteful timer.)

Where to Learn More

Unfortunately, most of the basic NPAPI docs still date back to the QuickDraw and Carbon days (at least, they do as I write this). The best resource for learning about the new models is the set of specifications for the updates.

Category: Geek

Comments (1)