LCOV - code coverage report
Current view: directory - modules/libpref/src - nsPrefBranch.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 430 293 68.1 %
Date: 2012-06-02 Functions: 55 43 78.2 %

       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
       4                 :  *
       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/
       9                 :  *
      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
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      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.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Alec Flett <alecf@netscape.com>
      24                 :  *   Brian Nesse <bnesse@netscape.com>
      25                 :  *   Frederic Plourde <frederic.plourde@collabora.co.uk>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "mozilla/dom/ContentChild.h"
      42                 : #include "nsXULAppAPI.h"
      43                 : 
      44                 : #include "nsPrefBranch.h"
      45                 : #include "nsILocalFile.h"
      46                 : #include "nsIObserverService.h"
      47                 : #include "nsXPCOM.h"
      48                 : #include "nsISupportsPrimitives.h"
      49                 : #include "nsIDirectoryService.h"
      50                 : #include "nsString.h"
      51                 : #include "nsReadableUtils.h"
      52                 : #include "nsXPIDLString.h"
      53                 : #include "nsIStringBundle.h"
      54                 : #include "prefapi.h"
      55                 : #include "prmem.h"
      56                 : #include "pldhash.h"
      57                 : 
      58                 : #include "plstr.h"
      59                 : #include "nsCRT.h"
      60                 : #include "mozilla/Services.h"
      61                 : 
      62                 : #include "prefapi_private_data.h"
      63                 : 
      64                 : // Definitions
      65                 : struct EnumerateData {
      66                 :   const char  *parent;
      67                 :   nsTArray<nsCString> *pref_list;
      68                 : };
      69                 : 
      70                 : // Prototypes
      71                 : static PLDHashOperator
      72                 :   pref_enumChild(PLDHashTable *table, PLDHashEntryHdr *heh,
      73                 :                  PRUint32 i, void *arg);
      74                 : 
      75                 : using mozilla::dom::ContentChild;
      76                 : 
      77                 : static ContentChild*
      78           59314 : GetContentChild()
      79                 : {
      80           59314 :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
      81               0 :     ContentChild* cpc = ContentChild::GetSingleton();
      82               0 :     if (!cpc) {
      83               0 :       NS_RUNTIMEABORT("Content Protocol is NULL!  We're going to crash!");
      84                 :     }
      85               0 :     return cpc;
      86                 :   }
      87           59314 :   return nsnull;
      88                 : }
      89                 : 
      90                 : /*
      91                 :  * Constructor/Destructor
      92                 :  */
      93                 : 
      94            5725 : nsPrefBranch::nsPrefBranch(const char *aPrefRoot, bool aDefaultBranch)
      95                 : {
      96            5725 :   mPrefRoot = aPrefRoot;
      97            5725 :   mPrefRootLength = mPrefRoot.Length();
      98            5725 :   mIsDefault = aDefaultBranch;
      99            5725 :   mFreeingObserverList = false;
     100            5725 :   mObservers.Init();
     101                 : 
     102                 :   nsCOMPtr<nsIObserverService> observerService =
     103           11450 :     mozilla::services::GetObserverService();
     104            5725 :   if (observerService) {
     105            5725 :     ++mRefCnt;    // Our refcnt must be > 0 when we call this, or we'll get deleted!
     106                 :     // add weak so we don't have to clean up at shutdown
     107            5725 :     observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
     108            5725 :     --mRefCnt;
     109                 :   }
     110            5725 : }
     111                 : 
     112           17166 : nsPrefBranch::~nsPrefBranch()
     113                 : {
     114            5722 :   freeObserverList();
     115                 : 
     116                 :   nsCOMPtr<nsIObserverService> observerService =
     117           11444 :     mozilla::services::GetObserverService();
     118            5722 :   if (observerService)
     119             773 :     observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
     120           22888 : }
     121                 : 
     122                 : 
     123                 : /*
     124                 :  * nsISupports Implementation
     125                 :  */
     126                 : 
     127           43666 : NS_IMPL_THREADSAFE_ADDREF(nsPrefBranch)
     128           43663 : NS_IMPL_THREADSAFE_RELEASE(nsPrefBranch)
     129                 : 
     130           55728 : NS_INTERFACE_MAP_BEGIN(nsPrefBranch)
     131           55728 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefBranch)
     132           49165 :   NS_INTERFACE_MAP_ENTRY(nsIPrefBranch)
     133           37800 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIPrefBranch2, !mIsDefault)
     134           37800 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIPrefBranchInternal, !mIsDefault)
     135           37800 :   NS_INTERFACE_MAP_ENTRY(nsIObserver)
     136           27123 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     137           20625 : NS_INTERFACE_MAP_END
     138                 : 
     139                 : 
     140                 : /*
     141                 :  * nsIPrefBranch Implementation
     142                 :  */
     143                 : 
     144               2 : NS_IMETHODIMP nsPrefBranch::GetRoot(char **aRoot)
     145                 : {
     146               2 :   NS_ENSURE_ARG_POINTER(aRoot);
     147               2 :   mPrefRoot.Truncate(mPrefRootLength);
     148               2 :   *aRoot = ToNewCString(mPrefRoot);
     149               2 :   return NS_OK;
     150                 : }
     151                 : 
     152           19734 : NS_IMETHODIMP nsPrefBranch::GetPrefType(const char *aPrefName, PRInt32 *_retval)
     153                 : {
     154           19734 :   NS_ENSURE_ARG(aPrefName);
     155           19733 :   const char *pref = getPrefName(aPrefName);
     156           19733 :   *_retval = PREF_GetPrefType(pref);
     157           19733 :   return NS_OK;
     158                 : }
     159                 : 
     160           98484 : NS_IMETHODIMP nsPrefBranch::GetBoolPref(const char *aPrefName, bool *_retval)
     161                 : {
     162           98484 :   NS_ENSURE_ARG(aPrefName);
     163           98483 :   const char *pref = getPrefName(aPrefName);
     164           98483 :   return PREF_GetBoolPref(pref, _retval, mIsDefault);
     165                 : }
     166                 : 
     167            5206 : NS_IMETHODIMP nsPrefBranch::SetBoolPref(const char *aPrefName, bool aValue)
     168                 : {
     169            5206 :   if (GetContentChild()) {
     170               0 :     NS_ERROR("cannot set pref from content process");
     171               0 :     return NS_ERROR_NOT_AVAILABLE;
     172                 :   }
     173                 : 
     174            5206 :   NS_ENSURE_ARG(aPrefName);
     175            5205 :   const char *pref = getPrefName(aPrefName);
     176            5205 :   return PREF_SetBoolPref(pref, aValue, mIsDefault);
     177                 : }
     178                 : 
     179           41933 : NS_IMETHODIMP nsPrefBranch::GetCharPref(const char *aPrefName, char **_retval)
     180                 : {
     181           41933 :   NS_ENSURE_ARG(aPrefName);
     182           41932 :   const char *pref = getPrefName(aPrefName);
     183           41932 :   return PREF_CopyCharPref(pref, _retval, mIsDefault);
     184                 : }
     185                 : 
     186            9796 : NS_IMETHODIMP nsPrefBranch::SetCharPref(const char *aPrefName, const char *aValue)
     187                 : {
     188            9796 :   if (GetContentChild()) {
     189               0 :     NS_ERROR("cannot set pref from content process");
     190               0 :     return NS_ERROR_NOT_AVAILABLE;
     191                 :   }
     192                 : 
     193            9796 :   NS_ENSURE_ARG(aPrefName);
     194            9795 :   NS_ENSURE_ARG(aValue);
     195            9795 :   const char *pref = getPrefName(aPrefName);
     196            9795 :   return PREF_SetCharPref(pref, aValue, mIsDefault);
     197                 : }
     198                 : 
     199           41530 : NS_IMETHODIMP nsPrefBranch::GetIntPref(const char *aPrefName, PRInt32 *_retval)
     200                 : {
     201           41530 :   NS_ENSURE_ARG(aPrefName);
     202           41529 :   const char *pref = getPrefName(aPrefName);
     203           41529 :   return PREF_GetIntPref(pref, _retval, mIsDefault);
     204                 : }
     205                 : 
     206            5446 : NS_IMETHODIMP nsPrefBranch::SetIntPref(const char *aPrefName, PRInt32 aValue)
     207                 : {
     208            5446 :   if (GetContentChild()) {
     209               0 :     NS_ERROR("cannot set pref from content process");
     210               0 :     return NS_ERROR_NOT_AVAILABLE;
     211                 :   }
     212                 : 
     213            5446 :   NS_ENSURE_ARG(aPrefName);
     214            5445 :   const char *pref = getPrefName(aPrefName);
     215            5445 :   return PREF_SetIntPref(pref, aValue, mIsDefault);
     216                 : }
     217                 : 
     218           13764 : NS_IMETHODIMP nsPrefBranch::GetComplexValue(const char *aPrefName, const nsIID & aType, void **_retval)
     219                 : {
     220           13764 :   NS_ENSURE_ARG(aPrefName);
     221                 : 
     222                 :   nsresult       rv;
     223           27526 :   nsXPIDLCString utf8String;
     224                 : 
     225                 :   // we have to do this one first because it's different than all the rest
     226           13763 :   if (aType.Equals(NS_GET_IID(nsIPrefLocalizedString))) {
     227            4258 :     nsCOMPtr<nsIPrefLocalizedString> theString(do_CreateInstance(NS_PREFLOCALIZEDSTRING_CONTRACTID, &rv));
     228            2129 :     if (NS_FAILED(rv)) return rv;
     229                 : 
     230            2129 :     const char *pref = getPrefName(aPrefName);
     231            2129 :     bool    bNeedDefault = false;
     232                 : 
     233            2129 :     if (mIsDefault) {
     234              73 :       bNeedDefault = true;
     235                 :     } else {
     236                 :       // if there is no user (or locked) value
     237            2056 :       if (!PREF_HasUserPref(pref) && !PREF_PrefIsLocked(pref)) {
     238            1866 :         bNeedDefault = true;
     239                 :       }
     240                 :     }
     241                 : 
     242                 :     // if we need to fetch the default value, do that instead, otherwise use the
     243                 :     // value we pulled in at the top of this function
     244            2129 :     if (bNeedDefault) {
     245            3878 :       nsXPIDLString utf16String;
     246            1939 :       rv = GetDefaultFromPropertiesFile(pref, getter_Copies(utf16String));
     247            1939 :       if (NS_SUCCEEDED(rv)) {
     248             706 :         theString->SetData(utf16String.get());
     249                 :       }
     250                 :     } else {
     251             190 :       rv = GetCharPref(aPrefName, getter_Copies(utf8String));
     252             190 :       if (NS_SUCCEEDED(rv)) {
     253             190 :         theString->SetData(NS_ConvertUTF8toUTF16(utf8String).get());
     254                 :       }
     255                 :     }
     256                 : 
     257            2129 :     if (NS_SUCCEEDED(rv)) {
     258             896 :       theString.forget(reinterpret_cast<nsIPrefLocalizedString**>(_retval));
     259                 :     }
     260                 : 
     261            2129 :     return rv;
     262                 :   }
     263                 : 
     264                 :   // if we can't get the pref, there's no point in being here
     265           11634 :   rv = GetCharPref(aPrefName, getter_Copies(utf8String));
     266           11634 :   if (NS_FAILED(rv)) {
     267             714 :     return rv;
     268                 :   }
     269                 : 
     270           10920 :   if (aType.Equals(NS_GET_IID(nsILocalFile))) {
     271              70 :     if (GetContentChild()) {
     272               0 :       NS_ERROR("cannot get nsILocalFile pref from content process");
     273               0 :       return NS_ERROR_NOT_AVAILABLE;
     274                 :     }
     275                 : 
     276             140 :     nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
     277                 : 
     278              70 :     if (NS_SUCCEEDED(rv)) {
     279              70 :       rv = file->SetPersistentDescriptor(utf8String);
     280              70 :       if (NS_SUCCEEDED(rv)) {
     281              70 :         file.forget(reinterpret_cast<nsILocalFile**>(_retval));
     282              70 :         return NS_OK;
     283                 :       }
     284                 :     }
     285               0 :     return rv;
     286                 :   }
     287                 : 
     288           10850 :   if (aType.Equals(NS_GET_IID(nsIRelativeFilePref))) {
     289               0 :     if (GetContentChild()) {
     290               0 :       NS_ERROR("cannot get nsIRelativeFilePref from content process");
     291               0 :       return NS_ERROR_NOT_AVAILABLE;
     292                 :     }
     293                 : 
     294               0 :     nsACString::const_iterator keyBegin, strEnd;
     295               0 :     utf8String.BeginReading(keyBegin);
     296               0 :     utf8String.EndReading(strEnd);    
     297                 : 
     298                 :     // The pref has the format: [fromKey]a/b/c
     299               0 :     if (*keyBegin++ != '[')        
     300               0 :       return NS_ERROR_FAILURE;
     301               0 :     nsACString::const_iterator keyEnd(keyBegin);
     302               0 :     if (!FindCharInReadable(']', keyEnd, strEnd))
     303               0 :       return NS_ERROR_FAILURE;
     304               0 :     nsCAutoString key(Substring(keyBegin, keyEnd));
     305                 :     
     306               0 :     nsCOMPtr<nsILocalFile> fromFile;        
     307               0 :     nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
     308               0 :     if (NS_FAILED(rv))
     309               0 :       return rv;
     310               0 :     rv = directoryService->Get(key.get(), NS_GET_IID(nsILocalFile), getter_AddRefs(fromFile));
     311               0 :     if (NS_FAILED(rv))
     312               0 :       return rv;
     313                 :     
     314               0 :     nsCOMPtr<nsILocalFile> theFile;
     315               0 :     rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(theFile));
     316               0 :     if (NS_FAILED(rv))
     317               0 :       return rv;
     318               0 :     rv = theFile->SetRelativeDescriptor(fromFile, Substring(++keyEnd, strEnd));
     319               0 :     if (NS_FAILED(rv))
     320               0 :       return rv;
     321               0 :     nsCOMPtr<nsIRelativeFilePref> relativePref;
     322               0 :     rv = NS_NewRelativeFilePref(theFile, key, getter_AddRefs(relativePref));
     323               0 :     if (NS_FAILED(rv))
     324               0 :       return rv;
     325                 : 
     326               0 :     relativePref.forget(reinterpret_cast<nsIRelativeFilePref**>(_retval));
     327               0 :     return NS_OK;
     328                 :   }
     329                 : 
     330           10850 :   if (aType.Equals(NS_GET_IID(nsISupportsString))) {
     331           21700 :     nsCOMPtr<nsISupportsString> theString(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
     332                 : 
     333           10850 :     if (NS_SUCCEEDED(rv)) {
     334           10850 :       theString->SetData(NS_ConvertUTF8toUTF16(utf8String));
     335           10850 :       theString.forget(reinterpret_cast<nsISupportsString**>(_retval));
     336                 :     }
     337           10850 :     return rv;
     338                 :   }
     339                 : 
     340               0 :   NS_WARNING("nsPrefBranch::GetComplexValue - Unsupported interface type");
     341               0 :   return NS_NOINTERFACE;
     342                 : }
     343                 : 
     344            3979 : NS_IMETHODIMP nsPrefBranch::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
     345                 : {
     346            3979 :   if (GetContentChild()) {
     347               0 :     NS_ERROR("cannot set pref from content process");
     348               0 :     return NS_ERROR_NOT_AVAILABLE;
     349                 :   }
     350                 : 
     351            3979 :   NS_ENSURE_ARG(aPrefName);
     352                 : 
     353            3978 :   nsresult   rv = NS_NOINTERFACE;
     354                 : 
     355            3978 :   if (aType.Equals(NS_GET_IID(nsILocalFile))) {
     356              56 :     nsCOMPtr<nsILocalFile> file = do_QueryInterface(aValue);
     357              28 :     if (!file)
     358               0 :       return NS_NOINTERFACE;
     359              56 :     nsCAutoString descriptorString;
     360                 : 
     361              28 :     rv = file->GetPersistentDescriptor(descriptorString);
     362              28 :     if (NS_SUCCEEDED(rv)) {
     363              28 :       rv = SetCharPref(aPrefName, descriptorString.get());
     364                 :     }
     365              28 :     return rv;
     366                 :   }
     367                 : 
     368            3950 :   if (aType.Equals(NS_GET_IID(nsIRelativeFilePref))) {
     369               0 :     nsCOMPtr<nsIRelativeFilePref> relFilePref = do_QueryInterface(aValue);
     370               0 :     if (!relFilePref)
     371               0 :       return NS_NOINTERFACE;
     372                 :     
     373               0 :     nsCOMPtr<nsILocalFile> file;
     374               0 :     relFilePref->GetFile(getter_AddRefs(file));
     375               0 :     if (!file)
     376               0 :       return NS_NOINTERFACE;
     377               0 :     nsCAutoString relativeToKey;
     378               0 :     (void) relFilePref->GetRelativeToKey(relativeToKey);
     379                 : 
     380               0 :     nsCOMPtr<nsILocalFile> relativeToFile;        
     381               0 :     nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
     382               0 :     if (NS_FAILED(rv))
     383               0 :       return rv;
     384               0 :     rv = directoryService->Get(relativeToKey.get(), NS_GET_IID(nsILocalFile), getter_AddRefs(relativeToFile));
     385               0 :     if (NS_FAILED(rv))
     386               0 :       return rv;
     387                 : 
     388               0 :     nsCAutoString relDescriptor;
     389               0 :     rv = file->GetRelativeDescriptor(relativeToFile, relDescriptor);
     390               0 :     if (NS_FAILED(rv))
     391               0 :       return rv;
     392                 :     
     393               0 :     nsCAutoString descriptorString;
     394               0 :     descriptorString.Append('[');
     395               0 :     descriptorString.Append(relativeToKey);
     396               0 :     descriptorString.Append(']');
     397               0 :     descriptorString.Append(relDescriptor);
     398               0 :     return SetCharPref(aPrefName, descriptorString.get());
     399                 :   }
     400                 : 
     401            3950 :   if (aType.Equals(NS_GET_IID(nsISupportsString))) {
     402            7900 :     nsCOMPtr<nsISupportsString> theString = do_QueryInterface(aValue);
     403                 : 
     404            3950 :     if (theString) {
     405            7900 :       nsAutoString wideString;
     406                 : 
     407            3950 :       rv = theString->GetData(wideString);
     408            3950 :       if (NS_SUCCEEDED(rv)) {
     409            3950 :         rv = SetCharPref(aPrefName, NS_ConvertUTF16toUTF8(wideString).get());
     410                 :       }
     411                 :     }
     412            3950 :     return rv;
     413                 :   }
     414                 : 
     415               0 :   if (aType.Equals(NS_GET_IID(nsIPrefLocalizedString))) {
     416               0 :     nsCOMPtr<nsIPrefLocalizedString> theString = do_QueryInterface(aValue);
     417                 : 
     418               0 :     if (theString) {
     419               0 :       nsXPIDLString wideString;
     420                 : 
     421               0 :       rv = theString->GetData(getter_Copies(wideString));
     422               0 :       if (NS_SUCCEEDED(rv)) {
     423               0 :         rv = SetCharPref(aPrefName, NS_ConvertUTF16toUTF8(wideString).get());
     424                 :       }
     425                 :     }
     426               0 :     return rv;
     427                 :   }
     428                 : 
     429               0 :   NS_WARNING("nsPrefBranch::SetComplexValue - Unsupported interface type");
     430               0 :   return NS_NOINTERFACE;
     431                 : }
     432                 : 
     433           34609 : NS_IMETHODIMP nsPrefBranch::ClearUserPref(const char *aPrefName)
     434                 : {
     435           34609 :   if (GetContentChild()) {
     436               0 :     NS_ERROR("cannot set pref from content process");
     437               0 :     return NS_ERROR_NOT_AVAILABLE;
     438                 :   }
     439                 : 
     440           34609 :   NS_ENSURE_ARG(aPrefName);
     441           34608 :   const char *pref = getPrefName(aPrefName);
     442           34608 :   return PREF_ClearUserPref(pref);
     443                 : }
     444                 : 
     445            1726 : NS_IMETHODIMP nsPrefBranch::PrefHasUserValue(const char *aPrefName, bool *_retval)
     446                 : {
     447            1726 :   NS_ENSURE_ARG_POINTER(_retval);
     448            1726 :   NS_ENSURE_ARG(aPrefName);
     449            1725 :   const char *pref = getPrefName(aPrefName);
     450            1725 :   *_retval = PREF_HasUserPref(pref);
     451            1725 :   return NS_OK;
     452                 : }
     453                 : 
     454               6 : NS_IMETHODIMP nsPrefBranch::LockPref(const char *aPrefName)
     455                 : {
     456               6 :   if (GetContentChild()) {
     457               0 :     NS_ERROR("cannot lock pref from content process");
     458               0 :     return NS_ERROR_NOT_AVAILABLE;
     459                 :   }
     460                 : 
     461               6 :   NS_ENSURE_ARG(aPrefName);
     462               5 :   const char *pref = getPrefName(aPrefName);
     463               5 :   return PREF_LockPref(pref, true);
     464                 : }
     465                 : 
     466               4 : NS_IMETHODIMP nsPrefBranch::PrefIsLocked(const char *aPrefName, bool *_retval)
     467                 : {
     468               4 :   if (GetContentChild()) {
     469               0 :     NS_ERROR("cannot check lock pref from content process");
     470               0 :     return NS_ERROR_NOT_AVAILABLE;
     471                 :   }
     472                 : 
     473               4 :   NS_ENSURE_ARG_POINTER(_retval);
     474               4 :   NS_ENSURE_ARG(aPrefName);
     475               3 :   const char *pref = getPrefName(aPrefName);
     476               3 :   *_retval = PREF_PrefIsLocked(pref);
     477               3 :   return NS_OK;
     478                 : }
     479                 : 
     480               5 : NS_IMETHODIMP nsPrefBranch::UnlockPref(const char *aPrefName)
     481                 : {
     482               5 :   if (GetContentChild()) {
     483               0 :     NS_ERROR("cannot unlock pref from content process");
     484               0 :     return NS_ERROR_NOT_AVAILABLE;
     485                 :   }
     486                 : 
     487               5 :   NS_ENSURE_ARG(aPrefName);
     488               4 :   const char *pref = getPrefName(aPrefName);
     489               4 :   return PREF_LockPref(pref, false);
     490                 : }
     491                 : 
     492                 : /* void resetBranch (in string startingAt); */
     493             300 : NS_IMETHODIMP nsPrefBranch::ResetBranch(const char *aStartingAt)
     494                 : {
     495             300 :   return NS_ERROR_NOT_IMPLEMENTED;
     496                 : }
     497                 : 
     498             193 : NS_IMETHODIMP nsPrefBranch::DeleteBranch(const char *aStartingAt)
     499                 : {
     500             193 :   if (GetContentChild()) {
     501               0 :     NS_ERROR("cannot set pref from content process");
     502               0 :     return NS_ERROR_NOT_AVAILABLE;
     503                 :   }
     504                 : 
     505             193 :   NS_ENSURE_ARG(aStartingAt);
     506             192 :   const char *pref = getPrefName(aStartingAt);
     507             192 :   return PREF_DeleteBranch(pref);
     508                 : }
     509                 : 
     510            2881 : NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, PRUint32 *aCount, char ***aChildArray)
     511                 : {
     512                 :   char            **outArray;
     513                 :   PRInt32         numPrefs;
     514                 :   PRInt32         dwIndex;
     515                 :   EnumerateData   ed;
     516            5762 :   nsAutoTArray<nsCString, 32> prefArray;
     517                 : 
     518            2881 :   NS_ENSURE_ARG(aStartingAt);
     519            2880 :   NS_ENSURE_ARG_POINTER(aCount);
     520            2880 :   NS_ENSURE_ARG_POINTER(aChildArray);
     521                 : 
     522            2880 :   *aChildArray = nsnull;
     523            2880 :   *aCount = 0;
     524                 : 
     525            2880 :   if (!gHashTable.ops)
     526               0 :     return NS_ERROR_NOT_INITIALIZED;
     527                 : 
     528                 :   // this will contain a list of all the pref name strings
     529                 :   // allocate on the stack for speed
     530                 :   
     531            2880 :   ed.parent = getPrefName(aStartingAt);
     532            2880 :   ed.pref_list = &prefArray;
     533            2880 :   PL_DHashTableEnumerate(&gHashTable, pref_enumChild, &ed);
     534                 : 
     535                 :   // now that we've built up the list, run the callback on
     536                 :   // all the matching elements
     537            2880 :   numPrefs = prefArray.Length();
     538                 : 
     539            2880 :   if (numPrefs) {
     540             540 :     outArray = (char **)nsMemory::Alloc(numPrefs * sizeof(char *));
     541             540 :     if (!outArray)
     542               0 :       return NS_ERROR_OUT_OF_MEMORY;
     543                 : 
     544           34238 :     for (dwIndex = 0; dwIndex < numPrefs; ++dwIndex) {
     545                 :       // we need to lop off mPrefRoot in case the user is planning to pass this
     546                 :       // back to us because if they do we are going to add mPrefRoot again.
     547           33698 :       const nsCString& element = prefArray[dwIndex];
     548           33698 :       outArray[dwIndex] = (char *)nsMemory::Clone(
     549           33698 :         element.get() + mPrefRootLength, element.Length() - mPrefRootLength + 1);
     550                 : 
     551           33698 :       if (!outArray[dwIndex]) {
     552                 :         // we ran out of memory... this is annoying
     553               0 :         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(dwIndex, outArray);
     554               0 :         return NS_ERROR_OUT_OF_MEMORY;
     555                 :       }
     556                 :     }
     557             540 :     *aChildArray = outArray;
     558                 :   }
     559            2880 :   *aCount = numPrefs;
     560                 : 
     561            2880 :   return NS_OK;
     562                 : }
     563                 : 
     564          120645 : NS_IMETHODIMP nsPrefBranch::AddObserver(const char *aDomain, nsIObserver *aObserver, bool aHoldWeak)
     565                 : {
     566                 :   PrefCallback *pCallback;
     567                 :   const char *pref;
     568                 : 
     569          120645 :   NS_ENSURE_ARG(aDomain);
     570          120645 :   NS_ENSURE_ARG(aObserver);
     571                 : 
     572                 :   // hold a weak reference to the observer if so requested
     573          120645 :   if (aHoldWeak) {
     574           64062 :     nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(aObserver);
     575           32031 :     if (!weakRefFactory) {
     576                 :       // the caller didn't give us a object that supports weak reference... tell them
     577               0 :       return NS_ERROR_INVALID_ARG;
     578                 :     }
     579                 : 
     580                 :     // Construct a PrefCallback with a weak reference to the observer.
     581           96093 :     pCallback = new PrefCallback(aDomain, weakRefFactory, this);
     582                 : 
     583                 :   } else {
     584                 :     // Construct a PrefCallback with a strong reference to the observer.
     585           88614 :     pCallback = new PrefCallback(aDomain, aObserver, this);
     586                 :   }
     587                 : 
     588          120645 :   if (mObservers.Get(pCallback)) {
     589               1 :     NS_WARNING("Ignoring duplicate observer.");
     590               1 :     delete pCallback;
     591               1 :     return NS_OK;
     592                 :   }
     593                 : 
     594          120644 :   bool putSucceeded = mObservers.Put(pCallback, pCallback);
     595                 : 
     596          120644 :   if (!putSucceeded) {
     597               0 :     delete pCallback;
     598               0 :     return NS_ERROR_FAILURE;
     599                 :   }
     600                 : 
     601                 :   // We must pass a fully qualified preference name to the callback
     602                 :   // aDomain == nsnull is the only possible failure, and we trapped it with
     603                 :   // NS_ENSURE_ARG above.
     604          120644 :   pref = getPrefName(aDomain);
     605          120644 :   PREF_RegisterCallback(pref, NotifyObserver, pCallback);
     606          120644 :   return NS_OK;
     607                 : }
     608                 : 
     609           66844 : NS_IMETHODIMP nsPrefBranch::RemoveObserver(const char *aDomain, nsIObserver *aObserver)
     610                 : {
     611           66844 :   NS_ENSURE_ARG(aDomain);
     612           66844 :   NS_ENSURE_ARG(aObserver);
     613                 : 
     614           66844 :   nsresult rv = NS_OK;
     615                 : 
     616                 :   // If we're in the middle of a call to freeObserverList, don't process this
     617                 :   // RemoveObserver call -- the observer in question will be removed soon, if
     618                 :   // it hasn't been already.
     619                 :   //
     620                 :   // It's important that we don't touch mObservers in any way -- even a Get()
     621                 :   // which retuns null might cause the hashtable to resize itself, which will
     622                 :   // break the Enumerator in freeObserverList.
     623           66844 :   if (mFreeingObserverList)
     624            1108 :     return NS_OK;
     625                 : 
     626                 :   // Remove the relevant PrefCallback from mObservers and get an owning
     627                 :   // pointer to it.  Unregister the callback first, and then let the owning
     628                 :   // pointer go out of scope and destroy the callback.
     629          131472 :   PrefCallback key(aDomain, aObserver, this);
     630          131472 :   nsAutoPtr<PrefCallback> pCallback;
     631           65736 :   mObservers.RemoveAndForget(&key, pCallback);
     632           65736 :   if (pCallback) {
     633                 :     // aDomain == nsnull is the only possible failure, trapped above
     634           12661 :     const char *pref = getPrefName(aDomain);
     635           12661 :     rv = PREF_UnregisterCallback(pref, NotifyObserver, pCallback);
     636                 :   }
     637                 : 
     638           65736 :   return rv;
     639                 : }
     640                 : 
     641            4952 : NS_IMETHODIMP nsPrefBranch::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
     642                 : {
     643                 :   // watch for xpcom shutdown and free our observers to eliminate any cyclic references
     644            4952 :   if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
     645            4952 :     freeObserverList();
     646                 :   }
     647            4952 :   return NS_OK;
     648                 : }
     649                 : 
     650                 : /* static */
     651            2512 : nsresult nsPrefBranch::NotifyObserver(const char *newpref, void *data)
     652                 : {
     653            2512 :   PrefCallback *pCallback = (PrefCallback *)data;
     654                 : 
     655            5024 :   nsCOMPtr<nsIObserver> observer = pCallback->GetObserver();
     656            2512 :   if (!observer) {
     657                 :     // The observer has expired.  Let's remove this callback.
     658               0 :     pCallback->GetPrefBranch()->RemoveExpiredCallback(pCallback);
     659               0 :     return NS_OK;
     660                 :   }
     661                 : 
     662                 :   // remove any root this string may contain so as to not confuse the observer
     663                 :   // by passing them something other than what they passed us as a topic
     664            2512 :   PRUint32 len = pCallback->GetPrefBranch()->GetRootLength();
     665            5024 :   nsCAutoString suffix(newpref + len);
     666                 : 
     667            5024 :   observer->Observe(static_cast<nsIPrefBranch *>(pCallback->GetPrefBranch()),
     668                 :                     NS_PREFBRANCH_PREFCHANGE_TOPIC_ID,
     669            5024 :                     NS_ConvertASCIItoUTF16(suffix).get());
     670            2512 :   return NS_OK;
     671                 : }
     672                 : 
     673                 : PLDHashOperator
     674          107983 : FreeObserverFunc(PrefCallback *aKey,
     675                 :                  nsAutoPtr<PrefCallback> &aCallback,
     676                 :                  void *aArgs)
     677                 : {
     678                 :   // Calling NS_RELEASE below might trigger a call to
     679                 :   // nsPrefBranch::RemoveObserver, since some classes remove themselves from
     680                 :   // the pref branch on destruction.  We don't need to worry about this causing
     681                 :   // double-frees, however, because freeObserverList sets mFreeingObserverList
     682                 :   // to true, which prevents RemoveObserver calls from doing anything.
     683                 : 
     684          107983 :   nsPrefBranch *prefBranch = aCallback->GetPrefBranch();
     685          107983 :   const char *pref = prefBranch->getPrefName(aCallback->GetDomain().get());
     686          107983 :   PREF_UnregisterCallback(pref, nsPrefBranch::NotifyObserver, aCallback);
     687                 : 
     688          107983 :   return PL_DHASH_REMOVE;
     689                 : }
     690                 : 
     691           10674 : void nsPrefBranch::freeObserverList(void)
     692                 : {
     693                 :   // We need to prevent anyone from modifying mObservers while we're
     694                 :   // enumerating over it.  In particular, some clients will call
     695                 :   // RemoveObserver() when they're destructed; we need to keep those calls from
     696                 :   // touching mObservers.
     697           10674 :   mFreeingObserverList = true;
     698           10674 :   mObservers.Enumerate(&FreeObserverFunc, nsnull);
     699           10674 :   mFreeingObserverList = false;
     700           10674 : }
     701                 : 
     702                 : void
     703               0 : nsPrefBranch::RemoveExpiredCallback(PrefCallback *aCallback)
     704                 : {
     705               0 :   NS_PRECONDITION(aCallback->IsExpired(), "Callback should be expired.");
     706               0 :   mObservers.Remove(aCallback);
     707               0 : }
     708                 : 
     709            1939 : nsresult nsPrefBranch::GetDefaultFromPropertiesFile(const char *aPrefName, PRUnichar **return_buf)
     710                 : {
     711                 :   nsresult rv;
     712                 : 
     713                 :   // the default value contains a URL to a .properties file
     714                 :     
     715            3878 :   nsXPIDLCString propertyFileURL;
     716            1939 :   rv = PREF_CopyCharPref(aPrefName, getter_Copies(propertyFileURL), true);
     717            1939 :   if (NS_FAILED(rv))
     718             180 :     return rv;
     719                 : 
     720                 :   nsCOMPtr<nsIStringBundleService> bundleService =
     721            3518 :     mozilla::services::GetStringBundleService();
     722            1759 :   if (!bundleService)
     723               0 :     return NS_ERROR_FAILURE;
     724                 : 
     725            3518 :   nsCOMPtr<nsIStringBundle> bundle;
     726            1759 :   rv = bundleService->CreateBundle(propertyFileURL,
     727            1759 :                                    getter_AddRefs(bundle));
     728            1759 :   if (NS_FAILED(rv))
     729               0 :     return rv;
     730                 : 
     731                 :   // string names are in unicode
     732            3518 :   nsAutoString stringId;
     733            1759 :   stringId.AssignASCII(aPrefName);
     734                 : 
     735            1759 :   return bundle->GetStringFromName(stringId.get(), return_buf);
     736                 : }
     737                 : 
     738          504956 : const char *nsPrefBranch::getPrefName(const char *aPrefName)
     739                 : {
     740          504956 :   NS_ASSERTION(aPrefName, "null pref name!");
     741                 : 
     742                 :   // for speed, avoid strcpy if we can:
     743          504956 :   if (mPrefRoot.IsEmpty())
     744          431724 :     return aPrefName;
     745                 : 
     746                 :   // isn't there a better way to do this? this is really kind of gross.
     747           73232 :   mPrefRoot.Truncate(mPrefRootLength);
     748           73232 :   mPrefRoot.Append(aPrefName);
     749           73232 :   return mPrefRoot.get();
     750                 : }
     751                 : 
     752                 : static PLDHashOperator
     753         4665720 : pref_enumChild(PLDHashTable *table, PLDHashEntryHdr *heh,
     754                 :                PRUint32 i, void *arg)
     755                 : {
     756         4665720 :   PrefHashEntry *he = static_cast<PrefHashEntry*>(heh);
     757         4665720 :   EnumerateData *d = reinterpret_cast<EnumerateData *>(arg);
     758         4665720 :   if (strncmp(he->key, d->parent, strlen(d->parent)) == 0) {
     759           33698 :     d->pref_list->AppendElement(he->key);
     760                 :   }
     761         4665720 :   return PL_DHASH_NEXT;
     762                 : }
     763                 : 
     764                 : //----------------------------------------------------------------------------
     765                 : // nsPrefLocalizedString
     766                 : //----------------------------------------------------------------------------
     767                 : 
     768            2131 : nsPrefLocalizedString::nsPrefLocalizedString()
     769                 : {
     770            2131 : }
     771                 : 
     772            4262 : nsPrefLocalizedString::~nsPrefLocalizedString()
     773                 : {
     774            8524 : }
     775                 : 
     776                 : 
     777                 : /*
     778                 :  * nsISupports Implementation
     779                 :  */
     780                 : 
     781            7508 : NS_IMPL_THREADSAFE_ADDREF(nsPrefLocalizedString)
     782            7508 : NS_IMPL_THREADSAFE_RELEASE(nsPrefLocalizedString)
     783                 : 
     784            6877 : NS_INTERFACE_MAP_BEGIN(nsPrefLocalizedString)
     785            6877 :     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefLocalizedString)
     786            6658 :     NS_INTERFACE_MAP_ENTRY(nsIPrefLocalizedString)
     787            1500 :     NS_INTERFACE_MAP_ENTRY(nsISupportsString)
     788            1500 : NS_INTERFACE_MAP_END
     789                 : 
     790            2131 : nsresult nsPrefLocalizedString::Init()
     791                 : {
     792                 :   nsresult rv;
     793            2131 :   mUnicodeString = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
     794                 : 
     795            2131 :   return rv;
     796                 : }
     797                 : 
     798                 : NS_IMETHODIMP
     799             119 : nsPrefLocalizedString::GetData(PRUnichar **_retval)
     800                 : {
     801             238 :   nsAutoString data;
     802                 : 
     803             119 :   nsresult rv = GetData(data);
     804             119 :   if (NS_FAILED(rv))
     805               0 :     return rv;
     806                 :   
     807             119 :   *_retval = ToNewUnicode(data);
     808             119 :   if (!*_retval)
     809               0 :     return NS_ERROR_OUT_OF_MEMORY;
     810                 : 
     811             119 :   return NS_OK;
     812                 : }
     813                 : 
     814                 : NS_IMETHODIMP
     815             896 : nsPrefLocalizedString::SetData(const PRUnichar *aData)
     816                 : {
     817             896 :   if (!aData)
     818               0 :     return SetData(EmptyString());
     819             896 :   return SetData(nsDependentString(aData));
     820                 : }
     821                 : 
     822                 : NS_IMETHODIMP
     823               0 : nsPrefLocalizedString::SetDataWithLength(PRUint32 aLength,
     824                 :                                          const PRUnichar *aData)
     825                 : {
     826               0 :   if (!aData)
     827               0 :     return SetData(EmptyString());
     828               0 :   return SetData(Substring(aData, aLength));
     829                 : }
     830                 : 
     831                 : //----------------------------------------------------------------------------
     832                 : // nsRelativeFilePref
     833                 : //----------------------------------------------------------------------------
     834                 : 
     835               0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsRelativeFilePref, nsIRelativeFilePref)
     836                 : 
     837               0 : nsRelativeFilePref::nsRelativeFilePref()
     838                 : {
     839               0 : }
     840                 : 
     841               0 : nsRelativeFilePref::~nsRelativeFilePref()
     842                 : {
     843               0 : }
     844                 : 
     845               0 : NS_IMETHODIMP nsRelativeFilePref::GetFile(nsILocalFile **aFile)
     846                 : {
     847               0 :   NS_ENSURE_ARG_POINTER(aFile);
     848               0 :   *aFile = mFile;
     849               0 :   NS_IF_ADDREF(*aFile);
     850               0 :   return NS_OK;
     851                 : }
     852                 : 
     853               0 : NS_IMETHODIMP nsRelativeFilePref::SetFile(nsILocalFile *aFile)
     854                 : {
     855               0 :   mFile = aFile;
     856               0 :   return NS_OK;
     857                 : }
     858                 : 
     859               0 : NS_IMETHODIMP nsRelativeFilePref::GetRelativeToKey(nsACString& aRelativeToKey)
     860                 : {
     861               0 :   aRelativeToKey.Assign(mRelativeToKey);
     862               0 :   return NS_OK;
     863                 : }
     864                 : 
     865               0 : NS_IMETHODIMP nsRelativeFilePref::SetRelativeToKey(const nsACString& aRelativeToKey)
     866                 : {
     867               0 :   mRelativeToKey.Assign(aRelativeToKey);
     868               0 :   return NS_OK;
     869                 : }

Generated by: LCOV version 1.7