Bug 464146 - about:rights notification sometimes not shown with session restore....
[wine-gecko.git] / extensions / pref / system-pref / src / nsSystemPref.cpp
blob09045205bcbc5a8b181c7b240e3ad5a9e4b1d786
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
3 */
4 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
8 * The contents of this file are subject to the Mozilla Public
9 * License Version 1.1 (the "License"); you may not use this file
10 * except in compliance with the License. You may obtain a copy of
11 * the License at http://www.mozilla.org/MPL/
13 * Software distributed under the License is distributed on an "AS
14 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 * implied. See the License for the specific language governing
16 * rights and limitations under the License.
18 * The Original Code is mozilla.org code.
20 * The Initial Developer of the Original Code is Sun Microsystems, Inc.
21 * Portions created by Sun Microsystems are Copyright (C) 2003 Sun
22 * Microsystems, Inc. All Rights Reserved.
24 * Original Author: Bolian Yin (bolian.yin@sun.com)
26 * Contributor(s):
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the NPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the NPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 #include "nsSystemPref.h"
43 #include "nsIObserverService.h"
45 #include "nsSystemPrefLog.h"
46 #include "nsSystemPrefService.h"
47 #include "nsString.h"
49 const char sSysPrefString[] = "config.use_system_prefs";
50 union MozPrefValue {
51 char * stringVal;
52 PRInt32 intVal;
53 PRBool boolVal;
56 struct SysPrefItem {
57 const char *prefName; // mozilla pref string name
58 MozPrefValue defaultValue; // store the mozilla default value
59 PRBool isLocked; // store the mozilla lock status
60 SysPrefItem() {
61 prefName = nsnull;
62 defaultValue.intVal = 0;
63 defaultValue.stringVal = nsnull;
64 defaultValue.boolVal = PR_FALSE;
65 isLocked = PR_FALSE;
67 void SetPrefName(const char *aPrefName) {
68 prefName = aPrefName;
72 // all prefs that mozilla need to read from host system if they are available
73 static const char *sSysPrefList[] = {
74 "network.proxy.http",
75 "network.proxy.http_port",
76 "network.proxy.ftp",
77 "network.proxy.ftp_port",
78 "network.proxy.ssl",
79 "network.proxy.ssl_port",
80 "network.proxy.socks",
81 "network.proxy.socks_port",
82 "network.proxy.no_proxies_on",
83 "network.proxy.autoconfig_url",
84 "network.proxy.type",
85 "config.use_system_prefs.accessibility",
88 PRLogModuleInfo *gSysPrefLog = NULL;
90 NS_IMPL_ISUPPORTS2(nsSystemPref, nsIObserver, nsISupportsWeakReference)
92 nsSystemPref::nsSystemPref():
93 mSysPrefService(nsnull),
94 mEnabled(PR_FALSE),
95 mSysPrefs(nsnull)
99 nsSystemPref::~nsSystemPref()
101 mSysPrefService = nsnull;
102 mEnabled = PR_FALSE;
103 delete [] mSysPrefs;
106 ///////////////////////////////////////////////////////////////////////////////
107 // nsSystemPref::Init
108 // Setup log and listen on NS_PREFSERVICE_READ_TOPIC_ID from pref service
109 ///////////////////////////////////////////////////////////////////////////////
110 nsresult
111 nsSystemPref::Init(void)
113 nsresult rv;
115 if (!gSysPrefLog) {
116 gSysPrefLog = PR_NewLogModule("Syspref");
117 if (!gSysPrefLog)
118 return NS_ERROR_OUT_OF_MEMORY;
121 nsCOMPtr<nsIObserverService> observerService =
122 do_GetService("@mozilla.org/observer-service;1", &rv);
124 if (observerService) {
125 rv = observerService->AddObserver(this, NS_PREFSERVICE_READ_TOPIC_ID,
126 PR_FALSE);
127 rv = observerService->AddObserver(this, "profile-before-change",
128 PR_FALSE);
129 SYSPREF_LOG(("Add Observer for %s\n", NS_PREFSERVICE_READ_TOPIC_ID));
131 return(rv);
134 ///////////////////////////////////////////////////////////////////////////////
135 // nsSystemPref::Observe
136 // Observe notifications from mozilla pref system and system prefs (if enabled)
137 ///////////////////////////////////////////////////////////////////////////////
138 NS_IMETHODIMP
139 nsSystemPref::Observe(nsISupports *aSubject,
140 const char *aTopic,
141 const PRUnichar *aData)
143 nsresult rv = NS_OK;
145 if (!aTopic)
146 return NS_OK;
148 // if we are notified by pref service
149 // check the system pref settings
150 if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
151 SYSPREF_LOG(("Observed: %s\n", aTopic));
153 nsCOMPtr<nsIPrefBranch2> prefBranch =
154 do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
155 if (NS_FAILED(rv))
156 return rv;
158 rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
159 if (NS_FAILED(rv)) {
160 SYSPREF_LOG(("...FAil to Get %s\n", sSysPrefString));
161 return rv;
164 // if there is no system pref service, assume nothing happen to us
165 mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
166 if (NS_FAILED(rv) || !mSysPrefService) {
167 SYSPREF_LOG(("...No System Pref Service\n"));
168 return NS_OK;
171 // listen on its changes
172 rv = prefBranch->AddObserver(sSysPrefString, this, PR_TRUE);
173 if (NS_FAILED(rv)) {
174 SYSPREF_LOG(("...FAil to add observer for %s\n", sSysPrefString));
175 return rv;
178 if (!mEnabled) {
179 SYSPREF_LOG(("%s is disabled\n", sSysPrefString));
180 return NS_OK;
182 SYSPREF_LOG(("%s is enabled\n", sSysPrefString));
183 rv = UseSystemPrefs();
186 // sSysPrefString value was changed, update ...
187 else if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
188 NS_ConvertUTF8toUTF16(sSysPrefString).Equals(aData)) {
189 SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
190 aTopic, NS_ConvertUTF16toUTF8(aData).get()));
192 nsCOMPtr<nsIPrefBranch> prefBranch =
193 do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
194 if (NS_FAILED(rv))
195 return rv;
197 PRBool enabled = mEnabled;
198 rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
199 if (enabled != mEnabled) {
200 if (mEnabled)
201 //read prefs from system
202 rv = UseSystemPrefs();
203 else
204 //roll back to mozilla prefs
205 rv = UseMozillaPrefs();
209 // if the system pref notify us that some pref has been changed by user
210 // outside mozilla. We need to read it again.
211 else if (!nsCRT::strcmp(aTopic, NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID) &&
212 aData) {
213 NS_ASSERTION(mEnabled == PR_TRUE, "Should not listen when disabled");
214 SYSPREF_LOG(("====== System Pref Notify topic=%s data=%s\n",
215 aTopic, (char*)aData));
216 rv = ReadSystemPref(NS_LossyConvertUTF16toASCII(aData).get());
217 return NS_OK;
218 } else if (!nsCRT::strcmp(aTopic,"profile-before-change")) {
219 //roll back to mozilla prefs
220 if (mEnabled)
221 UseMozillaPrefs();
222 mEnabled = PR_FALSE;
223 mSysPrefService = nsnull;
224 delete [] mSysPrefs;
225 mSysPrefs = nsnull;
226 } else
227 SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
228 return rv;
231 /* private */
233 ////////////////////////////////////////////////////////////////
234 // nsSystemPref::UseSystemPrefs
235 // Read all the prefs in the table from system, listen for their
236 // changes in system pref service.
237 ////////////////////////////////////////////////////////////////
238 nsresult
239 nsSystemPref::UseSystemPrefs()
241 SYSPREF_LOG(("\n====Now Use system prefs==\n"));
242 nsresult rv = NS_OK;
243 if (!mSysPrefService) {
244 return NS_ERROR_FAILURE;
247 PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
249 if (!mSysPrefs) {
250 mSysPrefs = new SysPrefItem[sysPrefCount];
251 if (!mSysPrefs)
252 return NS_ERROR_OUT_OF_MEMORY;
253 for (PRIntn index = 0; index < sysPrefCount; ++index)
254 mSysPrefs[index].SetPrefName(sSysPrefList[index]);
257 for (PRIntn index = 0; index < sysPrefCount; ++index) {
258 // save mozilla prefs
259 SaveMozDefaultPref(mSysPrefs[index].prefName,
260 &mSysPrefs[index].defaultValue,
261 &mSysPrefs[index].isLocked);
263 // get the system prefs
264 ReadSystemPref(mSysPrefs[index].prefName);
265 SYSPREF_LOG(("Add Listener on %s\n", mSysPrefs[index].prefName));
266 mSysPrefService->AddObserver(mSysPrefs[index].prefName,
267 this, PR_TRUE);
269 return rv;
272 //////////////////////////////////////////////////////////////////////
273 // nsSystemPref::ReadSystemPref
274 // Read a pref value from system pref service, and lock it in mozilla.
275 //////////////////////////////////////////////////////////////////////
276 nsresult
277 nsSystemPref::ReadSystemPref(const char *aPrefName)
279 if (!mSysPrefService)
280 return NS_ERROR_FAILURE;
281 nsresult rv;
283 nsCOMPtr<nsIPrefBranch> prefBranch
284 (do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
285 if (NS_FAILED(rv))
286 return rv;
288 SYSPREF_LOG(("about to read aPrefName %s\n", aPrefName));
290 prefBranch->UnlockPref(aPrefName);
292 PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
293 nsXPIDLCString strValue;
294 PRInt32 intValue = 0;
295 PRBool boolValue = PR_FALSE;
297 rv = prefBranch->GetPrefType(aPrefName, &prefType);
298 if (NS_FAILED(rv))
299 return rv;
300 switch (prefType) {
301 case nsIPrefBranch::PREF_STRING:
302 mSysPrefService->GetCharPref(aPrefName, getter_Copies(strValue));
303 SYSPREF_LOG(("system value is %s\n", strValue.get()));
305 prefBranch->SetCharPref(aPrefName, strValue.get());
306 break;
307 case nsIPrefBranch::PREF_INT:
308 mSysPrefService->GetIntPref(aPrefName, &intValue);
309 SYSPREF_LOG(("system value is %d\n", intValue));
311 prefBranch->SetIntPref(aPrefName, intValue);
312 break;
313 case nsIPrefBranch::PREF_BOOL:
314 mSysPrefService->GetBoolPref(aPrefName, &boolValue);
315 SYSPREF_LOG(("system value is %s\n", boolValue ? "TRUE" : "FALSE"));
317 prefBranch->SetBoolPref(aPrefName, boolValue);
318 break;
319 default:
320 SYSPREF_LOG(("Fail to system value for it\n"));
321 return NS_ERROR_FAILURE;
323 prefBranch->LockPref(aPrefName);
324 return NS_OK;
327 //////////////////////////////////////////////////////////////////////
328 // nsSystemPref::UseMozillaPrefs
329 // Restore mozilla default prefs, remove system pref listeners
330 /////////////////////////////////////////////////////////////////////
331 nsresult
332 nsSystemPref::UseMozillaPrefs()
334 nsresult rv = NS_OK;
335 SYSPREF_LOG(("\n====Now rollback to Mozilla prefs==\n"));
337 // if we did not use system prefs, do nothing
338 if (!mSysPrefService)
339 return NS_OK;
341 PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
342 for (PRIntn index = 0; index < sysPrefCount; ++index) {
343 // restore mozilla default value and free string memory if needed
344 RestoreMozDefaultPref(mSysPrefs[index].prefName,
345 &mSysPrefs[index].defaultValue,
346 mSysPrefs[index].isLocked);
347 SYSPREF_LOG(("stop listening on %s\n", mSysPrefs[index].prefName));
348 mSysPrefService->RemoveObserver(mSysPrefs[index].prefName,
349 this);
351 return rv;
354 ////////////////////////////////////////////////////////////////////////////
355 // nsSystemPref::RestoreMozDefaultPref
356 // Save the saved mozilla default value.
357 // It is also responsible for allocate the string memory when needed, because
358 // this method know what type of value is stored.
359 /////////////////////////////////////////////////////////////////////////////
360 nsresult
361 nsSystemPref::SaveMozDefaultPref(const char *aPrefName,
362 MozPrefValue *aPrefValue,
363 PRBool *aLocked)
365 NS_ENSURE_ARG_POINTER(aPrefName);
366 NS_ENSURE_ARG_POINTER(aPrefValue);
367 NS_ENSURE_ARG_POINTER(aLocked);
369 nsresult rv;
371 nsCOMPtr<nsIPrefBranch> prefBranch =
372 do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
373 if (NS_FAILED(rv))
374 return rv;
376 SYSPREF_LOG(("Save Mozilla value for %s\n", aPrefName));
378 PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
379 nsXPIDLCString strValue;
381 rv = prefBranch->GetPrefType(aPrefName, &prefType);
382 if (NS_FAILED(rv))
383 return rv;
384 switch (prefType) {
385 case nsIPrefBranch::PREF_STRING:
386 prefBranch->GetCharPref(aPrefName,
387 getter_Copies(strValue));
388 SYSPREF_LOG(("Mozilla value is %s", strValue.get()));
390 if (aPrefValue->stringVal)
391 PL_strfree(aPrefValue->stringVal);
392 aPrefValue->stringVal = PL_strdup(strValue.get());
393 break;
394 case nsIPrefBranch::PREF_INT:
395 prefBranch->GetIntPref(aPrefName, &aPrefValue->intVal);
396 SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
398 break;
399 case nsIPrefBranch::PREF_BOOL:
400 prefBranch->GetBoolPref(aPrefName, &aPrefValue->boolVal);
401 SYSPREF_LOG(("Mozilla value is %s\n",
402 aPrefValue->boolVal ? "TRUE" : "FALSE"));
404 break;
405 default:
406 SYSPREF_LOG(("Fail to Read Mozilla value for it\n"));
407 return NS_ERROR_FAILURE;
409 rv = prefBranch->PrefIsLocked(aPrefName, aLocked);
410 SYSPREF_LOG((" (%s).\n", aLocked ? "Locked" : "NOT Locked"));
411 return rv;
414 ////////////////////////////////////////////////////////////////////////////
415 // nsSystemPref::RestoreMozDefaultPref
416 // Restore the saved mozilla default value to pref service.
417 // It is also responsible for free the string memory when needed, because
418 // this method know what type of value is stored.
419 /////////////////////////////////////////////////////////////////////////////
420 nsresult
421 nsSystemPref::RestoreMozDefaultPref(const char *aPrefName,
422 MozPrefValue *aPrefValue,
423 PRBool aLocked)
425 NS_ENSURE_ARG_POINTER(aPrefName);
427 nsresult rv;
429 nsCOMPtr<nsIPrefBranch> prefBranch =
430 do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
431 if (NS_FAILED(rv))
432 return rv;
434 SYSPREF_LOG(("Restore Mozilla value for %s\n", aPrefName));
436 PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
437 rv = prefBranch->GetPrefType(aPrefName, &prefType);
438 if (NS_FAILED(rv))
439 return rv;
441 // unlock, if it is locked
442 prefBranch->UnlockPref(aPrefName);
444 switch (prefType) {
445 case nsIPrefBranch::PREF_STRING:
446 prefBranch->SetCharPref(aPrefName,
447 aPrefValue->stringVal);
448 SYSPREF_LOG(("Mozilla value is %s\n", aPrefValue->stringVal));
450 PL_strfree(aPrefValue->stringVal);
451 aPrefValue->stringVal = nsnull;
453 break;
454 case nsIPrefBranch::PREF_INT:
455 prefBranch->SetIntPref(aPrefName, aPrefValue->intVal);
456 SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
458 break;
459 case nsIPrefBranch::PREF_BOOL:
460 prefBranch->SetBoolPref(aPrefName, aPrefValue->boolVal);
461 SYSPREF_LOG(("Mozilla value is %s\n",
462 aPrefValue->boolVal ? "TRUE" : "FALSE"));
464 break;
465 default:
466 SYSPREF_LOG(("Fail to Restore Mozilla value for it\n"));
467 return NS_ERROR_FAILURE;
470 // restore its old lock status
471 if (aLocked)
472 prefBranch->LockPref(aPrefName);
473 return NS_OK;