Add-on hosting: Mozilla vs Google vs Opera

I habitually develop browser user scripts to stream-line things for myself (and others) on the web – and a half random scattering of them tends to end up proper add-ons, when I think the benefit of them being easy to find, install and reuse by others merits the added work for myself of packaging them and submitting them to an add-ons gallery.

This happens rarely enough for me to forget some details of the process (yet often enough to be annoying), hence this post to document salient parts of it, applaud parts of where hosts worked things out really well, and note where there are holes to patch up. (I don't cover Safari since I have not made any Safari add-ons.)

Firefox add-ons: addons.mozilla.org, a k a AMO

Your add-ons are listed here: addons.mozilla.org/en-US/developers/addons
Add-on URL: addons.mozilla.org/en-US/firefox/addon/your-configurable-addon-slug
Public data: current version, last update time, compatible browser versions, website and, optionally: all add-on detail metrics, if the developer wants to share them (excellent!)
Public metrics: total download count, average rating, number of ratings
Detail metrics: TONS: mainly installation rate and active installed user base over time, broken down by all sorts of interesting properties or in aggregate, graphed and downloadable in csv format. Notable omission: add-on page traffic stats. Public example: Greasemonkey stats
Developer page linked from the public add-on page when you're logged in: NO
Release process: Manual review process that can take a really long time, as AMO often is under-staffed, and hasn't successfully incentivized developer participation in the process to an extent as to make it not so.

Summary: great stats and an ambition to make information public and transparent.

Chrome add-ons: chrome.google.com/webstore, or the Chrome Web Store
Previously lived at chrome.google.com/extensions, the Chrome extensions gallery

Your add-ons are listed here: chrome.google.com/webstore/developer/dashboard
Add-on URL: chrome.google.com/webstore/detail/your-addon-signature[/optional-add-on-slug]
Public data: current version, last update time, if installed: a checkmark and the sign "Installed", instead of the "Install" button (excellent!)
Public metrics: total download count, average rating, number of ratings
Detail metrics: If you jump through the relatively tiny hoop of creating and tying a new Google Analytics account to your add-on, you get detailed add-on page traffic stats, over in Google Analytics. Notabe omission: all metrics about your installed user base :-/
Developer page linked from the public add-on page when you're logged in: NO
Release process: Automated review process, making yourself the only release blocker, in practice. This is bloody awesome!

In summary: A really delightful release process that doesn't waste your time. The metrics part is really disappointingly missing the most interesting data; I hope that will improve with time. There are other essential missing docs too: to find out that you can self host your add-on AND publish it in the chrome web store, with the same add-on id, you need excellent Google fu, or this secret knowledge:

  • first (before your initial web store submission) build your add-on locally
  • store the .pem file in some good location
  • rename it key.pem
  • copy that .pem file into the add-on directory
  • zip up that directory (so the top level of the zip file only has one directory)
  • NOW (and for all later versions, IIRC) upload this zip file to the Chrome Web Store
  • …and it will use your add-on signature, instead of that of Google's secret .pem

Opera add-on page

(slightly de-horizontalized screenshot taken here)

Opera add-ons: addons.opera.com/addons/extensions

Your add-ons are listed here: addons.opera.com/developer (this page is near impossible to find by navigation, and was the reason I created this blog post :-)
Add-on public URL: addons.opera.com/addons/extensions/details/addon-slug[/version (redirects visitors here)]
Add-on developer URL: addons.opera.com/developer/extensions/details/addon-slug/version (no redirect help, but links to all other versions)]
Public data: current version, last update time, add-on size (excellent!)
Public metrics: total download count, average rating, number of ratings
Detail metrics: NONE. Notabe omission: all data about your installed user base, AND add-on page traffic :-(
Developer page linked from the public add-on page when you're logged in: NO
Release process: Manual review process, rewarding the behaviour of publishing as little data about your add-on as possible, since each bit of data is a plausible blocker. (Example: it is a bad thing to link to your development site on github, unless it is a repository that only has Opera-addon-centric stuff in it, and not, say, covers the source code used to build add-ons all browsers it caters.)

Summary: young; still a far cry from easy to find your way around. I accidentally managed to log in via my email address (after having reset the password), which had gotten the same password as the account nickname I had published from before, but was otherwise treated as another account, with its own (empty) list of add-ons. So I first found no way to upgrade my existing add-on and just uploaded a new one. When I found the mistake, there was no way to abort the review process I had started (but I could edit it to add some reviewer notes for the probably equally confused reviewer). What probably looks like a really well integrated set of connected Opera sites to an Opera employee is a huge maze of web pages, none related to publishing your add-on, to an add-on developer.

All of these hosting sites have developer log-in of some sort, yet fail to link the developer's admin view from the public add-on page. For Opera, this hurts really badly, as there is so much Opera noise around, which does not try to help you publish your add-on; for the others, it's a smaller nuisance (it's also entirely possible that I learned where to find the "Developer Hub" and "Developer Dashboard" links long ago enough to now find them near intuitive).

Update: I just found Opera's dashboard link! Your logged-in name is the link that takes you to your dashboard of add-ons. And it only took knowing the wanted url, opening a web console and typing [].slice.call(document.links).filter(function(a){ return a.href == "https://addons.opera.com/developer/"; }) in it. What do you know? :-)


Github Improved 1.7

After a whole year in development as a user script (initial mention, formerly known as "Github: unfold commit history"), a brief test-drive as an Opera extension at the 2010 add-on con, I finished up the missing bits and pieces to make today's Github Improved! chrome extension available in the Chrome Gallery / Web Store (1.7 now also available in the Opera extension gallery).

New since last release is the little tag delta (Δ) links that let you instantly see what happened between, say, Greasemonkey 0.9.5 and the previous release tag (it recognizes anything where the only thing differing between tags are their numeric parts, which also means it's not going to handle fancy 1.6rc1 type tag names littered with semantic non-numeric parts):

And, as prior users may find even more importantly, that it doesn't hog any shifted keyboard shortcuts, which for some reason had the side effect of making arrow up pull in a pageful of diffs.

Full documentation of all features, and a few screenshots, is available on the Chrome Web Store page. I also take every opportunity to mention that it really shines best together with the AutoPatchWork extension, or something equivalent which unfolds the commit history pagination as you scroll off page. Enjoy!


Google Closure Library bookmarklet

Any self-respecting javascript library should have a debug bookmarklet that lets you load it into a page, so you can tinker with it (the library, or the page, for that matter) without any messy overhead like downloading the most recent version, building it with the specific flags and sub-components you want, saving the current page, adding library setup code to it, and reloading that page before you can do squat. I found Google Closure Library a bit lacking in that regard, so here's my take on it:

It has two modes of operation; if all you want to do is load the goog object into the current page (or overwrite the one you already have with one that has a different set of goog.require()s), just customize which those requires should be, and you're set; it creates an iframe, in which it loads the library (goog.require only works during page parsing time, as it uses document.write() to load its dependencies), and then overwrites the top window's goog identifier.

The second mode is good for writing your own bookmarklets making use of some Closure Library tools; provide your own function, and it will instead get called with the freshly loaded goog object, once it's ready. At the moment, I have only played with this in Google Chrome, but feel free to fork away on github, if you tinker in additional improvements for other browsers.

Finally, here's a bookmarklet version to save or play with, which will prompt you for just which closure dependencies you want to load: closure – drag it to your bookmarks toolbar or equivalent if you want to keep it around. Enjoy!

A "No News is Good News" Tsunami Feed

I have subscribed to the NOAA/NWS/West Coast and Alaska Tsunami Warning Center's feed of ahead-of-time tsunami warnings for the U.S. West Coast, Alaska, and British Columbia coastal regions (example information statement) for some time. Most, like this one, are "wolf-cry" statements stemming from some seismic activity somewhere that won't generate any tsunami, marked with the all-important body phrase "The magnitude is such that a tsunami WILL NOT be generated" - meaning I don't really care about them.

Today I made a Yahoo pipe, filtering away those from the feed. Here is the resulting feed, containing only positive tsunami warning statements. Behind the scenes, it's created by the simple YQL statement select * from rss where url="http://wcatwc.arh.noaa.gov/rss/tsunamirss.xml" and description like "%tsunami <strong>WILL NOT</strong> be%" (there's some newline or similar after "be" in the original feed, and it doesn't seem like YQL does any whitespace normalization, but this matches well enough to filter the stuff).

The resulting feed is my enrapturing contribution to today's supposed end of the world. You may note that the feed is currently (and hopefully still, by the time you read this :-) empty - which is, of course, good news. Enjoy!

On a related hacker's note, it would be really handy to extend Google Reader with a "filter this feed" feature that created these more on the fly, without mucking about for an hour in the Yahoo Pipes interface, and then changed the old subscription to the new feed.


Chrome + NaCl + libmodplug + ... = tracker modules on the web

Some notes I took while looking into how to build a libmikmod_x86_32.nexe and libmikmod_x86_64.nexe to get Chrome tracker module playing support from javascript (the work seems to be done already in naclports) via NativeClient, for all the MOD, S3M, XM, IT, 669, AMF, AMS, DBM, DMF, DSM, FAR, MDL, MED, MTM, OKT, PTM, STM, ULT, UMX, MT2 and PSM formats:

  • In a Chrome 11 profile, go to about:flags, and click Enable under "Native Client", and then the "Relaunch Now" button at the bottom (alternatively: start the session with the --enable-nacl command-line flag)
  • Download the NaCl SDK (for Chrome 11, in my case; eventually the ABI will supposedly freeze and cover a wider range of versions)
  • Download depot_tools, extract it and export NACL_SDK_ROOT=$PWD in that directory (technical overview here)
  • Check out naclports
  • Probably optional: comment out all the RunInstallScript lines in naclports/src/packages/nacl-install-all-bitsize.sh except the one you're interested in (in my case: RunInstallScript libmodplug-0.8.7 nacl-libmodplug-0.8.7.sh)
  • Run nacl-install-all-bitsize.sh 64 (or 32 for a 32-bit build), which, in my case, built $NACL_SDK_ROOT/toolchain/mac_x86/nacl64/usr/lib/libmodplug.a
  • About here my research petered out, as I found this smaller hack for XM-only playback by some forthcoming Japanese fellow (git repository here; English translation of same page c/o Google Translate), which has basic functionality
  • If you got curious about my original venue and proceeded further, I'd love to hear about it, especially if you managed to build the final nexe:s; do post a comment!


Github tag and branch labels

I just made a little update to my github improved! user script; now it shows you branch and tag labels in the commits view, like this:

There's been some more mystery meat features slipping in there too somewhat unannounced; if you click a committer icon a little filter panel opens on top that lets you see how many commits in the view were by whom, and if you click one of those, hide those commits. I got the idea when I was playing with Autopatchwork at some point, unpaginating a whole repository's worth of commits and wanted to slice and dice the view a bit, get aggregate stats and the like. This is what Greasemonkey's early history (from 0.8 and back) looks like, in terms of authors (not committers) involved, for example:

Autopatchwork could use some more coverage on the English-speaking web, by the way, because of its neat way of aggregating user data from contributors. Instead of a dedicated backend server someone maintains for the script to work, it's using a wiki-like JSON database for public domain content: Wedata.net; define your json schema and let anyone that wants to fill in, edit and co-maintain the data (here: unpagination url regexps and node xpaths). The editing process looks a bit like this. I am especially glad to have found it, as I've been wanting a service like that for a long time but not really wanted to host it, and having a public cloud sync point for mini-applications like this to update their localStorage copies of the data from is a neat trick.

Anyway, happy githubbing! As with so many little features before it, I already can't fathom going back to a github without this feature (and I've only been using it since yesternight). It helps a lot seeing what went into which release at a glance, without doing all sorts of manual work. It would be nice for it to mark branch-off points too, but it would require some kind of merge-base type api end-point, for digging up where a branch's closest common ancestor is to all other branches. Maybe time for devising a neat response format and crafting a little api feature request.