Bug 1642727 - Remove the VarCache machinery r=njn

This commit removes Varcache entirely, putting an end to our quest to get rid of VarCache.

Differential Revision: https://phabricator.services.mozilla.com/D79538
This commit is contained in:
Kristen Wright 2020-09-08 17:12:01 +00:00
parent f9e3a895af
commit 30a9faf35b
11 changed files with 15 additions and 380 deletions

View File

@ -465,11 +465,9 @@ XPCOMService_GetObserverService
?AddRef@AccessibleCaretEventHub@mozilla@@UAGKXZ
??$AppendElement@AAV?$nsTAutoStringN@D$0EA@@@UnsTArrayInfallibleAllocator@@@?$nsTArray_Impl@V?$nsTString@D@@UnsTArrayInfallibleAllocator@@@@IAEPAV?$nsTString@D@@AAV?$nsTAutoStringN@D$0EA@@@@Z
?GetPreference@Preferences@mozilla@@SAXPAVPref@dom@2@@Z
??$AddAtomicBoolVarCache@$0A@@Preferences@mozilla@@SAXPAV?$Atomic@_N$0A@X@1@ABV?$nsTSubstring@D@@_N@Z
??$RegisterCallbackImpl@$$CBV?$nsTSubstring@D@@@Preferences@mozilla@@CA?AW4nsresult@@P6AXPBDPAX@ZABV?$nsTSubstring@D@@1W4MatchKind@01@_N@Z
?GetComplex@Preferences@mozilla@@SA?AW4nsresult@@PBDABUnsID@@PAPAXW4PrefValueKind@2@@Z
?GetBool@Preferences@mozilla@@SA?AW4nsresult@@PBDPA_NW4PrefValueKind@2@@Z
??$AddAtomicBoolVarCache@$01@Preferences@mozilla@@SAXPAV?$Atomic@_N$01X@1@ABV?$nsTSubstring@D@@_N@Z
?SetPreference@Preferences@mozilla@@SAXABVPref@dom@2@@Z
?Allocate@ArenaChunk@?$ArenaAllocator@$0BAAA@$00@mozilla@@QAEPAXI@Z
?SavePrefFileBlocking@Preferences@mozilla@@QAE?AW4nsresult@@XZ
@ -6465,7 +6463,6 @@ Gecko_TakeFromCString
?ComputeCrossOriginOpenerPolicy@HttpBaseChannel@net@mozilla@@UAG?AW4nsresult@@W4CrossOriginOpenerPolicy@nsILoadInfo@@PAW456@@Z
?OnStartRequest@nsDocumentOpenInfo@@UAG?AW4nsresult@@PAVnsIRequest@@@Z
?GetResponseStatus@HttpBaseChannel@net@mozilla@@UAG?AW4nsresult@@PAI@Z
?AddBoolVarCache@Preferences@mozilla@@SAXPA_NABV?$nsTSubstring@D@@_N@Z
?GetResponseHeader@HttpBaseChannel@net@mozilla@@UAG?AW4nsresult@@ABV?$nsTSubstring@D@@AAV5@@Z
?GetHeader@nsHttpRequestHead@net@mozilla@@QAE?AW4nsresult@@UnsHttpAtom@23@AAV?$nsTSubstring@D@@@Z
?GetStatus@HttpBaseChannel@net@mozilla@@UAG?AW4nsresult@@PAW44@@Z

View File

