Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | const { interfaces: Ci, classes: Cc, results: Cr, utils: Cu } = Components; |
michael@0 | 6 | |
michael@0 | 7 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 8 | |
michael@0 | 9 | var cps; |
michael@0 | 10 | var asyncRunner; |
michael@0 | 11 | var next; |
michael@0 | 12 | |
michael@0 | 13 | (function init() { |
michael@0 | 14 | // There has to be a profile directory before the CPS service is gotten. |
michael@0 | 15 | do_get_profile(); |
michael@0 | 16 | })(); |
michael@0 | 17 | |
michael@0 | 18 | function runAsyncTests(tests) { |
michael@0 | 19 | do_test_pending(); |
michael@0 | 20 | |
michael@0 | 21 | cps = Cc["@mozilla.org/content-pref/service;1"]. |
michael@0 | 22 | getService(Ci.nsIContentPrefService2); |
michael@0 | 23 | |
michael@0 | 24 | // Without this the private-browsing service tries to open a dialog when you |
michael@0 | 25 | // change its enabled state. |
michael@0 | 26 | Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", |
michael@0 | 27 | true); |
michael@0 | 28 | |
michael@0 | 29 | let s = {}; |
michael@0 | 30 | Cu.import("resource://test/AsyncRunner.jsm", s); |
michael@0 | 31 | asyncRunner = new s.AsyncRunner({ |
michael@0 | 32 | done: do_test_finished, |
michael@0 | 33 | error: function (err) { |
michael@0 | 34 | // xpcshell test functions like do_check_eq throw NS_ERROR_ABORT on |
michael@0 | 35 | // failure. Ignore those and catch only uncaught exceptions. |
michael@0 | 36 | if (err !== Cr.NS_ERROR_ABORT) { |
michael@0 | 37 | if (err.stack) { |
michael@0 | 38 | err = err + "\n\nTraceback (most recent call first):\n" + err.stack + |
michael@0 | 39 | "\nUseless do_throw stack:"; |
michael@0 | 40 | } |
michael@0 | 41 | do_throw(err); |
michael@0 | 42 | } |
michael@0 | 43 | }, |
michael@0 | 44 | consoleError: function (scriptErr) { |
michael@0 | 45 | // As much as possible make sure the error is related to the test. On the |
michael@0 | 46 | // other hand if this fails to catch a test-related error, we'll hang. |
michael@0 | 47 | let filename = scriptErr.sourceName || scriptErr.toString() || ""; |
michael@0 | 48 | if (/contentpref/i.test(filename)) |
michael@0 | 49 | do_throw(scriptErr); |
michael@0 | 50 | } |
michael@0 | 51 | }); |
michael@0 | 52 | |
michael@0 | 53 | next = asyncRunner.next.bind(asyncRunner); |
michael@0 | 54 | |
michael@0 | 55 | do_register_cleanup(function () { |
michael@0 | 56 | asyncRunner.destroy(); |
michael@0 | 57 | asyncRunner = null; |
michael@0 | 58 | }); |
michael@0 | 59 | |
michael@0 | 60 | tests.forEach(function (test) { |
michael@0 | 61 | function gen() { |
michael@0 | 62 | do_print("Running " + test.name); |
michael@0 | 63 | yield test(); |
michael@0 | 64 | yield reset(); |
michael@0 | 65 | } |
michael@0 | 66 | asyncRunner.appendIterator(gen()); |
michael@0 | 67 | }); |
michael@0 | 68 | |
michael@0 | 69 | // reset() ends up calling asyncRunner.next(), starting the tests. |
michael@0 | 70 | reset(); |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | function makeCallback(callbacks) { |
michael@0 | 74 | callbacks = callbacks || {}; |
michael@0 | 75 | ["handleResult", "handleError"].forEach(function (meth) { |
michael@0 | 76 | if (!callbacks[meth]) |
michael@0 | 77 | callbacks[meth] = function () { |
michael@0 | 78 | do_throw(meth + " shouldn't be called."); |
michael@0 | 79 | }; |
michael@0 | 80 | }); |
michael@0 | 81 | if (!callbacks.handleCompletion) |
michael@0 | 82 | callbacks.handleCompletion = function (reason) { |
michael@0 | 83 | do_check_eq(reason, Ci.nsIContentPrefCallback2.COMPLETE_OK); |
michael@0 | 84 | next(); |
michael@0 | 85 | }; |
michael@0 | 86 | return callbacks; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | function do_check_throws(fn) { |
michael@0 | 90 | let threw = false; |
michael@0 | 91 | try { |
michael@0 | 92 | fn(); |
michael@0 | 93 | } |
michael@0 | 94 | catch (err) { |
michael@0 | 95 | threw = true; |
michael@0 | 96 | } |
michael@0 | 97 | do_check_true(threw); |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | function sendMessage(msg, callback) { |
michael@0 | 101 | let obj = callback || {}; |
michael@0 | 102 | let ref = Cu.getWeakReference(obj); |
michael@0 | 103 | cps.QueryInterface(Ci.nsIObserver).observe(ref, "test:" + msg, null); |
michael@0 | 104 | return "value" in obj ? obj.value : undefined; |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | function reset() { |
michael@0 | 108 | sendMessage("reset", next); |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | function set(group, name, val, context) { |
michael@0 | 112 | cps.set(group, name, val, context, makeCallback()); |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | function setGlobal(name, val, context) { |
michael@0 | 116 | cps.setGlobal(name, val, context, makeCallback()); |
michael@0 | 117 | } |
michael@0 | 118 | |
michael@0 | 119 | function prefOK(actual, expected, strict) { |
michael@0 | 120 | do_check_true(actual instanceof Ci.nsIContentPref); |
michael@0 | 121 | do_check_eq(actual.domain, expected.domain); |
michael@0 | 122 | do_check_eq(actual.name, expected.name); |
michael@0 | 123 | if (strict) |
michael@0 | 124 | do_check_true(actual.value === expected.value); |
michael@0 | 125 | else |
michael@0 | 126 | do_check_eq(actual.value, expected.value); |
michael@0 | 127 | } |
michael@0 | 128 | |
michael@0 | 129 | function getOK(args, expectedVal, expectedGroup, strict) { |
michael@0 | 130 | if (args.length == 2) |
michael@0 | 131 | args.push(undefined); |
michael@0 | 132 | let expectedPrefs = expectedVal === undefined ? [] : |
michael@0 | 133 | [{ domain: expectedGroup || args[0], |
michael@0 | 134 | name: args[1], |
michael@0 | 135 | value: expectedVal }]; |
michael@0 | 136 | yield getOKEx("getByDomainAndName", args, expectedPrefs, strict); |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | function getSubdomainsOK(args, expectedGroupValPairs) { |
michael@0 | 140 | if (args.length == 2) |
michael@0 | 141 | args.push(undefined); |
michael@0 | 142 | let expectedPrefs = expectedGroupValPairs.map(function ([group, val]) { |
michael@0 | 143 | return { domain: group, name: args[1], value: val }; |
michael@0 | 144 | }); |
michael@0 | 145 | yield getOKEx("getBySubdomainAndName", args, expectedPrefs); |
michael@0 | 146 | } |
michael@0 | 147 | |
michael@0 | 148 | function getGlobalOK(args, expectedVal) { |
michael@0 | 149 | if (args.length == 1) |
michael@0 | 150 | args.push(undefined); |
michael@0 | 151 | let expectedPrefs = expectedVal === undefined ? [] : |
michael@0 | 152 | [{ domain: null, name: args[0], value: expectedVal }]; |
michael@0 | 153 | yield getOKEx("getGlobal", args, expectedPrefs); |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | function getOKEx(methodName, args, expectedPrefs, strict, context) { |
michael@0 | 157 | let actualPrefs = []; |
michael@0 | 158 | args.push(makeCallback({ |
michael@0 | 159 | handleResult: function (pref) actualPrefs.push(pref) |
michael@0 | 160 | })); |
michael@0 | 161 | yield cps[methodName].apply(cps, args); |
michael@0 | 162 | arraysOfArraysOK([actualPrefs], [expectedPrefs], function (actual, expected) { |
michael@0 | 163 | prefOK(actual, expected, strict); |
michael@0 | 164 | }); |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | function getCachedOK(args, expectedIsCached, expectedVal, expectedGroup, |
michael@0 | 168 | strict) { |
michael@0 | 169 | if (args.length == 2) |
michael@0 | 170 | args.push(undefined); |
michael@0 | 171 | let expectedPref = !expectedIsCached ? null : { |
michael@0 | 172 | domain: expectedGroup || args[0], |
michael@0 | 173 | name: args[1], |
michael@0 | 174 | value: expectedVal |
michael@0 | 175 | }; |
michael@0 | 176 | getCachedOKEx("getCachedByDomainAndName", args, expectedPref, strict); |
michael@0 | 177 | } |
michael@0 | 178 | |
michael@0 | 179 | function getCachedSubdomainsOK(args, expectedGroupValPairs) { |
michael@0 | 180 | if (args.length == 2) |
michael@0 | 181 | args.push(undefined); |
michael@0 | 182 | let len = {}; |
michael@0 | 183 | args.push(len); |
michael@0 | 184 | let actualPrefs = cps.getCachedBySubdomainAndName.apply(cps, args); |
michael@0 | 185 | actualPrefs = actualPrefs.sort(function (a, b) { |
michael@0 | 186 | return a.domain.localeCompare(b.domain); |
michael@0 | 187 | }); |
michael@0 | 188 | do_check_eq(actualPrefs.length, len.value); |
michael@0 | 189 | let expectedPrefs = expectedGroupValPairs.map(function ([group, val]) { |
michael@0 | 190 | return { domain: group, name: args[1], value: val }; |
michael@0 | 191 | }); |
michael@0 | 192 | arraysOfArraysOK([actualPrefs], [expectedPrefs], prefOK); |
michael@0 | 193 | } |
michael@0 | 194 | |
michael@0 | 195 | function getCachedGlobalOK(args, expectedIsCached, expectedVal) { |
michael@0 | 196 | if (args.length == 1) |
michael@0 | 197 | args.push(undefined); |
michael@0 | 198 | let expectedPref = !expectedIsCached ? null : { |
michael@0 | 199 | domain: null, |
michael@0 | 200 | name: args[0], |
michael@0 | 201 | value: expectedVal |
michael@0 | 202 | }; |
michael@0 | 203 | getCachedOKEx("getCachedGlobal", args, expectedPref); |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | function getCachedOKEx(methodName, args, expectedPref, strict) { |
michael@0 | 207 | let actualPref = cps[methodName].apply(cps, args); |
michael@0 | 208 | if (expectedPref) |
michael@0 | 209 | prefOK(actualPref, expectedPref, strict); |
michael@0 | 210 | else |
michael@0 | 211 | do_check_true(actualPref === null); |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | function arraysOfArraysOK(actual, expected, cmp) { |
michael@0 | 215 | cmp = cmp || function (a, b) do_check_eq(a, b); |
michael@0 | 216 | do_check_eq(actual.length, expected.length); |
michael@0 | 217 | actual.forEach(function (actualChildArr, i) { |
michael@0 | 218 | let expectedChildArr = expected[i]; |
michael@0 | 219 | do_check_eq(actualChildArr.length, expectedChildArr.length); |
michael@0 | 220 | actualChildArr.forEach(function (actualElt, j) { |
michael@0 | 221 | let expectedElt = expectedChildArr[j]; |
michael@0 | 222 | cmp(actualElt, expectedElt); |
michael@0 | 223 | }); |
michael@0 | 224 | }); |
michael@0 | 225 | } |
michael@0 | 226 | |
michael@0 | 227 | function dbOK(expectedRows) { |
michael@0 | 228 | let db = sendMessage("db"); |
michael@0 | 229 | let stmt = db.createAsyncStatement( |
michael@0 | 230 | "SELECT groups.name AS grp, settings.name AS name, prefs.value AS value " + |
michael@0 | 231 | "FROM prefs " + |
michael@0 | 232 | "LEFT JOIN groups ON groups.id = prefs.groupID " + |
michael@0 | 233 | "LEFT JOIN settings ON settings.id = prefs.settingID " + |
michael@0 | 234 | "UNION " + |
michael@0 | 235 | |
michael@0 | 236 | // These second two SELECTs get the rows of the groups and settings tables |
michael@0 | 237 | // that aren't referenced by the prefs table. Neither should return any |
michael@0 | 238 | // rows if the component is working properly. |
michael@0 | 239 | "SELECT groups.name AS grp, NULL AS name, NULL AS value " + |
michael@0 | 240 | "FROM groups " + |
michael@0 | 241 | "WHERE id NOT IN (" + |
michael@0 | 242 | "SELECT DISTINCT groupID " + |
michael@0 | 243 | "FROM prefs " + |
michael@0 | 244 | "WHERE groupID NOTNULL" + |
michael@0 | 245 | ") " + |
michael@0 | 246 | "UNION " + |
michael@0 | 247 | "SELECT NULL AS grp, settings.name AS name, NULL AS value " + |
michael@0 | 248 | "FROM settings " + |
michael@0 | 249 | "WHERE id NOT IN (" + |
michael@0 | 250 | "SELECT DISTINCT settingID " + |
michael@0 | 251 | "FROM prefs " + |
michael@0 | 252 | "WHERE settingID NOTNULL" + |
michael@0 | 253 | ") " + |
michael@0 | 254 | |
michael@0 | 255 | "ORDER BY value ASC, grp ASC, name ASC" |
michael@0 | 256 | ); |
michael@0 | 257 | |
michael@0 | 258 | let actualRows = []; |
michael@0 | 259 | let cols = ["grp", "name", "value"]; |
michael@0 | 260 | |
michael@0 | 261 | db.executeAsync([stmt], 1, { |
michael@0 | 262 | handleCompletion: function (reason) { |
michael@0 | 263 | arraysOfArraysOK(actualRows, expectedRows); |
michael@0 | 264 | next(); |
michael@0 | 265 | }, |
michael@0 | 266 | handleResult: function (results) { |
michael@0 | 267 | let row = null; |
michael@0 | 268 | while (row = results.getNextRow()) { |
michael@0 | 269 | actualRows.push(cols.map(function (c) row.getResultByName(c))); |
michael@0 | 270 | } |
michael@0 | 271 | }, |
michael@0 | 272 | handleError: function (err) { |
michael@0 | 273 | do_throw(err); |
michael@0 | 274 | } |
michael@0 | 275 | }); |
michael@0 | 276 | stmt.finalize(); |
michael@0 | 277 | } |
michael@0 | 278 | |
michael@0 | 279 | function on(event, names, dontRemove) { |
michael@0 | 280 | let args = { |
michael@0 | 281 | reset: function () { |
michael@0 | 282 | for (let prop in this) { |
michael@0 | 283 | if (Array.isArray(this[prop])) |
michael@0 | 284 | this[prop].splice(0, this[prop].length); |
michael@0 | 285 | } |
michael@0 | 286 | }, |
michael@0 | 287 | }; |
michael@0 | 288 | |
michael@0 | 289 | let observers = {}; |
michael@0 | 290 | |
michael@0 | 291 | names.forEach(function (name) { |
michael@0 | 292 | let obs = {}; |
michael@0 | 293 | ["onContentPrefSet", "onContentPrefRemoved"].forEach(function (meth) { |
michael@0 | 294 | obs[meth] = function () do_throw(meth + " should not be called"); |
michael@0 | 295 | }); |
michael@0 | 296 | obs["onContentPref" + event] = function () { |
michael@0 | 297 | args[name].push(Array.slice(arguments)); |
michael@0 | 298 | }; |
michael@0 | 299 | observers[name] = obs; |
michael@0 | 300 | args[name] = []; |
michael@0 | 301 | args[name].observer = obs; |
michael@0 | 302 | cps.addObserverForName(name, obs); |
michael@0 | 303 | }); |
michael@0 | 304 | |
michael@0 | 305 | do_execute_soon(function () { |
michael@0 | 306 | if (!dontRemove) |
michael@0 | 307 | names.forEach(function (n) cps.removeObserverForName(n, observers[n])); |
michael@0 | 308 | next(args); |
michael@0 | 309 | }); |
michael@0 | 310 | } |
michael@0 | 311 | |
michael@0 | 312 | function wait() { |
michael@0 | 313 | do_execute_soon(next); |
michael@0 | 314 | } |
michael@0 | 315 | |
michael@0 | 316 | function observerArgsOK(actualArgs, expectedArgs) { |
michael@0 | 317 | do_check_neq(actualArgs, undefined); |
michael@0 | 318 | arraysOfArraysOK(actualArgs, expectedArgs); |
michael@0 | 319 | } |