1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,454 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +function run_test() { 1.9 + //**************************************************************************// 1.10 + // Database Creation, Schema Migration, and Backup 1.11 + 1.12 + // Note: in these tests we use createInstance instead of getService 1.13 + // so we can instantiate the service multiple times and make it run 1.14 + // its database initialization code each time. 1.15 + 1.16 + // Create a new database. 1.17 + { 1.18 + ContentPrefTest.deleteDatabase(); 1.19 + 1.20 + // Get the service and make sure it has a ready database connection. 1.21 + let cps = Cc["@mozilla.org/content-pref/service;1"]. 1.22 + createInstance(Ci.nsIContentPrefService); 1.23 + do_check_true(cps.DBConnection.connectionReady); 1.24 + cps.DBConnection.close(); 1.25 + } 1.26 + 1.27 + // Open an existing database. 1.28 + { 1.29 + let dbFile = ContentPrefTest.deleteDatabase(); 1.30 + 1.31 + let cps = Cc["@mozilla.org/content-pref/service;1"]. 1.32 + createInstance(Ci.nsIContentPrefService); 1.33 + cps.DBConnection.close(); 1.34 + do_check_true(dbFile.exists()); 1.35 + 1.36 + // Get the service and make sure it has a ready database connection. 1.37 + cps = Cc["@mozilla.org/content-pref/service;1"]. 1.38 + createInstance(Ci.nsIContentPrefService); 1.39 + do_check_true(cps.DBConnection.connectionReady); 1.40 + cps.DBConnection.close(); 1.41 + } 1.42 + 1.43 + // Open an empty database. 1.44 + { 1.45 + let dbFile = ContentPrefTest.deleteDatabase(); 1.46 + 1.47 + // Create an empty database. 1.48 + let dbService = Cc["@mozilla.org/storage/service;1"]. 1.49 + getService(Ci.mozIStorageService); 1.50 + let dbConnection = dbService.openDatabase(dbFile); 1.51 + do_check_eq(dbConnection.schemaVersion, 0); 1.52 + dbConnection.close(); 1.53 + do_check_true(dbFile.exists()); 1.54 + 1.55 + // Get the service and make sure it has created the schema. 1.56 + let cps = Cc["@mozilla.org/content-pref/service;1"]. 1.57 + createInstance(Ci.nsIContentPrefService); 1.58 + do_check_neq(cps.DBConnection.schemaVersion, 0); 1.59 + cps.DBConnection.close(); 1.60 + } 1.61 + 1.62 + // Open a corrupted database. 1.63 + { 1.64 + let dbFile = ContentPrefTest.deleteDatabase(); 1.65 + let backupDBFile = ContentPrefTest.deleteBackupDatabase(); 1.66 + 1.67 + // Create a corrupted database. 1.68 + let foStream = Cc["@mozilla.org/network/file-output-stream;1"]. 1.69 + createInstance(Ci.nsIFileOutputStream); 1.70 + foStream.init(dbFile, 0x02 | 0x08 | 0x20, 0666, 0); 1.71 + let garbageData = "garbage that makes SQLite think the file is corrupted"; 1.72 + foStream.write(garbageData, garbageData.length); 1.73 + foStream.close(); 1.74 + 1.75 + // Get the service and make sure it backs up and recreates the database. 1.76 + let cps = Cc["@mozilla.org/content-pref/service;1"]. 1.77 + createInstance(Ci.nsIContentPrefService); 1.78 + do_check_true(backupDBFile.exists()); 1.79 + do_check_true(cps.DBConnection.connectionReady); 1.80 + 1.81 + cps.DBConnection.close(); 1.82 + } 1.83 + 1.84 + // Open a database with a corrupted schema. 1.85 + { 1.86 + let dbFile = ContentPrefTest.deleteDatabase(); 1.87 + let backupDBFile = ContentPrefTest.deleteBackupDatabase(); 1.88 + 1.89 + // Create an empty database and set the schema version to a number 1.90 + // that will trigger a schema migration that will fail. 1.91 + let dbService = Cc["@mozilla.org/storage/service;1"]. 1.92 + getService(Ci.mozIStorageService); 1.93 + let dbConnection = dbService.openDatabase(dbFile); 1.94 + dbConnection.schemaVersion = -1; 1.95 + dbConnection.close(); 1.96 + do_check_true(dbFile.exists()); 1.97 + 1.98 + // Get the service and make sure it backs up and recreates the database. 1.99 + let cps = Cc["@mozilla.org/content-pref/service;1"]. 1.100 + createInstance(Ci.nsIContentPrefService); 1.101 + do_check_true(backupDBFile.exists()); 1.102 + do_check_true(cps.DBConnection.connectionReady); 1.103 + 1.104 + cps.DBConnection.close(); 1.105 + } 1.106 + 1.107 + 1.108 + // Now get the content pref service for real for use by the rest of the tests. 1.109 + let cps = new ContentPrefInstance(null); 1.110 + 1.111 + var uri = ContentPrefTest.getURI("http://www.example.com/"); 1.112 + 1.113 + // Make sure disk synchronization checking is turned off by default. 1.114 + var statement = cps.DBConnection.createStatement("PRAGMA synchronous"); 1.115 + statement.executeStep(); 1.116 + do_check_eq(0, statement.getInt32(0)); 1.117 + 1.118 + //**************************************************************************// 1.119 + // Nonexistent Pref 1.120 + 1.121 + do_check_eq(cps.getPref(uri, "test.nonexistent.getPref"), undefined); 1.122 + do_check_eq(cps.setPref(uri, "test.nonexistent.setPref", 5), undefined); 1.123 + do_check_false(cps.hasPref(uri, "test.nonexistent.hasPref")); 1.124 + do_check_eq(cps.removePref(uri, "test.nonexistent.removePref"), undefined); 1.125 + 1.126 + 1.127 + //**************************************************************************// 1.128 + // Existing Pref 1.129 + 1.130 + cps.setPref(uri, "test.existing", 5); 1.131 + 1.132 + // getPref should return the pref value 1.133 + do_check_eq(cps.getPref(uri, "test.existing"), 5); 1.134 + 1.135 + // setPref should return undefined and change the value of the pref 1.136 + do_check_eq(cps.setPref(uri, "test.existing", 6), undefined); 1.137 + do_check_eq(cps.getPref(uri, "test.existing"), 6); 1.138 + 1.139 + // hasPref should return true 1.140 + do_check_true(cps.hasPref(uri, "test.existing")); 1.141 + 1.142 + // removePref should return undefined and remove the pref 1.143 + do_check_eq(cps.removePref(uri, "test.existing"), undefined); 1.144 + do_check_false(cps.hasPref(uri, "test.existing")); 1.145 + 1.146 + 1.147 + //**************************************************************************// 1.148 + // Round-Trip Data Integrity 1.149 + 1.150 + // Make sure pref values remain the same from setPref to getPref. 1.151 + 1.152 + cps.setPref(uri, "test.data-integrity.integer", 5); 1.153 + do_check_eq(cps.getPref(uri, "test.data-integrity.integer"), 5); 1.154 + 1.155 + cps.setPref(uri, "test.data-integrity.float", 5.5); 1.156 + do_check_eq(cps.getPref(uri, "test.data-integrity.float"), 5.5); 1.157 + 1.158 + cps.setPref(uri, "test.data-integrity.boolean", true); 1.159 + do_check_eq(cps.getPref(uri, "test.data-integrity.boolean"), true); 1.160 + 1.161 + cps.setPref(uri, "test.data-integrity.string", "test"); 1.162 + do_check_eq(cps.getPref(uri, "test.data-integrity.string"), "test"); 1.163 + 1.164 + cps.setPref(uri, "test.data-integrity.null", null); 1.165 + do_check_eq(cps.getPref(uri, "test.data-integrity.null"), null); 1.166 + 1.167 + // XXX Test arbitrary binary data. 1.168 + 1.169 + // Make sure hasPref and removePref work on all data types. 1.170 + 1.171 + do_check_true(cps.hasPref(uri, "test.data-integrity.integer")); 1.172 + do_check_true(cps.hasPref(uri, "test.data-integrity.float")); 1.173 + do_check_true(cps.hasPref(uri, "test.data-integrity.boolean")); 1.174 + do_check_true(cps.hasPref(uri, "test.data-integrity.string")); 1.175 + do_check_true(cps.hasPref(uri, "test.data-integrity.null")); 1.176 + 1.177 + do_check_eq(cps.removePref(uri, "test.data-integrity.integer"), undefined); 1.178 + do_check_eq(cps.removePref(uri, "test.data-integrity.float"), undefined); 1.179 + do_check_eq(cps.removePref(uri, "test.data-integrity.boolean"), undefined); 1.180 + do_check_eq(cps.removePref(uri, "test.data-integrity.string"), undefined); 1.181 + do_check_eq(cps.removePref(uri, "test.data-integrity.null"), undefined); 1.182 + 1.183 + do_check_false(cps.hasPref(uri, "test.data-integrity.integer")); 1.184 + do_check_false(cps.hasPref(uri, "test.data-integrity.float")); 1.185 + do_check_false(cps.hasPref(uri, "test.data-integrity.boolean")); 1.186 + do_check_false(cps.hasPref(uri, "test.data-integrity.string")); 1.187 + do_check_false(cps.hasPref(uri, "test.data-integrity.null")); 1.188 + 1.189 + 1.190 + //**************************************************************************// 1.191 + // getPrefs 1.192 + 1.193 + cps.setPref(uri, "test.getPrefs.a", 1); 1.194 + cps.setPref(uri, "test.getPrefs.b", 2); 1.195 + cps.setPref(uri, "test.getPrefs.c", 3); 1.196 + 1.197 + var prefs = cps.getPrefs(uri); 1.198 + do_check_true(prefs.hasKey("test.getPrefs.a")); 1.199 + do_check_eq(prefs.get("test.getPrefs.a"), 1); 1.200 + do_check_true(prefs.hasKey("test.getPrefs.b")); 1.201 + do_check_eq(prefs.get("test.getPrefs.b"), 2); 1.202 + do_check_true(prefs.hasKey("test.getPrefs.c")); 1.203 + do_check_eq(prefs.get("test.getPrefs.c"), 3); 1.204 + 1.205 + 1.206 + //**************************************************************************// 1.207 + // Site-Specificity 1.208 + 1.209 + // These are all different sites, and setting a pref for one of them 1.210 + // shouldn't set it for the others. 1.211 + var uri1 = ContentPrefTest.getURI("http://www.domain1.com/"); 1.212 + var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/"); 1.213 + var uri3 = ContentPrefTest.getURI("http://domain1.com/"); 1.214 + var uri4 = ContentPrefTest.getURI("http://www.domain2.com/"); 1.215 + 1.216 + cps.setPref(uri1, "test.site-specificity.uri1", 5); 1.217 + do_check_false(cps.hasPref(uri2, "test.site-specificity.uri1")); 1.218 + do_check_false(cps.hasPref(uri3, "test.site-specificity.uri1")); 1.219 + do_check_false(cps.hasPref(uri4, "test.site-specificity.uri1")); 1.220 + 1.221 + cps.setPref(uri2, "test.site-specificity.uri2", 5); 1.222 + do_check_false(cps.hasPref(uri1, "test.site-specificity.uri2")); 1.223 + do_check_false(cps.hasPref(uri3, "test.site-specificity.uri2")); 1.224 + do_check_false(cps.hasPref(uri4, "test.site-specificity.uri2")); 1.225 + 1.226 + cps.setPref(uri3, "test.site-specificity.uri3", 5); 1.227 + do_check_false(cps.hasPref(uri1, "test.site-specificity.uri3")); 1.228 + do_check_false(cps.hasPref(uri2, "test.site-specificity.uri3")); 1.229 + do_check_false(cps.hasPref(uri4, "test.site-specificity.uri3")); 1.230 + 1.231 + cps.setPref(uri4, "test.site-specificity.uri4", 5); 1.232 + do_check_false(cps.hasPref(uri1, "test.site-specificity.uri4")); 1.233 + do_check_false(cps.hasPref(uri2, "test.site-specificity.uri4")); 1.234 + do_check_false(cps.hasPref(uri3, "test.site-specificity.uri4")); 1.235 + 1.236 + 1.237 + //**************************************************************************// 1.238 + // Observers 1.239 + 1.240 + var specificObserver = { 1.241 + interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports], 1.242 + 1.243 + QueryInterface: function ContentPrefTest_QueryInterface(iid) { 1.244 + if (!this.interfaces.some( function(v) { return iid.equals(v) } )) 1.245 + throw Cr.NS_ERROR_NO_INTERFACE; 1.246 + return this; 1.247 + }, 1.248 + 1.249 + numTimesSetCalled: 0, 1.250 + onContentPrefSet: function specificObserver_onContentPrefSet(group, name, value) { 1.251 + ++this.numTimesSetCalled; 1.252 + do_check_eq(group, "www.example.com"); 1.253 + do_check_eq(name, "test.observer.1"); 1.254 + do_check_eq(value, "test value"); 1.255 + }, 1.256 + 1.257 + numTimesRemovedCalled: 0, 1.258 + onContentPrefRemoved: function specificObserver_onContentPrefRemoved(group, name) { 1.259 + ++this.numTimesRemovedCalled; 1.260 + do_check_eq(group, "www.example.com"); 1.261 + do_check_eq(name, "test.observer.1"); 1.262 + } 1.263 + 1.264 + }; 1.265 + 1.266 + var genericObserver = { 1.267 + interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports], 1.268 + 1.269 + QueryInterface: function ContentPrefTest_QueryInterface(iid) { 1.270 + if (!this.interfaces.some( function(v) { return iid.equals(v) } )) 1.271 + throw Cr.NS_ERROR_NO_INTERFACE; 1.272 + return this; 1.273 + }, 1.274 + 1.275 + numTimesSetCalled: 0, 1.276 + onContentPrefSet: function genericObserver_onContentPrefSet(group, name, value) { 1.277 + ++this.numTimesSetCalled; 1.278 + do_check_eq(group, "www.example.com"); 1.279 + if (name != "test.observer.1" && name != "test.observer.2") 1.280 + do_throw("genericObserver.onContentPrefSet: " + 1.281 + "name not in (test.observer.1, test.observer.2)"); 1.282 + do_check_eq(value, "test value"); 1.283 + }, 1.284 + 1.285 + numTimesRemovedCalled: 0, 1.286 + onContentPrefRemoved: function genericObserver_onContentPrefRemoved(group, name) { 1.287 + ++this.numTimesRemovedCalled; 1.288 + do_check_eq(group, "www.example.com"); 1.289 + if (name != "test.observer.1" && name != "test.observer.2") 1.290 + do_throw("genericObserver.onContentPrefSet: " + 1.291 + "name not in (test.observer.1, test.observer.2)"); 1.292 + } 1.293 + 1.294 + }; 1.295 + 1.296 + // Make sure we can add observers, observers get notified about changes, 1.297 + // specific observers only get notified about changes to the specific setting, 1.298 + // and generic observers get notified about changes to all settings. 1.299 + cps.addObserver("test.observer.1", specificObserver); 1.300 + cps.addObserver(null, genericObserver); 1.301 + cps.setPref(uri, "test.observer.1", "test value"); 1.302 + cps.setPref(uri, "test.observer.2", "test value"); 1.303 + cps.removePref(uri, "test.observer.1"); 1.304 + cps.removePref(uri, "test.observer.2"); 1.305 + do_check_eq(specificObserver.numTimesSetCalled, 1); 1.306 + do_check_eq(genericObserver.numTimesSetCalled, 2); 1.307 + do_check_eq(specificObserver.numTimesRemovedCalled, 1); 1.308 + do_check_eq(genericObserver.numTimesRemovedCalled, 2); 1.309 + 1.310 + // Make sure we can remove observers and they don't get notified 1.311 + // about changes anymore. 1.312 + cps.removeObserver("test.observer.1", specificObserver); 1.313 + cps.removeObserver(null, genericObserver); 1.314 + cps.setPref(uri, "test.observer.1", "test value"); 1.315 + cps.removePref(uri, "test.observer.1", "test value"); 1.316 + do_check_eq(specificObserver.numTimesSetCalled, 1); 1.317 + do_check_eq(genericObserver.numTimesSetCalled, 2); 1.318 + do_check_eq(specificObserver.numTimesRemovedCalled, 1); 1.319 + do_check_eq(genericObserver.numTimesRemovedCalled, 2); 1.320 + 1.321 + 1.322 + //**************************************************************************// 1.323 + // Get/Remove Prefs By Name 1.324 + 1.325 + { 1.326 + var anObserver = { 1.327 + interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports], 1.328 + 1.329 + QueryInterface: function ContentPrefTest_QueryInterface(iid) { 1.330 + if (!this.interfaces.some( function(v) { return iid.equals(v) } )) 1.331 + throw Cr.NS_ERROR_NO_INTERFACE; 1.332 + return this; 1.333 + }, 1.334 + 1.335 + onContentPrefSet: function anObserver_onContentPrefSet(group, name, value) { 1.336 + }, 1.337 + 1.338 + expectedDomains: [], 1.339 + numTimesRemovedCalled: 0, 1.340 + onContentPrefRemoved: function anObserver_onContentPrefRemoved(group, name) { 1.341 + ++this.numTimesRemovedCalled; 1.342 + 1.343 + // remove the domain from the list of expected domains 1.344 + var index = this.expectedDomains.indexOf(group); 1.345 + do_check_true(index >= 0); 1.346 + this.expectedDomains.splice(index, 1); 1.347 + } 1.348 + }; 1.349 + 1.350 + var uri1 = ContentPrefTest.getURI("http://www.domain1.com/"); 1.351 + var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/"); 1.352 + var uri3 = ContentPrefTest.getURI("http://domain1.com/"); 1.353 + var uri4 = ContentPrefTest.getURI("http://www.domain2.com/"); 1.354 + 1.355 + cps.setPref(uri1, "test.byname.1", 1); 1.356 + cps.setPref(uri1, "test.byname.2", 2); 1.357 + cps.setPref(uri2, "test.byname.1", 4); 1.358 + cps.setPref(uri3, "test.byname.3", 8); 1.359 + cps.setPref(uri4, "test.byname.1", 16); 1.360 + cps.setPref(null, "test.byname.1", 32); 1.361 + cps.setPref(null, "test.byname.2", false); 1.362 + 1.363 + function enumerateAndCheck(testName, expectedSum, expectedDomains) { 1.364 + var prefsByName = cps.getPrefsByName(testName); 1.365 + var enumerator = prefsByName.enumerator; 1.366 + var sum = 0; 1.367 + while (enumerator.hasMoreElements()) { 1.368 + var property = enumerator.getNext().QueryInterface(Components.interfaces.nsIProperty); 1.369 + sum += parseInt(property.value); 1.370 + 1.371 + // remove the domain from the list of expected domains 1.372 + var index = expectedDomains.indexOf(property.name); 1.373 + do_check_true(index >= 0); 1.374 + expectedDomains.splice(index, 1); 1.375 + } 1.376 + do_check_eq(sum, expectedSum); 1.377 + // check all domains have been removed from the array 1.378 + do_check_eq(expectedDomains.length, 0); 1.379 + } 1.380 + 1.381 + enumerateAndCheck("test.byname.1", 53, 1.382 + ["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"]); 1.383 + enumerateAndCheck("test.byname.2", 2, ["www.domain1.com", null]); 1.384 + enumerateAndCheck("test.byname.3", 8, ["domain1.com"]); 1.385 + 1.386 + cps.addObserver("test.byname.1", anObserver); 1.387 + anObserver.expectedDomains = ["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"]; 1.388 + 1.389 + cps.removePrefsByName("test.byname.1"); 1.390 + do_check_false(cps.hasPref(uri1, "test.byname.1")); 1.391 + do_check_false(cps.hasPref(uri2, "test.byname.1")); 1.392 + do_check_false(cps.hasPref(uri3, "test.byname.1")); 1.393 + do_check_false(cps.hasPref(uri4, "test.byname.1")); 1.394 + do_check_false(cps.hasPref(null, "test.byname.1")); 1.395 + do_check_true(cps.hasPref(uri1, "test.byname.2")); 1.396 + do_check_true(cps.hasPref(uri3, "test.byname.3")); 1.397 + 1.398 + do_check_eq(anObserver.numTimesRemovedCalled, 4); 1.399 + do_check_eq(anObserver.expectedDomains.length, 0); 1.400 + 1.401 + cps.removeObserver("test.byname.1", anObserver); 1.402 + 1.403 + // Clean up after ourselves 1.404 + cps.removePref(uri1, "test.byname.2"); 1.405 + cps.removePref(uri3, "test.byname.3"); 1.406 + cps.removePref(null, "test.byname.2"); 1.407 + } 1.408 + 1.409 + 1.410 + //**************************************************************************// 1.411 + // Clear Private Data Pref Removal 1.412 + 1.413 + { 1.414 + let uri1 = ContentPrefTest.getURI("http://www.domain1.com/"); 1.415 + let uri2 = ContentPrefTest.getURI("http://www.domain2.com/"); 1.416 + let uri3 = ContentPrefTest.getURI("http://www.domain3.com/"); 1.417 + 1.418 + let dbConnection = cps.DBConnection; 1.419 + 1.420 + let prefCount = dbConnection.createStatement("SELECT COUNT(*) AS count FROM prefs"); 1.421 + 1.422 + let groupCount = dbConnection.createStatement("SELECT COUNT(*) AS count FROM groups"); 1.423 + 1.424 + // Add some prefs for multiple domains. 1.425 + cps.setPref(uri1, "test.removeAllGroups", 1); 1.426 + cps.setPref(uri2, "test.removeAllGroups", 2); 1.427 + cps.setPref(uri3, "test.removeAllGroups", 3); 1.428 + 1.429 + // Add a global pref. 1.430 + cps.setPref(null, "test.removeAllGroups", 1); 1.431 + 1.432 + // Make sure there are some prefs and groups in the database. 1.433 + prefCount.executeStep(); 1.434 + do_check_true(prefCount.row.count > 0); 1.435 + prefCount.reset(); 1.436 + groupCount.executeStep(); 1.437 + do_check_true(groupCount.row.count > 0); 1.438 + groupCount.reset(); 1.439 + 1.440 + // Remove all prefs and groups from the database using the same routine 1.441 + // the Clear Private Data dialog uses. 1.442 + cps.removeGroupedPrefs(); 1.443 + 1.444 + // Make sure there are no longer any groups in the database and the only pref 1.445 + // is the global one. 1.446 + prefCount.executeStep(); 1.447 + do_check_true(prefCount.row.count == 1); 1.448 + prefCount.reset(); 1.449 + groupCount.executeStep(); 1.450 + do_check_true(groupCount.row.count == 0); 1.451 + groupCount.reset(); 1.452 + let globalPref = dbConnection.createStatement("SELECT groupID FROM prefs"); 1.453 + globalPref.executeStep(); 1.454 + do_check_true(globalPref.row.groupID == null); 1.455 + globalPref.reset(); 1.456 + } 1.457 +}