@ -472,11 +472,9 @@ XPCOMService_GetObserverService
?AddRef@AccessibleCaretEventHub@mozilla@@UEAAKXZ
??$AppendElement@AEAV?$nsTAutoStringN@D$0EA@@@UnsTArrayInfallibleAllocator@@@?$nsTArray_Impl@V?$nsTString@D@@UnsTArrayInfallibleAllocator@@@@IEAAPEAV?$nsTString@D@@AEAV?$nsTAutoStringN@D$0EA@@@@Z
?GetIsExtraState@xpcAccStateChangeEvent@@UEAA?AW4nsresult@@PEA_N@Z
??$AddAtomicBoolVarCache@$0A@@Preferences@mozilla@@SAXPEAV?$Atomic@_N$0A@X@1@AEBV?$nsTSubstring@D@@_N@Z
??$RegisterCallbackImpl@$$CBV?$nsTSubstring@D@@@Preferences@mozilla@@CA?AW4nsresult@@P6AXPEBDPEAX@ZAEBV?$nsTSubstring@D@@1W4MatchKind@01@_N@Z
??$GetPrefValue@AEAPEAM@Internals@mozilla@@SA?AW4nsresult@@PEBDAEAPEAMW4PrefValueKind@1@@Z
?GetBool@Preferences@mozilla@@SA?AW4nsresult@@PEBDPEA_NW4PrefValueKind@2@@Z
??$AddAtomicBoolVarCache@$01@Preferences@mozilla@@SAXPEAV?$Atomic@_N$01X@1@AEBV?$nsTSubstring@D@@_N@Z
?SetPreference@Preferences@mozilla@@SAXAEBVPref@dom@2@@Z
?GetComplex@Preferences@mozilla@@SA?AW4nsresult@@PEBDAEBUnsID@@PEAPEAXW4PrefValueKind@2@@Z
?Allocate@ArenaChunk@?$ArenaAllocator@$0BAAA@$00@mozilla@@QEAAPEAX_K@Z
@ -6419,7 +6417,6 @@ Gecko_TakeFromCString
?ComputeCrossOriginOpenerPolicy@HttpBaseChannel@net@mozilla@@UEAA?AW4nsresult@@W4CrossOriginOpenerPolicy@nsILoadInfo@@PEAW456@@Z
?OnStartRequest@nsDocumentOpenInfo@@UEAA?AW4nsresult@@PEAVnsIRequest@@@Z
?GetResponseStatus@HttpBaseChannel@net@mozilla@@UEAA?AW4nsresult@@PEAI@Z
?AddBoolVarCache@Preferences@mozilla@@SAXPEA_NAEBV?$nsTSubstring@D@@_N@Z
?GetResponseHeader@HttpBaseChannel@net@mozilla@@UEAA?AW4nsresult@@AEBV?$nsTSubstring@D@@AEAV5@@Z
?GetHeader@nsHttpResponseHead@net@mozilla@@QEAA?AW4nsresult@@UnsHttpAtom@23@AEAV?$nsTSubstring@D@@@Z
?GetStatus@HttpBaseChannel@net@mozilla@@UEAA?AW4nsresult@@PEAW44@@Z

View File

