1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Alec Flett <alecf@netscape.com>
24 * Brian Nesse <bnesse@netscape.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsPrefBranch.h"
41 #include "nsILocalFile.h"
42 #include "nsIObserverService.h"
44 #include "nsISupportsPrimitives.h"
45 #include "nsIDirectoryService.h"
47 #include "nsReadableUtils.h"
48 #include "nsXPIDLString.h"
49 #include "nsIStringBundle.h"
53 #include "nsPrefsCID.h"
55 #ifndef MOZ_NO_XPCOM_OBSOLETE
56 #include "nsIFileSpec.h" // this should be removed eventually
62 #include "prefapi_private_data.h"
65 struct EnumerateData
{
67 nsVoidArray
*pref_list
;
70 struct PrefCallbackData
{
71 nsPrefBranch
*pBranch
;
72 nsIObserver
*pObserver
;
73 nsIWeakReference
*pWeakRef
;
78 static PLDHashOperator
79 pref_enumChild(PLDHashTable
*table
, PLDHashEntryHdr
*heh
,
80 PRUint32 i
, void *arg
);
82 NotifyObserver(const char *newpref
, void *data
);
85 * Constructor/Destructor
88 nsPrefBranch::nsPrefBranch(const char *aPrefRoot
, PRBool aDefaultBranch
)
91 mPrefRoot
= aPrefRoot
;
92 mPrefRootLength
= mPrefRoot
.Length();
93 mIsDefault
= aDefaultBranch
;
95 nsCOMPtr
<nsIObserverService
> observerService
=
96 do_GetService("@mozilla.org/observer-service;1");
97 if (observerService
) {
98 ++mRefCnt
; // Our refcnt must be > 0 when we call this, or we'll get deleted!
99 // add weak so we don't have to clean up at shutdown
100 observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, PR_TRUE
);
105 nsPrefBranch::~nsPrefBranch()
112 * nsISupports Implementation
115 NS_IMPL_THREADSAFE_ADDREF(nsPrefBranch
)
116 NS_IMPL_THREADSAFE_RELEASE(nsPrefBranch
)
118 NS_INTERFACE_MAP_BEGIN(nsPrefBranch
)
119 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIPrefBranch
)
120 NS_INTERFACE_MAP_ENTRY(nsIPrefBranch
)
121 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIPrefBranch2
, !mIsDefault
)
122 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIPrefBranchInternal
, !mIsDefault
)
123 NS_INTERFACE_MAP_ENTRY(nsISecurityPref
)
124 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
125 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
130 * nsIPrefBranch Implementation
133 NS_IMETHODIMP
nsPrefBranch::GetRoot(char * *aRoot
)
135 NS_ENSURE_ARG_POINTER(aRoot
);
137 mPrefRoot
.Truncate(mPrefRootLength
);
138 *aRoot
= ToNewCString(mPrefRoot
);
142 NS_IMETHODIMP
nsPrefBranch::GetPrefType(const char *aPrefName
, PRInt32
*_retval
)
147 rv
= getValidatedPrefName(aPrefName
, &pref
);
151 *_retval
= PREF_GetPrefType(pref
);
155 NS_IMETHODIMP
nsPrefBranch::GetBoolPref(const char *aPrefName
, PRBool
*_retval
)
160 rv
= getValidatedPrefName(aPrefName
, &pref
);
161 if (NS_SUCCEEDED(rv
)) {
162 rv
= PREF_GetBoolPref(pref
, _retval
, mIsDefault
);
167 NS_IMETHODIMP
nsPrefBranch::SetBoolPref(const char *aPrefName
, PRInt32 aValue
)
172 rv
= getValidatedPrefName(aPrefName
, &pref
);
173 if (NS_SUCCEEDED(rv
)) {
174 rv
= PREF_SetBoolPref(pref
, aValue
, mIsDefault
);
179 NS_IMETHODIMP
nsPrefBranch::GetCharPref(const char *aPrefName
, char **_retval
)
184 rv
= getValidatedPrefName(aPrefName
, &pref
);
185 if (NS_SUCCEEDED(rv
)) {
186 rv
= PREF_CopyCharPref(pref
, _retval
, mIsDefault
);
191 NS_IMETHODIMP
nsPrefBranch::SetCharPref(const char *aPrefName
, const char *aValue
)
196 NS_ENSURE_ARG_POINTER(aValue
);
197 rv
= getValidatedPrefName(aPrefName
, &pref
);
198 if (NS_SUCCEEDED(rv
)) {
199 rv
= PREF_SetCharPref(pref
, aValue
, mIsDefault
);
204 NS_IMETHODIMP
nsPrefBranch::GetIntPref(const char *aPrefName
, PRInt32
*_retval
)
209 rv
= getValidatedPrefName(aPrefName
, &pref
);
210 if (NS_SUCCEEDED(rv
)) {
211 rv
= PREF_GetIntPref(pref
, _retval
, mIsDefault
);
216 NS_IMETHODIMP
nsPrefBranch::SetIntPref(const char *aPrefName
, PRInt32 aValue
)
221 rv
= getValidatedPrefName(aPrefName
, &pref
);
222 if (NS_SUCCEEDED(rv
)) {
223 rv
= PREF_SetIntPref(pref
, aValue
, mIsDefault
);
228 NS_IMETHODIMP
nsPrefBranch::GetComplexValue(const char *aPrefName
, const nsIID
& aType
, void * *_retval
)
231 nsXPIDLCString utf8String
;
233 // we have to do this one first because it's different than all the rest
234 if (aType
.Equals(NS_GET_IID(nsIPrefLocalizedString
))) {
235 nsCOMPtr
<nsIPrefLocalizedString
> theString(do_CreateInstance(NS_PREFLOCALIZEDSTRING_CONTRACTID
, &rv
));
237 if (NS_SUCCEEDED(rv
)) {
239 PRBool bNeedDefault
= PR_FALSE
;
241 rv
= getValidatedPrefName(aPrefName
, &pref
);
246 bNeedDefault
= PR_TRUE
;
248 // if there is no user (or locked) value
249 if (!PREF_HasUserPref(pref
) && !PREF_PrefIsLocked(pref
)) {
250 bNeedDefault
= PR_TRUE
;
254 // if we need to fetch the default value, do that instead, otherwise use the
255 // value we pulled in at the top of this function
257 nsXPIDLString utf16String
;
258 rv
= GetDefaultFromPropertiesFile(pref
, getter_Copies(utf16String
));
259 if (NS_SUCCEEDED(rv
)) {
260 rv
= theString
->SetData(utf16String
.get());
263 rv
= GetCharPref(aPrefName
, getter_Copies(utf8String
));
264 if (NS_SUCCEEDED(rv
)) {
265 rv
= theString
->SetData(NS_ConvertUTF8toUTF16(utf8String
).get());
268 if (NS_SUCCEEDED(rv
)) {
269 nsIPrefLocalizedString
*temp
= theString
;
272 *_retval
= (void *)temp
;
279 // if we can't get the pref, there's no point in being here
280 rv
= GetCharPref(aPrefName
, getter_Copies(utf8String
));
285 if (aType
.Equals(NS_GET_IID(nsILocalFile
))) {
286 nsCOMPtr
<nsILocalFile
> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID
, &rv
));
288 if (NS_SUCCEEDED(rv
)) {
289 rv
= file
->SetPersistentDescriptor(utf8String
);
290 if (NS_SUCCEEDED(rv
)) {
291 nsILocalFile
*temp
= file
;
294 *_retval
= (void *)temp
;
301 if (aType
.Equals(NS_GET_IID(nsIRelativeFilePref
))) {
302 nsACString::const_iterator keyBegin
, strEnd
;
303 utf8String
.BeginReading(keyBegin
);
304 utf8String
.EndReading(strEnd
);
306 // The pref has the format: [fromKey]a/b/c
307 if (*keyBegin
++ != '[')
308 return NS_ERROR_FAILURE
;
309 nsACString::const_iterator
keyEnd(keyBegin
);
310 if (!FindCharInReadable(']', keyEnd
, strEnd
))
311 return NS_ERROR_FAILURE
;
312 nsCAutoString
key(Substring(keyBegin
, keyEnd
));
314 nsCOMPtr
<nsILocalFile
> fromFile
;
315 nsCOMPtr
<nsIProperties
> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
));
318 rv
= directoryService
->Get(key
.get(), NS_GET_IID(nsILocalFile
), getter_AddRefs(fromFile
));
322 nsCOMPtr
<nsILocalFile
> theFile
;
323 rv
= NS_NewNativeLocalFile(EmptyCString(), PR_TRUE
, getter_AddRefs(theFile
));
326 rv
= theFile
->SetRelativeDescriptor(fromFile
, Substring(++keyEnd
, strEnd
));
329 nsCOMPtr
<nsIRelativeFilePref
> relativePref
;
330 rv
= NS_NewRelativeFilePref(theFile
, key
, getter_AddRefs(relativePref
));
334 *_retval
= relativePref
;
335 NS_ADDREF(static_cast<nsIRelativeFilePref
*>(*_retval
));
339 if (aType
.Equals(NS_GET_IID(nsISupportsString
))) {
340 nsCOMPtr
<nsISupportsString
> theString(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID
, &rv
));
342 if (NS_SUCCEEDED(rv
)) {
343 rv
= theString
->SetData(NS_ConvertUTF8toUTF16(utf8String
));
344 if (NS_SUCCEEDED(rv
)) {
345 nsISupportsString
*temp
= theString
;
348 *_retval
= (void *)temp
;
355 // This is deprecated and you should not be using it
356 #ifndef MOZ_NO_XPCOM_OBSOLETE
357 if (aType
.Equals(NS_GET_IID(nsIFileSpec
))) {
358 nsCOMPtr
<nsIFileSpec
> file(do_CreateInstance(NS_FILESPEC_CONTRACTID
, &rv
));
360 if (NS_SUCCEEDED(rv
)) {
361 nsIFileSpec
*temp
= file
;
364 file
->SetPersistentDescriptorString(utf8String
); // only returns NS_OK
365 file
->IsValid(&valid
);
367 /* if the string wasn't a valid persistent descriptor, it might be a valid native path */
368 file
->SetNativePath(utf8String
);
371 *_retval
= (void *)temp
;
378 NS_WARNING("nsPrefBranch::GetComplexValue - Unsupported interface type");
379 return NS_NOINTERFACE
;
382 NS_IMETHODIMP
nsPrefBranch::SetComplexValue(const char *aPrefName
, const nsIID
& aType
, nsISupports
*aValue
)
384 nsresult rv
= NS_NOINTERFACE
;
386 if (aType
.Equals(NS_GET_IID(nsILocalFile
))) {
387 nsCOMPtr
<nsILocalFile
> file
= do_QueryInterface(aValue
);
389 return NS_NOINTERFACE
;
390 nsCAutoString descriptorString
;
392 rv
= file
->GetPersistentDescriptor(descriptorString
);
393 if (NS_SUCCEEDED(rv
)) {
394 rv
= SetCharPref(aPrefName
, descriptorString
.get());
399 if (aType
.Equals(NS_GET_IID(nsIRelativeFilePref
))) {
400 nsCOMPtr
<nsIRelativeFilePref
> relFilePref
= do_QueryInterface(aValue
);
402 return NS_NOINTERFACE
;
404 nsCOMPtr
<nsILocalFile
> file
;
405 relFilePref
->GetFile(getter_AddRefs(file
));
407 return NS_NOINTERFACE
;
408 nsCAutoString relativeToKey
;
409 (void) relFilePref
->GetRelativeToKey(relativeToKey
);
411 nsCOMPtr
<nsILocalFile
> relativeToFile
;
412 nsCOMPtr
<nsIProperties
> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
));
415 rv
= directoryService
->Get(relativeToKey
.get(), NS_GET_IID(nsILocalFile
), getter_AddRefs(relativeToFile
));
419 nsCAutoString relDescriptor
;
420 rv
= file
->GetRelativeDescriptor(relativeToFile
, relDescriptor
);
424 nsCAutoString descriptorString
;
425 descriptorString
.Append('[');
426 descriptorString
.Append(relativeToKey
);
427 descriptorString
.Append(']');
428 descriptorString
.Append(relDescriptor
);
429 return SetCharPref(aPrefName
, descriptorString
.get());
432 if (aType
.Equals(NS_GET_IID(nsISupportsString
))) {
433 nsCOMPtr
<nsISupportsString
> theString
= do_QueryInterface(aValue
);
436 nsAutoString wideString
;
438 rv
= theString
->GetData(wideString
);
439 if (NS_SUCCEEDED(rv
)) {
440 rv
= SetCharPref(aPrefName
, NS_ConvertUTF16toUTF8(wideString
).get());
446 if (aType
.Equals(NS_GET_IID(nsIPrefLocalizedString
))) {
447 nsCOMPtr
<nsIPrefLocalizedString
> theString
= do_QueryInterface(aValue
);
450 nsXPIDLString wideString
;
452 rv
= theString
->GetData(getter_Copies(wideString
));
453 if (NS_SUCCEEDED(rv
)) {
454 rv
= SetCharPref(aPrefName
, NS_ConvertUTF16toUTF8(wideString
).get());
460 #ifndef MOZ_NO_XPCOM_OBSOLETE
461 // This is deprecated and you should not be using it
462 if (aType
.Equals(NS_GET_IID(nsIFileSpec
))) {
463 nsCOMPtr
<nsIFileSpec
> file
= do_QueryInterface(aValue
);
465 return NS_NOINTERFACE
;
466 nsXPIDLCString descriptorString
;
468 rv
= file
->GetPersistentDescriptorString(getter_Copies(descriptorString
));
469 if (NS_SUCCEEDED(rv
)) {
470 rv
= SetCharPref(aPrefName
, descriptorString
);
476 NS_WARNING("nsPrefBranch::SetComplexValue - Unsupported interface type");
477 return NS_NOINTERFACE
;
480 NS_IMETHODIMP
nsPrefBranch::ClearUserPref(const char *aPrefName
)
485 rv
= getValidatedPrefName(aPrefName
, &pref
);
486 if (NS_SUCCEEDED(rv
)) {
487 rv
= PREF_ClearUserPref(pref
);
492 NS_IMETHODIMP
nsPrefBranch::PrefHasUserValue(const char *aPrefName
, PRBool
*_retval
)
497 NS_ENSURE_ARG_POINTER(_retval
);
499 rv
= getValidatedPrefName(aPrefName
, &pref
);
500 if (NS_SUCCEEDED(rv
)) {
501 *_retval
= PREF_HasUserPref(pref
);
506 NS_IMETHODIMP
nsPrefBranch::LockPref(const char *aPrefName
)
511 rv
= getValidatedPrefName(aPrefName
, &pref
);
512 if (NS_SUCCEEDED(rv
)) {
513 rv
= PREF_LockPref(pref
, PR_TRUE
);
518 NS_IMETHODIMP
nsPrefBranch::PrefIsLocked(const char *aPrefName
, PRBool
*_retval
)
523 NS_ENSURE_ARG_POINTER(_retval
);
525 rv
= getValidatedPrefName(aPrefName
, &pref
);
526 if (NS_SUCCEEDED(rv
)) {
527 *_retval
= PREF_PrefIsLocked(pref
);
532 NS_IMETHODIMP
nsPrefBranch::UnlockPref(const char *aPrefName
)
537 rv
= getValidatedPrefName(aPrefName
, &pref
);
538 if (NS_SUCCEEDED(rv
)) {
539 rv
= PREF_LockPref(pref
, PR_FALSE
);
544 /* void resetBranch (in string startingAt); */
545 NS_IMETHODIMP
nsPrefBranch::ResetBranch(const char *aStartingAt
)
547 return NS_ERROR_NOT_IMPLEMENTED
;
550 NS_IMETHODIMP
nsPrefBranch::DeleteBranch(const char *aStartingAt
)
555 rv
= getValidatedPrefName(aStartingAt
, &pref
);
556 if (NS_SUCCEEDED(rv
)) {
557 rv
= PREF_DeleteBranch(pref
);
562 NS_IMETHODIMP
nsPrefBranch::GetChildList(const char *aStartingAt
, PRUint32
*aCount
, char ***aChildArray
)
569 nsAutoVoidArray prefArray
;
571 NS_ENSURE_ARG_POINTER(aStartingAt
);
572 NS_ENSURE_ARG_POINTER(aCount
);
573 NS_ENSURE_ARG_POINTER(aChildArray
);
575 if (!gHashTable
.ops
) {
576 *aChildArray
= nsnull
;
578 return NS_ERROR_NOT_INITIALIZED
;
581 // this will contain a list of all the pref name strings
582 // allocate on the stack for speed
584 ed
.parent
= getPrefName(aStartingAt
);
585 ed
.pref_list
= &prefArray
;
586 PL_DHashTableEnumerate(&gHashTable
, pref_enumChild
, &ed
);
588 // now that we've built up the list, run the callback on
589 // all the matching elements
590 numPrefs
= prefArray
.Count();
593 outArray
= (char **)nsMemory::Alloc(numPrefs
* sizeof(char *));
595 return NS_ERROR_OUT_OF_MEMORY
;
597 for (dwIndex
= 0; dwIndex
< numPrefs
; ++dwIndex
) {
598 // we need to lop off mPrefRoot in case the user is planning to pass this
599 // back to us because if they do we are going to add mPrefRoot again.
600 theElement
= ((char *)prefArray
.ElementAt(dwIndex
)) + mPrefRootLength
;
601 outArray
[dwIndex
] = (char *)nsMemory::Clone(theElement
, strlen(theElement
) + 1);
603 if (!outArray
[dwIndex
]) {
604 // we ran out of memory... this is annoying
605 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(dwIndex
, outArray
);
606 return NS_ERROR_OUT_OF_MEMORY
;
609 *aChildArray
= outArray
;
611 *aChildArray
= nsnull
;
620 * nsIPrefBranch2 methods
623 NS_IMETHODIMP
nsPrefBranch::AddObserver(const char *aDomain
, nsIObserver
*aObserver
, PRBool aHoldWeak
)
625 PrefCallbackData
*pCallback
;
628 NS_ENSURE_ARG_POINTER(aDomain
);
629 NS_ENSURE_ARG_POINTER(aObserver
);
632 mObservers
= new nsAutoVoidArray();
633 if (nsnull
== mObservers
)
634 return NS_ERROR_OUT_OF_MEMORY
;
637 pCallback
= (PrefCallbackData
*)nsMemory::Alloc(sizeof(PrefCallbackData
));
638 if (nsnull
== pCallback
)
639 return NS_ERROR_OUT_OF_MEMORY
;
641 pCallback
->pBranch
= this;
642 pCallback
->pObserver
= aObserver
;
644 // hold a weak reference to the observer if so requested
646 nsCOMPtr
<nsISupportsWeakReference
> weakRefFactory
= do_QueryInterface(aObserver
);
647 if (!weakRefFactory
) {
648 // the caller didn't give us a object that supports weak reference... tell them
649 nsMemory::Free(pCallback
);
650 return NS_ERROR_INVALID_ARG
;
652 nsCOMPtr
<nsIWeakReference
> tmp
= do_GetWeakReference(weakRefFactory
);
653 NS_ADDREF(pCallback
->pWeakRef
= tmp
);
655 pCallback
->pWeakRef
= nsnull
;
656 NS_ADDREF(pCallback
->pObserver
);
659 mObservers
->AppendElement(pCallback
);
660 mObserverDomains
.AppendCString(nsCString(aDomain
));
662 // We must pass a fully qualified preference name to the callback
663 pref
= getPrefName(aDomain
); // aDomain == nsnull only possible failure, trapped above
664 PREF_RegisterCallback(pref
, NotifyObserver
, pCallback
);
668 NS_IMETHODIMP
nsPrefBranch::RemoveObserver(const char *aDomain
, nsIObserver
*aObserver
)
671 PrefCallbackData
*pCallback
;
675 nsCAutoString domain
;
677 NS_ENSURE_ARG_POINTER(aDomain
);
678 NS_ENSURE_ARG_POINTER(aObserver
);
683 // need to find the index of observer, so we can remove it from the domain list too
684 count
= mObservers
->Count();
688 for (i
= 0; i
< count
; i
++) {
689 pCallback
= (PrefCallbackData
*)mObservers
->ElementAt(i
);
691 if (pCallback
->pObserver
== aObserver
) {
692 mObserverDomains
.CStringAt(i
, domain
);
693 if (domain
.Equals(aDomain
)) {
694 // We must pass a fully qualified preference name to remove the callback
695 pref
= getPrefName(aDomain
); // aDomain == nsnull only possible failure, trapped above
696 rv
= PREF_UnregisterCallback(pref
, NotifyObserver
, pCallback
);
697 if (NS_SUCCEEDED(rv
)) {
698 // Remove this observer from our array so that nobody else can remove
699 // what we're trying to remove ourselves right now.
700 mObservers
->RemoveElementAt(i
);
701 mObserverDomains
.RemoveCStringAt(i
);
702 if (pCallback
->pWeakRef
) {
703 NS_RELEASE(pCallback
->pWeakRef
);
705 NS_RELEASE(pCallback
->pObserver
);
707 nsMemory::Free(pCallback
);
718 NS_IMETHODIMP
nsPrefBranch::Observe(nsISupports
*aSubject
, const char *aTopic
, const PRUnichar
*someData
)
720 // watch for xpcom shutdown and free our observers to eliminate any cyclic references
721 if (!nsCRT::strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
727 static nsresult
NotifyObserver(const char *newpref
, void *data
)
729 PrefCallbackData
*pData
= (PrefCallbackData
*)data
;
731 // remove any root this string may contain so as to not confuse the observer
732 // by passing them something other than what they passed us as a topic
733 PRUint32 len
= pData
->pBranch
->GetRootLength();
734 nsCAutoString
suffix(newpref
+ len
);
736 nsCOMPtr
<nsIObserver
> observer
;
737 if (pData
->pWeakRef
) {
738 observer
= do_QueryReferent(pData
->pWeakRef
);
740 // this weak referenced observer went away, remove them from the list
741 pData
->pBranch
->RemoveObserver(newpref
, pData
->pObserver
);
745 observer
= pData
->pObserver
;
748 observer
->Observe(static_cast<nsIPrefBranch
*>(pData
->pBranch
),
749 NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
,
750 NS_ConvertASCIItoUTF16(suffix
).get());
755 void nsPrefBranch::freeObserverList(void)
758 PrefCallbackData
*pCallback
;
761 // unregister the observers
764 count
= mObservers
->Count();
767 nsCAutoString domain
;
768 for (i
= 0; i
< count
; ++i
) {
769 pCallback
= (PrefCallbackData
*)mObservers
->ElementAt(i
);
771 mObserverDomains
.CStringAt(i
, domain
);
772 // We must pass a fully qualified preference name to remove the callback
773 pref
= getPrefName(domain
.get()); // can't fail because domain must be valid
774 // Remove this observer from our array so that nobody else can remove
775 // what we're trying to remove right now.
776 mObservers
->ReplaceElementAt(nsnull
, i
);
777 PREF_UnregisterCallback(pref
, NotifyObserver
, pCallback
);
778 if (pCallback
->pWeakRef
) {
779 NS_RELEASE(pCallback
->pWeakRef
);
781 NS_RELEASE(pCallback
->pObserver
);
783 nsMemory::Free(pCallback
);
787 // now empty the observer domains array in bulk
788 mObserverDomains
.Clear();
795 nsresult
nsPrefBranch::GetDefaultFromPropertiesFile(const char *aPrefName
, PRUnichar
**return_buf
)
799 // the default value contains a URL to a .properties file
801 nsXPIDLCString propertyFileURL
;
802 rv
= PREF_CopyCharPref(aPrefName
, getter_Copies(propertyFileURL
), PR_TRUE
);
806 nsCOMPtr
<nsIStringBundleService
> bundleService
=
807 do_GetService(NS_STRINGBUNDLE_CONTRACTID
, &rv
);
811 nsCOMPtr
<nsIStringBundle
> bundle
;
812 rv
= bundleService
->CreateBundle(propertyFileURL
,
813 getter_AddRefs(bundle
));
817 // string names are in unicode
818 nsAutoString stringId
;
819 stringId
.AssignASCII(aPrefName
);
821 return bundle
->GetStringFromName(stringId
.get(), return_buf
);
824 const char *nsPrefBranch::getPrefName(const char *aPrefName
)
826 // for speed, avoid strcpy if we can:
827 if (mPrefRoot
.IsEmpty())
830 // isn't there a better way to do this? this is really kind of gross.
831 mPrefRoot
.Truncate(mPrefRootLength
);
833 // only append if anything to append
834 if ((nsnull
!= aPrefName
) && (*aPrefName
!= '\0'))
835 mPrefRoot
.Append(aPrefName
);
837 return mPrefRoot
.get();
840 nsresult
nsPrefBranch::getValidatedPrefName(const char *aPrefName
, const char **_retval
)
842 static const char capabilityPrefix
[] = "capability.";
844 NS_ENSURE_ARG_POINTER(aPrefName
);
845 const char *fullPref
= getPrefName(aPrefName
);
847 // now that we have the pref, check it against the ScriptSecurityManager
848 if ((fullPref
[0] == 'c') &&
849 PL_strncmp(fullPref
, capabilityPrefix
, sizeof(capabilityPrefix
)-1) == 0)
852 nsCOMPtr
<nsIPrefSecurityCheck
> secCheck
=
853 do_GetService(NS_GLOBAL_PREF_SECURITY_CHECK
, &rv
);
856 return NS_ERROR_FAILURE
;
859 rv
= secCheck
->CanAccessSecurityPreferences(&enabled
);
860 if (NS_FAILED(rv
) || !enabled
)
861 return NS_ERROR_FAILURE
;
868 static PLDHashOperator
869 pref_enumChild(PLDHashTable
*table
, PLDHashEntryHdr
*heh
,
870 PRUint32 i
, void *arg
)
872 PrefHashEntry
*he
= static_cast<PrefHashEntry
*>(heh
);
873 EnumerateData
*d
= reinterpret_cast<EnumerateData
*>(arg
);
874 if (PL_strncmp(he
->key
, d
->parent
, PL_strlen(d
->parent
)) == 0) {
875 d
->pref_list
->AppendElement((void*)he
->key
);
877 return PL_DHASH_NEXT
;
882 * nsISecurityPref methods
884 * Pref access without security check - these are here
885 * to support nsScriptSecurityManager.
886 * These functions are part of nsISecurityPref, not nsIPref.
887 * **PLEASE** do not call these functions from elsewhere
889 NS_IMETHODIMP
nsPrefBranch::SecurityGetBoolPref(const char *pref
, PRBool
* return_val
)
891 return PREF_GetBoolPref(getPrefName(pref
), return_val
, PR_FALSE
);
894 NS_IMETHODIMP
nsPrefBranch::SecuritySetBoolPref(const char *pref
, PRBool value
)
896 return PREF_SetBoolPref(getPrefName(pref
), value
);
899 NS_IMETHODIMP
nsPrefBranch::SecurityGetCharPref(const char *pref
, char ** return_buf
)
901 return PREF_CopyCharPref(getPrefName(pref
), return_buf
, PR_FALSE
);
904 NS_IMETHODIMP
nsPrefBranch::SecuritySetCharPref(const char *pref
, const char* value
)
906 return PREF_SetCharPref(getPrefName(pref
), value
);
909 NS_IMETHODIMP
nsPrefBranch::SecurityGetIntPref(const char *pref
, PRInt32
* return_val
)
911 return PREF_GetIntPref(getPrefName(pref
), return_val
, PR_FALSE
);
914 NS_IMETHODIMP
nsPrefBranch::SecuritySetIntPref(const char *pref
, PRInt32 value
)
916 return PREF_SetIntPref(getPrefName(pref
), value
);
919 NS_IMETHODIMP
nsPrefBranch::SecurityClearUserPref(const char *pref_name
)
921 return PREF_ClearUserPref(getPrefName(pref_name
));
924 //----------------------------------------------------------------------------
925 // nsPrefLocalizedString
926 //----------------------------------------------------------------------------
928 nsPrefLocalizedString::nsPrefLocalizedString()
932 nsPrefLocalizedString::~nsPrefLocalizedString()
938 * nsISupports Implementation
941 NS_IMPL_THREADSAFE_ADDREF(nsPrefLocalizedString
)
942 NS_IMPL_THREADSAFE_RELEASE(nsPrefLocalizedString
)
944 NS_INTERFACE_MAP_BEGIN(nsPrefLocalizedString
)
945 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIPrefLocalizedString
)
946 NS_INTERFACE_MAP_ENTRY(nsIPrefLocalizedString
)
947 NS_INTERFACE_MAP_ENTRY(nsISupportsString
)
950 nsresult
nsPrefLocalizedString::Init()
953 mUnicodeString
= do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID
, &rv
);
959 nsPrefLocalizedString::GetData(PRUnichar
** _retval
)
963 nsresult rv
= GetData(data
);
967 *_retval
= ToNewUnicode(data
);
969 return NS_ERROR_OUT_OF_MEMORY
;
975 nsPrefLocalizedString::SetData(const PRUnichar
*aData
)
978 return SetData(EmptyString());
979 return SetData(nsDependentString(aData
));
983 nsPrefLocalizedString::SetDataWithLength(PRUint32 aLength
,
984 const PRUnichar
* aData
)
987 return SetData(EmptyString());
988 return SetData(Substring(aData
, aData
+ aLength
));
991 //----------------------------------------------------------------------------
992 // nsRelativeFilePref
993 //----------------------------------------------------------------------------
995 NS_IMPL_THREADSAFE_ISUPPORTS1(nsRelativeFilePref
, nsIRelativeFilePref
)
997 nsRelativeFilePref::nsRelativeFilePref()
1001 nsRelativeFilePref::~nsRelativeFilePref()
1005 NS_IMETHODIMP
nsRelativeFilePref::GetFile(nsILocalFile
* *aFile
)
1007 NS_ENSURE_ARG_POINTER(aFile
);
1009 NS_IF_ADDREF(*aFile
);
1013 NS_IMETHODIMP
nsRelativeFilePref::SetFile(nsILocalFile
* aFile
)
1019 NS_IMETHODIMP
nsRelativeFilePref::GetRelativeToKey(nsACString
& aRelativeToKey
)
1021 aRelativeToKey
.Assign(mRelativeToKey
);
1025 NS_IMETHODIMP
nsRelativeFilePref::SetRelativeToKey(const nsACString
& aRelativeToKey
)
1027 mRelativeToKey
.Assign(aRelativeToKey
);