Bug 1394578 - Pass pref locked status to content processes. r=glandium draft
authorNicholas Nethercote <nnethercote@mozilla.com>
Sat, 25 Nov 2017 13:46:26 +1100
changeset 703385 a6506ae8f7aed688ef5f8d730fb7d2f03bf0e3ab
parent 703384 e2209017d344822fa829befc0f6b430ec8d32047
child 741755 98df6b2b13a02935ec142bd7a347ce3bcd3364a1
push id90801
push usernnethercote@mozilla.com
push dateSat, 25 Nov 2017 06:45:10 +0000
reviewersglandium
bugs1394578
milestone59.0a1
Bug 1394578 - Pass pref locked status to content processes. r=glandium This makes the IPC messages a little bigger, but that's unavoidable. MozReview-Commit-ID: 1oPz2Yjjd9y
dom/ipc/ContentParent.cpp
dom/ipc/ContentProcess.cpp
dom/ipc/PContent.ipdl
modules/libpref/Preferences.cpp
modules/libpref/test/unit_ipc/test_initial_prefs.js
modules/libpref/test/unit_ipc/test_locked_prefs.js
modules/libpref/test/unit_ipc/test_observed_prefs.js
modules/libpref/test/unit_ipc/test_update_prefs.js
modules/libpref/test/unit_ipc/xpcshell.ini
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2792,17 +2792,17 @@ ContentParent::Observe(nsISupports* aSub
       if (NS_strncmp(entry.mPrefBranch, aData, entry.mLen) == 0) {
         return NS_OK;
       }
     }
 
     // We know prefs are ASCII here.
     NS_LossyConvertUTF16toASCII strData(aData);
 
