browser_storage_values.js (7909B)
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/. */ 4 5 // Test to verify that the values shown in sidebar are correct 6 7 // Format: [ 8 // <id of the table item to click> or <id array for tree item to select> or 9 // null do click nothing, 10 // null to skip checking value in variables view or a key value pair object 11 // which will be asserted to exist in the storage sidebar, 12 // true if the check is to be made in the parsed value section 13 // ] 14 15 "use strict"; 16 17 const LONG_WORD = "a".repeat(1000); 18 19 const testCases = [ 20 [ 21 getCookieId("cs2", ".example.org", "/"), 22 [ 23 { name: "cs2", value: "sessionCookie" }, 24 { name: "cs2.Path", value: "/" }, 25 { name: "cs2.HostOnly", value: "false" }, 26 { name: "cs2.HttpOnly", value: "false" }, 27 { name: "cs2.Domain", value: ".example.org" }, 28 { name: "cs2.Expires / Max-Age", value: "Session" }, 29 { name: "cs2.Secure", value: "false" }, 30 ], 31 ], 32 [ 33 getCookieId("c1", "test1.example.org", "/browser"), 34 [ 35 { name: "c1", value: JSON.stringify(["foo", "Bar", { foo: "Bar" }]) }, 36 { name: "c1.Path", value: "/browser" }, 37 { name: "c1.HostOnly", value: "true" }, 38 { name: "c1.HttpOnly", value: "false" }, 39 { name: "c1.Domain", value: "test1.example.org" }, 40 { 41 name: "c1.Expires / Max-Age", 42 value: new Date(2000000000000).toUTCString(), 43 }, 44 { name: "c1.Secure", value: "false" }, 45 ], 46 ], 47 [ 48 null, 49 [ 50 { name: "c1", value: "Array" }, 51 { name: "c1.0", value: "foo" }, 52 { name: "c1.1", value: "Bar" }, 53 { name: "c1.2", value: "Object" }, 54 { name: "c1.2.foo", value: "Bar" }, 55 ], 56 true, 57 ], 58 [ 59 getCookieId( 60 "c_encoded", 61 "test1.example.org", 62 "/browser/devtools/client/storage/test" 63 ), 64 [ 65 { 66 name: "c_encoded", 67 value: encodeURIComponent(JSON.stringify({ foo: { foo1: "bar" } })), 68 }, 69 ], 70 ], 71 [ 72 null, 73 [ 74 { name: "c_encoded", value: "Object" }, 75 { name: "c_encoded.foo", value: "Object" }, 76 { name: "c_encoded.foo.foo1", value: "bar" }, 77 ], 78 true, 79 ], 80 [["localStorage", "https://test1.example.org"]], 81 ["ls2", [{ name: "ls2", value: "foobar-2" }]], 82 [ 83 "ls1", 84 [ 85 { 86 name: "ls1", 87 value: JSON.stringify({ 88 es6: "for", 89 the: "win", 90 baz: [ 91 0, 92 2, 93 3, 94 { 95 deep: "down", 96 nobody: "cares", 97 }, 98 ], 99 }), 100 }, 101 ], 102 ], 103 [ 104 null, 105 [ 106 { name: "ls1", value: "Object" }, 107 { name: "ls1.es6", value: "for" }, 108 { name: "ls1.the", value: "win" }, 109 { name: "ls1.baz", value: "Array" }, 110 { name: "ls1.baz.0", value: "0" }, 111 { name: "ls1.baz.1", value: "2" }, 112 { name: "ls1.baz.2", value: "3" }, 113 { name: "ls1.baz.3", value: "Object" }, 114 { name: "ls1.baz.3.deep", value: "down" }, 115 { name: "ls1.baz.3.nobody", value: "cares" }, 116 ], 117 true, 118 ], 119 ["ls3", [{ name: "ls3", value: "http://foobar.com/baz.php" }]], 120 [ 121 null, 122 [{ name: "ls3", value: "http://foobar.com/baz.php", dontMatch: true }], 123 true, 124 ], 125 ["ls4", [{ name: "ls4", value: "0x1" }], false], 126 [["sessionStorage", "https://test1.example.org"]], 127 ["ss1", [{ name: "ss1", value: "This#is#an#array" }]], 128 [ 129 null, 130 [ 131 { name: "ss1", value: "Array" }, 132 { name: "ss1.0", value: "This" }, 133 { name: "ss1.1", value: "is" }, 134 { name: "ss1.2", value: "an" }, 135 { name: "ss1.3", value: "array" }, 136 ], 137 true, 138 ], 139 [ 140 "ss2", 141 [ 142 { name: "ss2", value: "Array" }, 143 { name: "ss2.0", value: "This" }, 144 { name: "ss2.1", value: "is" }, 145 { name: "ss2.2", value: "another" }, 146 { name: "ss2.3", value: "array" }, 147 ], 148 true, 149 ], 150 [ 151 "ss3", 152 [ 153 { name: "ss3", value: "Object" }, 154 { name: "ss3.this", value: "is" }, 155 { name: "ss3.an", value: "object" }, 156 { name: "ss3.foo", value: "bar" }, 157 ], 158 true, 159 ], 160 [ 161 "ss4", 162 [ 163 { name: "ss4", value: "Array" }, 164 { name: "ss4.0", value: "" }, 165 { name: "ss4.1", value: "array" }, 166 { name: "ss4.2", value: "" }, 167 { name: "ss4.3", value: "with" }, 168 { name: "ss4.4", value: "empty" }, 169 { name: "ss4.5", value: "items" }, 170 ], 171 true, 172 ], 173 [ 174 "ss5", 175 [ 176 { name: "ss5", value: "Array" }, 177 { name: "ss5.0", value: LONG_WORD }, 178 { name: "ss5.1", value: LONG_WORD }, 179 { name: "ss5.2", value: LONG_WORD }, 180 { name: "ss5.3", value: `${LONG_WORD}&${LONG_WORD}` }, 181 { name: "ss5.4", value: `${LONG_WORD}&${LONG_WORD}` }, 182 ], 183 true, 184 ], 185 [["indexedDB", "https://test1.example.org", "idb1 (default)", "obj1"]], 186 [ 187 1, 188 [ 189 { 190 name: 1, 191 value: JSON.stringify({ id: 1, name: "foo", email: "foo@bar.com" }), 192 }, 193 ], 194 ], 195 [ 196 null, 197 [ 198 { name: "1.id", value: "1" }, 199 { name: "1.name", value: "foo" }, 200 { name: "1.email", value: "foo@bar.com" }, 201 ], 202 true, 203 ], 204 [["indexedDB", "https://test1.example.org", "idb1 (default)", "obj2"]], 205 [ 206 1, 207 [ 208 { 209 name: 1, 210 value: JSON.stringify({ 211 id2: 1, 212 name: "foo", 213 email: "foo@bar.com", 214 extra: "baz".repeat(10000), 215 }), 216 }, 217 ], 218 ], 219 [ 220 null, 221 [ 222 { name: "1.id2", value: "1" }, 223 { name: "1.name", value: "foo" }, 224 { name: "1.email", value: "foo@bar.com" }, 225 { name: "1.extra", value: "baz".repeat(10000) }, 226 ], 227 true, 228 ], 229 ]; 230 231 add_task(async function () { 232 await SpecialPowers.pushPrefEnv({ 233 set: [["network.cookie.maxageCap", 0]], 234 }); 235 236 await openTabAndSetupStorage( 237 MAIN_DOMAIN_SECURED + "storage-complex-values.html" 238 ); 239 240 gUI.tree.expandAll(); 241 242 for (const item of testCases) { 243 info("clicking for item " + item); 244 const [path, ruleArray, parsed] = item; 245 const start = performance.now(); 246 247 if (Array.isArray(path)) { 248 await selectTreeItem(path); 249 continue; 250 } else if (path) { 251 await selectTableItem(path); 252 } 253 254 // Parsing "0x1" used to be very slow and memory intensive. 255 // Check that each test case completes in less than 15000ms. 256 const time = performance.now() - start; 257 Assert.less( 258 time, 259 15000, 260 `item ${item} completed in less than 15000ms ${time}` 261 ); 262 263 await findVariableViewProperties(ruleArray, parsed); 264 } 265 266 info( 267 `Check that the "Copy" context menu entry in the VariableView works as expected` 268 ); 269 await selectTreeItem(["cookies", "https://test1.example.org"]); 270 await selectTableItem(getCookieId("cs2", ".example.org", "/")); 271 272 const contextMenu = gPanelWindow.document.querySelector( 273 "#variable-view-popup" 274 ); 275 const contextMenuCopyItem = contextMenu.querySelector( 276 "#variable-view-popup-copy" 277 ); 278 279 const variableViewRootNodeValueEl = await waitFor(() => { 280 const el = gUI.sidebar.querySelector("label.value.token-string"); 281 if (!el || el.value !== `"sessionCookie"`) { 282 return false; 283 } 284 285 return el; 286 }); 287 288 // Focus the row so the context menu is enabled 289 variableViewRootNodeValueEl.closest(".variable-or-property").focus(); 290 291 const onContextMenuShown = once(contextMenu, "popupshown"); 292 synthesizeContextMenuEvent(variableViewRootNodeValueEl); 293 await onContextMenuShown; 294 ok(true, "Context menu is shown"); 295 296 info("Click on the Copy entry"); 297 await waitForClipboardPromise( 298 () => contextMenuCopyItem.click(), 299 `cs2:"sessionCookie"` 300 ); 301 302 info("Close context menu"); 303 const onContextMenuHidden = once(contextMenu, "popuphidden"); 304 DevToolsUtils.executeSoon(() => contextMenu.hidePopup()); 305 await onContextMenuHidden; 306 });