Zotz Developer's Guide

Zotz is a Zotero add-on, but it's written as a regular Firefox extension: the nature of firefox extensions all living in the same address space allows extensions to invoke each other internal methods, which means that Zotz can extend Zotero without Zotero having to expose special APIs for this.

While this is a very powerful mechanism, it is also insecure and fragile.

Insecure because it allows potentially malicious extensions to do act uncontrolled inside your browser (stealing your data and/or altering the browser or the extensions' own activities) and fragile because Zotero might change internal APIs not knowing that Zotz dependend on them and would immediately break Zotz functionality.

There is currently no better way to do things so we're stuck with it for the time being, but being aware of the situation helps forecast future development needs and potential issues that could arise.

It is worth noting that Firefox 3 addresses some of the issues of insecurity by preventing "mad in the middle" attacks by forcing extension updates to happen either on an encrypted web connection or by validating the digital signature of the extension metadata and its update information.

While this does, in fact, prevent attackers to inject malicious code into your browser via extensions that you trust, it doesn't do anything against the possibility of extensions acting as trojan horses. This doesn't have anything to do with Zotz in particular but it's worth mentioning.

Where to start

Given the above, Zotz should be treated as simply another Firefox extension (that simply manages to call some Zotero functions if Zotero is available), so no special information is needed other than the standard tutorials and info on Firefox extensions.

The best way to start to learn how to write Firefox extensions is the Firefox Extension start page at the MozDev web site. Very important is that you tweak your browser's settings for extension development, this will save you a lot of pain and browser restart cycles.

Get the code

The Zotz code is located on the SIMILE subversion repository. To obtain the code simply invoke a subversion client with

 svn co http://simile.mit.edu/repository/zotz/trunk/ zotz

making sure that the subversion client svn is in your path.

This will create a directory called zotz which folder's structure will look like this

 zotz
  +-- docs
  +-- src
       +-- extension
            +-- chrome
            |    +-- content
            |    |    +-- scripts
            |    +-- locale
            |    |    +-- en-US
            |    +-- skin
            |         +-- classic
            +-- defaults
                 +-- preferences

The most important part is the chrome directory which contains the files that make up the extension. Here, the most important files are in the content subfolder: overlay.xml, which contains the UI skeleton that makes up the extension and scripts/zotz.js which contains the javascript logic that drives its activities.

zotz.js is, most likely, the file that you would want to start with if you were to add functionality to the extension.

Package the Extension

Firefox extensions are packaged as "XPI", which is really a zip archive with a different extension and that Firefox recognizes as its own package format.

Zotz comes with an ant build file (the build.xml in the zotz root directory) that takes care of the executing the main build management functions, including creating the XPI for you.

To do this, simply invoke

 ant xpi

while your current directory is where the build.xml file is located. This will create a zotz-*.*.*.xpi file in the same directory (where * will be replaced by the current version number).

Generated Files

Unfortunately, Firefox extensions require the same information to be located in various places and this might lead to mis-alignment. For this reason, Zotz uses the ant build system to generate some of the extension files that Zotz needs from templates and uses the build.properties file to host the information in one place.

The two files that are generated are

  • zotz/src/extension/install.rdf (generated from zotz/src/extension/install.rdf.template)
  • zotz/src/extension/defaults/preferences/zotz.js (generated from zotz/src/extension/defaults/preferences/zotz.js.template)

and the data comes from the build.properties file in the zotz root directory.

So, if you want to change anything in those files, make sure to change the templates or to change , you shouldn't change it directly in the generated files, because any change you make will be wiped out at the next build.

Making a release

There are several steps that need to happen in order for a release to take place.

First of all, you need to have an SSH user account on simile.mit.edu and your username should be in the simile group (if that's not the case and you don't know who to ask to change that, this section is not for you).

Phase 1: the XPI

Before building the XPI, you need to update the version in the build.properties file. This is very important!

Then you can build the release on your own machine using ant xpi.

My suggestion is to test this package in your own browser (possibly not in your main profile where you were doing development it; see how to manage firefox profiles if you need help with that).

Once the XPI is built and it works as expected, you should copy the file over the simile server, like this:

 scp zotz-x.y.z.xpi username@simile.mit.edu:/var/dist-archive/zotz/

where username is your SSH username on that box. This will copy the file in the right destination directly.

Then you must change the symlink of the latest Zotz XPI to the new one you just uploaded. To do this you must do the following commands:

 > ssh username@simile.mit.edu
 > cd /var/dist-archives/zotz
 > rm zotz.xpi
 > ln -s zotz-x.y.z.xpi zotz.xpi

Ok, you're now done with Phase 1, which means that new Zotz users will automatically install the just released one. Now you have to tell all the people that are using an older version of Zotz to update. The second phase will do that.

Phase 2: updating the install base

Firefox has a built-in update mechanism that periodically checks a particular URL for update information (which is returned as an RDF file, nonetheless). If an update is found, the Add-on's manager will prompt you to install it.

Before Firefox 3, it was possible to have that update URL be anything, but now, for security concerns, you either have to have it served via HTTPS (encrypted with a not-self-signed certificate, like Zotero does here) or crypto-sign the update information and the extension metadata with the same key (like we do for Zotz).

Another valid option is to use Firefox's own Add-on's web site to upload and manage your extensions (and, in fact, there is a simile account there under the email "root@simile.mit.edu", password is the usual project one) but this requires some patience because your extension need to accepted out of the 'experimental' stage before it can be downloaded by people without having to sign up and log in as developers.

All these options are described in more details on the MozDev web site.

Since we do not own a non-self-signed digital certificate for the simile.mit.edu web site and we do not want people to have to sign up as developers to download an 'experimental', we follow the 'signed metadata' approach.

In order to make this easier, Mozilla has created an application called McCoy that is capable of:

  • generate and manage a private/public key pair
  • add the key information to the extension install.rdf file
  • sign the updates.rdf file accordingly

NOTE: unfortunately, there is no easy way to export and import the private/public key pair from McCoy, which makes it pretty hard for multiple people to be the release manager (or for one, to hand over the private key to another).

Before you start, you have to prepare your environment (this needs to be done only once):

  • install McCoy
  • run it once and pick a password (doesn't really matter which one since we'll remove it later)
  • close it
  • find the McCoy profile on your disk (read where to find it depending on your operating system)
  • get the file key3.db from the private SIMILE repo here (use "simile" as the username and the project-wide password to get in).
  • copy that file into your McCoy profile and overwrite the existing key3.db file (careful, this will wipe out your existing McCoy key-chain, so don't do this in case you care about some other key you have in there).
  • start McCoy and use the same project-wide password you used above to access the key chain.
  • you should now have a single key called "Simile" that you can use to sign and validate the update info

Now you can change the update info:

  • open the zotz/docs/updates.rdf file in your zotz local copy.
  • change all occurrences of the previous version of zotz with the new version. There are actually 4 places where you need to do this. One is the URL where the XPI is located, one is the version number and the other two are RDF URIs used to identify uniquely the extension.
  • find the SHA1 hashcode of the new zotz XPI and change the updateHash accordingly (see more info about that here)
  • once you're done with the 4 changes in that file, save it and close it.
  • open McCoy and insert the master password (the usual project-wide password).
  • select the "Simile" key.
  • click the "sign" button.
  • select the zotz/docs/updates.rdf.

McCoy won't give you any sign that it did anything, but you should run

 svn diff docs/updates.rdf

from the command line to see if the file has been changed.

If so, perform a "svn commit" and store it the version control system.

Then log in to update the web site:

> ssh username@simile.mit.edu
> cd /var/www/simile.mit.edu/zotz/
> svn update

and you're all set: firefox periodically asks for that updates.rdf file and checks to see if there are new versions of the extension currently installed.

If you need help troubleshooting why your updates are not picked up by Firefox, read this.