Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 2 | // Helper functions for accessible states testing. |
michael@0 | 3 | // |
michael@0 | 4 | // requires: |
michael@0 | 5 | // common.js |
michael@0 | 6 | // role.js |
michael@0 | 7 | // |
michael@0 | 8 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 9 | |
michael@0 | 10 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 11 | // State constants |
michael@0 | 12 | |
michael@0 | 13 | // const STATE_BUSY is defined in common.js |
michael@0 | 14 | const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED; |
michael@0 | 15 | const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE; |
michael@0 | 16 | const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED; |
michael@0 | 17 | const STATE_DEFAULT = nsIAccessibleStates.STATE_DEFAULT; |
michael@0 | 18 | const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED; |
michael@0 | 19 | const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE; |
michael@0 | 20 | const STATE_FLOATING = nsIAccessibleStates.STATE_FLOATING; |
michael@0 | 21 | const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE; |
michael@0 | 22 | const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED; |
michael@0 | 23 | const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP; |
michael@0 | 24 | const STATE_INVALID = nsIAccessibleStates.STATE_INVALID; |
michael@0 | 25 | const STATE_INVISIBLE = nsIAccessibleStates.STATE_INVISIBLE; |
michael@0 | 26 | const STATE_LINKED = nsIAccessibleStates.STATE_LINKED; |
michael@0 | 27 | const STATE_MIXED = nsIAccessibleStates.STATE_MIXED; |
michael@0 | 28 | const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE; |
michael@0 | 29 | const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN; |
michael@0 | 30 | const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED; |
michael@0 | 31 | const STATE_PROTECTED = nsIAccessibleStates.STATE_PROTECTED; |
michael@0 | 32 | const STATE_READONLY = nsIAccessibleStates.STATE_READONLY; |
michael@0 | 33 | const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED; |
michael@0 | 34 | const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE; |
michael@0 | 35 | const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED; |
michael@0 | 36 | const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED; |
michael@0 | 37 | const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE; |
michael@0 | 38 | |
michael@0 | 39 | const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE; |
michael@0 | 40 | const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT; |
michael@0 | 41 | const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE; |
michael@0 | 42 | const EXT_STATE_ENABLED = nsIAccessibleStates.EXT_STATE_ENABLED; |
michael@0 | 43 | const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE; |
michael@0 | 44 | const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL; |
michael@0 | 45 | const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE; |
michael@0 | 46 | const EXT_STATE_PINNED = nsIAccessibleStates.EXT_STATE_PINNED; |
michael@0 | 47 | const EXT_STATE_SENSITIVE = nsIAccessibleStates.EXT_STATE_SENSITIVE; |
michael@0 | 48 | const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE; |
michael@0 | 49 | const EXT_STATE_STALE = nsIAccessibleStates.EXT_STATE_STALE; |
michael@0 | 50 | const EXT_STATE_SUPPORTS_AUTOCOMPLETION = |
michael@0 | 51 | nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION; |
michael@0 | 52 | const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL; |
michael@0 | 53 | |
michael@0 | 54 | const kOrdinalState = 0; |
michael@0 | 55 | const kExtraState = 1; |
michael@0 | 56 | |
michael@0 | 57 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 58 | // Test functions |
michael@0 | 59 | |
michael@0 | 60 | /** |
michael@0 | 61 | * Tests the states and extra states of the given accessible. |
michael@0 | 62 | * Also tests for unwanted states and extra states. |
michael@0 | 63 | * In addition, the function performs a few plausibility checks derived from the |
michael@0 | 64 | * sstates and extra states passed in. |
michael@0 | 65 | * |
michael@0 | 66 | * @param aAccOrElmOrID The accessible, DOM element or ID to be tested. |
michael@0 | 67 | * @param aState The state bits that are wanted. |
michael@0 | 68 | * @param aExtraState The extra state bits that are wanted. |
michael@0 | 69 | * @param aAbsentState State bits that are not wanted. |
michael@0 | 70 | * @param aAbsentExtraState Extra state bits that are not wanted. |
michael@0 | 71 | * @param aTestName The test name. |
michael@0 | 72 | */ |
michael@0 | 73 | function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState, |
michael@0 | 74 | aAbsentExtraState, aTestName) |
michael@0 | 75 | { |
michael@0 | 76 | var [state, extraState] = getStates(aAccOrElmOrID); |
michael@0 | 77 | var role = getRole(aAccOrElmOrID); |
michael@0 | 78 | var id = prettyName(aAccOrElmOrID) + (aTestName ? " [" + aTestName + "]": ""); |
michael@0 | 79 | |
michael@0 | 80 | // Primary test. |
michael@0 | 81 | if (aState) { |
michael@0 | 82 | isState(state & aState, aState, false, |
michael@0 | 83 | "wrong state bits for " + id + "!"); |
michael@0 | 84 | } |
michael@0 | 85 | |
michael@0 | 86 | if (aExtraState) |
michael@0 | 87 | isState(extraState & aExtraState, aExtraState, true, |
michael@0 | 88 | "wrong extra state bits for " + id + "!"); |
michael@0 | 89 | |
michael@0 | 90 | if (aAbsentState) |
michael@0 | 91 | isState(state & aAbsentState, 0, false, |
michael@0 | 92 | "state bits should not be present in ID " + id + "!"); |
michael@0 | 93 | |
michael@0 | 94 | if (aAbsentExtraState) |
michael@0 | 95 | isState(extraState & aAbsentExtraState, 0, true, |
michael@0 | 96 | "extraState bits should not be present in ID " + id + "!"); |
michael@0 | 97 | |
michael@0 | 98 | // Additional test. |
michael@0 | 99 | |
michael@0 | 100 | // focused/focusable |
michael@0 | 101 | if (state & STATE_FOCUSED) |
michael@0 | 102 | isState(state & STATE_FOCUSABLE, STATE_FOCUSABLE, false, |
michael@0 | 103 | "Focussed " + id + " must be focusable!"); |
michael@0 | 104 | |
michael@0 | 105 | if (aAbsentState && (aAbsentState & STATE_FOCUSABLE)) { |
michael@0 | 106 | isState(state & STATE_FOCUSED, 0, false, |
michael@0 | 107 | "Not focusable " + id + " must be not focused!"); |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | // multiline/singleline |
michael@0 | 111 | if (extraState & EXT_STATE_MULTI_LINE) |
michael@0 | 112 | isState(extraState & EXT_STATE_SINGLE_LINE, 0, true, |
michael@0 | 113 | "Multiline " + id + " cannot be singleline!"); |
michael@0 | 114 | |
michael@0 | 115 | if (extraState & EXT_STATE_SINGLE_LINE) |
michael@0 | 116 | isState(extraState & EXT_STATE_MULTI_LINE, 0, true, |
michael@0 | 117 | "Singleline " + id + " cannot be multiline!"); |
michael@0 | 118 | |
michael@0 | 119 | // expanded/collapsed/expandable |
michael@0 | 120 | if (state & STATE_COLLAPSED || state & STATE_EXPANDED) |
michael@0 | 121 | isState(extraState & EXT_STATE_EXPANDABLE, EXT_STATE_EXPANDABLE, true, |
michael@0 | 122 | "Collapsed or expanded " + id + " must be expandable!"); |
michael@0 | 123 | |
michael@0 | 124 | if (state & STATE_COLLAPSED) |
michael@0 | 125 | isState(state & STATE_EXPANDED, 0, false, |
michael@0 | 126 | "Collapsed " + id + " cannot be expanded!"); |
michael@0 | 127 | |
michael@0 | 128 | if (state & STATE_EXPANDED) |
michael@0 | 129 | isState(state & STATE_COLLAPSED, 0, false, |
michael@0 | 130 | "Expanded " + id + " cannot be collapsed!"); |
michael@0 | 131 | |
michael@0 | 132 | if (aAbsentState && (extraState & EXT_STATE_EXPANDABLE)) { |
michael@0 | 133 | if (aAbsentState & STATE_EXPANDED) { |
michael@0 | 134 | isState(state & STATE_COLLAPSED, STATE_COLLAPSED, false, |
michael@0 | 135 | "Not expanded " + id + " must be collapsed!"); |
michael@0 | 136 | } else if (aAbsentState & STATE_COLLAPSED) { |
michael@0 | 137 | isState(state & STATE_EXPANDED, STATE_EXPANDED, false, |
michael@0 | 138 | "Not collapsed " + id + " must be expanded!"); |
michael@0 | 139 | } |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | // checked/mixed/checkable |
michael@0 | 143 | if (state & STATE_CHECKED || state & STATE_MIXED && |
michael@0 | 144 | role != ROLE_TOGGLE_BUTTON && role != ROLE_PROGRESSBAR) |
michael@0 | 145 | isState(state & STATE_CHECKABLE, STATE_CHECKABLE, false, |
michael@0 | 146 | "Checked or mixed element must be checkable!"); |
michael@0 | 147 | |
michael@0 | 148 | if (state & STATE_CHECKED) |
michael@0 | 149 | isState(state & STATE_MIXED, 0, false, |
michael@0 | 150 | "Checked element cannot be state mixed!"); |
michael@0 | 151 | |
michael@0 | 152 | if (state & STATE_MIXED) |
michael@0 | 153 | isState(state & STATE_CHECKED, 0, false, |
michael@0 | 154 | "Mixed element cannot be state checked!"); |
michael@0 | 155 | |
michael@0 | 156 | // selected/selectable |
michael@0 | 157 | if (state & STATE_SELECTED) { |
michael@0 | 158 | isState(state & STATE_SELECTABLE, STATE_SELECTABLE, false, |
michael@0 | 159 | "Selected element must be selectable!"); |
michael@0 | 160 | } |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | /** |
michael@0 | 164 | * Tests an acessible and its sub tree for the passed in state bits. |
michael@0 | 165 | * Used to make sure that states are propagated to descendants, for example the |
michael@0 | 166 | * STATE_UNAVAILABLE from a container to its children. |
michael@0 | 167 | * |
michael@0 | 168 | * @param aAccOrElmOrID The accessible, DOM element or ID to be tested. |
michael@0 | 169 | * @param aState The state bits that are wanted. |
michael@0 | 170 | * @param aExtraState The extra state bits that are wanted. |
michael@0 | 171 | * @param aAbsentState State bits that are not wanted. |
michael@0 | 172 | */ |
michael@0 | 173 | function testStatesInSubtree(aAccOrElmOrID, aState, aExtraState, aAbsentState) |
michael@0 | 174 | { |
michael@0 | 175 | // test accessible and its subtree for propagated states. |
michael@0 | 176 | var acc = getAccessible(aAccOrElmOrID); |
michael@0 | 177 | if (!acc) |
michael@0 | 178 | return; |
michael@0 | 179 | |
michael@0 | 180 | if (getRole(acc) != ROLE_TEXT_LEAF) |
michael@0 | 181 | // Right now, text leafs don't get tested because the states are not being |
michael@0 | 182 | // propagated. |
michael@0 | 183 | testStates(acc, aState, aExtraState, aAbsentState); |
michael@0 | 184 | |
michael@0 | 185 | // Iterate over its children to see if the state got propagated. |
michael@0 | 186 | var children = null; |
michael@0 | 187 | try { |
michael@0 | 188 | children = acc.children; |
michael@0 | 189 | } catch(e) {} |
michael@0 | 190 | ok(children, "Could not get children for " + aAccOrElmOrID +"!"); |
michael@0 | 191 | |
michael@0 | 192 | if (children) { |
michael@0 | 193 | for (var i = 0; i < children.length; i++) { |
michael@0 | 194 | var childAcc = children.queryElementAt(i, nsIAccessible); |
michael@0 | 195 | testStatesInSubtree(childAcc, aState, aExtraState, aAbsentState); |
michael@0 | 196 | } |
michael@0 | 197 | } |
michael@0 | 198 | } |
michael@0 | 199 | |
michael@0 | 200 | function getStringStates(aAccOrElmOrID) |
michael@0 | 201 | { |
michael@0 | 202 | var [state, extraState] = getStates(aAccOrElmOrID); |
michael@0 | 203 | return statesToString(state, extraState); |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | function getStates(aAccOrElmOrID) |
michael@0 | 207 | { |
michael@0 | 208 | var acc = getAccessible(aAccOrElmOrID); |
michael@0 | 209 | if (!acc) |
michael@0 | 210 | return [0, 0]; |
michael@0 | 211 | |
michael@0 | 212 | var state = {}, extraState = {}; |
michael@0 | 213 | acc.getState(state, extraState); |
michael@0 | 214 | |
michael@0 | 215 | return [state.value, extraState.value]; |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | /** |
michael@0 | 219 | * Return true if the accessible has given states. |
michael@0 | 220 | */ |
michael@0 | 221 | function hasState(aAccOrElmOrID, aState, aExtraState) |
michael@0 | 222 | { |
michael@0 | 223 | var [state, exstate] = getStates(aAccOrElmOrID); |
michael@0 | 224 | return (aState ? state & aState : true) && |
michael@0 | 225 | (aExtraState ? exstate & aExtraState : true); |
michael@0 | 226 | } |
michael@0 | 227 | |
michael@0 | 228 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 229 | // Private implementation details |
michael@0 | 230 | |
michael@0 | 231 | /** |
michael@0 | 232 | * Analogy of SimpleTest.is function used to compare states. |
michael@0 | 233 | */ |
michael@0 | 234 | function isState(aState1, aState2, aIsExtraStates, aMsg) |
michael@0 | 235 | { |
michael@0 | 236 | if (aState1 == aState2) { |
michael@0 | 237 | ok(true, aMsg); |
michael@0 | 238 | return; |
michael@0 | 239 | } |
michael@0 | 240 | |
michael@0 | 241 | var got = "0"; |
michael@0 | 242 | if (aState1) { |
michael@0 | 243 | got = statesToString(aIsExtraStates ? 0 : aState1, |
michael@0 | 244 | aIsExtraStates ? aState1 : 0); |
michael@0 | 245 | } |
michael@0 | 246 | |
michael@0 | 247 | var expected = "0"; |
michael@0 | 248 | if (aState2) { |
michael@0 | 249 | expected = statesToString(aIsExtraStates ? 0 : aState2, |
michael@0 | 250 | aIsExtraStates ? aState2 : 0); |
michael@0 | 251 | } |
michael@0 | 252 | |
michael@0 | 253 | ok(false, aMsg + "got '" + got + "', expected '" + expected + "'"); |
michael@0 | 254 | } |