|
|
(24 intermediate revisions by 6 users not shown) |
Line 1: |
Line 1: |
| {{extdev}}
| | Moved [http://developer.mozilla.org/en/docs/Code_snippets:Preferences here] |
|
| |
|
| 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. <!-- Read about preferences in general [[??? | here]]. -->
| | [[Category:Redirects]] |
| | |
| If you haven't yet, read other documents about Mozilla preferences on XUL Planet and on mozilla.org (links below in [[#Resources|Resources section]]).
| |
| | |
| ==XPCOM interfaces for preferences system==
| |
| Mozilla exposes its preferences system through a few XPCOM interfaces. Look in the [[#Resources|Resources section]] below for the link to list of preferences-related interfaces.
| |
| | |
| Three most used interfaces are <code>nsIPrefService</code>, <code>nsIPrefBranch</code> and <code>nsIPrefBranchInternal</code>. First two are frozen and will not change, last one is “internal”, but is very useful because it allows you to set up prefs observers — see below for an example.
| |
| | |
| It's worth noting that there also is an <code>nsIPref</code> interface. Despite it being used in some places, it is '''deprecated''' and should not be used.
| |
| | |
| Preferences service is instantiated exactly as any other service. (See [http://xulplanet.com/references/xpcomref/creatingcomps.html Creating XPCOM Components] document at XUL Planet for details.) To get an <code>nsIPrefBranch</code>, either QI the pref service (that will give you the root branch) or call <code>nsIPrefService.getBranch()</code> to get a sub-branch.
| |
| | |
| Here are two examples:
| |
| <pre>
| |
| // Get the root branch
| |
| var prefs = Components.classes["@mozilla.org/preferences-service;1"].
| |
| getService(Components.interfaces.nsIPrefBranch);
| |
| </pre>
| |
| <pre>
| |
| // Get the "extensions.myext." branch
| |
| var prefs = Components.classes["@mozilla.org/preferences-service;1"].
| |
| getService(Components.interfaces.nsIPrefService);
| |
| prefs = prefs.getBranch("extensions.myext.");
| |
| </pre>
| |
| | |
| ==Simple types==
| |
| There 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 <code>nsIPrefBranch</code> that read and write them: <code>getBoolPref</code>, <code>setBoolPref</code>, <code>getCharPref</code>, <code>setCharPref</code>, <code>getIntPref</code> and <code>setIntPref</code>. Using them is as easy as:
| |
| <pre>
| |
| // 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
| |
| </pre>
| |
| | |
| ==Complex types==
| |
| As 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 <code>nsILocalFile</code> and <code>nsISupportsString</code> objects in preferences (as strings — note that from the preferences system's POV, complex values have a <code>nsIPrefBranch.PREF_STRING</code> type.)
| |
| | |
| There are two <code>nsIPrefBranch</code> methods implementing the concept — <code>setComplexValue</code> and <code>getComplexValue</code>. You can look up their implementation in [http://lxr.mozilla.org/mozilla/source/modules/libpref/src/nsPrefBranch.cpp#221 nsPrefBranch.cpp]. Here is the IDL definition:
| |
| <pre>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);</pre>
| |
| | |
| As you can see, both of them take <code>aType</code> parameter. It can have the following values <small>(to be precise, you should pass <code>Components.interfaces.nsIWhatever</code> instead of just <code>nsIWhatever</code>, which is undefined):</small>
| |
| *<code>[[#nsISupportsString|nsISupportsString]]</code> — used to handle unicode strings in preferences. Use this when the preference value may contain non-ASCII characters (for example, user's name).
| |
| *<code>[[#nsIPrefLocalizedString|nsIPrefLocalizedString]]</code> — almost same as <code>nsISupportsString</code>, but it is handled differently in <code>getComplexValue</code> when there's no user value for given preference, see below for details.
| |
| *[[Dev : Extensions : Example Code : File IO|<code>nsILocalFile</code> and <code>nsIRelativeFilePref</code>]] — store paths in preferences. <code>nsILocalFile</code> is used to store absolute paths, while <code>nsIRelativeFilePref</code> is used to store paths relative to one of “special” directories, like the profile folder.
| |
| | |
| ===nsISupportsString===
| |
| As noted above, this is used to handle unicode strings in preferences. Example:
| |
| <pre>
| |
| // 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);
| |
| </pre>
| |
| | |
| ===nsIPrefLocalizedString===
| |
| Another complex type supported by Mozilla is <code>nsIPrefLocalizedString</code>. It is similar to <code>nsISupportsString</code>, the only difference is that when there is no user value, <code>getComplexValue</code> gets the default value from a locale file (thus making the default value localizable).
| |
| | |
| It's easier to explain this on example. Let's say you want to make the default value for <code>extensions.myext.welcomemessage</code> preference localizable. You should do the following:
| |
| <ol>
| |
| <li>Add this line to some <code>.properties</code> file (for all of your locales), say to <code>chrome://myext/locale/defaults.properties</code>:
| |
| <pre>extensions.myext.welcomemessage=Localized default value</pre></li>
| |
| | |
| <li>Add the default value for <code>extensions.myext.welcomemessage</code>, pointing to that properties file, by adding the following line to your file with ''default preferences'' (see below).
| |
| <pre>pref("extensions.myext.welcomemessage", "chrome://myext/locale/defaults.properties");</pre>
| |
| </li>
| |
| | |
| <li>Read the preference with <code>getComplexValue</code>, passing <code>nsIPrefLocalizedString</code> as <code>aType</code>:
| |
| <pre>
| |
| var prefs = Components.classes["@mozilla.org/preferences-service;1"].
| |
| getService(Components.interfaces.nsIPrefService);
| |
| var branch = prefs.getBranch("extensions.myext.");
| |
| var value = branch.getComplexValue("welcomemessage",
| |
| Components.interfaces.nsIPrefLocalizedString).data;
| |
| </pre></li>
| |
| </ol>
| |
| | |
| The code in step 3 will read the default value from <code>chrome://myext/locale/defaults.properties</code> when no user value is set, and will behave exactly the same as if <code>nsISupportsString</code> was passed as <code>aType</code> otherwise.
| |
| | |
| ===nsILocalFile and nsIRelativeFilePref===
| |
| <!-- Leave this section to have nice TOC -->
| |
| Please see the [[Dev : Extensions : Example Code : File IO|File IO article]] for details on <code>nsILocalFile</code> and <code>nsIRelativeFilePref</code>.
| |
| | |
| ==Default preferences==
| |
| <!-- someone should reword this section -->
| |
| Each 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.
| |
| | |
| ===What effect do default preferences have on various ''get'' methods===
| |
| When one of ''get'' methods of <code>nsIPrefBranch</code> (assuming it's a branch of the tree with current values) is called, it does the following:
| |
| #Checks whether the “current” tree has a value for the pref and whether the pref is locked.
| |
| #If there's a value of correct type (f.e. <code>getBoolValue</code> expects a value of type <code>nsIPrefBranch.PREF_BOOL</code>), and the preference is not locked, the method returns that value.
| |
| #If there's a value of incorrect type and the pref is not locked, an exception is thrown (<code>NS_ERROR_UNEXPECTED</code>)
| |
| #If the preference is locked or if there is no value for that preference in “current” tree, the ''get'' method checks the default tree.
| |
| #If there's a value of expected type in the “default” tree, it is returned (with the only exception, <code>getComplexValue</code> with <code>aType</code> parameter = <code>nsIPrefLocalizedString</code>, [[#nsIPrefLocalizedString|described above]])
| |
| #Otherwise an exception is thrown (<code>NS_ERROR_UNEXPECTED</code>).
| |
| | |
| If the branch is from the “default” tree, the ''get'' method doesn't check the tree with current values at all.
| |
| | |
| <small>(This is not exactly how it's coded in <code>libpref</code>, but it's equivalent)</small>
| |
| | |
| ===Where are the default values read from===
| |
| *All Mozilla-based applications read <code>(application directory)/defaults/pref/*.js</code> <!-- (xxx are non-.js files read?) -->.
| |
| * In addition to that, the recent versions of new toolkit applications (Firefox 1.0, Thunderbird 1.0 and the like; '''not''' Mozilla Suite) read files listed in <code>(profile folder)/defaults.ini</code> — usually <code>(profile folder)/extensions/{guid}/defaults/preferences/</code>
| |
| | |
| ===How to install extension's defaults files===
| |
| For Mozilla, copy them to <code>(appdir)/defaults/pref</code> in your [[Install.js|install script]].
| |
| | |
| For Firefox/Thunderbird, just put them in <code>myext.xpi/defaults/preferences/</code>. They will be copied and registered in <code>defaults.ini</code> automatically.
| |
| | |
| ==Using preferences observers==
| |
| You can use <code>nsIPrefBranchInternal</code> interface to “listen” to changes to preferences in a certain branch. Here's an example (note, this code hasn't actually been tested, so it may contain typos and other errors):
| |
| | |
| <pre>var myPrefObserver =
| |
| {
| |
| register: function()
| |
| {
| |
| var prefService = Components.classes["@mozilla.org/preferences-service;1"].
| |
| getService(Components.interfaces.nsIPrefService);
| |
| this._branch = prefService.getBranch("extensions.myextension.");
| |
| | |
| var pbi = this._branch.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
| |
| pbi.addObserver("", this, false);
| |
| },
| |
| | |
| unregister: function()
| |
| {
| |
| if(!this._branch) return;
| |
| | |
| var pbi = this._branch.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
| |
| pbi.removeObserver("", this);
| |
| },
| |
| | |
| observe: function(aSubject, aTopic, aData)
| |
| {
| |
| if(aTopic != "nsPref:changed") return;
| |
| // aSubject is the nsIPrefBranch we're observing
| |
| switch (aData) {
| |
| case "pref1":
| |
| // extensions.myextension.pref1 was changed
| |
| break;
| |
| case "pref2":
| |
| // extensions.myextension.pref2 was changed
| |
| break;
| |
| }
| |
| }
| |
| }
| |
| myPrefListener.register();
| |
| </pre>
| |
| | |
| ==Resources==
| |
| *Other documentation on preferences
| |
| **[http://www.mozilla.org/catalog/end-user/customizing/briefprefs.html A Brief Guide to Mozilla Preferences] — describes preferences system from user's / administrator's POV.
| |
| **[http://www.xulplanet.com/tutorials/xulqa/q_prefs.html XUL Planet's article on preferences] — an explanation of the preferences system with simple examples. A must read.
| |
| *Mozilla XPCOM interfaces of the preferences system.
| |
| **[http://xulplanet.com/references/xpcomref/group_Preferences.html#Preferences Complete list]
| |
| **Most used interfaces (these are frozen and will not change): [http://xulplanet.com/references/xpcomref/ifaces/nsIPrefBranch.html <code>nsIPrefBranch</code>] and [http://xulplanet.com/references/xpcomref/ifaces/nsIPrefService.html <code>nsIPrefService</code>]
| |
| *[http://lxr.mozilla.org/mozilla/source/modules/libpref/ LXR pages for <code>libpref</code>], the module implementing preferences system.
| |
| | |
| [[Category:Example code|Using preferences]] [[Category:XPCOM example code|Using preferences]]
| |