Bug 1418467 - Add PrefHashEntry::SetValue(). r=glandium
authorNicholas Nethercote <nnethercote@mozilla.com>
Sat, 18 Nov 2017 07:38:24 +1100
changeset 437300 85eea5172cd8c6efe4ee8c060d1bd58b377b4caf
parent 437299 8fe0a8c0c579627cb4fb30da60b06f715c0d0461
child 437301 effb563bb7e5692cf7d911725b5870f1b7f6c41c
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersglandium
bugs1418467
milestone59.0a1
Bug 1418467 - Add PrefHashEntry::SetValue(). r=glandium It's a horrible method, but the horribleness was pre-existing. I hope to make it nicer in a follow-up bug. MozReview-Commit-ID: 3tMTEeBNVax
modules/libpref/Preferences.cpp
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -228,16 +228,23 @@ StrEscape(const char* aOriginal, nsCStri
         aResult.Append(*p);
         break;
     }
   }
 
   aResult.Append('"');
 }
 
+enum
+{
+  kPrefSetDefault = 1,
+  kPrefForceSet = 2,
+  kPrefSticky = 4,
+};
+
 static ArenaAllocator<8192, 1> gPrefNameArena;
 
 class PrefHashEntry : public PLDHashEntryHdr
 {
 public:
   PrefHashEntry(const char* aName, PrefType aType)
   {
     mName = ArenaStrdup(aName, gPrefNameArena);
@@ -438,16 +445,17 @@ public:
       if (strlen(stringVal) > MAX_ADVISABLE_PREF_LENGTH) {
         return false;
       }
     }
 
     return true;
   }
 
+private:
   // Overwrite the type and value of an existing preference. Caller must ensure
   // that they are not changing the type of a preference that has a default
   // value.
   void ReplaceValue(PrefValueKind aKind, PrefType aNewType, PrefValue aNewValue)
   {
     PrefValue* value =
       aKind == PrefValueKind::Default ? &mDefaultValue : &mUserValue;
 
@@ -460,16 +468,65 @@ public:
     if (aNewType == PrefType::String) {
       MOZ_ASSERT(aNewValue.mStringVal);
       value->mStringVal = moz_xstrdup(aNewValue.mStringVal);
     } else {
       *value = aNewValue;
     }
   }
 
+public:
+  void SetValue(PrefType aType,
+                PrefValue aValue,
+                uint32_t aFlags,
+                bool* aValueChanged,
+                bool* aDirty)
+  {
+    if (aFlags & kPrefSetDefault) {
+      if (!IsLocked()) {
+        // ?? change of semantics?
+        if (!HasDefaultValue() || !mDefaultValue.Equals(aType, aValue)) {
+          ReplaceValue(PrefValueKind::Default, aType, aValue);
+          SetHasDefaultValue(true);
+          if (aFlags & kPrefSticky) {
+            SetIsSticky(true);
+          }
+          if (!HasUserValue()) {
+            *aValueChanged = true;
+          }
+        }
+        // What if we change the default to be the same as the user value?
+        // Should we clear the user value?
+      }
+    } else {
+      // If new value is same as the default value and it's not a "sticky"
+      // pref, then un-set the user value. Otherwise, set the user value only
+      // if it has changed.
+      if (HasDefaultValue() && !IsSticky() &&
+          mDefaultValue.Equals(aType, aValue) && !(aFlags & kPrefForceSet)) {
+        if (HasUserValue()) {
+          // XXX should we free a user-set string value if there is one?
+          SetHasUserValue(false);
+          if (!IsLocked()) {
+            *aDirty = true;
+            *aValueChanged = true;
+          }
+        }
+      } else if (!HasUserValue() || !IsType(aType) ||
+                 !mUserValue.Equals(aType, aValue)) {
+        ReplaceValue(PrefValueKind::User, aType, aValue);
+        SetHasUserValue(true);
+        if (!IsLocked()) {
+          *aDirty = true;
+          *aValueChanged = true;
+        }
+      }
+    }
+  }
+
   // Returns false if this pref doesn't have a user value worth saving.
   bool UserValueToStringForSaving(nsCString& aStr)
   {
     if (HasUserValue() && (!HasDefaultValue() || IsSticky() ||
                            !mDefaultValue.Equals(Type(), mUserValue))) {
       if (IsTypeString()) {
         StrEscape(mUserValue.mStringVal, aStr);
 
@@ -555,23 +612,16 @@ static PLDHashTableOps pref_HashTableOps
 //---------------------------------------------------------------------------
 
 static PrefHashEntry*
 pref_HashTableLookup(const char* aPrefName);
 
 static nsresult
 pref_DoCallback(const char* aChangedPref);
 
-enum
-{
-  kPrefSetDefault = 1,
-  kPrefForceSet = 2,
-  kPrefSticky = 4,
-};
-
 #define PREF_HASHTABLE_INITIAL_LENGTH 1024
 
 static PrefSaveData
 pref_savePrefs()
 {
   PrefSaveData savedPrefs(gHashTable->EntryCount());
 
   for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
@@ -793,60 +843,22 @@ pref_SetPref(const char* aPrefName,
         aPrefName,
         PrefTypeToString(pref->Type()),
         PrefTypeToString(aType))
         .get());
 
     return NS_ERROR_UNEXPECTED;
   }
 
-  bool valueChanged = false;
-  if (aFlags & kPrefSetDefault) {
-    if (!pref->IsLocked()) {
-      // ?? change of semantics?
-      if (!pref->HasDefaultValue() ||
-          !pref->mDefaultValue.Equals(aType, aValue)) {
-        pref->ReplaceValue(PrefValueKind::Default, aType, aValue);
-        pref->SetHasDefaultValue(true);
-        if (aFlags & kPrefSticky) {
-          pref->SetIsSticky(true);
-        }
-        if (!pref->HasUserValue()) {
-          valueChanged = true;
-        }
-      }
-      // What if we change the default to be the same as the user value?
-      // Should we clear the user value?
-    }
-  } else {
-    // If new value is same as the default value and it's not a "sticky" pref,
-    // then un-set the user value. Otherwise, set the user value only if it has
-    // changed.
-    if (pref->HasDefaultValue() && !pref->IsSticky() &&
-        pref->mDefaultValue.Equals(aType, aValue) &&
-        !(aFlags & kPrefForceSet)) {
-      if (pref->HasUserValue()) {
-        // XXX should we free a user-set string value if there is one?
-        pref->SetHasUserValue(false);
-        if (!pref->IsLocked()) {
-          Preferences::HandleDirty();
-          valueChanged = true;
-        }
-      }
-    } else if (!pref->HasUserValue() || !pref->IsType(aType) ||
-               !pref->mUserValue.Equals(aType, aValue)) {
-      pref->ReplaceValue(PrefValueKind::User, aType, aValue);
-      pref->SetHasUserValue(true);
-      if (!pref->IsLocked()) {
-        Preferences::HandleDirty();
-        valueChanged = true;
-      }
-    }
+  bool valueChanged = false, handleDirty = false;
+  pref->SetValue(aType, aValue, aFlags, &valueChanged, &handleDirty);
+
+  if (handleDirty) {
+    Preferences::HandleDirty();
   }
-
   if (valueChanged) {
     return pref_DoCallback(aPrefName);
   }
 
   return NS_OK;
 }
 
 // Bool function that returns whether or not the preference is locked and