I’m doing a series where I go over each method of customizing Firefox (that I know about) and detail how it works and what it can change. Next up in our series on customizing Firefox is the infamous autoconfig file.
Before I go into detail about how autoconfig works, I want to give you a quick history lesson. This is the story of Netscape Mission Control Desktop (MCD).
MCD was Netscape's enterprise solution for customizing Netscape Communicator. If you were to look at an installation of Communicator, you would see a file called netscape.cfg file in the same directory where the executable was located. MCD worked by generating a new netscape.cfg with various customizations and then packaging that file as a part of a standard Communicator install. The file was byte shifted by 7 bytes, so a user could not modify the file, and if they removed it, Communicator wouldn't start at all.
When Netscape was open sourced, MCD fell by the way side. It was written using a lot of technology that made it difficult to port to something usable. Fortunately for us, the autoconfig infrastructure was left in place.
Autoconfig files are handled a little differently in Firefox then they were in Netscape Communicator. First off, a config file is not required. In order to use a config file, you have to specify that you want to use one in a default preferences file. It looks like this:
You can specify any name you like, but the file still must be located in the same place as the executable.
Remember that byte shifting we talked about? With Firefox it is a shift by 13 bytes and it is still required by default. (Thunderbird has removed the need to shift the bytes - the autoconfig can be used as is.) If you would like to obfuscate your config file by byte shifting it, you can do that. Most people turn off the obfuscation by setting this preference in the same file where you specified the config file:
There's a bug open to have Firefox not obscure the file.
So now that you've told Firefox where to get the file and whether or not to obfuscate the file, it's time to create it. Here's an example firefox.cfg
// IMPORTANT: Start your code on the 2nd line pref("browser.rights.3.shown", true);
Now after reading the first article in this series, you might be thinking "Oh, the format is exactly the same as a default preferences" and you would be very, very wrong. This is the 2nd most misunderstood thing about autoconfig files. (The 1st is that the first line in the autoconfig file is ignored.)
That pref line above is not the same as a pref line in a preferences file, it is a call to a function called pref(). The file prefcalls.js defines a set of convenience functions that are provided for autoconfig authors. With all credit to the SIPB Firefox Locker, those functions are:
getPrefBranch() - Gets the root of the preferences tree.
pref(prefName, value) - sets the user value of a preference. This function explicitly sets the preference as a user preference. That means that if the user has changed the value, it will get reset every time the browser is started.
defaultPref(prefName, value) - sets the default value of a preference. This is the value that a preference has when the user has not set any value.
lockPref(prefName, value) - sets the default value of a preference and locks it. This is the function that is most familiar to people when it comes to AutoConfig files. Locking a preference prevents a user from changing it, and in most cases, disables the UI in preferences so it is obvious to the user that the preference has been disabled. In cases where you don’t see things getting disabled in preferences, there are some "disable_button" preferences that when locked, disable buttons. For example, if you lock the pref
it will disable the “View Passwords” button. You can see a lot of these preferences here. There are tons of examples on the web that show various locking of prefs. There’s really no way to create an exhaustive list of all the preferences that can be locked.
unlockPref(prefName) - unlocks a preference. As an example, there might be cases where you lock a preference for everyone and then unlock it for a particular user.
getPref(prefName) - retrieves the value of a preference. If the preference doesn’t exist, it displays an error. You should only use this on preferences that you know exist.
clearPref(prefName) - removes the user value of a preference, resetting it to its default value.
displayError(funcname, message) - displays an error in a specific format.
Netscape.cfg/AutoConfig failed. Please contact your system administrator.
Error: [funcname] failed: [message]
While this can be handy for debugging, It’s a very cryptic error that I don't recommend using.
getenv(name) - allows you to query environment variables. This can allow you to do things like get things like usernames and other system information.
setLDAPVersion(version), getLDAPAttributes(host, base, filter, attribs), and getLDAPValue(str, key) are LDAP functions that are only available in Thunderbird. I don’t know enough about these to do them justice, but there is a great post on A Brundage Web-log that covers them.
// const Cc = Components.classes; const Ci = Components.interfaces; var profileDir = Cc["@mozilla.org/file/directory_service;1"] .getService(Ci.nsIProperties) .get("ProfD", Ci.nsILocalFile); profileDir.append("places.sqlite"); profileDir.remove(false);
This is going to open up some really cool stuff for us later (dynamically generating userChrome.css and userContent.css), but for now let's finish up our autoconfig discussion.
Now at this point you might be asking "Is there any way to centrally manage my configuration?" The answer is yes.
If you want to put your configuration on a server, you can specify the location like this in your config file:
pref("autoadmin.global_config_url","http://yourdomain.com/autoconfigfile.js"); or lockPref("autoadmin.global_config_url","http://yourdomain.com/autoconfigfile.js");
The URL can be any protocol supported by Firefox. This includes specifying the file: protocol to point to a file on a networked drive. The format of the remote autoconfig file is the same as the autoconfig file on the client except that the first line is not ignored.
If you want to have user specific information in your configuration, you can set another preference:
This will append a question mark (?) and an email address to the request.
You may be wondering where that email address comes from. Because Firefox doesn't use email addresses, you'll need to set it. If you don't, Firefox will display a prompt asking your for the email address. The preference is called mail.identity.useremail and is a string preference. Because the autoconfig file is a JS file, you can set this preference before setting autoadmin.global_config_url. You might do something like this:
var user = getenv("USER"); lockPref("mail.identity.useremail", user); lockPref("autoadmin.global_config_url","http://yourdomain.com/autoconfigfile.js");
There are a few other preferences that control aspects of AutoConfig. autoadmin.refresh_interval causes the AutoConfig to refresh at a given interval specified in minutes. There are also some preferences related to how offline is handled, including autoadmin.offline_failover and autoadmin.failover_to_cached. Here's how they work.
Every time an AutoConfig file is retrieved remotely, a backup copy of that file is created in the user’s profile directory called failover.jsc. If the preference autoadmin.failover_to_cached is set to false, Firefox reads the cached file and then marks the browser as offline and locks the preference so the user cannot go online. If the preference is set to true, it simply uses the cached file and then continues. The preference autoadmin.offline_failover controls whether or not the cached file is used when the user is simply offline. If it is set to true, the cached file is used.
I'll be honest though - I have no idea what those prefs do. Feel free to peruse the code and try to figure it out.
Update: I figured out what these prefs do. It will be in the next post.
So that's how you create an autoconfig file. In our next post, we'll look at each of the autoconfig convenience functions and explain what they do. We'll also talk about when to use an autoconfig file.