|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 function run_test() { |
|
6 //**************************************************************************// |
|
7 // Database Creation, Schema Migration, and Backup |
|
8 |
|
9 // Note: in these tests we use createInstance instead of getService |
|
10 // so we can instantiate the service multiple times and make it run |
|
11 // its database initialization code each time. |
|
12 |
|
13 // Create a new database. |
|
14 { |
|
15 ContentPrefTest.deleteDatabase(); |
|
16 |
|
17 // Get the service and make sure it has a ready database connection. |
|
18 let cps = Cc["@mozilla.org/content-pref/service;1"]. |
|
19 createInstance(Ci.nsIContentPrefService); |
|
20 do_check_true(cps.DBConnection.connectionReady); |
|
21 cps.DBConnection.close(); |
|
22 } |
|
23 |
|
24 // Open an existing database. |
|
25 { |
|
26 let dbFile = ContentPrefTest.deleteDatabase(); |
|
27 |
|
28 let cps = Cc["@mozilla.org/content-pref/service;1"]. |
|
29 createInstance(Ci.nsIContentPrefService); |
|
30 cps.DBConnection.close(); |
|
31 do_check_true(dbFile.exists()); |
|
32 |
|
33 // Get the service and make sure it has a ready database connection. |
|
34 cps = Cc["@mozilla.org/content-pref/service;1"]. |
|
35 createInstance(Ci.nsIContentPrefService); |
|
36 do_check_true(cps.DBConnection.connectionReady); |
|
37 cps.DBConnection.close(); |
|
38 } |
|
39 |
|
40 // Open an empty database. |
|
41 { |
|
42 let dbFile = ContentPrefTest.deleteDatabase(); |
|
43 |
|
44 // Create an empty database. |
|
45 let dbService = Cc["@mozilla.org/storage/service;1"]. |
|
46 getService(Ci.mozIStorageService); |
|
47 let dbConnection = dbService.openDatabase(dbFile); |
|
48 do_check_eq(dbConnection.schemaVersion, 0); |
|
49 dbConnection.close(); |
|
50 do_check_true(dbFile.exists()); |
|
51 |
|
52 // Get the service and make sure it has created the schema. |
|
53 let cps = Cc["@mozilla.org/content-pref/service;1"]. |
|
54 createInstance(Ci.nsIContentPrefService); |
|
55 do_check_neq(cps.DBConnection.schemaVersion, 0); |
|
56 cps.DBConnection.close(); |
|
57 } |
|
58 |
|
59 // Open a corrupted database. |
|
60 { |
|
61 let dbFile = ContentPrefTest.deleteDatabase(); |
|
62 let backupDBFile = ContentPrefTest.deleteBackupDatabase(); |
|
63 |
|
64 // Create a corrupted database. |
|
65 let foStream = Cc["@mozilla.org/network/file-output-stream;1"]. |
|
66 createInstance(Ci.nsIFileOutputStream); |
|
67 foStream.init(dbFile, 0x02 | 0x08 | 0x20, 0666, 0); |
|
68 let garbageData = "garbage that makes SQLite think the file is corrupted"; |
|
69 foStream.write(garbageData, garbageData.length); |
|
70 foStream.close(); |
|
71 |
|
72 // Get the service and make sure it backs up and recreates the database. |
|
73 let cps = Cc["@mozilla.org/content-pref/service;1"]. |
|
74 createInstance(Ci.nsIContentPrefService); |
|
75 do_check_true(backupDBFile.exists()); |
|
76 do_check_true(cps.DBConnection.connectionReady); |
|
77 |
|
78 cps.DBConnection.close(); |
|
79 } |
|
80 |
|
81 // Open a database with a corrupted schema. |
|
82 { |
|
83 let dbFile = ContentPrefTest.deleteDatabase(); |
|
84 let backupDBFile = ContentPrefTest.deleteBackupDatabase(); |
|
85 |
|
86 // Create an empty database and set the schema version to a number |
|
87 // that will trigger a schema migration that will fail. |
|
88 let dbService = Cc["@mozilla.org/storage/service;1"]. |
|
89 getService(Ci.mozIStorageService); |
|
90 let dbConnection = dbService.openDatabase(dbFile); |
|
91 dbConnection.schemaVersion = -1; |
|
92 dbConnection.close(); |
|
93 do_check_true(dbFile.exists()); |
|
94 |
|
95 // Get the service and make sure it backs up and recreates the database. |
|
96 let cps = Cc["@mozilla.org/content-pref/service;1"]. |
|
97 createInstance(Ci.nsIContentPrefService); |
|
98 do_check_true(backupDBFile.exists()); |
|
99 do_check_true(cps.DBConnection.connectionReady); |
|
100 |
|
101 cps.DBConnection.close(); |
|
102 } |
|
103 |
|
104 |
|
105 // Now get the content pref service for real for use by the rest of the tests. |
|
106 let cps = new ContentPrefInstance(null); |
|
107 |
|
108 var uri = ContentPrefTest.getURI("http://www.example.com/"); |
|
109 |
|
110 // Make sure disk synchronization checking is turned off by default. |
|
111 var statement = cps.DBConnection.createStatement("PRAGMA synchronous"); |
|
112 statement.executeStep(); |
|
113 do_check_eq(0, statement.getInt32(0)); |
|
114 |
|
115 //**************************************************************************// |
|
116 // Nonexistent Pref |
|
117 |
|
118 do_check_eq(cps.getPref(uri, "test.nonexistent.getPref"), undefined); |
|
119 do_check_eq(cps.setPref(uri, "test.nonexistent.setPref", 5), undefined); |
|
120 do_check_false(cps.hasPref(uri, "test.nonexistent.hasPref")); |
|
121 do_check_eq(cps.removePref(uri, "test.nonexistent.removePref"), undefined); |
|
122 |
|
123 |
|
124 //**************************************************************************// |
|
125 // Existing Pref |
|
126 |
|
127 cps.setPref(uri, "test.existing", 5); |
|
128 |
|
129 // getPref should return the pref value |
|
130 do_check_eq(cps.getPref(uri, "test.existing"), 5); |
|
131 |
|
132 // setPref should return undefined and change the value of the pref |
|
133 do_check_eq(cps.setPref(uri, "test.existing", 6), undefined); |
|
134 do_check_eq(cps.getPref(uri, "test.existing"), 6); |
|
135 |
|
136 // hasPref should return true |
|
137 do_check_true(cps.hasPref(uri, "test.existing")); |
|
138 |
|
139 // removePref should return undefined and remove the pref |
|
140 do_check_eq(cps.removePref(uri, "test.existing"), undefined); |
|
141 do_check_false(cps.hasPref(uri, "test.existing")); |
|
142 |
|
143 |
|
144 //**************************************************************************// |
|
145 // Round-Trip Data Integrity |
|
146 |
|
147 // Make sure pref values remain the same from setPref to getPref. |
|
148 |
|
149 cps.setPref(uri, "test.data-integrity.integer", 5); |
|
150 do_check_eq(cps.getPref(uri, "test.data-integrity.integer"), 5); |
|
151 |
|
152 cps.setPref(uri, "test.data-integrity.float", 5.5); |
|
153 do_check_eq(cps.getPref(uri, "test.data-integrity.float"), 5.5); |
|
154 |
|
155 cps.setPref(uri, "test.data-integrity.boolean", true); |
|
156 do_check_eq(cps.getPref(uri, "test.data-integrity.boolean"), true); |
|
157 |
|
158 cps.setPref(uri, "test.data-integrity.string", "test"); |
|
159 do_check_eq(cps.getPref(uri, "test.data-integrity.string"), "test"); |
|
160 |
|
161 cps.setPref(uri, "test.data-integrity.null", null); |
|
162 do_check_eq(cps.getPref(uri, "test.data-integrity.null"), null); |
|
163 |
|
164 // XXX Test arbitrary binary data. |
|
165 |
|
166 // Make sure hasPref and removePref work on all data types. |
|
167 |
|
168 do_check_true(cps.hasPref(uri, "test.data-integrity.integer")); |
|
169 do_check_true(cps.hasPref(uri, "test.data-integrity.float")); |
|
170 do_check_true(cps.hasPref(uri, "test.data-integrity.boolean")); |
|
171 do_check_true(cps.hasPref(uri, "test.data-integrity.string")); |
|
172 do_check_true(cps.hasPref(uri, "test.data-integrity.null")); |
|
173 |
|
174 do_check_eq(cps.removePref(uri, "test.data-integrity.integer"), undefined); |
|
175 do_check_eq(cps.removePref(uri, "test.data-integrity.float"), undefined); |
|
176 do_check_eq(cps.removePref(uri, "test.data-integrity.boolean"), undefined); |
|
177 do_check_eq(cps.removePref(uri, "test.data-integrity.string"), undefined); |
|
178 do_check_eq(cps.removePref(uri, "test.data-integrity.null"), undefined); |
|
179 |
|
180 do_check_false(cps.hasPref(uri, "test.data-integrity.integer")); |
|
181 do_check_false(cps.hasPref(uri, "test.data-integrity.float")); |
|
182 do_check_false(cps.hasPref(uri, "test.data-integrity.boolean")); |
|
183 do_check_false(cps.hasPref(uri, "test.data-integrity.string")); |
|
184 do_check_false(cps.hasPref(uri, "test.data-integrity.null")); |
|
185 |
|
186 |
|
187 //**************************************************************************// |
|
188 // getPrefs |
|
189 |
|
190 cps.setPref(uri, "test.getPrefs.a", 1); |
|
191 cps.setPref(uri, "test.getPrefs.b", 2); |
|
192 cps.setPref(uri, "test.getPrefs.c", 3); |
|
193 |
|
194 var prefs = cps.getPrefs(uri); |
|
195 do_check_true(prefs.hasKey("test.getPrefs.a")); |
|
196 do_check_eq(prefs.get("test.getPrefs.a"), 1); |
|
197 do_check_true(prefs.hasKey("test.getPrefs.b")); |
|
198 do_check_eq(prefs.get("test.getPrefs.b"), 2); |
|
199 do_check_true(prefs.hasKey("test.getPrefs.c")); |
|
200 do_check_eq(prefs.get("test.getPrefs.c"), 3); |
|
201 |
|
202 |
|
203 //**************************************************************************// |
|
204 // Site-Specificity |
|
205 |
|
206 // These are all different sites, and setting a pref for one of them |
|
207 // shouldn't set it for the others. |
|
208 var uri1 = ContentPrefTest.getURI("http://www.domain1.com/"); |
|
209 var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/"); |
|
210 var uri3 = ContentPrefTest.getURI("http://domain1.com/"); |
|
211 var uri4 = ContentPrefTest.getURI("http://www.domain2.com/"); |
|
212 |
|
213 cps.setPref(uri1, "test.site-specificity.uri1", 5); |
|
214 do_check_false(cps.hasPref(uri2, "test.site-specificity.uri1")); |
|
215 do_check_false(cps.hasPref(uri3, "test.site-specificity.uri1")); |
|
216 do_check_false(cps.hasPref(uri4, "test.site-specificity.uri1")); |
|
217 |
|
218 cps.setPref(uri2, "test.site-specificity.uri2", 5); |
|
219 do_check_false(cps.hasPref(uri1, "test.site-specificity.uri2")); |
|
220 do_check_false(cps.hasPref(uri3, "test.site-specificity.uri2")); |
|
221 do_check_false(cps.hasPref(uri4, "test.site-specificity.uri2")); |
|
222 |
|
223 cps.setPref(uri3, "test.site-specificity.uri3", 5); |
|
224 do_check_false(cps.hasPref(uri1, "test.site-specificity.uri3")); |
|
225 do_check_false(cps.hasPref(uri2, "test.site-specificity.uri3")); |
|
226 do_check_false(cps.hasPref(uri4, "test.site-specificity.uri3")); |
|
227 |
|
228 cps.setPref(uri4, "test.site-specificity.uri4", 5); |
|
229 do_check_false(cps.hasPref(uri1, "test.site-specificity.uri4")); |
|
230 do_check_false(cps.hasPref(uri2, "test.site-specificity.uri4")); |
|
231 do_check_false(cps.hasPref(uri3, "test.site-specificity.uri4")); |
|
232 |
|
233 |
|
234 //**************************************************************************// |
|
235 // Observers |
|
236 |
|
237 var specificObserver = { |
|
238 interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports], |
|
239 |
|
240 QueryInterface: function ContentPrefTest_QueryInterface(iid) { |
|
241 if (!this.interfaces.some( function(v) { return iid.equals(v) } )) |
|
242 throw Cr.NS_ERROR_NO_INTERFACE; |
|
243 return this; |
|
244 }, |
|
245 |
|
246 numTimesSetCalled: 0, |
|
247 onContentPrefSet: function specificObserver_onContentPrefSet(group, name, value) { |
|
248 ++this.numTimesSetCalled; |
|
249 do_check_eq(group, "www.example.com"); |
|
250 do_check_eq(name, "test.observer.1"); |
|
251 do_check_eq(value, "test value"); |
|
252 }, |
|
253 |
|
254 numTimesRemovedCalled: 0, |
|
255 onContentPrefRemoved: function specificObserver_onContentPrefRemoved(group, name) { |
|
256 ++this.numTimesRemovedCalled; |
|
257 do_check_eq(group, "www.example.com"); |
|
258 do_check_eq(name, "test.observer.1"); |
|
259 } |
|
260 |
|
261 }; |
|
262 |
|
263 var genericObserver = { |
|
264 interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports], |
|
265 |
|
266 QueryInterface: function ContentPrefTest_QueryInterface(iid) { |
|
267 if (!this.interfaces.some( function(v) { return iid.equals(v) } )) |
|
268 throw Cr.NS_ERROR_NO_INTERFACE; |
|
269 return this; |
|
270 }, |
|
271 |
|
272 numTimesSetCalled: 0, |
|
273 onContentPrefSet: function genericObserver_onContentPrefSet(group, name, value) { |
|
274 ++this.numTimesSetCalled; |
|
275 do_check_eq(group, "www.example.com"); |
|
276 if (name != "test.observer.1" && name != "test.observer.2") |
|
277 do_throw("genericObserver.onContentPrefSet: " + |
|
278 "name not in (test.observer.1, test.observer.2)"); |
|
279 do_check_eq(value, "test value"); |
|
280 }, |
|
281 |
|
282 numTimesRemovedCalled: 0, |
|
283 onContentPrefRemoved: function genericObserver_onContentPrefRemoved(group, name) { |
|
284 ++this.numTimesRemovedCalled; |
|
285 do_check_eq(group, "www.example.com"); |
|
286 if (name != "test.observer.1" && name != "test.observer.2") |
|
287 do_throw("genericObserver.onContentPrefSet: " + |
|
288 "name not in (test.observer.1, test.observer.2)"); |
|
289 } |
|
290 |
|
291 }; |
|
292 |
|
293 // Make sure we can add observers, observers get notified about changes, |
|
294 // specific observers only get notified about changes to the specific setting, |
|
295 // and generic observers get notified about changes to all settings. |
|
296 cps.addObserver("test.observer.1", specificObserver); |
|
297 cps.addObserver(null, genericObserver); |
|
298 cps.setPref(uri, "test.observer.1", "test value"); |
|
299 cps.setPref(uri, "test.observer.2", "test value"); |
|
300 cps.removePref(uri, "test.observer.1"); |
|
301 cps.removePref(uri, "test.observer.2"); |
|
302 do_check_eq(specificObserver.numTimesSetCalled, 1); |
|
303 do_check_eq(genericObserver.numTimesSetCalled, 2); |
|
304 do_check_eq(specificObserver.numTimesRemovedCalled, 1); |
|
305 do_check_eq(genericObserver.numTimesRemovedCalled, 2); |
|
306 |
|
307 // Make sure we can remove observers and they don't get notified |
|
308 // about changes anymore. |
|
309 cps.removeObserver("test.observer.1", specificObserver); |
|
310 cps.removeObserver(null, genericObserver); |
|
311 cps.setPref(uri, "test.observer.1", "test value"); |
|
312 cps.removePref(uri, "test.observer.1", "test value"); |
|
313 do_check_eq(specificObserver.numTimesSetCalled, 1); |
|
314 do_check_eq(genericObserver.numTimesSetCalled, 2); |
|
315 do_check_eq(specificObserver.numTimesRemovedCalled, 1); |
|
316 do_check_eq(genericObserver.numTimesRemovedCalled, 2); |
|
317 |
|
318 |
|
319 //**************************************************************************// |
|
320 // Get/Remove Prefs By Name |
|
321 |
|
322 { |
|
323 var anObserver = { |
|
324 interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports], |
|
325 |
|
326 QueryInterface: function ContentPrefTest_QueryInterface(iid) { |
|
327 if (!this.interfaces.some( function(v) { return iid.equals(v) } )) |
|
328 throw Cr.NS_ERROR_NO_INTERFACE; |
|
329 return this; |
|
330 }, |
|
331 |
|
332 onContentPrefSet: function anObserver_onContentPrefSet(group, name, value) { |
|
333 }, |
|
334 |
|
335 expectedDomains: [], |
|
336 numTimesRemovedCalled: 0, |
|
337 onContentPrefRemoved: function anObserver_onContentPrefRemoved(group, name) { |
|
338 ++this.numTimesRemovedCalled; |
|
339 |
|
340 // remove the domain from the list of expected domains |
|
341 var index = this.expectedDomains.indexOf(group); |
|
342 do_check_true(index >= 0); |
|
343 this.expectedDomains.splice(index, 1); |
|
344 } |
|
345 }; |
|
346 |
|
347 var uri1 = ContentPrefTest.getURI("http://www.domain1.com/"); |
|
348 var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/"); |
|
349 var uri3 = ContentPrefTest.getURI("http://domain1.com/"); |
|
350 var uri4 = ContentPrefTest.getURI("http://www.domain2.com/"); |
|
351 |
|
352 cps.setPref(uri1, "test.byname.1", 1); |
|
353 cps.setPref(uri1, "test.byname.2", 2); |
|
354 cps.setPref(uri2, "test.byname.1", 4); |
|
355 cps.setPref(uri3, "test.byname.3", 8); |
|
356 cps.setPref(uri4, "test.byname.1", 16); |
|
357 cps.setPref(null, "test.byname.1", 32); |
|
358 cps.setPref(null, "test.byname.2", false); |
|
359 |
|
360 function enumerateAndCheck(testName, expectedSum, expectedDomains) { |
|
361 var prefsByName = cps.getPrefsByName(testName); |
|
362 var enumerator = prefsByName.enumerator; |
|
363 var sum = 0; |
|
364 while (enumerator.hasMoreElements()) { |
|
365 var property = enumerator.getNext().QueryInterface(Components.interfaces.nsIProperty); |
|
366 sum += parseInt(property.value); |
|
367 |
|
368 // remove the domain from the list of expected domains |
|
369 var index = expectedDomains.indexOf(property.name); |
|
370 do_check_true(index >= 0); |
|
371 expectedDomains.splice(index, 1); |
|
372 } |
|
373 do_check_eq(sum, expectedSum); |
|
374 // check all domains have been removed from the array |
|
375 do_check_eq(expectedDomains.length, 0); |
|
376 } |
|
377 |
|
378 enumerateAndCheck("test.byname.1", 53, |
|
379 ["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"]); |
|
380 enumerateAndCheck("test.byname.2", 2, ["www.domain1.com", null]); |
|
381 enumerateAndCheck("test.byname.3", 8, ["domain1.com"]); |
|
382 |
|
383 cps.addObserver("test.byname.1", anObserver); |
|
384 anObserver.expectedDomains = ["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"]; |
|
385 |
|
386 cps.removePrefsByName("test.byname.1"); |
|
387 do_check_false(cps.hasPref(uri1, "test.byname.1")); |
|
388 do_check_false(cps.hasPref(uri2, "test.byname.1")); |
|
389 do_check_false(cps.hasPref(uri3, "test.byname.1")); |
|
390 do_check_false(cps.hasPref(uri4, "test.byname.1")); |
|
391 do_check_false(cps.hasPref(null, "test.byname.1")); |
|
392 do_check_true(cps.hasPref(uri1, "test.byname.2")); |
|
393 do_check_true(cps.hasPref(uri3, "test.byname.3")); |
|
394 |
|
395 do_check_eq(anObserver.numTimesRemovedCalled, 4); |
|
396 do_check_eq(anObserver.expectedDomains.length, 0); |
|
397 |
|
398 cps.removeObserver("test.byname.1", anObserver); |
|
399 |
|
400 // Clean up after ourselves |
|
401 cps.removePref(uri1, "test.byname.2"); |
|
402 cps.removePref(uri3, "test.byname.3"); |
|
403 cps.removePref(null, "test.byname.2"); |
|
404 } |
|
405 |
|
406 |
|
407 //**************************************************************************// |
|
408 // Clear Private Data Pref Removal |
|
409 |
|
410 { |
|
411 let uri1 = ContentPrefTest.getURI("http://www.domain1.com/"); |
|
412 let uri2 = ContentPrefTest.getURI("http://www.domain2.com/"); |
|
413 let uri3 = ContentPrefTest.getURI("http://www.domain3.com/"); |
|
414 |
|
415 let dbConnection = cps.DBConnection; |
|
416 |
|
417 let prefCount = dbConnection.createStatement("SELECT COUNT(*) AS count FROM prefs"); |
|
418 |
|
419 let groupCount = dbConnection.createStatement("SELECT COUNT(*) AS count FROM groups"); |
|
420 |
|
421 // Add some prefs for multiple domains. |
|
422 cps.setPref(uri1, "test.removeAllGroups", 1); |
|
423 cps.setPref(uri2, "test.removeAllGroups", 2); |
|
424 cps.setPref(uri3, "test.removeAllGroups", 3); |
|
425 |
|
426 // Add a global pref. |
|
427 cps.setPref(null, "test.removeAllGroups", 1); |
|
428 |
|
429 // Make sure there are some prefs and groups in the database. |
|
430 prefCount.executeStep(); |
|
431 do_check_true(prefCount.row.count > 0); |
|
432 prefCount.reset(); |
|
433 groupCount.executeStep(); |
|
434 do_check_true(groupCount.row.count > 0); |
|
435 groupCount.reset(); |
|
436 |
|
437 // Remove all prefs and groups from the database using the same routine |
|
438 // the Clear Private Data dialog uses. |
|
439 cps.removeGroupedPrefs(); |
|
440 |
|
441 // Make sure there are no longer any groups in the database and the only pref |
|
442 // is the global one. |
|
443 prefCount.executeStep(); |
|
444 do_check_true(prefCount.row.count == 1); |
|
445 prefCount.reset(); |
|
446 groupCount.executeStep(); |
|
447 do_check_true(groupCount.row.count == 0); |
|
448 groupCount.reset(); |
|
449 let globalPref = dbConnection.createStatement("SELECT groupID FROM prefs"); |
|
450 globalPref.executeStep(); |
|
451 do_check_true(globalPref.row.groupID == null); |
|
452 globalPref.reset(); |
|
453 } |
|
454 } |