mozilla-gconf-backend.patch
changeset 24 ca988be0905b
child 59 604517bb16d8
equal deleted inserted replaced
23:c62859a2fd22 24:ca988be0905b
       
     1 From: various contributors
       
     2 Subject: replace gconf backend with more complete mapping for lockdown feature
       
     3 
       
     4 diff --git a/extensions/pref/Makefile.in b/extensions/pref/Makefile.in
       
     5 --- a/extensions/pref/Makefile.in
       
     6 +++ b/extensions/pref/Makefile.in
       
     7 @@ -40,13 +40,13 @@ DEPTH            = ../..
       
     8  topsrcdir        = @top_srcdir@
       
     9  srcdir           = @srcdir@
       
    10  VPATH            = @srcdir@
       
    11  
       
    12  include $(DEPTH)/config/autoconf.mk
       
    13  
       
    14  DIRS             = autoconfig
       
    15  
       
    16 -ifdef MOZ_ENABLE_GTK2
       
    17 +ifdef MOZ_ENABLE_GCONF
       
    18  DIRS		+= system-pref
       
    19  endif
       
    20  
       
    21  include $(topsrcdir)/config/rules.mk
       
    22 diff --git a/extensions/pref/system-pref/src/Makefile.in b/extensions/pref/system-pref/src/Makefile.in
       
    23 --- a/extensions/pref/system-pref/src/Makefile.in
       
    24 +++ b/extensions/pref/system-pref/src/Makefile.in
       
    25 @@ -38,47 +38,41 @@
       
    26  DEPTH = ../../../..
       
    27  topsrcdir = @top_srcdir@
       
    28  srcdir = @srcdir@
       
    29  VPATH = @srcdir@
       
    30  
       
    31  include $(DEPTH)/config/autoconf.mk
       
    32  
       
    33  MODULE = system-pref
       
    34 -LIBRARY_NAME = system-pref_s
       
    35 +LIBRARY_NAME = system-pref
       
    36  ifneq ($(OS_ARCH),WINNT)
       
    37  SHORT_LIBNAME = syspref
       
    38  endif
       
    39  
       
    40  # We want to force the creation of a static lib.
       
    41 -FORCE_STATIC_LIB = 1
       
    42 -LIBXUL_LIBRARY = 1
       
    43 +#FORCE_STATIC_LIB = 1
       
    44 +LIBXUL_LIBRARY   = 1
       
    45 +MODULE_NAME      = nsSystemPrefModule
       
    46 +IS_COMPONENT     = 1
       
    47 +EXPORT_LIBRARY   = 1
       
    48  
       
    49  REQUIRES        = xpcom \
       
    50  		  string \
       
    51  		  embedcomponents \
       
    52  		  pref \
       
    53  		  $(NULL)
       
    54  
       
    55 -ifdef MOZ_ENABLE_GTK2
       
    56 -DIRS		= gconf
       
    57 -endif
       
    58 +CPPSRCS =   \
       
    59 +  nsSystemPref.cpp	   \
       
    60 +  nsSystemPrefFactory.cpp  \
       
    61 +  $(NULL)
       
    62  
       
    63  EXTRA_DSO_LDOPTS = \
       
    64 -		-L$(DIST)/bin \
       
    65  		$(MOZ_COMPONENT_LIBS) \
       
    66  		$(NULL)
       
    67  
       
    68 -CPPSRCS =   \
       
    69 -  nsSystemPref.cpp	   \
       
    70 -  $(NULL)
       
    71 -
       
    72  EXPORTS		= \
       
    73 -		nsSystemPrefLog.h \
       
    74 +		nsISystemPrefService.h \
       
    75  		$(NULL)
       
    76  
       
    77  include $(topsrcdir)/config/rules.mk
       
    78  
       
    79 -ifdef MOZ_ENABLE_GTK2
       
    80 -INCLUDES	+= \
       
    81 -		-I$(srcdir)/gconf \
       
    82 -		$(NULL)
       
    83 -endif
       
    84 diff --git a/extensions/pref/system-pref/src/gconf/Makefile.in b/extensions/pref/system-pref/src/gconf/Makefile.in
       
    85 --- a/extensions/pref/system-pref/src/gconf/Makefile.in
       
    86 +++ b/extensions/pref/system-pref/src/gconf/Makefile.in
       
    87 @@ -37,50 +37,37 @@
       
    88  
       
    89  DEPTH = ../../../../..
       
    90  topsrcdir = @top_srcdir@
       
    91  srcdir = @srcdir@
       
    92  VPATH = @srcdir@
       
    93  
       
    94  include $(DEPTH)/config/autoconf.mk
       
    95  
       
    96 -MODULE = system-pref
       
    97 -LIBRARY_NAME = system-pref
       
    98 -LIBXUL_LIBRARY = 1
       
    99 +MODULE = system-pref-gconf
       
   100 +LIBRARY_NAME = system-pref-gconf
       
   101 +IS_COMPONENT = 1
       
   102 +MODULE_NAME = nsSystemPrefServiceModule
       
   103 +FORCE_SHARED_LIB = 1
       
   104  
       
   105  REQUIRES        = pref \
       
   106  		  string \
       
   107  		  xpcom \
       
   108 -		  embedcomponents \
       
   109 +		  necko \
       
   110  		  $(NULL)
       
   111  
       
   112  CPPSRCS =   \
       
   113  	nsSystemPrefService.cpp       \
       
   114 -	nsSystemPrefFactory.cpp \
       
   115  	$(NULL)
       
   116  
       
   117 -SHARED_LIBRARY_LIBS = ../libsystem-pref_s.a
       
   118 +OS_INCLUDES += $(MOZ_GCONF_CFLAGS)
       
   119 +
       
   120  
       
   121  EXTRA_DSO_LDOPTS = \
       
   122 -		-L$(DIST)/bin \
       
   123 -		$(MOZ_COMPONENT_LIBS) \
       
   124 -		$(MOZ_GTK2_LIBS) \
       
   125 +		$(XPCOM_GLUE_LDOPTS) \
       
   126 +		$(MOZ_GCONF_LIBS)    \
       
   127 +		$(NSPR_LIBS) \
       
   128  		$(NULL)
       
   129  
       
   130 -EXPORT_LIBRARY = 1
       
   131 -IS_COMPONENT = 1
       
   132 -MODULE_NAME	= nsSystemPrefModule
       
   133 -
       
   134 -EXPORTS		= \
       
   135 -		nsSystemPrefService.h \
       
   136 -		$(NULL)
       
   137  
       
   138  include $(topsrcdir)/config/rules.mk
       
   139  
       
   140 -CFLAGS		+= $(MOZ_GTK2_CFLAGS)
       
   141 -CXXFLAGS	+= $(MOZ_GTK2_CFLAGS)
       
   142 -
       
   143 -LOCAL_INCLUDES = -I$(srcdir)/..
       
   144 -
       
   145 -export::
       
   146 -	$(INSTALL) $(srcdir)/../nsSystemPrefFactory.cpp .
       
   147 -
       
   148  GARBAGE += nsSystemPrefFactory.cpp
       
   149 diff --git a/extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp b/extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp
       
   150 --- a/extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp
       
   151 +++ b/extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp
       
   152 @@ -18,17 +18,19 @@
       
   153   * The Original Code is mozilla.org code.
       
   154   *
       
   155   * The Initial Developer of the Original Code is Sun Microsystems, Inc.
       
   156   * Portions created by Sun Microsystems are Copyright (C) 2003 Sun
       
   157   * Microsystems, Inc. All Rights Reserved.
       
   158   *
       
   159   * Original Author: Bolian Yin (bolian.yin@sun.com)
       
   160   *
       
   161 - * Contributor(s):
       
   162 + * Contributor(s): Robert O'Callahan/Novell (rocallahan@novell.com)
       
   163 + *                 Hubert Figuiere (hfiguiere@novell.com)
       
   164 + *                 Wolfgang Rosenauer (wr@rosenauer.org)
       
   165   *
       
   166   * Alternatively, the contents of this file may be used under the terms of
       
   167   * either the GNU General Public License Version 2 or later (the "GPL"), or
       
   168   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
       
   169   * in which case the provisions of the GPL or the LGPL are applicable instead
       
   170   * of those above. If you wish to allow use of your version of this file only
       
   171   * under the terms of either the GPL or the LGPL, and not to allow others to
       
   172   * use your version of this file under the terms of the NPL, indicate your
       
   173 @@ -36,299 +38,1300 @@
       
   174   * and other provisions required by the GPL or the LGPL. If you do not delete
       
   175   * the provisions above, a recipient may use your version of this file under
       
   176   * the terms of any one of the NPL, the GPL or the LGPL.
       
   177   *
       
   178   * ***** END LICENSE BLOCK ***** */
       
   179  
       
   180  #include <glib.h>
       
   181  #include <glib-object.h>
       
   182 +#include <gconf/gconf-client.h>
       
   183  
       
   184  #include "plstr.h"
       
   185  #include "nsCOMPtr.h"
       
   186 -#include "nsIPrefBranch.h"
       
   187 -#include "nsIPrefService.h"
       
   188 +#include "nsIPref.h"
       
   189  #include "nsIServiceManager.h"
       
   190  #include "nsIObserver.h"
       
   191  #include "nsWeakReference.h"
       
   192 +#include "nsIPrefBranch2.h"
       
   193 +#include "nsDataHashtable.h"
       
   194 +#include "nsHashKeys.h"
       
   195 +#include "nsICategoryManager.h"
       
   196 +#include "nsIGenericFactory.h"
       
   197 +#include "nsStringAPI.h"
       
   198 +#include "nsIPermissionManager.h"
       
   199 +#include "../nsSystemPref.h"
       
   200  
       
   201 -#include "nsString.h"
       
   202 -#include "nsSystemPrefLog.h"
       
   203 -#include "nsSystemPrefService.h"
       
   204 +#define NS_SYSTEMPREF_SERVICE_CID                  \
       
   205 +  { /* {3724e748-b088-4bf8-9298-aad426b66293} */       \
       
   206 +    0x3724e748,                                        \
       
   207 +    0xb088,                                            \
       
   208 +    0x4bf8,                                            \
       
   209 +        { 0x92, 0x98, 0xaa, 0xd4, 0x26, 0xb6, 0x62, 0x93 } \
       
   210 +  }
       
   211  
       
   212 -/*************************************************************************
       
   213 - * The strange thing here is that we load the gconf library manually and 
       
   214 - * search the function pointers we need. If that process fails, no gconf
       
   215 - * support is available in mozilla. The aim is to make mozilla independent
       
   216 - * on gconf, in both compile time and run time.
       
   217 - ************************************************************************/
       
   218 +#define NS_SYSTEMPREF_SERVICE_CLASSNAME "System Preferences Platform Service"
       
   219  
       
   220 -//gconf types
       
   221 -extern "C" {
       
   222 +NS_DEFINE_STATIC_IID_ACCESSOR(nsISystemPrefService, NS_ISYSTEMPREFSERVICE_IID)
       
   223  
       
   224 -    typedef enum {
       
   225 -        GCONF_VALUE_INVALID,
       
   226 -        GCONF_VALUE_STRING,
       
   227 -        GCONF_VALUE_INT,
       
   228 -        GCONF_VALUE_FLOAT,
       
   229 -        GCONF_VALUE_BOOL,
       
   230 -        GCONF_VALUE_SCHEMA,
       
   231 +/**
       
   232 + * We can link directly to the gconf library. If it's not available,
       
   233 + * this component just won't load and no system prefs will be offered.
       
   234 + */
       
   235  
       
   236 -        GCONF_VALUE_LIST,
       
   237 -        GCONF_VALUE_PAIR
       
   238 +#define NUM_ELEM(a) (sizeof(a)/sizeof(a[0]))
       
   239  
       
   240 -    }GConfValueType;
       
   241 +class nsSystemPrefService;
       
   242  
       
   243 -    typedef struct {
       
   244 -        GConfValueType type;
       
   245 -    }GConfValue;
       
   246 +/**
       
   247 + * List the preferences that have a simple mapping between Moz and gconf.
       
   248 + * These preferences have the same meaning and their values are
       
   249 + * automatically converted.
       
   250 + */
       
   251 +struct SimplePrefMapping {
       
   252 +    const char *mozPrefName;
       
   253 +    const char *gconfPrefName;
       
   254 +    /**
       
   255 +     * If this is PR_FALSE, then we never allow Mozilla to change
       
   256 +     * this setting. The Mozilla pref will always be locked.
       
   257 +     * If this is PR_TRUE then Mozilla will be allowed to change
       
   258 +     * the setting --- but only if it is writable in gconf.
       
   259 +     */
       
   260 +    PRBool allowWritesFromMozilla;
       
   261 +};
       
   262 +typedef nsresult (* ComplexGConfPrefChanged)(nsSystemPrefService* aPrefService,
       
   263 +                                             GConfClient* aClient);
       
   264 +typedef nsresult (* ComplexMozPrefChanged)(nsSystemPrefService* aPrefService,
       
   265 +                                           GConfClient* aClient);
       
   266 +struct ComplexGConfPrefMapping {
       
   267 +    const char* gconfPrefName;
       
   268 +    ComplexGConfPrefChanged callback;
       
   269 +};
       
   270  
       
   271 -    typedef void * (*GConfClientGetDefaultType) (void);
       
   272 -    typedef PRBool (*GConfClientGetBoolType) (void *client, const gchar *key,
       
   273 -                                              GError **err);
       
   274 -    typedef gchar* (*GConfClientGetStringType) (void *client, const gchar *key,
       
   275 -                                                GError **err);
       
   276 -    typedef PRInt32 (*GConfClientGetIntType) (void *client, const gchar *key,
       
   277 -                                              GError **err);
       
   278 -    typedef GSList* (*GConfClientGetListType) (void *client, const gchar *key,
       
   279 -                                               GConfValueType list_type,
       
   280 -                                               GError **err);
       
   281 -    typedef  void (*GConfClientNotifyFuncType) (void* client, guint cnxn_id,
       
   282 -                                                void *entry, 
       
   283 -                                                gpointer user_data);
       
   284 -    typedef guint (*GConfClientNotifyAddType) (void* client,
       
   285 -                                               const gchar* namespace_section,
       
   286 -                                               GConfClientNotifyFuncType func,
       
   287 -                                               gpointer user_data,
       
   288 -                                               GFreeFunc destroy_notify,
       
   289 -                                               GError** err);
       
   290 -    typedef void (*GConfClientNotifyRemoveType) (void *client,
       
   291 -                                                 guint cnxn);
       
   292 -    typedef void (*GConfClientAddDirType) (void *client,
       
   293 -                                           const gchar *dir,
       
   294 -                                           guint8 preload,
       
   295 -                                           GError **err);
       
   296 -    typedef void (*GConfClientRemoveDirType) (void *client,
       
   297 -                                              const gchar *dir,
       
   298 -                                              GError **err);
       
   299 +struct ComplexMozPrefMapping {
       
   300 +    const char* mozPrefName;
       
   301 +    ComplexMozPrefChanged callback;
       
   302 +};
       
   303  
       
   304 -    typedef const char* (*GConfEntryGetKeyType) (const void *entry);
       
   305 -    typedef GConfValue* (*GConfEntryGetValueType) (const void *entry);
       
   306 +class nsSystemPrefService : public nsISystemPrefService, nsIPrefBranch
       
   307 + {
       
   308 + public:
       
   309 +    NS_DECL_ISUPPORTS
       
   310 +    NS_DECL_NSIPREFBRANCH
       
   311  
       
   312 -    typedef const char* (*GConfValueGetStringType) (const GConfValue *value);
       
   313 -    typedef PRInt32 (*GConfValueGetIntType) (const GConfValue *value);
       
   314 -    typedef PRBool (*GConfValueGetBoolType) (const GConfValue *value);
       
   315 +    nsresult Init();
       
   316  
       
   317 -    
       
   318 -    static void gconf_key_listener (void* client, guint cnxn_id,
       
   319 -                                    void *entry, gpointer user_data);
       
   320 -}
       
   321 +    virtual nsresult LoadSystemPreferences(nsISystemPref* aPrefs);
       
   322 +    virtual nsresult NotifyMozillaPrefChanged(const char* aPrefName);
       
   323 +    virtual nsresult NotifyUnloadSystemPreferences();
       
   324  
       
   325 -struct GConfCallbackData
       
   326 -{
       
   327 -    GConfProxy *proxy;
       
   328 -    void * userData;
       
   329 -    PRUint32 atom;
       
   330 -    PRUint32 notifyId;
       
   331 -};
       
   332 -//////////////////////////////////////////////////////////////////////
       
   333 -// GConPrxoy is a thin wrapper for easy use of gconf funcs. It loads the
       
   334 -// gconf library and initializes the func pointers for later use.
       
   335 -//////////////////////////////////////////////////////////////////////
       
   336 -class GConfProxy
       
   337 -{
       
   338 -public:
       
   339 -    GConfProxy(nsSystemPrefService* aSysPrefService);
       
   340 -    ~GConfProxy();
       
   341 -    PRBool Init();
       
   342 +    nsSystemPrefService();
       
   343 +    virtual ~nsSystemPrefService();
       
   344  
       
   345 -    nsresult GetBoolPref(const char *aMozKey, PRBool *retval);
       
   346 -    nsresult GetCharPref(const char *aMozKey, char **retval);
       
   347 -    nsresult GetIntPref(const char *aMozKey, PRInt32 *retval);
       
   348 -
       
   349 -    nsresult NotifyAdd (PRUint32 aAtom, void *aUserData);
       
   350 -    nsresult NotifyRemove (PRUint32 aAtom, const void *aUserData);
       
   351 -
       
   352 -    nsresult GetAtomForMozKey(const char *aMozKey, PRUint32 *aAtom) {
       
   353 -        return GetAtom(aMozKey, 0, aAtom); 
       
   354 +    nsISystemPref* GetPrefs() { return mPref; }
       
   355 +    SimplePrefMapping* GetSimpleCallbackData(PRUint32 aKey) {
       
   356 +      SimplePrefMapping* result = nsnull;
       
   357 +      mGConfSimpleCallbacks.Get(aKey, &result);
       
   358 +      return result;
       
   359      }
       
   360 -    const char *GetMozKey(PRUint32 aAtom) {
       
   361 -        return GetKey(aAtom, 0); 
       
   362 -    }
       
   363 -
       
   364 -    void OnNotify(void *aClient, void * aEntry, PRUint32 aNotifyId,
       
   365 -                  GConfCallbackData *aData);
       
   366 +    ComplexGConfPrefMapping* GetComplexCallbackData(PRUint32 aKey) {
       
   367 +      ComplexGConfPrefMapping* result = nsnull;
       
   368 +      mGConfComplexCallbacks.Get(aKey, &result);
       
   369 +      return result;
       
   370 +     }
       
   371  
       
   372  private:
       
   373 -    void *mGConfClient;
       
   374 -    PRLibrary *mGConfLib;
       
   375 -    PRBool mInitialized;
       
   376 -    nsSystemPrefService *mSysPrefService;
       
   377 +    nsISystemPref* mPref;
       
   378 +    nsDataHashtable<nsUint32HashKey, SimplePrefMapping*> mGConfSimpleCallbacks;
       
   379 +    nsDataHashtable<nsUint32HashKey, ComplexGConfPrefMapping*> mGConfComplexCallbacks;
       
   380 +    // This is set to PR_FALSE temporarily to stop listening to gconf
       
   381 +    // change notifications (while we change gconf values)
       
   382 +    PRPackedBool mListenToGConf;
       
   383  
       
   384 -    //listeners
       
   385 -    nsAutoVoidArray *mObservers;
       
   386 -
       
   387 -    void InitFuncPtrs();
       
   388 -    //gconf public func ptrs
       
   389 -
       
   390 -    //gconf client funcs
       
   391 -    GConfClientGetDefaultType GConfClientGetDefault;
       
   392 -    GConfClientGetBoolType GConfClientGetBool;
       
   393 -    GConfClientGetStringType GConfClientGetString;
       
   394 -    GConfClientGetIntType GConfClientGetInt;
       
   395 -    GConfClientGetListType GConfClientGetList;
       
   396 -    GConfClientNotifyAddType GConfClientNotifyAdd;
       
   397 -    GConfClientNotifyRemoveType GConfClientNotifyRemove;
       
   398 -    GConfClientAddDirType GConfClientAddDir;
       
   399 -    GConfClientRemoveDirType GConfClientRemoveDir;
       
   400 -
       
   401 -    //gconf entry funcs
       
   402 -    GConfEntryGetValueType GConfEntryGetValue;
       
   403 -    GConfEntryGetKeyType GConfEntryGetKey;
       
   404 -
       
   405 -    //gconf value funcs
       
   406 -    GConfValueGetBoolType GConfValueGetBool;
       
   407 -    GConfValueGetStringType GConfValueGetString;
       
   408 -    GConfValueGetIntType GConfValueGetInt;
       
   409 -
       
   410 -    //pref name translating stuff
       
   411 -    nsresult GetAtom(const char *aKey, PRUint8 aNameType, PRUint32 *aAtom);
       
   412 -    nsresult GetAtomForGConfKey(const char *aGConfKey, PRUint32 *aAtom) \
       
   413 -    {return GetAtom(aGConfKey, 1, aAtom);}
       
   414 -    const char *GetKey(PRUint32 aAtom, PRUint8 aNameType);
       
   415 -    const char *GetGConfKey(PRUint32 aAtom) \
       
   416 -    {return GetKey(aAtom, 1); }
       
   417 -    inline const char *MozKey2GConfKey(const char *aMozKey);
       
   418 -
       
   419 -    //const strings
       
   420 -    static const char sPrefGConfKey[];
       
   421 -    static const char sDefaultLibName1[];
       
   422 -    static const char sDefaultLibName2[];
       
   423 +    GConfValue* GConfGet(const char *aPrefName);
       
   424  };
       
   425  
       
   426 -struct SysPrefCallbackData {
       
   427 -    nsISupports *observer;
       
   428 -    PRBool bIsWeakRef;
       
   429 -    PRUint32 prefAtom;
       
   430 -};
       
   431 -
       
   432 -PRBool
       
   433 -sysPrefDeleteObserver(void *aElement, void *aData) {
       
   434 -    SysPrefCallbackData *pElement =
       
   435 -        static_cast<SysPrefCallbackData *>(aElement);
       
   436 -    NS_RELEASE(pElement->observer);
       
   437 -    nsMemory::Free(pElement);
       
   438 -    return PR_TRUE;
       
   439 -}
       
   440 -
       
   441 -NS_IMPL_ISUPPORTS2(nsSystemPrefService, nsIPrefBranch, nsIPrefBranch2)
       
   442 -
       
   443 -/* public */
       
   444  nsSystemPrefService::nsSystemPrefService()
       
   445 -    :mInitialized(PR_FALSE),
       
   446 -     mGConf(nsnull),
       
   447 -     mObservers(nsnull)
       
   448 +   : mPref(nsnull), mListenToGConf(PR_TRUE)
       
   449  {
       
   450 +   mGConfSimpleCallbacks.Init();
       
   451 +   mGConfComplexCallbacks.Init();
       
   452  }
       
   453  
       
   454  nsSystemPrefService::~nsSystemPrefService()
       
   455  {
       
   456 -    mInitialized = PR_FALSE;
       
   457 -
       
   458 -    if (mGConf)
       
   459 -        delete mGConf;
       
   460 -    if (mObservers) {
       
   461 -        (void)mObservers->EnumerateForwards(sysPrefDeleteObserver, nsnull);
       
   462 -        delete mObservers;
       
   463 -    }
       
   464 +   NotifyUnloadSystemPreferences();
       
   465  }
       
   466  
       
   467  nsresult
       
   468  nsSystemPrefService::Init()
       
   469  {
       
   470 -    if (!gSysPrefLog) {
       
   471 -        gSysPrefLog = PR_NewLogModule("Syspref");
       
   472 -        if (!gSysPrefLog) return NS_ERROR_OUT_OF_MEMORY;
       
   473 +    return NS_OK;
       
   474 +}
       
   475 +
       
   476 +NS_IMPL_ISUPPORTS2(nsSystemPrefService, 
       
   477 +                   nsISystemPrefService, 
       
   478 +                   nsIPrefBranch)
       
   479 +
       
   480 +static GConfClient* GetGConf() {
       
   481 +    return gconf_client_get_default();
       
   482 +}
       
   483 +
       
   484 +static PRBool VerifyMatchingTypes(nsISystemPref* aPrefs,
       
   485 +                                  const char* aMozPref, GConfValue* aVal)
       
   486 +{
       
   487 +    nsCOMPtr<nsIPrefBranch2> prefBranch = aPrefs->GetPrefUserBranch();
       
   488 +    PRInt32 type;
       
   489 +    nsresult rv = prefBranch->GetPrefType(aMozPref, &type);
       
   490 +    if (NS_FAILED(rv)) {
       
   491 +        // pref probably doesn't exist. Let gconf set it.
       
   492 +        return PR_TRUE;
       
   493      }
       
   494  
       
   495 -    SYSPREF_LOG(("Init SystemPref Service\n"));
       
   496 -    if (mInitialized)
       
   497 +    PRBool ok;
       
   498 +    switch (aVal->type) {
       
   499 +    case GCONF_VALUE_STRING:
       
   500 +        ok = type == nsIPrefBranch2::PREF_STRING;
       
   501 +        break;
       
   502 +    case GCONF_VALUE_INT:
       
   503 +        ok = type == nsIPrefBranch2::PREF_INT;
       
   504 +        break;
       
   505 +    case GCONF_VALUE_BOOL:
       
   506 +        ok = type == nsIPrefBranch2::PREF_BOOL;
       
   507 +        break;
       
   508 +    default:
       
   509 +        NS_ERROR("Unhandled gconf preference type");
       
   510 +        return PR_FALSE;
       
   511 +    }
       
   512 +
       
   513 +    NS_ASSERTION(ok, "Mismatched gconf/Mozilla pref types");
       
   514 +    return ok;
       
   515 +}
       
   516 +
       
   517 +/**
       
   518 + * Map a gconf pref value into the corresponding Mozilla pref.
       
   519 + */
       
   520 +static nsresult ApplySimpleMapping(SimplePrefMapping* aMap,
       
   521 +                                   nsISystemPref* aPrefs,
       
   522 +                                   GConfClient* aClient)
       
   523 +{
       
   524 +    GConfValue* val = gconf_client_get(aClient, aMap->gconfPrefName, nsnull);
       
   525 +    if (!val) {
       
   526 +        // No gconf key, so there's really nothing to do
       
   527 +        return NS_OK;
       
   528 +    }
       
   529 +
       
   530 +    VerifyMatchingTypes(aPrefs, aMap->mozPrefName, val);
       
   531 +
       
   532 +    PRBool locked = !aMap->allowWritesFromMozilla ||
       
   533 +        !gconf_client_key_is_writable(aClient, aMap->gconfPrefName, nsnull);
       
   534 +    nsresult rv;
       
   535 +    switch (val->type) {
       
   536 +    case GCONF_VALUE_STRING: {
       
   537 +        const char* str = gconf_value_get_string(val);
       
   538 +        rv = aPrefs->SetOverridingMozillaStringPref(aMap->mozPrefName, str, locked);
       
   539 +        // XXX do we need to free 'str' here?
       
   540 +        break;
       
   541 +    }
       
   542 +    case GCONF_VALUE_INT:
       
   543 +        rv = aPrefs->SetOverridingMozillaIntPref(aMap->mozPrefName,
       
   544 +                                                 gconf_value_get_int(val), locked);
       
   545 +        break;
       
   546 +    case GCONF_VALUE_BOOL:
       
   547 +        rv = aPrefs->SetOverridingMozillaBoolPref(aMap->mozPrefName,
       
   548 +                                                  gconf_value_get_bool(val), locked);
       
   549 +        break;
       
   550 +    default:
       
   551 +        NS_ERROR("Unusable gconf value type");
       
   552 +        rv = NS_ERROR_FAILURE;
       
   553 +        break;
       
   554 +    }
       
   555 +
       
   556 +    gconf_value_free(val);
       
   557 +    return rv;
       
   558 +}
       
   559 +
       
   560 +/**
       
   561 + * Map a Mozilla pref into the corresponding gconf pref, if
       
   562 + * that's allowed.
       
   563 + */
       
   564 +static nsresult ReverseApplySimpleMapping(SimplePrefMapping* aMap,
       
   565 +                                          nsISystemPref* aPrefs,
       
   566 +                                          GConfClient* aClient)
       
   567 +{
       
   568 +    // Verify that the gconf key has the right type, if it exists
       
   569 +    GConfValue* val = gconf_client_get(aClient, aMap->gconfPrefName, nsnull);
       
   570 +    if (val) {
       
   571 +        VerifyMatchingTypes(aPrefs, aMap->mozPrefName, val);
       
   572 +        gconf_value_free(val);
       
   573 +    }
       
   574 +
       
   575 +    PRBool writable = aMap->allowWritesFromMozilla &&
       
   576 +        gconf_client_key_is_writable(aClient, aMap->gconfPrefName, nsnull);
       
   577 +    if (!writable) {
       
   578 +        NS_ERROR("Gconf key is not writable");
       
   579          return NS_ERROR_FAILURE;
       
   580 +    }
       
   581  
       
   582 -    if (!mGConf) {
       
   583 -        mGConf = new GConfProxy(this);
       
   584 -        if (!mGConf->Init()) {
       
   585 -            delete mGConf;
       
   586 -            mGConf = nsnull;
       
   587 +    nsCOMPtr<nsIPrefBranch2> prefBranch = aPrefs->GetPrefUserBranch();
       
   588 +    PRInt32 type;
       
   589 +    nsresult rv = prefBranch->GetPrefType(aMap->mozPrefName, &type);
       
   590 +    if (NS_FAILED(rv)) {
       
   591 +        NS_ERROR("Writing back a pref that doesn't exist?");
       
   592 +        return rv;
       
   593 +    }
       
   594 +
       
   595 +    switch (type) {
       
   596 +    case nsIPrefBranch2::PREF_STRING:
       
   597 +        {
       
   598 +            char* result;
       
   599 +            rv = prefBranch->GetCharPref(aMap->mozPrefName, &result);
       
   600 +            if (NS_FAILED(rv))
       
   601 +                return rv;
       
   602 +
       
   603 +            gconf_client_set_string(aClient, aMap->gconfPrefName, result, nsnull);
       
   604 +            nsMemory::Free(result);
       
   605 +        }
       
   606 +        break;
       
   607 +    case nsIPrefBranch2::PREF_INT:
       
   608 +        {
       
   609 +            PRInt32 result;
       
   610 +            rv = prefBranch->GetIntPref(aMap->mozPrefName, &result);
       
   611 +            if (NS_FAILED(rv))
       
   612 +                return rv;
       
   613 +
       
   614 +            gconf_client_set_int(aClient, aMap->gconfPrefName, result, nsnull);
       
   615 +        }
       
   616 +        break;
       
   617 +    case nsIPrefBranch2::PREF_BOOL:
       
   618 +        {
       
   619 +            PRBool result;
       
   620 +            rv = prefBranch->GetBoolPref(aMap->mozPrefName, &result);
       
   621 +            if (NS_FAILED(rv))
       
   622 +                return rv;
       
   623 +
       
   624 +            gconf_client_set_bool(aClient, aMap->gconfPrefName, result, nsnull);
       
   625 +        }
       
   626 +        break;
       
   627 +    default:
       
   628 +        NS_ERROR("Unhandled gconf preference type");
       
   629 +        return NS_ERROR_FAILURE;
       
   630 +    }
       
   631 +
       
   632 +    return NS_OK;
       
   633 +}
       
   634 +
       
   635 +/* BEGIN preference mapping definition area
       
   636 + *
       
   637 + * There are a few rules that our preference maps have to obey:
       
   638 + *
       
   639 + * 1) Each mapping defines a relationship R between a set of GConf preferences and
       
   640 + * a set of Mozilla preferences that must *always* be true. Thus, when a Mozilla
       
   641 + * pref changes or a gconf pref changes, we may need to change something on the
       
   642 + * other side to preserve R. If a GConf preference is read-only, then we may
       
   643 + * need to lock one or more Mozilla preferences to avoid a situation where the
       
   644 + * Mozilla preference changes and we can't update the GConf preference to
       
   645 + * ensure R continues to hold.
       
   646 + *
       
   647 + * 2) If an unlocked Mozilla preference is changed, then we can only
       
   648 + * preserve R by changing GConf preferences; we are not allowed to
       
   649 + * change Mozilla preferences.
       
   650 + *
       
   651 + * 3) If a GConf preference is changed, then we can only preserve R by
       
   652 + * changing Moozilla preferences; we are nt allowed to change GConf
       
   653 + * preferences.
       
   654 + *
       
   655 + * For "simple" mappings, the relationship R is just of the form
       
   656 + * "GConf preference 'A' is equal to Mozilla preference 'B'". R is
       
   657 + * preserved by setting A to B when B changes, and by setting B to A
       
   658 + * when A changes. If A is read-only then we lock B (or we may just
       
   659 + * decide to lock B for other reasons). Thus rules 1-3 are satisfied.
       
   660 + *
       
   661 + * For "complex" mappings we have more complicated
       
   662 + * relationships. These are documented below.
       
   663 + */
       
   664 +
       
   665 +static SimplePrefMapping sSimplePrefMappings[] = {
       
   666 +    // GNOME accessibility setting; never allow this to be set by Firefox
       
   667 +    {"config.use_system_prefs.accessibility",
       
   668 +     "/desktop/gnome/interface/accessibility", PR_FALSE},
       
   669 +
       
   670 +    // GConf Firefox preferences; allow these to be set through the Firefox UI
       
   671 +    {"security.enable_java", "/apps/firefox/web/java_enabled", PR_TRUE},
       
   672 +    {"javascript.enabled", "/apps/firefox/web/javascript_enabled", PR_TRUE},
       
   673 +    {"browser.startup.homepage", "/apps/firefox/general/homepage_url", PR_TRUE},
       
   674 +    {"browser.cache.disk.capacity", "/apps/firefox/web/cache_size", PR_TRUE},
       
   675 +    {"network.cookie.lifetimePolicy", "/apps/firefox/web/cookie_accept", PR_TRUE},
       
   676 +
       
   677 +    // UI lockdown settings; never allow these to be set by Firefox. There is no
       
   678 +    // Firefox UI for these but they could otherwise be set via about:config.
       
   679 +    {"config.lockdown.printing", "/desktop/gnome/lockdown/disable_printing", PR_FALSE},
       
   680 +    {"config.lockdown.printsetup", "/desktop/gnome/lockdown/disable_print_setup", PR_FALSE},
       
   681 +    {"config.lockdown.savepage", "/desktop/gnome/lockdown/disable_save_to_disk", PR_FALSE},
       
   682 +    {"config.lockdown.history", "/apps/firefox/lockdown/disable_history", PR_FALSE},
       
   683 +    {"config.lockdown.toolbarediting", "/apps/firefox/lockdown/disable_toolbar_editing", PR_FALSE},
       
   684 +    {"config.lockdown.urlbar", "/apps/firefox/lockdown/disable_url_bar", PR_FALSE},
       
   685 +    {"config.lockdown.bookmark", "/apps/firefox/lockdown/disable_bookmark_editing", PR_FALSE},
       
   686 +    {"config.lockdown.disable_themes", "/apps/firefox/lockdown/disable_themes", PR_FALSE},
       
   687 +    {"config.lockdown.disable_extensions", "/apps/firefox/lockdown/disable_extensions", PR_FALSE},
       
   688 +    {"config.lockdown.searchbar", "/apps/firefox/lockdown/disable_searchbar", PR_FALSE},
       
   689 +    {"config.lockdown.hidebookmark", "/apps/firefox/lockdown/hide_bookmark", PR_FALSE},
       
   690 +    {"config.lockdown.showsavedpasswords", "/apps/firefox/lockdown/disable_show_passwords", PR_FALSE},
       
   691 +};
       
   692 +
       
   693 +static nsresult ApplyListPref(nsSystemPrefService* aPrefService,
       
   694 +                             GConfClient* aClient,
       
   695 +                             const char* aGConfKey, const char* aMozKey,
       
   696 +                             char aSeparator)
       
   697 +{
       
   698 +    GSList* list = gconf_client_get_list(aClient, aGConfKey,
       
   699 +                                         GCONF_VALUE_STRING, nsnull);
       
   700 +    nsCAutoString str;
       
   701 +    for (GSList* l = list; l; l = l->next) {
       
   702 +        str.Append((const char*)l->data);
       
   703 +        if (l->next) {
       
   704 +            str.Append(aSeparator);
       
   705 +        }
       
   706 +    }
       
   707 +    PRBool lock = !gconf_client_key_is_writable(aClient, aGConfKey, nsnull);
       
   708 +    nsresult rv = aPrefService->GetPrefs()->
       
   709 +        SetOverridingMozillaStringPref(aMozKey, str.get(), lock);
       
   710 +    // XXX does this free the strings? Should it?
       
   711 +    g_slist_free(list);
       
   712 +    return rv;
       
   713 +}
       
   714 +static nsresult ReverseApplyListPref(nsSystemPrefService* aPrefService,
       
   715 +                                    GConfClient* aClient,
       
   716 +                                    const char* aGConfKey, const char* aMozKey,
       
   717 +                                    char aSeparator)
       
   718 +{
       
   719 +    char* data = nsnull;
       
   720 +    nsCOMPtr<nsIPrefBranch2> prefs =
       
   721 +        aPrefService->GetPrefs()->GetPrefUserBranch();
       
   722 +    prefs->GetCharPref(aMozKey, &data);
       
   723 +    if (!data)
       
   724 +        return NS_ERROR_FAILURE;
       
   725 +    nsresult rv = NS_OK;
       
   726 +    GSList* list = nsnull;
       
   727 +    PRInt32 i = 0;
       
   728 +    while (data[i]) {
       
   729 +        const char* nextComma = strchr(data+i, ',');
       
   730 +        PRInt32 tokLen = nextComma ? nextComma - (data+i) : strlen(data+i);
       
   731 +        char* tok = strndup(data+i, tokLen);
       
   732 +        if (!tok)
       
   733 +            break;
       
   734 +        GSList* newList = g_slist_append(list, tok);
       
   735 +        if (!newList) {
       
   736 +            rv = NS_ERROR_OUT_OF_MEMORY;
       
   737 +            break;
       
   738 +        }
       
   739 +        list = newList;
       
   740 +        if (!nextComma)
       
   741 +            break;
       
   742 +        i = nextComma + 1 - data;
       
   743 +    }
       
   744 +    nsMemory::Free(data);
       
   745 +    if (NS_SUCCEEDED(rv)) {
       
   746 +        if (gconf_client_key_is_writable(aClient, aGConfKey, nsnull))
       
   747 +            gconf_client_set_list(aClient, aGConfKey, GCONF_VALUE_STRING, list, nsnull);
       
   748 +        else
       
   749 +            NS_ERROR("Gconf key is not writable");
       
   750 +    }
       
   751 +    for (GSList* l = list; l; l = l->next) {
       
   752 +        free(l->data);
       
   753 +    }
       
   754 +    g_slist_free(list);
       
   755 +    return rv;
       
   756 +}
       
   757 +
       
   758 +/**
       
   759 + * The relationship R is
       
   760 + * "network.negotiate-auth.trusted-uris" is the comma-separated concatenation
       
   761 + * of the elements of the list "/apps/firefox/general/trusted_URIs"
       
   762 + */
       
   763 +static const char GConfKey_TrustedURIs[] = "/apps/firefox/general/trusted_URIs";
       
   764 +static const char MozKey_TrustedURIs[] = "network.negotiate-auth.trusted-uris";
       
   765 +static nsresult ApplyTrustedURIs(nsSystemPrefService* aPrefService,
       
   766 +                                GConfClient* aClient)
       
   767 +{
       
   768 +    return ApplyListPref(aPrefService, aClient,
       
   769 +                        GConfKey_TrustedURIs, MozKey_TrustedURIs, ',');
       
   770 +}
       
   771 +static nsresult ReverseApplyTrustedURIs(nsSystemPrefService* aPrefService,
       
   772 +                                       GConfClient* aClient)
       
   773 +{
       
   774 +    return ReverseApplyListPref(aPrefService, aClient,
       
   775 +                               GConfKey_TrustedURIs, MozKey_TrustedURIs, ',');
       
   776 +}
       
   777 +
       
   778 +/**
       
   779 + * The relationship R is
       
   780 + * "network.negotiate-auth.delegation-uris" is the comma-separated concatenation
       
   781 + * of the elements of the list "/apps/firefox/general/delegation_URIs"
       
   782 + */
       
   783 +static const char GConfKey_DelegationURIs[] = "/apps/firefox/general/delegation_URIs";
       
   784 +static const char MozKey_DelegationURIs[] = "network.negotiate-auth.delegation-uris";
       
   785 +static nsresult ApplyDelegationURIs(nsSystemPrefService* aPrefService,
       
   786 +                                   GConfClient* aClient)
       
   787 +{
       
   788 +    return ApplyListPref(aPrefService, aClient,
       
   789 +                        GConfKey_DelegationURIs, MozKey_DelegationURIs, ',');
       
   790 +}
       
   791 +static nsresult ReverseApplyDelegationURIs(nsSystemPrefService* aPrefService,
       
   792 +                                          GConfClient* aClient)
       
   793 +{
       
   794 +    return ReverseApplyListPref(aPrefService, aClient,
       
   795 +                               GConfKey_DelegationURIs, MozKey_DelegationURIs, ',');
       
   796 +}
       
   797 +
       
   798 +
       
   799 +/**
       
   800 + * The relationship R is
       
   801 + * If "/apps/firefox/web/download_defaultfolder" is the empty string, then
       
   802 + * "browser.download.useDownloadDir" is false;
       
   803 + * otherwise "browser.download.useDownloadDir" is true and "browser.download.folderList"
       
   804 + * is (0 if "/apps/firefox/web/download_defaultfolder" is "Desktop";
       
   805 + *     1 if "/apps/firefox/web/download_defaultfolder" is "My Downloads";
       
   806 + *     3 if "/apps/firefox/web/download_defaultfolder" is "Home";
       
   807 + *     otherwise 2 and "browser.download.dir" = "/apps/firefox/web/download_defaultfolder")
       
   808 + */
       
   809 +static const char GConfKey_DownloadFolder[] = "/apps/firefox/web/download_defaultfolder";
       
   810 +static const char MozKey_UseDownloadDir[] = "browser.download.useDownloadDir";
       
   811 +static const char MozKey_DownloadDirType[] = "browser.download.folderList";
       
   812 +static const char MozKey_DownloadDirExplicit[] = "browser.download.dir";
       
   813 +static nsresult ApplyDownloadFolder(nsSystemPrefService* aPrefService,
       
   814 +                                    GConfClient* aClient)
       
   815 +{
       
   816 +    char* str = gconf_client_get_string(aClient, GConfKey_DownloadFolder, nsnull);
       
   817 +    if (!str)
       
   818 +        return NS_ERROR_FAILURE;
       
   819 +    PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DownloadFolder, nsnull);
       
   820 +    nsresult rv = aPrefService->GetPrefs()->
       
   821 +        SetOverridingMozillaBoolPref(MozKey_UseDownloadDir, *str != 0, lock);
       
   822 +    if (NS_FAILED(rv)) {
       
   823 +        g_free(str);
       
   824 +        return rv;
       
   825 +    }
       
   826 +    PRInt32 dirType = 0;
       
   827 +    if (!strcmp(str, "Desktop")) {
       
   828 +        dirType = 0;
       
   829 +    } else if (!strcmp(str, "My Downloads")) {
       
   830 +        dirType = 1;
       
   831 +    } else if (!strcmp(str, "Home")) {
       
   832 +        dirType = 3;
       
   833 +    } else {
       
   834 +        dirType = 2;
       
   835 +    }
       
   836 +    // Always set all three Mozilla preferences. This is simpler and avoids
       
   837 +    // problems; e.g., if the gconf value changes from "/home/rocallahan" to "Desktop"
       
   838 +    // we might leave MozKey_DownloadDirType accidentally locked.
       
   839 +    rv = aPrefService->GetPrefs()->
       
   840 +        SetOverridingMozillaIntPref(MozKey_DownloadDirType, dirType, lock);
       
   841 +    if (NS_SUCCEEDED(rv)) {
       
   842 +        rv = aPrefService->GetPrefs()->
       
   843 +            SetOverridingMozillaStringPref(MozKey_DownloadDirExplicit, str, lock);
       
   844 +    }
       
   845 +    g_free(str);
       
   846 +    return rv;
       
   847 +}
       
   848 +
       
   849 +static nsresult ReverseApplyDownloadFolder(nsSystemPrefService* aPrefService,
       
   850 +                                           GConfClient* aClient)
       
   851 +{
       
   852 +    PRBool useDownloadDir = PR_FALSE;
       
   853 +    const char* result;
       
   854 +    char* explicitStr = nsnull;
       
   855 +    nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
   856 +    prefs->GetBoolPref(MozKey_UseDownloadDir, &useDownloadDir);
       
   857 +    if (!useDownloadDir) {
       
   858 +        result = "";
       
   859 +    } else {
       
   860 +        PRInt32 type = -1;
       
   861 +        prefs->GetIntPref(MozKey_DownloadDirType, &type);
       
   862 +        if (type < 0)
       
   863 +            return NS_ERROR_FAILURE;
       
   864 +        switch (type) {
       
   865 +        case 0: result = "Desktop"; break;
       
   866 +        case 1: result = "Downloads"; break;
       
   867 +        case 2:
       
   868 +            prefs->GetCharPref(MozKey_DownloadDirExplicit, &explicitStr);
       
   869 +            result = explicitStr;
       
   870 +            break;
       
   871 +        case 3: result = "Home"; break;
       
   872 +        default:
       
   873 +            NS_ERROR("Unknown download dir type");
       
   874              return NS_ERROR_FAILURE;
       
   875          }
       
   876      }
       
   877 +    if (!result)
       
   878 +        return NS_ERROR_FAILURE;
       
   879 +    if (gconf_client_key_is_writable(aClient, GConfKey_DownloadFolder, nsnull))
       
   880 +        gconf_client_set_string(aClient, GConfKey_DownloadFolder,
       
   881 +                                result, nsnull);
       
   882 +    else
       
   883 +        NS_ERROR("Gconf key is not writable");
       
   884 +    nsMemory::Free(explicitStr);
       
   885 +    return NS_OK;
       
   886 +}
       
   887  
       
   888 -    mInitialized = PR_TRUE;
       
   889 +/**
       
   890 + * The relationship R is
       
   891 + * "/apps/firefox/web/disable_cookies" is true if and only if
       
   892 + * "network.cookie.cookieBehavior" is 2 ('dontUse')
       
   893 + */
       
   894 +static const char GConfKey_DisableCookies[] = "/apps/firefox/web/disable_cookies";
       
   895 +static const char MozKey_CookieBehavior[] = "network.cookie.cookieBehavior";
       
   896 +static const char MozKey_CookieExceptions[] = "network.cookie.honorExceptions";
       
   897 +static const char MozKey_CookieViewExceptions[] = "pref.privacy.disable_button.cookie_exceptions";
       
   898 +static nsresult ApplyDisableCookies(nsSystemPrefService* aPrefService,
       
   899 +                                    GConfClient* aClient)
       
   900 +{
       
   901 +    gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableCookies, nsnull);
       
   902 +    PRInt32 behavior = -1;
       
   903 +    nsCOMPtr<nsIPrefBranch2> prefs =
       
   904 +        aPrefService->GetPrefs()->GetPrefUserBranch();
       
   905 +    prefs->GetIntPref(MozKey_CookieBehavior, &behavior);
       
   906 +    if (behavior < 0)
       
   907 +        return NS_ERROR_FAILURE;
       
   908 +    if (disable) {
       
   909 +        behavior = 2;
       
   910 +    } else {
       
   911 +        if (behavior == 2) {
       
   912 +            behavior = 0;
       
   913 +        }
       
   914 +    }
       
   915 +    PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableCookies, nsnull);
       
   916 +    nsresult rv = aPrefService->GetPrefs()->
       
   917 +        SetOverridingMozillaBoolPref(MozKey_CookieExceptions, !lock, lock);
       
   918 +    if (NS_FAILED(rv))
       
   919 +      return rv;
       
   920 +    rv = aPrefService->GetPrefs()->
       
   921 +        SetOverridingMozillaBoolPref(MozKey_CookieViewExceptions, lock, lock);
       
   922 +    if (NS_FAILED(rv))
       
   923 +      return rv;
       
   924 +    return aPrefService->GetPrefs()->
       
   925 +        SetOverridingMozillaIntPref(MozKey_CookieBehavior, behavior, lock);
       
   926 +}
       
   927 +static nsresult ReverseApplyDisableCookies(nsSystemPrefService* aPrefService,
       
   928 +                                           GConfClient* aClient)
       
   929 +{
       
   930 +    PRInt32 behavior = -1;
       
   931 +    nsCOMPtr<nsIPrefBranch2> prefs =
       
   932 +        aPrefService->GetPrefs()->GetPrefUserBranch();
       
   933 +    prefs->GetIntPref(MozKey_CookieBehavior, &behavior);
       
   934 +    if (behavior < 0)
       
   935 +        return NS_ERROR_FAILURE;
       
   936 +    if (gconf_client_key_is_writable(aClient, GConfKey_DisableCookies, nsnull))
       
   937 +        gconf_client_set_bool(aClient, GConfKey_DisableCookies, behavior == 2, nsnull);
       
   938 +    else
       
   939 +        NS_ERROR("Gconf key is not writable");
       
   940      return NS_OK;
       
   941  }
       
   942  
       
   943 +static char const* windowOpenFeatures[] = {
       
   944 +    "dom.disable_window_open_feature.close",
       
   945 +    "dom.disable_window_open_feature.directories",
       
   946 +    "dom.disable_window_open_feature.location",
       
   947 +    "dom.disable_window_open_feature.menubar",
       
   948 +    "dom.disable_window_open_feature.minimizable",
       
   949 +    "dom.disable_window_open_feature.personalbar",
       
   950 +    "dom.disable_window_open_feature.resizable",
       
   951 +    "dom.disable_window_open_feature.scrollbars",
       
   952 +    "dom.disable_window_open_feature.status",
       
   953 +    "dom.disable_window_open_feature.titlebar",
       
   954 +    "dom.disable_window_open_feature.toolbar"
       
   955 +};
       
   956 +/**
       
   957 + * The relationship R is
       
   958 + * "/apps/firefox/lockdown/disable_javascript_chrome" is true if and only if
       
   959 + * all of windowOpenFeatures are true
       
   960 + */
       
   961 +static const char GConfKey_DisableJSChrome[] =
       
   962 +    "/apps/firefox/lockdown/disable_javascript_chrome";
       
   963 +static nsresult ApplyWindowOpen(nsSystemPrefService* aPrefService,
       
   964 +                                GConfClient* aClient)
       
   965 +{
       
   966 +    gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableJSChrome, nsnull);
       
   967 +    PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableJSChrome, nsnull);
       
   968 +    PRBool curValues[NUM_ELEM(windowOpenFeatures)];
       
   969 +    PRUint32 i;
       
   970 +    nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
   971 +    PRBool allDisabled = PR_TRUE;
       
   972 +    for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
       
   973 +        nsresult rv = prefs->GetBoolPref(windowOpenFeatures[i], &curValues[i]);
       
   974 +        if (NS_FAILED(rv))
       
   975 +            return rv;
       
   976 +        if (!curValues[i]) {
       
   977 +            allDisabled = PR_FALSE;
       
   978 +        }
       
   979 +    }
       
   980 +    for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
       
   981 +        PRBool newVal = curValues[i];
       
   982 +        if (disable) {
       
   983 +            newVal = PR_TRUE;
       
   984 +        } else if (allDisabled) {
       
   985 +            // If all disable-window-open-feature prefs are currently
       
   986 +            // PR_TRUE, then we need to set at least one of them to
       
   987 +            // PR_FALSE. Set all of them to PR_FALSE.
       
   988 +            newVal = PR_FALSE;
       
   989 +        } // If at least one disable-window-open-feature pref is
       
   990 +          // currently PR_FALSE, then we don't need to change anything
       
   991 +          // when the gconf pref says don't disable
       
   992 +        nsresult rv = aPrefService->GetPrefs()->
       
   993 +            SetOverridingMozillaBoolPref(windowOpenFeatures[i], newVal, lock);
       
   994 +        if (NS_FAILED(rv))
       
   995 +            return rv;
       
   996 +    }
       
   997 +    return NS_OK;
       
   998 +}
       
   999 +
       
  1000 +static nsresult ReverseApplyWindowOpen(nsSystemPrefService* aPrefService,
       
  1001 +                                       GConfClient* aClient)
       
  1002 +{
       
  1003 +    nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
  1004 +    PRBool allDisabled = PR_TRUE;
       
  1005 +    PRBool curValues[NUM_ELEM(windowOpenFeatures)];
       
  1006 +    for (PRUint32 i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
       
  1007 +        nsresult rv = prefs->GetBoolPref(windowOpenFeatures[i], &curValues[i]);
       
  1008 +        if (NS_FAILED(rv))
       
  1009 +            return rv;
       
  1010 +        if (!curValues[i]) {
       
  1011 +            allDisabled = PR_FALSE;
       
  1012 +        }
       
  1013 +    }
       
  1014 +    if (gconf_client_key_is_writable(aClient, GConfKey_DisableJSChrome, nsnull))
       
  1015 +        gconf_client_set_bool(aClient, GConfKey_DisableJSChrome, allDisabled, nsnull);
       
  1016 +    else
       
  1017 +        NS_ERROR("Gconf key is not writable");
       
  1018 +    return NS_OK;
       
  1019 +}
       
  1020 +
       
  1021 +/**
       
  1022 + * The relationship R is
       
  1023 + * If "/apps/firefox/lockdown/disable_unsafe_protocol" is true then
       
  1024 + * -- "network.protocol-handler.blocked-default" is true
       
  1025 + * -- "network.protocol-handler.blocked.XYZ" is false if and only if
       
  1026 + * XYZ is a builtin non-disablable protocol or in
       
  1027 + * "/apps/firefox/lockdown/additional_safe_protocols"
       
  1028 + * AND if "/apps/firefox/lockdown/disable_unsafe_protocol" is false then
       
  1029 + * -- "network.protocol-handler.blocked-default" is false
       
  1030 + * -- if "network.protocol-handler.blocked.XYZ" exists then it is false
       
  1031 + */
       
  1032 +static const char GConfKey_DisableUnsafeProtocols[] =
       
  1033 +    "/apps/firefox/lockdown/disable_unsafe_protocol";
       
  1034 +static const char GConfKey_AdditionalSafeProtocols[] =
       
  1035 +    "/apps/firefox/lockdown/additional_safe_protocols";
       
  1036 +static const char MozKey_BlockedDefault[] =
       
  1037 +    "network.protocol-handler.blocked-default";
       
  1038 +static const char MozKey_BlockedPrefix[] =
       
  1039 +    "network.protocol-handler.blocked.";
       
  1040 +static const char* nonDisablableBuiltinProtocols[] =
       
  1041 +    { "about", "data", "jar", "keyword", "resource", "viewsource",
       
  1042 +      "chrome", "moz-icon", "javascript", "file" };
       
  1043 +static PRBool FindString(const char** aList, PRInt32 aCount,
       
  1044 +                         const char* aStr)
       
  1045 +{
       
  1046 +    for (PRInt32 i = 0; i < aCount; ++i) {
       
  1047 +        if (!strcmp(aStr, aList[i]))
       
  1048 +            return PR_TRUE;
       
  1049 +    }
       
  1050 +    return PR_FALSE;
       
  1051 +}
       
  1052 +typedef nsDataHashtable<nsCStringHashKey,int> StringSet;
       
  1053 +/** Collect the set of protocol names that we want to set preferences for */
       
  1054 +static nsresult AddAllProtocols(nsSystemPrefService* aPrefService,
       
  1055 +                                const char* aSafeProtocols,
       
  1056 +                                StringSet* aProtocolSet,
       
  1057 +                                StringSet* aSafeSet)
       
  1058 +{
       
  1059 +    nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
  1060 +    PRUint32 childCount;
       
  1061 +    char **childArray = nsnull;
       
  1062 +    nsresult rv = prefs->GetChildList(MozKey_BlockedPrefix, &childCount, &childArray);
       
  1063 +    if (NS_FAILED(rv))
       
  1064 +        return rv;
       
  1065 +    PRUint32 i;
       
  1066 +    for (i = 0; i < childCount; ++i) {
       
  1067 +        nsDependentCString tmp(childArray[i] + NUM_ELEM(MozKey_BlockedPrefix)-1);
       
  1068 +        aProtocolSet->Put(tmp, 1); // copies
       
  1069 +    }
       
  1070 +    for (i = 0; i < NUM_ELEM(nonDisablableBuiltinProtocols); ++i) {
       
  1071 +        nsDependentCString tmp(nonDisablableBuiltinProtocols[i]);
       
  1072 +        aProtocolSet->Put(tmp, 1);
       
  1073 +    }
       
  1074 +    i = 0;
       
  1075 +    while (aSafeProtocols[i]) {
       
  1076 +        const char* nextComma = strchr(aSafeProtocols+i, ',');
       
  1077 +        PRUint32 tokLen = nextComma ? nextComma - (aSafeProtocols+i)
       
  1078 +            : strlen(aSafeProtocols+i);
       
  1079 +        nsCAutoString tok(aSafeProtocols+i, tokLen);
       
  1080 +        aProtocolSet->Put(tok, 1);
       
  1081 +        aSafeSet->Put(tok, 1);
       
  1082 +        if (nextComma) {
       
  1083 +            i = nextComma - aSafeProtocols + 1;
       
  1084 +        } else {
       
  1085 +            break;
       
  1086 +        }
       
  1087 +    }
       
  1088 +    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
       
  1089 +    return NS_OK;
       
  1090 +}
       
  1091 +
       
  1092 +struct ProtocolPrefClosure {
       
  1093 +    StringSet safeProtocolSet;
       
  1094 +    nsIPrefBranch2* prefs;
       
  1095 +    nsISystemPref* prefSetter;
       
  1096 +    PRPackedBool disableUnsafe;
       
  1097 +    PRPackedBool lock;
       
  1098 +};
       
  1099 +
       
  1100 +static PLDHashOperator PR_CALLBACK SetProtocolPref(const nsACString& aKey,
       
  1101 +                                                   int aItem,
       
  1102 +                                                   void* aClosure)
       
  1103 +{
       
  1104 +    ProtocolPrefClosure* closure = static_cast<ProtocolPrefClosure*>(aClosure);
       
  1105 +    const nsCString& protocol = PromiseFlatCString(aKey);
       
  1106 +    PRBool blockProtocol = PR_FALSE;
       
  1107 +    if (closure->disableUnsafe &&
       
  1108 +        !FindString(nonDisablableBuiltinProtocols,
       
  1109 +                    NUM_ELEM(nonDisablableBuiltinProtocols), protocol.get()) &&
       
  1110 +        !closure->safeProtocolSet.Get(aKey, nsnull)) {
       
  1111 +        blockProtocol = PR_TRUE;
       
  1112 +    }
       
  1113 +
       
  1114 +    nsCAutoString prefName;
       
  1115 +    prefName.Append(MozKey_BlockedPrefix);
       
  1116 +    prefName.Append(protocol);
       
  1117 +    closure->prefSetter->SetOverridingMozillaBoolPref(prefName.get(), blockProtocol,
       
  1118 +                                                      closure->lock);
       
  1119 +    return PL_DHASH_NEXT;
       
  1120 +}
       
  1121 +static nsresult ApplyUnsafeProtocols(nsSystemPrefService* aPrefService,
       
  1122 +                                     GConfClient* aClient)
       
  1123 +{
       
  1124 +    PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableUnsafeProtocols, nsnull)
       
  1125 +        || !gconf_client_key_is_writable(aClient, GConfKey_AdditionalSafeProtocols, nsnull);
       
  1126 +    gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableUnsafeProtocols, nsnull);
       
  1127 +    char* protocols = gconf_client_get_string(aClient, GConfKey_AdditionalSafeProtocols, nsnull);
       
  1128 +    if (!protocols)
       
  1129 +        return NS_ERROR_FAILURE;
       
  1130 +    nsresult rv = aPrefService->GetPrefs()->
       
  1131 +        SetOverridingMozillaBoolPref(MozKey_BlockedDefault, disable, lock);
       
  1132 +    StringSet protocolSet;
       
  1133 +    ProtocolPrefClosure closure;
       
  1134 +    protocolSet.Init();
       
  1135 +    closure.safeProtocolSet.Init();
       
  1136 +    if (NS_SUCCEEDED(rv)) {
       
  1137 +        rv = AddAllProtocols(aPrefService, protocols, &protocolSet,
       
  1138 +                             &closure.safeProtocolSet);
       
  1139 +    }
       
  1140 +    if (NS_SUCCEEDED(rv)) {
       
  1141 +        closure.disableUnsafe = disable;
       
  1142 +        closure.lock = lock;
       
  1143 +        closure.prefSetter = aPrefService->GetPrefs();
       
  1144 +        nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
  1145 +        closure.prefs = prefs;
       
  1146 +        protocolSet.EnumerateRead(SetProtocolPref, &closure);
       
  1147 +    }
       
  1148 +    g_free(protocols);
       
  1149 +    return rv;
       
  1150 +}
       
  1151 +
       
  1152 +static nsresult ReverseApplyUnsafeProtocols(nsSystemPrefService* aPrefService,
       
  1153 +                                            GConfClient* aClient)
       
  1154 +{
       
  1155 +    nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
  1156 +    PRBool blockedDefault;
       
  1157 +    nsresult rv = prefs->GetBoolPref(MozKey_BlockedDefault, &blockedDefault);
       
  1158 +    if (NS_FAILED(rv))
       
  1159 +        return rv;
       
  1160 +    nsCAutoString enabledProtocols;
       
  1161 +    PRUint32 childCount;
       
  1162 +    char **childArray = nsnull;
       
  1163 +    rv = prefs->GetChildList(MozKey_BlockedPrefix, &childCount, &childArray);
       
  1164 +    if (NS_FAILED(rv))
       
  1165 +        return rv;
       
  1166 +    for (PRUint32 i = 0; i < childCount; ++i) {
       
  1167 +        PRBool val = PR_FALSE;
       
  1168 +        prefs->GetBoolPref(childArray[i], &val);
       
  1169 +        if (val) {
       
  1170 +            if (enabledProtocols.Length() > 0) {
       
  1171 +                enabledProtocols.Append(',');
       
  1172 +            }
       
  1173 +            enabledProtocols.Append(childArray[i] + NUM_ELEM(MozKey_BlockedPrefix)-1);
       
  1174 +        }
       
  1175 +    }
       
  1176 +    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
       
  1177 +    if (gconf_client_key_is_writable(aClient, GConfKey_DisableUnsafeProtocols, nsnull) &&
       
  1178 +            gconf_client_key_is_writable(aClient, GConfKey_AdditionalSafeProtocols, nsnull)) {
       
  1179 +        gconf_client_set_bool(aClient, GConfKey_DisableUnsafeProtocols, blockedDefault, nsnull);
       
  1180 +        gconf_client_set_string(aClient, GConfKey_AdditionalSafeProtocols,
       
  1181 +                                enabledProtocols.get(), nsnull);
       
  1182 +    } else {
       
  1183 +        NS_ERROR("Gconf key is not writable");
       
  1184 +    }
       
  1185 +    return NS_OK;
       
  1186 +}
       
  1187 +
       
  1188 +/**
       
  1189 + * Set config.lockdown.setwallpaper if and only if
       
  1190 + * /desktop/gnome/background/picture_filename is write-only. Always
       
  1191 + * lock it.
       
  1192 + */
       
  1193 +static const char MozKey_LockdownWallpaper[] = "config.lockdown.setwallpaper";
       
  1194 +static const char GConfKey_WallpaperSetting[] =
       
  1195 +    "/desktop/gnome/background/picture_filename";
       
  1196 +static nsresult ApplyWallpaper(nsSystemPrefService* aPrefService,
       
  1197 +                               GConfClient* aClient)
       
  1198 +{
       
  1199 +    PRBool canSetWallpaper =
       
  1200 +        gconf_client_key_is_writable(aClient, GConfKey_WallpaperSetting, nsnull);
       
  1201 +    return aPrefService->GetPrefs()->
       
  1202 +        SetOverridingMozillaBoolPref(MozKey_LockdownWallpaper,
       
  1203 +                                     !canSetWallpaper, PR_TRUE);
       
  1204 +}
       
  1205 +// No ReverseApplyWallpaper because this Mozilla pref can never be
       
  1206 +// modified
       
  1207 +
       
  1208 +/**
       
  1209 + * The relationship R is
       
  1210 + * "signon.rememberSignons" is true if and only if "/apps/firefox/web/disable_save_password"
       
  1211 + * is false.
       
  1212 + */
       
  1213 +static const char MozKey_RememberSignons[] = "signon.rememberSignons";
       
  1214 +static const char GConfKey_DisableSavePassword[] = "/apps/firefox/web/disable_save_password";
       
  1215 +static nsresult ApplyDisableSavePassword(nsSystemPrefService* aPrefService,
       
  1216 +                                         GConfClient* aClient)
       
  1217 +{
       
  1218 +    PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableSavePassword, nsnull);
       
  1219 +    gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableSavePassword, nsnull);
       
  1220 +    return aPrefService->GetPrefs()->
       
  1221 +        SetOverridingMozillaBoolPref(MozKey_RememberSignons, !disable, lock);
       
  1222 +}
       
  1223 +
       
  1224 +static nsresult ReverseApplyDisableSavePassword(nsSystemPrefService* aPrefService,
       
  1225 +                                                GConfClient* aClient)
       
  1226 +{
       
  1227 +    nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
  1228 +    PRBool remember;
       
  1229 +    nsresult rv = prefs->GetBoolPref(MozKey_RememberSignons, &remember);
       
  1230 +    if (NS_FAILED(rv))
       
  1231 +        return rv;
       
  1232 +    gconf_client_set_bool(aClient, GConfKey_DisableSavePassword, !remember, nsnull);
       
  1233 +    return NS_OK;
       
  1234 +}
       
  1235 +
       
  1236 +/**
       
  1237 + * The relationship R is
       
  1238 + * "permissions.default.image" is 1 (nsIPermissionManager::ALLOW_ACTION) if and only if
       
  1239 + * "/apps/firefox/web/images_load" is 0, AND
       
  1240 + * "permissions.default.image" is 2 (nsIPermissionManager::DENY_ACTION) if and only if
       
  1241 + * "/apps/firefox/web/images_load" is 2, AND
       
  1242 + * "permissions.default.image" is 3 if and only if "/apps/firefox/web/images_load" is 1
       
  1243 + *
       
  1244 + * Also, we set pref.advanced.images.disable_button.view_image iff
       
  1245 + * /apps/firefox/web/images_load is read-only
       
  1246 + * And we set permissions.default.honorExceptions iff
       
  1247 + * /apps/firefox/web/images_load is not read-only
       
  1248 + */
       
  1249 +static const char MozKey_ImagePermissions[] = "permissions.default.image";
       
  1250 +static const char MozKey_ImageExceptions[] = "permissions.honorExceptions.image";
       
  1251 +static const char MozKey_ImageViewExceptions[] = "pref.advanced.images.disable_button.view_image";
       
  1252 +static const char GConfKey_LoadImages[] = "/apps/firefox/web/images_load";
       
  1253 +static nsresult ApplyLoadImages(nsSystemPrefService* aPrefService,
       
  1254 +                                 GConfClient* aClient)
       
  1255 +{
       
  1256 +    PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_LoadImages, nsnull);
       
  1257 +    // 0 == accept, 1 == no-foreign, 2 == reject
       
  1258 +    gint setting = gconf_client_get_int(aClient, GConfKey_LoadImages, nsnull);
       
  1259 +    PRInt32 pref;
       
  1260 +    switch (setting) {
       
  1261 +      case 0: pref = nsIPermissionManager::ALLOW_ACTION; break;
       
  1262 +      case 2: pref = nsIPermissionManager::DENY_ACTION; break;
       
  1263 +      case 1: pref = 3; break;
       
  1264 +      default: return NS_ERROR_FAILURE;
       
  1265 +    }
       
  1266 +    nsresult rv = aPrefService->GetPrefs()->
       
  1267 +        SetOverridingMozillaBoolPref(MozKey_ImageExceptions, !lock, lock);
       
  1268 +    if (NS_FAILED(rv))
       
  1269 +      return rv;
       
  1270 +    rv = aPrefService->GetPrefs()->
       
  1271 +        SetOverridingMozillaBoolPref(MozKey_ImageViewExceptions, lock, lock);
       
  1272 +    if (NS_FAILED(rv))
       
  1273 +      return rv;
       
  1274 +    return aPrefService->GetPrefs()->
       
  1275 +        SetOverridingMozillaIntPref(MozKey_ImagePermissions, pref, lock);
       
  1276 +}
       
  1277 +
       
  1278 +static nsresult ReverseApplyLoadImages(nsSystemPrefService* aPrefService,
       
  1279 +                                        GConfClient* aClient)
       
  1280 +{
       
  1281 +    nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
  1282 +    PRInt32 pref;
       
  1283 +    nsresult rv = prefs->GetIntPref(MozKey_ImagePermissions, &pref);
       
  1284 +    if (NS_FAILED(rv))
       
  1285 +        return rv;
       
  1286 +    gint setting;
       
  1287 +    switch (pref) {
       
  1288 +      case nsIPermissionManager::ALLOW_ACTION: setting = 0; break;
       
  1289 +      case nsIPermissionManager::DENY_ACTION: setting = 2; break;
       
  1290 +      case 3: setting = 1; break;
       
  1291 +      default: return NS_ERROR_FAILURE;
       
  1292 +    }
       
  1293 +    if (gconf_client_key_is_writable(aClient, GConfKey_LoadImages, nsnull))
       
  1294 +        gconf_client_set_int(aClient, GConfKey_LoadImages, setting, nsnull);
       
  1295 +    else
       
  1296 +        NS_ERROR("Gconf key is not writable");
       
  1297 +    return NS_OK;
       
  1298 +}
       
  1299 +
       
  1300 +/**
       
  1301 + * The relationship R is
       
  1302 + * "/apps/firefox/web/disable_popups" is true if and only if
       
  1303 + * "dom.disable_open_during_load" is true
       
  1304 + * AND if "/apps/firefox/web/disable_popups" is true then
       
  1305 + * "privacy.popups.showBrowserMessage" is false.
       
  1306 + */
       
  1307 +static const char MozKey_DisablePopups[] = "dom.disable_open_during_load";
       
  1308 +static const char MozKey_DisableBrowserPopupMessage[] = "privacy.popups.showBrowserMessage";
       
  1309 +static const char GConfKey_DisablePopups[] = "/apps/firefox/web/disable_popups";
       
  1310 +static nsresult ApplyDisablePopups(nsSystemPrefService* aPrefService,
       
  1311 +                                   GConfClient* aClient)
       
  1312 +{
       
  1313 +    PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisablePopups, nsnull);
       
  1314 +    gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisablePopups, nsnull);
       
  1315 +    nsresult rv = aPrefService->GetPrefs()->
       
  1316 +        SetOverridingMozillaBoolPref(MozKey_DisablePopups, disable, lock);
       
  1317 +    if (NS_SUCCEEDED(rv)) {
       
  1318 +        if (disable) {
       
  1319 +            rv = aPrefService->GetPrefs()->
       
  1320 +                SetOverridingMozillaBoolPref(MozKey_DisableBrowserPopupMessage, PR_TRUE, lock);
       
  1321 +        } else {
       
  1322 +            rv = aPrefService->GetPrefs()->
       
  1323 +                StopOverridingMozillaPref(MozKey_DisableBrowserPopupMessage);
       
  1324 +        }
       
  1325 +    }
       
  1326 +    return rv;
       
  1327 +}
       
  1328 +
       
  1329 +static nsresult ReverseApplyDisablePopups(nsSystemPrefService* aPrefService,
       
  1330 +                                          GConfClient* aClient)
       
  1331 +{
       
  1332 +    nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
       
  1333 +    PRBool disabled;
       
  1334 +    nsresult rv = prefs->GetBoolPref(MozKey_DisablePopups, &disabled);
       
  1335 +    if (NS_FAILED(rv))
       
  1336 +        return rv;
       
  1337 +    if (gconf_client_key_is_writable(aClient, GConfKey_DisablePopups, nsnull))
       
  1338 +        gconf_client_set_bool(aClient, GConfKey_DisablePopups, disabled, nsnull);
       
  1339 +    else
       
  1340 +        NS_ERROR("Gconf key is not writable");
       
  1341 +    return NS_OK;
       
  1342 +}
       
  1343 +
       
  1344 +static ComplexGConfPrefMapping sComplexGConfPrefMappings[] = {
       
  1345 +    {GConfKey_TrustedURIs, ApplyTrustedURIs},
       
  1346 +    {GConfKey_DelegationURIs, ApplyDelegationURIs},
       
  1347 +    {GConfKey_DownloadFolder, ApplyDownloadFolder},
       
  1348 +    {GConfKey_DisableCookies, ApplyDisableCookies},
       
  1349 +    {GConfKey_DisableJSChrome, ApplyWindowOpen},
       
  1350 +    {GConfKey_DisableUnsafeProtocols, ApplyUnsafeProtocols},
       
  1351 +    {GConfKey_AdditionalSafeProtocols, ApplyUnsafeProtocols},
       
  1352 +    {GConfKey_WallpaperSetting, ApplyWallpaper},
       
  1353 +    {GConfKey_DisableSavePassword, ApplyDisableSavePassword},
       
  1354 +    {GConfKey_LoadImages, ApplyLoadImages},
       
  1355 +    {GConfKey_DisablePopups, ApplyDisablePopups}
       
  1356 +};
       
  1357 +static ComplexMozPrefMapping sComplexMozPrefMappings[] = {
       
  1358 +    {MozKey_TrustedURIs, ReverseApplyTrustedURIs},
       
  1359 +    {MozKey_DelegationURIs, ReverseApplyDelegationURIs},
       
  1360 +    {MozKey_UseDownloadDir, ReverseApplyDownloadFolder},
       
  1361 +    {MozKey_DownloadDirType, ReverseApplyDownloadFolder},
       
  1362 +    {MozKey_DownloadDirExplicit, ReverseApplyDownloadFolder},
       
  1363 +    {MozKey_CookieBehavior, ReverseApplyDisableCookies},
       
  1364 +    {MozKey_RememberSignons, ReverseApplyDisableSavePassword},
       
  1365 +    {MozKey_ImagePermissions, ReverseApplyLoadImages},
       
  1366 +    {MozKey_DisablePopups, ReverseApplyDisablePopups}
       
  1367 +};
       
  1368 +// The unsafe protocol preferences are handled specially because
       
  1369 +// they affect an unknown number of Mozilla preferences
       
  1370 +// Window opener permissions are also handled specially so we don't have to
       
  1371 +// repeat the windowOpenFeatures list.
       
  1372 +
       
  1373 +/* END preference mapping definition area */
       
  1374 +
       
  1375 +static PR_CALLBACK void GConfSimpleNotification(GConfClient* client,
       
  1376 +                                                guint cnxn_id,
       
  1377 +                                                GConfEntry *entry,
       
  1378 +                                                gpointer user_data)
       
  1379 +{
       
  1380 +    nsSystemPrefService* service = static_cast<nsSystemPrefService*>(user_data);
       
  1381 +    SimplePrefMapping* map = static_cast<SimplePrefMapping*>(
       
  1382 +                                            service->GetSimpleCallbackData(cnxn_id));
       
  1383 +    NS_ASSERTION(map, "Can't find mapping for callback");
       
  1384 +    if (!map)
       
  1385 +        return;
       
  1386 +
       
  1387 +    ApplySimpleMapping(map, service->GetPrefs(), client);
       
  1388 +}
       
  1389 +
       
  1390 +static PR_CALLBACK void GConfComplexNotification(GConfClient* client,
       
  1391 +                                                 guint cnxn_id,
       
  1392 +                                                 GConfEntry *entry,
       
  1393 +                                                 gpointer user_data)
       
  1394 +{
       
  1395 +    nsSystemPrefService* service = static_cast<nsSystemPrefService*>(user_data);
       
  1396 +    ComplexGConfPrefMapping* map = static_cast<ComplexGConfPrefMapping*>(
       
  1397 +                                                  service->GetComplexCallbackData(cnxn_id));
       
  1398 +    NS_ASSERTION(map, "Can't find mapping for callback");
       
  1399 +    if (!map)
       
  1400 +        return;
       
  1401 +
       
  1402 +    map->callback(service, GetGConf());
       
  1403 +}
       
  1404 +
       
  1405 +nsresult nsSystemPrefService::LoadSystemPreferences(nsISystemPref* aPrefs)
       
  1406 +{
       
  1407 +    mPref = aPrefs;
       
  1408 +
       
  1409 +    GConfClient* client = GetGConf();
       
  1410 +    PRUint32 i;
       
  1411 +    // Register simple mappings and callbacks
       
  1412 +    for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
       
  1413 +        guint cx = gconf_client_notify_add(client,
       
  1414 +                                           sSimplePrefMappings[i].gconfPrefName,
       
  1415 +                                           GConfSimpleNotification, this,
       
  1416 +                                           nsnull, nsnull);
       
  1417 +        mGConfSimpleCallbacks.Put(cx, &sSimplePrefMappings[i]);
       
  1418 +        nsresult rv = ApplySimpleMapping(&sSimplePrefMappings[i], aPrefs, client);
       
  1419 +        if (NS_FAILED(rv))
       
  1420 +            return rv;
       
  1421 +    }
       
  1422 +
       
  1423 +    // Update Mozilla settings with any gconf settings that have
       
  1424 +    // changed from the default. Do it before we register our
       
  1425 +    // Mozilla notifications.
       
  1426 +    ComplexGConfPrefChanged lastCallback = nsnull;
       
  1427 +    for (i = 0; i < NUM_ELEM(sComplexGConfPrefMappings); ++i) {
       
  1428 +        guint cx = gconf_client_notify_add(client,
       
  1429 +                                           sComplexGConfPrefMappings[i].gconfPrefName,
       
  1430 +                                           GConfComplexNotification, this,
       
  1431 +                                           nsnull, nsnull);
       
  1432 +        mGConfComplexCallbacks.Put(cx, &sComplexGConfPrefMappings[i]);
       
  1433 +        ComplexGConfPrefChanged cb = sComplexGConfPrefMappings[i].callback;
       
  1434 +        if (cb != lastCallback) {
       
  1435 +            cb(this, client);
       
  1436 +            lastCallback = cb;
       
  1437 +        }
       
  1438 +    }
       
  1439 +
       
  1440 +    nsCOMPtr<nsIPrefBranch2> userPrefs = aPrefs->GetPrefUserBranch();
       
  1441 +
       
  1442 +    // Update gconf settings with any Mozilla settings that have
       
  1443 +    // changed from the default.
       
  1444 +    for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
       
  1445 +        gconf_client_add_dir(client, sSimplePrefMappings[i].gconfPrefName,
       
  1446 +                             GCONF_CLIENT_PRELOAD_NONE, nsnull);
       
  1447 +
       
  1448 +        PRBool hasUserPref = PR_FALSE;
       
  1449 +        nsresult rv =
       
  1450 +            userPrefs->PrefHasUserValue(sSimplePrefMappings[i].mozPrefName,
       
  1451 +                                        &hasUserPref);
       
  1452 +        if (NS_FAILED(rv))
       
  1453 +            return rv;
       
  1454 +        if (hasUserPref && sSimplePrefMappings[i].allowWritesFromMozilla) {
       
  1455 +            rv = ReverseApplySimpleMapping(&sSimplePrefMappings[i],
       
  1456 +                                           aPrefs, client);
       
  1457 +            if (NS_FAILED(rv))
       
  1458 +                return rv;
       
  1459 +        }
       
  1460 +    }
       
  1461 +    for (i = 0; i < NUM_ELEM(sComplexGConfPrefMappings); ++i) {
       
  1462 +        gconf_client_add_dir(client, sComplexGConfPrefMappings[i].gconfPrefName,
       
  1463 +                             GCONF_CLIENT_PRELOAD_NONE, nsnull);
       
  1464 +    }
       
  1465 +    ComplexMozPrefChanged lastMozCallback = nsnull;
       
  1466 +    for (i = 0; i < NUM_ELEM(sComplexMozPrefMappings); ++i) {
       
  1467 +        PRBool hasUserPref = PR_FALSE;
       
  1468 +        nsresult rv =
       
  1469 +            userPrefs->PrefHasUserValue(sComplexMozPrefMappings[i].mozPrefName,
       
  1470 +                                        &hasUserPref);
       
  1471 +        if (NS_FAILED(rv))
       
  1472 +            return rv;
       
  1473 +        if (hasUserPref) {
       
  1474 +            ComplexMozPrefChanged cb = sComplexMozPrefMappings[i].callback;
       
  1475 +            if (cb != lastMozCallback) {
       
  1476 +                cb(this, client);
       
  1477 +                lastMozCallback = cb;
       
  1478 +            }
       
  1479 +        }
       
  1480 +    }
       
  1481 +
       
  1482 +    ApplyUnsafeProtocols(this, client);
       
  1483 +
       
  1484 +    return NS_OK;
       
  1485 +}
       
  1486 +
       
  1487 +nsresult nsSystemPrefService::NotifyMozillaPrefChanged(const char* aPrefName)
       
  1488 +{
       
  1489 +    PRUint32 i;
       
  1490 +    GConfClient* client = GetGConf();
       
  1491 +
       
  1492 +    for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
       
  1493 +        if (!strcmp(aPrefName, sSimplePrefMappings[i].mozPrefName)) {
       
  1494 +            ReverseApplySimpleMapping(&sSimplePrefMappings[i],
       
  1495 +                                      mPref, client);
       
  1496 +        }
       
  1497 +    }
       
  1498 +
       
  1499 +    for (i = 0; i < NUM_ELEM(sComplexMozPrefMappings); ++i) {
       
  1500 +        if (!strcmp(aPrefName, sComplexMozPrefMappings[i].mozPrefName)) {
       
  1501 +            sComplexMozPrefMappings[i].callback(this, client);
       
  1502 +        }
       
  1503 +    }
       
  1504 +
       
  1505 +    for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
       
  1506 +        if (!strcmp(aPrefName, windowOpenFeatures[i])) {
       
  1507 +            ReverseApplyWindowOpen(this, client);
       
  1508 +        }
       
  1509 +    }
       
  1510 +
       
  1511 +    ReverseApplyUnsafeProtocols(this, client);
       
  1512 +
       
  1513 +    return NS_OK;
       
  1514 +}
       
  1515 +
       
  1516 +static PLDHashOperator PR_CALLBACK UnregisterSimple(const PRUint32& aKey,
       
  1517 +                                                    SimplePrefMapping* aData,
       
  1518 +                                                    void* aClosure)
       
  1519 +{
       
  1520 +    GConfClient* client = GetGConf();
       
  1521 +    gconf_client_notify_remove(client, aKey);
       
  1522 +    gconf_client_remove_dir(client, aData->gconfPrefName, nsnull);
       
  1523 +    return PL_DHASH_NEXT;
       
  1524 +}
       
  1525 +
       
  1526 +static PLDHashOperator PR_CALLBACK UnregisterComplex(const PRUint32& aKey,
       
  1527 +                                                     ComplexGConfPrefMapping* aData,
       
  1528 +                                                     void* aClosure)
       
  1529 +{
       
  1530 +    GConfClient* client = GetGConf();
       
  1531 +    gconf_client_notify_remove(client, aKey);
       
  1532 +    gconf_client_remove_dir(client, aData->gconfPrefName, nsnull);
       
  1533 +    return PL_DHASH_NEXT;
       
  1534 +}
       
  1535 +
       
  1536 +nsresult nsSystemPrefService::NotifyUnloadSystemPreferences()
       
  1537 +{
       
  1538 +    // Unregister callbacks
       
  1539 +    mGConfSimpleCallbacks.EnumerateRead(UnregisterSimple, this);
       
  1540 +    mGConfSimpleCallbacks.Clear();
       
  1541 +    mGConfComplexCallbacks.EnumerateRead(UnregisterComplex, this);
       
  1542 +    mGConfComplexCallbacks.Clear();
       
  1543 +
       
  1544 +    return NS_OK;
       
  1545 +}
       
  1546 +
       
  1547 +// PrefBranch interfaces
       
  1548 +
       
  1549 +GConfValue* nsSystemPrefService::GConfGet(const char *aPrefName)
       
  1550 +{
       
  1551 +    PRUint32 i;
       
  1552 +    PRBool found = PR_FALSE;
       
  1553 +    GConfValue *val = NULL;
       
  1554 +    GConfClient* client = GetGConf();
       
  1555 +    NS_ASSERTION(client, "Could not get default GConf client");
       
  1556 +    if (!client) {
       
  1557 +        return NULL;
       
  1558 +    }
       
  1559 +    for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
       
  1560 +        if (!strcmp(aPrefName, sSimplePrefMappings[i].mozPrefName)) {
       
  1561 +            found = PR_TRUE;
       
  1562 +            break;
       
  1563 +        }
       
  1564 +    }
       
  1565 +    if (found) {
       
  1566 +        val = gconf_client_get(client, 
       
  1567 +                               sSimplePrefMappings[i].gconfPrefName, 
       
  1568 +                               NULL);
       
  1569 +    }
       
  1570 +    return val;
       
  1571 +}
       
  1572 +
       
  1573  /* readonly attribute string root; */
       
  1574  NS_IMETHODIMP nsSystemPrefService::GetRoot(char * *aRoot)
       
  1575  {
       
  1576      return NS_ERROR_NOT_IMPLEMENTED;
       
  1577  }
       
  1578  
       
  1579  /* long getPrefType (in string aPrefName); */
       
  1580  NS_IMETHODIMP nsSystemPrefService::GetPrefType(const char *aPrefName, PRInt32 *_retval)
       
  1581  {
       
  1582      return NS_ERROR_NOT_IMPLEMENTED;
       
  1583  }
       
  1584  
       
  1585  /* boolean getBoolPref (in string aPrefName); */
       
  1586  NS_IMETHODIMP nsSystemPrefService::GetBoolPref(const char *aPrefName, PRBool *_retval)
       
  1587  {
       
  1588 -    return mInitialized ?
       
  1589 -        mGConf->GetBoolPref(aPrefName, _retval) : NS_ERROR_FAILURE;
       
  1590 +    GConfValue *val = GConfGet(aPrefName);
       
  1591 +    if (val) {
       
  1592 +        *_retval = (PRBool)(gconf_value_get_bool(val));
       
  1593 +        return NS_OK;
       
  1594 +    }
       
  1595 +    return NS_ERROR_FAILURE;
       
  1596  }
       
  1597  
       
  1598  /* void setBoolPref (in string aPrefName, in long aValue); */
       
  1599  NS_IMETHODIMP nsSystemPrefService::SetBoolPref(const char *aPrefName, PRInt32 aValue)
       
  1600  {
       
  1601      return NS_ERROR_NOT_IMPLEMENTED;
       
  1602  }
       
  1603  
       
  1604  /* string getCharPref (in string aPrefName); */
       
  1605  NS_IMETHODIMP nsSystemPrefService::GetCharPref(const char *aPrefName, char **_retval)
       
  1606  {
       
  1607 -    return mInitialized ?
       
  1608 -        mGConf->GetCharPref(aPrefName, _retval) : NS_ERROR_FAILURE;
       
  1609 +    GConfValue *val = GConfGet(aPrefName);
       
  1610 +    if (val) {
       
  1611 +        *_retval = (char*)(gconf_value_get_string(val));
       
  1612 +        return *_retval ? NS_OK : NS_ERROR_FAILURE;
       
  1613 +    }
       
  1614 +    return NS_ERROR_FAILURE;
       
  1615  }
       
  1616  
       
  1617  /* void setCharPref (in string aPrefName, in string aValue); */
       
  1618  NS_IMETHODIMP nsSystemPrefService::SetCharPref(const char *aPrefName, const char *aValue)
       
  1619  {
       
  1620      return NS_ERROR_NOT_IMPLEMENTED;
       
  1621  }
       
  1622  
       
  1623  /* long getIntPref (in string aPrefName); */
       
  1624  NS_IMETHODIMP nsSystemPrefService::GetIntPref(const char *aPrefName, PRInt32 *_retval)
       
  1625  {
       
  1626 -    return mInitialized ?
       
  1627 -        mGConf->GetIntPref(aPrefName, _retval) : NS_ERROR_FAILURE;
       
  1628 +    GConfValue *val = GConfGet(aPrefName);
       
  1629 +    if (val) {
       
  1630 +        *_retval = (PRInt32)(gconf_value_get_int(val));
       
  1631 +        return NS_OK;
       
  1632 +    }
       
  1633 +    return NS_ERROR_FAILURE;
       
  1634  }
       
  1635  
       
  1636  /* void setIntPref (in string aPrefName, in long aValue); */
       
  1637  NS_IMETHODIMP nsSystemPrefService::SetIntPref(const char *aPrefName, PRInt32 aValue)
       
  1638  {
       
  1639      return NS_ERROR_NOT_IMPLEMENTED;
       
  1640  }
       
  1641  
       
  1642 -/* void getComplexValue (in string aPrefName, in nsIIDRef aType, [iid_is (aType), retval] out nsQIResult aValue); */
       
  1643 +/* void getComplexValue (in string aPrefName, in nsIIDRef aType, [iid_is
       
  1644 + * (aType), retval] out nsQIResult aValue); */
       
  1645  NS_IMETHODIMP nsSystemPrefService::GetComplexValue(const char *aPrefName, const nsIID & aType, void * *aValue)
       
  1646  {
       
  1647      return NS_ERROR_NOT_IMPLEMENTED;
       
  1648  }
       
  1649 -
       
  1650 -/* void setComplexValue (in string aPrefName, in nsIIDRef aType, in nsISupports aValue); */
       
  1651 +/* void setComplexValue (in string aPrefName, in nsIIDRef aType, in
       
  1652 + * nsISupports aValue); */
       
  1653  NS_IMETHODIMP nsSystemPrefService::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
       
  1654  {
       
  1655      return NS_ERROR_NOT_IMPLEMENTED;
       
  1656  }
       
  1657  
       
  1658  /* void clearUserPref (in string aPrefName); */
       
  1659  NS_IMETHODIMP nsSystemPrefService::ClearUserPref(const char *aPrefName)
       
  1660  {
       
  1661 @@ -360,557 +1363,36 @@ NS_IMETHODIMP nsSystemPrefService::Unloc
       
  1662  }
       
  1663  
       
  1664  /* void deleteBranch (in string aStartingAt); */
       
  1665  NS_IMETHODIMP nsSystemPrefService::DeleteBranch(const char *aStartingAt)
       
  1666  {
       
  1667      return NS_ERROR_NOT_IMPLEMENTED;
       
  1668  }
       
  1669  
       
  1670 -/* void getChildList (in string aStartingAt, out unsigned long aCount, [array, size_is (aCount), retval] out string aChildArray); */
       
  1671 +/* void getChildList (in string aStartingAt, out unsigned long aCount, [array,
       
  1672 + * size_is (aCount), retval] out string aChildArray); */
       
  1673  NS_IMETHODIMP nsSystemPrefService::GetChildList(const char *aStartingAt, PRUint32 *aCount, char ***aChildArray)
       
  1674  {
       
  1675      return NS_ERROR_NOT_IMPLEMENTED;
       
  1676  }
       
  1677  
       
  1678  /* void resetBranch (in string aStartingAt); */
       
  1679  NS_IMETHODIMP nsSystemPrefService::ResetBranch(const char *aStartingAt)
       
  1680  {
       
  1681      return NS_ERROR_NOT_IMPLEMENTED;
       
  1682  }
       
  1683  
       
  1684 -/* void addObserver (in string aDomain, in nsIObserver aObserver, in boolean aHoldWeak); */
       
  1685 -NS_IMETHODIMP nsSystemPrefService::AddObserver(const char *aDomain, nsIObserver *aObserver, PRBool aHoldWeak)
       
  1686 -{
       
  1687 -    nsresult rv;
       
  1688  
       
  1689 -    NS_ENSURE_ARG_POINTER(aDomain);
       
  1690 -    NS_ENSURE_ARG_POINTER(aObserver);
       
  1691 +// Factory stuff
       
  1692  
       
  1693 -    NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
       
  1694 +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPrefService, Init)
       
  1695  
       
  1696 -    PRUint32 prefAtom;
       
  1697 -    // make sure the pref name is supported
       
  1698 -    rv = mGConf->GetAtomForMozKey(aDomain, &prefAtom);
       
  1699 -    NS_ENSURE_SUCCESS(rv, rv);
       
  1700 -
       
  1701 -    if (!mObservers) {
       
  1702 -        mObservers = new nsAutoVoidArray();
       
  1703 -        if (mObservers == nsnull)
       
  1704 -            return NS_ERROR_OUT_OF_MEMORY;
       
  1705 -    }
       
  1706 -
       
  1707 -    SysPrefCallbackData *pCallbackData = (SysPrefCallbackData *)
       
  1708 -        nsMemory::Alloc(sizeof(SysPrefCallbackData));
       
  1709 -    if (pCallbackData == nsnull)
       
  1710 -        return NS_ERROR_OUT_OF_MEMORY;
       
  1711 -
       
  1712 -    pCallbackData->bIsWeakRef = aHoldWeak;
       
  1713 -    pCallbackData->prefAtom = prefAtom;
       
  1714 -    // hold a weak reference to the observer if so requested
       
  1715 -    nsCOMPtr<nsISupports> observerRef;
       
  1716 -    if (aHoldWeak) {
       
  1717 -        nsCOMPtr<nsISupportsWeakReference> weakRefFactory = 
       
  1718 -            do_QueryInterface(aObserver);
       
  1719 -        if (!weakRefFactory) {
       
  1720 -            // the caller didn't give us a object that supports weak reference.
       
  1721 -            // ... tell them
       
  1722 -            nsMemory::Free(pCallbackData);
       
  1723 -            return NS_ERROR_INVALID_ARG;
       
  1724 -        }
       
  1725 -        nsCOMPtr<nsIWeakReference> tmp = do_GetWeakReference(weakRefFactory);
       
  1726 -        observerRef = tmp;
       
  1727 -    } else {
       
  1728 -        observerRef = aObserver;
       
  1729 -    }
       
  1730 -
       
  1731 -    rv = mGConf->NotifyAdd(prefAtom, pCallbackData);
       
  1732 -    if (NS_FAILED(rv)) {
       
  1733 -        nsMemory::Free(pCallbackData);
       
  1734 -        return rv;
       
  1735 -    }
       
  1736 -
       
  1737 -    pCallbackData->observer = observerRef;
       
  1738 -    NS_ADDREF(pCallbackData->observer);
       
  1739 -
       
  1740 -    mObservers->AppendElement(pCallbackData);
       
  1741 -    return NS_OK;
       
  1742 -}
       
  1743 -
       
  1744 -/* void removeObserver (in string aDomain, in nsIObserver aObserver); */
       
  1745 -NS_IMETHODIMP nsSystemPrefService::RemoveObserver(const char *aDomain, nsIObserver *aObserver)
       
  1746 -{
       
  1747 -    nsresult rv;
       
  1748 -
       
  1749 -    NS_ENSURE_ARG_POINTER(aDomain);
       
  1750 -    NS_ENSURE_ARG_POINTER(aObserver);
       
  1751 -    NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
       
  1752 -
       
  1753 -    if (!mObservers)
       
  1754 -        return NS_OK;
       
  1755 -    
       
  1756 -    PRUint32 prefAtom;
       
  1757 -    // make sure the pref name is supported
       
  1758 -    rv = mGConf->GetAtomForMozKey(aDomain, &prefAtom);
       
  1759 -    NS_ENSURE_SUCCESS(rv, rv);
       
  1760 -
       
  1761 -    // need to find the index of observer, so we can remove it
       
  1762 -    PRIntn count = mObservers->Count();
       
  1763 -    if (count <= 0)
       
  1764 -        return NS_OK;
       
  1765 -
       
  1766 -    PRIntn i;
       
  1767 -    SysPrefCallbackData *pCallbackData;
       
  1768 -    for (i = 0; i < count; ++i) {
       
  1769 -        pCallbackData = (SysPrefCallbackData *)mObservers->ElementAt(i);
       
  1770 -        if (pCallbackData) {
       
  1771 -            nsCOMPtr<nsISupports> observerRef;
       
  1772 -            if (pCallbackData->bIsWeakRef) {
       
  1773 -                nsCOMPtr<nsISupportsWeakReference> weakRefFactory =
       
  1774 -                    do_QueryInterface(aObserver);
       
  1775 -                if (weakRefFactory) {
       
  1776 -                    nsCOMPtr<nsIWeakReference> tmp =
       
  1777 -                        do_GetWeakReference(aObserver);
       
  1778 -                    observerRef = tmp;
       
  1779 -                }
       
  1780 -            }
       
  1781 -            if (!observerRef)
       
  1782 -                observerRef = aObserver;
       
  1783 -
       
  1784 -            if (pCallbackData->observer == observerRef &&
       
  1785 -                pCallbackData->prefAtom == prefAtom) {
       
  1786 -                rv = mGConf->NotifyRemove(prefAtom, pCallbackData);
       
  1787 -                if (NS_SUCCEEDED(rv)) {
       
  1788 -                    mObservers->RemoveElementAt(i);
       
  1789 -                    NS_RELEASE(pCallbackData->observer);
       
  1790 -                    nsMemory::Free(pCallbackData);
       
  1791 -                }
       
  1792 -                return rv;
       
  1793 -            }
       
  1794 -        }
       
  1795 -    }
       
  1796 -    return NS_OK;
       
  1797 -}
       
  1798 -
       
  1799 -void
       
  1800 -nsSystemPrefService::OnPrefChange(PRUint32 aPrefAtom, void *aData)
       
  1801 -{
       
  1802 -    if (!mInitialized)
       
  1803 -        return;
       
  1804 -
       
  1805 -    SysPrefCallbackData *pData = (SysPrefCallbackData *)aData;
       
  1806 -    if (pData->prefAtom != aPrefAtom)
       
  1807 -        return;
       
  1808 -
       
  1809 -    nsCOMPtr<nsIObserver> observer;
       
  1810 -    if (pData->bIsWeakRef) {
       
  1811 -        nsCOMPtr<nsIWeakReference> weakRef =
       
  1812 -            do_QueryInterface(pData->observer);
       
  1813 -        if(weakRef)
       
  1814 -            observer = do_QueryReferent(weakRef);
       
  1815 -        if (!observer) {
       
  1816 -            // this weak referenced observer went away, remove it from the list
       
  1817 -            nsresult rv = mGConf->NotifyRemove(aPrefAtom, pData);
       
  1818 -            if (NS_SUCCEEDED(rv)) {
       
  1819 -                mObservers->RemoveElement(pData);
       
  1820 -                NS_RELEASE(pData->observer);
       
  1821 -                nsMemory::Free(pData);
       
  1822 -            }
       
  1823 -            return;
       
  1824 -        }
       
  1825 -    }
       
  1826 -    else
       
  1827 -        observer = do_QueryInterface(pData->observer);
       
  1828 -
       
  1829 -    if (observer)
       
  1830 -        observer->Observe(static_cast<nsIPrefBranch *>(this),
       
  1831 -                          NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID,
       
  1832 -                          NS_ConvertUTF8toUTF16(mGConf->GetMozKey(aPrefAtom)).
       
  1833 -                          get());
       
  1834 -}
       
  1835 -
       
  1836 -/*************************************************************
       
  1837 - *  GConfProxy
       
  1838 - *
       
  1839 - ************************************************************/
       
  1840 -
       
  1841 -struct GConfFuncListType {
       
  1842 -    const char *FuncName;
       
  1843 -    PRFuncPtr  FuncPtr;
       
  1844 +static const nsModuleComponentInfo components[] = {
       
  1845 +    { NS_SYSTEMPREF_SERVICE_CLASSNAME,
       
  1846 +      NS_SYSTEMPREF_SERVICE_CID,
       
  1847 +      NS_SYSTEMPREF_SERVICE_CONTRACTID,
       
  1848 +      nsSystemPrefServiceConstructor,
       
  1849 +    },
       
  1850  };
       
  1851  
       
  1852 -struct PrefNamePair {
       
  1853 -    const char *mozPrefName;
       
  1854 -    const char *gconfPrefName;
       
  1855 -};
       
  1856 +NS_IMPL_NSGETMODULE(nsSystemPrefServiceModule, components)
       
  1857  
       
  1858 -const char
       
  1859 -GConfProxy::sPrefGConfKey[] = "accessibility.unix.gconf2.shared-library";
       
  1860 -const char GConfProxy::sDefaultLibName1[] = "libgconf-2.so.4";
       
  1861 -const char GConfProxy::sDefaultLibName2[] = "libgconf-2.so";
       
  1862 -
       
  1863 -#define GCONF_FUNCS_POINTER_BEGIN \
       
  1864 -    static GConfFuncListType sGConfFuncList[] = {
       
  1865 -#define GCONF_FUNCS_POINTER_ADD(func_name) \
       
  1866 -    {func_name, nsnull},
       
  1867 -#define GCONF_FUNCS_POINTER_END \
       
  1868 -    {nsnull, nsnull}, };
       
  1869 -
       
  1870 -GCONF_FUNCS_POINTER_BEGIN
       
  1871 -    GCONF_FUNCS_POINTER_ADD("gconf_client_get_default")        // 0
       
  1872 -    GCONF_FUNCS_POINTER_ADD("gconf_client_get_bool")       // 1
       
  1873 -    GCONF_FUNCS_POINTER_ADD("gconf_client_get_string")     //2
       
  1874 -    GCONF_FUNCS_POINTER_ADD("gconf_client_get_int")       //3
       
  1875 -    GCONF_FUNCS_POINTER_ADD("gconf_client_notify_add")   //4
       
  1876 -    GCONF_FUNCS_POINTER_ADD("gconf_client_notify_remove")   //5
       
  1877 -    GCONF_FUNCS_POINTER_ADD("gconf_client_add_dir")   //6
       
  1878 -    GCONF_FUNCS_POINTER_ADD("gconf_client_remove_dir")   //7
       
  1879 -    GCONF_FUNCS_POINTER_ADD("gconf_entry_get_value")       //8
       
  1880 -    GCONF_FUNCS_POINTER_ADD("gconf_entry_get_key")       //9
       
  1881 -    GCONF_FUNCS_POINTER_ADD("gconf_value_get_bool")      //10
       
  1882 -    GCONF_FUNCS_POINTER_ADD("gconf_value_get_string")     //11
       
  1883 -    GCONF_FUNCS_POINTER_ADD("gconf_value_get_int")       //12
       
  1884 -    GCONF_FUNCS_POINTER_ADD("gconf_client_get_list")       //13
       
  1885 -GCONF_FUNCS_POINTER_END
       
  1886 -
       
  1887 -/////////////////////////////////////////////////////////////////////////////
       
  1888 -// the list is the mapping table, between mozilla prefs and gconf prefs
       
  1889 -// It is expected to include all the pref pairs that are related in mozilla
       
  1890 -// and gconf. 
       
  1891 -//
       
  1892 -// Note: the prefs listed here are not neccessarily be read from gconf, they
       
  1893 -//       are the prefs that could be read from gconf. Mozilla has another
       
  1894 -//       list (see sSysPrefList in nsSystemPref.cpp) that decide which prefs
       
  1895 -//       are really read.
       
  1896 -//////////////////////////////////////////////////////////////////////////////
       
  1897 -
       
  1898 -static const PrefNamePair sPrefNameMapping[] = {
       
  1899 -#include "gconf_pref_list.inc"
       
  1900 -    {nsnull, nsnull},
       
  1901 -};
       
  1902 -
       
  1903 -PRBool
       
  1904 -gconfDeleteObserver(void *aElement, void *aData) {
       
  1905 -    nsMemory::Free(aElement);
       
  1906 -    return PR_TRUE;
       
  1907 -}
       
  1908 -
       
  1909 -GConfProxy::GConfProxy(nsSystemPrefService *aSysPrefService):
       
  1910 -    mGConfClient(nsnull),
       
  1911 -    mGConfLib(nsnull),
       
  1912 -    mInitialized(PR_FALSE),
       
  1913 -    mSysPrefService(aSysPrefService),
       
  1914 -    mObservers(nsnull)
       
  1915 -{
       
  1916 -}
       
  1917 -
       
  1918 -GConfProxy::~GConfProxy()
       
  1919 -{
       
  1920 -    if (mGConfClient)
       
  1921 -        g_object_unref(G_OBJECT(mGConfClient));
       
  1922 -
       
  1923 -    if (mObservers) {
       
  1924 -        (void)mObservers->EnumerateForwards(gconfDeleteObserver, nsnull);
       
  1925 -        delete mObservers;
       
  1926 -    }
       
  1927 -
       
  1928 -    // bug 379666: can't unload GConf-2 since it registers atexit handlers
       
  1929 -    //PR_UnloadLibrary(mGConfLib);
       
  1930 -}
       
  1931 -
       
  1932 -PRBool
       
  1933 -GConfProxy::Init()
       
  1934 -{
       
  1935 -    SYSPREF_LOG(("GConfProxy:: Init GConfProxy\n"));
       
  1936 -    if (!mSysPrefService)
       
  1937 -        return PR_FALSE;
       
  1938 -    if (mInitialized)
       
  1939 -        return PR_TRUE;
       
  1940 -
       
  1941 -    nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID); 
       
  1942 -
       
  1943 -    if (!pref)
       
  1944 -        return PR_FALSE;
       
  1945 -
       
  1946 -    nsXPIDLCString gconfLibName;
       
  1947 -    nsresult rv;
       
  1948 -
       
  1949 -    //check if gconf-2 library is given in prefs
       
  1950 -    rv = pref->GetCharPref(sPrefGConfKey, getter_Copies(gconfLibName));
       
  1951 -    if (NS_SUCCEEDED(rv)) {
       
  1952 -        //use the library name in the preference
       
  1953 -        SYSPREF_LOG(("GConf library in prefs is %s\n", gconfLibName.get()));
       
  1954 -        mGConfLib = PR_LoadLibrary(gconfLibName.get());
       
  1955 -    }
       
  1956 -    else {
       
  1957 -        SYSPREF_LOG(("GConf library not specified in prefs, try the default: "
       
  1958 -                     "%s and %s\n", sDefaultLibName1, sDefaultLibName2));
       
  1959 -        mGConfLib = PR_LoadLibrary(sDefaultLibName1);
       
  1960 -        if (!mGConfLib)
       
  1961 -            mGConfLib = PR_LoadLibrary(sDefaultLibName2);
       
  1962 -    }
       
  1963 -
       
  1964 -    if (!mGConfLib) {
       
  1965 -        SYSPREF_LOG(("Fail to load GConf library\n"));
       
  1966 -        return PR_FALSE;
       
  1967 -    }
       
  1968 -
       
  1969 -    //check every func we need in the gconf library
       
  1970 -    GConfFuncListType *funcList;
       
  1971 -    PRFuncPtr func;
       
  1972 -    for (funcList = sGConfFuncList; funcList->FuncName; ++funcList) {
       
  1973 -        func = PR_FindFunctionSymbol(mGConfLib, funcList->FuncName);
       
  1974 -        if (!func) {
       
  1975 -            SYSPREF_LOG(("Check GConf Func Error: %s", funcList->FuncName));
       
  1976 -            goto init_failed_unload;
       
  1977 -        }
       
  1978 -        funcList->FuncPtr = func;
       
  1979 -    }
       
  1980 -
       
  1981 -    InitFuncPtrs();
       
  1982 -
       
  1983 -    mGConfClient = GConfClientGetDefault();
       
  1984 -
       
  1985 -    // Don't unload past this point, since GConf's initialization of ORBit
       
  1986 -    // causes atexit handlers to be registered.
       
  1987 -
       
  1988 -    if (!mGConfClient) {
       
  1989 -        SYSPREF_LOG(("Fail to Get default gconf client\n"));
       
  1990 -        goto init_failed;
       
  1991 -    }
       
  1992 -    mInitialized = PR_TRUE;
       
  1993 -    return PR_TRUE;
       
  1994 -
       
  1995 - init_failed_unload:
       
  1996 -    PR_UnloadLibrary(mGConfLib);
       
  1997 - init_failed:
       
  1998 -    mGConfLib = nsnull;
       
  1999 -    return PR_FALSE;
       
  2000 -}
       
  2001 -
       
  2002 -nsresult
       
  2003 -GConfProxy::GetBoolPref(const char *aMozKey, PRBool *retval)
       
  2004 -{
       
  2005 -    NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
       
  2006 -    *retval = GConfClientGetBool(mGConfClient, MozKey2GConfKey(aMozKey), NULL);
       
  2007 -    return NS_OK;
       
  2008 -}
       
  2009 -
       
  2010 -nsresult
       
  2011 -GConfProxy::GetCharPref(const char *aMozKey, char **retval)
       
  2012 -{
       
  2013 -    NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
       
  2014 -
       
  2015 -    const gchar *gconfkey = MozKey2GConfKey(aMozKey);
       
  2016 -
       
  2017 -    if (!strcmp (aMozKey, "network.proxy.no_proxies_on")) {
       
  2018 -        GSList *s;
       
  2019 -        nsCString noproxy;
       
  2020 -        GSList *gslist = GConfClientGetList(mGConfClient, gconfkey,
       
  2021 -                                            GCONF_VALUE_STRING, NULL);
       
  2022 -
       
  2023 -        for (s = gslist; s; s = g_slist_next(s)) {
       
  2024 -            noproxy += (char *)s->data;
       
  2025 -            noproxy += ", ";
       
  2026 -            g_free ((char *)s->data);
       
  2027 -        }
       
  2028 -        g_slist_free (gslist);
       
  2029 -
       
  2030 -        *retval = PL_strdup(noproxy.get());
       
  2031 -    } else {
       
  2032 -        gchar *str = GConfClientGetString(mGConfClient, gconfkey, NULL);
       
  2033 -        if (str) {
       
  2034 -            *retval = PL_strdup(str);
       
  2035 -            g_free (str);
       
  2036 -        }
       
  2037 -    }
       
  2038 -
       
  2039 -    return NS_OK;
       
  2040 -}
       
  2041 -
       
  2042 -nsresult
       
  2043 -GConfProxy::GetIntPref(const char *aMozKey, PRInt32 *retval)
       
  2044 -{
       
  2045 -    NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
       
  2046 -    if (strcmp (aMozKey, "network.proxy.type") == 0) {
       
  2047 -	gchar *str;
       
  2048 -
       
  2049 -	str = GConfClientGetString(mGConfClient,
       
  2050 -	                           MozKey2GConfKey (aMozKey), NULL);
       
  2051 -
       
  2052 -	if (str) {
       
  2053 -		if (strcmp (str, "manual") == 0)
       
  2054 -			*retval = 1;
       
  2055 -		else if (strcmp (str, "auto") == 0)
       
  2056 -			*retval = 2;
       
  2057 -		else
       
  2058 -			*retval = 0;
       
  2059 -
       
  2060 -		g_free (str);
       
  2061 -	} else
       
  2062 -		*retval = 0;
       
  2063 -    } else {
       
  2064 -    	*retval = GConfClientGetInt(mGConfClient, 
       
  2065 -	                            MozKey2GConfKey(aMozKey), NULL);
       
  2066 -    }
       
  2067 -
       
  2068 -    return NS_OK;
       
  2069 -}
       
  2070 -
       
  2071 -nsresult
       
  2072 -GConfProxy::NotifyAdd (PRUint32 aAtom, void *aUserData)
       
  2073 -{
       
  2074 -    NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
       
  2075 -
       
  2076 -    const char *gconfKey = GetGConfKey(aAtom);
       
  2077 -    if (!gconfKey)
       
  2078 -        return NS_ERROR_FAILURE;
       
  2079 -
       
  2080 -    if (!mObservers) {
       
  2081 -        mObservers = new nsAutoVoidArray();
       
  2082 -        if (mObservers == nsnull)
       
  2083 -            return NS_ERROR_OUT_OF_MEMORY;
       
  2084 -    }
       
  2085 - 
       
  2086 -    GConfCallbackData *pData = (GConfCallbackData *)
       
  2087 -        nsMemory::Alloc(sizeof(GConfCallbackData));
       
  2088 -    NS_ENSURE_TRUE(pData, NS_ERROR_OUT_OF_MEMORY);
       
  2089 -
       
  2090 -    pData->proxy = this;
       
  2091 -    pData->userData = aUserData;
       
  2092 -    pData->atom = aAtom;
       
  2093 -    mObservers->AppendElement(pData);
       
  2094 -
       
  2095 -    GConfClientAddDir(mGConfClient, gconfKey,
       
  2096 -                      0, // GCONF_CLIENT_PRELOAD_NONE,  don't preload anything 
       
  2097 -                      NULL);
       
  2098 -
       
  2099 -    pData->notifyId = GConfClientNotifyAdd(mGConfClient, gconfKey,
       
  2100 -                                           gconf_key_listener, pData,
       
  2101 -                                           NULL, NULL);
       
  2102 -    return NS_OK;
       
  2103 -}
       
  2104 -
       
  2105 -nsresult
       
  2106 -GConfProxy::NotifyRemove (PRUint32 aAtom, const void *aUserData)
       
  2107 -{
       
  2108 -    NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
       
  2109 -
       
  2110 -    PRIntn count = mObservers->Count();
       
  2111 -    if (count <= 0)
       
  2112 -        return NS_OK;
       
  2113 -
       
  2114 -    PRIntn i;
       
  2115 -    GConfCallbackData *pData;
       
  2116 -    for (i = 0; i < count; ++i) {
       
  2117 -        pData = (GConfCallbackData *)mObservers->ElementAt(i);
       
  2118 -        if (pData && pData->atom == aAtom && pData->userData == aUserData) {
       
  2119 -            GConfClientNotifyRemove(mGConfClient, pData->notifyId);
       
  2120 -            GConfClientRemoveDir(mGConfClient,
       
  2121 -                                 GetGConfKey(pData->atom), NULL);
       
  2122 -            mObservers->RemoveElementAt(i);
       
  2123 -            nsMemory::Free(pData);
       
  2124 -            break;
       
  2125 -        }
       
  2126 -    }
       
  2127 -    return NS_OK;
       
  2128 -}
       
  2129 -
       
  2130 -void
       
  2131 -GConfProxy::InitFuncPtrs()
       
  2132 -{
       
  2133 -    //gconf client funcs
       
  2134 -    GConfClientGetDefault =
       
  2135 -        (GConfClientGetDefaultType) sGConfFuncList[0].FuncPtr;
       
  2136 -    GConfClientGetBool =
       
  2137 -        (GConfClientGetBoolType) sGConfFuncList[1].FuncPtr;
       
  2138 -    GConfClientGetString =
       
  2139 -        (GConfClientGetStringType) sGConfFuncList[2].FuncPtr;
       
  2140 -    GConfClientGetInt =
       
  2141 -        (GConfClientGetIntType) sGConfFuncList[3].FuncPtr;
       
  2142 -    GConfClientNotifyAdd =
       
  2143 -        (GConfClientNotifyAddType) sGConfFuncList[4].FuncPtr;
       
  2144 -    GConfClientNotifyRemove =
       
  2145 -        (GConfClientNotifyRemoveType) sGConfFuncList[5].FuncPtr;
       
  2146 -    GConfClientAddDir =
       
  2147 -        (GConfClientAddDirType) sGConfFuncList[6].FuncPtr;
       
  2148 -    GConfClientRemoveDir =
       
  2149 -        (GConfClientRemoveDirType) sGConfFuncList[7].FuncPtr;
       
  2150 -
       
  2151 -    //gconf entry funcs
       
  2152 -    GConfEntryGetValue = (GConfEntryGetValueType) sGConfFuncList[8].FuncPtr;
       
  2153 -    GConfEntryGetKey = (GConfEntryGetKeyType) sGConfFuncList[9].FuncPtr;
       
  2154 -
       
  2155 -    //gconf value funcs
       
  2156 -    GConfValueGetBool = (GConfValueGetBoolType) sGConfFuncList[10].FuncPtr;
       
  2157 -    GConfValueGetString = (GConfValueGetStringType) sGConfFuncList[11].FuncPtr;
       
  2158 -    GConfValueGetInt = (GConfValueGetIntType) sGConfFuncList[12].FuncPtr;
       
  2159 -
       
  2160 -    //gconf client list func
       
  2161 -    GConfClientGetList =
       
  2162 -        (GConfClientGetListType) sGConfFuncList[13].FuncPtr;
       
  2163 -}
       
  2164 -
       
  2165 -void
       
  2166 -GConfProxy::OnNotify(void *aClient, void * aEntry, PRUint32 aNotifyId,
       
  2167 -                     GConfCallbackData *aData)
       
  2168 -{
       
  2169 -    if (!mInitialized || !aEntry || (mGConfClient != aClient) || !aData)
       
  2170 -        return;
       
  2171 -
       
  2172 -    if (GConfEntryGetValue(aEntry) == NULL)
       
  2173 -        return;
       
  2174 -
       
  2175 -    PRUint32 prefAtom;
       
  2176 -    nsresult rv = GetAtomForGConfKey(GConfEntryGetKey(aEntry), &prefAtom);
       
  2177 -    if (NS_FAILED(rv))
       
  2178 -        return;
       
  2179 -
       
  2180 -    mSysPrefService->OnPrefChange(prefAtom, aData->userData);
       
  2181 -}
       
  2182 -
       
  2183 -nsresult
       
  2184 -GConfProxy::GetAtom(const char *aKey, PRUint8 aNameType, PRUint32 *aAtom)
       
  2185 -{
       
  2186 -    if (!aKey)
       
  2187 -        return NS_ERROR_FAILURE;
       
  2188 -    PRUint32 prefSize = sizeof(sPrefNameMapping) / sizeof(sPrefNameMapping[0]);
       
  2189 -    for (PRUint32 index = 0; index < prefSize; ++index) {
       
  2190 -        if (!strcmp((aNameType == 0) ? sPrefNameMapping[index].mozPrefName :
       
  2191 -                    sPrefNameMapping[index].gconfPrefName, aKey)) {
       
  2192 -            *aAtom = index;
       
  2193 -            return NS_OK;
       
  2194 -        }
       
  2195 -    }
       
  2196 -    return NS_ERROR_FAILURE;
       
  2197 -}
       
  2198 -
       
  2199 -const char *
       
  2200 -GConfProxy::GetKey(PRUint32 aAtom, PRUint8 aNameType)
       
  2201 -{
       
  2202 -    PRUint32 mapSize = sizeof(sPrefNameMapping) / sizeof(sPrefNameMapping[0]);
       
  2203 -    if (aAtom >= 0 && aAtom < mapSize)
       
  2204 -        return (aNameType == 0) ? sPrefNameMapping[aAtom].mozPrefName :
       
  2205 -            sPrefNameMapping[aAtom].gconfPrefName;
       
  2206 -    return NULL;
       
  2207 -}
       
  2208 -
       
  2209 -inline const char *
       
  2210 -GConfProxy::MozKey2GConfKey(const char *aMozKey)
       
  2211 -{
       
  2212 -    PRUint32 atom;
       
  2213 -    nsresult rv = GetAtomForMozKey(aMozKey, &atom);
       
  2214 -    if (NS_SUCCEEDED(rv))
       
  2215 -        return GetGConfKey(atom);
       
  2216 -    return NULL;
       
  2217 -}
       
  2218 -
       
  2219 -/* static */
       
  2220 -void gconf_key_listener (void* client, guint cnxn_id,
       
  2221 -                         void *entry, gpointer user_data)
       
  2222 -{
       
  2223 -    SYSPREF_LOG(("...SYSPREF_LOG...key listener get called \n"));
       
  2224 -    if (!user_data)
       
  2225 -        return;
       
  2226 -    GConfCallbackData *pData = reinterpret_cast<GConfCallbackData *>
       
  2227 -                                               (user_data);
       
  2228 -    pData->proxy->OnNotify(client, entry, cnxn_id, pData);
       
  2229 -}
       
  2230 diff --git a/extensions/pref/system-pref/src/nsISystemPrefService.h b/extensions/pref/system-pref/src/nsISystemPrefService.h
       
  2231 new file mode 100644
       
  2232 --- /dev/null
       
  2233 +++ b/extensions/pref/system-pref/src/nsISystemPrefService.h
       
  2234 @@ -0,0 +1,107 @@
       
  2235 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       
  2236 +/* vim:expandtab:shiftwidth=4:tabstop=4:
       
  2237 + */
       
  2238 +/* ***** BEGIN LICENSE BLOCK *****
       
  2239 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       
  2240 + *
       
  2241 + *
       
  2242 + * The contents of this file are subject to the Mozilla Public
       
  2243 + * License Version 1.1 (the "License"); you may not use this file
       
  2244 + * except in compliance with the License. You may obtain a copy of
       
  2245 + * the License at http://www.mozilla.org/MPL/
       
  2246 + *
       
  2247 + * Software distributed under the License is distributed on an "AS
       
  2248 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
       
  2249 + * implied. See the License for the specific language governing
       
  2250 + * rights and limitations under the License.
       
  2251 + *
       
  2252 + * The Original Code is mozilla.org code.
       
  2253 + *
       
  2254 + * The Initial Developer of the Original Code is Novell
       
  2255 + * Portions created by Novell are Copyright (C) 2005 Novell,
       
  2256 + * All Rights Reserved.
       
  2257 + *
       
  2258 + * Original Author: Robert O'Callahan (rocallahan@novell.com)
       
  2259 + *
       
  2260 + * Contributor(s):
       
  2261 + *
       
  2262 + * Alternatively, the contents of this file may be used under the terms of
       
  2263 + * either the GNU General Public License Version 2 or later (the "GPL"), or
       
  2264 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
       
  2265 + * in which case the provisions of the GPL or the LGPL are applicable instead
       
  2266 + * of those above. If you wish to allow use of your version of this file only
       
  2267 + * under the terms of either the GPL or the LGPL, and not to allow others to
       
  2268 + * use your version of this file under the terms of the NPL, indicate your
       
  2269 + * decision by deleting the provisions above and replace them with the notice
       
  2270 + * and other provisions required by the GPL or the LGPL. If you do not delete
       
  2271 + * the provisions above, a recipient may use your version of this file under
       
  2272 + * the terms of any one of the NPL, the GPL or the LGPL.
       
  2273 + *
       
  2274 + * ***** END LICENSE BLOCK ***** */
       
  2275 +
       
  2276 +#ifndef nsISystemPrefService_h__
       
  2277 +#define nsISystemPrefService_h__
       
  2278 +
       
  2279 +#include "nsCOMPtr.h"
       
  2280 +#include "nsIPrefBranchInternal.h"
       
  2281 +
       
  2282 +#define NS_SYSTEMPREF_SERVICE_CONTRACTID "@mozilla.org/system-preference-service;1"
       
  2283 +
       
  2284 +#define NS_ISYSTEMPREFSERVICE_IID   \
       
  2285 +{ 0x006e1cfd, 0xd66a, 0x40b9, \
       
  2286 +    { 0x84, 0xa1, 0x84, 0xf3, 0xe6, 0xa2, 0xca, 0xbc } }
       
  2287 +
       
  2288 +class nsISystemPref {
       
  2289 +public:
       
  2290 +    /**
       
  2291 +     * Call one of these three methods to override a Mozilla
       
  2292 +     * preference with a system value. You can call it multiple
       
  2293 +     * times to change the value of a given preference to track
       
  2294 +     * the underlying system value.
       
  2295 +     *
       
  2296 +     * If aLocked is true then we set the default preference and
       
  2297 +     * lock it so the user value is ignored. If aLocked is false
       
  2298 +     * then we unlock the Mozilla preference and set the Mozilla
       
  2299 +     * user value.
       
  2300 +     */
       
  2301 +    virtual nsresult SetOverridingMozillaBoolPref(const char* aPrefName,
       
  2302 +                                                  PRBool aValue, PRBool aLocked,
       
  2303 +                                                  PRBool aPresent = PR_TRUE) = 0;
       
  2304 +    virtual nsresult SetOverridingMozillaIntPref(const char* aPrefName,
       
  2305 +                                                 PRInt32 aValue, PRBool aLocked,
       
  2306 +                                                 PRBool aPresent = PR_TRUE) = 0;
       
  2307 +    virtual nsresult SetOverridingMozillaStringPref(const char* aPrefName,
       
  2308 +                                                    const char* aValue, PRBool aLocked,
       
  2309 +                                                    PRBool aPresent = PR_TRUE) = 0;
       
  2310 +    virtual nsresult StopOverridingMozillaPref(const char* aPrefName) = 0;
       
  2311 +    virtual already_AddRefed<nsIPrefBranch2> GetPrefUserBranch() = 0;
       
  2312 +    virtual already_AddRefed<nsIPrefBranch> GetPrefDefaultBranch() = 0;
       
  2313 +};
       
  2314 +
       
  2315 +class nsISystemPrefService : public nsISupports {
       
  2316 +public:
       
  2317 +    NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISYSTEMPREFSERVICE_IID)
       
  2318 +
       
  2319 +    /**
       
  2320 +     * Load the system prefs from the store into their corresponding
       
  2321 +     * Mozilla prefs, calling SetOverridingMozillaPref on each
       
  2322 +     * such pref.
       
  2323 +     */
       
  2324 +    virtual nsresult LoadSystemPreferences(nsISystemPref* aPrefs) = 0;
       
  2325 +
       
  2326 +    /**
       
  2327 +     * Notify that a Mozilla user pref that is being overridden by the
       
  2328 +     * store has changed.  The new value of the Mozilla pref should be
       
  2329 +     * written back to the store.
       
  2330 +     */
       
  2331 +    virtual nsresult NotifyMozillaPrefChanged(const char* aPrefName) = 0;
       
  2332 +
       
  2333 +    /**
       
  2334 +     * Notify that we're about to stop using the system prefs.  After
       
  2335 +     * this, nsSystemPref will automatically stop overriding all
       
  2336 +     * Mozilla prefs that are being overridden.
       
  2337 +     */
       
  2338 +    virtual nsresult NotifyUnloadSystemPreferences() = 0;
       
  2339 +};
       
  2340 +
       
  2341 +#endif
       
  2342 diff --git a/extensions/pref/system-pref/src/nsSystemPref.cpp b/extensions/pref/system-pref/src/nsSystemPref.cpp
       
  2343 --- a/extensions/pref/system-pref/src/nsSystemPref.cpp
       
  2344 +++ b/extensions/pref/system-pref/src/nsSystemPref.cpp
       
  2345 @@ -19,16 +19,17 @@
       
  2346   *
       
  2347   * The Initial Developer of the Original Code is Sun Microsystems, Inc.
       
  2348   * Portions created by Sun Microsystems are Copyright (C) 2003 Sun
       
  2349   * Microsystems, Inc. All Rights Reserved.
       
  2350   *
       
  2351   * Original Author: Bolian Yin (bolian.yin@sun.com)
       
  2352   *
       
  2353   * Contributor(s):
       
  2354 + *   Robert O'Callahan (rocallahan@novell.com)
       
  2355   *
       
  2356   * Alternatively, the contents of this file may be used under the terms of
       
  2357   * either the GNU General Public License Version 2 or later (the "GPL"), or
       
  2358   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
       
  2359   * in which case the provisions of the GPL or the LGPL are applicable instead
       
  2360   * of those above. If you wish to allow use of your version of this file only
       
  2361   * under the terms of either the GPL or the LGPL, and not to allow others to
       
  2362   * use your version of this file under the terms of the NPL, indicate your
       
  2363 @@ -36,76 +37,72 @@
       
  2364   * and other provisions required by the GPL or the LGPL. If you do not delete
       
  2365   * the provisions above, a recipient may use your version of this file under
       
  2366   * the terms of any one of the NPL, the GPL or the LGPL.
       
  2367   *
       
  2368   * ***** END LICENSE BLOCK ***** */
       
  2369  
       
  2370  #include "nsSystemPref.h"
       
  2371  #include "nsIObserverService.h"
       
  2372 +#include "nsIAppStartupNotifier.h"
       
  2373 +#include "nsIPrefService.h"
       
  2374 +#include "nsIPrefBranch.h"
       
  2375 +#include "nsICategoryManager.h"
       
  2376 +#include "nsIServiceManager.h"
       
  2377  
       
  2378  #include "nsSystemPrefLog.h"
       
  2379 -#include "nsSystemPrefService.h"
       
  2380  #include "nsString.h"
       
  2381  
       
  2382 -const char sSysPrefString[] = "config.use_system_prefs";
       
  2383 -union MozPrefValue {
       
  2384 -    char *      stringVal;
       
  2385 -    PRInt32     intVal;
       
  2386 -    PRBool      boolVal;
       
  2387 -};
       
  2388 +#include <stdlib.h>
       
  2389  
       
  2390  struct SysPrefItem {
       
  2391 -    const char *prefName;       // mozilla pref string name
       
  2392 -    MozPrefValue defaultValue;  // store the mozilla default value
       
  2393 -    PRBool isLocked;  // store the mozilla lock status
       
  2394 +    // Saved values on both branches
       
  2395 +    PRInt32      savedUserValueScalar;
       
  2396 +    char*        savedUserValueString;
       
  2397 +    PRInt32      savedDefaultValueScalar;
       
  2398 +    char*        savedDefaultValueString;
       
  2399 +    // When this is true, then the value was locked originally
       
  2400 +    PRPackedBool savedLocked;
       
  2401 +    // When this is true, then there was a user value
       
  2402 +    PRPackedBool savedUserPresent;
       
  2403 +    PRPackedBool ignore;
       
  2404 +    
       
  2405      SysPrefItem() {
       
  2406 -        prefName = nsnull;
       
  2407 -        defaultValue.intVal = 0;
       
  2408 -        defaultValue.stringVal = nsnull;
       
  2409 -        defaultValue.boolVal = PR_FALSE;
       
  2410 -        isLocked = PR_FALSE;
       
  2411 +        savedUserValueScalar = 0;
       
  2412 +        savedUserValueString = nsnull;
       
  2413 +        savedDefaultValueScalar = 0;
       
  2414 +        savedDefaultValueString = nsnull;
       
  2415 +        savedUserPresent = PR_FALSE;
       
  2416 +        savedLocked = PR_FALSE;
       
  2417 +        ignore = PR_FALSE;
       
  2418      }
       
  2419 -    void SetPrefName(const char *aPrefName) {
       
  2420 -        prefName = aPrefName;
       
  2421 +
       
  2422 +    virtual ~SysPrefItem() {
       
  2423 +        nsMemory::Free(savedUserValueString);
       
  2424 +        nsMemory::Free(savedDefaultValueString);
       
  2425      }
       
  2426  };
       
  2427  
       
  2428 -// all prefs that mozilla need to read from host system if they are available
       
  2429 -static const char *sSysPrefList[] = {
       
  2430 -    "network.proxy.http",
       
  2431 -    "network.proxy.http_port",
       
  2432 -    "network.proxy.ftp",
       
  2433 -    "network.proxy.ftp_port",
       
  2434 -    "network.proxy.ssl",
       
  2435 -    "network.proxy.ssl_port",
       
  2436 -    "network.proxy.socks",
       
  2437 -    "network.proxy.socks_port",
       
  2438 -    "network.proxy.no_proxies_on",
       
  2439 -    "network.proxy.autoconfig_url",
       
  2440 -    "network.proxy.type",
       
  2441 -    "config.use_system_prefs.accessibility",
       
  2442 -};
       
  2443 +NS_DEFINE_STATIC_IID_ACCESSOR(nsISystemPrefService, NS_ISYSTEMPREFSERVICE_IID)
       
  2444 +
       
  2445 +static const char sSysPrefString[] = "config.use_system_prefs";
       
  2446  
       
  2447  PRLogModuleInfo *gSysPrefLog = NULL;
       
  2448  
       
  2449  NS_IMPL_ISUPPORTS2(nsSystemPref, nsIObserver, nsISupportsWeakReference)
       
  2450  
       
  2451 -nsSystemPref::nsSystemPref():
       
  2452 -    mSysPrefService(nsnull),
       
  2453 -    mEnabled(PR_FALSE),
       
  2454 -    mSysPrefs(nsnull)
       
  2455 +nsSystemPref::nsSystemPref() : mIgnorePrefSetting(PR_FALSE)
       
  2456  {
       
  2457 +   mSavedPrefs.Init();
       
  2458 +   mCachedUserPrefBranch = nsnull;
       
  2459 +   mCachedDefaultPrefBranch = nsnull;
       
  2460  }
       
  2461  
       
  2462  nsSystemPref::~nsSystemPref()
       
  2463  {
       
  2464 -    mSysPrefService = nsnull;
       
  2465 -    mEnabled = PR_FALSE;
       
  2466 -    delete [] mSysPrefs;
       
  2467  }
       
  2468  
       
  2469  ///////////////////////////////////////////////////////////////////////////////
       
  2470  // nsSystemPref::Init
       
  2471  // Setup log and listen on NS_PREFSERVICE_READ_TOPIC_ID from pref service
       
  2472  ///////////////////////////////////////////////////////////////////////////////
       
  2473  nsresult
       
  2474  nsSystemPref::Init(void)
       
  2475 @@ -126,349 +123,519 @@ nsSystemPref::Init(void)
       
  2476                                            PR_FALSE);
       
  2477          rv = observerService->AddObserver(this, "profile-before-change",
       
  2478                                            PR_FALSE);
       
  2479          SYSPREF_LOG(("Add Observer for %s\n", NS_PREFSERVICE_READ_TOPIC_ID));
       
  2480      }
       
  2481      return(rv);
       
  2482  }
       
  2483  
       
  2484 +already_AddRefed<nsIPrefBranch2>
       
  2485 +nsSystemPref::GetPrefUserBranch()
       
  2486 +{
       
  2487 +    if (mCachedUserPrefBranch) {
       
  2488 +        NS_ADDREF(mCachedUserPrefBranch);
       
  2489 +        return mCachedUserPrefBranch;
       
  2490 +    }
       
  2491 +
       
  2492 +    nsresult rv;
       
  2493 +    nsCOMPtr<nsIPrefService> prefService = 
       
  2494 +        do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
       
  2495 +    if (NS_FAILED(rv))
       
  2496 +        return nsnull;
       
  2497 +    nsCOMPtr<nsIPrefBranch> prefBranch;
       
  2498 +    rv = prefService->GetBranch(nsnull, getter_AddRefs(prefBranch));
       
  2499 +    if (NS_FAILED(rv))
       
  2500 +        return nsnull;
       
  2501 +    nsCOMPtr<nsIPrefBranch2> pb2(do_QueryInterface(prefBranch));
       
  2502 +    if (!pb2)
       
  2503 +        return nsnull;
       
  2504 +    
       
  2505 +    nsIPrefBranch2* result = nsnull;
       
  2506 +    pb2.swap(result);
       
  2507 +    return result;
       
  2508 +}
       
  2509 +
       
  2510 +already_AddRefed<nsIPrefBranch>
       
  2511 +nsSystemPref::GetPrefDefaultBranch()
       
  2512 +{
       
  2513 +    if (mCachedDefaultPrefBranch) {
       
  2514 +        NS_ADDREF(mCachedDefaultPrefBranch);
       
  2515 +        return mCachedDefaultPrefBranch;
       
  2516 +    }
       
  2517 +
       
  2518 +    nsresult rv;
       
  2519 +    nsCOMPtr<nsIPrefService> prefService = 
       
  2520 +        do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
       
  2521 +    if (NS_FAILED(rv))
       
  2522 +        return nsnull;
       
  2523 +    nsCOMPtr<nsIPrefBranch> prefBranch;
       
  2524 +    rv = prefService->GetDefaultBranch(nsnull, getter_AddRefs(prefBranch));
       
  2525 +    if (NS_FAILED(rv))
       
  2526 +        return nsnull;
       
  2527 +    nsIPrefBranch* pb = nsnull;
       
  2528 +    prefBranch.swap(pb);
       
  2529 +    return pb;
       
  2530 +}
       
  2531 +
       
  2532  ///////////////////////////////////////////////////////////////////////////////
       
  2533  // nsSystemPref::Observe
       
  2534  // Observe notifications from mozilla pref system and system prefs (if enabled)
       
  2535  ///////////////////////////////////////////////////////////////////////////////
       
  2536  NS_IMETHODIMP
       
  2537  nsSystemPref::Observe(nsISupports *aSubject,
       
  2538                        const char *aTopic,
       
  2539                        const PRUnichar *aData)
       
  2540  {
       
  2541      nsresult rv = NS_OK;
       
  2542  
       
  2543      if (!aTopic)
       
  2544          return NS_OK;
       
  2545  
       
  2546 -    // if we are notified by pref service
       
  2547 -    // check the system pref settings
       
  2548 +    nsCOMPtr<nsIPrefBranch2> userBranch = GetPrefUserBranch();
       
  2549 +    nsCOMPtr<nsIPrefBranch> defaultBranch = GetPrefDefaultBranch();
       
  2550 + 
       
  2551 +    // Check the default branch first. If system prefs are enabled
       
  2552 +    // by default, then don't check the user prefs; we don't want
       
  2553 +    // to allow users to change the default.
       
  2554 +    PRBool defaultEnabled;
       
  2555 +    rv = defaultBranch->GetBoolPref(sSysPrefString, &defaultEnabled);
       
  2556 +    if (NS_FAILED(rv)) {
       
  2557 +        SYSPREF_LOG(("...Failed to Get %s\n", sSysPrefString));
       
  2558 +        return rv;
       
  2559 +    }
       
  2560 +    PRBool enabled = defaultEnabled;
       
  2561 +    if (!enabled) {
       
  2562 +        rv = userBranch->GetBoolPref(sSysPrefString, &enabled);
       
  2563 +
       
  2564 +        if (NS_FAILED(rv)) {
       
  2565 +            SYSPREF_LOG(("...Failed to Get %s\n", sSysPrefString));
       
  2566 +            return rv;
       
  2567 +        }
       
  2568 +    }
       
  2569      if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
       
  2570 +        // The prefs have just loaded. This is the first thing that
       
  2571 +        // happens to us.
       
  2572          SYSPREF_LOG(("Observed: %s\n", aTopic));
       
  2573 + 
       
  2574  
       
  2575 -        nsCOMPtr<nsIPrefBranch2> prefBranch =
       
  2576 -            do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
       
  2577 +        // listen on changes to use_system_pref. It's OK to
       
  2578 +        // hold a strong reference because we don't keep a reference
       
  2579 +        // to the pref branch.
       
  2580 +        rv = userBranch->AddObserver(sSysPrefString, this, PR_TRUE);
       
  2581 +
       
  2582 +        if (NS_FAILED(rv)) {
       
  2583 +            SYSPREF_LOG(("...Failed to add observer for %s\n", sSysPrefString));
       
  2584 +            return rv;
       
  2585 +        }
       
  2586 +        NS_ASSERTION(!mSysPrefService, "Should not be already enabled");
       
  2587 +        if (!enabled) {
       
  2588 +            // Don't load the system pref service if the preference is
       
  2589 +            // not set.
       
  2590 +            return NS_OK;
       
  2591 +        }
       
  2592 +
       
  2593 +        SYSPREF_LOG(("%s is enabled\n", sSysPrefString));
       
  2594 +
       
  2595 +	rv = LoadSystemPrefs();
       
  2596          if (NS_FAILED(rv))
       
  2597              return rv;
       
  2598  
       
  2599 -        rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
       
  2600 -        if (NS_FAILED(rv)) {
       
  2601 -            SYSPREF_LOG(("...FAil to Get %s\n", sSysPrefString));
       
  2602 -            return rv;
       
  2603 -        }
       
  2604 -
       
  2605 -        // if there is no system pref service, assume nothing happen to us
       
  2606 -        mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
       
  2607 -        if (NS_FAILED(rv) || !mSysPrefService) {
       
  2608 -            SYSPREF_LOG(("...No System Pref Service\n"));
       
  2609 -            return NS_OK;
       
  2610 -        }
       
  2611 -
       
  2612 -        // listen on its changes
       
  2613 -        rv = prefBranch->AddObserver(sSysPrefString, this, PR_TRUE);
       
  2614 -        if (NS_FAILED(rv)) {
       
  2615 -            SYSPREF_LOG(("...FAil to add observer for %s\n", sSysPrefString));
       
  2616 -            return rv;
       
  2617 -        }
       
  2618 -
       
  2619 -        if (!mEnabled) {
       
  2620 -            SYSPREF_LOG(("%s is disabled\n", sSysPrefString));
       
  2621 -            return NS_OK;
       
  2622 -        }
       
  2623 -        SYSPREF_LOG(("%s is enabled\n", sSysPrefString));
       
  2624 -        rv = UseSystemPrefs();
       
  2625 -
       
  2626 -    }
       
  2627 -    // sSysPrefString value was changed, update ...
       
  2628 -    else if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
       
  2629 -             NS_ConvertUTF8toUTF16(sSysPrefString).Equals(aData)) {
       
  2630 -        SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
       
  2631 -                     aTopic, NS_ConvertUTF16toUTF8(aData).get()));
       
  2632 -
       
  2633 -        nsCOMPtr<nsIPrefBranch> prefBranch =
       
  2634 -            do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
       
  2635 -        if (NS_FAILED(rv))
       
  2636 -            return rv;
       
  2637 -
       
  2638 -        PRBool enabled = mEnabled;
       
  2639 -        rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
       
  2640 -        if (enabled != mEnabled) {
       
  2641 -            if (mEnabled)
       
  2642 -                //read prefs from system
       
  2643 -                rv = UseSystemPrefs();
       
  2644 -            else
       
  2645 -                //roll back to mozilla prefs
       
  2646 -                rv = UseMozillaPrefs();
       
  2647 +        // Lock config.use_system_prefs so the user can't undo
       
  2648 +        // it. But only do this if it was set by in the default prefs;
       
  2649 +        // if it was not set by default, then locking it would actually
       
  2650 +        // unset the value! And the user should be allowed to turn off
       
  2651 +        // something they set themselves.
       
  2652 +        if (NS_SUCCEEDED(rv) && defaultEnabled) {
       
  2653 +            userBranch->LockPref(sSysPrefString);
       
  2654          }
       
  2655      }
       
  2656  
       
  2657 -    // if the system pref notify us that some pref has been changed by user
       
  2658 -    // outside mozilla. We need to read it again.
       
  2659 -    else if (!nsCRT::strcmp(aTopic, NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID) &&
       
  2660 -             aData) {
       
  2661 -        NS_ASSERTION(mEnabled == PR_TRUE, "Should not listen when disabled");
       
  2662 -        SYSPREF_LOG(("====== System Pref Notify topic=%s data=%s\n",
       
  2663 -                     aTopic, (char*)aData));
       
  2664 -        rv = ReadSystemPref(NS_LossyConvertUTF16toASCII(aData).get());
       
  2665 +    if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
       
  2666 +        nsDependentString(aData).EqualsASCII(sSysPrefString)) {
       
  2667 +        // sSysPrefString value was changed, update...
       
  2668 +        SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
       
  2669 +                     aTopic, NS_ConvertUTF16toUTF8(aData).get()));
       
  2670 +        if (mSysPrefService && !enabled)
       
  2671 +            return RestoreMozillaPrefs();
       
  2672 +        if (!mSysPrefService && enabled) {
       
  2673 +            // Don't lock it. If the user enabled use_system_prefs,
       
  2674 +            // they should be allowed to unlock it.
       
  2675 +            return LoadSystemPrefs();
       
  2676 +        }
       
  2677 + 
       
  2678 +        // didn't change?
       
  2679          return NS_OK;
       
  2680 -    } else if (!nsCRT::strcmp(aTopic,"profile-before-change")) {
       
  2681 -      //roll back to mozilla prefs
       
  2682 -      if (mEnabled)
       
  2683 -        UseMozillaPrefs();
       
  2684 -      mEnabled = PR_FALSE;
       
  2685 -      mSysPrefService = nsnull;
       
  2686 -      delete [] mSysPrefs;
       
  2687 -      mSysPrefs = nsnull;
       
  2688 -    } else
       
  2689 -        SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
       
  2690 +    }
       
  2691 +
       
  2692 +    if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
       
  2693 +        // some other pref changed, tell the backend if there is one
       
  2694 +        if (mSysPrefService && !mIgnorePrefSetting) {
       
  2695 +            NS_LossyConvertUTF16toASCII tmp(aData);
       
  2696 +#ifdef DEBUG
       
  2697 +            PRBool isLocked;
       
  2698 +            userBranch->PrefIsLocked(tmp.get(), &isLocked);
       
  2699 +            NS_ASSERTION(!isLocked, "Locked pref is changing?");
       
  2700 +#endif
       
  2701 +            SysPrefItem* item;
       
  2702 +            if (!mSavedPrefs.Get(tmp, &item)) {
       
  2703 +                NS_ERROR("Notified about pref change that we didn't ask about?");
       
  2704 +            } else {
       
  2705 +                if (!item->ignore) {
       
  2706 +                    mSysPrefService->NotifyMozillaPrefChanged(tmp.get());
       
  2707 +                }
       
  2708 +            }
       
  2709 +        }
       
  2710 +        return NS_OK;
       
  2711 +    }
       
  2712 +
       
  2713 +    if (!nsCRT::strcmp(aTopic,"profile-before-change"))
       
  2714 +        return RestoreMozillaPrefs();
       
  2715 +
       
  2716 +    SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
       
  2717 +
       
  2718      return rv;
       
  2719  }
       
  2720  
       
  2721 -/* private */
       
  2722 +nsresult
       
  2723 +nsSystemPref::SetOverridingMozillaBoolPref(const char* aPrefName,
       
  2724 +                                           PRBool aValue, PRBool aLock, PRBool aPresent)
       
  2725 +{
       
  2726 +    return OverridePref(aPrefName, nsIPrefBranch::PREF_BOOL,
       
  2727 +                        (void*)aValue, aLock, aPresent);
       
  2728 +}
       
  2729  
       
  2730 -////////////////////////////////////////////////////////////////
       
  2731 -// nsSystemPref::UseSystemPrefs
       
  2732 -// Read all the prefs in the table from system, listen for their
       
  2733 -// changes in system pref service.
       
  2734 -////////////////////////////////////////////////////////////////
       
  2735  nsresult
       
  2736 -nsSystemPref::UseSystemPrefs()
       
  2737 +nsSystemPref::SetOverridingMozillaIntPref(const char* aPrefName,
       
  2738 +                                          PRInt32 aValue, PRBool aLock, PRBool aPresent)
       
  2739  {
       
  2740 -    SYSPREF_LOG(("\n====Now Use system prefs==\n"));
       
  2741 -    nsresult rv = NS_OK;
       
  2742 -    if (!mSysPrefService) {
       
  2743 +    return OverridePref(aPrefName, nsIPrefBranch::PREF_INT,
       
  2744 +                        (void*)aValue, aLock, aPresent);
       
  2745 +}
       
  2746 +
       
  2747 +
       
  2748 +nsresult
       
  2749 +nsSystemPref::SetOverridingMozillaStringPref(const char* aPrefName,
       
  2750 +                                             const char* aValue, PRBool aLock, PRBool aPresent)
       
  2751 +{
       
  2752 +    return OverridePref(aPrefName, nsIPrefBranch::PREF_STRING,
       
  2753 +                        (void*)aValue, aLock, aPresent);
       
  2754 +}
       
  2755 +
       
  2756 +static nsresult RestorePrefValue(PRInt32 aPrefType,
       
  2757 +                                 const char* aPrefName,
       
  2758 +                                 SysPrefItem* aItem,
       
  2759 +                                 nsIPrefBranch* aUser,
       
  2760 +                                 nsIPrefBranch* aDefault)
       
  2761 +{
       
  2762 +    switch (aPrefType) {
       
  2763 +
       
  2764 +    case nsIPrefBranch::PREF_STRING:
       
  2765 +        aDefault->SetCharPref(aPrefName,
       
  2766 +                              aItem->savedDefaultValueString);
       
  2767 +        if (aItem->savedUserPresent) {
       
  2768 +            aUser->SetCharPref(aPrefName, aItem->savedUserValueString);
       
  2769 +        }
       
  2770 +        break;
       
  2771 +    case nsIPrefBranch::PREF_INT:
       
  2772 +        aDefault->SetBoolPref(aPrefName, aItem->savedDefaultValueScalar);
       
  2773 +        if (aItem->savedUserPresent) {
       
  2774 +            aUser->SetBoolPref(aPrefName, aItem->savedUserValueScalar);
       
  2775 +        }
       
  2776 +        break;
       
  2777 +    case nsIPrefBranch::PREF_BOOL:
       
  2778 +        aDefault->SetBoolPref(aPrefName, aItem->savedDefaultValueScalar);
       
  2779 +        if (aItem->savedUserPresent) {
       
  2780 +            aUser->SetBoolPref(aPrefName, aItem->savedUserValueScalar);
       
  2781 +        }
       
  2782 +        break;
       
  2783 +    default:
       
  2784 +        NS_ERROR("Unknown preference type");
       
  2785          return NS_ERROR_FAILURE;
       
  2786      }
       
  2787  
       
  2788 -    PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
       
  2789 -
       
  2790 -    if (!mSysPrefs) {
       
  2791 -        mSysPrefs = new SysPrefItem[sysPrefCount];
       
  2792 -        if (!mSysPrefs)
       
  2793 -            return NS_ERROR_OUT_OF_MEMORY;
       
  2794 -        for (PRIntn index = 0; index < sysPrefCount; ++index)
       
  2795 -            mSysPrefs[index].SetPrefName(sSysPrefList[index]);
       
  2796 +    if (!aItem->savedUserPresent) {
       
  2797 +        aUser->DeleteBranch(aPrefName);
       
  2798      }
       
  2799  
       
  2800 -    for (PRIntn index = 0; index < sysPrefCount; ++index) {
       
  2801 -        // save mozilla prefs
       
  2802 -        SaveMozDefaultPref(mSysPrefs[index].prefName,
       
  2803 -                           &mSysPrefs[index].defaultValue,
       
  2804 -                           &mSysPrefs[index].isLocked);
       
  2805 +    return NS_OK;
       
  2806 +}
       
  2807  
       
  2808 -        // get the system prefs
       
  2809 -        ReadSystemPref(mSysPrefs[index].prefName);
       
  2810 -        SYSPREF_LOG(("Add Listener on %s\n", mSysPrefs[index].prefName));
       
  2811 -        mSysPrefService->AddObserver(mSysPrefs[index].prefName,
       
  2812 -                                     this, PR_TRUE);
       
  2813 +static PLDHashOperator PR_CALLBACK RestorePref(const nsACString& aKey,
       
  2814 +                                               SysPrefItem* aItem,
       
  2815 +                                               void* aClosure)
       
  2816 +{
       
  2817 +    nsSystemPref* prefs = static_cast<nsSystemPref*>(aClosure);
       
  2818 +    nsCOMPtr<nsIPrefBranch2> userBranch = prefs->GetPrefUserBranch();
       
  2819 +    const nsCString& prefName = PromiseFlatCString(aKey);
       
  2820 +    
       
  2821 +    PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
       
  2822 +    nsresult rv = userBranch->GetPrefType(prefName.get(), &prefType);
       
  2823 +    if (NS_FAILED(rv))
       
  2824 +        return PL_DHASH_NEXT;
       
  2825 +    PRBool isLocked;
       
  2826 +    userBranch->PrefIsLocked(prefName.get(), &isLocked);
       
  2827 +    if (NS_FAILED(rv))
       
  2828 +        return PL_DHASH_NEXT;
       
  2829 +
       
  2830 +
       
  2831 +    // Remove our observer before we change the value
       
  2832 +    userBranch->RemoveObserver(prefName.get(), prefs);
       
  2833 +    // Remember to ignore this item. Because some prefs start with "config.use_system_prefs",
       
  2834 +    // which we always observe, even after we remove the observer, changes to the pref will
       
  2835 +    // still be observed by us. We must ignore them.
       
  2836 +    aItem->ignore = PR_TRUE;
       
  2837 +
       
  2838 +
       
  2839 +    // Unlock the pref so we can set it
       
  2840 +    if (isLocked) {
       
  2841 +        userBranch->UnlockPref(prefName.get());
       
  2842      }
       
  2843 +
       
  2844 +    nsCOMPtr<nsIPrefBranch> defaultBranch = prefs->GetPrefDefaultBranch();
       
  2845 +
       
  2846 +    RestorePrefValue(prefType, prefName.get(), aItem,
       
  2847 +                     userBranch, defaultBranch);
       
  2848 +
       
  2849 +    if (aItem->savedLocked) {
       
  2850 +        userBranch->LockPref(prefName.get());
       
  2851 +    }
       
  2852 +
       
  2853 +    return PL_DHASH_NEXT;
       
  2854 +}
       
  2855 +
       
  2856 +nsresult
       
  2857 +nsSystemPref::StopOverridingMozillaPref(const char* aPrefName)
       
  2858 +{
       
  2859 +    SysPrefItem* item;
       
  2860 +    nsDependentCString prefNameStr(aPrefName);
       
  2861 +    if (!mSavedPrefs.Get(prefNameStr, &item))
       
  2862 +        return NS_OK;
       
  2863 +
       
  2864 +    RestorePref(prefNameStr, item, this);
       
  2865 +    mSavedPrefs.Remove(prefNameStr);
       
  2866 +    delete item;
       
  2867 +    return NS_OK;
       
  2868 +}
       
  2869 +
       
  2870 +/* private */
       
  2871 + 
       
  2872 +nsresult
       
  2873 +nsSystemPref::OverridePref(const char* aPrefName, PRInt32 aType,
       
  2874 +                           void* aValue, PRBool aLock, PRBool aPresent)
       
  2875 +{
       
  2876 +    nsCOMPtr<nsIPrefBranch2> userBranch = GetPrefUserBranch();
       
  2877 +    nsCOMPtr<nsIPrefBranch> defaultBranch = GetPrefDefaultBranch();
       
  2878 +
       
  2879 +    PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
       
  2880 +    nsresult rv = userBranch->GetPrefType(aPrefName, &prefType);
       
  2881 +    PRBool isLocked;
       
  2882 +    rv = userBranch->PrefIsLocked(aPrefName, &isLocked);
       
  2883 +    if (NS_FAILED(rv))
       
  2884 +        return rv;
       
  2885 +    PRBool hasUserValue;
       
  2886 +    rv = userBranch->PrefHasUserValue(aPrefName, &hasUserValue);
       
  2887 +    if (NS_FAILED(rv))
       
  2888 +        return rv;
       
  2889 +    if (prefType == 0) {
       
  2890 +        // Preference does not exist. Allow the system prefs to
       
  2891 +        // set it.
       
  2892 +    } else {
       
  2893 +        NS_ASSERTION(aType == prefType,
       
  2894 +                     "System pref engine passed incorrect type for Mozilla pref");
       
  2895 +        if (aType != prefType)
       
  2896 +            return NS_ERROR_FAILURE;
       
  2897 +    }
       
  2898 +
       
  2899 +    if (prefType != 0) {
       
  2900 +        nsDependentCString prefNameStr(aPrefName);
       
  2901 +        SysPrefItem* item = nsnull;
       
  2902 +        if (!mSavedPrefs.Get(prefNameStr, &item)) {
       
  2903 +            // Need to save the existing value away
       
  2904 +            item = new SysPrefItem();
       
  2905 +            if (!item)
       
  2906 +                return NS_ERROR_OUT_OF_MEMORY;
       
  2907 +
       
  2908 +            item->savedLocked = isLocked;
       
  2909 +            item->savedUserPresent = hasUserValue;
       
  2910 +        
       
  2911 +            switch (prefType) {
       
  2912 +            case nsIPrefBranch::PREF_STRING:
       
  2913 +                if (hasUserValue) {
       
  2914 +                    userBranch->GetCharPref(aPrefName, &item->savedUserValueString);
       
  2915 +                }
       
  2916 +                defaultBranch->GetCharPref(aPrefName, &item->savedDefaultValueString);
       
  2917 +                break;
       
  2918 +            case nsIPrefBranch::PREF_INT:
       
  2919 +                if (hasUserValue) {
       
  2920 +                    userBranch->GetIntPref(aPrefName, &item->savedUserValueScalar);
       
  2921 +                }
       
  2922 +                defaultBranch->GetIntPref(aPrefName, &item->savedDefaultValueScalar);
       
  2923 +                break;
       
  2924 +            case nsIPrefBranch::PREF_BOOL:
       
  2925 +                if (hasUserValue) {
       
  2926 +                    userBranch->GetBoolPref(aPrefName, &item->savedUserValueScalar);
       
  2927 +                }
       
  2928 +                defaultBranch->GetBoolPref(aPrefName, &item->savedDefaultValueScalar);
       
  2929 +                break;
       
  2930 +            default:
       
  2931 +                NS_ERROR("Unknown preference type");
       
  2932 +                delete item;
       
  2933 +                return NS_ERROR_FAILURE;
       
  2934 +            }
       
  2935 +
       
  2936 +            mSavedPrefs.Put(prefNameStr, item);
       
  2937 +
       
  2938 +            // Watch the user value in case it changes on the Mozilla side
       
  2939 +            // If 'aLock' is true then it shouldn't change and we don't
       
  2940 +            // need the observer, but don't bother optimizing for that.
       
  2941 +            userBranch->AddObserver(aPrefName, this, PR_TRUE);
       
  2942 +        } else {
       
  2943 +            if (isLocked != aLock) {
       
  2944 +                // restore pref value on user and default branches
       
  2945 +                RestorePrefValue(prefType, aPrefName, item,
       
  2946 +                                 userBranch, defaultBranch);
       
  2947 +            }
       
  2948 +        }
       
  2949 +    }
       
  2950 +
       
  2951 +    // We need to ignore pref changes due to our own calls here
       
  2952 +    mIgnorePrefSetting = PR_TRUE;
       
  2953 + 
       
  2954 +    // Unlock it if it's locked, so we can set it
       
  2955 +    if (isLocked) {
       
  2956 +        rv = userBranch->UnlockPref(aPrefName);
       
  2957 +        if (NS_FAILED(rv))
       
  2958 +            return rv;
       
  2959 +    }
       
  2960 +
       
  2961 +    // Set the pref on the default branch if we're locking it, because
       
  2962 +    // only the default branch gets used when the pref is locked.
       
  2963 +    // Set the pref on the user branch if we're not locking it, because
       
  2964 +    // that's where the user change will go.
       
  2965 +    nsIPrefBranch* settingBranch =
       
  2966 +        aLock ? defaultBranch.get() : static_cast<nsIPrefBranch*>(userBranch.get());
       
  2967 +
       
  2968 +    if (!aPresent) {
       
  2969 +        rv = settingBranch->DeleteBranch(aPrefName);
       
  2970 +    } else {
       
  2971 +        switch (aType) {
       
  2972 +        case nsIPrefBranch::PREF_STRING:
       
  2973 +            rv = settingBranch->SetCharPref(aPrefName, (const char*)aValue);
       
  2974 +            break;
       
  2975 +        case nsIPrefBranch::PREF_INT:
       
  2976 +            rv = settingBranch->SetIntPref(aPrefName, (PRInt32)(NS_PTR_TO_INT32(aValue)));
       
  2977 +            break;
       
  2978 +        case nsIPrefBranch::PREF_BOOL:
       
  2979 +            rv = settingBranch->SetBoolPref(aPrefName, (PRBool)(NS_PTR_TO_INT32(aValue)));
       
  2980 +            break;
       
  2981 +        default:
       
  2982 +            NS_ERROR("Unknown preference type");
       
  2983 +            mIgnorePrefSetting = PR_FALSE;
       
  2984 +            return NS_ERROR_FAILURE;
       
  2985 +        }
       
  2986 +    }
       
  2987 +
       
  2988 +    if (NS_FAILED(rv))
       
  2989 +        return rv;
       
  2990 +    if (aLock) {
       
  2991 +        rv = userBranch->LockPref(aPrefName);
       
  2992 +    }
       
  2993 +
       
  2994 +    mIgnorePrefSetting = PR_FALSE;
       
  2995      return rv;
       
  2996  }
       
  2997  
       
  2998 -//////////////////////////////////////////////////////////////////////
       
  2999 -// nsSystemPref::ReadSystemPref
       
  3000 -// Read a pref value from system pref service, and lock it in mozilla.
       
  3001 -//////////////////////////////////////////////////////////////////////
       
  3002 +
       
  3003  nsresult
       
  3004 -nsSystemPref::ReadSystemPref(const char *aPrefName)
       
  3005 +nsSystemPref::FixupLockdownPrefs()
       
  3006  {
       
  3007 -    if (!mSysPrefService)
       
  3008 -        return NS_ERROR_FAILURE;
       
  3009 -    nsresult rv;
       
  3010 -
       
  3011 -    nsCOMPtr<nsIPrefBranch> prefBranch
       
  3012 -        (do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
       
  3013 +    nsCOMPtr<nsIPrefBranch2> userPrefs = GetPrefUserBranch();
       
  3014 +    nsCOMPtr<nsIPrefBranch2> defaultPrefs = GetPrefUserBranch();
       
  3015 +    PRUint32 childCount;
       
  3016 +    char **childArray = nsnull;
       
  3017 +    nsresult rv = userPrefs->GetChildList("config.lockdown.",
       
  3018 +                                          &childCount, &childArray);
       
  3019      if (NS_FAILED(rv))
       
  3020          return rv;
       
  3021 -
       
  3022 -    SYSPREF_LOG(("about to read aPrefName %s\n", aPrefName));
       
  3023 -
       
  3024 -    prefBranch->UnlockPref(aPrefName);
       
  3025 -
       
  3026 -    PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
       
  3027 -    nsXPIDLCString strValue;
       
  3028 -    PRInt32 intValue = 0;
       
  3029 -    PRBool boolValue = PR_FALSE;
       
  3030 -
       
  3031 -    rv = prefBranch->GetPrefType(aPrefName, &prefType);
       
  3032 -    if (NS_FAILED(rv))
       
  3033 -        return rv;
       
  3034 -    switch (prefType) {
       
  3035 -    case nsIPrefBranch::PREF_STRING:
       
  3036 -        mSysPrefService->GetCharPref(aPrefName, getter_Copies(strValue));
       
  3037 -        SYSPREF_LOG(("system value is %s\n", strValue.get()));
       
  3038 -
       
  3039 -        prefBranch->SetCharPref(aPrefName, strValue.get());
       
  3040 -        break;
       
  3041 -    case nsIPrefBranch::PREF_INT:
       
  3042 -        mSysPrefService->GetIntPref(aPrefName, &intValue);
       
  3043 -        SYSPREF_LOG(("system value is %d\n", intValue));
       
  3044 -
       
  3045 -        prefBranch->SetIntPref(aPrefName, intValue);
       
  3046 -        break;
       
  3047 -    case nsIPrefBranch::PREF_BOOL:
       
  3048 -        mSysPrefService->GetBoolPref(aPrefName, &boolValue);
       
  3049 -        SYSPREF_LOG(("system value is %s\n", boolValue ? "TRUE" : "FALSE"));
       
  3050 -
       
  3051 -        prefBranch->SetBoolPref(aPrefName, boolValue);
       
  3052 -        break;
       
  3053 -    default:
       
  3054 -        SYSPREF_LOG(("Fail to system value for it\n"));
       
  3055 -        return NS_ERROR_FAILURE;
       
  3056 +    for (PRUint32 i = 0; i < childCount; ++i) {
       
  3057 +        PRInt32 type;
       
  3058 +        rv = defaultPrefs->GetPrefType(childArray[i], &type);
       
  3059 +        if (NS_FAILED(rv))
       
  3060 +            return rv;
       
  3061 +        NS_ASSERTION(type == nsIPrefBranch2::PREF_BOOL,
       
  3062 +                     "All config.lockdown.* prefs should be boolean");
       
  3063 +        if (type == nsIPrefBranch2::PREF_BOOL) {
       
  3064 +            rv = defaultPrefs->SetBoolPref(childArray[i], PR_FALSE);
       
  3065 +            if (NS_FAILED(rv))
       
  3066 +                return rv;
       
  3067 +        }
       
  3068      }
       
  3069 -    prefBranch->LockPref(aPrefName);
       
  3070 +    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
       
  3071      return NS_OK;
       
  3072  }
       
  3073  
       
  3074 -//////////////////////////////////////////////////////////////////////
       
  3075 -// nsSystemPref::UseMozillaPrefs
       
  3076 -// Restore mozilla default prefs, remove system pref listeners
       
  3077 -/////////////////////////////////////////////////////////////////////
       
  3078 +
       
  3079  nsresult
       
  3080 -nsSystemPref::UseMozillaPrefs()
       
  3081 +nsSystemPref::LoadSystemPrefs()
       
  3082  {
       
  3083 -    nsresult rv = NS_OK;
       
  3084 -    SYSPREF_LOG(("\n====Now rollback to Mozilla prefs==\n"));
       
  3085 +    SYSPREF_LOG(("\n====Now Use system prefs==\n"));
       
  3086 +    NS_ASSERTION(!mSysPrefService,
       
  3087 +                 "Shouldn't have the pref service here");
       
  3088 +    nsresult rv;
       
  3089 +    mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
       
  3090 +    if (NS_FAILED(rv) || !mSysPrefService) {
       
  3091 +        FixupLockdownPrefs();
       
  3092 +        SYSPREF_LOG(("...No System Pref Service\n"));
       
  3093 +        return NS_OK;
       
  3094 +    }
       
  3095  
       
  3096 -    // if we did not use system prefs, do nothing
       
  3097 -    if (!mSysPrefService)
       
  3098 -        return NS_OK;
       
  3099 +    // Cache the pref-branch while we load up the system prefs.
       
  3100 +    NS_ASSERTION(!mCachedUserPrefBranch,
       
  3101 +                 "Shouldn't have a cache here");
       
  3102 +    nsCOMPtr<nsIPrefBranch2> userBranch = GetPrefUserBranch();
       
  3103 +    nsCOMPtr<nsIPrefBranch> defaultBranch = GetPrefDefaultBranch();
       
  3104 +    mCachedDefaultPrefBranch = defaultBranch;
       
  3105 +    mCachedUserPrefBranch = userBranch;
       
  3106 +    rv = mSysPrefService->LoadSystemPreferences(this);
       
  3107 +    mCachedDefaultPrefBranch = nsnull;
       
  3108 +    mCachedUserPrefBranch = nsnull;
       
  3109  
       
  3110 -    PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
       
  3111 -    for (PRIntn index = 0; index < sysPrefCount; ++index) {
       
  3112 -        // restore mozilla default value and free string memory if needed
       
  3113 -        RestoreMozDefaultPref(mSysPrefs[index].prefName,
       
  3114 -                              &mSysPrefs[index].defaultValue,
       
  3115 -                              mSysPrefs[index].isLocked);
       
  3116 -        SYSPREF_LOG(("stop listening on %s\n", mSysPrefs[index].prefName));
       
  3117 -        mSysPrefService->RemoveObserver(mSysPrefs[index].prefName,
       
  3118 -                                        this);
       
  3119 +    if (NS_FAILED(rv)) {
       
  3120 +        // Restore all modified preferences to their original values
       
  3121 +        mSavedPrefs.EnumerateRead(RestorePref, this);
       
  3122 +        mSavedPrefs.Clear();
       
  3123 +        mSysPrefService = nsnull;
       
  3124      }
       
  3125 +        
       
  3126      return rv;
       
  3127  }
       
  3128  
       
  3129 -////////////////////////////////////////////////////////////////////////////
       
  3130 -// nsSystemPref::RestoreMozDefaultPref
       
  3131 -// Save the saved mozilla default value.
       
  3132 -// It is also responsible for allocate the string memory when needed, because
       
  3133 -// this method know what type of value is stored.
       
  3134 -/////////////////////////////////////////////////////////////////////////////
       
  3135 +
       
  3136  nsresult
       
  3137 -nsSystemPref::SaveMozDefaultPref(const char *aPrefName,
       
  3138 -                                 MozPrefValue *aPrefValue,
       
  3139 -                                 PRBool *aLocked)
       
  3140 +nsSystemPref::RestoreMozillaPrefs()
       
  3141  {
       
  3142 -    NS_ENSURE_ARG_POINTER(aPrefName);
       
  3143 -    NS_ENSURE_ARG_POINTER(aPrefValue);
       
  3144 -    NS_ENSURE_ARG_POINTER(aLocked);
       
  3145 +    SYSPREF_LOG(("\n====Now rollback to Mozilla prefs==\n"));
       
  3146  
       
  3147 -    nsresult rv;
       
  3148 +    NS_ASSERTION(mSysPrefService,
       
  3149 +                 "Should have the pref service here");
       
  3150 +    if (!mSysPrefService)
       
  3151 +        return NS_ERROR_FAILURE;
       
  3152  
       
  3153 -    nsCOMPtr<nsIPrefBranch> prefBranch =
       
  3154 -        do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
       
  3155 -    if (NS_FAILED(rv))
       
  3156 -        return rv;
       
  3157 +    nsCOMPtr<nsIPrefBranch2> userBranch = GetPrefUserBranch();
       
  3158 +    nsCOMPtr<nsIPrefBranch> defaultBranch = GetPrefDefaultBranch();
       
  3159 +    mCachedDefaultPrefBranch = defaultBranch;
       
  3160 +    mCachedUserPrefBranch = userBranch;
       
  3161  
       
  3162 -    SYSPREF_LOG(("Save Mozilla value for %s\n", aPrefName));
       
  3163 +    mSysPrefService->NotifyUnloadSystemPreferences();
       
  3164 +    // Restore all modified preferences to their original values
       
  3165 +    mSavedPrefs.EnumerateRead(RestorePref, this);
       
  3166 +    mSavedPrefs.Clear();
       
  3167  
       
  3168 -    PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
       
  3169 -    nsXPIDLCString strValue;
       
  3170 +    mCachedDefaultPrefBranch = nsnull;
       
  3171 +    mCachedUserPrefBranch = nsnull;
       
  3172 +    
       
  3173 +    mSysPrefService = nsnull;
       
  3174  
       
  3175 -    rv = prefBranch->GetPrefType(aPrefName, &prefType);
       
  3176 -    if (NS_FAILED(rv))
       
  3177 -        return rv;
       
  3178 -    switch (prefType) {
       
  3179 -    case nsIPrefBranch::PREF_STRING:
       
  3180 -        prefBranch->GetCharPref(aPrefName,
       
  3181 -                                getter_Copies(strValue));
       
  3182 -        SYSPREF_LOG(("Mozilla value is %s", strValue.get()));
       
  3183 +    FixupLockdownPrefs();
       
  3184  
       
  3185 -        if (aPrefValue->stringVal)
       
  3186 -            PL_strfree(aPrefValue->stringVal);
       
  3187 -        aPrefValue->stringVal = PL_strdup(strValue.get());
       
  3188 -        break;
       
  3189 -    case nsIPrefBranch::PREF_INT:
       
  3190 -        prefBranch->GetIntPref(aPrefName, &aPrefValue->intVal);
       
  3191 -        SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
       
  3192 -
       
  3193 -        break;
       
  3194 -    case nsIPrefBranch::PREF_BOOL:
       
  3195 -        prefBranch->GetBoolPref(aPrefName, &aPrefValue->boolVal);
       
  3196 -        SYSPREF_LOG(("Mozilla value is %s\n",
       
  3197 -                     aPrefValue->boolVal ? "TRUE" : "FALSE"));
       
  3198 -
       
  3199 -        break;
       
  3200 -    default:
       
  3201 -        SYSPREF_LOG(("Fail to Read Mozilla value for it\n"));
       
  3202 -        return NS_ERROR_FAILURE;
       
  3203 -    }
       
  3204 -    rv = prefBranch->PrefIsLocked(aPrefName, aLocked);
       
  3205 -    SYSPREF_LOG((" (%s).\n", aLocked ? "Locked" : "NOT Locked"));
       
  3206 -    return rv;
       
  3207 -}
       
  3208 -
       
  3209 -////////////////////////////////////////////////////////////////////////////
       
  3210 -// nsSystemPref::RestoreMozDefaultPref
       
  3211 -// Restore the saved mozilla default value to pref service.
       
  3212 -// It is also responsible for free the string memory when needed, because
       
  3213 -// this method know what type of value is stored.
       
  3214 -/////////////////////////////////////////////////////////////////////////////
       
  3215 -nsresult
       
  3216 -nsSystemPref::RestoreMozDefaultPref(const char *aPrefName,
       
  3217 -                                    MozPrefValue *aPrefValue,
       
  3218 -                                    PRBool aLocked)
       
  3219 -{
       
  3220 -    NS_ENSURE_ARG_POINTER(aPrefName);
       
  3221 -
       
  3222 -    nsresult rv;
       
  3223 -
       
  3224 -    nsCOMPtr<nsIPrefBranch> prefBranch =
       
  3225 -        do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
       
  3226 -    if (NS_FAILED(rv))
       
  3227 -        return rv;
       
  3228 -
       
  3229 -    SYSPREF_LOG(("Restore Mozilla value for %s\n", aPrefName));
       
  3230 -
       
  3231 -    PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
       
  3232 -    rv = prefBranch->GetPrefType(aPrefName, &prefType);
       
  3233 -    if (NS_FAILED(rv))
       
  3234 -        return rv;
       
  3235 -
       
  3236 -    // unlock, if it is locked
       
  3237 -    prefBranch->UnlockPref(aPrefName);
       
  3238 -
       
  3239 -    switch (prefType) {
       
  3240 -    case nsIPrefBranch::PREF_STRING:
       
  3241 -        prefBranch->SetCharPref(aPrefName,
       
  3242 -                                aPrefValue->stringVal);
       
  3243 -        SYSPREF_LOG(("Mozilla value is %s\n", aPrefValue->stringVal));
       
  3244 -
       
  3245 -        PL_strfree(aPrefValue->stringVal);
       
  3246 -        aPrefValue->stringVal = nsnull;
       
  3247 -
       
  3248 -        break;
       
  3249 -    case nsIPrefBranch::PREF_INT:
       
  3250 -        prefBranch->SetIntPref(aPrefName, aPrefValue->intVal);
       
  3251 -        SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
       
  3252 -
       
  3253 -        break;
       
  3254 -    case nsIPrefBranch::PREF_BOOL:
       
  3255 -        prefBranch->SetBoolPref(aPrefName, aPrefValue->boolVal);
       
  3256 -        SYSPREF_LOG(("Mozilla value is %s\n",
       
  3257 -                     aPrefValue->boolVal ? "TRUE" : "FALSE"));
       
  3258 -
       
  3259 -        break;
       
  3260 -    default:
       
  3261 -        SYSPREF_LOG(("Fail to Restore Mozilla value for it\n"));
       
  3262 -        return NS_ERROR_FAILURE;
       
  3263 -    }
       
  3264 -
       
  3265 -    // restore its old lock status
       
  3266 -    if (aLocked)
       
  3267 -        prefBranch->LockPref(aPrefName);
       
  3268      return NS_OK;
       
  3269  }
       
  3270 diff --git a/extensions/pref/system-pref/src/nsSystemPref.h b/extensions/pref/system-pref/src/nsSystemPref.h
       
  3271 --- a/extensions/pref/system-pref/src/nsSystemPref.h
       
  3272 +++ b/extensions/pref/system-pref/src/nsSystemPref.h
       
  3273 @@ -18,17 +18,17 @@
       
  3274   * The Original Code is mozilla.org code.
       
  3275   *
       
  3276   * The Initial Developer of the Original Code is Sun Microsystems, Inc.
       
  3277   * Portions created by Sun Microsystems are Copyright (C) 2003 Sun
       
  3278   * Microsystems, Inc. All Rights Reserved.
       
  3279   *
       
  3280   * Original Author: Bolian Yin (bolian.yin@sun.com)
       
  3281   *
       
  3282 - * Contributor(s):
       
  3283 + * Contributor(s): Robert O'Callahan/Novell (rocallahan@novell.com)
       
  3284   *
       
  3285   * Alternatively, the contents of this file may be used under the terms of
       
  3286   * either the GNU General Public License Version 2 or later (the "GPL"), or
       
  3287   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
       
  3288   * in which case the provisions of the GPL or the LGPL are applicable instead
       
  3289   * of those above. If you wish to allow use of your version of this file only
       
  3290   * under the terms of either the GPL or the LGPL, and not to allow others to
       
  3291   * use your version of this file under the terms of the NPL, indicate your
       
  3292 @@ -40,71 +40,101 @@
       
  3293   * ***** END LICENSE BLOCK ***** */
       
  3294  
       
  3295  #ifndef __SYSTEM_PREF_H__
       
  3296  #define __SYSTEM_PREF_H__
       
  3297  
       
  3298  #include "nsCOMPtr.h"
       
  3299  #include "nsXPCOM.h"
       
  3300  #include "nsCRT.h"
       
  3301 -#include "nsIAppStartupNotifier.h"
       
  3302 -#include "nsICategoryManager.h"
       
  3303 -#include "nsIServiceManager.h"
       
  3304  #include "nsWeakReference.h"
       
  3305 -#include "nsIPrefService.h"
       
  3306 -#include "nsIPrefBranch2.h"
       
  3307 +#include "nsClassHashtable.h"
       
  3308 +#include "nsHashKeys.h"
       
  3309 +#include "nsMemory.h"
       
  3310  
       
  3311 -#include <nsIObserver.h>
       
  3312 +#include "nsISystemPrefService.h"
       
  3313 +#include "nsIObserver.h"
       
  3314  
       
  3315 -union MozPrefValue;
       
  3316  struct SysPrefItem;
       
  3317  
       
  3318  //////////////////////////////////////////////////////////////////////////
       
  3319  //
       
  3320  // nsSystemPref, as an extension of mozilla pref service, reads some mozilla
       
  3321  // prefs from host system when the feature is enabled ("config.system-pref").
       
  3322  //
       
  3323 -// nsSystemPref listens on NS_PREFSERVICE_READ_TOPIC_ID. When notified,
       
  3324 -// nsSystemPref will start the nsSystemPrefService (platform specific) to
       
  3325 -// read all the interested prefs (listed in sSysPrefList table) from system
       
  3326 -// and lock these prefs from user's modification. 
       
  3327 +// nsSystemPref listens on NS_PREFSERVICE_READ_TOPIC_ID. When
       
  3328 +// notified, nsSystemPref will start the nsSystemPrefService (platform
       
  3329 +// specific) and tell it to override Mozilla prefs with its own
       
  3330 +// settings.
       
  3331  //
       
  3332 -// This feature will make mozilla integrated better into host platforms. If
       
  3333 -// users want to change the prefs read from system, the system provided pref
       
  3334 -// editor (i.e. gconf-editor in gnome) should be used.
       
  3335 +// When overriding a Mozilla preference the prefservice can request the
       
  3336 +// pref be locked or unlocked. If the pref is locked then we set the default
       
  3337 +// value and lock it in Mozilla so the user value is ignored and the user cannot
       
  3338 +// change the value. If the pref is unlocked then we set the user value
       
  3339 +// and unlock it in Mozilla so the user can change it. If the user changes it,
       
  3340 +// then the prefservice is notified so it can copy the value back to its
       
  3341 +// underlying store.
       
  3342 +//
       
  3343 +// We detect changes to Mozilla prefs by observing pref changes in the
       
  3344 +// user branch.
       
  3345 +//
       
  3346 +// For testing purposes, if the user toggles on
       
  3347 +// config.use_system_prefs then we save the current preferences before
       
  3348 +// overriding them from gconf, and if the user toggles off
       
  3349 +// config.use_system_prefs *in the same session* then we restore the
       
  3350 +// preferences. If the user exits without turning off use_system_prefs
       
  3351 +// then the saved values are lost and the new values are permanent.
       
  3352 +//
       
  3353  //////////////////////////////////////////////////////////////////////////
       
  3354  
       
  3355  class nsSystemPref : public nsIObserver,
       
  3356 -                     public nsSupportsWeakReference
       
  3357 +                     public nsSupportsWeakReference,
       
  3358 +                     public nsISystemPref
       
  3359  {
       
  3360  public:
       
  3361      NS_DECL_ISUPPORTS
       
  3362      NS_DECL_NSIOBSERVER
       
  3363  
       
  3364      nsSystemPref();
       
  3365      virtual ~nsSystemPref();
       
  3366      nsresult Init(void);
       
  3367  
       
  3368 +    // nsISystemPref
       
  3369 +    virtual nsresult SetOverridingMozillaBoolPref(const char* aPrefName,
       
  3370 +                                                  PRBool aValue, PRBool aLocked,
       
  3371 +                                                  PRBool aPresent = PR_TRUE);
       
  3372 +    virtual nsresult SetOverridingMozillaIntPref(const char* aPrefName,
       
  3373 +                                                 PRInt32 aValue, PRBool aLocked,
       
  3374 +                                                 PRBool aPresent = PR_TRUE);
       
  3375 +    virtual nsresult SetOverridingMozillaStringPref(const char* aPrefName,
       
  3376 +                                                    const char* aValue, PRBool aLocked,
       
  3377 +                                                    PRBool aPresent = PR_TRUE);
       
  3378 +    virtual nsresult StopOverridingMozillaPref(const char* aPrefName);
       
  3379 +    virtual already_AddRefed<nsIPrefBranch2> GetPrefUserBranch();
       
  3380 +    virtual already_AddRefed<nsIPrefBranch> GetPrefDefaultBranch();
       
  3381 +
       
  3382  private:
       
  3383 -    // funcs used to load system prefs and save mozilla default prefs
       
  3384 -    nsresult UseSystemPrefs();
       
  3385 -    nsresult ReadSystemPref(const char *aPrefName);
       
  3386 -    nsresult SaveMozDefaultPref(const char *aPrefName,
       
  3387 -                                MozPrefValue *aPrefVal,
       
  3388 -                                PRBool *aLocked);
       
  3389 +    // If we don't load the system prefs for any reason, then
       
  3390 +    // set all config.lockdown.* preferences to PR_FALSE so that
       
  3391 +    // residual lockdown settings are removed.
       
  3392 +    nsresult FixupLockdownPrefs();
       
  3393  
       
  3394 -    // funcs used to load mozilla default prefs
       
  3395 -    nsresult UseMozillaPrefs();
       
  3396 -    nsresult RestoreMozDefaultPref(const char *aPrefName,
       
  3397 -                                   MozPrefValue *aPrefVal,
       
  3398 -                                   PRBool aLocked);
       
  3399 +    nsresult LoadSystemPrefs();
       
  3400  
       
  3401 -    nsCOMPtr<nsIPrefBranch2>  mSysPrefService;
       
  3402 -    PRBool mEnabled;  // system pref is enabled or not
       
  3403 -    SysPrefItem *mSysPrefs;
       
  3404 +    nsresult RestoreMozillaPrefs();
       
  3405 +
       
  3406 +    nsresult OverridePref(const char* aPrefName, PRInt32 aType,
       
  3407 +                          void* aValue, PRBool aLock, PRBool aPresent);
       
  3408 +
       
  3409 +    nsCOMPtr<nsISystemPrefService>  mSysPrefService;
       
  3410 +    nsClassHashtable<nsCStringHashKey,SysPrefItem> mSavedPrefs;
       
  3411 +    // weak pointers to cached prefbranches
       
  3412 +    nsIPrefBranch2* mCachedUserPrefBranch;
       
  3413 +    nsIPrefBranch* mCachedDefaultPrefBranch;
       
  3414 +    PRPackedBool mIgnorePrefSetting;
       
  3415  };
       
  3416  
       
  3417  #define NS_SYSTEMPREF_CID                  \
       
  3418    { /* {549abb24-7c9d-4aba-915e-7ce0b716b32f} */       \
       
  3419      0x549abb24,                                        \
       
  3420      0x7c9d,                                            \
       
  3421      0x4aba,                                            \
       
  3422      { 0x91, 0x5e, 0x7c, 0xe0, 0xb7, 0x16, 0xb3, 0x2f } \
       
  3423 diff --git a/extensions/pref/system-pref/src/nsSystemPrefFactory.cpp b/extensions/pref/system-pref/src/nsSystemPrefFactory.cpp
       
  3424 --- a/extensions/pref/system-pref/src/nsSystemPrefFactory.cpp
       
  3425 +++ b/extensions/pref/system-pref/src/nsSystemPrefFactory.cpp
       
  3426 @@ -37,20 +37,20 @@
       
  3427   * the provisions above, a recipient may use your version of this file under
       
  3428   * the terms of any one of the NPL, the GPL or the LGPL.
       
  3429   *
       
  3430   * ***** END LICENSE BLOCK ***** */
       
  3431  
       
  3432  #include "nsICategoryManager.h"
       
  3433  #include "nsIGenericFactory.h"
       
  3434  #include "nsSystemPref.h"
       
  3435 -#include "nsSystemPrefService.h"
       
  3436 +#include "nsIServiceManager.h"
       
  3437 +#include "nsIAppStartupNotifier.h"
       
  3438  
       
  3439  NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPref, Init)
       
  3440 -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPrefService, Init)
       
  3441  
       
  3442  // Registering nsSystemPref module as part of the app-startup category to get 
       
  3443  // it instantiated.
       
  3444  
       
  3445  static NS_METHOD
       
  3446  RegisterSystemPref(nsIComponentManager *aCompMgr,
       
  3447                     nsIFile *aPath,
       
  3448                     const char *registryLocation,
       
  3449 @@ -91,16 +91,11 @@ UnRegisterSystemPref(nsIComponentManager
       
  3450  static const nsModuleComponentInfo components[] = {
       
  3451      { NS_SYSTEMPREF_CLASSNAME,
       
  3452        NS_SYSTEMPREF_CID,
       
  3453        NS_SYSTEMPREF_CONTRACTID,
       
  3454        nsSystemPrefConstructor,
       
  3455        RegisterSystemPref,
       
  3456        UnRegisterSystemPref,
       
  3457      },
       
  3458 -    { NS_SYSTEMPREF_SERVICE_CLASSNAME,
       
  3459 -      NS_SYSTEMPREF_SERVICE_CID,
       
  3460 -      NS_SYSTEMPREF_SERVICE_CONTRACTID,
       
  3461 -      nsSystemPrefServiceConstructor,
       
  3462 -    },
       
  3463  };
       
  3464  
       
  3465  NS_IMPL_NSGETMODULE(nsSystemPrefModule, components)
       
  3466 diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in
       
  3467 --- a/toolkit/library/Makefile.in
       
  3468 +++ b/toolkit/library/Makefile.in
       
  3469 @@ -229,16 +229,20 @@ endif
       
  3470  ifdef NS_OSSO
       
  3471  EXTRA_DSO_LDOPTS += $(LIBOSSO_LIBS)
       
  3472  endif
       
  3473  
       
  3474  ifdef MOZ_ENABLE_DBUS
       
  3475  EXTRA_DSO_LDOPTS += $(MOZ_DBUS_GLIB_LIBS)
       
  3476  endif
       
  3477  
       
  3478 +ifdef MOZ_ENABLE_GCONF
       
  3479 +EXTRA_DSO_LDOPTS += $(MOZ_GCONF_LIBS)
       
  3480 +endif
       
  3481 +
       
  3482  ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))
       
  3483  EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(XEXT_LIBS) $(XCOMPOSITE_LIBS) $(MOZ_PANGO_LIBS) $(MOZ_GTK2_LIBS) $(XT_LIBS) -lgthread-2.0
       
  3484  EXTRA_DSO_LDOPTS += $(FT2_LIBS)
       
  3485  endif
       
  3486  
       
  3487  ifeq (qt,$(MOZ_WIDGET_TOOLKIT))
       
  3488  EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(XT_LIBS) $(MOZ_QT_LIBS) -lgthread-2.0
       
  3489  EXTRA_DSO_LDOPTS += $(FT2_LIBS)
       
  3490 diff --git a/toolkit/toolkit-tiers.mk b/toolkit/toolkit-tiers.mk
       
  3491 --- a/toolkit/toolkit-tiers.mk
       
  3492 +++ b/toolkit/toolkit-tiers.mk
       
  3493 @@ -253,16 +253,23 @@ endif
       
  3494  ifdef MOZ_ENABLE_LIBXUL
       
  3495  tier_toolkit_dirs += xpcom/stub
       
  3496  endif
       
  3497  
       
  3498  ifdef NS_TRACE_MALLOC
       
  3499  tier_toolkit_dirs += tools/trace-malloc
       
  3500  endif
       
  3501  
       
  3502 +# gconf module is external
       
  3503 +ifdef MOZ_PREF_EXTENSIONS
       
  3504 +ifdef MOZ_ENABLE_GCONF
       
  3505 +tier_toolkit_dirs += extensions/pref/system-pref/src/gconf
       
  3506 +endif
       
  3507 +endif
       
  3508 +
       
  3509  ifdef MOZ_ENABLE_GNOME_COMPONENT
       
  3510  tier_toolkit_dirs    += toolkit/system/gnome
       
  3511  endif
       
  3512  
       
  3513  ifndef MOZ_ENABLE_LIBCONIC
       
  3514  # if libconic is present, it will do its own network monitoring
       
  3515  ifdef MOZ_ENABLE_DBUS
       
  3516  tier_toolkit_dirs    += toolkit/system/dbus