Dev : Using preferencesFrom MozillaZine Knowledge Base(Difference between revisions)
Revision as of 01:25, 11 February 2006This page is part of the extension development documentation project. Ask your questions in MozillaZine Forums. Also try browsing example code. Note: development documentation is in process of being moved to Mozilla Development Center (MDC). This article is about using Mozilla Preferences system. Information here applies to the Mozilla Suite, Firefox, Thunderbird and possibly other Mozilla-based applications. Intended audience is Mozilla extension developers who wish to learn details about using preferences in Mozilla. If you haven't yet, read other documents about Mozilla preferences on XUL Planet and on mozilla.org (links below in Resources section). Note: This article doesn't cover all available methods for manipulating preferences yet, please refer to XulPlanet XPCOM reference pages listed in Resources section for the complete list of methods. The interfaces dealing with preferences are fairly well documented, so using the methods not documented here should be easy.
XPCOM interfaces for preferences systemMozilla exposes its preferences system through a few XPCOM interfaces. Look in the Resources section below for the link to list of preferences-related interfaces. Three most used interfaces are It's worth noting that there also is an Preferences service is instantiated exactly as any other service. (See Creating XPCOM Components document at XUL Planet for details.) To get an Here are two examples: // Get the root branch var prefs = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefBranch); // Get the "extensions.myext." branch var prefs = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.myext."); Simple typesThere are three types of preferences: string, integer and boolean. Each entry in preferences database (prefs.js) has one of those types. There are six methods of // prefs is an nsIPrefBranch. // Look in the above section for examples of getting one. var value = prefs.getBoolPref("accessibility.typeaheadfind"); // get a pref prefs.setBoolPref("accessibility.typeaheadfind", !value); // set a pref Complex typesAs noted in previous section, each entry in prefs database (prefs.js) must have a string, an integer or a boolean value. However, there is a concept of complex types, which makes it easier for developers to save and load There are two void getComplexValue(in string aPrefName, in nsIIDRef aType, [iid_is(aType), retval] out nsQIResult aValue); void setComplexValue(in string aPrefName, in nsIIDRef aType, in nsISupports aValue); As you can see, both of them take
nsISupportsStringAs noted above, this is used to handle unicode strings in preferences. Example: // prefs is an nsIPrefBranch // Example 1: getting unicode value var value = prefs.getComplexValue("preference.with.non.ascii.value", Components.interfaces.nsISupportsString).data; // Example 2: setting unicode value var str = Components.classes["@mozilla.org/supports-string;1"] .createInstance(Components.interfaces.nsISupportsString); str.data = "some non-ascii text"; prefs.setComplexValue("preference.with.non.ascii.value", Components.interfaces.nsISupportsString, str); nsIPrefLocalizedStringAnother complex type supported by Mozilla is It's easier to explain this on example. Let's say you want to make the default value for
The code in step 3 will read the default value from nsILocalFile and nsIRelativeFilePrefPlease see the File IO article for details on Default preferencesEach preference may have up to two values — current and default. That means there are two “pref trees” — current and default, — and each of them may or may not have a value for preference in question. You can see the list of preferences in about:config (where available). Preferences that have user value are bold, those that don't have a user value are printed in normal font. You can get both trees using What effect do default preferences have on various get methodsWhen one of get methods of
If the branch is from the “default” tree, the get method doesn't check the tree with current values at all. (This is not exactly how it's coded in Where are the default values read from
These files use simple JS-like syntax. To add a default value for a preference, you should add a line like this to your default preferences file: pref("extensions.infolister.hide_menu_item", false); How to install extension's defaults filesFor Mozilla, copy them to For Firefox/Thunderbird, just put them in More about preferences "branches"Preferences names consist of a few strings separated with dots, and related prefs usually share the same prefix. For example, most accessibility preferences in Mozilla start with "accessibility." This means that all existing preferences can be imagined as if they were in a tree, like this: + | +-- accessibility | | | +-- typeaheadfind | | | | | +-- autostart (accessibility.typeaheadfind.autostart) | | | | | +-- enablesound (accessibility.typeaheadfind.enablesound) | | | +-- usebrailledisplay (accessibility.usebrailledisplay) | +-- extensions | +-- lastAppVersion (extensions.lastAppVersion) This is the metaphor behind var prefs = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefService); var branch = prefs.getBranch("acce"); var enablesound = branch.getBoolPref("ssibility.typeaheadfind.enablesound"); This is the reason why you should usually pass strings ending with a dot to Another caveat you should be aware of is that var branch = prefs.getBranch("accessibility."); var children = branch.getChildList("", {}); will return these items (for the example tree above): Using preferences observersYou can use
Here's an example (note, this code hasn't actually been tested, so it may contain typos and other errors): var myPrefObserver = { register: function() { var prefService = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); this._branch = prefService.getBranch("extensions.myextension."); this._branch.QueryInterface(Components.interfaces.nsIPrefBranch2); this._branch.addObserver("", this, false); }, unregister: function() { if(!this._branch) return; this._branch.removeObserver("", this); }, observe: function(aSubject, aTopic, aData) { if(aTopic != "nsPref:changed") return; // aSubject is the nsIPrefBranch we're observing (after appropriate QI) // aData is the name of the pref that's been changed (relative to aSubject) switch (aData) { case "pref1": // extensions.myextension.pref1 was changed break; case "pref2": // extensions.myextension.pref2 was changed break; } } } myPrefListener.register(); Using prefHasUserValueprefHasUserValue(preference) checks whether the preference has been changes from the default value to another one (by an user or an extension), if so it will return true, else false. in addition prefHasUserValue can be also used to check whether a preference exists. if calling a preference e.g. by getCharPref which was not defined previously the system will throw an exception (which of course can be handled by try...catch (which is not a nice solution to check whether a preference exists)). Using prefHasUserValue will return false if the preference was not defined before. This can be used for example to initialize an extension (see code snippet below). ... var QuickMenuMC_pref = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); ... if(QuickMenuMC_pref.prefHasUserValue("QuickMenuMC.FolderLabel")){ ... } Using preferences in extensionsIf you're writing your extension for one of Toolkit applications (Firefox, Thunderbird, Nvu), it's recommended to provide default values for your extension's preferences (see above for information on how to do it). It has the following benefits:
JavaScript wrappers for preferences systemThere are a few JavaScript wrappers to make your life easier: see
this, this, and the Resources
|