Re: XPCOM Documentation tree

Daniel Wang <[email protected]> Fri, 09 May 2003 11:22:43 -0700
Newsgroups gmane.comp.mozilla.documentation,gmane.comp.mozilla.devel.xpcom
Organization Another Netscape Collabra Server User
Message-ID <[email protected]>
Alec Flett wrote:
> I got tired of all the meta-discussion about documentation

that's probably because newsgroup is a good place for such discussion 
and Bugzilla is a better place for discussing specifics of a doc?

> and decided
> to actually write some, starting with XPCOM... and I need your help. 
> There's an outline with links here:
> 
> http://www.mozilla.org/projects/xpcom/doc/

why not http://www.mozilla.org/catalog/architecture/xpcom/ ?
documentation and project-specific information should be kept separate

And please open a bug for tracking this

> The idea is that this guide is for clients of XPCOM - these are not the 
> internal details of how this stuff works, but rather a set of "how to 
> use XXX" style documents. The string guide and array guides are good 
> examples. If you're getting this e-mail then I'm asking you to help out 
> (see below) - at least getting us started.
> 
> [snip]
> 
> I've linked to these skeleton docs in the link above.
> There are a few areas that I think we can start documenting now, and 
> here's where I need your help:
> - [snip]
> - nsIPref* (daniel?)
> 
> There are lots of other issues that we can dwell on like:
> - these docs are in the wrong place on mozilla.org
> - I don't like the style/organization/formatting

fantasai is working on a new style guide

> [snip]
> - I want to write my docs in TeX

Please use HTML or plain/text:
- most documentation effort are done in HTML/text
- after you check in something, you should make sure the content
   isn't reformatted so much content diff doesn't show up in CVS .diff

> [snip]
> 
> Also, I'm not married to this particular organization, it is just what 
> made sense to me at the time. If you want to move/combine/split some of 
> these subject areas, feel free - lets not discuss it too much lets just 
> do it!
> Alec
> 
> P.S. see http://www.mozilla.org/README-cvs.html for easy instructions to 
> check out the files, or just:

README-cvs.html is obsolete. Use 
http://www.mozilla.org/catalog/development/website/cvs-website.html

and somebody please link 
http://www.mozilla.org/catalog/development/tools/cvs-intro.html from 
http://www.mozilla.org/cvs.html

> cvs -d:pserver:email%[email protected]:/cvsroot co 
> html/projects/xpcom/

     <style type="text/css">
         a[href*="http://lxr"] { color: #6633cc; /* text-decoration: 
underline; */}

         th, td {  vertical-align:top; }

         .indent { margin-left: 5em; }

         .table { border-collapse: collapse; }
         .table td, .table th {
             border: 1px solid #cccccc;
             padding: 0.2em;
             padding-left:0.3em;
             padding-right:0.3em;}
         .table th { text-align:left; }

         pre.codeExample {
             margin-left:4em;
             margin-right:4em;
             border:1px solid #cccccc;
             background-color:#f6f6f6;
             padding:1em;
         }

         .note { border-top:1px solid #cccccc; border-bottom:1px solid 
#cccccc;width:40em; }
     </style>

<script type="text/javascript">
function load() {
     cvsSrc = new Array (
     {re:/nsReadConfig\.(cpp|h)/, lxr:"extensions/pref/autoconfig/src/"},
     {re:/prefapi\.cpp/,          lxr:"modules/libpref/src/"},
     {re:/nsPrefService\.cpp/,    lxr:"modules/libpref/src/"},
     {re:/pldhash\.h/,            lxr:"xpcom/ds/"}
     )

     for (var i=0; i< document.links.length; i++) {
         href = document.links[i].href;
         if (href.indexOf('cvs:')==0) {
             for (var j=0; j < cvsSrc.length; j++) {
                 if (href.match(cvsSrc[j].re)) {
                     href = href.replace(cvsSrc[j].re,
                                         cvsSrc[j].lxr + "$&");
                     break;
                 } // if
             } // for
             document.links[i].href =
             href.replace(/^cvs:/, 
"http://lxr.mozilla.org/mozilla/source/");
         } // if
     }//for
}
</script>

<body onload="load();">

<p>This reference is intended for Mozilla developers and Mozilla
application developers. Users and system administrators looking
for information on editing preferences and changing defaults should
read <a href="/catalog/end-user/customizing/briefprefs.html">A Brief
Guide to Mozilla+Netscape Preferences</a>.</p>

<h3>Preference XPCOM Interfaces</h3>

<p>The libPref module provide back-end preferences access
facilities. It has two interfaces&#151;nsIPrefService and
nsIPrefBranch<sup>&dagger;</sup>&#151;. Built on top of
libPref are two extensions: AutoConfig and SystemPref.
AutoConfig provides system administrators facilities for
preference locking. SystemPref is for ????.</p>

<p class="note"><sup>&dagger;</sup>nsIPref has been deprecated.</p>

<h4>Interfaces</h4>

<p>The <strong><tt>nsIPrefService</tt></strong> interface is the main
entry point into the back-end preferences management library. The
preference service is directly responsible for the management of the
preferences files and also facilitates access to the preference branch
object which allows the direct manipulation of the preferences
themselves.</p>

<p>The following is an example code to read and set preferences in 
JavaScript:</p>

<pre class="codeExample">
<!--
var pref;
try {
     pref = ( Components.classes["@mozilla.org/preferences;1"]
            ).getService(Components.interfaces.nsIPrefService);
} catch (error) {
     // fails to load pref service
}

// getting preferences
  try {
     prefValue = pref.GetCharPref("prefName");
     // prefValue = pref.GetBoolPref("prefName");
     // prefValue = pref.GetIntPref("prefName");
} catch (error) {
     // preference loading failed, or
     // preference hasn't been set
     prefValue = defalutValue;
}

// setting preferences
pref.SetCharPref("prefName", "prefValue");
// pref.SetBoolPref("prefName", prefValue);
// pref.SetIntPref("prefName", prefValue);
-->
</pre>

<p class="note">
<b>Note</b> preference names are case-sensitive.</p>

<p>nsIPrefService does not have any function for resetting a preference
to its default. Developers may work around this issue by taking
advantage of preferences <a href="#compression">compression</a>; to
reset a preference, first set the default value (e.g. using
<code>SetDefaultBoolPref()</code>), then set the preference with the
same value.</p>

<h3>Preference Navigation</h3>

<p>Instead of always specifying full preference names, you can query
preferences from a parent node using the nsIPrefBranch interface and
read/set a preference by querying the node name.
</p>

<pre class="codeExample">
nsCOMPtr<nsIPrefBranch> prefBranch;
nsCOMPtr<nsIPrefService> prefService =
    do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);

