Team LiB
Previous Section Next Section

Hack 23. Play With the Preference System

Dig underneath Firefox's user interface and hack the preference system directly.

Firefox's preference system holds many of the small configuration items of the Firefox browser. These items are hidden from the user: behind formal user interfaces, unimplemented by user interfaces, or invisible because no default values are recorded anywhere. This hack explains how to work with the preference system directly.

3.3.1. Understanding the Preference Database

The preference system is equivalent to a tiny database. It sits in memory while Firefox runs. The preference database is a thread-safe but single-user database. It consists of a single table of four columns:


Name

Contains a unique string that identifies the preference. This is the primary key.


Value

Contains the data for the preference. It can be a string, number, or true/false (Boolean) value.


Locked Attribute

States whether the preference has been locked. Users cannot change locked preferences.


Default Attribute

Remains true as long as the user does not set (override) the preference.

The last two columns are not set explicitly; they are set indirectly [Section 3.3.4, later in this hack] Here is a typical preference:

Name                                    Value
----                              -----
browser.chrome.site_icons          true   /* not locked, user set */

Any string (within reason) can be used as a preference name. The dots (periods) are not especially meaningful. They are just a convenience for programmers. Programmers can compose a query that pulls out all the preferences that start with a given string followed by a dot. Dots also help readers classify preferences into a simple hierarchy.

Like any database table, you can add whatever rows (preferences) you like. However, Firefox will look only at preferences that it knows about. All others are excess baggage. An extension or other code can add new preferences. Upgrading from old Mozilla or Netscape versions can also add preferences. Firefox will ignore all preferences that it doesn't understand. If extensions need to read the preference database, they do that on their own initiative.

The preference database is constructed by reading files from disk when Firefox starts up. The database is not written out in full before or while Firefox shuts down. There is nowhere on disk where you can see all the currently set preferences. However, you can see all the currently set preferences using the about:config URL, discussed next.

There is also nowhere where you can get a list of all known preferences. There are, however, several web pages that act as preference birdwatchers. They provide extensive lists of preferences spotted in the wild. It's not really as bad as it sounds; the majority of preferences are very well known.

3.3.2. Tweaking Preferences with about:config

The special about:config URL provides an XUL page inside the normal HTML display area. It can be used to query, insert, update, and delete preferences. Preferences changed here are accurately picked up by any configuration dialog boxes in Firefox that also use those preferences. Any changes made apply immediately.

Figure 3-1 shows this page at work after all preferences have been filtered to display only those whose names contain the substring browser (You can filter preferences by putting something in the top Filter: field.). One preference has been context-clicked to reveal the set of operations that can be applied. The options under the New submenu are not specific to the highlighted preference.

Figure 3-1. Generic preferences interface


The Status column describes whether the preference is user set or not (see the next section for more details). All such preferences are shown in bold. In such cases, it is usually harmless to choose Reset from the context menu to take away changes made by the user of the current Firefox profile. There is no undo functionality; if you change a preference, you must remember to change it back.

Many preferences are meaningful on their own. Some preferences, however, work together in groups. If you use about:config, any required coordination between preferences is up to you. Most Firefox dialog boxes do the coordination for you.

3.3.3. Spotting Files that Contribute to Preferences

Preference files exist in both the install area and the profile area. They run in a certain order, and later scripts can override some settings that earlier scripts have made.

The install area folder defaults/pref contains .js preference scripts delivered with the Firefox install. These scripts are executed first when Firefox starts up. All files in that directory are executed. By default, only the standard files firefox.js and firefox-l10n.js are present.

The install area can also contain a .cfg ReadConfig configuration script [Hack #29] . That file, if it exists, is read second on startup.

The profile area can contain a prefs.js script, one per profile. It is run third on startup. No such file is provided with the standard install. This file is written to when preferences change, and it's also written to when Firefox shuts down. It contains only those preferences whose values have been changed from the values set by install-area preference scripts. This makes copying the prefs.js script between profiles both easy (because it is a small set of changes to manage) and hard (because it is an incomplete picture).

Lastly, the profile area can contain a user.js script, one per profile, in the same directory as the prefs.js script. This file must be put in place by hand. No such file is supplied at install time. This script is run last on Firefox startup.

3.3.4. Modifying Preference Files

All files that contribute to preferences are JavaScript files (but see also the special case of remote configuration [Hack #29] ), which means they must contain JavaScript syntax. If bad syntax is used, the script will fail silently. Although JavaScript 1.5 does not insist on trailing semicolons on each line, future versions will, so put them in. Putting in general-purpose JavaScript code is not at all useful; the only useful thing to do is to call one of these functions:

pref(name, value);
user_pref(name, value);
lockPref(name, value);
unlockPref(name, value);

Therefore, here's a simple example of setting a preference:

user_pref("browser.chrome.site_icons", false);

If you're doing remote configuration, double-check the names used. Some names are different in that environment. Here are the standard preference functions:


pref( name, value);

This function sets the named preference, if it is not locked, and turns on the default attribute. It can be called by all preference scripts.


user_pref( name, value);

This function sets the named preference, if it is not locked, and turns off the default attribute. It can be called by all preference scripts. It is the only function that is sensible to put in user.js.


lockPref( name, value);

This function sets the named preference and also sets the locked attribute. It can be used only in remote configuration .cfg scripts.


unlockPref( name, value);

This function sets the named preference and also unsets the locked attribute. It can be used only in remote configuration .cfg scripts.

    Team LiB
    Previous Section Next Section