Automatically Update Firefox Extensions

I bring to your attention a translation of the article Automatic Firefox Extension Updates .

The article is old, but all the information is relevant to this day.


Firefox extension developers, of course, know that when distributing extensions through the official store, you get the opportunity to automatically update your extensions for free. But what if we want to host our extension on our site ourselves? How do we ourselves implement support for automatic updates?

Signing Extensions


Starting with the third version of Firefox, all extension updates should be provided through reliable channels. Since we decided to host our extension on our own, we have two options to fulfill this requirement:

  • Provide updates over a secure (https) connection
  • Sign extension electronically

We will not consider the first option - in most cases it requires additional costs (you need to buy an SSL certificate and have a static IP (I didn’t understand what it’s for, but you won’t erase words from the song [approx. Transl.] )) The digital signature is the opposite - free, easy to use and fast to implement. Well, let's learn how to use it!

Create a private / public key pair


The first step in signing our extension is to create a private / public key pair. Mozilla provides the McCoy utility for this purpose. Not the easiest utility in the world, so below is how to cook it:

  • go to the McCoy website and download the appropriate package (there are versions for Windows, Linux and Mac OS X)
  • unpack the package in a convenient directory
  • run the application. At the first start, it will offer to create a master password to protect the keys. Creating such a password is highly recommended! Each time McCoy starts up again, it will ask for this password.
  • The application is running, select in the menu Keys »Create New Key. Enter the sane name for your key and click Ok. Keep in mind, even if you want to host several extensions on your site, you only need one key.

Well, the keys are created, now you need to update the extension manifest.

Update install.rdf


It is assumed that you are familiar with install.rdf, so we won’t waste time describing its structure (if not, here you are ). For an example I use install.rdf from Toolbar Tutorial . Here is its original version:

tuttoolbar@borngeek.comTutorial Toolbar21.0{ec8030f7-c20a-464f-9b0e-13a3a9e97384}4.030.*Jonah BishopAn example toolbar extension.https://www.borngeek.com/firefox/

We need to add two elements to this manifest: em:updateURLand em:updateKey. The element em:updateURLpoints to the URL at which the update manifest (update.rdf) is located. It looks like this:

http://www.example.com/update.rdf

Keep in mind - you cannot place an extension in the official store if your manifest contains this element.

The next one is with us em:updateKey. It just contains a public key. To get it, open McCoy, right-click on the key that you created earlier and select Copy Public Key in the context menu. After, put the key between the opening and closing tags:


MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW8qxAeURIMLnHjb
KrjR/uqnRsiomahNArMh3KqRLDDmRGCoO21fyHyh5kdgiEL+2Q+sNP
z+j5maIG4qePXp7BVp90QMqiGLvl+z4baDOqcNvErN0l8scd8EegXc
G7Ofa5Gc5oEU/gItIVR4k9AICyW2pJhe51UPa3UKXDS0v3TwIDAQAB

Abracadabra. Fortunately, Firefox is smart enough and allows you to use spaces in the em:updateKeyelement, which makes install.rdf more readable (as shown above, this is a formatted version). By default, one long string is copied from McCoy.

After adding these two elements, install.rdf starts to look like this:

tuttoolbar@borngeek.comTutorial Toolbar21.0{ec8030f7-c20a-464f-9b0e-13a3a9e97384}4.030.*Jonah BishopAn example toolbar extension.https://www.borngeek.com/firefox/http://www.example.com/update.rdf
        MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW8qxAeURIMLnHjb
        KrjR/uqnRsiomahNArMh3KqRLDDmRGCoO21fyHyh5kdgiEL+2Q+sNP
        z+j5maIG4qePXp7BVp90QMqiGLvl+z4baDOqcNvErN0l8scd8EegXc
        G7Ofa5Gc5oEU/gItIVR4k9AICyW2pJhe51UPa3UKXDS0v3TwIDAQAB
        

We have completed updating the manifest of our extension! Please note that this step needs to be done only once. That is, with each next update, you don’t have to repeat these steps (unless you change the update.rdf URL or change the key). Everything, at this stage it is already possible to pack the extension for further distribution (to distribute to users).

Create update.rdf


Since we have completed with the extension itself, it's time to create an update manifest. This file (update.rdf) will live on our server and, in fact, it determines what the user will see when checking for updates. Let's start by taking a quick look at the final version of the file we're going to create:

1.0.2{ec8030f7-c20a-464f-9b0e-13a3a9e97384}4.030.*http://www.example.com/downloads/tuttoolbar_1_0_2.xpi
            sha256:c22ad513c1243959a6d8e6b3cfad18a2a9141306f0165da6b05b008b2042e502
            