if (NS_FAILED(rv)) return rv;

if (prefService) {
     prefService->;GetBranch("browser.",
                            getter_AddRefs(prefBranch));
}

// read "browser.fixup.alternate.enabled" pref
prefBranch->GetBoolPref("fixup.alternate.enabled",
                         getter_Copies(strValue));
</pre>

<h3>Reading a Preference of Arbitrary Type</h3>

<p>The <code>GetPrefType(char*)</code> method returns a flag indicating
<a href="cvs:prefapi.h#188">type</a>. You can use this method to
determine if a preference is a Boolean, integer, or string. The
following is a C++ example of using
<code>nsIPrefBranch::GetPrefType()</code> to read a preference of
arbitrary type:</p>

<pre class="codeExample">
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIServiceManager.h"
   :
   :

nsresult test::readPref(const char *aPrefName)
{
    nsresult rv;

    nsCOMPtr<nsIPrefService> prefService =
       do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
    if (NS_FAILED(rv))
       return rv;

    nsCOMPtr<nsIPrefBranch> prefBranch;
    rv = prefService->GetDefaultBranch(nsnull, getter_AddRefs(prefBranch));
    if (NS_FAILED(rv))
       return rv;

    char* strValue = nsnull;
    PRInt32 intValue = 0;
    PRBool boolValue = PR_FALSE;
    PRInt32 prefType = nsIPrefBranch::PREF_INVALID;

    rv = prefBranch->GetPrefType(aPrefName, &prefType);

    switch(prefType) {
         case nsIPrefBranch::PREF_STRING:
             prefBranch->GetCharPref(aPrefName, getter_Copies(strValue));
             // do other stuff here
             break;
         case nsIPrefBranch::PREF_INT:
             prefBranch->GetIntPref(aPrefName, &intValue);
             // do other stuff here
             break;
         case nsIPrefBranch::PREF_BOOL:
             prefBranch->GetBoolPref(aPrefName, &boolValue);
             // do other stuff here
             break;
         default:
             return NS_ERROR_FAILURE;
    }

    return NS_OK;
}
</pre>

<h3>Listening for Preference Changes</h3>
<p>You can register an observer with a Preference object to listen to any
change to a particular preference you are interested in. The following is
a C++ example of listening to the <tt>browser.fixup.alternate.enabled</tt>
preference.</p>

<pre class="codeExample">
nsresult tester::Init()
{
    nsresult rv;
    if (!gPrefBranch) {
       nsCOMPtr<nsIPrefService> prefs = 
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = prefs->GetBranch(PREF_BRANCH_BASE, &gPrefBranch);
       NS_ENSURE_SUCCESS(rv, rv);
    }

    nsCOMPtr<nsIPrefBranch> pb = do_QueryInterface(gPrefBranch);

    if (pb) {
       pb->AddObserver("browser.fixup.alternate.enabled", this, PR_FALSE);
    }
}

// inherited from public class nsIObserver
NS_IMETHODIMP tester::Observe(nsISupports *aSubject,
                               const char *aTopic,
                               const PRUnichar *aSomeData)
{
    if (!nsCRT::strcmp(aTopic, "nsPref:changed")) {
       NS_ENSURE_STATE(gPrefBranch);

       PRBool boolValue = PR_FALSE;

       if (!nsCRT::strcmp(aSomeData, "browser.fixup.alternate.enabled") {
          // domain autocompletion is has been enabled/disabled
          gPrefBranch->GetBoolPref("browser.fixup.alternate.enabled", 
&boolValue);
          // do something else
       }
    }
}
</pre>

<h3>Locking and Unlocking a Preference</h3>

<p>The following is a C++ code example of locking and unloading a preference
dynamically:</p>

<pre class="codeExample">
RBool isLocked;
prefBranch->PrefIsLocked("preferencename", &isLocked);
if (isLocked)
    prefBranch->UnlockPref("preferencename");
:
prefBranch->LockPref("preferencename");
</pre>

<p style="color:red">Example of loading a custom user pref file via
nsIPrefService::ReadUserPrefs needed.</p>