@ -53,7 +53,7 @@ nsXULTooltipListener::nsXULTooltipListener()
mLastTreeRow(-1)
#endif
{
// FIXME(emilio): This can be faster, this should use BoolVarCache.
// FIXME(emilio): This can be faster, this should use static prefs.
//
// register the callback so we get notified of updates
Preferences::RegisterCallback(ToolbarTipsPrefChanged,

View File

@ -4332,24 +4332,10 @@ struct Internals {
template <typename T>
static void UpdateMirror(const char* aPref, void* aMirror) {
StripAtomic<T> value;
nsresult rv = GetPrefValue(aPref, &value, PrefValueKind::User);
if (NS_SUCCEEDED(rv)) {
*static_cast<T*>(aMirror) = value;
} else {
// GetPrefValue() can fail if the update is caused by the pref being
// deleted. In that case the mirror variable will be untouched, thus
// keeping the value it had prior to the deletion. (Note that this case
// won't happen for a deletion via DeleteBranch() unless bug 343600 is
// fixed, but it will happen for a deletion via ClearUserPref().)
//
// This is a case we want to avoid in general because it's a bit unclear
// what value the mirror variable should take; hence the assertion
// failure. Once all VarCache prefs are removed in favour of static prefs
// (bug 1448219) the plan is to mark static prefs as undeletable and this
// case will become impossible.
NS_WARNING(nsPrintfCString("VarChanged failure: %s\n", aPref).get());
MOZ_ASSERT(false);
}
// We disallow the deletion of mirrored prefs.
// This assertion is the only place where we enforce this.
MOZ_ALWAYS_SUCCEEDS(GetPrefValue(aPref, &value, PrefValueKind::User));
*static_cast<T*>(aMirror) = value;
}
template <typename T>
@ -5074,85 +5060,6 @@ static MOZ_NEVER_INLINE void AddMirror(T* aMirror, const nsACString& aPref,
AddMirrorCallback(aMirror, aPref);
}
/* static */
void Preferences::AddBoolVarCache(bool* aCache, const nsACString& aPref,
bool aDefault) {
AddMirror(aCache, aPref, aDefault);
}
template <MemoryOrdering Order>
/* static */
void Preferences::AddAtomicBoolVarCache(Atomic<bool, Order>* aCache,
const nsACString& aPref,
bool aDefault) {
AddMirror(aCache, aPref, aDefault);
}
/* static */
void Preferences::AddIntVarCache(int32_t* aCache, const nsACString& aPref,
int32_t aDefault) {
AddMirror(aCache, aPref, aDefault);
}
template <MemoryOrdering Order>
/* static */
void Preferences::AddAtomicIntVarCache(Atomic<int32_t, Order>* aCache,
const nsACString& aPref,
int32_t aDefault) {
AddMirror(aCache, aPref, aDefault);
}
/* static */
void Preferences::AddUintVarCache(uint32_t* aCache, const nsACString& aPref,
uint32_t aDefault) {
AddMirror(aCache, aPref, aDefault);
}
template <MemoryOrdering Order>
/* static */
void Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Order>* aCache,
const nsACString& aPref,
uint32_t aDefault) {
AddMirror(aCache, aPref, aDefault);
}
// Since the definition of template functions is not in a header file, we
// need to explicitly specify the instantiations that are required. Currently
// limited orders are needed and therefore implemented.
template void Preferences::AddAtomicBoolVarCache(Atomic<bool, Relaxed>*,
const nsACString&, bool);
template void Preferences::AddAtomicBoolVarCache(Atomic<bool, ReleaseAcquire>*,
const nsACString&, bool);
template void Preferences::AddAtomicBoolVarCache(
Atomic<bool, SequentiallyConsistent>*, const nsACString&, bool);
template void Preferences::AddAtomicIntVarCache(Atomic<int32_t, Relaxed>*,
const nsACString&, int32_t);
template void Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Relaxed>*,
const nsACString&, uint32_t);
template void Preferences::AddAtomicUintVarCache(
Atomic<uint32_t, ReleaseAcquire>*, const nsACString&, uint32_t);
template void Preferences::AddAtomicUintVarCache(
Atomic<uint32_t, SequentiallyConsistent>*, const nsACString&, uint32_t);
/* static */
void Preferences::AddFloatVarCache(float* aCache, const nsACString& aPref,
float aDefault) {
AddMirror(aCache, aPref, aDefault);
}
/* static */
void Preferences::AddAtomicFloatVarCache(std::atomic<float>* aCache,
const nsACString& aPref,
float aDefault) {
AddMirror(aCache, aPref, aDefault);
}
// The InitPref_*() functions below end in a `_<type>` suffix because they are
// used by the PREF macro definition in InitAll() below.

View File

@ -393,84 +393,6 @@ class Preferences final : public nsIPrefService,
PrefixMatch);
}
// Adds the aVariable to cache table. |aVariable| must be a pointer for a
// static variable. The value will be modified when the pref value is changed
// but note that even if you modified it, the value isn't assigned to the
// pref.
static void AddBoolVarCache(bool* aVariable, const nsACString& aPref,
bool aDefault = false);
template <MemoryOrdering Order>
static void AddAtomicBoolVarCache(Atomic<bool, Order>* aVariable,
const nsACString& aPref,
bool aDefault = false);
static void AddIntVarCache(int32_t* aVariable, const nsACString& aPref,
int32_t aDefault = 0);
template <MemoryOrdering Order>
static void AddAtomicIntVarCache(Atomic<int32_t, Order>* aVariable,
const nsACString& aPref,
int32_t aDefault = 0);
static void AddUintVarCache(uint32_t* aVariable, const nsACString& aPref,
uint32_t aDefault = 0);
template <MemoryOrdering Order>
static void AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable,
const nsACString& aPref,
uint32_t aDefault = 0);
static void AddFloatVarCache(float* aVariable, const nsACString& aPref,
float aDefault = 0.0f);
static void AddAtomicFloatVarCache(std::atomic<float>* aVariable,
const nsACString& aPref,
float aDefault = 0.0f);
template <int N>
static void AddBoolVarCache(bool* aVariable, const char (&aPref)[N],
bool aDefault = false) {
return AddBoolVarCache(aVariable, nsLiteralCString(aPref), aDefault);
}
template <MemoryOrdering Order, int N>
static void AddAtomicBoolVarCache(Atomic<bool, Order>* aVariable,
const char (&aPref)[N],
bool aDefault = false) {
return AddAtomicBoolVarCache<Order>(aVariable, nsLiteralCString(aPref),
aDefault);
}
template <int N>
static void AddIntVarCache(int32_t* aVariable, const char (&aPref)[N],
int32_t aDefault = 0) {
return AddIntVarCache(aVariable, nsLiteralCString(aPref), aDefault);
}
template <MemoryOrdering Order, int N>
static void AddAtomicIntVarCache(Atomic<int32_t, Order>* aVariable,
const char (&aPref)[N],
int32_t aDefault = 0) {
return AddAtomicIntVarCache<Order>(aVariable, nsLiteralCString(aPref),
aDefault);
}
template <int N>
static void AddUintVarCache(uint32_t* aVariable, const char (&aPref)[N],
uint32_t aDefault = 0) {
return AddUintVarCache(aVariable, nsLiteralCString(aPref), aDefault);
}
template <MemoryOrdering Order, int N>
static void AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable,
const char (&aPref)[N],
uint32_t aDefault = 0) {
return AddAtomicUintVarCache<Order>(aVariable, nsLiteralCString(aPref),
aDefault);
}
template <int N>
static void AddFloatVarCache(float* aVariable, const char (&aPref)[N],
float aDefault = 0.0f) {
return AddFloatVarCache(aVariable, nsLiteralCString(aPref), aDefault);
}
template <int N>
static void AddAtomicFloatVarCache(std::atomic<float>* aVariable,
const char (&aPref)[N],
float aDefault = 0.0f) {
return AddAtomicFloatVarCache(aVariable, nsLiteralCString(aPref), aDefault);
}
// When a content process is created these methods are used to pass changed
// prefs in bulk from the parent process, via shared memory.
static void SerializePreferences(nsCString& aStr);

