Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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 |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | "use strict"; |
michael@0 | 6 | |
michael@0 | 7 | var BaseAssert = require("sdk/test/assert").Assert; |
michael@0 | 8 | |
michael@0 | 9 | /** |
michael@0 | 10 | * Whether or not given property descriptors are equivalent. They are |
michael@0 | 11 | * equivalent either if both are marked as "conflict" or "required" property |
michael@0 | 12 | * or if all the properties of descriptors are equal. |
michael@0 | 13 | * @param {Object} actual |
michael@0 | 14 | * @param {Object} expected |
michael@0 | 15 | */ |
michael@0 | 16 | function equivalentDescriptors(actual, expected) { |
michael@0 | 17 | return (actual.conflict && expected.conflict) || |
michael@0 | 18 | (actual.required && expected.required) || |
michael@0 | 19 | equalDescriptors(actual, expected); |
michael@0 | 20 | } |
michael@0 | 21 | |
michael@0 | 22 | function equalDescriptors(actual, expected) { |
michael@0 | 23 | return actual.get === expected.get && |
michael@0 | 24 | actual.set === expected.set && |
michael@0 | 25 | actual.value === expected.value && |
michael@0 | 26 | !!actual.enumerable === !!expected.enumerable && |
michael@0 | 27 | !!actual.configurable === !!expected.configurable && |
michael@0 | 28 | !!actual.writable === !!expected.writable; |
michael@0 | 29 | } |
michael@0 | 30 | |
michael@0 | 31 | /** |
michael@0 | 32 | * Whether or not given `target` array contains all the element |
michael@0 | 33 | * from a given `source` array. |
michael@0 | 34 | */ |
michael@0 | 35 | function containsSet(source, target) { |
michael@0 | 36 | return source.some(function(element) { |
michael@0 | 37 | return 0 > target.indexOf(element); |
michael@0 | 38 | }); |
michael@0 | 39 | } |
michael@0 | 40 | |
michael@0 | 41 | /** |
michael@0 | 42 | * Whether or not given two arrays contain all elements from another. |
michael@0 | 43 | */ |
michael@0 | 44 | function equivalentSets(source, target) { |
michael@0 | 45 | return containsSet(source, target) && containsSet(target, source); |
michael@0 | 46 | } |
michael@0 | 47 | |
michael@0 | 48 | /** |
michael@0 | 49 | * Finds name of the property from `source` property descriptor map, that |
michael@0 | 50 | * is not equivalent of the name named property in the `target` property |
michael@0 | 51 | * descriptor map. If not found `null` is returned instead. |
michael@0 | 52 | */ |
michael@0 | 53 | function findNonEquivalentPropertyName(source, target) { |
michael@0 | 54 | var value = null; |
michael@0 | 55 | Object.getOwnPropertyNames(source).some(function(key) { |
michael@0 | 56 | var areEquivalent = false; |
michael@0 | 57 | if (!equivalentDescriptors(source[key], target[key])) { |
michael@0 | 58 | value = key; |
michael@0 | 59 | areEquivalent = true; |
michael@0 | 60 | } |
michael@0 | 61 | return areEquivalent; |
michael@0 | 62 | }); |
michael@0 | 63 | return value; |
michael@0 | 64 | } |
michael@0 | 65 | |
michael@0 | 66 | var AssertDescriptor = { |
michael@0 | 67 | equalTraits: { |
michael@0 | 68 | value: function equivalentTraits(actual, expected, message) { |
michael@0 | 69 | var difference; |
michael@0 | 70 | var actualKeys = Object.getOwnPropertyNames(actual); |
michael@0 | 71 | var expectedKeys = Object.getOwnPropertyNames(expected); |
michael@0 | 72 | |
michael@0 | 73 | if (equivalentSets(actualKeys, expectedKeys)) { |
michael@0 | 74 | this.fail({ |
michael@0 | 75 | operator: "equalTraits", |
michael@0 | 76 | message: "Traits define different properties", |
michael@0 | 77 | actual: actualKeys.sort().join(","), |
michael@0 | 78 | expected: expectedKeys.sort().join(","), |
michael@0 | 79 | }); |
michael@0 | 80 | } |
michael@0 | 81 | else if ((difference = findNonEquivalentPropertyName(actual, expected))) { |
michael@0 | 82 | this.fail({ |
michael@0 | 83 | operator: "equalTraits", |
michael@0 | 84 | message: "Traits define non-equivalent property `" + difference + "`", |
michael@0 | 85 | actual: actual[difference], |
michael@0 | 86 | expected: expected[difference] |
michael@0 | 87 | }); |
michael@0 | 88 | } |
michael@0 | 89 | else { |
michael@0 | 90 | this.pass(message || "Traits are equivalent."); |
michael@0 | 91 | } |
michael@0 | 92 | } |
michael@0 | 93 | } |
michael@0 | 94 | }; |
michael@0 | 95 | |
michael@0 | 96 | exports.Assert = function Assert() { |
michael@0 | 97 | return Object.create(BaseAssert.apply(null, arguments), AssertDescriptor); |
michael@0 | 98 | }; |