Bug 1752332: Add a sanitized property to prefs r=KrisWright

Differential Revision: https://phabricator.services.mozilla.com/D141408
This commit is contained in:
Tom Ritter 2022-04-21 13:22:46 +00:00
Родитель 1ac5da6a36
Коммит bb04bf6564
12 изменённых файлов: 116 добавлений и 29 удалений

Просмотреть файл

@ -3637,7 +3637,8 @@ ContentParent::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
Pref pref(strData, /* isLocked */ false, Nothing(), Nothing());
Pref pref(strData, /* isLocked */ false, /* isSanitized */ false, Nothing(),
Nothing());
Preferences::GetPreference(&pref);
if (IsInitialized()) {
MOZ_ASSERT(mQueuedPrefs.IsEmpty());

Просмотреть файл

@ -23,6 +23,7 @@ union PrefValue {
struct Pref {
nsCString name;
bool isLocked;
bool isSanitized;
PrefValue? defaultValue;
PrefValue? userValue;
};

Просмотреть файл

@ -101,7 +101,8 @@ void RDDProcessManager::OnPreferenceChange(const char16_t* aData) {
return;
}
mozilla::dom::Pref pref(strData, /* isLocked */ false, Nothing(), Nothing());
mozilla::dom::Pref pref(strData, /* isLocked */ false,
/* isSanitized */ false, Nothing(), Nothing());
Preferences::GetPreference(&pref);
if (!!mRDDChild) {
MOZ_ASSERT(mQueuedPrefs.IsEmpty());

Просмотреть файл

@ -168,7 +168,8 @@ void GPUProcessManager::OnPreferenceChange(const char16_t* aData) {
return;
}
mozilla::dom::Pref pref(strData, /* isLocked */ false, Nothing(), Nothing());
mozilla::dom::Pref pref(strData, /* isLocked */ false,
/* isSanitized */ false, Nothing(), Nothing());
Preferences::GetPreference(&pref);
if (!!mGPUChild) {
MOZ_ASSERT(mQueuedPrefs.IsEmpty());

Просмотреть файл

@ -221,7 +221,8 @@ void VRProcessManager::OnPreferenceChange(const char16_t* aData) {
return;
}
mozilla::dom::Pref pref(strData, /* isLocked */ false, Nothing(), Nothing());
mozilla::dom::Pref pref(strData, /* isLocked */ false,
/* isSanitized */ false, Nothing(), Nothing());
Preferences::GetPreference(&pref);
if (!!mVRChild) {
MOZ_ASSERT(mQueuedPrefs.IsEmpty());

Просмотреть файл

@ -99,7 +99,8 @@ void UtilityProcessManager::OnPreferenceChange(const char16_t* aData) {
return;
}
mozilla::dom::Pref pref(strData, /* isLocked */ false, Nothing(), Nothing());
mozilla::dom::Pref pref(strData, /* isLocked */ false,
/* isSanitized */ false, Nothing(), Nothing());
Preferences::GetPreference(&pref);
for (auto& p : mProcesses) {

Просмотреть файл

@ -445,6 +445,7 @@ class Pref {
mType(static_cast<uint32_t>(PrefType::None)),
mIsSticky(false),
mIsLocked(false),
mIsSanitized(false),
mHasDefaultValue(false),
mHasUserValue(false),
mIsSkippedByIteration(false),
@ -482,6 +483,8 @@ class Pref {
bool IsSticky() const { return mIsSticky; }
bool IsSanitized() const { return mIsSanitized; }
bool HasDefaultValue() const { return mHasDefaultValue; }
bool HasUserValue() const { return mHasUserValue; }
@ -489,7 +492,7 @@ class Pref {
void AddToMap(SharedPrefMapBuilder& aMap) {
aMap.Add(NameString(),
{HasDefaultValue(), HasUserValue(), IsSticky(), IsLocked(),
IsSkippedByIteration()},
/* isSanitized */ false, IsSkippedByIteration()},
HasDefaultValue() ? mDefaultValue.Get<T>() : T(),
HasUserValue() ? mUserValue.Get<T>() : T());
}
@ -548,6 +551,8 @@ class Pref {
aDomPref->isLocked() = mIsLocked;
aDomPref->isSanitized() = mIsSanitized;
if (mHasDefaultValue) {
aDomPref->defaultValue() = Some(dom::PrefValue());
mDefaultValue.ToDomPrefValue(Type(), &aDomPref->defaultValue().ref());
@ -555,7 +560,7 @@ class Pref {
aDomPref->defaultValue() = Nothing();
}
if (mHasUserValue) {
if (mHasUserValue && !mIsSanitized) {
aDomPref->userValue() = Some(dom::PrefValue());
mUserValue.ToDomPrefValue(Type(), &aDomPref->userValue().ref());
} else {
@ -563,7 +568,7 @@ class Pref {
}
MOZ_ASSERT(aDomPref->defaultValue().isNothing() ||
aDomPref->userValue().isNothing() ||
aDomPref->userValue().isNothing() || mIsSanitized ||
(aDomPref->defaultValue().ref().type() ==
aDomPref->userValue().ref().type()));
}
@ -573,6 +578,7 @@ class Pref {
MOZ_ASSERT(mName == aDomPref.name());
mIsLocked = aDomPref.isLocked();
mIsSanitized = aDomPref.isSanitized();
const Maybe<dom::PrefValue>& defaultValue = aDomPref.defaultValue();
bool defaultValueChanged = false;
@ -718,9 +724,11 @@ class Pref {
//
// The grammar for the serialized prefs has the following form.
//
// <pref> = <type> <locked> ':' <name> ':' <value>? ':' <value>? '\n'
// <pref> = <type> <locked> <sanitized> ':' <name> ':' <value>? ':'
// <value>? '\n'
// <type> = 'B' | 'I' | 'S'
// <locked> = 'L' | '-'
// <sanitized> = 'S' | '-'
// <name> = <string-value>
// <value> = <bool-value> | <int-value> | <string-value>
// <bool-value> = 'T' | 'F'
@ -747,21 +755,26 @@ class Pref {
// print it and inspect it easily in a debugger.
//
// Examples of unlocked boolean prefs:
// - "B-:8/my.bool1:F:T\n"
// - "B-:8/my.bool2:F:\n"
// - "B-:8/my.bool3::T\n"
// - "B--:8/my.bool1:F:T\n"
// - "B--:8/my.bool2:F:\n"
// - "B--:8/my.bool3::T\n"
//
// Examples of sanitized, unlocked boolean prefs:
// - "B-S:8/my.bool1:F:T\n"
// - "B-S:8/my.bool2:F:\n"
// - "B-S:8/my.bool3::T\n"
//
// Examples of locked integer prefs:
// - "IL:7/my.int1:0:1\n"
// - "IL:7/my.int2:123:\n"
// - "IL:7/my.int3::-99\n"
// - "IL-:7/my.int1:0:1\n"
// - "IL-:7/my.int2:123:\n"
// - "IL-:7/my.int3::-99\n"
//
// Examples of unlocked string prefs:
// - "S-:10/my.string1:3/abc:4/wxyz\n"
// - "S-:10/my.string2:5/1.234:\n"
// - "S-:10/my.string3::7/string!\n"
// - "S--:10/my.string1:3/abc:4/wxyz\n"
// - "S--:10/my.string2:5/1.234:\n"
// - "S--:10/my.string3::7/string!\n"
void SerializeAndAppend(nsCString& aStr) {
void SerializeAndAppend(nsCString& aStr, bool aSanitizeUserValue) {
switch (Type()) {
case PrefType::Bool:
aStr.Append('B');
@ -782,6 +795,7 @@ class Pref {
}
aStr.Append(mIsLocked ? 'L' : '-');
aStr.Append(aSanitizeUserValue ? 'S' : '-');
aStr.Append(':');
SerializeAndAppendString(mName, aStr);
@ -792,7 +806,7 @@ class Pref {
}
aStr.Append(':');
if (mHasUserValue) {
if (mHasUserValue && !aSanitizeUserValue) {
mUserValue.SerializeAndAppend(Type(), aStr);
}
aStr.Append('\n');
@ -827,6 +841,18 @@ class Pref {
}
p++; // move past the isLocked char
// Sanitize?
bool isSanitized;
if (*p == 'S') {
isSanitized = true;
} else if (*p == '-') {
isSanitized = false;
} else {
NS_ERROR("bad pref sanitized status");
isSanitized = false;
}
p++; // move past the isSanitized char
MOZ_ASSERT(*p == ':');
p++; // move past the ':'
@ -855,7 +881,8 @@ class Pref {
MOZ_ASSERT(*p == '\n');
p++; // move past the '\n' following the user value
*aDomPref = dom::Pref(name, isLocked, maybeDefaultValue, maybeUserValue);
*aDomPref = dom::Pref(name, isLocked, isSanitized, maybeDefaultValue,
maybeUserValue);
return p;
}
@ -879,6 +906,7 @@ class Pref {
uint32_t mType : 2;
uint32_t mIsSticky : 1;
uint32_t mIsLocked : 1;
uint32_t mIsSanitized : 1;
uint32_t mHasDefaultValue : 1;
uint32_t mHasUserValue : 1;
uint32_t mIsSkippedByIteration : 1;
@ -930,6 +958,7 @@ class MOZ_STACK_CLASS PrefWrapper : public PrefWrapperBase {
}
FORWARD(bool, IsLocked)
FORWARD(bool, IsSanitized)
FORWARD(bool, IsSticky)
FORWARD(bool, HasDefaultValue)
FORWARD(bool, HasUserValue)
@ -1084,6 +1113,7 @@ void Pref::FromWrapper(PrefWrapper& aWrapper) {
mType = uint32_t(pref.Type());
mIsLocked = pref.IsLocked();
mIsSanitized = pref.IsSanitized();
mIsSticky = pref.IsSticky();
mHasDefaultValue = pref.HasDefaultValue();
@ -2521,6 +2551,16 @@ nsPrefBranch::PrefIsLocked(const char* aPrefName, bool* aRetVal) {
return NS_OK;
}
NS_IMETHODIMP
nsPrefBranch::PrefIsSanitized(const char* aPrefName, bool* aRetVal) {
NS_ENSURE_ARG_POINTER(aRetVal);
NS_ENSURE_ARG(aPrefName);
const PrefName& pref = GetPrefName(aPrefName);
*aRetVal = Preferences::IsSanitized(pref.get());
return NS_OK;
}
NS_IMETHODIMP
nsPrefBranch::UnlockPref(const char* aPrefName) {
NS_ENSURE_ARG(aPrefName);
@ -3555,9 +3595,8 @@ void Preferences::SerializePreferences(
for (auto iter = HashTable()->iter(); !iter.done(); iter.next()) {
Pref* pref = iter.get().get();
if (!pref->IsTypeNone() && pref->HasAdvisablySizedValues() &&
aShouldSerializeFn(pref->Name())) {
pref->SerializeAndAppend(aStr);
if (!pref->IsTypeNone() && pref->HasAdvisablySizedValues()) {
pref->SerializeAndAppend(aStr, !aShouldSerializeFn(pref->Name()));
}
}
@ -4975,6 +5014,14 @@ bool Preferences::IsLocked(const char* aPrefName) {
return pref.isSome() && pref->IsLocked();
}
/* static */
bool Preferences::IsSanitized(const char* aPrefName) {
NS_ENSURE_TRUE(InitStaticMembers(), false);
Maybe<PrefWrapper> pref = pref_Lookup(aPrefName);
return pref.isSome() && pref->IsSanitized();
}
/* static */
nsresult Preferences::ClearUser(const char* aPrefName) {
ENSURE_PARENT_PROCESS("ClearUser", aPrefName);

Просмотреть файл

@ -216,6 +216,7 @@ class Preferences final : public nsIPrefService,
static nsresult Lock(const char* aPrefName);
static nsresult Unlock(const char* aPrefName);
static bool IsLocked(const char* aPrefName);
static bool IsSanitized(const char* aPrefName);
// Clears user set pref. Fails if run outside the parent process.
static nsresult ClearUser(const char* aPrefName);

Просмотреть файл

@ -81,6 +81,7 @@ void SharedPrefMapBuilder::Add(const nsCString& aKey, const Flags& aFlags,
aFlags.mHasUserValue,
aFlags.mIsSticky,
aFlags.mIsLocked,
aFlags.mIsSanitized,
aFlags.mIsSkippedByIteration,
});
}
@ -103,6 +104,7 @@ void SharedPrefMapBuilder::Add(const nsCString& aKey, const Flags& aFlags,
aFlags.mHasUserValue,
aFlags.mIsSticky,
aFlags.mIsLocked,
aFlags.mIsSanitized,
aFlags.mIsSkippedByIteration,
});
}
@ -128,6 +130,7 @@ void SharedPrefMapBuilder::Add(const nsCString& aKey, const Flags& aFlags,
aFlags.mHasUserValue,
aFlags.mIsSticky,
aFlags.mIsLocked,
aFlags.mIsSanitized,
aFlags.mIsSkippedByIteration,
});
}
@ -190,10 +193,15 @@ Result<Ok, nsresult> SharedPrefMapBuilder::Finalize(loader::AutoMemMap& aMap) {
auto* entryPtr = reinterpret_cast<SharedPrefMap::Entry*>(&headerPtr[1]);
for (auto* entry : entries) {
*entryPtr = {
entry->mKey, GetValue(*entry),
entry->mType, entry->mHasDefaultValue,
entry->mHasUserValue, entry->mIsSticky,
entry->mIsLocked, entry->mIsSkippedByIteration,
entry->mKey,
GetValue(*entry),
entry->mType,
entry->mHasDefaultValue,
entry->mHasUserValue,
entry->mIsSticky,
entry->mIsLocked,
entry->mIsSanitized,
entry->mIsSkippedByIteration,
};
entryPtr++;
}

Просмотреть файл

@ -307,6 +307,9 @@ class SharedPrefMap {
uint8_t mIsSticky : 1;
// True if the preference is locked, as defined by the preference service.
uint8_t mIsLocked : 1;
// True if the preference is sanitized, as defined by the preference
// service.
uint8_t mIsSanitized : 1;
// True if the preference should be skipped while iterating over the
// SharedPrefMap. This is used to internally store Once StaticPrefs.
// This property is not visible to users the way sticky and locked are.
@ -339,6 +342,7 @@ class SharedPrefMap {
bool HasDefaultValue() const { return mEntry->mHasDefaultValue; }
bool HasUserValue() const { return mEntry->mHasUserValue; }
bool IsLocked() const { return mEntry->mIsLocked; }
bool IsSanitized() const { return mEntry->mIsSanitized; }
bool IsSticky() const { return mEntry->mIsSticky; }
bool IsSkippedByIteration() const { return mEntry->mIsSkippedByIteration; }
@ -569,6 +573,7 @@ class MOZ_RAII SharedPrefMapBuilder {
uint8_t mHasUserValue : 1;
uint8_t mIsSticky : 1;
uint8_t mIsLocked : 1;
uint8_t mIsSanitized : 1;
uint8_t mIsSkippedByIteration : 1;
};
@ -807,6 +812,7 @@ class MOZ_RAII SharedPrefMapBuilder {
uint8_t mHasUserValue : 1;
uint8_t mIsSticky : 1;
uint8_t mIsLocked : 1;
uint8_t mIsSanitized : 1;
uint8_t mIsSkippedByIteration : 1;
};

Просмотреть файл

@ -315,6 +315,24 @@ interface nsIPrefBranch : nsISupports
*/
boolean prefIsLocked(in string aPrefName);
/**
* Called to check if a specific preference has been sanitized. If a
* preference is sanitized, any user value the preference may have will not
* be present in a sub-process. A preference is never sanitized in the
* parent process; it is only marked as sanitized when it is converted
* to a dom::Pref for serialization to a child process.
*
* @param aPrefName The preference to be tested.
*
* @note
* This method can be called on either a default or user branch but it
* makes no difference.
*
* @return boolean true The preference is sanitized.
* false The preference is not sanitized.
*/
boolean prefIsSanitized(in string aPrefName);
/**
* Called to unlock a specific preference. Unlocking a previously locked
* preference allows the preference service to once again return the user set

Просмотреть файл

@ -646,7 +646,8 @@ void nsIOService::NotifySocketProcessPrefsChanged(const char* aName) {
return;
}
dom::Pref pref(nsCString(aName), /* isLocked */ false, Nothing(), Nothing());
dom::Pref pref(nsCString(aName), /* isLocked */ false,
/* isSanitized */ false, Nothing(), Nothing());
Preferences::GetPreference(&pref);
auto sendPrefUpdate = [pref]() {
Unused << gIOService->mSocketProcess->GetActor()->SendPreferenceUpdate(