View File

@ -2180,7 +2180,7 @@
# Whether we disable triggering mutation events for changes to style
# attribute via CSSOM.
# NOTE: This preference is used in unit tests. If it is removed or its default
# value changes, please update test_sharedMap_var_caches.js accordingly.
# value changes, please update test_sharedMap_static_prefs.js accordingly.
- name: dom.mutation-events.cssom.disabled
type: bool
value: true
@ -3214,7 +3214,7 @@
mirror: always
# NOTE: This preference is used in unit tests. If it is removed or its default
# value changes, please update test_sharedMap_var_caches.js accordingly.
# value changes, please update test_sharedMap_static_prefs.js accordingly.
- name: dom.webcomponents.shadowdom.report_usage
type: bool
value: false

View File

@ -9,8 +9,8 @@
// mobile/android/app/mobile.js.
//
// NOTE: Not all prefs should be defined in this (or any other) data file.
// Static prefs, especially VarCache prefs, are defined in StaticPrefList.yaml.
// Those prefs should *not* appear in this file.
// Static prefs are defined in StaticPrefList.yaml. Those prefs should *not*
// appear in this file.
//
// For the syntax used by this file, consult the comments at the top of
// modules/libpref/parser/src/lib.rs.

View File

@ -1,187 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
// Test that var caches are updated before callbacks.
#include "gtest/gtest.h"
#include "Preferences.h"
namespace mozilla {
template <typename T, typename U>
struct Closure {
U* mLocation;
T mExpected;
bool mCalled;
};
template <typename T, typename U>
void VarChanged(const char* aPrefName, void* aClosure) {
auto closure = static_cast<Closure<T, U>*>(aClosure);
ASSERT_EQ(*closure->mLocation, closure->mExpected);
ASSERT_FALSE(closure->mCalled);
closure->mCalled = true;
}
void SetFunc(const nsCString& aPrefName, bool aValue) {
nsresult rv = Preferences::SetBool(aPrefName.get(), aValue);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}
void SetFunc(const nsCString& aPrefName, int32_t aValue) {
nsresult rv = Preferences::SetInt(aPrefName.get(), aValue);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}
void SetFunc(const nsCString& aPrefName, uint32_t aValue) {
nsresult rv = Preferences::SetUint(aPrefName.get(), aValue);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}
void SetFunc(const nsCString& aPrefName, float aValue) {
nsresult rv = Preferences::SetFloat(aPrefName.get(), aValue);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}
void AddVarCacheFunc(bool* aVar, const nsCString& aPrefName) {
Preferences::AddBoolVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(Atomic<bool, Relaxed>* aVar, const nsCString& aPrefName) {
Preferences::AddAtomicBoolVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(Atomic<bool, ReleaseAcquire>* aVar,
const nsCString& aPrefName) {
Preferences::AddAtomicBoolVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(int32_t* aVar, const nsCString& aPrefName) {
Preferences::AddIntVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(Atomic<int32_t, Relaxed>* aVar,
const nsCString& aPrefName) {
Preferences::AddAtomicIntVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(uint32_t* aVar, const nsCString& aPrefName) {
Preferences::AddUintVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(Atomic<uint32_t, Relaxed>* aVar,
const nsCString& aPrefName) {
Preferences::AddAtomicUintVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(Atomic<uint32_t, ReleaseAcquire>* aVar,
const nsCString& aPrefName) {
Preferences::AddAtomicUintVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(float* aVar, const nsCString& aPrefName) {
Preferences::AddFloatVarCache(aVar, aPrefName);
}
void AddVarCacheFunc(std::atomic<float>* aVar, const nsCString& aPrefName) {
Preferences::AddAtomicFloatVarCache(aVar, aPrefName);
}
template <typename T, typename U = T>
void RunTest(const nsCString& aPrefName1, const nsCString& aPrefName2,
T aValue1, T aValue2) {
static U var1, var2;
static Closure<T, U> closure1, closure2;
nsresult rv;
ASSERT_STRNE(aPrefName1.get(), aPrefName2.get());
ASSERT_NE(aValue1, aValue2);
// Call Add*VarCache first.
SetFunc(aPrefName1, aValue1);
AddVarCacheFunc(&var1, aPrefName1);
ASSERT_EQ(var1, aValue1);
closure1 = {&var1, aValue2};
rv = Preferences::RegisterCallback(VarChanged<T, U>, aPrefName1, &closure1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_FALSE(closure1.mCalled);
SetFunc(aPrefName1, aValue2);
ASSERT_EQ(var1, aValue2);
ASSERT_TRUE(closure1.mCalled);
// Call RegisterCallback first.
SetFunc(aPrefName2, aValue1);
closure2 = {&var2, aValue2};
rv = Preferences::RegisterCallback(VarChanged<T, U>, aPrefName2, &closure2);
ASSERT_TRUE(NS_SUCCEEDED(rv));
AddVarCacheFunc(&var2, aPrefName2);
ASSERT_EQ(var2, aValue1);
ASSERT_FALSE(closure2.mCalled);
SetFunc(aPrefName2, aValue2);
ASSERT_EQ(var2, aValue2);
ASSERT_TRUE(closure2.mCalled);
}
TEST(CallbackAndVarCacheOrder, Bool)
{ RunTest<bool>("test_pref.bool.1"_ns, "test_pref.bool.2"_ns, false, true); }
TEST(CallbackAndVarCacheOrder, AtomicBoolRelaxed)
{
RunTest<bool, Atomic<bool, Relaxed>>(
"test_pref.atomic_bool.1"_ns, "test_pref.atomic_bool.2"_ns, false, true);
}
TEST(CallbackAndVarCacheOrder, AtomicBoolReleaseAcquire)
{
RunTest<bool, Atomic<bool, ReleaseAcquire>>(
"test_pref.atomic_bool.3"_ns, "test_pref.atomic_bool.4"_ns, false, true);
}
TEST(CallbackAndVarCacheOrder, Int)
{ RunTest<int32_t>("test_pref.int.1"_ns, "test_pref.int.2"_ns, -2, 3); }
TEST(CallbackAndVarCacheOrder, AtomicInt)
{
RunTest<int32_t, Atomic<int32_t, Relaxed>>(
"test_pref.atomic_int.1"_ns, "test_pref.atomic_int.2"_ns, -3, 4);
}
TEST(CallbackAndVarCacheOrder, Uint)
{ RunTest<uint32_t>("test_pref.uint.1"_ns, "test_pref.uint.2"_ns, 4u, 5u); }
TEST(CallbackAndVarCacheOrder, AtomicUintRelaxed)
{
RunTest<uint32_t, Atomic<uint32_t, Relaxed>>(
"test_pref.atomic_uint.1"_ns, "test_pref.atomic_uint.2"_ns, 6u, 7u);
}
TEST(CallbackAndVarCacheOrder, AtomicUintReleaseAcquire)
{
RunTest<uint32_t, Atomic<uint32_t, ReleaseAcquire>>(
"test_pref.atomic_uint.3"_ns, "test_pref.atomic_uint.4"_ns, 8u, 9u);
}
TEST(CallbackAndVarCacheOrder, Float)
{
RunTest<float>("test_pref.float.1"_ns, "test_pref.float.2"_ns, -10.0f, 11.0f);
}
TEST(CallbackAndVarCacheOrder, AtomicFloat)
{
RunTest<float, std::atomic<float>>("test_pref.atomic_float.1"_ns,
"test_pref.atomic_float.2"_ns, -12.0f,
13.0f);
}
} // namespace mozilla

View File

@ -12,7 +12,6 @@ LOCAL_INCLUDES += [
UNIFIED_SOURCES = [
'Basics.cpp',
'CallbackAndVarCacheOrder.cpp',
'Parser.cpp',
]

View File

@ -3,15 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Tests that static preference varcaches in the content process
// Tests that static preferences in the content process
// correctly handle values which are different from their
// statically-defined defaults.
//
// Since we can't access varcaches values from JS, this tests relies on
// Since we can't access static preference values from JS, this tests relies on
// assertions in debug builds to detect mismatches. The default and user
// values of two preferences are changed (respectively) before a content
// process is started. Once the content process is launched, the
// preference service asserts that the values stored in all var caches
// preference service asserts that the values stored in all static prefs
// match their current values as known to the preference service. If
// there's a mismatch, the shell will crash, and the test will fail.
//
@ -35,7 +35,7 @@ ExtensionTestUtils.init(this);
const { prefs } = Services;
const defaultPrefs = prefs.getDefaultBranch("");
add_task(async function test_sharedMap_var_caches() {
add_task(async function test_sharedMap_static_prefs() {
equal(
prefs.getBoolPref(PREF1_NAME),
PREF1_VALUE,

View File

@ -1,5 +1,5 @@
[DEFAULT]
head =
head =
skip-if = toolkit == 'android'
[test_existing_prefs.js]
@ -9,6 +9,6 @@ skip-if = toolkit == 'android'
[test_observed_prefs.js]
[test_update_prefs.js]
[test_sharedMap.js]
[test_sharedMap_var_caches.js]
[test_sharedMap_static_prefs.js]
skip-if = !debug # Relies on debug assertions to catch failure cases.
[test_user_default_prefs.js]