mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Profile sharing - use in prefs. bug=202474, r=jgaunt/sr=alecf/a=asa
This commit is contained in:
parent
47683e635f
commit
a7e34e6c37
@ -45,6 +45,13 @@ REQUIRES = xpcom \
|
||||
intl \
|
||||
necko \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_PROFILESHARING
|
||||
REQUIRES += transmngr \
|
||||
ipcd \
|
||||
profilesharingsetup \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
@ -56,6 +63,11 @@ CPPSRCS = nsPref.cpp \
|
||||
prefapi.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_PROFILESHARING
|
||||
CPPSRCS += nsSharedPrefHandler.cpp
|
||||
SHARED_LIBRARY_LIBS = $(DIST)/lib/$(LIB_PREFIX)ipcdutil_s.$(LIB_SUFFIX)
|
||||
endif
|
||||
|
||||
PREF_JS_EXPORTS = \
|
||||
$(srcdir)/init/all.js \
|
||||
$(srcdir)/init/mailnews.js \
|
||||
@ -87,6 +99,10 @@ ifeq ($(OS_ARCH),OpenVMS)
|
||||
PREF_JS_EXPORTS += $(srcdir)/unix/openvms.js
|
||||
endif
|
||||
|
||||
ifdef MOZ_PROFILESHARING
|
||||
PREF_JS_EXPORTS += $(srcdir)/init/non-shared.txt
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),AIX)
|
||||
PREF_JS_EXPORTS += $(srcdir)/unix/aix.js
|
||||
endif
|
||||
|
6
modules/libpref/src/init/non-shared.txt
Normal file
6
modules/libpref/src/init/non-shared.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# A list of preferences which are not shared between profile sharing clients.
|
||||
# An entry may be either a complete preference name, or the name of a branch,
|
||||
# in which case, none if its children will be shared.
|
||||
|
||||
signon.SignonFileName
|
||||
|
@ -63,11 +63,20 @@
|
||||
|
||||
#include "nsITimelineService.h"
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
#include "nsIProfileSharingSetup.h"
|
||||
#include "nsSharedPrefHandler.h"
|
||||
#endif
|
||||
|
||||
// Definitions
|
||||
#define INITIAL_MAX_DEFAULT_PREF_FILES 10
|
||||
|
||||
|
||||
// Prototypes
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
static PRBool isSharingEnabled();
|
||||
#endif
|
||||
|
||||
static nsresult openPrefFile(nsIFile* aFile, PRBool aIsErrorFatal,
|
||||
PRBool aIsGlobalContext, PRBool aSkipFirstLine);
|
||||
|
||||
@ -75,19 +84,25 @@ static nsresult openPrefFile(nsIFile* aFile, PRBool aIsErrorFatal,
|
||||
// needed so we can still get the JS Runtime Service during XPCOM shutdown
|
||||
static nsIJSRuntimeService* gJSRuntimeService = nsnull; // owning reference
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Constructor/Destructor
|
||||
*/
|
||||
|
||||
nsPrefService::nsPrefService()
|
||||
: mCurrentFile(nsnull)
|
||||
: mCurrentFile(nsnull),
|
||||
mErrorOpeningUserPrefs(PR_FALSE)
|
||||
{
|
||||
nsPrefBranch *rootBranch;
|
||||
|
||||
rootBranch = new nsPrefBranch("", PR_FALSE);
|
||||
mRootBranch = (nsIPrefBranch *)rootBranch;
|
||||
|
||||
|
||||
#if MOZ_PROFILESHARING
|
||||
mCurrentSharedFile = nsnull;
|
||||
mErrorOpeningSharedUserPrefs = PR_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsPrefService::~nsPrefService()
|
||||
@ -95,6 +110,11 @@ nsPrefService::~nsPrefService()
|
||||
PREF_Cleanup();
|
||||
NS_IF_RELEASE(mCurrentFile);
|
||||
NS_IF_RELEASE(gJSRuntimeService);
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
NS_IF_RELEASE(mCurrentSharedFile);
|
||||
NS_IF_RELEASE(gSharedPrefHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -149,6 +169,11 @@ nsresult nsPrefService::Init()
|
||||
rv = observerService->AddObserver(this, "profile-do-change", PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
rv = NS_CreateSharedPrefHandler(this);
|
||||
#endif
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
@ -164,10 +189,22 @@ NS_IMETHODIMP nsPrefService::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
}
|
||||
} else {
|
||||
rv = SavePrefFile(nsnull);
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
if (isSharingEnabled())
|
||||
rv = gSharedPrefHandler->OnSessionEnd();
|
||||
#endif
|
||||
}
|
||||
} else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
|
||||
ResetUserPrefs();
|
||||
rv = ReadUserPrefs(nsnull);
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
if (isSharingEnabled())
|
||||
rv = gSharedPrefHandler->OnSessionBegin();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ResetUserPrefs();
|
||||
rv = ReadUserPrefs(nsnull);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -182,19 +219,10 @@ NS_IMETHODIMP nsPrefService::ReadUserPrefs(nsIFile *aFile)
|
||||
UseUserPrefFile();
|
||||
|
||||
NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID);
|
||||
|
||||
|
||||
JS_MaybeGC(gMochaContext);
|
||||
} else {
|
||||
if (mCurrentFile == aFile)
|
||||
return NS_OK;
|
||||
|
||||
NS_IF_RELEASE(mCurrentFile);
|
||||
mCurrentFile = aFile;
|
||||
NS_ADDREF(mCurrentFile);
|
||||
|
||||
gErrorOpeningUserPrefs = PR_FALSE;
|
||||
|
||||
rv = openPrefFile(mCurrentFile, PR_TRUE, PR_FALSE, PR_TRUE);
|
||||
rv = ReadAndOwnUserPrefFile(aFile);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -218,19 +246,12 @@ NS_IMETHODIMP nsPrefService::ResetUserPrefs()
|
||||
|
||||
NS_IMETHODIMP nsPrefService::SavePrefFile(nsIFile *aFile)
|
||||
{
|
||||
if (nsnull == aFile) {
|
||||
// the gDirty flag tells us if we should write to mCurrentFile
|
||||
// we only check this flag when the caller wants to write to the default
|
||||
if (!gDirty) {
|
||||
NS_WARNING("not writing prefs because they haven't changed");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// It's possible that we never got a prefs file.
|
||||
return mCurrentFile ? WritePrefFile(mCurrentFile) : NS_OK;
|
||||
} else {
|
||||
return WritePrefFile(aFile);
|
||||
}
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
// sharing only applies to the default prefs file
|
||||
if (aFile == nsnull && isSharingEnabled())
|
||||
return gSharedPrefHandler->OnSavePrefs();
|
||||
#endif
|
||||
return SavePrefFileInternal(aFile);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPrefService::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
|
||||
@ -305,29 +326,39 @@ nsresult nsPrefService::NotifyServiceObservers(const char *aTopic)
|
||||
|
||||
nsresult nsPrefService::UseDefaultPrefFile()
|
||||
{
|
||||
nsresult rv;
|
||||
nsresult rv, rv2;
|
||||
nsCOMPtr<nsIFile> aFile;
|
||||
|
||||
// Anything which calls NS_InitXPCOM will have this
|
||||
rv = NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE, getter_AddRefs(aFile));
|
||||
|
||||
if (!aFile) {
|
||||
// We know we have XPCOM directory services, but we might not have a provider which
|
||||
// knows about NS_APP_PREFS_50_FILE. Put the file in NS_XPCOM_CURRENT_PROCESS_DIR.
|
||||
rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, getter_AddRefs(aFile));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = aFile->AppendNative(NS_LITERAL_CSTRING("default_prefs.js"));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = ReadUserPrefs(aFile);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return rv;
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
// First, read the shared file.
|
||||
if (isSharingEnabled()) {
|
||||
rv = NS_GetSpecialDirectory(NS_SHARED NS_APP_PREFS_50_FILE, getter_AddRefs(aFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = ReadAndOwnSharedUserPrefFile(aFile);
|
||||
// Most likely cause of failure here is that the file didn't
|
||||
// exist, so save a new one. mSharedUserPrefReadFailed will be
|
||||
// used to catch an error in actually reading the file.
|
||||
if (NS_FAILED(rv)) {
|
||||
rv2 = SavePrefFileInternal(aFile);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv2), "Failed to save new shared pref file");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Continue on to read the nonshared file.
|
||||
#endif
|
||||
|
||||
// need to save the prefs now
|
||||
SavePrefFile(aFile);
|
||||
|
||||
rv = NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE, getter_AddRefs(aFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = ReadAndOwnUserPrefFile(aFile);
|
||||
// Most likely cause of failure here is that the file didn't
|
||||
// exist, so save a new one. mUserPrefReadFailed will be
|
||||
// used to catch an error in actually reading the file.
|
||||
if (NS_FAILED(rv)) {
|
||||
rv2 = SavePrefFileInternal(aFile);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv2), "Failed to save new shared pref file");
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -336,7 +367,15 @@ nsresult nsPrefService::UseUserPrefFile()
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIFile> aFile;
|
||||
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(aFile));
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
nsCAutoString prefsDirProp(NS_APP_PREFS_50_DIR);
|
||||
if (isSharingEnabled())
|
||||
prefsDirProp.Insert(NS_SHARED, 0); // Prepend modifier so we get shared file
|
||||
#else
|
||||
nsDependentCString prefsDirProp(NS_APP_PREFS_50_DIR);
|
||||
#endif
|
||||
|
||||
rv = NS_GetSpecialDirectory(prefsDirProp.get(), getter_AddRefs(aFile));
|
||||
if (NS_SUCCEEDED(rv) && aFile) {
|
||||
rv = aFile->AppendNative(NS_LITERAL_CSTRING("user.js"));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -346,6 +385,93 @@ nsresult nsPrefService::UseUserPrefFile()
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsPrefService::ReadAndOwnUserPrefFile(nsIFile *aFile)
|
||||
{
|
||||
NS_ENSURE_ARG(aFile);
|
||||
|
||||
if (mCurrentFile == aFile)
|
||||
return NS_OK;
|
||||
NS_IF_RELEASE(mCurrentFile);
|
||||
mCurrentFile = aFile;
|
||||
NS_ADDREF(mCurrentFile);
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
// We don't want prefs set here to cause transactions
|
||||
gSharedPrefHandler->ReadingUserPrefs(PR_TRUE);
|
||||
#endif
|
||||
|
||||
// We need to track errors in reading the shared and the
|
||||
// non-shared files independently. Clear gErrorOpeningUserPrefs
|
||||
// and set the appropriate member variable from it after reading.
|
||||
gErrorOpeningUserPrefs = PR_FALSE;
|
||||
nsresult rv = openPrefFile(mCurrentFile, PR_TRUE, PR_FALSE, PR_TRUE);
|
||||
mErrorOpeningUserPrefs = gErrorOpeningUserPrefs;
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
gSharedPrefHandler->ReadingUserPrefs(PR_FALSE);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
nsresult nsPrefService::ReadAndOwnSharedUserPrefFile(nsIFile *aFile)
|
||||
{
|
||||
NS_ENSURE_ARG(aFile);
|
||||
|
||||
if (mCurrentSharedFile == aFile)
|
||||
return NS_OK;
|
||||
NS_IF_RELEASE(mCurrentSharedFile);
|
||||
mCurrentSharedFile = aFile;
|
||||
NS_ADDREF(mCurrentSharedFile);
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
// We don't want prefs set here to cause transactions
|
||||
gSharedPrefHandler->ReadingUserPrefs(PR_TRUE);
|
||||
#endif
|
||||
|
||||
// We need to track errors in reading the shared and the
|
||||
// non-shared files independently. Clear gErrorOpeningUserPrefs
|
||||
// and set the appropriate member variable from it after reading.
|
||||
gErrorOpeningUserPrefs = PR_FALSE;
|
||||
nsresult rv = openPrefFile(mCurrentSharedFile, PR_TRUE, PR_FALSE, PR_TRUE);
|
||||
mErrorOpeningSharedUserPrefs = gErrorOpeningUserPrefs;
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
gSharedPrefHandler->ReadingUserPrefs(PR_FALSE);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult nsPrefService::SavePrefFileInternal(nsIFile *aFile)
|
||||
{
|
||||
if (nsnull == aFile) {
|
||||
// the gDirty flag tells us if we should write to mCurrentFile
|
||||
// we only check this flag when the caller wants to write to the default
|
||||
if (!gDirty)
|
||||
return NS_OK;
|
||||
|
||||
// It's possible that we never got a prefs file.
|
||||
nsresult rv = NS_OK;
|
||||
if (mCurrentFile)
|
||||
rv = WritePrefFile(mCurrentFile);
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
if (mCurrentSharedFile) {
|
||||
nsresult rv2 = WritePrefFile(mCurrentSharedFile);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = rv2;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
} else {
|
||||
return WritePrefFile(aFile);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsPrefService::WritePrefFile(nsIFile* aFile)
|
||||
{
|
||||
const char outHeader[] =
|
||||
@ -378,8 +504,12 @@ nsresult nsPrefService::WritePrefFile(nsIFile* aFile)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
/* ?! Don't save (blank) user prefs if there was an error reading them */
|
||||
if (gErrorOpeningUserPrefs)
|
||||
if (aFile == mCurrentFile && mErrorOpeningUserPrefs)
|
||||
return NS_OK;
|
||||
#if MOZ_PROFILESHARING
|
||||
if (aFile == mCurrentSharedFile && mErrorOpeningSharedUserPrefs)
|
||||
return NS_OK;
|
||||
#endif
|
||||
|
||||
// execute a "safe" save by saving through a tempfile
|
||||
PRInt32 numCopies = 1;
|
||||
@ -397,12 +527,25 @@ nsresult nsPrefService::WritePrefFile(nsIFile* aFile)
|
||||
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream), aFile);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
||||
// write out the file header
|
||||
rv = outStream->Write(outHeader, sizeof(outHeader) - 1, &writeAmount);
|
||||
|
||||
pref_saveArgs saveArgs;
|
||||
saveArgs.prefArray = valueArray;
|
||||
saveArgs.saveTypes = SAVE_ALL;
|
||||
|
||||
#if MOZ_PROFILESHARING
|
||||
if (isSharingEnabled()) {
|
||||
if (aFile == mCurrentSharedFile)
|
||||
saveArgs.saveTypes = SAVE_SHARED;
|
||||
else if (aFile == mCurrentFile)
|
||||
saveArgs.saveTypes = SAVE_NONSHARED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// get the lines that we're supposed to be writing to the file
|
||||
PL_DHashTableEnumerate(&gHashTable, pref_savePref, valueArray);
|
||||
PL_DHashTableEnumerate(&gHashTable, pref_savePref, &saveArgs);
|
||||
|
||||
/* Sort the preferences to make a readable file on disk */
|
||||
NS_QuickSort(valueArray, gHashTable.entryCount, sizeof(char *), pref_CompareStrings, NULL);
|
||||
@ -436,6 +579,22 @@ nsresult nsPrefService::WritePrefFile(nsIFile* aFile)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
static PRBool isSharingEnabled()
|
||||
{
|
||||
static PRBool gSharingEnabled = PR_FALSE;
|
||||
|
||||
// If FALSE, query again. It may not have been set yet.
|
||||
if (!gSharingEnabled) {
|
||||
nsCOMPtr<nsIProfileSharingSetup> sharingSetup =
|
||||
do_GetService("@mozilla.org/embedcomp/profile-sharing-setup;1");
|
||||
if (sharingSetup)
|
||||
sharingSetup->GetIsSharingEnabled(&gSharingEnabled);
|
||||
}
|
||||
return gSharingEnabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
static nsresult openPrefFile(nsIFile* aFile, PRBool aIsErrorFatal,
|
||||
PRBool aIsGlobalContext, PRBool aSkipFirstLine)
|
||||
{
|
||||
|
@ -51,6 +51,8 @@ class nsPrefService : public nsIPrefService,
|
||||
public nsIPrefBranchInternal,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
friend class nsSharedPrefHandler;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPREFSERVICE
|
||||
@ -67,11 +69,17 @@ protected:
|
||||
nsresult NotifyServiceObservers(const char *aSubject);
|
||||
nsresult UseDefaultPrefFile();
|
||||
nsresult UseUserPrefFile();
|
||||
nsresult ReadAndOwnUserPrefFile(nsIFile *aFile);
|
||||
nsresult ReadAndOwnSharedUserPrefFile(nsIFile *aFile);
|
||||
nsresult SavePrefFileInternal(nsIFile* aFile);
|
||||
nsresult WritePrefFile(nsIFile* aFile);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIPrefBranch> mRootBranch;
|
||||
nsIFile* mCurrentFile;
|
||||
|
||||
PRPackedBool mErrorOpeningUserPrefs;
|
||||
|
||||
PRPackedBool mErrorOpeningSharedUserPrefs;
|
||||
nsIFile* mCurrentSharedFile;
|
||||
};
|
||||
|
||||
|
432
modules/libpref/src/nsSharedPrefHandler.cpp
Normal file
432
modules/libpref/src/nsSharedPrefHandler.cpp
Normal file
@ -0,0 +1,432 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen <ccarlen@netscape.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
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsSharedPrefHandler.h"
|
||||
#include "nsPrefService.h"
|
||||
|
||||
#include "nsIServiceManagerUtils.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "ipcMessageReader.h"
|
||||
#include "ipcMessageWriter.h"
|
||||
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
// set NSPR_LOG_MODULES=nsSharedPrefHandler:5
|
||||
PRLogModuleInfo *gPrefsTransactionObserverLog = nsnull;
|
||||
#define LOG(args) PR_LOG(PrefsTransactionObserver, PR_LOG_DEBUG, args)
|
||||
#else
|
||||
#define LOG(args)
|
||||
#endif
|
||||
|
||||
nsSharedPrefHandler *gSharedPrefHandler = nsnull;
|
||||
|
||||
// Constants
|
||||
#define kPrefsTSQueueName NS_LITERAL_CSTRING("prefs")
|
||||
|
||||
#define kExceptionListFileName NS_LITERAL_CSTRING("nonshared.txt")
|
||||
const char kExceptionListCommentChar = '#';
|
||||
|
||||
const PRUint32 kCurrentPrefsTransactionDataVersion = 1;
|
||||
|
||||
// Static function prototypes
|
||||
static PRBool PR_CALLBACK enumFind(void* aElement, void *aData);
|
||||
static PRBool PR_CALLBACK enumFree(void* aElement, void *aData);
|
||||
static PRInt32 ReadLine(FILE* inStm, nsACString& destString);
|
||||
|
||||
|
||||
//****************************************************************************
|
||||
// Transaction Format for kCurrentPrefsTransactionDataVersion
|
||||
//****************************************************************************
|
||||
|
||||
/*
|
||||
NOTE: All string data is null terminated.
|
||||
The data length includes the null character.
|
||||
|
||||
PRUint32 dataVersion
|
||||
PRUint32 action SET or CLEAR
|
||||
PRUint32 prefNameLen
|
||||
char prefName[prefNameLen]
|
||||
PRUint32 prefValueKind
|
||||
PRUint32 prefValueLen
|
||||
char prefValue[prefValueLen]
|
||||
*/
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSharedPrefHandler
|
||||
//*****************************************************************************
|
||||
|
||||
nsSharedPrefHandler::nsSharedPrefHandler() :
|
||||
mPrefService(nsnull), mPrefsTSQueueName("prefs"),
|
||||
mSessionActive(PR_FALSE),
|
||||
mReadingUserPrefs(PR_FALSE),
|
||||
mProcessingTransaction(PR_FALSE)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
if (!gPrefsTransactionObserverLog)
|
||||
gPrefsTransactionObserverLog = PR_NewLogModule("nsSharedPrefHandler");
|
||||
#endif
|
||||
}
|
||||
|
||||
nsSharedPrefHandler::~nsSharedPrefHandler()
|
||||
{
|
||||
mExceptionList.EnumerateForwards(enumFree, nsnull);
|
||||
}
|
||||
|
||||
nsresult nsSharedPrefHandler::OnSessionBegin()
|
||||
{
|
||||
nsresult rv = EnsureTransactionService();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// When the reply to this comes (synchronously), we'll actually
|
||||
// read in our data. The transaction service holds a lock on
|
||||
// our data file during our reply.
|
||||
rv = mTransService->Attach(kPrefsTSQueueName, this, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "tmITransactionService::Attach() failed");
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mSessionActive = PR_TRUE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsSharedPrefHandler::OnSessionEnd()
|
||||
{
|
||||
nsresult rv = EnsureTransactionService();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mTransService->Detach(kPrefsTSQueueName);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "tmITransactionService::Detach() failed");
|
||||
|
||||
mSessionActive = PR_FALSE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsSharedPrefHandler::OnSavePrefs()
|
||||
{
|
||||
nsresult rv = EnsureTransactionService();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// When the reply to this comes (synchronously), we'll actually
|
||||
// write out our data. The transaction service holds a lock on
|
||||
// our data file during our reply.
|
||||
rv = mTransService->Flush(kPrefsTSQueueName, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "tmITransactionService::Flush() failed");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsSharedPrefHandler::OnPrefChanged(PrefAction action,
|
||||
PrefHashEntry* pref,
|
||||
PrefValue newValue)
|
||||
{
|
||||
if (!mSessionActive)
|
||||
return NS_OK;
|
||||
if (action != PREF_SETUSER)
|
||||
return NS_OK;
|
||||
if (!IsPrefShared(pref->key))
|
||||
return NS_OK;
|
||||
if (mReadingUserPrefs || mProcessingTransaction)
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = EnsureTransactionService();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 valueLen, prefNameLen = strlen(pref->key);
|
||||
|
||||
ipcMessageWriter outMsg(256);
|
||||
outMsg.PutInt32(kCurrentPrefsTransactionDataVersion);
|
||||
outMsg.PutInt32(action);
|
||||
outMsg.PutInt32(prefNameLen + 1);
|
||||
outMsg.PutBytes(pref->key, prefNameLen + 1);
|
||||
|
||||
switch (pref->flags & PREF_VALUETYPE_MASK) {
|
||||
case PREF_STRING:
|
||||
outMsg.PutInt32(PREF_STRING);
|
||||
valueLen = strlen(newValue.stringVal) + 1;
|
||||
outMsg.PutInt32(valueLen);
|
||||
outMsg.PutBytes(newValue.stringVal, valueLen);
|
||||
break;
|
||||
case PREF_INT:
|
||||
outMsg.PutInt32(PREF_INT);
|
||||
outMsg.PutInt32(sizeof(PRInt32));
|
||||
outMsg.PutInt32(newValue.intVal);
|
||||
break;
|
||||
case PREF_BOOL:
|
||||
outMsg.PutInt32(PREF_BOOL);
|
||||
outMsg.PutInt32(sizeof(PRInt32));
|
||||
outMsg.PutInt32(newValue.boolVal);
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv = outMsg.HasError() ? NS_ERROR_FAILURE : NS_OK;
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "OnPrefChanged: outMsg failed");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mTransService->PostTransaction(kPrefsTSQueueName, outMsg.GetBuffer(), outMsg.GetSize());
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "tmITransactionService::PostTransaction() failed");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool nsSharedPrefHandler::IsPrefShared(const char* prefName)
|
||||
{
|
||||
if (!mExceptionList.Count()) // quick check for empty list
|
||||
return PR_TRUE;
|
||||
|
||||
// returns PR_TRUE if we reached the end without finding it.
|
||||
return mExceptionList.EnumerateForwards(enumFind, NS_CONST_CAST(char*, prefName));
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSharedPrefHandler Protected Methods
|
||||
//*****************************************************************************
|
||||
|
||||
nsresult nsSharedPrefHandler::Init(nsPrefService* aOwner)
|
||||
{
|
||||
NS_ENSURE_ARG(aOwner);
|
||||
mPrefService = aOwner;
|
||||
(void)ReadExceptionFile();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsSharedPrefHandler::ReadExceptionFile()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIProperties> directoryService =
|
||||
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsILocalFile> exceptionFile;
|
||||
rv = directoryService->Get(NS_APP_PREF_DEFAULTS_50_DIR, NS_GET_IID(nsILocalFile),
|
||||
getter_AddRefs(exceptionFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = exceptionFile->AppendNative(kExceptionListFileName);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
FILE *inStm;
|
||||
rv = exceptionFile->OpenANSIFileDesc("r", &inStm);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString lineStr;
|
||||
while (ReadLine(inStm, lineStr) != EOF) {
|
||||
lineStr.CompressWhitespace();
|
||||
if (lineStr.IsEmpty() || lineStr.CharAt(0) == kExceptionListCommentChar)
|
||||
continue;
|
||||
|
||||
char *rawStr = ToNewCString(lineStr);
|
||||
if (!rawStr) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
mExceptionList.AppendElement(rawStr);
|
||||
}
|
||||
fclose(inStm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsSharedPrefHandler::EnsureTransactionService()
|
||||
{
|
||||
if (mTransService)
|
||||
return NS_OK;
|
||||
nsresult rv;
|
||||
mTransService = do_GetService("@mozilla.org/transaction/service;1", &rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSharedPrefHandler::nsISupports
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsSharedPrefHandler, tmITransactionObserver)
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSharedPrefHandler::tmITransactionObserver
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMETHODIMP nsSharedPrefHandler::OnTransactionAvailable(PRUint32 aQueueID, const PRUint8 *aData, PRUint32 aDataLen)
|
||||
{
|
||||
LOG(("nsSharedPrefHandler::OnTransactionAvailable [%s]\n", aData));
|
||||
|
||||
ipcMessageReader inMsg(aData, aDataLen);
|
||||
|
||||
PRUint32 dataVersion, prefAction, dataLen, prefKind, tempInt32;
|
||||
const char *stringStart;
|
||||
|
||||
dataVersion = inMsg.GetInt32();
|
||||
NS_ENSURE_TRUE(dataVersion == kCurrentPrefsTransactionDataVersion, NS_ERROR_INVALID_ARG);
|
||||
prefAction = inMsg.GetInt32();
|
||||
dataLen = inMsg.GetInt32(); // includes terminating null
|
||||
stringStart = (const char *)inMsg.GetPtr();
|
||||
nsDependentCString prefNameStr(stringStart);
|
||||
inMsg.AdvancePtr(dataLen);
|
||||
prefKind = inMsg.GetInt32();
|
||||
dataLen = inMsg.GetInt32();
|
||||
|
||||
mProcessingTransaction = PR_TRUE; // Don't generate transactions for these
|
||||
switch (prefKind) {
|
||||
case PREF_STRING:
|
||||
{
|
||||
stringStart = (const char *)inMsg.GetPtr();
|
||||
nsDependentCString prefStrValueStr(stringStart);
|
||||
inMsg.AdvancePtr(dataLen);
|
||||
NS_ASSERTION(!inMsg.HasError(), "error in reading transaction");
|
||||
if (!inMsg.HasError())
|
||||
PREF_SetCharPref(prefNameStr.get(), prefStrValueStr.get());
|
||||
}
|
||||
break;
|
||||
case PREF_INT:
|
||||
tempInt32 = inMsg.GetInt32();
|
||||
NS_ASSERTION(!inMsg.HasError(), "error in reading transaction");
|
||||
if (!inMsg.HasError())
|
||||
PREF_SetIntPref(prefNameStr.get(), tempInt32);
|
||||
break;
|
||||
case PREF_BOOL:
|
||||
tempInt32 = inMsg.GetInt32();
|
||||
NS_ASSERTION(!inMsg.HasError(), "error in reading transaction");
|
||||
if (!inMsg.HasError())
|
||||
PREF_SetBoolPref(prefNameStr.get(), tempInt32);
|
||||
break;
|
||||
}
|
||||
mProcessingTransaction = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSharedPrefHandler::OnAttachReply(PRUint32 aQueueID, PRUint32 aStatus)
|
||||
{
|
||||
LOG(("nsSharedPrefHandler::OnAttachReply [%d]\n", aStatus));
|
||||
|
||||
// The transaction service holds a lock on the file during this call.
|
||||
mPrefService->ResetUserPrefs();
|
||||
mPrefService->ReadUserPrefs(nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSharedPrefHandler::OnDetachReply(PRUint32 aQueueID, PRUint32 aStatus)
|
||||
{
|
||||
LOG(("tmModuleTest: nsSharedPrefHandler::OnDetachReply [%d]\n", aStatus));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSharedPrefHandler::OnFlushReply(PRUint32 aQueueID, PRUint32 aStatus)
|
||||
{
|
||||
LOG(("tmModuleTest: nsSharedPrefHandler::OnFlushReply [%d]\n", aStatus));
|
||||
|
||||
// Call the internal method to write immediately
|
||||
// The transaction service holds a lock on the file during this call.
|
||||
mPrefService->SavePrefFileInternal(nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Static functions
|
||||
//*****************************************************************************
|
||||
|
||||
static PRBool PR_CALLBACK enumFind(void* aElement, void *aData)
|
||||
{
|
||||
char *elemStr = NS_STATIC_CAST(char*, aElement);
|
||||
char *searchStr = NS_STATIC_CAST(char*, aData);
|
||||
// return PR_FALSE for a match and to stop search
|
||||
return (strncmp(elemStr, searchStr, strlen(elemStr)) != 0);
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK enumFree(void* aElement, void *aData)
|
||||
{
|
||||
if (aElement)
|
||||
nsMemory::Free(aElement);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRInt32 ReadLine(FILE* inStm, nsACString& destString)
|
||||
{
|
||||
char stackBuf[512];
|
||||
PRUint32 charsInBuf = 0;
|
||||
destString.Truncate();
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
c = getc(inStm);
|
||||
if (c == EOF)
|
||||
break;
|
||||
else if (c == '\r') {
|
||||
c = getc(inStm);
|
||||
if (c != '\n')
|
||||
ungetc(c, inStm);
|
||||
break;
|
||||
}
|
||||
else if (c == '\n')
|
||||
break;
|
||||
else {
|
||||
if (charsInBuf >= sizeof(stackBuf)) {
|
||||
destString.Append(stackBuf, charsInBuf);
|
||||
charsInBuf = 0;
|
||||
}
|
||||
stackBuf[charsInBuf++] = c;
|
||||
}
|
||||
}
|
||||
if (charsInBuf)
|
||||
destString.Append(stackBuf, charsInBuf);
|
||||
return (c == EOF && destString.IsEmpty()) ? EOF : 1;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// NS_CreateSharedPrefHandler
|
||||
//*****************************************************************************
|
||||
|
||||
nsresult NS_CreateSharedPrefHandler(nsPrefService *aOwner)
|
||||
{
|
||||
nsSharedPrefHandler *local = new nsSharedPrefHandler;
|
||||
if (!local)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsresult rv = local->Init(aOwner);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete local;
|
||||
return rv;
|
||||
}
|
||||
NS_ADDREF(gSharedPrefHandler = local);
|
||||
return NS_OK;
|
||||
}
|
||||
|
115
modules/libpref/src/nsSharedPrefHandler.h
Normal file
115
modules/libpref/src/nsSharedPrefHandler.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen <ccarlen@netscape.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
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsSharedPrefHandler_h__
|
||||
#define nsSharedPrefHandler_h__
|
||||
|
||||
// Interfaces needed
|
||||
#include "tmITransactionService.h"
|
||||
|
||||
// Includes
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
// Local includes
|
||||
#include "prefapi.h"
|
||||
|
||||
// Forward declarations
|
||||
class nsPrefService;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// nsSharedPrefHandler
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
class nsSharedPrefHandler : public tmITransactionObserver
|
||||
{
|
||||
friend nsresult NS_CreateSharedPrefHandler(nsPrefService*);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_TMITRANSACTIONOBSERVER
|
||||
|
||||
public:
|
||||
nsresult OnSessionBegin();
|
||||
nsresult OnSessionEnd();
|
||||
|
||||
nsresult OnSavePrefs();
|
||||
|
||||
nsresult OnPrefChanged(PrefAction action,
|
||||
PrefHashEntry* pref,
|
||||
PrefValue newValue);
|
||||
|
||||
void ReadingUserPrefs(PRBool isReading)
|
||||
{ mReadingUserPrefs = isReading; }
|
||||
|
||||
PRBool IsPrefShared(const char* prefName);
|
||||
|
||||
protected:
|
||||
nsSharedPrefHandler();
|
||||
virtual ~nsSharedPrefHandler();
|
||||
|
||||
nsresult Init(nsPrefService *aOwner);
|
||||
nsresult ReadExceptionFile();
|
||||
nsresult EnsureTransactionService();
|
||||
|
||||
protected:
|
||||
nsPrefService *mPrefService; // weak ref
|
||||
|
||||
nsCOMPtr<tmITransactionService> mTransService;
|
||||
const nsCString mPrefsTSQueueName;
|
||||
|
||||
PRPackedBool mSessionActive;
|
||||
PRPackedBool mReadingUserPrefs;
|
||||
PRPackedBool mProcessingTransaction;
|
||||
|
||||
nsAutoVoidArray mExceptionList;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
extern nsSharedPrefHandler *gSharedPrefHandler; // greasy, but used by procedural code.
|
||||
|
||||
/**
|
||||
* Global method to create gSharedPrefHandler
|
||||
*
|
||||
* @param aOwner
|
||||
*/
|
||||
|
||||
extern nsresult NS_CreateSharedPrefHandler(nsPrefService *aOwner);
|
||||
|
||||
#endif // nsSharedPrefHandler_h__
|
@ -69,6 +69,10 @@
|
||||
#include "nsPrintfCString.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
#include "nsSharedPrefHandler.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_OS2
|
||||
#define INCL_DOS
|
||||
#include <os2.h>
|
||||
@ -542,7 +546,7 @@ PREF_SetDefaultBoolPref(const char *pref_name,PRBool value)
|
||||
PLDHashOperator
|
||||
pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, PRUint32 i, void *arg)
|
||||
{
|
||||
char **prefArray = (char**) arg;
|
||||
pref_saveArgs *argData = NS_STATIC_CAST(pref_saveArgs *, arg);
|
||||
PrefHashEntry *pref = NS_STATIC_CAST(PrefHashEntry *, heh);
|
||||
|
||||
PR_ASSERT(pref);
|
||||
@ -565,6 +569,14 @@ pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, PRUint32 i, void *arg)
|
||||
// do not save default prefs that haven't changed
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
#if MOZ_PROFILESHARING
|
||||
if ((argData->saveTypes == SAVE_SHARED &&
|
||||
!gSharedPrefHandler->IsPrefShared(pref->key)) ||
|
||||
(argData->saveTypes == SAVE_NONSHARED &&
|
||||
gSharedPrefHandler->IsPrefShared(pref->key)))
|
||||
return PL_DHASH_NEXT;
|
||||
#endif
|
||||
|
||||
// strings are in quotes!
|
||||
if (pref->flags & PREF_STRING) {
|
||||
prefValue = '\"';
|
||||
@ -581,7 +593,7 @@ pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, PRUint32 i, void *arg)
|
||||
nsCAutoString prefName;
|
||||
str_escape(pref->key, prefName);
|
||||
|
||||
prefArray[i] = ToNewCString(NS_LITERAL_CSTRING("user_pref(\"") +
|
||||
argData->prefArray[i] = ToNewCString(NS_LITERAL_CSTRING("user_pref(\"") +
|
||||
prefName +
|
||||
NS_LITERAL_CSTRING("\", ") +
|
||||
prefValue +
|
||||
@ -1017,6 +1029,10 @@ PrefResult pref_HashPref(const char *key, PrefValue value, PrefType type, PrefAc
|
||||
if (result2 < 0)
|
||||
result = result2;
|
||||
}
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
if (gSharedPrefHandler)
|
||||
gSharedPrefHandler->OnPrefChanged(action, pref, value);
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -41,6 +41,15 @@ extern JSContext * gMochaContext;
|
||||
extern PRBool gErrorOpeningUserPrefs;
|
||||
extern PLDHashTable gHashTable;
|
||||
extern PRBool gDirty;
|
||||
|
||||
enum pref_SaveTypes { SAVE_NONSHARED, SAVE_SHARED, SAVE_ALL };
|
||||
|
||||
// Passed as the arg to pref_savePref
|
||||
struct pref_saveArgs {
|
||||
char **prefArray;
|
||||
pref_SaveTypes saveTypes;
|
||||
};
|
||||
|
||||
PLDHashOperator PR_CALLBACK pref_savePref(PLDHashTable*, PLDHashEntryHdr *, PRUint32, void *arg);
|
||||
|
||||
int PR_CALLBACK pref_CompareStrings(const void *v1, const void *v2, void* unused);
|
||||
|
Loading…
Reference in New Issue
Block a user