-    Pref pref(strData, null_t(), null_t());
+    Pref pref(strData, false, null_t(), null_t());
     Preferences::GetPreference(&pref);
     if (!SendPreferenceUpdate(pref)) {
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
   else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
     NS_ConvertUTF16toUTF8 dataStr(aData);
     const char *offline = dataStr.get();
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -151,48 +151,51 @@ ContentProcess::Init(int aArgc, char* aA
       char* str = aArgv[idx + 1];
       while (*str) {
         int32_t index = strtol(str, &str, 10);
         MOZ_ASSERT(str[0] == ':');
         str++;
         MaybePrefValue value(PrefValue(static_cast<int32_t>(strtol(str, &str, 10))));
         MOZ_ASSERT(str[0] == '|');
         str++;
-        Pref pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue());
+        // XXX: we assume these values as default values, which may not be
+        // true. We also assume they are unlocked. Fortunately, these prefs
+        // get reset properly by the first IPC message.
+        Pref pref(nsCString(ContentPrefs::GetContentPref(index)), false, value, MaybePrefValue());
         prefsArray.AppendElement(pref);
       }
       SET_PREF_PHASE(END_INIT_PREFS);
       foundIntPrefs = true;
     } else if (!strcmp(aArgv[idx], "-boolPrefs")) {
       SET_PREF_PHASE(BEGIN_INIT_PREFS);
       char* str = aArgv[idx + 1];
       while (*str) {
         int32_t index = strtol(str, &str, 10);
         MOZ_ASSERT(str[0] == ':');
         str++;
         MaybePrefValue value(PrefValue(!!strtol(str, &str, 10)));
         MOZ_ASSERT(str[0] == '|');
         str++;
-        Pref pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue());
+        Pref pref(nsCString(ContentPrefs::GetContentPref(index)), false, value, MaybePrefValue());
         prefsArray.AppendElement(pref);
       }
       SET_PREF_PHASE(END_INIT_PREFS);
       foundBoolPrefs = true;
     } else if (!strcmp(aArgv[idx], "-stringPrefs")) {
       SET_PREF_PHASE(BEGIN_INIT_PREFS);
       char* str = aArgv[idx + 1];
       while (*str) {
         int32_t index = strtol(str, &str, 10);
         MOZ_ASSERT(str[0] == ':');
         str++;
         int32_t length = strtol(str, &str, 10);
         MOZ_ASSERT(str[0] == ';');
         str++;
         MaybePrefValue value(PrefValue(nsCString(str, length)));
-        Pref pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue());
+        Pref pref(nsCString(ContentPrefs::GetContentPref(index)), false, value, MaybePrefValue());
         prefsArray.AppendElement(pref);
         str += length + 1;
         MOZ_ASSERT(*(str - 1) == '|');
       }
       SET_PREF_PHASE(END_INIT_PREFS);
       foundStringPrefs = true;
     } else if (!strcmp(aArgv[idx], "-schedulerPrefs")) {
       schedulerPrefs = aArgv[idx + 1];
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -153,16 +153,17 @@ union PrefValue {
 
 union MaybePrefValue {
   PrefValue;
   null_t;
 };
 
 struct Pref {
   nsCString name;
+  bool isLocked;
   MaybePrefValue defaultValue;
   MaybePrefValue userValue;
 };
 
 struct DataStorageItem {
   nsCString key;
   nsCString value;
   DataStorageType type;
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -419,16 +419,18 @@ public:
     aResult = stringVal;
     return NS_OK;
   }
 
   void ToDomPref(dom::Pref* aDomPref)
   {
     aDomPref->name() = mName;
 
+    aDomPref->isLocked() = mIsLocked;
+
     if (mHasDefaultValue) {
       aDomPref->defaultValue() = dom::PrefValue();
       mDefaultValue.ToDomPrefValue(Type(),
                                    &aDomPref->defaultValue().get_PrefValue());
     } else {
       aDomPref->defaultValue() = null_t();
     }
 
@@ -445,16 +447,18 @@ public:
                (aDomPref->defaultValue().get_PrefValue().type() ==
                 aDomPref->userValue().get_PrefValue().type()));
   }
 
   void FromDomPref(const dom::Pref& aDomPref, bool* aValueChanged)
   {
     MOZ_ASSERT(strcmp(mName, aDomPref.name().get()) == 0);
 
+    mIsLocked = aDomPref.isLocked();
+
     const dom::MaybePrefValue& defaultValue = aDomPref.defaultValue();
     bool defaultValueChanged = false;
     if (defaultValue.type() == dom::MaybePrefValue::TPrefValue) {
       PrefValue value;
       PrefType type = value.FromDomPrefValue(defaultValue.get_PrefValue());
       if (!ValueMatches(PrefValueKind::Default, type, value)) {
         // Type() is PrefType::None if it's a newly added pref. This is ok.
         mDefaultValue.Replace(Type(), type, value);
--- a/modules/libpref/test/unit_ipc/test_initial_prefs.js
+++ b/modules/libpref/test/unit_ipc/test_initial_prefs.js
@@ -8,11 +8,11 @@ function isParentProcess() {
 
 function run_test() {
   if (isParentProcess() == false) {
       var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
       pb.setBoolPref("Test.IPC.bool", true);
       pb.setIntPref("Test.IPC.int", 23);
       pb.setCharPref("Test.IPC.char", "hey");
 
-      run_test_in_child("test_existing_prefs.JS");
+      run_test_in_child("test_existing_prefs.js");
   }
-}
\ No newline at end of file
+}
new file mode 100644
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/test_locked_prefs.js
@@ -0,0 +1,40 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Locked status should be communicated to children.
+
+var Ci = Components.interfaces;
+var Cc = Components.classes;
+
+function isParentProcess() {
+    let appInfo = Cc["@mozilla.org/xre/app-info;1"];
+    return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
+}
+
+function run_test() {
+  let pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+
+  let bprefname = "Test.IPC.locked.bool";
+  let iprefname = "Test.IPC.locked.int";
+  let sprefname = "Test.IPC.locked.string";
+
+  let isParent = isParentProcess();
+  if (isParent) {
+    pb.setBoolPref(bprefname, true);
+    pb.lockPref(bprefname);
+
+    pb.setIntPref(iprefname, true);
+    pb.lockPref(iprefname);
+
+    pb.setStringPref(sprefname, true);
+    pb.lockPref(sprefname);
+    pb.unlockPref(sprefname);
+
+    run_test_in_child("test_locked_prefs.js");
+  }
+
+  ok(pb.prefIsLocked(bprefname), bprefname + " should be locked in the child");
+  ok(pb.prefIsLocked(iprefname), iprefname + " should be locked in the child");
+  ok(!pb.prefIsLocked(sprefname), sprefname + " should be unlocked in the child");
+}
--- a/modules/libpref/test/unit_ipc/test_observed_prefs.js
+++ b/modules/libpref/test/unit_ipc/test_observed_prefs.js
@@ -8,9 +8,9 @@ function isParentProcess() {
 
 function run_test() {
   if (isParentProcess() == false) {
       var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
       do_check_eq(pb.getBoolPref("Test.IPC.bool.new"), true);
       do_check_eq(pb.getIntPref("Test.IPC.int.new"), 23);
       do_check_eq(pb.getCharPref("Test.IPC.char.new"), "hey");
   }
-}
\ No newline at end of file
+}
--- a/modules/libpref/test/unit_ipc/test_update_prefs.js
+++ b/modules/libpref/test/unit_ipc/test_update_prefs.js
@@ -30,9 +30,9 @@ function testPrefClear() {
 'var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);\n'+
 'pb.prefHasUserValue("Test.IPC.bool.new");\n',
     checkWasCleared);
 }
 
 function checkWasCleared(existsStr) {
     do_check_eq(existsStr, "false");
     do_test_finished();
-}
\ No newline at end of file
+}
--- a/modules/libpref/test/unit_ipc/xpcshell.ini
+++ b/modules/libpref/test/unit_ipc/xpcshell.ini
@@ -1,10 +1,11 @@
 [DEFAULT]
 head = 
 skip-if = toolkit == 'android'
 
 [test_existing_prefs.js]
 [test_initial_prefs.js]
 [test_large_pref.js]
+[test_locked_prefs.js]
 [test_observed_prefs.js]
 [test_update_prefs.js]
 [test_user_default_prefs.js]