MozillaFirefox/gconf-backend.patch

3268 lines
121 KiB
Diff

Index: extensions/pref/system-pref/src/nsSystemPref.h
================================================================================
--- browser/installer/unix/packages-static
+++ browser/installer/unix/packages-static
@@ -210,6 +210,7 @@
bin/components/nsUpdateService.js
bin/components/extensions.xpt
bin/components/update.xpt
+bin/components/libsystem-pref-gconf.so
bin/components/nsBookmarkTransactionManager.js
bin/components/nsSessionStartup.js
bin/components/nsSessionStore.js
--- config/autoconf.mk.in
+++ config/autoconf.mk.in
@@ -226,6 +226,7 @@
MOZ_GNOMEVFS_CFLAGS = @MOZ_GNOMEVFS_CFLAGS@
MOZ_GNOMEVFS_LIBS = @MOZ_GNOMEVFS_LIBS@
+MOZ_ENABLE_GCONF = @MOZ_ENABLE_GCONF@
MOZ_GCONF_CFLAGS = @MOZ_GCONF_CFLAGS@
MOZ_GCONF_LIBS = @MOZ_GCONF_LIBS@
--- configure.in
+++ configure.in
@@ -4709,6 +4709,7 @@
])
fi
+ AC_SUBST(MOZ_ENABLE_GCONF)
AC_SUBST(MOZ_GCONF_CFLAGS)
AC_SUBST(MOZ_GCONF_LIBS)
--- extensions/pref/system-pref/src/Makefile.in
+++ extensions/pref/system-pref/src/Makefile.in
@@ -47,14 +47,13 @@
include $(DEPTH)/config/autoconf.mk
MODULE = system-pref
-LIBRARY_NAME = system-pref_s
+LIBRARY_NAME = system-pref
ifneq ($(OS_ARCH),WINNT)
SHORT_LIBNAME = syspref
endif
-# We want to force the creation of a static lib.
-FORCE_STATIC_LIB = 1
MOZILLA_INTERNAL_API = 1
+GRE_MODULE = 1
REQUIRES = xpcom \
string \
@@ -62,27 +61,25 @@
pref \
$(NULL)
-ifdef MOZ_ENABLE_GTK2
+ifdef MOZ_ENABLE_GCONF
DIRS = gconf
endif
-EXTRA_DSO_LDOPTS = \
- -L$(DIST)/bin \
- $(MOZ_COMPONENT_LIBS) \
- $(NULL)
-
CPPSRCS = \
nsSystemPref.cpp \
+ nsSystemPrefFactory.cpp \
$(NULL)
+EXTRA_DSO_LDOPTS = \
+ $(MOZ_COMPONENT_LIBS) \
+ $(NULL)
+
EXPORTS = \
- nsSystemPrefLog.h \
+ nsISystemPrefService.h \
$(NULL)
-include $(topsrcdir)/config/rules.mk
+EXPORT_LIBRARY = 1
+IS_COMPONENT = 1
+MODULE_NAME = nsSystemPrefModule
-ifdef MOZ_ENABLE_GTK2
-INCLUDES += \
- -I$(srcdir)/gconf \
- $(NULL)
-endif
+include $(topsrcdir)/config/rules.mk
--- extensions/pref/system-pref/src/gconf/Makefile.in
+++ extensions/pref/system-pref/src/gconf/Makefile.in
@@ -46,44 +46,36 @@
include $(DEPTH)/config/autoconf.mk
-MODULE = system-pref
-LIBRARY_NAME = system-pref
+MODULE = system-pref-gconf
+LIBRARY_NAME = system-pref-gconf
GRE_MODULE = 1
MOZILLA_INTERNAL_API = 1
+PACKAGE_FILE = gconf.pkg
+
REQUIRES = pref \
+ system-pref \
string \
xpcom \
embedcomponents \
+ necko \
$(NULL)
CPPSRCS = \
nsSystemPrefService.cpp \
- nsSystemPrefFactory.cpp \
$(NULL)
-SHARED_LIBRARY_LIBS = $(DIST)/lib/libsystem-pref_s.a
-
EXTRA_DSO_LDOPTS = \
- -L$(DIST)/bin \
$(MOZ_COMPONENT_LIBS) \
- $(MOZ_GTK2_LIBS) \
+ $(MOZ_GTK2_LIBS) \
+ $(MOZ_GCONF_LIBS) \
$(NULL)
-EXPORT_LIBRARY = 1
+#EXPORT_LIBRARY = 1
IS_COMPONENT = 1
-MODULE_NAME = nsSystemPrefModule
-
-EXPORTS = \
- nsSystemPrefService.h \
- $(NULL)
+FORCE_SHARED_LIB = 1
include $(topsrcdir)/config/rules.mk
-CFLAGS += $(MOZ_GTK2_CFLAGS)
-CXXFLAGS += $(MOZ_GTK2_CFLAGS)
-
-LOCAL_INCLUDES = -I$(srcdir)/..
-
-export::
- $(INSTALL) $(srcdir)/../nsSystemPrefFactory.cpp .
+CFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_GCONF_CFLAGS)
+CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_GCONF_CFLAGS)
--- extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp
+++ extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp
@@ -23,7 +23,7 @@
*
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
- * Contributor(s):
+ * Contributor(s): Robert O'Callahan/Novell (rocallahan@novell.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -41,6 +41,7 @@
#include <glib.h>
#include <glib-object.h>
+#include <gconf/gconf-client.h>
#include "plstr.h"
#include "nsCOMPtr.h"
@@ -48,837 +49,1259 @@
#include "nsIServiceManager.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
-
+#include "nsIPrefBranch2.h"
+#include "nsISystemPrefService.h"
+#include "nsDataHashtable.h"
+#include "nsHashKeys.h"
+#include "nsICategoryManager.h"
+#include "nsIGenericFactory.h"
#include "nsString.h"
-#include "nsSystemPrefLog.h"
-#include "nsSystemPrefService.h"
-
-/*************************************************************************
- * The strange thing here is that we load the gconf library manually and
- * search the function pointers we need. If that process fails, no gconf
- * support is available in mozilla. The aim is to make mozilla independent
- * on gconf, in both compile time and run time.
- ************************************************************************/
-
-//gconf types
-extern "C" {
-
- typedef enum {
- GCONF_VALUE_INVALID,
- GCONF_VALUE_STRING,
- GCONF_VALUE_INT,
- GCONF_VALUE_FLOAT,
- GCONF_VALUE_BOOL,
- GCONF_VALUE_SCHEMA,
-
- GCONF_VALUE_LIST,
- GCONF_VALUE_PAIR
-
- }GConfValueType;
-
- typedef struct {
- GConfValueType type;
- }GConfValue;
-
- typedef void * (*GConfClientGetDefaultType) (void);
- typedef PRBool (*GConfClientGetBoolType) (void *client, const gchar *key,
- GError **err);
- typedef gchar* (*GConfClientGetStringType) (void *client, const gchar *key,
- GError **err);
- typedef PRInt32 (*GConfClientGetIntType) (void *client, const gchar *key,
- GError **err);
- typedef void (*GConfClientNotifyFuncType) (void* client, guint cnxn_id,
- void *entry,
- gpointer user_data);
- typedef guint (*GConfClientNotifyAddType) (void* client,
- const gchar* namespace_section,
- GConfClientNotifyFuncType func,
- gpointer user_data,
- GFreeFunc destroy_notify,
- GError** err);
- typedef void (*GConfClientNotifyRemoveType) (void *client,
- guint cnxn);
- typedef void (*GConfClientAddDirType) (void *client,
- const gchar *dir,
- guint8 preload,
- GError **err);
- typedef void (*GConfClientRemoveDirType) (void *client,
- const gchar *dir,
- GError **err);
-
- typedef const char* (*GConfEntryGetKeyType) (const void *entry);
- typedef GConfValue* (*GConfEntryGetValueType) (const void *entry);
-
- typedef const char* (*GConfValueGetStringType) (const GConfValue *value);
- typedef PRInt32 (*GConfValueGetIntType) (const GConfValue *value);
- typedef PRBool (*GConfValueGetBoolType) (const GConfValue *value);
+#include "nsIPermissionManager.h"
-
- static void gconf_key_listener (void* client, guint cnxn_id,
- void *entry, gpointer user_data);
-}
+#define NS_SYSTEMPREF_SERVICE_CID \
+ { /* {3724e748-b088-4bf8-9298-aad426b66293} */ \
+ 0x3724e748, \
+ 0xb088, \
+ 0x4bf8, \
+ { 0x92, 0x98, 0xaa, 0xd4, 0x26, 0xb6, 0x62, 0x93 } \
+ }
+
+#define NS_SYSTEMPREF_SERVICE_CLASSNAME "System Preferences Platform Service"
+
+/**
+ * We can link directly to the gconf library. If it's not available,
+ * this component just won't load and no system prefs will be offered.
+ */
+
+#define NUM_ELEM(a) (sizeof(a)/sizeof(a[0]))
+
+class nsSystemPrefService;
+
+/**
+ * List the preferences that have a simple mapping between Moz and gconf.
+ * These preferences have the same meaning and their values are
+ * automatically converted.
+ */
+struct SimplePrefMapping {
+ const char *mozPrefName;
+ const char *gconfPrefName;
+ /**
+ * If this is PR_FALSE, then we never allow Mozilla to change
+ * this setting. The Mozilla pref will always be locked.
+ * If this is PR_TRUE then Mozilla will be allowed to change
+ * the setting --- but only if it is writable in gconf.
+ */
+ PRBool allowWritesFromMozilla;
+};
+typedef nsresult (* ComplexGConfPrefChanged)(nsSystemPrefService* aPrefService,
+ GConfClient* aClient);
+typedef nsresult (* ComplexMozPrefChanged)(nsSystemPrefService* aPrefService,
+ GConfClient* aClient);
+struct ComplexGConfPrefMapping {
+ const char* gconfPrefName;
+ ComplexGConfPrefChanged callback;
+};
-struct GConfCallbackData
-{
- GConfProxy *proxy;
- void * userData;
- PRUint32 atom;
- PRUint32 notifyId;
+struct ComplexMozPrefMapping {
+ const char* mozPrefName;
+ ComplexMozPrefChanged callback;
};
-//////////////////////////////////////////////////////////////////////
-// GConPrxoy is a thin wrapper for easy use of gconf funcs. It loads the
-// gconf library and initializes the func pointers for later use.
-//////////////////////////////////////////////////////////////////////
-class GConfProxy
+
+class nsSystemPrefService : public nsISystemPrefService
{
public:
- GConfProxy(nsSystemPrefService* aSysPrefService);
- ~GConfProxy();
- PRBool Init();
-
- nsresult GetBoolPref(const char *aMozKey, PRBool *retval);
- nsresult GetCharPref(const char *aMozKey, char **retval);
- nsresult GetIntPref(const char *aMozKey, PRInt32 *retval);
+ NS_DECL_ISUPPORTS
- nsresult NotifyAdd (PRUint32 aAtom, void *aUserData);
- nsresult NotifyRemove (PRUint32 aAtom, const void *aUserData);
+ nsresult Init();
- nsresult GetAtomForMozKey(const char *aMozKey, PRUint32 *aAtom) {
- return GetAtom(aMozKey, 0, aAtom);
- }
- const char *GetMozKey(PRUint32 aAtom) {
- return GetKey(aAtom, 0);
+ virtual nsresult LoadSystemPreferences(nsISystemPref* aPrefs);
+ virtual nsresult NotifyMozillaPrefChanged(const char* aPrefName);
+ virtual nsresult NotifyUnloadSystemPreferences();
+
+ nsSystemPrefService();
+ virtual ~nsSystemPrefService();
+
+ nsISystemPref* GetPrefs() { return mPref; }
+ SimplePrefMapping* GetSimpleCallbackData(PRUint32 aKey) {
+ SimplePrefMapping* result = nsnull;
+ mGConfSimpleCallbacks.Get(aKey, &result);
+ return result;
+ }
+ ComplexGConfPrefMapping* GetComplexCallbackData(PRUint32 aKey) {
+ ComplexGConfPrefMapping* result = nsnull;
+ mGConfComplexCallbacks.Get(aKey, &result);
+ return result;
}
- void OnNotify(void *aClient, void * aEntry, PRUint32 aNotifyId,
- GConfCallbackData *aData);
-
private:
- void *mGConfClient;
- PRLibrary *mGConfLib;
- PRBool mInitialized;
- nsSystemPrefService *mSysPrefService;
-
- //listeners
- nsAutoVoidArray *mObservers;
-
- void InitFuncPtrs();
- //gconf public func ptrs
-
- //gconf client funcs
- GConfClientGetDefaultType GConfClientGetDefault;
- GConfClientGetBoolType GConfClientGetBool;
- GConfClientGetStringType GConfClientGetString;
- GConfClientGetIntType GConfClientGetInt;
- GConfClientNotifyAddType GConfClientNotifyAdd;
- GConfClientNotifyRemoveType GConfClientNotifyRemove;
- GConfClientAddDirType GConfClientAddDir;
- GConfClientRemoveDirType GConfClientRemoveDir;
-
- //gconf entry funcs
- GConfEntryGetValueType GConfEntryGetValue;
- GConfEntryGetKeyType GConfEntryGetKey;
-
- //gconf value funcs
- GConfValueGetBoolType GConfValueGetBool;
- GConfValueGetStringType GConfValueGetString;
- GConfValueGetIntType GConfValueGetInt;
-
- //pref name translating stuff
- nsresult GetAtom(const char *aKey, PRUint8 aNameType, PRUint32 *aAtom);
- nsresult GetAtomForGConfKey(const char *aGConfKey, PRUint32 *aAtom) \
- {return GetAtom(aGConfKey, 1, aAtom);}
- const char *GetKey(PRUint32 aAtom, PRUint8 aNameType);
- const char *GetGConfKey(PRUint32 aAtom) \
- {return GetKey(aAtom, 1); }
- inline const char *MozKey2GConfKey(const char *aMozKey);
-
- //const strings
- static const char sPrefGConfKey[];
- static const char sDefaultLibName1[];
- static const char sDefaultLibName2[];
+ nsISystemPref* mPref;
+ nsDataHashtable<nsUint32HashKey, SimplePrefMapping*> mGConfSimpleCallbacks;
+ nsDataHashtable<nsUint32HashKey, ComplexGConfPrefMapping*> mGConfComplexCallbacks;
+ // This is set to PR_FALSE temporarily to stop listening to gconf
+ // change notifications (while we change gconf values)
+ PRPackedBool mListenToGConf;
};
-struct SysPrefCallbackData {
- nsISupports *observer;
- PRBool bIsWeakRef;
- PRUint32 prefAtom;
-};
-
-PRBool PR_CALLBACK
-sysPrefDeleteObserver(void *aElement, void *aData) {
- SysPrefCallbackData *pElement =
- NS_STATIC_CAST(SysPrefCallbackData *, aElement);
- NS_RELEASE(pElement->observer);
- nsMemory::Free(pElement);
- return PR_TRUE;
-}
-
-NS_IMPL_ISUPPORTS2(nsSystemPrefService, nsIPrefBranch, nsIPrefBranch2)
-
-/* public */
nsSystemPrefService::nsSystemPrefService()
- :mInitialized(PR_FALSE),
- mGConf(nsnull),
- mObservers(nsnull)
+ : mPref(nsnull), mListenToGConf(PR_TRUE)
{
+ mGConfSimpleCallbacks.Init();
+ mGConfComplexCallbacks.Init();
}
nsSystemPrefService::~nsSystemPrefService()
{
- mInitialized = PR_FALSE;
-
- if (mGConf)
- delete mGConf;
- if (mObservers) {
- (void)mObservers->EnumerateForwards(sysPrefDeleteObserver, nsnull);
- delete mObservers;
- }
+ NotifyUnloadSystemPreferences();
}
nsresult
nsSystemPrefService::Init()
{
- if (!gSysPrefLog) {
- gSysPrefLog = PR_NewLogModule("Syspref");
- if (!gSysPrefLog) return NS_ERROR_OUT_OF_MEMORY;
- }
-
- SYSPREF_LOG(("Init SystemPref Service\n"));
- if (mInitialized)
- return NS_ERROR_FAILURE;
-
- if (!mGConf) {
- mGConf = new GConfProxy(this);
- if (!mGConf->Init()) {
- delete mGConf;
- mGConf = nsnull;
- return NS_ERROR_FAILURE;
- }
- }
-
- mInitialized = PR_TRUE;
return NS_OK;
}
-/* readonly attribute string root; */
-NS_IMETHODIMP nsSystemPrefService::GetRoot(char * *aRoot)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+NS_IMPL_ISUPPORTS1(nsSystemPrefService, nsISystemPrefService)
-/* long getPrefType (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::GetPrefType(const char *aPrefName, PRInt32 *_retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
+static GConfClient* GetGConf() {
+ return gconf_client_get_default();
}
-/* boolean getBoolPref (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::GetBoolPref(const char *aPrefName, PRBool *_retval)
+static PRBool VerifyMatchingTypes(nsISystemPref* aPrefs,
+ const char* aMozPref, GConfValue* aVal)
{
- return mInitialized ?
- mGConf->GetBoolPref(aPrefName, _retval) : NS_ERROR_FAILURE;
-}
+ nsCOMPtr<nsIPrefBranch2> prefBranch = aPrefs->GetPrefUserBranch();
+ PRInt32 type;
+ nsresult rv = prefBranch->GetPrefType(aMozPref, &type);
+ if (NS_FAILED(rv)) {
+ // pref probably doesn't exist. Let gconf set it.
+ return PR_TRUE;
+ }
-/* void setBoolPref (in string aPrefName, in long aValue); */
-NS_IMETHODIMP nsSystemPrefService::SetBoolPref(const char *aPrefName, PRInt32 aValue)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
+ PRBool ok;
+ switch (aVal->type) {
+ case GCONF_VALUE_STRING:
+ ok = type == nsIPrefBranch2::PREF_STRING;
+ break;
+ case GCONF_VALUE_INT:
+ ok = type == nsIPrefBranch2::PREF_INT;
+ break;
+ case GCONF_VALUE_BOOL:
+ ok = type == nsIPrefBranch2::PREF_BOOL;
+ break;
+ default:
+ NS_ERROR("Unhandled gconf preference type");
+ return PR_FALSE;
+ }
+
+ NS_ASSERTION(ok, "Mismatched gconf/Mozilla pref types");
+ return ok;
}
-/* string getCharPref (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::GetCharPref(const char *aPrefName, char **_retval)
-{
- return mInitialized ?
- mGConf->GetCharPref(aPrefName, _retval) : NS_ERROR_FAILURE;
-}
+/**
+ * Map a gconf pref value into the corresponding Mozilla pref.
+ */
+static nsresult ApplySimpleMapping(SimplePrefMapping* aMap,
+ nsISystemPref* aPrefs,
+ GConfClient* aClient)
+{
+ GConfValue* val = gconf_client_get(aClient, aMap->gconfPrefName, nsnull);
+ if (!val) {
+ // No gconf key, so there's really nothing to do
+ return NS_OK;
+ }
-/* void setCharPref (in string aPrefName, in string aValue); */
-NS_IMETHODIMP nsSystemPrefService::SetCharPref(const char *aPrefName, const char *aValue)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+ VerifyMatchingTypes(aPrefs, aMap->mozPrefName, val);
-/* long getIntPref (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::GetIntPref(const char *aPrefName, PRInt32 *_retval)
-{
- return mInitialized ?
- mGConf->GetIntPref(aPrefName, _retval) : NS_ERROR_FAILURE;
-}
+ PRBool locked = !aMap->allowWritesFromMozilla ||
+ !gconf_client_key_is_writable(aClient, aMap->gconfPrefName, nsnull);
+ nsresult rv;
+ switch (val->type) {
+ case GCONF_VALUE_STRING: {
+ const char* str = gconf_value_get_string(val);
+ rv = aPrefs->SetOverridingMozillaStringPref(aMap->mozPrefName, str, locked);
+ // XXX do we need to free 'str' here?
+ break;
+ }
+ case GCONF_VALUE_INT:
+ rv = aPrefs->SetOverridingMozillaIntPref(aMap->mozPrefName,
+ gconf_value_get_int(val), locked);
+ break;
+ case GCONF_VALUE_BOOL:
+ rv = aPrefs->SetOverridingMozillaBoolPref(aMap->mozPrefName,
+ gconf_value_get_bool(val), locked);
+ break;
+ default:
+ NS_ERROR("Unusable gconf value type");
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ gconf_value_free(val);
+ return rv;
+}
+
+/**
+ * Map a Mozilla pref into the corresponding gconf pref, if
+ * that's allowed.
+ */
+static nsresult ReverseApplySimpleMapping(SimplePrefMapping* aMap,
+ nsISystemPref* aPrefs,
+ GConfClient* aClient)
+{
+ // Verify that the gconf key has the right type, if it exists
+ GConfValue* val = gconf_client_get(aClient, aMap->gconfPrefName, nsnull);
+ if (val) {
+ VerifyMatchingTypes(aPrefs, aMap->mozPrefName, val);
+ gconf_value_free(val);
+ }
+
+ PRBool writable = aMap->allowWritesFromMozilla &&
+ gconf_client_key_is_writable(aClient, aMap->gconfPrefName, nsnull);
+ if (!writable) {
+ NS_ERROR("Gconf key is not writable");
+ return NS_ERROR_FAILURE;
+ }
-/* void setIntPref (in string aPrefName, in long aValue); */
-NS_IMETHODIMP nsSystemPrefService::SetIntPref(const char *aPrefName, PRInt32 aValue)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+ nsCOMPtr<nsIPrefBranch2> prefBranch = aPrefs->GetPrefUserBranch();
+ PRInt32 type;
+ nsresult rv = prefBranch->GetPrefType(aMap->mozPrefName, &type);
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Writing back a pref that doesn't exist?");
+ return rv;
+ }
-/* void getComplexValue (in string aPrefName, in nsIIDRef aType, [iid_is (aType), retval] out nsQIResult aValue); */
-NS_IMETHODIMP nsSystemPrefService::GetComplexValue(const char *aPrefName, const nsIID & aType, void * *aValue)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+ switch (type) {
+ case nsIPrefBranch2::PREF_STRING:
+ {
+ char* result;
+ rv = prefBranch->GetCharPref(aMap->mozPrefName, &result);
+ if (NS_FAILED(rv))
+ return rv;
-/* void setComplexValue (in string aPrefName, in nsIIDRef aType, in nsISupports aValue); */
-NS_IMETHODIMP nsSystemPrefService::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+ gconf_client_set_string(aClient, aMap->gconfPrefName, result, nsnull);
+ nsMemory::Free(result);
+ }
+ break;
+ case nsIPrefBranch2::PREF_INT:
+ {
+ PRInt32 result;
+ rv = prefBranch->GetIntPref(aMap->mozPrefName, &result);
+ if (NS_FAILED(rv))
+ return rv;
-/* void clearUserPref (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::ClearUserPref(const char *aPrefName)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+ gconf_client_set_int(aClient, aMap->gconfPrefName, result, nsnull);
+ }
+ break;
+ case nsIPrefBranch2::PREF_BOOL:
+ {
+ PRBool result;
+ rv = prefBranch->GetBoolPref(aMap->mozPrefName, &result);
+ if (NS_FAILED(rv))
+ return rv;
-/* void lockPref (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::LockPref(const char *aPrefName)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+ gconf_client_set_bool(aClient, aMap->gconfPrefName, result, nsnull);
+ }
+ break;
+ default:
+ NS_ERROR("Unhandled gconf preference type");
+ return NS_ERROR_FAILURE;
+ }
-/* boolean prefHasUserValue (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::PrefHasUserValue(const char *aPrefName, PRBool *_retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
+ return NS_OK;
}
-/* boolean prefIsLocked (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::PrefIsLocked(const char *aPrefName, PRBool *_retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+/* BEGIN preference mapping definition area
+ *
+ * There are a few rules that our preference maps have to obey:
+ *
+ * 1) Each mapping defines a relationship R between a set of GConf preferences and
+ * a set of Mozilla preferences that must *always* be true. Thus, when a Mozilla
+ * pref changes or a gconf pref changes, we may need to change something on the
+ * other side to preserve R. If a GConf preference is read-only, then we may
+ * need to lock one or more Mozilla preferences to avoid a situation where the
+ * Mozilla preference changes and we can't update the GConf preference to
+ * ensure R continues to hold.
+ *
+ * 2) If an unlocked Mozilla preference is changed, then we can only
+ * preserve R by changing GConf preferences; we are not allowed to
+ * change Mozilla preferences.
+ *
+ * 3) If a GConf preference is changed, then we can only preserve R by
+ * changing Moozilla preferences; we are nt allowed to change GConf
+ * preferences.
+ *
+ * For "simple" mappings, the relationship R is just of the form
+ * "GConf preference 'A' is equal to Mozilla preference 'B'". R is
+ * preserved by setting A to B when B changes, and by setting B to A
+ * when A changes. If A is read-only then we lock B (or we may just
+ * decide to lock B for other reasons). Thus rules 1-3 are satisfied.
+ *
+ * For "complex" mappings we have more complicated
+ * relationships. These are documented below.
+ */
+
+static SimplePrefMapping sSimplePrefMappings[] = {
+ // GNOME proxy settings; allow these to be set through the Firefox UI
+ {"network.proxy.http", "/system/http_proxy/host", PR_TRUE},
+ {"network.proxy.http_port", "/system/http_proxy/port", PR_TRUE},
+ {"network.proxy.ftp", "/system/proxy/ftp_host", PR_TRUE},
+ {"network.proxy.ftp_port", "/system/proxy/ftp_port", PR_TRUE},
+ {"network.proxy.ssl", "/system/proxy/secure_host", PR_TRUE},
+ {"network.proxy.ssl_port", "/system/proxy/secure_port", PR_TRUE},
+ {"network.proxy.socks", "/system/proxy/socks_host", PR_TRUE},
+ {"network.proxy.socks_port", "/system/proxy/socks_port", PR_TRUE},
+ {"network.proxy.autoconfig_url", "/system/proxy/autoconfig_url", PR_TRUE},
+
+ // GNOME accessibility setting; never allow this to be set by Firefox
+ {"config.use_system_prefs.accessibility",
+ "/desktop/gnome/interface/accessibility", PR_FALSE},
+
+ // GConf Firefox preferences; allow these to be set through the Firefox UI
+ {"security.enable_java", "/apps/firefox/web/java_enabled", PR_TRUE},
+ {"javascript.enabled", "/apps/firefox/web/javascript_enabled", PR_TRUE},
+ {"browser.startup.homepage", "/apps/firefox/general/homepage_url", PR_TRUE},
+ {"browser.cache.disk.capacity", "/apps/firefox/web/cache_size", PR_TRUE},
+ {"network.cookie.lifetimePolicy", "/apps/firefox/web/cookie_accept", PR_TRUE},
+
+ // UI lockdown settings; never allow these to be set by Firefox. There is no
+ // Firefox UI for these but they could otherwise be set via about:config.
+ {"config.lockdown.printing", "/desktop/gnome/lockdown/disable_printing", PR_FALSE},
+ {"config.lockdown.printsetup", "/desktop/gnome/lockdown/disable_print_setup", PR_FALSE},
+ {"config.lockdown.savepage", "/desktop/gnome/lockdown/disable_save_to_disk", PR_FALSE},
+ {"config.lockdown.history", "/apps/firefox/lockdown/disable_history", PR_FALSE},
+ {"config.lockdown.toolbarediting", "/apps/firefox/lockdown/disable_toolbar_editing", PR_FALSE},
+ {"config.lockdown.urlbar", "/apps/firefox/lockdown/disable_url_bar", PR_FALSE},
+ {"config.lockdown.bookmark", "/apps/firefox/lockdown/disable_bookmark_editing", PR_FALSE},
+ {"config.lockdown.disable_themes", "/apps/firefox/lockdown/disable_themes", PR_FALSE},
+ {"config.lockdown.disable_extensions", "/apps/firefox/lockdown/disable_extensions", PR_FALSE},
+ {"config.lockdown.searchbar", "/apps/firefox/lockdown/disable_searchbar", PR_FALSE},
+ {"config.lockdown.hidebookmark", "/apps/firefox/lockdown/hide_bookmark", PR_FALSE},
+};
-/* void unlockPref (in string aPrefName); */
-NS_IMETHODIMP nsSystemPrefService::UnlockPref(const char *aPrefName)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
+static nsresult ApplyListPref(nsSystemPrefService* aPrefService,
+ GConfClient* aClient,
+ const char* aGConfKey, const char* aMozKey,
+ char aSeparator)
+{
+ GSList* list = gconf_client_get_list(aClient, aGConfKey,
+ GCONF_VALUE_STRING, nsnull);
+ nsCAutoString str;
+ for (GSList* l = list; l; l = l->next) {
+ str.Append((const char*)l->data);
+ if (l->next) {
+ str.Append(aSeparator);
+ }
+ }
+ PRBool lock = !gconf_client_key_is_writable(aClient, aGConfKey, nsnull);
+ nsresult rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaStringPref(aMozKey, str.get(), lock);
+ // XXX does this free the strings? Should it?
+ g_slist_free(list);
+ return rv;
+}
+static nsresult ReverseApplyListPref(nsSystemPrefService* aPrefService,
+ GConfClient* aClient,
+ const char* aGConfKey, const char* aMozKey,
+ char aSeparator)
+{
+ char* data = nsnull;
+ nsCOMPtr<nsIPrefBranch2> prefs =
+ aPrefService->GetPrefs()->GetPrefUserBranch();
+ prefs->GetCharPref(aMozKey, &data);
+ if (!data)
+ return NS_ERROR_FAILURE;
+ nsresult rv = NS_OK;
+ GSList* list = nsnull;
+ PRInt32 i = 0;
+ while (data[i]) {
+ const char* nextComma = strchr(data+i, ',');
+ PRInt32 tokLen = nextComma ? nextComma - (data+i) : strlen(data+i);
+ char* tok = strndup(data+i, tokLen);
+ if (!tok)
+ break;
+ GSList* newList = g_slist_append(list, tok);
+ if (!newList) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ list = newList;
+ if (!nextComma)
+ break;
+ i = nextComma + 1 - data;
+ }
+ nsMemory::Free(data);
+ if (NS_SUCCEEDED(rv)) {
+ gconf_client_set_list(aClient, aGConfKey, GCONF_VALUE_STRING, list, nsnull);
+ }
+ for (GSList* l = list; l; l = l->next) {
+ free(l->data);
+ }
+ g_slist_free(list);
+ return rv;
}
-/* void deleteBranch (in string aStartingAt); */
-NS_IMETHODIMP nsSystemPrefService::DeleteBranch(const char *aStartingAt)
+/**
+ * The relationship R is
+ * "network.negotiate-auth.trusted-uris" is the comma-separated concatenation
+ * of the elements of the list "/apps/firefox/general/trusted_URIs"
+ */
+static const char GConfKey_TrustedURIs[] = "/apps/firefox/general/trusted_URIs";
+static const char MozKey_TrustedURIs[] = "network.negotiate-auth.trusted-uris";
+static nsresult ApplyTrustedURIs(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ return ApplyListPref(aPrefService, aClient,
+ GConfKey_TrustedURIs, MozKey_TrustedURIs, ',');
+}
+static nsresult ReverseApplyTrustedURIs(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ return ReverseApplyListPref(aPrefService, aClient,
+ GConfKey_TrustedURIs, MozKey_TrustedURIs, ',');
+}
+
+/**
+ * The relationship R is
+ * "network.negotiate-auth.delegation-uris" is the comma-separated concatenation
+ * of the elements of the list "/apps/firefox/general/delegation_URIs"
+ */
+static const char GConfKey_DelegationURIs[] = "/apps/firefox/general/delegation_URIs";
+static const char MozKey_DelegationURIs[] = "network.negotiate-auth.delegation-uris";
+static nsresult ApplyDelegationURIs(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ return ApplyListPref(aPrefService, aClient,
+ GConfKey_DelegationURIs, MozKey_DelegationURIs, ',');
+}
+static nsresult ReverseApplyDelegationURIs(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ return ReverseApplyListPref(aPrefService, aClient,
+ GConfKey_DelegationURIs, MozKey_DelegationURIs, ',');
+}
+
+/**
+ * The relationship R is
+ * "network.proxy.no_proxies_on" is the comma-separated concatenation
+ * of the elements of the list "/system/http_proxy/ignore_hosts"
+ */
+static const char GConfKey_IgnoreHosts[] = "/system/http_proxy/ignore_hosts";
+static const char MozKey_IgnoreHosts[] = "network.proxy.no_proxies_on";
+static nsresult ApplyIgnoreHosts(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ return ApplyListPref(aPrefService, aClient,
+ GConfKey_IgnoreHosts, MozKey_IgnoreHosts, ',');
+}
+static nsresult ReverseApplyIgnoreHosts(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ return ReverseApplyListPref(aPrefService, aClient,
+ GConfKey_IgnoreHosts, MozKey_IgnoreHosts, ',');
+}
+
+/**
+ * The relationship R is
+ * ("/system/proxy/mode" is 'manual' if and only if "network.proxy.type" is eProxyConfig_Manual (1))
+ * AND ("/system/proxy/mode" is 'auto' if and only if "network.proxy.type" is eProxyConfig_PAC (2))
+ *
+ * [This means 'none' matches any value of "network.proxy.type" other than 1 or 2.]
+ */
+static const char GConfKey_ProxyMode[] = "/system/proxy/mode";
+static const char MozKey_ProxyMode[] = "network.proxy.type";
+static nsresult ApplyProxyMode(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
{
- return NS_ERROR_NOT_IMPLEMENTED;
+ char* str = gconf_client_get_string(aClient, GConfKey_ProxyMode, nsnull);
+ if (!str)
+ return NS_ERROR_FAILURE;
+ PRInt32 val = -1;
+ nsCOMPtr<nsIPrefBranch2> prefs =
+ aPrefService->GetPrefs()->GetPrefUserBranch();
+ prefs->GetIntPref(MozKey_ProxyMode, &val);
+ if (val < 0)
+ return NS_ERROR_FAILURE;
+ if (!strcmp(str, "manual")) {
+ val = 1;
+ } else if (!strcmp(str, "auto")) {
+ val = 2;
+ } else if (strcmp(str, "none")) {
+ // invalid value for this gconf pref; do nothing
+ g_free(str);
+ return NS_OK;
+ } else {
+ if (val == 1 || val == 2) {
+ // We need to make it something that 'none' maps to
+ val = 0;
+ }
+ }
+ g_free(str);
+ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_ProxyMode, nsnull);
+ nsresult rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaIntPref(MozKey_ProxyMode, val, lock);
+ return rv;
+}
+static nsresult ReverseApplyProxyMode(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ PRInt32 val = -1;
+ nsCOMPtr<nsIPrefBranch2> prefs =
+ aPrefService->GetPrefs()->GetPrefUserBranch();
+ prefs->GetIntPref(MozKey_ProxyMode, &val);
+ if (val < 0)
+ return NS_ERROR_FAILURE;
+ const char* str;
+ switch (val) {
+ case 1: str = "manual"; break;
+ case 2: str = "auto"; break;
+ default: str = "none"; break;
+ }
+ gconf_client_set_string(aClient, GConfKey_ProxyMode, str, nsnull);
+ return NS_OK;
}
-/* void getChildList (in string aStartingAt, out unsigned long aCount, [array, size_is (aCount), retval] out string aChildArray); */
-NS_IMETHODIMP nsSystemPrefService::GetChildList(const char *aStartingAt, PRUint32 *aCount, char ***aChildArray)
+/**
+ * The relationship R is
+ * If "/apps/firefox/web/download_defaultfolder" is the empty string, then
+ * "browser.download.useDownloadDir" is false;
+ * otherwise "browser.download.useDownloadDir" is true and "browser.download.folderList"
+ * is (0 if "/apps/firefox/web/download_defaultfolder" is "Desktop";
+ * 1 if "/apps/firefox/web/download_defaultfolder" is "My Downloads";
+ * 3 if "/apps/firefox/web/download_defaultfolder" is "Home";
+ * otherwise 2 and "browser.download.dir" = "/apps/firefox/web/download_defaultfolder")
+ */
+static const char GConfKey_DownloadFolder[] = "/apps/firefox/web/download_defaultfolder";
+static const char MozKey_UseDownloadDir[] = "browser.download.useDownloadDir";
+static const char MozKey_DownloadDirType[] = "browser.download.folderList";
+static const char MozKey_DownloadDirExplicit[] = "browser.download.dir";
+static nsresult ApplyDownloadFolder(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
{
- return NS_ERROR_NOT_IMPLEMENTED;
+ char* str = gconf_client_get_string(aClient, GConfKey_DownloadFolder, nsnull);
+ if (!str)
+ return NS_ERROR_FAILURE;
+ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DownloadFolder, nsnull);
+ nsresult rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_UseDownloadDir, *str != 0, lock);
+ if (NS_FAILED(rv)) {
+ g_free(str);
+ return rv;
+ }
+ PRInt32 dirType = 0;
+ if (!strcmp(str, "Desktop")) {
+ dirType = 0;
+ } else if (!strcmp(str, "My Downloads")) {
+ dirType = 1;
+ } else if (!strcmp(str, "Home")) {
+ dirType = 3;
+ } else {
+ dirType = 2;
+ }
+ // Always set all three Mozilla preferences. This is simpler and avoids
+ // problems; e.g., if the gconf value changes from "/home/rocallahan" to "Desktop"
+ // we might leave MozKey_DownloadDirType accidentally locked.
+ rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaIntPref(MozKey_DownloadDirType, dirType, lock);
+ if (NS_SUCCEEDED(rv)) {
+ rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaStringPref(MozKey_DownloadDirExplicit, str, lock);
+ }
+ g_free(str);
+ return rv;
}
-/* void resetBranch (in string aStartingAt); */
-NS_IMETHODIMP nsSystemPrefService::ResetBranch(const char *aStartingAt)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
+static nsresult ReverseApplyDownloadFolder(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ PRBool useDownloadDir = PR_FALSE;
+ const char* result;
+ char* explicitStr = nsnull;
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ prefs->GetBoolPref(MozKey_UseDownloadDir, &useDownloadDir);
+ if (!useDownloadDir) {
+ result = "";
+ } else {
+ PRInt32 type = -1;
+ prefs->GetIntPref(MozKey_DownloadDirType, &type);
+ if (type < 0)
+ return NS_ERROR_FAILURE;
+ switch (type) {
+ case 0: result = "Desktop"; break;
+ case 1: result = "My Downloads"; break;
+ case 2:
+ prefs->GetCharPref(MozKey_DownloadDirExplicit, &explicitStr);
+ result = explicitStr;
+ break;
+ case 3: result = "Home"; break;
+ default:
+ NS_ERROR("Unknown download dir type");
+ return NS_ERROR_FAILURE;
+ }
+ }
+ if (!result)
+ return NS_ERROR_FAILURE;
+ gconf_client_set_string(aClient, GConfKey_DownloadFolder,
+ result, nsnull);
+ nsMemory::Free(explicitStr);
+ return NS_OK;
}
-/* void addObserver (in string aDomain, in nsIObserver aObserver, in boolean aHoldWeak); */
-NS_IMETHODIMP nsSystemPrefService::AddObserver(const char *aDomain, nsIObserver *aObserver, PRBool aHoldWeak)
-{
- nsresult rv;
-
- NS_ENSURE_ARG_POINTER(aDomain);
- NS_ENSURE_ARG_POINTER(aObserver);
-
- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
-
- PRUint32 prefAtom;
- // make sure the pref name is supported
- rv = mGConf->GetAtomForMozKey(aDomain, &prefAtom);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!mObservers) {
- mObservers = new nsAutoVoidArray();
- if (mObservers == nsnull)
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- SysPrefCallbackData *pCallbackData = (SysPrefCallbackData *)
- nsMemory::Alloc(sizeof(SysPrefCallbackData));
- if (pCallbackData == nsnull)
- return NS_ERROR_OUT_OF_MEMORY;
-
- pCallbackData->bIsWeakRef = aHoldWeak;
- pCallbackData->prefAtom = prefAtom;
- // hold a weak reference to the observer if so requested
- nsCOMPtr<nsISupports> observerRef;
- if (aHoldWeak) {
- nsCOMPtr<nsISupportsWeakReference> weakRefFactory =
- do_QueryInterface(aObserver);
- if (!weakRefFactory) {
- // the caller didn't give us a object that supports weak reference.
- // ... tell them
- nsMemory::Free(pCallbackData);
- return NS_ERROR_INVALID_ARG;
- }
- nsCOMPtr<nsIWeakReference> tmp = do_GetWeakReference(weakRefFactory);
- observerRef = tmp;
+/**
+ * The relationship R is
+ * "/apps/firefox/web/disable_cookies" is true if and only if
+ * "network.cookie.cookieBehavior" is 2 ('dontUse')
+ */
+static const char GConfKey_DisableCookies[] = "/apps/firefox/web/disable_cookies";
+static const char MozKey_CookieBehavior[] = "network.cookie.cookieBehavior";
+static const char MozKey_CookieExceptions[] = "network.cookie.honorExceptions";
+static const char MozKey_CookieViewExceptions[] = "pref.privacy.disable_button.cookie_exceptions";
+static nsresult ApplyDisableCookies(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableCookies, nsnull);
+ PRInt32 behavior = -1;
+ nsCOMPtr<nsIPrefBranch2> prefs =
+ aPrefService->GetPrefs()->GetPrefUserBranch();
+ prefs->GetIntPref(MozKey_CookieBehavior, &behavior);
+ if (behavior < 0)
+ return NS_ERROR_FAILURE;
+ if (disable) {
+ behavior = 2;
} else {
- observerRef = aObserver;
+ if (behavior == 2) {
+ behavior = 0;
+ }
}
+ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableCookies, nsnull);
+ nsresult rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_CookieExceptions, !lock, lock);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_CookieViewExceptions, lock, lock);
+ if (NS_FAILED(rv))
+ return rv;
+ return aPrefService->GetPrefs()->
+ SetOverridingMozillaIntPref(MozKey_CookieBehavior, behavior, lock);
+}
+static nsresult ReverseApplyDisableCookies(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ PRInt32 behavior = -1;
+ nsCOMPtr<nsIPrefBranch2> prefs =
+ aPrefService->GetPrefs()->GetPrefUserBranch();
+ prefs->GetIntPref(MozKey_CookieBehavior, &behavior);
+ if (behavior < 0)
+ return NS_ERROR_FAILURE;
+ gconf_client_set_bool(aClient, GConfKey_DisableCookies, behavior == 2, nsnull);
+ return NS_OK;
+}
- rv = mGConf->NotifyAdd(prefAtom, pCallbackData);
- if (NS_FAILED(rv)) {
- nsMemory::Free(pCallbackData);
- return rv;
+static char const* windowOpenFeatures[] = {
+ "dom.disable_window_open_feature.close",
+ "dom.disable_window_open_feature.directories",
+ "dom.disable_window_open_feature.location",
+ "dom.disable_window_open_feature.menubar",
+ "dom.disable_window_open_feature.minimizable",
+ "dom.disable_window_open_feature.personalbar",
+ "dom.disable_window_open_feature.resizable",
+ "dom.disable_window_open_feature.scrollbars",
+ "dom.disable_window_open_feature.status",
+ "dom.disable_window_open_feature.titlebar",
+ "dom.disable_window_open_feature.toolbar"
+};
+/**
+ * The relationship R is
+ * "/apps/firefox/lockdown/disable_javascript_chrome" is true if and only if
+ * all of windowOpenFeatures are true
+ */
+static const char GConfKey_DisableJSChrome[] =
+ "/apps/firefox/lockdown/disable_javascript_chrome";
+static nsresult ApplyWindowOpen(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableJSChrome, nsnull);
+ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableJSChrome, nsnull);
+ PRBool curValues[NUM_ELEM(windowOpenFeatures)];
+ PRUint32 i;
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ PRBool allDisabled = PR_TRUE;
+ for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
+ nsresult rv = prefs->GetBoolPref(windowOpenFeatures[i], &curValues[i]);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!curValues[i]) {
+ allDisabled = PR_FALSE;
+ }
+ }
+ for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
+ PRBool newVal = curValues[i];
+ if (disable) {
+ newVal = PR_TRUE;
+ } else if (allDisabled) {
+ // If all disable-window-open-feature prefs are currently
+ // PR_TRUE, then we need to set at least one of them to
+ // PR_FALSE. Set all of them to PR_FALSE.
+ newVal = PR_FALSE;
+ } // If at least one disable-window-open-feature pref is
+ // currently PR_FALSE, then we don't need to change anything
+ // when the gconf pref says don't disable
+ nsresult rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(windowOpenFeatures[i], newVal, lock);
+ if (NS_FAILED(rv))
+ return rv;
}
-
- pCallbackData->observer = observerRef;
- NS_ADDREF(pCallbackData->observer);
-
- mObservers->AppendElement(pCallbackData);
return NS_OK;
}
-/* void removeObserver (in string aDomain, in nsIObserver aObserver); */
-NS_IMETHODIMP nsSystemPrefService::RemoveObserver(const char *aDomain, nsIObserver *aObserver)
+static nsresult ReverseApplyWindowOpen(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
{
- nsresult rv;
-
- NS_ENSURE_ARG_POINTER(aDomain);
- NS_ENSURE_ARG_POINTER(aObserver);
- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
-
- if (!mObservers)
- return NS_OK;
-
- PRUint32 prefAtom;
- // make sure the pref name is supported
- rv = mGConf->GetAtomForMozKey(aDomain, &prefAtom);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // need to find the index of observer, so we can remove it
- PRIntn count = mObservers->Count();
- if (count <= 0)
- return NS_OK;
-
- PRIntn i;
- SysPrefCallbackData *pCallbackData;
- for (i = 0; i < count; ++i) {
- pCallbackData = (SysPrefCallbackData *)mObservers->ElementAt(i);
- if (pCallbackData) {
- nsCOMPtr<nsISupports> observerRef;
- if (pCallbackData->bIsWeakRef) {
- nsCOMPtr<nsISupportsWeakReference> weakRefFactory =
- do_QueryInterface(aObserver);
- if (weakRefFactory) {
- nsCOMPtr<nsIWeakReference> tmp =
- do_GetWeakReference(aObserver);
- observerRef = tmp;
- }
- }
- if (!observerRef)
- observerRef = aObserver;
-
- if (pCallbackData->observer == observerRef &&
- pCallbackData->prefAtom == prefAtom) {
- rv = mGConf->NotifyRemove(prefAtom, pCallbackData);
- if (NS_SUCCEEDED(rv)) {
- mObservers->RemoveElementAt(i);
- NS_RELEASE(pCallbackData->observer);
- nsMemory::Free(pCallbackData);
- }
- return rv;
- }
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ PRBool allDisabled = PR_TRUE;
+ PRBool curValues[NUM_ELEM(windowOpenFeatures)];
+ for (PRUint32 i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
+ nsresult rv = prefs->GetBoolPref(windowOpenFeatures[i], &curValues[i]);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!curValues[i]) {
+ allDisabled = PR_FALSE;
}
}
+ gconf_client_set_bool(aClient, GConfKey_DisableJSChrome, allDisabled, nsnull);
return NS_OK;
}
-void
-nsSystemPrefService::OnPrefChange(PRUint32 aPrefAtom, void *aData)
-{
- if (!mInitialized)
- return;
-
- SysPrefCallbackData *pData = (SysPrefCallbackData *)aData;
- if (pData->prefAtom != aPrefAtom)
- return;
-
- nsCOMPtr<nsIObserver> observer;
- if (pData->bIsWeakRef) {
- nsCOMPtr<nsIWeakReference> weakRef =
- do_QueryInterface(pData->observer);
- if(weakRef)
- observer = do_QueryReferent(weakRef);
- if (!observer) {
- // this weak referenced observer went away, remove it from the list
- nsresult rv = mGConf->NotifyRemove(aPrefAtom, pData);
- if (NS_SUCCEEDED(rv)) {
- mObservers->RemoveElement(pData);
- NS_RELEASE(pData->observer);
- nsMemory::Free(pData);
- }
- return;
+/**
+ * The relationship R is
+ * If "/apps/firefox/lockdown/disable_unsafe_protocol" is true then
+ * -- "network.protocol-handler.blocked-default" is true
+ * -- "network.protocol-handler.blocked.XYZ" is false if and only if
+ * XYZ is a builtin non-disablable protocol or in
+ * "/apps/firefox/lockdown/additional_safe_protocols"
+ * AND if "/apps/firefox/lockdown/disable_unsafe_protocol" is false then
+ * -- "network.protocol-handler.blocked-default" is false
+ * -- if "network.protocol-handler.blocked.XYZ" exists then it is false
+ */
+static const char GConfKey_DisableUnsafeProtocols[] =
+ "/apps/firefox/lockdown/disable_unsafe_protocol";
+static const char GConfKey_AdditionalSafeProtocols[] =
+ "/apps/firefox/lockdown/additional_safe_protocols";
+static const char MozKey_BlockedDefault[] =
+ "network.protocol-handler.blocked-default";
+static const char MozKey_BlockedPrefix[] =
+ "network.protocol-handler.blocked.";
+static const char* nonDisablableBuiltinProtocols[] =
+ { "about", "data", "jar", "keyword", "resource", "viewsource",
+ "chrome", "moz-icon", "javascript", "file" };
+static PRBool FindString(const char** aList, PRInt32 aCount,
+ const char* aStr)
+{
+ for (PRInt32 i = 0; i < aCount; ++i) {
+ if (!strcmp(aStr, aList[i]))
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+typedef nsDataHashtable<nsCStringHashKey,int> StringSet;
+/** Collect the set of protocol names that we want to set preferences for */
+static nsresult AddAllProtocols(nsSystemPrefService* aPrefService,
+ const char* aSafeProtocols,
+ StringSet* aProtocolSet,
+ StringSet* aSafeSet)
+{
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ PRUint32 childCount;
+ char **childArray = nsnull;
+ nsresult rv = prefs->GetChildList(MozKey_BlockedPrefix, &childCount, &childArray);
+ if (NS_FAILED(rv))
+ return rv;
+ PRUint32 i;
+ for (i = 0; i < childCount; ++i) {
+ nsDependentCString tmp(childArray[i] + NUM_ELEM(MozKey_BlockedPrefix)-1);
+ aProtocolSet->Put(tmp, 1); // copies
+ }
+ for (i = 0; i < NUM_ELEM(nonDisablableBuiltinProtocols); ++i) {
+ nsDependentCString tmp(nonDisablableBuiltinProtocols[i]);
+ aProtocolSet->Put(tmp, 1);
+ }
+ i = 0;
+ while (aSafeProtocols[i]) {
+ const char* nextComma = strchr(aSafeProtocols+i, ',');
+ PRUint32 tokLen = nextComma ? nextComma - (aSafeProtocols+i)
+ : strlen(aSafeProtocols+i);
+ nsCAutoString tok(aSafeProtocols+i, tokLen);
+ aProtocolSet->Put(tok, 1);
+ aSafeSet->Put(tok, 1);
+ if (nextComma) {
+ i = nextComma - aSafeProtocols + 1;
+ } else {
+ break;
}
}
- else
- observer = do_QueryInterface(pData->observer);
-
- if (observer)
- observer->Observe(NS_STATIC_CAST(nsIPrefBranch *, this),
- NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID,
- NS_ConvertUTF8toUCS2(mGConf->GetMozKey(aPrefAtom)).
- get());
+ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
+ return NS_OK;
}
-/*************************************************************
- * GConfProxy
- *
- ************************************************************/
-
-struct GConfFuncListType {
- const char *FuncName;
- PRFuncPtr FuncPtr;
-};
-
-struct PrefNamePair {
- const char *mozPrefName;
- const char *gconfPrefName;
-};
-
-const char
-GConfProxy::sPrefGConfKey[] = "accessibility.unix.gconf2.shared-library";
-const char GConfProxy::sDefaultLibName1[] = "libgconf-2.so.4";
-const char GConfProxy::sDefaultLibName2[] = "libgconf-2.so";
-
-#define GCONF_FUNCS_POINTER_BEGIN \
- static GConfFuncListType sGConfFuncList[] = {
-#define GCONF_FUNCS_POINTER_ADD(func_name) \
- {func_name, nsnull},
-#define GCONF_FUNCS_POINTER_END \
- {nsnull, nsnull}, };
-
-GCONF_FUNCS_POINTER_BEGIN
- GCONF_FUNCS_POINTER_ADD("gconf_client_get_default") // 0
- GCONF_FUNCS_POINTER_ADD("gconf_client_get_bool") // 1
- GCONF_FUNCS_POINTER_ADD("gconf_client_get_string") //2
- GCONF_FUNCS_POINTER_ADD("gconf_client_get_int") //3
- GCONF_FUNCS_POINTER_ADD("gconf_client_notify_add") //4
- GCONF_FUNCS_POINTER_ADD("gconf_client_notify_remove") //5
- GCONF_FUNCS_POINTER_ADD("gconf_client_add_dir") //6
- GCONF_FUNCS_POINTER_ADD("gconf_client_remove_dir") //7
- GCONF_FUNCS_POINTER_ADD("gconf_entry_get_value") //8
- GCONF_FUNCS_POINTER_ADD("gconf_entry_get_key") //9
- GCONF_FUNCS_POINTER_ADD("gconf_value_get_bool") //10
- GCONF_FUNCS_POINTER_ADD("gconf_value_get_string") //11
- GCONF_FUNCS_POINTER_ADD("gconf_value_get_int") //12
-GCONF_FUNCS_POINTER_END
-
-/////////////////////////////////////////////////////////////////////////////
-// the list is the mapping table, between mozilla prefs and gconf prefs
-// It is expected to include all the pref pairs that are related in mozilla
-// and gconf.
-//
-// Note: the prefs listed here are not neccessarily be read from gconf, they
-// are the prefs that could be read from gconf. Mozilla has another
-// list (see sSysPrefList in nsSystemPref.cpp) that decide which prefs
-// are really read.
-//////////////////////////////////////////////////////////////////////////////
-
-static const PrefNamePair sPrefNameMapping[] = {
-#include "gconf_pref_list.inc"
- {nsnull, nsnull},
+struct ProtocolPrefClosure {
+ StringSet safeProtocolSet;
+ nsIPrefBranch2* prefs;
+ nsISystemPref* prefSetter;
+ PRPackedBool disableUnsafe;
+ PRPackedBool lock;
};
-PRBool PR_CALLBACK
-gconfDeleteObserver(void *aElement, void *aData) {
- nsMemory::Free(aElement);
- return PR_TRUE;
+static PLDHashOperator PR_CALLBACK SetProtocolPref(const nsACString& aKey,
+ int aItem,
+ void* aClosure)
+{
+ ProtocolPrefClosure* closure = NS_STATIC_CAST(ProtocolPrefClosure*, aClosure);
+ const nsCString& protocol = PromiseFlatCString(aKey);
+ PRBool blockProtocol = PR_FALSE;
+ if (closure->disableUnsafe &&
+ !FindString(nonDisablableBuiltinProtocols,
+ NUM_ELEM(nonDisablableBuiltinProtocols), protocol.get()) &&
+ !closure->safeProtocolSet.Get(aKey, nsnull)) {
+ blockProtocol = PR_TRUE;
+ }
+
+ nsCAutoString prefName;
+ prefName.Append(MozKey_BlockedPrefix);
+ prefName.Append(protocol);
+ closure->prefSetter->SetOverridingMozillaBoolPref(prefName.get(), blockProtocol,
+ closure->lock);
+ return PL_DHASH_NEXT;
+}
+static nsresult ApplyUnsafeProtocols(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableUnsafeProtocols, nsnull)
+ || !gconf_client_key_is_writable(aClient, GConfKey_AdditionalSafeProtocols, nsnull);
+ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableUnsafeProtocols, nsnull);
+ char* protocols = gconf_client_get_string(aClient, GConfKey_AdditionalSafeProtocols, nsnull);
+ if (!protocols)
+ return NS_ERROR_FAILURE;
+ nsresult rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_BlockedDefault, disable, lock);
+ StringSet protocolSet;
+ ProtocolPrefClosure closure;
+ protocolSet.Init();
+ closure.safeProtocolSet.Init();
+ if (NS_SUCCEEDED(rv)) {
+ rv = AddAllProtocols(aPrefService, protocols, &protocolSet,
+ &closure.safeProtocolSet);
+ }
+ if (NS_SUCCEEDED(rv)) {
+ closure.disableUnsafe = disable;
+ closure.lock = lock;
+ closure.prefSetter = aPrefService->GetPrefs();
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ closure.prefs = prefs;
+ protocolSet.EnumerateRead(SetProtocolPref, &closure);
+ }
+ g_free(protocols);
+ return rv;
+}
+
+static nsresult ReverseApplyUnsafeProtocols(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ PRBool blockedDefault;
+ nsresult rv = prefs->GetBoolPref(MozKey_BlockedDefault, &blockedDefault);
+ if (NS_FAILED(rv))
+ return rv;
+ nsCAutoString enabledProtocols;
+ PRUint32 childCount;
+ char **childArray = nsnull;
+ rv = prefs->GetChildList(MozKey_BlockedPrefix, &childCount, &childArray);
+ if (NS_FAILED(rv))
+ return rv;
+ for (PRUint32 i = 0; i < childCount; ++i) {
+ PRBool val = PR_FALSE;
+ prefs->GetBoolPref(childArray[i], &val);
+ if (val) {
+ if (enabledProtocols.Length() > 0) {
+ enabledProtocols.Append(',');
+ }
+ enabledProtocols.Append(childArray[i] + NUM_ELEM(MozKey_BlockedPrefix)-1);
+ }
+ }
+ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
+ gconf_client_set_bool(aClient, GConfKey_DisableUnsafeProtocols, blockedDefault, nsnull);
+ gconf_client_set_string(aClient, GConfKey_AdditionalSafeProtocols,
+ enabledProtocols.get(), nsnull);
+ return NS_OK;
}
-GConfProxy::GConfProxy(nsSystemPrefService *aSysPrefService):
- mGConfClient(nsnull),
- mGConfLib(nsnull),
- mInitialized(PR_FALSE),
- mSysPrefService(aSysPrefService),
- mObservers(nsnull)
-{
+/**
+ * Set config.lockdown.setwallpaper if and only if
+ * /desktop/gnome/background/picture_filename is write-only. Always
+ * lock it.
+ */
+static const char MozKey_LockdownWallpaper[] = "config.lockdown.setwallpaper";
+static const char GConfKey_WallpaperSetting[] =
+ "/desktop/gnome/background/picture_filename";
+static nsresult ApplyWallpaper(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ PRBool canSetWallpaper =
+ gconf_client_key_is_writable(aClient, GConfKey_WallpaperSetting, nsnull);
+ return aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_LockdownWallpaper,
+ !canSetWallpaper, PR_TRUE);
+}
+// No ReverseApplyWallpaper because this Mozilla pref can never be
+// modified
+
+/**
+ * The relationship R is
+ * "signon.rememberSignons" is true if and only if "/apps/firefox/web/disable_save_password"
+ * is false.
+ */
+static const char MozKey_RememberSignons[] = "signon.rememberSignons";
+static const char GConfKey_DisableSavePassword[] = "/apps/firefox/web/disable_save_password";
+static nsresult ApplyDisableSavePassword(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableSavePassword, nsnull);
+ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableSavePassword, nsnull);
+ return aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_RememberSignons, !disable, lock);
+}
+
+static nsresult ReverseApplyDisableSavePassword(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ PRBool remember;
+ nsresult rv = prefs->GetBoolPref(MozKey_RememberSignons, &remember);
+ if (NS_FAILED(rv))
+ return rv;
+ gconf_client_set_bool(aClient, GConfKey_DisableSavePassword, !remember, nsnull);
+ return NS_OK;
}
-GConfProxy::~GConfProxy()
-{
- if (mGConfClient)
- g_object_unref(G_OBJECT(mGConfClient));
-
- if (mObservers) {
- (void)mObservers->EnumerateForwards(gconfDeleteObserver, nsnull);
- delete mObservers;
+/**
+ * The relationship R is
+ * "permissions.default.image" is 1 (nsIPermissionManager::ALLOW_ACTION) if and only if
+ * "/apps/firefox/web/images_load" is 0, AND
+ * "permissions.default.image" is 2 (nsIPermissionManager::DENY_ACTION) if and only if
+ * "/apps/firefox/web/images_load" is 2, AND
+ * "permissions.default.image" is 3 if and only if "/apps/firefox/web/images_load" is 1
+ *
+ * Also, we set pref.advanced.images.disable_button.view_image iff
+ * /apps/firefox/web/images_load is read-only
+ * And we set permissions.default.honorExceptions iff
+ * /apps/firefox/web/images_load is not read-only
+ */
+static const char MozKey_ImagePermissions[] = "permissions.default.image";
+static const char MozKey_ImageExceptions[] = "permissions.honorExceptions.image";
+static const char MozKey_ImageViewExceptions[] = "pref.advanced.images.disable_button.view_image";
+static const char GConfKey_LoadImages[] = "/apps/firefox/web/images_load";
+static nsresult ApplyLoadImages(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_LoadImages, nsnull);
+ // 0 == accept, 1 == no-foreign, 2 == reject
+ gint setting = gconf_client_get_int(aClient, GConfKey_LoadImages, nsnull);
+ PRInt32 pref;
+ switch (setting) {
+ case 0: pref = nsIPermissionManager::ALLOW_ACTION; break;
+ case 2: pref = nsIPermissionManager::DENY_ACTION; break;
+ case 1: pref = 3; break;
+ default: return NS_ERROR_FAILURE;
}
+ nsresult rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_ImageExceptions, !lock, lock);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_ImageViewExceptions, lock, lock);
+ if (NS_FAILED(rv))
+ return rv;
+ return aPrefService->GetPrefs()->
+ SetOverridingMozillaIntPref(MozKey_ImagePermissions, pref, lock);
}
-PRBool
-GConfProxy::Init()
+static nsresult ReverseApplyLoadImages(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
{
- SYSPREF_LOG(("GConfProxy:: Init GConfProxy\n"));
- if (!mSysPrefService)
- return PR_FALSE;
- if (mInitialized)
- return PR_TRUE;
-
- nsCOMPtr<nsIPref> pref = do_GetService(NS_PREF_CONTRACTID);
- if (!pref)
- return PR_FALSE;
-
- nsXPIDLCString gconfLibName;
- nsresult rv;
-
- //check if gconf-2 library is given in prefs
- rv = pref->GetCharPref(sPrefGConfKey, getter_Copies(gconfLibName));
- if (NS_SUCCEEDED(rv)) {
- //use the library name in the preference
- SYSPREF_LOG(("GConf library in prefs is %s\n", gconfLibName.get()));
- mGConfLib = PR_LoadLibrary(gconfLibName.get());
- }
- else {
- SYSPREF_LOG(("GConf library not specified in prefs, try the default: "
- "%s and %s\n", sDefaultLibName1, sDefaultLibName2));
- mGConfLib = PR_LoadLibrary(sDefaultLibName1);
- if (!mGConfLib)
- mGConfLib = PR_LoadLibrary(sDefaultLibName2);
- }
-
- if (!mGConfLib) {
- SYSPREF_LOG(("Fail to load GConf library\n"));
- return PR_FALSE;
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ PRInt32 pref;
+ nsresult rv = prefs->GetIntPref(MozKey_ImagePermissions, &pref);
+ if (NS_FAILED(rv))
+ return rv;
+ gint setting;
+ switch (pref) {
+ case nsIPermissionManager::ALLOW_ACTION: setting = 0; break;
+ case nsIPermissionManager::DENY_ACTION: setting = 2; break;
+ case 3: setting = 1; break;
+ default: return NS_ERROR_FAILURE;
}
+ gconf_client_set_int(aClient, GConfKey_LoadImages, setting, nsnull);
+ return NS_OK;
+}
- //check every func we need in the gconf library
- GConfFuncListType *funcList;
- PRFuncPtr func;
- for (funcList = sGConfFuncList; funcList->FuncName; ++funcList) {
- func = PR_FindFunctionSymbol(mGConfLib, funcList->FuncName);
- if (!func) {
- SYSPREF_LOG(("Check GConf Func Error: %s", funcList->FuncName));
- goto init_failed_unload;
+/**
+ * The relationship R is
+ * "/apps/firefox/web/disable_popups" is true if and only if
+ * "dom.disable_open_during_load" is true
+ * AND if "/apps/firefox/web/disable_popups" is true then
+ * "privacy.popups.showBrowserMessage" is false.
+ */
+static const char MozKey_DisablePopups[] = "dom.disable_open_during_load";
+static const char MozKey_DisableBrowserPopupMessage[] = "privacy.popups.showBrowserMessage";
+static const char GConfKey_DisablePopups[] = "/apps/firefox/web/disable_popups";
+static nsresult ApplyDisablePopups(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
+{
+ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisablePopups, nsnull);
+ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisablePopups, nsnull);
+ nsresult rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_DisablePopups, disable, lock);
+ if (NS_SUCCEEDED(rv)) {
+ if (disable) {
+ rv = aPrefService->GetPrefs()->
+ SetOverridingMozillaBoolPref(MozKey_DisableBrowserPopupMessage, PR_TRUE, lock);
+ } else {
+ rv = aPrefService->GetPrefs()->
+ StopOverridingMozillaPref(MozKey_DisableBrowserPopupMessage);
}
- funcList->FuncPtr = func;
}
-
- InitFuncPtrs();
-
- mGConfClient = GConfClientGetDefault();
-
- // Don't unload past this point, since GConf's initialization of ORBit
- // causes atexit handlers to be registered.
-
- if (!mGConfClient) {
- SYSPREF_LOG(("Fail to Get default gconf client\n"));
- goto init_failed;
- }
- mInitialized = PR_TRUE;
- return PR_TRUE;
-
- init_failed_unload:
- PR_UnloadLibrary(mGConfLib);
- init_failed:
- mGConfLib = nsnull;
- return PR_FALSE;
+ return rv;
}
-nsresult
-GConfProxy::GetBoolPref(const char *aMozKey, PRBool *retval)
+static nsresult ReverseApplyDisablePopups(nsSystemPrefService* aPrefService,
+ GConfClient* aClient)
{
- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
- *retval = GConfClientGetBool(mGConfClient, MozKey2GConfKey(aMozKey), NULL);
+ nsCOMPtr<nsIPrefBranch2> prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
+ PRBool disabled;
+ nsresult rv = prefs->GetBoolPref(MozKey_DisablePopups, &disabled);
+ if (NS_FAILED(rv))
+ return rv;
+ gconf_client_set_bool(aClient, GConfKey_DisablePopups, disabled, nsnull);
return NS_OK;
}
-nsresult
-GConfProxy::GetCharPref(const char *aMozKey, char **retval)
-{
- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+static ComplexGConfPrefMapping sComplexGConfPrefMappings[] = {
+ {GConfKey_TrustedURIs, ApplyTrustedURIs},
+ {GConfKey_DelegationURIs, ApplyDelegationURIs},
+ {GConfKey_IgnoreHosts, ApplyIgnoreHosts},
+ {GConfKey_ProxyMode, ApplyProxyMode},
+ {GConfKey_DownloadFolder, ApplyDownloadFolder},
+ {GConfKey_DisableCookies, ApplyDisableCookies},
+ {GConfKey_DisableJSChrome, ApplyWindowOpen},
+ {GConfKey_DisableUnsafeProtocols, ApplyUnsafeProtocols},
+ {GConfKey_AdditionalSafeProtocols, ApplyUnsafeProtocols},
+ {GConfKey_WallpaperSetting, ApplyWallpaper},
+ {GConfKey_DisableSavePassword, ApplyDisableSavePassword},
+ {GConfKey_LoadImages, ApplyLoadImages},
+ {GConfKey_DisablePopups, ApplyDisablePopups}
+};
+static ComplexMozPrefMapping sComplexMozPrefMappings[] = {
+ {MozKey_TrustedURIs, ReverseApplyTrustedURIs},
+ {MozKey_DelegationURIs, ReverseApplyDelegationURIs},
+ {MozKey_IgnoreHosts, ReverseApplyIgnoreHosts},
+ {MozKey_ProxyMode, ReverseApplyProxyMode},
+ {MozKey_UseDownloadDir, ReverseApplyDownloadFolder},
+ {MozKey_DownloadDirType, ReverseApplyDownloadFolder},
+ {MozKey_DownloadDirExplicit, ReverseApplyDownloadFolder},
+ {MozKey_CookieBehavior, ReverseApplyDisableCookies},
+ {MozKey_RememberSignons, ReverseApplyDisableSavePassword},
+ {MozKey_ImagePermissions, ReverseApplyLoadImages},
+ {MozKey_DisablePopups, ReverseApplyDisablePopups}
+};
+// The unsafe protocol preferences are handled specially because
+// they affect an unknown number of Mozilla preferences
+// Window opener permissions are also handled specially so we don't have to
+// repeat the windowOpenFeatures list.
+
+/* END preference mapping definition area */
+
+static PR_CALLBACK void GConfSimpleNotification(GConfClient* client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer user_data)
+{
+ nsSystemPrefService* service = NS_STATIC_CAST(nsSystemPrefService*, user_data);
+ SimplePrefMapping* map = NS_STATIC_CAST(SimplePrefMapping*,
+ service->GetSimpleCallbackData(cnxn_id));
+ NS_ASSERTION(map, "Can't find mapping for callback");
+ if (!map)
+ return;
- gchar *str = GConfClientGetString(mGConfClient,
- MozKey2GConfKey(aMozKey), NULL);
- if (str) {
- *retval = PL_strdup(str);
- g_free(str);
- }
- return NS_OK;
+ ApplySimpleMapping(map, service->GetPrefs(), client);
}
-nsresult
-GConfProxy::GetIntPref(const char *aMozKey, PRInt32 *retval)
-{
- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
- if (strcmp (aMozKey, "network.proxy.type") == 0) {
- gchar *str;
-
- str = GConfClientGetString(mGConfClient,
- MozKey2GConfKey (aMozKey), NULL);
-
- if (str) {
- if (strcmp (str, "manual") == 0)
- *retval = 1;
- else if (strcmp (str, "auto") == 0)
- *retval = 2;
- else
- *retval = 0;
-
- g_free (str);
- } else
- *retval = 0;
- } else {
- *retval = GConfClientGetInt(mGConfClient,
- MozKey2GConfKey(aMozKey), NULL);
- }
+static PR_CALLBACK void GConfComplexNotification(GConfClient* client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer user_data)
+{
+ nsSystemPrefService* service = NS_STATIC_CAST(nsSystemPrefService*, user_data);
+ ComplexGConfPrefMapping* map = NS_STATIC_CAST(ComplexGConfPrefMapping*,
+ service->GetComplexCallbackData(cnxn_id));
+ NS_ASSERTION(map, "Can't find mapping for callback");
+ if (!map)
+ return;
- return NS_OK;
+ map->callback(service, GetGConf());
}
-nsresult
-GConfProxy::NotifyAdd (PRUint32 aAtom, void *aUserData)
+nsresult nsSystemPrefService::LoadSystemPreferences(nsISystemPref* aPrefs)
{
- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
-
- const char *gconfKey = GetGConfKey(aAtom);
- if (!gconfKey)
- return NS_ERROR_FAILURE;
+ mPref = aPrefs;
- if (!mObservers) {
- mObservers = new nsAutoVoidArray();
- if (mObservers == nsnull)
- return NS_ERROR_OUT_OF_MEMORY;
+ GConfClient* client = GetGConf();
+ PRUint32 i;
+ nsCOMPtr<nsIPrefBranch2> userPrefs = aPrefs->GetPrefUserBranch();
+
+ // Update gconf settings with any Mozilla settings that have
+ // changed from the default. Do it before we register our
+ // gconf notifications.
+ for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
+ gconf_client_add_dir(client, sSimplePrefMappings[i].gconfPrefName,
+ GCONF_CLIENT_PRELOAD_NONE, nsnull);
+
+ PRBool hasUserPref = PR_FALSE;
+ nsresult rv =
+ userPrefs->PrefHasUserValue(sSimplePrefMappings[i].mozPrefName,
+ &hasUserPref);
+ if (NS_FAILED(rv))
+ return rv;
+ if (hasUserPref && sSimplePrefMappings[i].allowWritesFromMozilla &&
+ gconf_client_key_is_writable(client,
+ sSimplePrefMappings[i].gconfPrefName,
+ nsnull)) {
+ rv = ReverseApplySimpleMapping(&sSimplePrefMappings[i],
+ aPrefs, client);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+ for (i = 0; i < NUM_ELEM(sComplexGConfPrefMappings); ++i) {
+ gconf_client_add_dir(client, sComplexGConfPrefMappings[i].gconfPrefName,
+ GCONF_CLIENT_PRELOAD_NONE, nsnull);
+ }
+ ComplexMozPrefChanged lastMozCallback = nsnull;
+ for (i = 0; i < NUM_ELEM(sComplexMozPrefMappings); ++i) {
+ PRBool hasUserPref = PR_FALSE;
+ nsresult rv =
+ userPrefs->PrefHasUserValue(sComplexMozPrefMappings[i].mozPrefName,
+ &hasUserPref);
+ if (NS_FAILED(rv))
+ return rv;
+ if (hasUserPref) {
+ ComplexMozPrefChanged cb = sComplexMozPrefMappings[i].callback;
+ if (cb != lastMozCallback) {
+ cb(this, client);
+ lastMozCallback = cb;
+ }
+ }
}
- GConfCallbackData *pData = (GConfCallbackData *)
- nsMemory::Alloc(sizeof(GConfCallbackData));
- NS_ENSURE_TRUE(pData, NS_ERROR_OUT_OF_MEMORY);
-
- pData->proxy = this;
- pData->userData = aUserData;
- pData->atom = aAtom;
- mObservers->AppendElement(pData);
-
- GConfClientAddDir(mGConfClient, gconfKey,
- 0, // GCONF_CLIENT_PRELOAD_NONE, don't preload anything
- NULL);
-
- pData->notifyId = GConfClientNotifyAdd(mGConfClient, gconfKey,
- gconf_key_listener, pData,
- NULL, NULL);
+ // Register simple mappings and callbacks
+ for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
+ guint cx = gconf_client_notify_add(client,
+ sSimplePrefMappings[i].gconfPrefName,
+ GConfSimpleNotification, this,
+ nsnull, nsnull);
+ mGConfSimpleCallbacks.Put(cx, &sSimplePrefMappings[i]);
+ nsresult rv = ApplySimpleMapping(&sSimplePrefMappings[i], aPrefs, client);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ ComplexGConfPrefChanged lastCallback = nsnull;
+ for (i = 0; i < NUM_ELEM(sComplexGConfPrefMappings); ++i) {
+ guint cx = gconf_client_notify_add(client,
+ sComplexGConfPrefMappings[i].gconfPrefName,
+ GConfComplexNotification, this,
+ nsnull, nsnull);
+ mGConfComplexCallbacks.Put(cx, &sComplexGConfPrefMappings[i]);
+ ComplexGConfPrefChanged cb = sComplexGConfPrefMappings[i].callback;
+ if (cb != lastCallback) {
+ cb(this, client);
+ lastCallback = cb;
+ }
+ }
+
+ ApplyUnsafeProtocols(this, client);
+
return NS_OK;
}
-nsresult
-GConfProxy::NotifyRemove (PRUint32 aAtom, const void *aUserData)
+nsresult nsSystemPrefService::NotifyMozillaPrefChanged(const char* aPrefName)
{
- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+ PRUint32 i;
+ GConfClient* client = GetGConf();
- PRIntn count = mObservers->Count();
- if (count <= 0)
- return NS_OK;
-
- PRIntn i;
- GConfCallbackData *pData;
- for (i = 0; i < count; ++i) {
- pData = (GConfCallbackData *)mObservers->ElementAt(i);
- if (pData && pData->atom == aAtom && pData->userData == aUserData) {
- GConfClientNotifyRemove(mGConfClient, pData->notifyId);
- GConfClientRemoveDir(mGConfClient,
- GetGConfKey(pData->atom), NULL);
- mObservers->RemoveElementAt(i);
- nsMemory::Free(pData);
- break;
+ for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
+ if (!strcmp(aPrefName, sSimplePrefMappings[i].mozPrefName)) {
+ ReverseApplySimpleMapping(&sSimplePrefMappings[i],
+ mPref, client);
}
}
- return NS_OK;
-}
-void
-GConfProxy::InitFuncPtrs()
-{
- //gconf client funcs
- GConfClientGetDefault =
- (GConfClientGetDefaultType) sGConfFuncList[0].FuncPtr;
- GConfClientGetBool =
- (GConfClientGetBoolType) sGConfFuncList[1].FuncPtr;
- GConfClientGetString =
- (GConfClientGetStringType) sGConfFuncList[2].FuncPtr;
- GConfClientGetInt =
- (GConfClientGetIntType) sGConfFuncList[3].FuncPtr;
- GConfClientNotifyAdd =
- (GConfClientNotifyAddType) sGConfFuncList[4].FuncPtr;
- GConfClientNotifyRemove =
- (GConfClientNotifyRemoveType) sGConfFuncList[5].FuncPtr;
- GConfClientAddDir =
- (GConfClientAddDirType) sGConfFuncList[6].FuncPtr;
- GConfClientRemoveDir =
- (GConfClientRemoveDirType) sGConfFuncList[7].FuncPtr;
-
- //gconf entry funcs
- GConfEntryGetValue = (GConfEntryGetValueType) sGConfFuncList[8].FuncPtr;
- GConfEntryGetKey = (GConfEntryGetKeyType) sGConfFuncList[9].FuncPtr;
-
- //gconf value funcs
- GConfValueGetBool = (GConfValueGetBoolType) sGConfFuncList[10].FuncPtr;
- GConfValueGetString = (GConfValueGetStringType) sGConfFuncList[11].FuncPtr;
- GConfValueGetInt = (GConfValueGetIntType) sGConfFuncList[12].FuncPtr;
-}
-
-void
-GConfProxy::OnNotify(void *aClient, void * aEntry, PRUint32 aNotifyId,
- GConfCallbackData *aData)
-{
- if (!mInitialized || !aEntry || (mGConfClient != aClient) || !aData)
- return;
+ for (i = 0; i < NUM_ELEM(sComplexMozPrefMappings); ++i) {
+ if (!strcmp(aPrefName, sComplexMozPrefMappings[i].mozPrefName)) {
+ sComplexMozPrefMappings[i].callback(this, client);
+ }
+ }
- if (GConfEntryGetValue(aEntry) == NULL)
- return;
+ for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
+ if (!strcmp(aPrefName, windowOpenFeatures[i])) {
+ ReverseApplyWindowOpen(this, client);
+ }
+ }
- PRUint32 prefAtom;
- nsresult rv = GetAtomForGConfKey(GConfEntryGetKey(aEntry), &prefAtom);
- if (NS_FAILED(rv))
- return;
+ ReverseApplyUnsafeProtocols(this, client);
- mSysPrefService->OnPrefChange(prefAtom, aData->userData);
+ return NS_OK;
}
-nsresult
-GConfProxy::GetAtom(const char *aKey, PRUint8 aNameType, PRUint32 *aAtom)
+static PLDHashOperator PR_CALLBACK UnregisterSimple(const PRUint32& aKey,
+ SimplePrefMapping* aData,
+ void* aClosure)
{
- if (!aKey)
- return NS_ERROR_FAILURE;
- PRUint32 prefSize = sizeof(sPrefNameMapping) / sizeof(sPrefNameMapping[0]);
- for (PRUint32 index = 0; index < prefSize; ++index) {
- if (!strcmp((aNameType == 0) ? sPrefNameMapping[index].mozPrefName :
- sPrefNameMapping[index].gconfPrefName, aKey)) {
- *aAtom = index;
- return NS_OK;
- }
- }
- return NS_ERROR_FAILURE;
+ GConfClient* client = GetGConf();
+ gconf_client_notify_remove(client, aKey);
+ gconf_client_remove_dir(client, aData->gconfPrefName, nsnull);
+ return PL_DHASH_NEXT;
}
-const char *
-GConfProxy::GetKey(PRUint32 aAtom, PRUint8 aNameType)
+static PLDHashOperator PR_CALLBACK UnregisterComplex(const PRUint32& aKey,
+ ComplexGConfPrefMapping* aData,
+ void* aClosure)
{
- PRUint32 mapSize = sizeof(sPrefNameMapping) / sizeof(sPrefNameMapping[0]);
- if (aAtom >= 0 && aAtom < mapSize)
- return (aNameType == 0) ? sPrefNameMapping[aAtom].mozPrefName :
- sPrefNameMapping[aAtom].gconfPrefName;
- return NULL;
+ GConfClient* client = GetGConf();
+ gconf_client_notify_remove(client, aKey);
+ gconf_client_remove_dir(client, aData->gconfPrefName, nsnull);
+ return PL_DHASH_NEXT;
}
-inline const char *
-GConfProxy::MozKey2GConfKey(const char *aMozKey)
+nsresult nsSystemPrefService::NotifyUnloadSystemPreferences()
{
- PRUint32 atom;
- nsresult rv = GetAtomForMozKey(aMozKey, &atom);
- if (NS_SUCCEEDED(rv))
- return GetGConfKey(atom);
- return NULL;
-}
+ // Unregister callbacks
+ mGConfSimpleCallbacks.EnumerateRead(UnregisterSimple, this);
+ mGConfSimpleCallbacks.Clear();
+ mGConfComplexCallbacks.EnumerateRead(UnregisterComplex, this);
+ mGConfComplexCallbacks.Clear();
-/* static */
-void gconf_key_listener (void* client, guint cnxn_id,
- void *entry, gpointer user_data)
-{
- SYSPREF_LOG(("...SYSPREF_LOG...key listener get called \n"));
- if (!user_data)
- return;
- GConfCallbackData *pData = NS_REINTERPRET_CAST(GConfCallbackData *,
- user_data);
- pData->proxy->OnNotify(client, entry, cnxn_id, pData);
+ return NS_OK;
}
+
+// Factory stuff
+
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPrefService, Init)
+
+static const nsModuleComponentInfo components[] = {
+ { NS_SYSTEMPREF_SERVICE_CLASSNAME,
+ NS_SYSTEMPREF_SERVICE_CID,
+ NS_SYSTEMPREF_SERVICE_CONTRACTID,
+ nsSystemPrefServiceConstructor,
+ },
+};
+
+NS_IMPL_NSGETMODULE(nsSystemPrefServiceModule, components)
--- extensions/pref/system-pref/src/nsISystemPrefService.h
+++ extensions/pref/system-pref/src/nsISystemPrefService.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ *
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Novell
+ * Portions created by Novell are Copyright (C) 2005 Novell,
+ * All Rights Reserved.
+ *
+ * Original Author: Robert O'Callahan (rocallahan@novell.com)
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the NPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsISystemPrefService_h__
+#define nsISystemPrefService_h__
+
+#include "nsCOMPtr.h"
+#include "nsIPrefBranchInternal.h"
+
+#define NS_SYSTEMPREF_SERVICE_CONTRACTID "@mozilla.org/system-preferences-service;1"
+
+#define NS_ISYSTEMPREFSERVICE_IID \
+{ 0x006e1cfd, 0xd66a, 0x40b9, \
+ { 0x84, 0xa1, 0x84, 0xf3, 0xe6, 0xa2, 0xca, 0xbc } }
+
+class nsISystemPref {
+public:
+ /**
+ * Call one of these three methods to override a Mozilla
+ * preference with a system value. You can call it multiple
+ * times to change the value of a given preference to track
+ * the underlying system value.
+ *
+ * If aLocked is true then we set the default preference and
+ * lock it so the user value is ignored. If aLocked is false
+ * then we unlock the Mozilla preference and set the Mozilla
+ * user value.
+ */
+ virtual nsresult SetOverridingMozillaBoolPref(const char* aPrefName,
+ PRBool aValue, PRBool aLocked,
+ PRBool aPresent = PR_TRUE) = 0;
+ virtual nsresult SetOverridingMozillaIntPref(const char* aPrefName,
+ PRInt32 aValue, PRBool aLocked,
+ PRBool aPresent = PR_TRUE) = 0;
+ virtual nsresult SetOverridingMozillaStringPref(const char* aPrefName,
+ const char* aValue, PRBool aLocked,
+ PRBool aPresent = PR_TRUE) = 0;
+ virtual nsresult StopOverridingMozillaPref(const char* aPrefName) = 0;
+ virtual already_AddRefed<nsIPrefBranch2> GetPrefUserBranch() = 0;
+ virtual already_AddRefed<nsIPrefBranch> GetPrefDefaultBranch() = 0;
+};
+
+class nsISystemPrefService : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISYSTEMPREFSERVICE_IID)
+
+ /**
+ * Load the system prefs from the store into their corresponding
+ * Mozilla prefs, calling SetOverridingMozillaPref on each
+ * such pref.
+ */
+ virtual nsresult LoadSystemPreferences(nsISystemPref* aPrefs) = 0;
+
+ /**
+ * Notify that a Mozilla user pref that is being overridden by the
+ * store has changed. The new value of the Mozilla pref should be
+ * written back to the store.
+ */
+ virtual nsresult NotifyMozillaPrefChanged(const char* aPrefName) = 0;
+
+ /**
+ * Notify that we're about to stop using the system prefs. After
+ * this, nsSystemPref will automatically stop overriding all
+ * Mozilla prefs that are being overridden.
+ */
+ virtual nsresult NotifyUnloadSystemPreferences() = 0;
+};
+
+#endif
--- extensions/pref/system-pref/src/nsSystemPref.cpp
+++ extensions/pref/system-pref/src/nsSystemPref.cpp
@@ -24,6 +24,7 @@
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
* Contributor(s):
+ * Robert O'Callahan (rocallahan@novell.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -41,66 +42,60 @@
#include "nsSystemPref.h"
#include "nsIObserverService.h"
+#include "nsIAppStartupNotifier.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsICategoryManager.h"
+#include "nsIServiceManager.h"
#include "nsSystemPrefLog.h"
-#include "nsSystemPrefService.h"
#include "nsString.h"
-const char sSysPrefString[] = "config.use_system_prefs";
-union MozPrefValue {
- char * stringVal;
- PRInt32 intVal;
- PRBool boolVal;
-};
+#include <stdlib.h>
struct SysPrefItem {
- const char *prefName; // mozilla pref string name
- MozPrefValue defaultValue; // store the mozilla default value
- PRBool isLocked; // store the mozilla lock status
+ // Saved values on both branches
+ PRInt32 savedUserValueScalar;
+ char* savedUserValueString;
+ PRInt32 savedDefaultValueScalar;
+ char* savedDefaultValueString;
+ // When this is true, then the value was locked originally
+ PRPackedBool savedLocked;
+ // When this is true, then there was a user value
+ PRPackedBool savedUserPresent;
+ PRPackedBool ignore;
+
SysPrefItem() {
- prefName = nsnull;
- defaultValue.intVal = 0;
- defaultValue.stringVal = nsnull;
- defaultValue.boolVal = PR_FALSE;
- isLocked = PR_FALSE;
+ savedUserValueScalar = 0;
+ savedUserValueString = nsnull;
+ savedDefaultValueScalar = 0;
+ savedDefaultValueString = nsnull;
+ savedUserPresent = PR_FALSE;
+ savedLocked = PR_FALSE;
+ ignore = PR_FALSE;
}
- void SetPrefName(const char *aPrefName) {
- prefName = aPrefName;
+
+ virtual ~SysPrefItem() {
+ nsMemory::Free(savedUserValueString);
+ nsMemory::Free(savedDefaultValueString);
}
};
-// all prefs that mozilla need to read from host system if they are available
-static const char *sSysPrefList[] = {
- "network.proxy.http",
- "network.proxy.http_port",
- "network.proxy.ftp",
- "network.proxy.ftp_port",
- "network.proxy.ssl",
- "network.proxy.ssl_port",
- "network.proxy.socks",
- "network.proxy.socks_port",
- "network.proxy.no_proxies_on",
- "network.proxy.autoconfig_url",
- "network.proxy.type",
- "config.use_system_prefs.accessibility",
-};
+static const char sSysPrefString[] = "config.use_system_prefs";
PRLogModuleInfo *gSysPrefLog = NULL;
NS_IMPL_ISUPPORTS2(nsSystemPref, nsIObserver, nsISupportsWeakReference)
-nsSystemPref::nsSystemPref():
- mSysPrefService(nsnull),
- mEnabled(PR_FALSE),
- mSysPrefs(nsnull)
+nsSystemPref::nsSystemPref() : mIgnorePrefSetting(PR_FALSE)
{
+ mSavedPrefs.Init();
+ mCachedUserPrefBranch = nsnull;
+ mCachedDefaultPrefBranch = nsnull;
}
nsSystemPref::~nsSystemPref()
{
- mSysPrefService = nsnull;
- mEnabled = PR_FALSE;
- delete [] mSysPrefs;
}
///////////////////////////////////////////////////////////////////////////////
@@ -131,6 +126,54 @@
return(rv);
}
+already_AddRefed<nsIPrefBranch2>
+nsSystemPref::GetPrefUserBranch()
+{
+ if (mCachedUserPrefBranch) {
+ NS_ADDREF(mCachedUserPrefBranch);
+ return mCachedUserPrefBranch;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIPrefService> prefService =
+ do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv))
+ return nsnull;
+ nsCOMPtr<nsIPrefBranch> prefBranch;
+ rv = prefService->GetBranch(nsnull, getter_AddRefs(prefBranch));
+ if (NS_FAILED(rv))
+ return nsnull;
+ nsCOMPtr<nsIPrefBranch2> pb2(do_QueryInterface(prefBranch));
+ if (!pb2)
+ return nsnull;
+
+ nsIPrefBranch2* result = nsnull;
+ pb2.swap(result);
+ return result;
+}
+
+already_AddRefed<nsIPrefBranch>
+nsSystemPref::GetPrefDefaultBranch()
+{
+ if (mCachedDefaultPrefBranch) {
+ NS_ADDREF(mCachedDefaultPrefBranch);
+ return mCachedDefaultPrefBranch;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIPrefService> prefService =
+ do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv))
+ return nsnull;
+ nsCOMPtr<nsIPrefBranch> prefBranch;
+ rv = prefService->GetDefaultBranch(nsnull, getter_AddRefs(prefBranch));
+ if (NS_FAILED(rv))
+ return nsnull;
+ nsIPrefBranch* pb = nsnull;
+ prefBranch.swap(pb);
+ return pb;
+}
+
///////////////////////////////////////////////////////////////////////////////
// nsSystemPref::Observe
// Observe notifications from mozilla pref system and system prefs (if enabled)
@@ -145,330 +188,446 @@
if (!aTopic)
return NS_OK;
- // if we are notified by pref service
- // check the system pref settings
- if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
- SYSPREF_LOG(("Observed: %s\n", aTopic));
-
- nsCOMPtr<nsIPrefBranch2> prefBranch =
- do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
- if (NS_FAILED(rv))
- return rv;
+ nsCOMPtr<nsIPrefBranch2> userBranch = GetPrefUserBranch();
+ nsCOMPtr<nsIPrefBranch> defaultBranch = GetPrefDefaultBranch();
- rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
+ // Check the default branch first. If system prefs are enabled
+ // by default, then don't check the user prefs; we don't want
+ // to allow users to change the default.
+ PRBool defaultEnabled;
+ rv = defaultBranch->GetBoolPref(sSysPrefString, &defaultEnabled);
+ if (NS_FAILED(rv)) {
+ SYSPREF_LOG(("...Failed to Get %s\n", sSysPrefString));
+ return rv;
+ }
+ PRBool enabled = defaultEnabled;
+ if (!enabled) {
+ rv = userBranch->GetBoolPref(sSysPrefString, &enabled);
if (NS_FAILED(rv)) {
- SYSPREF_LOG(("...FAil to Get %s\n", sSysPrefString));
+ SYSPREF_LOG(("...Failed to Get %s\n", sSysPrefString));
return rv;
}
+ }
- // if there is no system pref service, assume nothing happen to us
- mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
- if (NS_FAILED(rv) || !mSysPrefService) {
- SYSPREF_LOG(("...No System Pref Service\n"));
- return NS_OK;
- }
+ if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
+ // The prefs have just loaded. This is the first thing that
+ // happens to us.
+ SYSPREF_LOG(("Observed: %s\n", aTopic));
- // listen on its changes
- rv = prefBranch->AddObserver(sSysPrefString, this, PR_TRUE);
+ // listen on changes to use_system_pref. It's OK to
+ // hold a strong reference because we don't keep a reference
+ // to the pref branch.
+ rv = userBranch->AddObserver(sSysPrefString, this, PR_TRUE);
if (NS_FAILED(rv)) {
- SYSPREF_LOG(("...FAil to add observer for %s\n", sSysPrefString));
+ SYSPREF_LOG(("...Failed to add observer for %s\n", sSysPrefString));
return rv;
}
- if (!mEnabled) {
- SYSPREF_LOG(("%s is disabled\n", sSysPrefString));
+ NS_ASSERTION(!mSysPrefService, "Should not be already enabled");
+ if (!enabled) {
+ // Don't load the system pref service if the preference is
+ // not set.
return NS_OK;
}
- SYSPREF_LOG(("%s is enabled\n", sSysPrefString));
- rv = UseSystemPrefs();
- }
- // sSysPrefString value was changed, update ...
- else if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
- NS_ConvertUTF8toUCS2(sSysPrefString).Equals(aData)) {
- SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
- aTopic, NS_ConvertUCS2toUTF8(aData).get()));
+ SYSPREF_LOG(("%s is enabled\n", sSysPrefString));
- nsCOMPtr<nsIPrefBranch> prefBranch =
- do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+ rv = LoadSystemPrefs();
if (NS_FAILED(rv))
return rv;
- PRBool enabled = mEnabled;
- rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
- if (enabled != mEnabled) {
- if (mEnabled)
- //read prefs from system
- rv = UseSystemPrefs();
- else
- //roll back to mozilla prefs
- rv = UseMozillaPrefs();
+ // Lock config.use_system_prefs so the user can't undo
+ // it. But only do this if it was set by in the default prefs;
+ // if it was not set by default, then locking it would actually
+ // unset the value! And the user should be allowed to turn off
+ // something they set themselves.
+ if (NS_SUCCEEDED(rv) && defaultEnabled) {
+ userBranch->LockPref(sSysPrefString);
}
}
- // if the system pref notify us that some pref has been changed by user
- // outside mozilla. We need to read it again.
- else if (!nsCRT::strcmp(aTopic, NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID) &&
- aData) {
- NS_ASSERTION(mEnabled == PR_TRUE, "Should not listen when disabled");
- SYSPREF_LOG(("====== System Pref Notify topic=%s data=%s\n",
- aTopic, (char*)aData));
- rv = ReadSystemPref(NS_LossyConvertUCS2toASCII(aData).get());
- return NS_OK;
- } else if (!nsCRT::strcmp(aTopic,"profile-before-change")) {
- //roll back to mozilla prefs
- if (mEnabled)
- UseMozillaPrefs();
- mEnabled = PR_FALSE;
- mSysPrefService = nsnull;
- delete [] mSysPrefs;
- mSysPrefs = nsnull;
- } else
- SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
- return rv;
-}
+ if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
+ nsDependentString(aData).EqualsASCII(sSysPrefString)) {
+ // sSysPrefString value was changed, update...
+ SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
+ aTopic, NS_ConvertUCS2toUTF8(aData).get()));
+ if (mSysPrefService && !enabled)
+ return RestoreMozillaPrefs();
+ if (!mSysPrefService && enabled) {
+ // Don't lock it. If the user enabled use_system_prefs,
+ // they should be allowed to unlock it.
+ return LoadSystemPrefs();
+ }
-/* private */
+ // didn't change?
+ return NS_OK;
+ }
-////////////////////////////////////////////////////////////////
-// nsSystemPref::UseSystemPrefs
-// Read all the prefs in the table from system, listen for their
-// changes in system pref service.
-////////////////////////////////////////////////////////////////
-nsresult
-nsSystemPref::UseSystemPrefs()
-{
- SYSPREF_LOG(("\n====Now Use system prefs==\n"));
- nsresult rv = NS_OK;
- if (!mSysPrefService) {
- return NS_ERROR_FAILURE;
+ if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
+ // some other pref changed, tell the backend if there is one
+ if (mSysPrefService && !mIgnorePrefSetting) {
+ NS_LossyConvertUTF16toASCII tmp(aData);
+#ifdef DEBUG
+ PRBool isLocked;
+ userBranch->PrefIsLocked(tmp.get(), &isLocked);
+ NS_ASSERTION(!isLocked, "Locked pref is changing?");
+#endif
+ SysPrefItem* item;
+ if (!mSavedPrefs.Get(tmp, &item)) {
+ NS_ERROR("Notified about pref change that we didn't ask about?");
+ } else {
+ if (!item->ignore) {
+ mSysPrefService->NotifyMozillaPrefChanged(tmp.get());
+ }
+ }
+ }
+ return NS_OK;
}
- PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
+ if (!nsCRT::strcmp(aTopic,"profile-before-change"))
+ return RestoreMozillaPrefs();
- if (!mSysPrefs) {
- mSysPrefs = new SysPrefItem[sysPrefCount];
- if (!mSysPrefs)
- return NS_ERROR_OUT_OF_MEMORY;
- for (PRIntn index = 0; index < sysPrefCount; ++index)
- mSysPrefs[index].SetPrefName(sSysPrefList[index]);
- }
+ SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
- for (PRIntn index = 0; index < sysPrefCount; ++index) {
- // save mozilla prefs
- SaveMozDefaultPref(mSysPrefs[index].prefName,
- &mSysPrefs[index].defaultValue,
- &mSysPrefs[index].isLocked);
-
- // get the system prefs
- ReadSystemPref(mSysPrefs[index].prefName);
- SYSPREF_LOG(("Add Listener on %s\n", mSysPrefs[index].prefName));
- mSysPrefService->AddObserver(mSysPrefs[index].prefName,
- this, PR_TRUE);
- }
return rv;
}
-//////////////////////////////////////////////////////////////////////
-// nsSystemPref::ReadSystemPref
-// Read a pref value from system pref service, and lock it in mozilla.
-//////////////////////////////////////////////////////////////////////
nsresult
-nsSystemPref::ReadSystemPref(const char *aPrefName)
+nsSystemPref::SetOverridingMozillaBoolPref(const char* aPrefName,
+ PRBool aValue, PRBool aLock, PRBool aPresent)
{
- if (!mSysPrefService)
- return NS_ERROR_FAILURE;
- nsresult rv;
-
- nsCOMPtr<nsIPrefBranch> prefBranch
- (do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
- if (NS_FAILED(rv))
- return rv;
-
- SYSPREF_LOG(("about to read aPrefName %s\n", aPrefName));
+ return OverridePref(aPrefName, nsIPrefBranch::PREF_BOOL,
+ (void*)aValue, aLock, aPresent);
+}
- prefBranch->UnlockPref(aPrefName);
+nsresult
+nsSystemPref::SetOverridingMozillaIntPref(const char* aPrefName,
+ PRInt32 aValue, PRBool aLock, PRBool aPresent)
+{
+ return OverridePref(aPrefName, nsIPrefBranch::PREF_INT,
+ (void*)aValue, aLock, aPresent);
+}
- PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
- nsXPIDLCString strValue;
- PRInt32 intValue = 0;
- PRBool boolValue = PR_FALSE;
+nsresult
+nsSystemPref::SetOverridingMozillaStringPref(const char* aPrefName,
+ const char* aValue, PRBool aLock, PRBool aPresent)
+{
+ return OverridePref(aPrefName, nsIPrefBranch::PREF_STRING,
+ (void*)aValue, aLock, aPresent);
+}
- rv = prefBranch->GetPrefType(aPrefName, &prefType);
- if (NS_FAILED(rv))
- return rv;
- switch (prefType) {
+static nsresult RestorePrefValue(PRInt32 aPrefType,
+ const char* aPrefName,
+ SysPrefItem* aItem,
+ nsIPrefBranch* aUser,
+ nsIPrefBranch* aDefault)
+{
+ switch (aPrefType) {
case nsIPrefBranch::PREF_STRING:
- mSysPrefService->GetCharPref(aPrefName, getter_Copies(strValue));
- SYSPREF_LOG(("system value is %s\n", strValue.get()));
-
- prefBranch->SetCharPref(aPrefName, strValue.get());
+ aDefault->SetCharPref(aPrefName,
+ aItem->savedDefaultValueString);
+ if (aItem->savedUserPresent) {
+ aUser->SetCharPref(aPrefName, aItem->savedUserValueString);
+ }
break;
case nsIPrefBranch::PREF_INT:
- mSysPrefService->GetIntPref(aPrefName, &intValue);
- SYSPREF_LOG(("system value is %d\n", intValue));
-
- prefBranch->SetIntPref(aPrefName, intValue);
+ aDefault->SetIntPref(aPrefName, aItem->savedDefaultValueScalar);
+ if (aItem->savedUserPresent) {
+ aUser->SetIntPref(aPrefName, aItem->savedUserValueScalar);
+ }
break;
case nsIPrefBranch::PREF_BOOL:
- mSysPrefService->GetBoolPref(aPrefName, &boolValue);
- SYSPREF_LOG(("system value is %s\n", boolValue ? "TRUE" : "FALSE"));
-
- prefBranch->SetBoolPref(aPrefName, boolValue);
+ aDefault->SetBoolPref(aPrefName, aItem->savedDefaultValueScalar);
+ if (aItem->savedUserPresent) {
+ aUser->SetBoolPref(aPrefName, aItem->savedUserValueScalar);
+ }
break;
default:
- SYSPREF_LOG(("Fail to system value for it\n"));
+ NS_ERROR("Unknown preference type");
return NS_ERROR_FAILURE;
}
- prefBranch->LockPref(aPrefName);
+
+ if (!aItem->savedUserPresent) {
+ aUser->DeleteBranch(aPrefName);
+ }
+
return NS_OK;
}
-//////////////////////////////////////////////////////////////////////
-// nsSystemPref::UseMozillaPrefs
-// Restore mozilla default prefs, remove system pref listeners
-/////////////////////////////////////////////////////////////////////
-nsresult
-nsSystemPref::UseMozillaPrefs()
+static PLDHashOperator PR_CALLBACK RestorePref(const nsACString& aKey,
+ SysPrefItem* aItem,
+ void* aClosure)
{
- nsresult rv = NS_OK;
- SYSPREF_LOG(("\n====Now rollback to Mozilla prefs==\n"));
+ nsSystemPref* prefs = NS_STATIC_CAST(nsSystemPref*, aClosure);
+ nsCOMPtr<nsIPrefBranch2> userBranch = prefs->GetPrefUserBranch();
+ const nsCString& prefName = PromiseFlatCString(aKey);
+
+ PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
+ nsresult rv = userBranch->GetPrefType(prefName.get(), &prefType);
+ if (NS_FAILED(rv))
+ return PL_DHASH_NEXT;
+ PRBool isLocked;
+ userBranch->PrefIsLocked(prefName.get(), &isLocked);
+ if (NS_FAILED(rv))
+ return PL_DHASH_NEXT;
- // if we did not use system prefs, do nothing
- if (!mSysPrefService)
- return NS_OK;
+ // Remove our observer before we change the value
+ userBranch->RemoveObserver(prefName.get(), prefs);
+ // Remember to ignore this item. Because some prefs start with "config.use_system_prefs",
+ // which we always observe, even after we remove the observer, changes to the pref will
+ // still be observed by us. We must ignore them.
+ aItem->ignore = PR_TRUE;
- PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
- for (PRIntn index = 0; index < sysPrefCount; ++index) {
- // restore mozilla default value and free string memory if needed
- RestoreMozDefaultPref(mSysPrefs[index].prefName,
- &mSysPrefs[index].defaultValue,
- mSysPrefs[index].isLocked);
- SYSPREF_LOG(("stop listening on %s\n", mSysPrefs[index].prefName));
- mSysPrefService->RemoveObserver(mSysPrefs[index].prefName,
- this);
+ // Unlock the pref so we can set it
+ if (isLocked) {
+ userBranch->UnlockPref(prefName.get());
}
- return rv;
+
+ nsCOMPtr<nsIPrefBranch> defaultBranch = prefs->GetPrefDefaultBranch();
+
+ RestorePrefValue(prefType, prefName.get(), aItem,
+ userBranch, defaultBranch);
+
+ if (aItem->savedLocked) {
+ userBranch->LockPref(prefName.get());
+ }
+
+ return PL_DHASH_NEXT;
}
-////////////////////////////////////////////////////////////////////////////
-// nsSystemPref::RestoreMozDefaultPref
-// Save the saved mozilla default value.
-// It is also responsible for allocate the string memory when needed, because
-// this method know what type of value is stored.
-/////////////////////////////////////////////////////////////////////////////
nsresult
-nsSystemPref::SaveMozDefaultPref(const char *aPrefName,
- MozPrefValue *aPrefValue,
- PRBool *aLocked)
-{
- NS_ENSURE_ARG_POINTER(aPrefName);
- NS_ENSURE_ARG_POINTER(aPrefValue);
- NS_ENSURE_ARG_POINTER(aLocked);
-
- nsresult rv;
+nsSystemPref::StopOverridingMozillaPref(const char* aPrefName)
+{
+ SysPrefItem* item;
+ nsDependentCString prefNameStr(aPrefName);
+ if (!mSavedPrefs.Get(prefNameStr, &item))
+ return NS_OK;
- nsCOMPtr<nsIPrefBranch> prefBranch =
- do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
- if (NS_FAILED(rv))
- return rv;
+ RestorePref(prefNameStr, item, this);
+ mSavedPrefs.Remove(prefNameStr);
+ delete item;
+ return NS_OK;
+}
- SYSPREF_LOG(("Save Mozilla value for %s\n", aPrefName));
+/* private */
+nsresult
+nsSystemPref::OverridePref(const char* aPrefName, PRInt32 aType,
+ void* aValue, PRBool aLock, PRBool aPresent)
+{
+ nsCOMPtr<nsIPrefBranch2> userBranch = GetPrefUserBranch();
+ nsCOMPtr<nsIPrefBranch> defaultBranch = GetPrefDefaultBranch();
PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
- nsXPIDLCString strValue;
-
- rv = prefBranch->GetPrefType(aPrefName, &prefType);
+ nsresult rv = userBranch->GetPrefType(aPrefName, &prefType);
if (NS_FAILED(rv))
return rv;
- switch (prefType) {
- case nsIPrefBranch::PREF_STRING:
- prefBranch->GetCharPref(aPrefName,
- getter_Copies(strValue));
- SYSPREF_LOG(("Mozilla value is %s", strValue.get()));
-
- if (aPrefValue->stringVal)
- PL_strfree(aPrefValue->stringVal);
- aPrefValue->stringVal = PL_strdup(strValue.get());
- break;
- case nsIPrefBranch::PREF_INT:
- prefBranch->GetIntPref(aPrefName, &aPrefValue->intVal);
- SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
- break;
- case nsIPrefBranch::PREF_BOOL:
- prefBranch->GetBoolPref(aPrefName, &aPrefValue->boolVal);
- SYSPREF_LOG(("Mozilla value is %s\n",
- aPrefValue->boolVal ? "TRUE" : "FALSE"));
+ PRBool isLocked;
+ rv = userBranch->PrefIsLocked(aPrefName, &isLocked);
+ if (NS_FAILED(rv))
+ return rv;
+ PRBool hasUserValue;
+ rv = userBranch->PrefHasUserValue(aPrefName, &hasUserValue);
+ if (NS_FAILED(rv))
+ return rv;
- break;
- default:
- SYSPREF_LOG(("Fail to Read Mozilla value for it\n"));
- return NS_ERROR_FAILURE;
+ if (prefType == 0) {
+ // Preference does not exist. Allow the system prefs to
+ // set it.
+ } else {
+ NS_ASSERTION(aType == prefType,
+ "System pref engine passed incorrect type for Mozilla pref");
+ if (aType != prefType)
+ return NS_ERROR_FAILURE;
+ }
+
+ if (prefType != 0) {
+ nsDependentCString prefNameStr(aPrefName);
+ SysPrefItem* item = nsnull;
+ if (!mSavedPrefs.Get(prefNameStr, &item)) {
+ // Need to save the existing value away
+ item = new SysPrefItem();
+ if (!item)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ item->savedLocked = isLocked;
+ item->savedUserPresent = hasUserValue;
+
+ switch (prefType) {
+ case nsIPrefBranch::PREF_STRING:
+ if (hasUserValue) {
+ userBranch->GetCharPref(aPrefName, &item->savedUserValueString);
+ }
+ defaultBranch->GetCharPref(aPrefName, &item->savedDefaultValueString);
+ break;
+ case nsIPrefBranch::PREF_INT:
+ if (hasUserValue) {
+ userBranch->GetIntPref(aPrefName, &item->savedUserValueScalar);
+ }
+ defaultBranch->GetIntPref(aPrefName, &item->savedDefaultValueScalar);
+ break;
+ case nsIPrefBranch::PREF_BOOL:
+ if (hasUserValue) {
+ userBranch->GetBoolPref(aPrefName, &item->savedUserValueScalar);
+ }
+ defaultBranch->GetBoolPref(aPrefName, &item->savedDefaultValueScalar);
+ break;
+ default:
+ NS_ERROR("Unknown preference type");
+ delete item;
+ return NS_ERROR_FAILURE;
+ }
+
+ mSavedPrefs.Put(prefNameStr, item);
+
+ // Watch the user value in case it changes on the Mozilla side
+ // If 'aLock' is true then it shouldn't change and we don't
+ // need the observer, but don't bother optimizing for that.
+ userBranch->AddObserver(aPrefName, this, PR_TRUE);
+ } else {
+ if (isLocked != aLock) {
+ // restore pref value on user and default branches
+ RestorePrefValue(prefType, aPrefName, item,
+ userBranch, defaultBranch);
+ }
+ }
}
- rv = prefBranch->PrefIsLocked(aPrefName, aLocked);
- SYSPREF_LOG((" (%s).\n", aLocked ? "Locked" : "NOT Locked"));
- return rv;
-}
-////////////////////////////////////////////////////////////////////////////
-// nsSystemPref::RestoreMozDefaultPref
-// Restore the saved mozilla default value to pref service.
-// It is also responsible for free the string memory when needed, because
-// this method know what type of value is stored.
-/////////////////////////////////////////////////////////////////////////////
-nsresult
-nsSystemPref::RestoreMozDefaultPref(const char *aPrefName,
- MozPrefValue *aPrefValue,
- PRBool aLocked)
-{
- NS_ENSURE_ARG_POINTER(aPrefName);
+ // We need to ignore pref changes due to our own calls here
+ mIgnorePrefSetting = PR_TRUE;
- nsresult rv;
+ // Unlock it if it's locked, so we can set it
+ if (isLocked) {
+ rv = userBranch->UnlockPref(aPrefName);
+ if (NS_FAILED(rv))
+ return rv;
+ }
- nsCOMPtr<nsIPrefBranch> prefBranch =
- do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+ // Set the pref on the default branch if we're locking it, because
+ // only the default branch gets used when the pref is locked.
+ // Set the pref on the user branch if we're not locking it, because
+ // that's where the user change will go.
+ nsIPrefBranch* settingBranch =
+ aLock ? defaultBranch.get() : NS_STATIC_CAST(nsIPrefBranch*, userBranch.get());
+
+ if (!aPresent) {
+ rv = settingBranch->DeleteBranch(aPrefName);
+ } else {
+ switch (aType) {
+ case nsIPrefBranch::PREF_STRING:
+ rv = settingBranch->SetCharPref(aPrefName, (const char*)aValue);
+ break;
+ case nsIPrefBranch::PREF_INT:
+ rv = settingBranch->SetIntPref(aPrefName, (PRInt32)(NS_PTR_TO_INT32(aValue)));
+ break;
+ case nsIPrefBranch::PREF_BOOL:
+ rv = settingBranch->SetBoolPref(aPrefName, (PRBool)(NS_PTR_TO_INT32(aValue)));
+ break;
+ default:
+ NS_ERROR("Unknown preference type");
+ mIgnorePrefSetting = PR_FALSE;
+ return NS_ERROR_FAILURE;
+ }
+ }
if (NS_FAILED(rv))
return rv;
+ if (aLock) {
+ rv = userBranch->LockPref(aPrefName);
+ }
- SYSPREF_LOG(("Restore Mozilla value for %s\n", aPrefName));
+ mIgnorePrefSetting = PR_FALSE;
+ return rv;
+}
- PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
- rv = prefBranch->GetPrefType(aPrefName, &prefType);
+nsresult
+nsSystemPref::FixupLockdownPrefs()
+{
+ nsCOMPtr<nsIPrefBranch2> userPrefs = GetPrefUserBranch();
+ nsCOMPtr<nsIPrefBranch2> defaultPrefs = GetPrefUserBranch();
+ PRUint32 childCount;
+ char **childArray = nsnull;
+ nsresult rv = userPrefs->GetChildList("config.lockdown.",
+ &childCount, &childArray);
if (NS_FAILED(rv))
return rv;
+ for (PRUint32 i = 0; i < childCount; ++i) {
+ PRInt32 type;
+ rv = defaultPrefs->GetPrefType(childArray[i], &type);
+ if (NS_FAILED(rv))
+ return rv;
+ NS_ASSERTION(type == nsIPrefBranch2::PREF_BOOL,
+ "All config.lockdown.* prefs should be boolean");
+ if (type == nsIPrefBranch2::PREF_BOOL) {
+ rv = defaultPrefs->SetBoolPref(childArray[i], PR_FALSE);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
+ return NS_OK;
+}
- // unlock, if it is locked
- prefBranch->UnlockPref(aPrefName);
+nsresult
+nsSystemPref::LoadSystemPrefs()
+{
+ SYSPREF_LOG(("\n====Now Use system prefs==\n"));
+ NS_ASSERTION(!mSysPrefService,
+ "Shouldn't have the pref service here");
+ nsresult rv;
+ mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv) || !mSysPrefService) {
+ FixupLockdownPrefs();
+ SYSPREF_LOG(("...No System Pref Service\n"));
+ return NS_OK;
+ }
- switch (prefType) {
- case nsIPrefBranch::PREF_STRING:
- prefBranch->SetCharPref(aPrefName,
- aPrefValue->stringVal);
- SYSPREF_LOG(("Mozilla value is %s\n", aPrefValue->stringVal));
+ // Cache the pref-branch while we load up the system prefs.
+ NS_ASSERTION(!mCachedUserPrefBranch,
+ "Shouldn't have a cache here");
+ nsCOMPtr<nsIPrefBranch2> userBranch = GetPrefUserBranch();
+ nsCOMPtr<nsIPrefBranch> defaultBranch = GetPrefDefaultBranch();
+ mCachedDefaultPrefBranch = defaultBranch;
+ mCachedUserPrefBranch = userBranch;
+ rv = mSysPrefService->LoadSystemPreferences(this);
+ mCachedDefaultPrefBranch = nsnull;
+ mCachedUserPrefBranch = nsnull;
+
+ if (NS_FAILED(rv)) {
+ // Restore all modified preferences to their original values
+ mSavedPrefs.EnumerateRead(RestorePref, this);
+ mSavedPrefs.Clear();
+ mSysPrefService = nsnull;
+ }
+
+ return rv;
+}
- PL_strfree(aPrefValue->stringVal);
- aPrefValue->stringVal = nsnull;
+nsresult
+nsSystemPref::RestoreMozillaPrefs()
+{
+ SYSPREF_LOG(("\n====Now rollback to Mozilla prefs==\n"));
- break;
- case nsIPrefBranch::PREF_INT:
- prefBranch->SetIntPref(aPrefName, aPrefValue->intVal);
- SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
+ NS_ASSERTION(mSysPrefService,
+ "Should have the pref service here");
+ if (!mSysPrefService)
+ return NS_ERROR_FAILURE;
- break;
- case nsIPrefBranch::PREF_BOOL:
- prefBranch->SetBoolPref(aPrefName, aPrefValue->boolVal);
- SYSPREF_LOG(("Mozilla value is %s\n",
- aPrefValue->boolVal ? "TRUE" : "FALSE"));
+ nsCOMPtr<nsIPrefBranch2> userBranch = GetPrefUserBranch();
+ nsCOMPtr<nsIPrefBranch> defaultBranch = GetPrefDefaultBranch();
+ mCachedDefaultPrefBranch = defaultBranch;
+ mCachedUserPrefBranch = userBranch;
+
+ mSysPrefService->NotifyUnloadSystemPreferences();
+ // Restore all modified preferences to their original values
+ mSavedPrefs.EnumerateRead(RestorePref, this);
+ mSavedPrefs.Clear();
+
+ mCachedDefaultPrefBranch = nsnull;
+ mCachedUserPrefBranch = nsnull;
+
+ mSysPrefService = nsnull;
- break;
- default:
- SYSPREF_LOG(("Fail to Restore Mozilla value for it\n"));
- return NS_ERROR_FAILURE;
- }
+ FixupLockdownPrefs();
- // restore its old lock status
- if (aLocked)
- prefBranch->LockPref(aPrefName);
return NS_OK;
}
--- extensions/pref/system-pref/src/nsSystemPref.h
+++ extensions/pref/system-pref/src/nsSystemPref.h
@@ -23,7 +23,7 @@
*
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
- * Contributor(s):
+ * Contributor(s): Robert O'Callahan/Novell (rocallahan@novell.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -45,16 +45,14 @@
#include "nsCOMPtr.h"
#include "nsXPCOM.h"
#include "nsCRT.h"
-#include "nsIAppStartupNotifier.h"
-#include "nsICategoryManager.h"
-#include "nsIServiceManager.h"
#include "nsWeakReference.h"
-#include "nsIPrefService.h"
-#include "nsIPrefBranch2.h"
+#include "nsClassHashtable.h"
+#include "nsHashKeys.h"
+#include "nsMemory.h"
-#include <nsIObserver.h>
+#include "nsISystemPrefService.h"
+#include "nsIObserver.h"
-union MozPrefValue;
struct SysPrefItem;
//////////////////////////////////////////////////////////////////////////
@@ -62,18 +60,34 @@
// nsSystemPref, as an extension of mozilla pref service, reads some mozilla
// prefs from host system when the feature is enabled ("config.system-pref").
//
-// nsSystemPref listens on NS_PREFSERVICE_READ_TOPIC_ID. When notified,
-// nsSystemPref will start the nsSystemPrefService (platform specific) to
-// read all the interested prefs (listed in sSysPrefList table) from system
-// and lock these prefs from user's modification.
-//
-// This feature will make mozilla integrated better into host platforms. If
-// users want to change the prefs read from system, the system provided pref
-// editor (i.e. gconf-editor in gnome) should be used.
+// nsSystemPref listens on NS_PREFSERVICE_READ_TOPIC_ID. When
+// notified, nsSystemPref will start the nsSystemPrefService (platform
+// specific) and tell it to override Mozilla prefs with its own
+// settings.
+//
+// When overriding a Mozilla preference the prefservice can request the
+// pref be locked or unlocked. If the pref is locked then we set the default
+// value and lock it in Mozilla so the user value is ignored and the user cannot
+// change the value. If the pref is unlocked then we set the user value
+// and unlock it in Mozilla so the user can change it. If the user changes it,
+// then the prefservice is notified so it can copy the value back to its
+// underlying store.
+//
+// We detect changes to Mozilla prefs by observing pref changes in the
+// user branch.
+//
+// For testing purposes, if the user toggles on
+// config.use_system_prefs then we save the current preferences before
+// overriding them from gconf, and if the user toggles off
+// config.use_system_prefs *in the same session* then we restore the
+// preferences. If the user exits without turning off use_system_prefs
+// then the saved values are lost and the new values are permanent.
+//
//////////////////////////////////////////////////////////////////////////
class nsSystemPref : public nsIObserver,
- public nsSupportsWeakReference
+ public nsSupportsWeakReference,
+ public nsISystemPref
{
public:
NS_DECL_ISUPPORTS
@@ -83,23 +97,39 @@
virtual ~nsSystemPref();
nsresult Init(void);
+ // nsISystemPref
+ virtual nsresult SetOverridingMozillaBoolPref(const char* aPrefName,
+ PRBool aValue, PRBool aLocked,
+ PRBool aPresent = PR_TRUE);
+ virtual nsresult SetOverridingMozillaIntPref(const char* aPrefName,
+ PRInt32 aValue, PRBool aLocked,
+ PRBool aPresent = PR_TRUE);
+ virtual nsresult SetOverridingMozillaStringPref(const char* aPrefName,
+ const char* aValue, PRBool aLocked,
+ PRBool aPresent = PR_TRUE);
+ virtual nsresult StopOverridingMozillaPref(const char* aPrefName);
+ virtual already_AddRefed<nsIPrefBranch2> GetPrefUserBranch();
+ virtual already_AddRefed<nsIPrefBranch> GetPrefDefaultBranch();
+
private:
- // funcs used to load system prefs and save mozilla default prefs
- nsresult UseSystemPrefs();
- nsresult ReadSystemPref(const char *aPrefName);
- nsresult SaveMozDefaultPref(const char *aPrefName,
- MozPrefValue *aPrefVal,
- PRBool *aLocked);
-
- // funcs used to load mozilla default prefs
- nsresult UseMozillaPrefs();
- nsresult RestoreMozDefaultPref(const char *aPrefName,
- MozPrefValue *aPrefVal,
- PRBool aLocked);
-
- nsCOMPtr<nsIPrefBranch2> mSysPrefService;
- PRBool mEnabled; // system pref is enabled or not
- SysPrefItem *mSysPrefs;
+ // If we don't load the system prefs for any reason, then
+ // set all config.lockdown.* preferences to PR_FALSE so that
+ // residual lockdown settings are removed.
+ nsresult FixupLockdownPrefs();
+
+ nsresult LoadSystemPrefs();
+
+ nsresult RestoreMozillaPrefs();
+
+ nsresult OverridePref(const char* aPrefName, PRInt32 aType,
+ void* aValue, PRBool aLock, PRBool aPresent);
+
+ nsCOMPtr<nsISystemPrefService> mSysPrefService;
+ nsClassHashtable<nsCStringHashKey,SysPrefItem> mSavedPrefs;
+ // weak pointers to cached prefbranches
+ nsIPrefBranch2* mCachedUserPrefBranch;
+ nsIPrefBranch* mCachedDefaultPrefBranch;
+ PRPackedBool mIgnorePrefSetting;
};
#define NS_SYSTEMPREF_CID \
--- extensions/pref/system-pref/src/nsSystemPrefFactory.cpp
+++ extensions/pref/system-pref/src/nsSystemPrefFactory.cpp
@@ -42,10 +42,10 @@
#include "nsICategoryManager.h"
#include "nsIGenericFactory.h"
#include "nsSystemPref.h"
-#include "nsSystemPrefService.h"
+#include "nsIServiceManager.h"
+#include "nsIAppStartupNotifier.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPref, Init)
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPrefService, Init)
// Registering nsSystemPref module as part of the app-startup category to get
// it instantiated.
@@ -96,11 +96,6 @@
RegisterSystemPref,
UnRegisterSystemPref,
},
- { NS_SYSTEMPREF_SERVICE_CLASSNAME,
- NS_SYSTEMPREF_SERVICE_CID,
- NS_SYSTEMPREF_SERVICE_CONTRACTID,
- nsSystemPrefServiceConstructor,
- },
};
NS_IMPL_NSGETMODULE(nsSystemPrefModule, components)