Back to index

lightning-sunbird  0.9+nobinonly
nsSystemPref.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 /* ***** BEGIN LICENSE BLOCK *****
00005  * Version: NPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  *
00008  * The contents of this file are subject to the Mozilla Public
00009  * License Version 1.1 (the "License"); you may not use this file
00010  * except in compliance with the License. You may obtain a copy of
00011  * the License at http://www.mozilla.org/MPL/
00012  *
00013  * Software distributed under the License is distributed on an "AS
00014  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
00015  * implied. See the License for the specific language governing
00016  * rights and limitations under the License.
00017  *
00018  * The Original Code is mozilla.org code.
00019  *
00020  * The Initial Developer of the Original Code is Sun Microsystems, Inc.
00021  * Portions created by Sun Microsystems are Copyright (C) 2003 Sun
00022  * Microsystems, Inc. All Rights Reserved.
00023  *
00024  * Original Author: Bolian Yin (bolian.yin@sun.com)
00025  *
00026  * Contributor(s):
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either the GNU General Public License Version 2 or later (the "GPL"), or
00030  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the NPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the NPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 #include "nsSystemPref.h"
00043 #include "nsIObserverService.h"
00044 
00045 #include "nsSystemPrefLog.h"
00046 #include "nsSystemPrefService.h"
00047 #include "nsString.h"
00048 
00049 const char sSysPrefString[] = "config.use_system_prefs";
00050 union MozPrefValue {
00051     char *      stringVal;
00052     PRInt32     intVal;
00053     PRBool      boolVal;
00054 };
00055 
00056 struct SysPrefItem {
00057     const char *prefName;       // mozilla pref string name
00058     MozPrefValue defaultValue;  // store the mozilla default value
00059     PRBool isLocked;  // store the mozilla lock status
00060     SysPrefItem() {
00061         prefName = nsnull;
00062         defaultValue.intVal = 0;
00063         defaultValue.stringVal = nsnull;
00064         defaultValue.boolVal = PR_FALSE;
00065         isLocked = PR_FALSE;
00066     }
00067     void SetPrefName(const char *aPrefName) {
00068         prefName = aPrefName;
00069     }
00070 };
00071 
00072 // all prefs that mozilla need to read from host system if they are available
00073 static const char *sSysPrefList[] = {
00074     "network.proxy.http",
00075     "network.proxy.http_port",
00076     "network.proxy.ftp",
00077     "network.proxy.ftp_port",
00078     "network.proxy.ssl",
00079     "network.proxy.ssl_port",
00080     "network.proxy.socks",
00081     "network.proxy.socks_port",
00082     "network.proxy.no_proxies_on",
00083     "network.proxy.autoconfig_url",
00084     "network.proxy.type",
00085     "config.use_system_prefs.accessibility",
00086 };
00087 
00088 PRLogModuleInfo *gSysPrefLog = NULL;
00089 
00090 NS_IMPL_ISUPPORTS2(nsSystemPref, nsIObserver, nsISupportsWeakReference)
00091 
00092 nsSystemPref::nsSystemPref():
00093     mSysPrefService(nsnull),
00094     mEnabled(PR_FALSE),
00095     mSysPrefs(nsnull)
00096 {
00097 }
00098 
00099 nsSystemPref::~nsSystemPref()
00100 {
00101     mSysPrefService = nsnull;
00102     mEnabled = PR_FALSE;
00103     delete [] mSysPrefs;
00104 }
00105 
00107 // nsSystemPref::Init
00108 // Setup log and listen on NS_PREFSERVICE_READ_TOPIC_ID from pref service
00110 nsresult
00111 nsSystemPref::Init(void)
00112 {
00113     nsresult rv;
00114 
00115     if (!gSysPrefLog) {
00116         gSysPrefLog = PR_NewLogModule("Syspref");
00117         if (!gSysPrefLog)
00118             return NS_ERROR_OUT_OF_MEMORY;
00119     }
00120 
00121     nsCOMPtr<nsIObserverService> observerService = 
00122         do_GetService("@mozilla.org/observer-service;1", &rv);
00123 
00124     if (observerService) {
00125         rv = observerService->AddObserver(this, NS_PREFSERVICE_READ_TOPIC_ID,
00126                                           PR_FALSE);
00127         rv = observerService->AddObserver(this, "profile-before-change",
00128                                           PR_FALSE);
00129         SYSPREF_LOG(("Add Observer for %s\n", NS_PREFSERVICE_READ_TOPIC_ID));
00130     }
00131     return(rv);
00132 }
00133 
00135 // nsSystemPref::Observe
00136 // Observe notifications from mozilla pref system and system prefs (if enabled)
00138 NS_IMETHODIMP
00139 nsSystemPref::Observe(nsISupports *aSubject,
00140                       const char *aTopic,
00141                       const PRUnichar *aData)
00142 {
00143     nsresult rv = NS_OK;
00144 
00145     if (!aTopic)
00146         return NS_OK;
00147 
00148     // if we are notified by pref service
00149     // check the system pref settings
00150     if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
00151         SYSPREF_LOG(("Observed: %s\n", aTopic));
00152 
00153         nsCOMPtr<nsIPrefBranch2> prefBranch =
00154             do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00155         if (NS_FAILED(rv))
00156             return rv;
00157 
00158         rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
00159         if (NS_FAILED(rv)) {
00160             SYSPREF_LOG(("...FAil to Get %s\n", sSysPrefString));
00161             return rv;
00162         }
00163 
00164         // if there is no system pref service, assume nothing happen to us
00165         mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
00166         if (NS_FAILED(rv) || !mSysPrefService) {
00167             SYSPREF_LOG(("...No System Pref Service\n"));
00168             return NS_OK;
00169         }
00170 
00171         // listen on its changes
00172         rv = prefBranch->AddObserver(sSysPrefString, this, PR_TRUE);
00173         if (NS_FAILED(rv)) {
00174             SYSPREF_LOG(("...FAil to add observer for %s\n", sSysPrefString));
00175             return rv;
00176         }
00177 
00178         if (!mEnabled) {
00179             SYSPREF_LOG(("%s is disabled\n", sSysPrefString));
00180             return NS_OK;
00181         }
00182         SYSPREF_LOG(("%s is enabled\n", sSysPrefString));
00183         rv = UseSystemPrefs();
00184 
00185     }
00186     // sSysPrefString value was changed, update ...
00187     else if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
00188              NS_ConvertUTF8toUCS2(sSysPrefString).Equals(aData)) {
00189         SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
00190                      aTopic, NS_ConvertUCS2toUTF8(aData).get()));
00191 
00192         nsCOMPtr<nsIPrefBranch> prefBranch =
00193             do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00194         if (NS_FAILED(rv))
00195             return rv;
00196 
00197         PRBool enabled = mEnabled;
00198         rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
00199         if (enabled != mEnabled) {
00200             if (mEnabled)
00201                 //read prefs from system
00202                 rv = UseSystemPrefs();
00203             else
00204                 //roll back to mozilla prefs
00205                 rv = UseMozillaPrefs();
00206         }
00207     }
00208 
00209     // if the system pref notify us that some pref has been changed by user
00210     // outside mozilla. We need to read it again.
00211     else if (!nsCRT::strcmp(aTopic, NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID) &&
00212              aData) {
00213         NS_ASSERTION(mEnabled == PR_TRUE, "Should not listen when disabled");
00214         SYSPREF_LOG(("====== System Pref Notify topic=%s data=%s\n",
00215                      aTopic, (char*)aData));
00216         rv = ReadSystemPref(NS_LossyConvertUCS2toASCII(aData).get());
00217         return NS_OK;
00218     } else if (!nsCRT::strcmp(aTopic,"profile-before-change")) {
00219       //roll back to mozilla prefs
00220       if (mEnabled)
00221         UseMozillaPrefs();
00222       mEnabled = PR_FALSE;
00223       mSysPrefService = nsnull;
00224       delete [] mSysPrefs;
00225       mSysPrefs = nsnull;
00226     } else
00227         SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
00228     return rv;
00229 }
00230 
00231 /* private */
00232 
00234 // nsSystemPref::UseSystemPrefs
00235 // Read all the prefs in the table from system, listen for their
00236 // changes in system pref service.
00238 nsresult
00239 nsSystemPref::UseSystemPrefs()
00240 {
00241     SYSPREF_LOG(("\n====Now Use system prefs==\n"));
00242     nsresult rv = NS_OK;
00243     if (!mSysPrefService) {
00244         return NS_ERROR_FAILURE;
00245     }
00246 
00247     PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
00248 
00249     if (!mSysPrefs) {
00250         mSysPrefs = new SysPrefItem[sysPrefCount];
00251         if (!mSysPrefs)
00252             return NS_ERROR_OUT_OF_MEMORY;
00253         for (PRIntn index = 0; index < sysPrefCount; ++index)
00254             mSysPrefs[index].SetPrefName(sSysPrefList[index]);
00255     }
00256 
00257     for (PRIntn index = 0; index < sysPrefCount; ++index) {
00258         // save mozilla prefs
00259         SaveMozDefaultPref(mSysPrefs[index].prefName,
00260                            &mSysPrefs[index].defaultValue,
00261                            &mSysPrefs[index].isLocked);
00262 
00263         // get the system prefs
00264         ReadSystemPref(mSysPrefs[index].prefName);
00265         SYSPREF_LOG(("Add Listener on %s\n", mSysPrefs[index].prefName));
00266         mSysPrefService->AddObserver(mSysPrefs[index].prefName,
00267                                      this, PR_TRUE);
00268     }
00269     return rv;
00270 }
00271 
00273 // nsSystemPref::ReadSystemPref
00274 // Read a pref value from system pref service, and lock it in mozilla.
00276 nsresult
00277 nsSystemPref::ReadSystemPref(const char *aPrefName)
00278 {
00279     if (!mSysPrefService)
00280         return NS_ERROR_FAILURE;
00281     nsresult rv;
00282 
00283     nsCOMPtr<nsIPrefBranch> prefBranch
00284         (do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
00285     if (NS_FAILED(rv))
00286         return rv;
00287 
00288     SYSPREF_LOG(("about to read aPrefName %s\n", aPrefName));
00289 
00290     prefBranch->UnlockPref(aPrefName);
00291 
00292     PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
00293     nsXPIDLCString strValue;
00294     PRInt32 intValue = 0;
00295     PRBool boolValue = PR_FALSE;
00296 
00297     rv = prefBranch->GetPrefType(aPrefName, &prefType);
00298     if (NS_FAILED(rv))
00299         return rv;
00300     switch (prefType) {
00301     case nsIPrefBranch::PREF_STRING:
00302         mSysPrefService->GetCharPref(aPrefName, getter_Copies(strValue));
00303         SYSPREF_LOG(("system value is %s\n", strValue.get()));
00304 
00305         prefBranch->SetCharPref(aPrefName, strValue.get());
00306         break;
00307     case nsIPrefBranch::PREF_INT:
00308         mSysPrefService->GetIntPref(aPrefName, &intValue);
00309         SYSPREF_LOG(("system value is %d\n", intValue));
00310 
00311         prefBranch->SetIntPref(aPrefName, intValue);
00312         break;
00313     case nsIPrefBranch::PREF_BOOL:
00314         mSysPrefService->GetBoolPref(aPrefName, &boolValue);
00315         SYSPREF_LOG(("system value is %s\n", boolValue ? "TRUE" : "FALSE"));
00316 
00317         prefBranch->SetBoolPref(aPrefName, boolValue);
00318         break;
00319     default:
00320         SYSPREF_LOG(("Fail to system value for it\n"));
00321         return NS_ERROR_FAILURE;
00322     }
00323     prefBranch->LockPref(aPrefName);
00324     return NS_OK;
00325 }
00326 
00328 // nsSystemPref::UseMozillaPrefs
00329 // Restore mozilla default prefs, remove system pref listeners
00331 nsresult
00332 nsSystemPref::UseMozillaPrefs()
00333 {
00334     nsresult rv = NS_OK;
00335     SYSPREF_LOG(("\n====Now rollback to Mozilla prefs==\n"));
00336 
00337     // if we did not use system prefs, do nothing
00338     if (!mSysPrefService)
00339         return NS_OK;
00340 
00341     PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
00342     for (PRIntn index = 0; index < sysPrefCount; ++index) {
00343         // restore mozilla default value and free string memory if needed
00344         RestoreMozDefaultPref(mSysPrefs[index].prefName,
00345                               &mSysPrefs[index].defaultValue,
00346                               mSysPrefs[index].isLocked);
00347         SYSPREF_LOG(("stop listening on %s\n", mSysPrefs[index].prefName));
00348         mSysPrefService->RemoveObserver(mSysPrefs[index].prefName,
00349                                         this);
00350     }
00351     return rv;
00352 }
00353 
00355 // nsSystemPref::RestoreMozDefaultPref
00356 // Save the saved mozilla default value.
00357 // It is also responsible for allocate the string memory when needed, because
00358 // this method know what type of value is stored.
00360 nsresult
00361 nsSystemPref::SaveMozDefaultPref(const char *aPrefName,
00362                                  MozPrefValue *aPrefValue,
00363                                  PRBool *aLocked)
00364 {
00365     NS_ENSURE_ARG_POINTER(aPrefName);
00366     NS_ENSURE_ARG_POINTER(aPrefValue);
00367     NS_ENSURE_ARG_POINTER(aLocked);
00368 
00369     nsresult rv;
00370 
00371     nsCOMPtr<nsIPrefBranch> prefBranch =
00372         do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00373     if (NS_FAILED(rv))
00374         return rv;
00375 
00376     SYSPREF_LOG(("Save Mozilla value for %s\n", aPrefName));
00377 
00378     PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
00379     nsXPIDLCString strValue;
00380 
00381     rv = prefBranch->GetPrefType(aPrefName, &prefType);
00382     if (NS_FAILED(rv))
00383         return rv;
00384     switch (prefType) {
00385     case nsIPrefBranch::PREF_STRING:
00386         prefBranch->GetCharPref(aPrefName,
00387                                 getter_Copies(strValue));
00388         SYSPREF_LOG(("Mozilla value is %s", strValue.get()));
00389 
00390         if (aPrefValue->stringVal)
00391             PL_strfree(aPrefValue->stringVal);
00392         aPrefValue->stringVal = PL_strdup(strValue.get());
00393         break;
00394     case nsIPrefBranch::PREF_INT:
00395         prefBranch->GetIntPref(aPrefName, &aPrefValue->intVal);
00396         SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
00397 
00398         break;
00399     case nsIPrefBranch::PREF_BOOL:
00400         prefBranch->GetBoolPref(aPrefName, &aPrefValue->boolVal);
00401         SYSPREF_LOG(("Mozilla value is %s\n",
00402                      aPrefValue->boolVal ? "TRUE" : "FALSE"));
00403 
00404         break;
00405     default:
00406         SYSPREF_LOG(("Fail to Read Mozilla value for it\n"));
00407         return NS_ERROR_FAILURE;
00408     }
00409     rv = prefBranch->PrefIsLocked(aPrefName, aLocked);
00410     SYSPREF_LOG((" (%s).\n", aLocked ? "Locked" : "NOT Locked"));
00411     return rv;
00412 }
00413 
00415 // nsSystemPref::RestoreMozDefaultPref
00416 // Restore the saved mozilla default value to pref service.
00417 // It is also responsible for free the string memory when needed, because
00418 // this method know what type of value is stored.
00420 nsresult
00421 nsSystemPref::RestoreMozDefaultPref(const char *aPrefName,
00422                                     MozPrefValue *aPrefValue,
00423                                     PRBool aLocked)
00424 {
00425     NS_ENSURE_ARG_POINTER(aPrefName);
00426 
00427     nsresult rv;
00428 
00429     nsCOMPtr<nsIPrefBranch> prefBranch =
00430         do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00431     if (NS_FAILED(rv))
00432         return rv;
00433 
00434     SYSPREF_LOG(("Restore Mozilla value for %s\n", aPrefName));
00435 
00436     PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
00437     rv = prefBranch->GetPrefType(aPrefName, &prefType);
00438     if (NS_FAILED(rv))
00439         return rv;
00440 
00441     // unlock, if it is locked
00442     prefBranch->UnlockPref(aPrefName);
00443 
00444     switch (prefType) {
00445     case nsIPrefBranch::PREF_STRING:
00446         prefBranch->SetCharPref(aPrefName,
00447                                 aPrefValue->stringVal);
00448         SYSPREF_LOG(("Mozilla value is %s\n", aPrefValue->stringVal));
00449 
00450         PL_strfree(aPrefValue->stringVal);
00451         aPrefValue->stringVal = nsnull;
00452 
00453         break;
00454     case nsIPrefBranch::PREF_INT:
00455         prefBranch->SetIntPref(aPrefName, aPrefValue->intVal);
00456         SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
00457 
00458         break;
00459     case nsIPrefBranch::PREF_BOOL:
00460         prefBranch->SetBoolPref(aPrefName, aPrefValue->boolVal);
00461         SYSPREF_LOG(("Mozilla value is %s\n",
00462                      aPrefValue->boolVal ? "TRUE" : "FALSE"));
00463 
00464         break;
00465     default:
00466         SYSPREF_LOG(("Fail to Restore Mozilla value for it\n"));
00467         return NS_ERROR_FAILURE;
00468     }
00469 
00470     // restore its old lock status
00471     if (aLocked)
00472         prefBranch->LockPref(aPrefName);
00473     return NS_OK;
00474 }