Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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/. */
5 // Ideally this would be an xpcshell test, but Troubleshoot relies on things
6 // that aren't initialized outside of a XUL app environment like AddonManager
7 // and the "@mozilla.org/xre/app-info;1" component.
9 Components.utils.import("resource://gre/modules/Services.jsm");
10 Components.utils.import("resource://gre/modules/Troubleshoot.jsm");
12 function test() {
13 waitForExplicitFinish();
14 function doNextTest() {
15 if (!tests.length) {
16 finish();
17 return;
18 }
19 tests.shift()(doNextTest);
20 }
21 doNextTest();
22 }
24 registerCleanupFunction(function () {
25 // Troubleshoot.jsm is imported into the global scope -- the window -- above.
26 // If it's not deleted, it outlives the test and is reported as a leak.
27 delete window.Troubleshoot;
28 });
30 let tests = [
32 function snapshotSchema(done) {
33 Troubleshoot.snapshot(function (snapshot) {
34 try {
35 validateObject(snapshot, SNAPSHOT_SCHEMA);
36 ok(true, "The snapshot should conform to the schema.");
37 }
38 catch (err) {
39 ok(false, err);
40 }
41 done();
42 });
43 },
45 function modifiedPreferences(done) {
46 let prefs = [
47 "javascript.troubleshoot",
48 "troubleshoot.foo",
49 "javascript.print_to_filename",
50 "network.proxy.troubleshoot",
51 ];
52 prefs.forEach(function (p) {
53 Services.prefs.setBoolPref(p, true);
54 is(Services.prefs.getBoolPref(p), true, "The pref should be set: " + p);
55 });
56 Troubleshoot.snapshot(function (snapshot) {
57 let p = snapshot.modifiedPreferences;
58 is(p["javascript.troubleshoot"], true,
59 "The pref should be present because it's whitelisted " +
60 "but not blacklisted.");
61 ok(!("troubleshoot.foo" in p),
62 "The pref should be absent because it's not in the whitelist.");
63 ok(!("javascript.print_to_filename" in p),
64 "The pref should be absent because it's blacklisted.");
65 ok(!("network.proxy.troubleshoot" in p),
66 "The pref should be absent because it's blacklisted.");
67 prefs.forEach(function (p) Services.prefs.deleteBranch(p));
68 done();
69 });
70 },
71 ];
73 // This is inspired by JSON Schema, or by the example on its Wikipedia page
74 // anyway.
75 const SNAPSHOT_SCHEMA = {
76 type: "object",
77 required: true,
78 properties: {
79 application: {
80 required: true,
81 type: "object",
82 properties: {
83 name: {
84 required: true,
85 type: "string",
86 },
87 version: {
88 required: true,
89 type: "string",
90 },
91 userAgent: {
92 required: true,
93 type: "string",
94 },
95 vendor: {
96 type: "string",
97 },
98 supportURL: {
99 type: "string",
100 },
101 },
102 },
103 crashes: {
104 required: false,
105 type: "object",
106 properties: {
107 pending: {
108 required: true,
109 type: "number",
110 },
111 submitted: {
112 required: true,
113 type: "array",
114 items: {
115 type: "object",
116 properties: {
117 id: {
118 required: true,
119 type: "string",
120 },
121 date: {
122 required: true,
123 type: "number",
124 },
125 pending: {
126 required: true,
127 type: "boolean",
128 },
129 },
130 },
131 },
132 },
133 },
134 extensions: {
135 required: true,
136 type: "array",
137 items: {
138 type: "object",
139 properties: {
140 name: {
141 required: true,
142 type: "string",
143 },
144 version: {
145 required: true,
146 type: "string",
147 },
148 id: {
149 required: true,
150 type: "string",
151 },
152 isActive: {
153 required: true,
154 type: "boolean",
155 },
156 },
157 },
158 },
159 modifiedPreferences: {
160 required: true,
161 type: "object",
162 },
163 graphics: {
164 required: true,
165 type: "object",
166 properties: {
167 numTotalWindows: {
168 required: true,
169 type: "number",
170 },
171 numAcceleratedWindows: {
172 required: true,
173 type: "number",
174 },
175 windowLayerManagerType: {
176 type: "string",
177 },
178 windowLayerManagerRemote: {
179 type: "boolean",
180 },
181 numAcceleratedWindowsMessage: {
182 type: "array",
183 },
184 adapterDescription: {
185 type: "string",
186 },
187 adapterVendorID: {
188 type: "string",
189 },
190 adapterDeviceID: {
191 type: "string",
192 },
193 adapterRAM: {
194 type: "string",
195 },
196 adapterDrivers: {
197 type: "string",
198 },
199 driverVersion: {
200 type: "string",
201 },
202 driverDate: {
203 type: "string",
204 },
205 adapterDescription2: {
206 type: "string",
207 },
208 adapterVendorID2: {
209 type: "string",
210 },
211 adapterDeviceID2: {
212 type: "string",
213 },
214 adapterRAM2: {
215 type: "string",
216 },
217 adapterDrivers2: {
218 type: "string",
219 },
220 driverVersion2: {
221 type: "string",
222 },
223 driverDate2: {
224 type: "string",
225 },
226 isGPU2Active: {
227 type: "boolean",
228 },
229 direct2DEnabled: {
230 type: "boolean",
231 },
232 directWriteEnabled: {
233 type: "boolean",
234 },
235 directWriteVersion: {
236 type: "string",
237 },
238 clearTypeParameters: {
239 type: "string",
240 },
241 webglRenderer: {
242 type: "string",
243 },
244 info: {
245 type: "object",
246 },
247 failures: {
248 type: "array",
249 items: {
250 type: "string",
251 },
252 },
253 direct2DEnabledMessage: {
254 type: "array",
255 },
256 webglRendererMessage: {
257 type: "array",
258 },
259 },
260 },
261 javaScript: {
262 required: true,
263 type: "object",
264 properties: {
265 incrementalGCEnabled: {
266 type: "boolean",
267 },
268 },
269 },
270 accessibility: {
271 required: true,
272 type: "object",
273 properties: {
274 isActive: {
275 required: true,
276 type: "boolean",
277 },
278 forceDisabled: {
279 type: "number",
280 },
281 },
282 },
283 libraryVersions: {
284 required: true,
285 type: "object",
286 properties: {
287 NSPR: {
288 required: true,
289 type: "object",
290 properties: {
291 minVersion: {
292 required: true,
293 type: "string",
294 },
295 version: {
296 required: true,
297 type: "string",
298 },
299 },
300 },
301 NSS: {
302 required: true,
303 type: "object",
304 properties: {
305 minVersion: {
306 required: true,
307 type: "string",
308 },
309 version: {
310 required: true,
311 type: "string",
312 },
313 },
314 },
315 NSSUTIL: {
316 required: true,
317 type: "object",
318 properties: {
319 minVersion: {
320 required: true,
321 type: "string",
322 },
323 version: {
324 required: true,
325 type: "string",
326 },
327 },
328 },
329 NSSSSL: {
330 required: true,
331 type: "object",
332 properties: {
333 minVersion: {
334 required: true,
335 type: "string",
336 },
337 version: {
338 required: true,
339 type: "string",
340 },
341 },
342 },
343 NSSSMIME: {
344 required: true,
345 type: "object",
346 properties: {
347 minVersion: {
348 required: true,
349 type: "string",
350 },
351 version: {
352 required: true,
353 type: "string",
354 },
355 },
356 },
357 },
358 },
359 userJS: {
360 required: true,
361 type: "object",
362 properties: {
363 exists: {
364 required: true,
365 type: "boolean",
366 },
367 },
368 },
369 experiments: {
370 type: "array",
371 },
372 },
373 };
375 /**
376 * Throws an Error if obj doesn't conform to schema. That way you get a nice
377 * error message and a stack to help you figure out what went wrong, which you
378 * wouldn't get if this just returned true or false instead. There's still
379 * room for improvement in communicating validation failures, however.
380 *
381 * @param obj The object to validate.
382 * @param schema The schema that obj should conform to.
383 */
384 function validateObject(obj, schema) {
385 if (obj === undefined && !schema.required)
386 return;
387 if (typeof(schema.type) != "string")
388 throw schemaErr("'type' must be a string", schema);
389 if (objType(obj) != schema.type)
390 throw validationErr("Object is not of the expected type", obj, schema);
391 let validatorFnName = "validateObject_" + schema.type;
392 if (!(validatorFnName in this))
393 throw schemaErr("Validator function not defined for type", schema);
394 this[validatorFnName](obj, schema);
395 }
397 function validateObject_object(obj, schema) {
398 if (typeof(schema.properties) != "object")
399 // Don't care what obj's properties are.
400 return;
401 // First check that all the schema's properties match the object.
402 for (let prop in schema.properties)
403 validateObject(obj[prop], schema.properties[prop]);
404 // Now check that the object doesn't have any properties not in the schema.
405 for (let prop in obj)
406 if (!(prop in schema.properties))
407 throw validationErr("Object has property not in schema", obj, schema);
408 }
410 function validateObject_array(array, schema) {
411 if (typeof(schema.items) != "object")
412 // Don't care what the array's elements are.
413 return;
414 array.forEach(function (elt) validateObject(elt, schema.items));
415 }
417 function validateObject_string(str, schema) {}
418 function validateObject_boolean(bool, schema) {}
419 function validateObject_number(num, schema) {}
421 function validationErr(msg, obj, schema) {
422 return new Error("Validation error: " + msg +
423 ": object=" + JSON.stringify(obj) +
424 ", schema=" + JSON.stringify(schema));
425 }
427 function schemaErr(msg, schema) {
428 return new Error("Schema error: " + msg + ": " + JSON.stringify(schema));
429 }
431 function objType(obj) {
432 let type = typeof(obj);
433 if (type != "object")
434 return type;
435 if (Array.isArray(obj))
436 return "array";
437 if (obj === null)
438 return "null";
439 return type;
440 }