I bring to your attention the translation of the article Automatic Firefox Extension Updates .
The article is old, but all the information is relevant to this day.The developers of Firefox extensions 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 website ourselves? How can we implement automatic update support?
Signing Extensions
Starting with the third version of Firefox, all extensions updates should be provided via secure channels. Since we decided to host our extension ourselves, we have two options to fulfill this requirement:
')
- Provide updates over secure (https) connection
- Sign an extension with an electronic signature
We will not consider the first option - in most cases it requires additional expenses (you need to buy an SSL certificate and have a static IP (I
did not understand what it is for, but you cannot throw out words from the song )) Digital signature opposite - is free, easy to use and quick 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 prepare 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. When first launched, it will offer to create a master password to protect the keys. Creating such a password is highly recommended! Each time McCoy starts up, he 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 will 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 will not waste time on the description of its structure (if not - you are
here ). For example, I use install.rdf from the
Toolbar Tutorial . Here is its original version:
<?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <em:id>tuttoolbar@borngeek.com</em:id> <em:name>Tutorial Toolbar</em:name> <em:type>2</em:type> <em:version>1.0</em:version> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>4.0</em:minVersion> <em:maxVersion>30.*</em:maxVersion> </Description> </em:targetApplication> <em:creator>Jonah Bishop</em:creator> <em:description>An example toolbar extension.</em:description> <em:homepageURL>https://www.borngeek.com/firefox/</em:homepageURL> </Description> </RDF>
We need to add two elements to this manifest:
em:updateURL
and
em:updateKey
. The
em:updateURL
points to the URL for the
update manifest (update.rdf). It looks like this:
<em:updateURL>http://www.example.com/update.rdf</em:updateURL>
Keep in mind - you will not be able to place the extension in the official store if your manifest contains this element.
The following is our
em:updateKey
. It simply contains the public key. To get it, open McCoy, right-click on the key you created earlier and select
Copy Public Key from the context menu. Then place the key between the opening and closing tags:
<em:updateKey> MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW8qxAeURIMLnHjb KrjR/uqnRsiomahNArMh3KqRLDDmRGCoO21fyHyh5kdgiEL+2Q+sNP z+j5maIG4qePXp7BVp90QMqiGLvl+z4baDOqcNvErN0l8scd8EegXc G7Ofa5Gc5oEU/gItIVR4k9AICyW2pJhe51UPa3UKXDS0v3TwIDAQAB </em:updateKey>
Abracadabra. Fortunately, Firefox is smart enough to use spaces in the
em:updateKey
element, which makes install.rdf more readable (as shown above, this is already a formatted version). By default, one long line is copied from McCoy.
After adding these two elements, install.rdf begins to look like this:
<?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <em:id>tuttoolbar@borngeek.com</em:id> <em:name>Tutorial Toolbar</em:name> <em:type>2</em:type> <em:version>1.0</em:version> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>4.0</em:minVersion> <em:maxVersion>30.*</em:maxVersion> </Description> </em:targetApplication> <em:creator>Jonah Bishop</em:creator> <em:description>An example toolbar extension.</em:description> <em:homepageURL>https://www.borngeek.com/firefox/</em:homepageURL> <em:updateURL>http://www.example.com/update.rdf</em:updateURL> <em:updateKey> MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW8qxAeURIMLnHjb KrjR/uqnRsiomahNArMh3KqRLDDmRGCoO21fyHyh5kdgiEL+2Q+sNP z+j5maIG4qePXp7BVp90QMqiGLvl+z4baDOqcNvErN0l8scd8EegXc G7Ofa5Gc5oEU/gItIVR4k9AICyW2pJhe51UPa3UKXDS0v3TwIDAQAB </em:updateKey> </Description> </RDF>
We have completed the update of our expansion manifest! Please note - this step needs to be done only once. That is, with each subsequent update these actions will not have to be repeated (unless you change the URL update.rdf or change the key). Everything, at this stage it is already possible to pack an extension for further distribution (distribute to users).
Create update.rdf
Since we're done 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 looking at the final version of the file we are going to create:
<?xml version="1.0"?> <r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.mozilla.org/2004/em-rdf#"> <r:Description about="urn:mozilla:extension:tuttoolbar@borngeek.com"> <updates> <r:Seq> <r:li> <r:Description> <version>1.0.2</version> <targetApplication> <r:Description> <id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</id> <minVersion>4.0</minVersion> <maxVersion>30.*</maxVersion> <updateLink>http://www.example.com/downloads/tuttoolbar_1_0_2.xpi</updateLink> <updateHash> sha256:c22ad513c1243959a6d8e6b3cfad18a2a9141306f0165da6b05b008b2042e502 </updateHash> </r:Description> </targetApplication> </r:Description> </r:li> </r:Seq> </updates> </r:Description> </r:RDF>
Let's go over line by line and discuss what's 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 element r: Description. You must have one element for each extension described in update.rdf.
(
Yes, yes, in one update.rdf it is possible to describe updates of multiple extensions, Extension Versioning, Update and Compatibility [comment. Translation.] )
Further, the first thing we need to register is the
about
attribute. The
urn:mozilla:extension
required, followed by the GUID of your extension. In our case, the GUID is: tuttoolbar@borngeek.com. Keep in mind - if you do not have email-style GUID (and something like d4373b50-43b3-11de-8a39-0800200c9a66), then it should be enclosed in braces:
{d4373b50-43b3-11de-8a39-0800200c9a66}
.
After several child elements (
updates
,
r:Seq
,
r:li
, and one more
r:Description
) we
r:Description
focus on the
version
element. 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 a
targetApplication
element enclosed in
r:Description
and containing the extremely important
id
element. The value of this element is the Firefox GUID.
(
Immediately it’s clear that they wrote to the bassurman. In short, each target has its own GUID — Firefox, Thunderbird, and Firefox for Android, everyone’s different. Go here , choose the application under which our extension works and copy it GUID. Here you can take a look at the update.rdf example for several targets [comment. Translation]This is followed by the familiar
minVersion
and
maxVersion
elements, which respectively determine the minimum and maximum versions of Firefox
(or another target) , for which the extension is calculated. It is very important that these values coincide with those specified in install.rdf.
Next we have the
updateLink
element. It indicates the URL of the extension itself (i.e., the xpi file). Make sure that the URL points to the appropriate file, especially if you support and allow older versions of the extension to download.
Well, in the end we are waiting for the
updateHash
element. This element contains the sha1, sha256, sha384, or sha512 hash of our extension (i.e., xpi file). I prefer sha256, because there were backward compatibility problems 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 (all that is up to the space) is what you need to put in
updateHash
indicating the type of encryption. It should look something like this:
<updateHash> sha256:c22ad513c1243959a6d8e6b3cfad18a2a9141306f0165da6b05b008b2042e502 </updateHash>
Actually everything!
Save it as a developer version! I personally use the name update.rdf.dev. Why is it necessary to keep a separate version for development? Because when you sign this manifest (
and we are considering a variant with the signature [comment. Of translation.] ) Its contents will become a little unreadable and unsuitable for further editing. So it’s better to keep the developer version separate and, when necessary, to sign a copy of it.
We sign the manifesto
In order to sign the manifest, follow these simple steps:
- copy the developer version of the manifest and name it update.rdf. It is this file that we will sign
- run McCoy if it is not already running
- highlight in it the key you are going to sign and select in the menu Update »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 manifesto, you may notice that it has changed a little. Actually on this work on the extension is completed - it's time to upload files to the server.
Host update.rdf
Before uploading files, we need to make sure that our server is ready to host rdf and xpi files. On Apache, we can do this through .htaccess rules (I don’t know how it works in IIS or TomCat, keep in mind - this is an Apache instruction only). 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, under it we do this:
types { application/x-xpinstall xpi; text/xml xml, rdf; }
and put it either in the general /etc/nginx/mime.types
, or in the configuration of our server. [approx. translation.] )
This is necessary for the correct return of files by the server.
This is a very important point! Otherwise, your extension will not be installed, updates will not work either. Also keep in mind: if you use any CMS (like WordPress), then it is better to place these rules in the root of the site just in case.
After everything is spelled out, you can fill in our xpi and update.rdf at the appropriate addresses. Update.rdf should be located where the install.rdf extension points (
em:updateURL
tag of the
em:updateURL
install.rdf file). The extension itself (.xpi) must be placed where update.rdf points (
updateLink
tag). 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!