Bug 1364146: Only reset the prefs dirty flag when we save to the default prefs file, not on a save to another file. r?bsmedberg draft
authorMilan Sreckovic <milan@mozilla.com>
Tue, 16 May 2017 13:10:40 -0400 (2017-05-16)
changeset 578821 eec807ca909785f388f51d9e61cbe4e5cc8387b3
parent 578818 b8e9b674033bcd1f3a4c59b9d0ee7619c1a17cc5
child 628851 f12123e7e91383c69a5f64b0afdb32cea261f168
push id59078
push userbmo:milan@mozilla.com
push dateTue, 16 May 2017 17:11:11 +0000 (2017-05-16)
reviewersbsmedberg
bugs1364146
milestone55.0a1
Bug 1364146: Only reset the prefs dirty flag when we save to the default prefs file, not on a save to another file. r?bsmedberg MozReview-Commit-ID: ITskObzuTTb
modules/libpref/Preferences.cpp
modules/libpref/test/unit/test_dirtyPrefs.js
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -966,28 +966,38 @@ Preferences::ReadAndOwnUserPrefFile(nsIF
   }
 
   return rv;
 }
 
 nsresult
 Preferences::SavePrefFileInternal(nsIFile *aFile)
 {
+  // We allow different behavior here when aFile argument is not null,
+  // but it happens to be the same as the current file.  It is not
+  // clear that we should, but it does give us a "force" save on the
+  // unmodified pref file (see the original bug 160377 when we added this.)
+
   if (nullptr == aFile) {
     // the mDirty flag tells us if we should write to mCurrentFile
     // we only check this flag when the caller wants to write to the default
     if (!mDirty) {
       return NS_OK;
     }
 
     // It's possible that we never got a prefs file.
     nsresult rv = NS_OK;
-    if (mCurrentFile)
+    if (mCurrentFile) {
       rv = WritePrefFile(mCurrentFile);
+    }
 
+    // If we succeeded writing to mCurrentFile, reset the dirty flag
+    if (NS_SUCCEEDED(rv)) {
+      mDirty = false;
+    }
     return rv;
   } else {
     return WritePrefFile(aFile);
   }
 }
 
 nsresult
 Preferences::WritePrefFile(nsIFile* aFile)
@@ -1040,18 +1050,16 @@ Preferences::WritePrefFile(nsIFile* aFil
   NS_ASSERTION(safeStream, "expected a safe output stream!");
   if (safeStream) {
     rv = safeStream->Finish();
     if (NS_FAILED(rv)) {
       NS_WARNING("failed to save prefs file! possible data loss");
       return rv;
     }
   }
-
-  mDirty = false;
   return NS_OK;
 }
 
 static nsresult openPrefFile(nsIFile* aFile)
 {
   nsCOMPtr<nsIInputStream> inStr;
 
   nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), aFile);
--- a/modules/libpref/test/unit/test_dirtyPrefs.js
+++ b/modules/libpref/test/unit/test_dirtyPrefs.js
@@ -15,61 +15,72 @@ function run_test() {
             getService(Ci.nsIPrefService);
 
   let defaultBranch = ps.getDefaultBranch("");
   let userBranch = ps.getBranch("");
 
   let prefFile = do_get_profile();
   prefFile.append("prefs.js");
 
+  // dirty flag only applies to the default pref file save, not all of them,
+  // so we need to set the default pref file first.  Chances are, the file
+  // does not exist, but we don't need it to - we just want to set the
+  // name/location to match
+  //
+  try {
+    ps.readUserPrefs(prefFile);
+  } catch (e) {
+    // we're fine if the file isn't there
+  }
+
   //**************************************************************************//
   // prefs are not dirty after a write
-  ps.savePrefFile(prefFile);
+  ps.savePrefFile(null);
   do_check_false(ps.dirty);
 
   // set a new a user value, we should become dirty
   userBranch.setBoolPref("DirtyTest.new.bool", true);
   do_check_true(ps.dirty);
-  ps.savePrefFile(prefFile);
+  ps.savePrefFile(null);
   // Overwrite a pref with the same value => not dirty
   userBranch.setBoolPref("DirtyTest.new.bool", true);
   do_check_false(ps.dirty);
 
   // Repeat for the other two types
   userBranch.setIntPref("DirtyTest.new.int", 1);
   do_check_true(ps.dirty);
-  ps.savePrefFile(prefFile);
+  ps.savePrefFile(null);
   // Overwrite a pref with the same value => not dirty
   userBranch.setIntPref("DirtyTest.new.int", 1);
   do_check_false(ps.dirty);
 
   userBranch.setCharPref("DirtyTest.new.char", "oop");
   do_check_true(ps.dirty);
-  ps.savePrefFile(prefFile);
+  ps.savePrefFile(null);
   // Overwrite a pref with the same value => not dirty
   userBranch.setCharPref("DirtyTest.new.char", "oop");
   do_check_false(ps.dirty);
 
   // change *type* of a user value -> dirty
   userBranch.setBoolPref("DirtyTest.new.char", false);
   do_check_true(ps.dirty);
-  ps.savePrefFile(prefFile);
+  ps.savePrefFile(null);
 
   // Set a default pref => not dirty (defaults don't go into prefs.js)
   defaultBranch.setBoolPref("DirtyTest.existing.bool", true);
   do_check_false(ps.dirty);
   // Fail to change type of a pref with default value -> not dirty
   do_check_throws(function() {
     userBranch.setCharPref("DirtyTest.existing.bool", "boo"); }, Cr.NS_ERROR_UNEXPECTED);
   do_check_false(ps.dirty);
 
   // Set user value same as default, not dirty
   userBranch.setBoolPref("DirtyTest.existing.bool", true);
   do_check_false(ps.dirty);
   // User value different from default, dirty
   userBranch.setBoolPref("DirtyTest.existing.bool", false);
   do_check_true(ps.dirty);
-  ps.savePrefFile(prefFile);
+  ps.savePrefFile(null);
   // Back to default value, dirty again
   userBranch.setBoolPref("DirtyTest.existing.bool", true);
   do_check_true(ps.dirty);
-  ps.savePrefFile(prefFile);
+  ps.savePrefFile(null);
 }