Deploying Firefox 2 within the Enterprise: Part 5

IMPORTANT! Some of the information in this post is not correct. I will be updating it soon.

Updated: See section on serving the update.xml file

OK, now that we have MAR files, how do we get them to our users?

Setting Up a Firefox Update Server

A Firefox update server is actually not that complex of a setup. Basically a Firefox update server takes a URL that describes a particular Firefox version, and if there is an update available, it returns an XML file that identifies the location of the update. So let’s take a look at this URL.

If you are to go into about:config and search for app.update.url, you would see the following:

https://aus2.mozilla.org/update/1/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/update.xml

When Firefox 2.0.0.3 looks for an upgrade (English on Windows), the URL looks like this:

https://aus2.mozilla.org/update/1/Firefox/2.0.0.3/2007030919/WINNT_x86-msvc/en-US/release/update.xml

Most of this URL is self explanatory. The only part we need to explain is BUILD_ID. The build ID of a Firefox is a unique identifer that conveys the exact date down to the hour when a build was created. For the build above, that data is March 9, 2007 at 7:00 PM. You can see the build ID for any Firefox build by type about: in the URL bar. Note that selecting Help->About does not display the complete build ID. If you build a custom version of Firefox, you can see the build ID by looking in the file mozilla/obj/config/nsBuildID.h. If you see a build ID of 0000000000 in this file, it means that you forgot to set MOZILLA_OFFICIAL and BUILD_OFFICIAL before building.

If we look at the URL that is served, it ends in update.xml. So what do these update.xml files look like? Here’s the update.xml to upgrade from Firefox 2.0.0.2 to Firefox 2.0.0.3. (https://aus2.mozilla.org/update/1/Firefox/2.0.0.2/2007021917/WINNT_x86-msvc/en-US/release/update.xml)

<?xml version="1.0"?>
<updates>
  <update type="minor"
          version="2.0.0.3"
          extensionVersion="2.0.0.3"
          buildID="2007030919"
          detailsURL="http://en-US.www.mozilla.com/en-US/firefox/2.0.0.3/releasenotes/">
    <patch type="complete"
           URL="http://download.mozilla.org/?product=firefox-2.0.0.3-complete&amp;os=win&amp;lang=en-US"
           hashFunction="SHA1"
           hashValue="bc64376c13867b5524d71e87f7ad98e727f2d3f4"
           size="7617299"/>
    <patch type="partial"
           URL="http://download.mozilla.org/?product=firefox-2.0.0.3-partial-2.0.0.2&amp;os=win&amp;lang=en-US"
           hashFunction="SHA1"
           hashValue="2555dcad94c9bc1c7327cb3699844f633888ea4a"
           size="270514"/>
  </update>
</updates>

Rather then go into a lot of detail here about this file, I’d rather point you to wiki.mozilla.org which has a great explanation of this file. (Incidentally, the wiki you can lots of other great information about the Software Update process) One thing you might be wondering is how to generate the hashValue. Microsoft has a tool available called FCIV that can be used to generate the hashes.

OK, we know the URL and we have the update.xml file, so how do we serve it to the browser?


Update: as Benjamin Smedberg pointed out, I am doing a lot of work for nothing. mod_rewrite can be used to accomplish this task. Create a file called “noupdate.xml” that contains <updates></updates>Then put this in a .htaccess file:

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) noupdate.xml

What this says is if you find the file, serve it, if you don’t, serve the file that represents the empty update.


At first, it looks like we can just setup directories that correspond to the URL, but this won’t work since we need to send an XML file that looks like:

<updates>
</updates>

If there are no updates available. So I’m going to use a simple PHP file to function as our update server. We’ll need to do some changes to our web server configuration as well. Note I am using Apache.

First go into httpd.conf and make sure that mod_rewrite is available. Then go into your main web directory and add or edit the file .htaccess with this:

RewriteEngine on
RewriteRule ^/?update/(.*) /update.php/$1 [L]

What this rule says is whenever you see a URL that begins with “update” send it to update.php. The actual update.php file looks like this:

<?php
header("Content-type: text/xml");

$url_array=explode("/",$_SERVER["REQUEST_URI"]);
$noidea=$url_array[2];
$product=$url_array[3];
$version=$url_array[4];
$build_id=$url_array[5];
$build_target=$url_array[6];
$locale=$url_array[7];
$channel=$url_array[8];
$filename=$url_array[9];

$updatefile = "$noidea/$product/$version/$build_id/$build_target/$locale/$channel/$filename";
//echo "$updatefile";

if (file_exists($updatefile)) {
  $handle = fopen($updatefile, "r");
  $contents = fread($handle, filesize($updatefile));
  echo "$contents";
  fclose($handle);
} else {
  echo '';
  echo '';
}
?>

This PHP simply looks for the presence of an update.xml directory structure specified by the URL and if it is available, it returns it, otherwise it returns <updates></updates>

So how do we publish updates then? We simply create an update.xml file and place it in the appropriate subdirectory.

The last step is updating the browser to point to our new update URL. Your first thought might have been to simple update app.update.url in about:config, but that will not work. When app.update.url is queried by Firefox, it always looks for the “default preference” which means that even if a user changes the preference, it won’t be used. For testing purposes, you can add a new preference called “app.update.url.override” that will work, but when you go to deploy your updates, you should set app.update.url in an extension like the CCK. That will cause it to become a “default preference.”

One more installment to go. I’ll try to address some general deployment issues, and if you have questions (any questions), PLEASE let me know.

Please note: I reserve the right to delete comments that are offensive or off-topic.

Leave a Reply

Your email address will not be published. Required fields are marked *

9 thoughts on “Deploying Firefox 2 within the Enterprise: Part 5

  1. Could you move the MAR articles you’ve written over to DevMo, and cross-reference them from the XULRunner pages? Software update was a topic of some discussion at the Mountain View Dev Day, particularly the lack of docs on it. What you’ve written here sounds like it could apply to XULRunner-based apps, not just Firefox.

  2. Fantastic offerings, thanks. One further thing that we considered for this process was how to deploy FF in a restricted environment. It wouldnt be hard to write a script to manually push the MAR files and perform a manual install during boot, ../firefox-update/updater ../firefox-update 0 (http://wiki.mozilla.org/Software_Update:Manually_Installing_a_MAR_file), dynamic checking by the script on the process is even possible by looking at a the update.status file (http://wiki.mozilla.org/Software_Update:Processing_Updates). Dont know how well this would work in non-interactive mode, given that updates to extensions are checked on the next launch.

  3. Eric, you are looking for some software deployment tool, which has a local agent running under some admin/system account. That would do the trick. But you would have to use the deployment tool to update software.
    Mike, for me it is an ideal source for disabling auto-update via .htaccess/update.php and the CCK extension. Because updates will be rolled out over my deployment tool.

  4. Hello, Mike
    I need your advise.
    I want setup my own update server for LAN there more 1200 users already installed various versions Mozilla Thunderbird 2.0.0.x / FireFox 2.0.x.x – 3.0.x as well, I already have a Apache web server.

    The strategy with using update.xml + URL(REST) extremely inconvenient because

    I must manually create all specific directories, subdirectories and update.xml’s files(?) for all bunch versions usable by my end-users. It’s realy terrible :\

    Exist more loyal method create local update server?