summaryrefslogtreecommitdiffstats
path: root/modules/libpref/test/unit/test_stickyprefs.js
blob: d344d208abbdb96987f90779ccfebc18d1746a64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/licenses/publicdomain/  */

const ps = Services.prefs;

// It is necessary to manually disable `xpc::IsInAutomation` since
// `resetPrefs` will flip the preference to re-enable `once`-synced
// preference change assertions, and also change the value of those
// preferences.
Services.prefs.setBoolPref(
  "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer",
  false
);

// A little helper to reset the service and load one pref file.
function resetAndLoadDefaults() {
  ps.resetPrefs();
  ps.readDefaultPrefsFromFile(do_get_file("data/testPrefSticky.js"));
}

// A little helper to reset the service and load two pref files.
function resetAndLoadAll() {
  ps.resetPrefs();
  ps.readDefaultPrefsFromFile(do_get_file("data/testPrefSticky.js"));
  ps.readUserPrefsFromFile(do_get_file("data/testPrefStickyUser.js"));
}

// A little helper that saves the current state to a file in the profile
// dir, then resets the service and re-reads the file it just saved.
// Used to test what gets actually written - things the pref service decided
// not to write don't exist at all after this call.
function saveAndReload() {
  let file = do_get_profile();
  file.append("prefs.js");
  ps.savePrefFile(file);

  // Now reset the pref service and re-read what we saved.
  ps.resetPrefs();

  // Hack alert: on Windows nsLocalFile caches the size of savePrefFile from
  // the .create() call above as 0. We call .exists() to reset the cache.
  file.exists();

  ps.readUserPrefsFromFile(file);
}

// A sticky pref should not be written if the value is unchanged.
add_test(function notWrittenWhenUnchanged() {
  resetAndLoadDefaults();
  Assert.strictEqual(ps.getBoolPref("testPref.unsticky.bool"), true);
  Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false);

  // write prefs - but we haven't changed the sticky one, so it shouldn't be written.
  saveAndReload();
  // sticky should not have been written to the new file.
  try {
    ps.getBoolPref("testPref.sticky.bool");
    Assert.ok(false, "expected failure reading this pref");
  } catch (ex) {
    Assert.ok(ex, "exception reading regular pref");
  }
  run_next_test();
});

// Loading a sticky `pref` then a `user_pref` for the same pref means it should
// always be written.
add_test(function writtenOnceLoadedWithoutChange() {
  // Load the same pref file *as well as* a pref file that has a user_pref for
  // our sticky with the default value. It should be re-written without us
  // touching it.
  resetAndLoadAll();
  // reset and re-read what we just wrote - it should be written.
  saveAndReload();
  Assert.strictEqual(
    ps.getBoolPref("testPref.sticky.bool"),
    false,
    "user_pref was written with default value"
  );
  run_next_test();
});

// If a sticky pref is explicicitly changed, even to the default, it is written.
add_test(function writtenOnceLoadedWithChangeNonDefault() {
  // Load the same pref file *as well as* a pref file that has a user_pref for
  // our sticky - then change the pref. It should be written.
  resetAndLoadAll();
  // Set a new val and check we wrote it.
  ps.setBoolPref("testPref.sticky.bool", false);
  saveAndReload();
  Assert.strictEqual(
    ps.getBoolPref("testPref.sticky.bool"),
    false,
    "user_pref was written with custom value"
  );
  run_next_test();
});

// If a sticky pref is changed to the non-default value, it is written.
add_test(function writtenOnceLoadedWithChangeNonDefault() {
  // Load the same pref file *as well as* a pref file that has a user_pref for
  // our sticky - then change the pref. It should be written.
  resetAndLoadAll();
  // Set a new val and check we wrote it.
  ps.setBoolPref("testPref.sticky.bool", true);
  saveAndReload();
  Assert.strictEqual(
    ps.getBoolPref("testPref.sticky.bool"),
    true,
    "user_pref was written with custom value"
  );
  run_next_test();
});

// Test that prefHasUserValue always returns true whenever there is a sticky
// value, even when that value matches the default. This is mainly for
// about:config semantics - prefs with a sticky value always remain bold and
// always offer "reset" (which fully resets and drops the sticky value as if
// the pref had never changed.)
add_test(function hasUserValue() {
  // sticky pref without user value.
  resetAndLoadDefaults();
  Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false);
  Assert.ok(
    !ps.prefHasUserValue("testPref.sticky.bool"),
    "should not initially reflect a user value"
  );

  ps.setBoolPref("testPref.sticky.bool", false);
  Assert.ok(
    ps.prefHasUserValue("testPref.sticky.bool"),
    "should reflect a user value after set to default"
  );

  ps.setBoolPref("testPref.sticky.bool", true);
  Assert.ok(
    ps.prefHasUserValue("testPref.sticky.bool"),
    "should reflect a user value after change to non-default"
  );

  ps.clearUserPref("testPref.sticky.bool");
  Assert.ok(
    !ps.prefHasUserValue("testPref.sticky.bool"),
    "should reset to no user value"
  );
  ps.setBoolPref("testPref.sticky.bool", false, "expected default");

  // And make sure the pref immediately reflects a user value after load.
  resetAndLoadAll();
  Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false);
  Assert.ok(
    ps.prefHasUserValue("testPref.sticky.bool"),
    "should have a user value when loaded value is the default"
  );
  run_next_test();
});

// Test that clearUserPref removes the "sticky" value.
add_test(function clearUserPref() {
  // load things such that we have a sticky value which is the same as the
  // default.
  resetAndLoadAll();
  ps.clearUserPref("testPref.sticky.bool");

  // Once we save prefs the sticky pref should no longer be written.
  saveAndReload();
  try {
    ps.getBoolPref("testPref.sticky.bool");
    Assert.ok(false, "expected failure reading this pref");
  } catch (ex) {
    Assert.ok(ex, "pref doesn't have a sticky value");
  }
  run_next_test();
});

// Test that a pref observer gets a notification fired when a sticky pref
// has it's value changed to the same value as the default. The reason for
// this behaviour is that later we might have other code that cares about a
// pref being sticky (IOW, we notify due to the "state" of the pref changing
// even if the value has not)
add_test(function observerFires() {
  // load things so there's no sticky value.
  resetAndLoadDefaults();

  function observe(subject, topic, data) {
    Assert.equal(data, "testPref.sticky.bool");
    ps.removeObserver("testPref.sticky.bool", observe);
    run_next_test();
  }
  ps.addObserver("testPref.sticky.bool", observe);

  ps.setBoolPref(
    "testPref.sticky.bool",
    ps.getBoolPref("testPref.sticky.bool")
  );
  // and the observer will fire triggering the next text.
});