Bug 616414: Notify content processes when a pref has been cleared. r=dwitte
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -488,16 +488,28 @@ ContentChild::RecvPreferenceUpdate(const
return false;
prefs->SetPreference(&aPref);
return true;
}
bool
+ContentChild::RecvClearUserPreference(const nsCString& aPrefName)
+{
+ nsCOMPtr<nsIPrefServiceInternal> prefs = do_GetService("@mozilla.org/preferences-service;1");
+ if (!prefs)
+ return false;
+
+ prefs->ClearContentPref(aPrefName);
+
+ return true;
+}
+
+bool
ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData)
{
for (PRUint32 i = 0; i < mAlertObservers.Length();
/*we mutate the array during the loop; ++i iff no mutation*/) {
AlertObserver* observer = mAlertObservers[i];
if (observer->Observes(aData) && observer->Notify(aType)) {
// if aType == alertfinished, this alert is done. we can
// remove the observer.
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -113,16 +113,17 @@ public:
virtual bool RecvSetOffline(const PRBool& offline);
virtual bool RecvNotifyVisited(const IPC::URI& aURI);
// auto remove when alertfinished is received.
nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);
virtual bool RecvPreferenceUpdate(const PrefTuple& aPref);
+ virtual bool RecvClearUserPreference(const nsCString& aPrefName);
virtual bool RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData);
virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);
virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere);
virtual bool RecvAddPermission(const IPC::Permission& permission);
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -367,24 +367,36 @@ ContentParent::Observe(nsISupports* aSub
if (!strcmp(aTopic, "memory-pressure")) {
SendFlushMemory(nsDependentString(aData));
}
// listening for remotePrefs...
else if (!strcmp(aTopic, "nsPref:changed")) {
// We know prefs are ASCII here.
NS_LossyConvertUTF16toASCII strData(aData);
- PrefTuple pref;
nsCOMPtr<nsIPrefServiceInternal> prefService =
do_GetService("@mozilla.org/preferences-service;1");
- prefService->MirrorPreference(strData, &pref);
-
- if (!SendPreferenceUpdate(pref))
- return NS_ERROR_NOT_AVAILABLE;
+ PRBool prefHasValue;
+ prefService->PrefHasUserValue(strData, &prefHasValue);
+ if (prefHasValue) {
+ // Pref was created, or previously existed and its value
+ // changed.
+ PrefTuple pref;
+ nsresult rv = prefService->MirrorPreference(strData, &pref);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Pref has value but can't mirror?");
+ if (!SendPreferenceUpdate(pref)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ } else {
+ // Pref wasn't found. It was probably removed.
+ if (!SendClearUserPreference(strData)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ }
}
else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
NS_ConvertUTF16toUTF8 dataStr(aData);
const char *offline = dataStr.get();
if (!SendSetOffline(!strcmp(offline, "true") ? true : false))
return NS_ERROR_NOT_AVAILABLE;
}
// listening for alert notifications
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -99,16 +99,17 @@ child:
RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
OverrideMapping[] overrides);
async SetOffline(PRBool offline);
async NotifyVisited(URI uri);
PreferenceUpdate(PrefTuple pref);
+ ClearUserPreference(nsCString prefName);
NotifyAlertsObserver(nsCString topic, nsString data);
GeolocationUpdate(GeoPosition somewhere);
// nsIPermissionManager messages
AddPermission(Permission permission);
--- a/modules/libpref/public/nsIPrefService.idl
+++ b/modules/libpref/public/nsIPrefService.idl
@@ -158,17 +158,17 @@ interface nsIPrefService : nsISupports
* @return nsIPrefBranch The object representing the requested default branch.
*
* @see getBranch
*/
nsIPrefBranch getDefaultBranch(in string aPrefRoot);
};
-[scriptable, uuid(37577836-e3fc-4a5e-b5d1-92a17fe0e7f7)]
+[scriptable, uuid(08c8cd2f-8345-45ee-938d-37ee6d3661b2)]
interface nsIPrefServiceInternal : nsISupports
{
/**
* Called to read the preferences in the defaults/preferences/
* directory of a zip file
*
* @param aFile The zip file to be read.
*
@@ -176,17 +176,19 @@ interface nsIPrefServiceInternal : nsISu
* @return Other The file failed to read or contained invalid data.
*
* @see readUserPrefs
*/
void readExtensionPrefs(in nsILocalFile aFile);
[noscript] void mirrorPreferences(in nsPreferencesArrayPtr aArray);
[noscript] void mirrorPreference(in ACString aPrefName, in nsPreferencePtr aPref);
+ [noscript] boolean prefHasUserValue(in ACString aPrefName);
[noscript] void setPreference(in nsPreferencePtrConst aPref);
+ [noscript] void clearContentPref(in ACString aPrefName);
};
%{C++
#define NS_PREFSERVICE_CID \
{ /* {1cd91b88-1dd2-11b2-92e1-ed22ed298000} */ \
0x91ca2441, \
0x050f, \
--- a/modules/libpref/src/nsPrefService.cpp
+++ b/modules/libpref/src/nsPrefService.cpp
@@ -345,21 +345,33 @@ NS_IMETHODIMP nsPrefService::ReadExtensi
break;
}
}
PREF_FinalizeParseState(&ps);
}
return rv;
}
+NS_IMETHODIMP nsPrefService::PrefHasUserValue(const nsACString& aPrefName,
+ PRBool* aHasValue)
+{
+ *aHasValue = PREF_HasUserPref(aPrefName.BeginReading());
+ return NS_OK;
+}
+
NS_IMETHODIMP nsPrefService::SetPreference(const PrefTuple *aPref)
{
return pref_SetPrefTuple(*aPref, PR_TRUE);
}
+NS_IMETHODIMP nsPrefService::ClearContentPref(const nsACString& aPrefName)
+{
+ return PREF_ClearUserPref(aPrefName.BeginReading());
+}
+
NS_IMETHODIMP nsPrefService::MirrorPreference(const nsACString& aPrefName,
PrefTuple *aPref)
{
PrefHashEntry *pref = pref_HashTableLookup(nsDependentCString(aPrefName).get());
if (!pref)
return NS_ERROR_NOT_AVAILABLE;