Let's go over line by line and discuss what is going on here. First, we have a standard XML header followed by an r: RDF element, which tells us that we have an RDF (Resource Description Framework) file. We are mainly interested in the r: Description element. You must have one element for each extension that you describe in update.rdf.

( Yes, yes, in one update.rdf you can describe the updates of many extensions, Extension Versioning, Update and Compatibility [approx. Translation.] )

Next, the first thing we need to write is an attribute about. Parturn:mozilla:extensionrequired, followed by the GUID of your extension. In our case, the GUID is: tuttoolbar@borngeek.com. Keep in mind - if you do not email-style GUID (and something like d4373b50-43b3-11de-8a39-0800200c9a66), then it must be enclosed in braces {d4373b50-43b3-11de-8a39-0800200c9a66}.

After several child elements ( updates, r:Seq, r:li, and another r:Description) on the stop member version. This is the version of your extension, in our case 1.0.2.

Next, we have information about the application for which our extension is intended (Firefox). We have an targetApplicationelement enclosed in r:Descriptionand containing an extremely important idelement. The value of this element is the Firefox GUID.

(Immediately obvious, the Basurmans wrote. In short - each target has its own GUID - for Firefox, for Thunderbird, for Firefox for Android, everyone has a different one. We go here , select the application under which our extension works and copy its GUID. Here you can take a look at the update.rdf example for several targets [approx. translation.] )

followed familiar minVersionand maxVersionelements which respectively define the minimum and maximum versions Firefox-well (or other target-a) , a work in which the calculated extension. It is very important that these values ​​match those specified in install.rdf.

Next we haveupdateLinkelement. It indicates the URL of the extension itself (i.e. xpi file). Make sure that the URL points to the appropriate file, especially if you support and let download older versions of the extension.

Well, in the end we are waiting for updateHashan element. This element contains the sha1, sha256, sha384, or sha512 hash of our extension (i.e. the xpi file). I prefer sha256 because there were backward compatibility issues for sha384 and sha512 (see bug 383390 ( everything has been fixed for a long time ). If you are on Linux, you already have everything you need to generate sha. Windows users can download the corresponding utility (I use sha256sum), for example, here: Cygwin . To get a hash, type something like this in the terminal:

sha256sum tuttoolbar_1_0_2.xpi

The output will look something like this:

c22ad513c1243959a6d8e6b3cfad18a2a9141306f0165da6b05b008b2042e502 *tuttoolbar.xpi

The hexadecimal string (everything up to a space) is what you need to put in updateHashindicating the type of encryption. It should look something like this:


sha256:c22ad513c1243959a6d8e6b3cfad18a2a9141306f0165da6b05b008b2042e502

Actually everything! Save it as a development version! I personally use the name update.rdf.dev. Why do I need to keep a separate version for development? Because when you sign this manifesto ( and we are considering the option with the signature [approx. Transl.] ) Its contents will become a little unreadable and unsuitable for further editing. So it’s better to keep the development version separate, and when necessary, sign a copy of it.

Sign the manifesto


In order to sign the manifest, follow these simple steps in sequence:

  • copy the developer version of the manifest and name it update.rdf. It is this file that we will sign
  • launch McCoy if it is not already running
  • select the key with which you are going to sign and select in the Update menu »Sign Update Manifest
  • in the menu that opens, select the update.rdf that we just created, and click Open

It will look like nothing is happening, but it is not! I have such a claim to McCoy - he says nothing at the end of the work. But if you open the manifest, you may notice that it has changed a bit. Actually this is where the work on the extension ends - it's time to upload files to the server.

Host update.rdf


Before uploading files, we must make sure that our server is ready to host rdf and xpi files. On Apache, we can do this through the .htaccess rules (I don’t know how it works in IIS or TomCat, keep in mind that this is an instruction only for Apache). I usually put these rules in the .htaccess site root - in case I want to move xpi and rdf. The rules are simple:

AddType application/x-xpinstall .xpi
AddType text/xml .rdf

( now it is already fashionable nginx, for it we do this:

types {
 application/x-xpinstall      xpi;
 text/xml      xml, rdf;
}

and put it either in the general /etc/nginx/mime.typesor in the config of our server. [approx. translation.]
)

This is necessary for the correct file upload by the server. This is a very important point! Otherwise, your extension will not be installed, and updates will not work either. Also keep in mind: if you use any kind of CMS (such as WordPress), then it’s best to place these rules just in case at the root of the site.

After everything is registered, you can fill in our xpi and update.rdf at the appropriate addresses. Update.rdf should be where the install.rdf extension points (the em:updateURLinstall.rdf file tag of the extension). The extension itself (.xpi) should lie where update.rdf (tag updateLink) points . Try not to get confused.

That's all! Although the procedure is a bit confusing for the first time, everything is quite simple.

Clean code!

Also popular now: