test_cookie.js (9596B)
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 file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 const { cookie } = ChromeUtils.importESModule( 6 "chrome://remote/content/marionette/cookie.sys.mjs" 7 ); 8 9 cookie.manager = { 10 cookies: [], 11 12 add( 13 domain, 14 path, 15 name, 16 value, 17 secure, 18 httpOnly, 19 session, 20 expiry, 21 originAttributes, 22 sameSite 23 ) { 24 if (name === "fail") { 25 throw new Error("An error occurred while adding cookie"); 26 } 27 let newCookie = { 28 host: domain, 29 path, 30 name, 31 value, 32 isSecure: secure, 33 isHttpOnly: httpOnly, 34 isSession: session, 35 expiry, 36 originAttributes, 37 sameSite, 38 }; 39 cookie.manager.cookies.push(newCookie); 40 41 return { 42 result: Ci.nsICookieValidation.eOK, 43 }; 44 }, 45 46 remove(host, name, path) { 47 for (let i = 0; i < this.cookies.length; ++i) { 48 let candidate = this.cookies[i]; 49 if ( 50 candidate.host === host && 51 candidate.name === name && 52 candidate.path === path 53 ) { 54 return this.cookies.splice(i, 1); 55 } 56 } 57 return false; 58 }, 59 60 getCookiesFromHost(host) { 61 let hostCookies = this.cookies.filter( 62 c => c.host === host || c.host === "." + host 63 ); 64 65 return hostCookies; 66 }, 67 }; 68 69 add_task(function test_fromJSON() { 70 // object 71 for (let invalidType of ["foo", 42, true, [], null, undefined]) { 72 Assert.throws( 73 () => cookie.fromJSON(invalidType), 74 /Expected "cookie" to be an object/ 75 ); 76 } 77 78 // name and value 79 for (let invalidType of [42, true, [], {}, null, undefined]) { 80 Assert.throws( 81 () => cookie.fromJSON({ name: invalidType }), 82 /Expected cookie "name" to be a string/ 83 ); 84 Assert.throws( 85 () => cookie.fromJSON({ name: "foo", value: invalidType }), 86 /Expected cookie "value" to be a string/ 87 ); 88 } 89 90 // domain 91 for (let invalidType of [42, true, [], {}, null]) { 92 let domainTest = { 93 name: "foo", 94 value: "bar", 95 domain: invalidType, 96 }; 97 Assert.throws( 98 () => cookie.fromJSON(domainTest), 99 /Expected cookie "domain" to be a string/ 100 ); 101 } 102 let domainTest = { 103 name: "foo", 104 value: "bar", 105 domain: "domain", 106 }; 107 let parsedCookie = cookie.fromJSON(domainTest); 108 equal(parsedCookie.domain, "domain"); 109 110 // path 111 for (let invalidType of [42, true, [], {}, null]) { 112 let pathTest = { 113 name: "foo", 114 value: "bar", 115 path: invalidType, 116 }; 117 Assert.throws( 118 () => cookie.fromJSON(pathTest), 119 /Expected cookie "path" to be a string/ 120 ); 121 } 122 123 // secure 124 for (let invalidType of ["foo", 42, [], {}, null]) { 125 let secureTest = { 126 name: "foo", 127 value: "bar", 128 secure: invalidType, 129 }; 130 Assert.throws( 131 () => cookie.fromJSON(secureTest), 132 /Expected cookie "secure" to be a boolean/ 133 ); 134 } 135 136 // httpOnly 137 for (let invalidType of ["foo", 42, [], {}, null]) { 138 let httpOnlyTest = { 139 name: "foo", 140 value: "bar", 141 httpOnly: invalidType, 142 }; 143 Assert.throws( 144 () => cookie.fromJSON(httpOnlyTest), 145 /Expected cookie "httpOnly" to be a boolean/ 146 ); 147 } 148 149 // expiry 150 for (let invalidType of [ 151 -1, 152 Number.MAX_SAFE_INTEGER + 1, 153 "foo", 154 true, 155 [], 156 {}, 157 null, 158 ]) { 159 let expiryTest = { 160 name: "foo", 161 value: "bar", 162 expiry: invalidType, 163 }; 164 Assert.throws( 165 () => cookie.fromJSON(expiryTest), 166 /Expected cookie "expiry" to be a positive integer/ 167 ); 168 } 169 170 // sameSite 171 for (let invalidType of ["foo", 42, [], {}, null]) { 172 const sameSiteTest = { 173 name: "foo", 174 value: "bar", 175 sameSite: invalidType, 176 }; 177 Assert.throws( 178 () => cookie.fromJSON(sameSiteTest), 179 /Expected cookie "sameSite" to be one of None,Lax,Strict/ 180 ); 181 } 182 183 // bare requirements 184 let bare = cookie.fromJSON({ name: "name", value: "value" }); 185 equal("name", bare.name); 186 equal("value", bare.value); 187 for (let missing of [ 188 "path", 189 "secure", 190 "httpOnly", 191 "session", 192 "expiry", 193 "sameSite", 194 ]) { 195 ok(!bare.hasOwnProperty(missing)); 196 } 197 198 // everything 199 let full = cookie.fromJSON({ 200 name: "name", 201 value: "value", 202 domain: ".domain", 203 path: "path", 204 secure: true, 205 httpOnly: true, 206 expiry: 42, 207 sameSite: "Lax", 208 }); 209 equal("name", full.name); 210 equal("value", full.value); 211 equal(".domain", full.domain); 212 equal("path", full.path); 213 equal(true, full.secure); 214 equal(true, full.httpOnly); 215 equal(42, full.expiry); 216 equal("Lax", full.sameSite); 217 }); 218 219 add_task(function test_add() { 220 cookie.manager.cookies = []; 221 222 for (let invalidType of [42, true, [], {}, null, undefined]) { 223 Assert.throws( 224 () => cookie.add({ name: invalidType }), 225 /Expected cookie "name" to be a string/ 226 ); 227 Assert.throws( 228 () => cookie.add({ name: "name", value: invalidType }), 229 /Expected cookie "value" to be a string/ 230 ); 231 Assert.throws( 232 () => cookie.add({ name: "name", value: "value", domain: invalidType }), 233 /Expected cookie "domain" to be a string/ 234 ); 235 } 236 237 cookie.add({ 238 name: "name", 239 value: "value", 240 domain: "domain", 241 }); 242 equal(1, cookie.manager.cookies.length); 243 equal("name", cookie.manager.cookies[0].name); 244 equal("value", cookie.manager.cookies[0].value); 245 equal(".domain", cookie.manager.cookies[0].host); 246 equal("/", cookie.manager.cookies[0].path); 247 Assert.greater( 248 cookie.manager.cookies[0].expiry, 249 new Date(Date.now()).getTime() / 1000 250 ); 251 252 cookie.add({ 253 name: "name2", 254 value: "value2", 255 domain: "domain2", 256 }); 257 equal(2, cookie.manager.cookies.length); 258 259 Assert.throws(() => { 260 let biscuit = { name: "name3", value: "value3", domain: "domain3" }; 261 cookie.add(biscuit, { restrictToHost: "other domain" }); 262 }, /Cookies may only be set for the current domain/); 263 264 cookie.add({ 265 name: "name4", 266 value: "value4", 267 domain: "my.domain:1234", 268 }); 269 equal(".my.domain", cookie.manager.cookies[2].host); 270 271 cookie.add({ 272 name: "name5", 273 value: "value5", 274 domain: "domain5", 275 path: "/foo/bar", 276 }); 277 equal("/foo/bar", cookie.manager.cookies[3].path); 278 279 cookie.add({ 280 name: "name6", 281 value: "value", 282 domain: ".domain", 283 }); 284 equal(".domain", cookie.manager.cookies[4].host); 285 286 const aDayInSec = 60 * 60 * 24; 287 const nowInSec = Math.round(Date.now() / 1000); 288 const tenDaysInTheFutureInSec = nowInSec + aDayInSec * 10; 289 290 cookie.add({ 291 name: "name6", 292 value: "value", 293 domain: ".domain", 294 expiry: tenDaysInTheFutureInSec, 295 }); 296 equal(tenDaysInTheFutureInSec * 1000, cookie.manager.cookies[5].expiry); 297 298 const two1000DaysInTheFutureInSec = nowInSec + aDayInSec * 2000; 299 cookie.add({ 300 name: "name6", 301 value: "value", 302 domain: ".domain", 303 expiry: two1000DaysInTheFutureInSec, 304 }); 305 306 const maxageCap = Services.prefs.getIntPref("network.cookie.maxageCap"); 307 if (maxageCap) { 308 // To avoid timing race condition, let's compare the expiry value with maxageCap +/- a few seconds. 309 const maxageCapMin = nowInSec + maxageCap - 3; /* secs */ 310 const maxageCapMax = nowInSec + maxageCap + 3; /* secs */ 311 312 // Max allowed value: 400 days. 313 Assert.greater(maxageCapMax * 1000, cookie.manager.cookies[6].expiry); 314 Assert.greater(cookie.manager.cookies[6].expiry, maxageCapMin * 1000); 315 } 316 317 const sameSiteMap = new Map([ 318 ["None", Ci.nsICookie.SAMESITE_NONE], 319 ["Lax", Ci.nsICookie.SAMESITE_LAX], 320 ["Strict", Ci.nsICookie.SAMESITE_STRICT], 321 ]); 322 323 Array.from(sameSiteMap.keys()).forEach((entry, index) => { 324 cookie.add({ 325 name: "name" + index, 326 value: "value", 327 domain: ".domain", 328 sameSite: entry, 329 }); 330 equal(sameSiteMap.get(entry), cookie.manager.cookies[7 + index].sameSite); 331 }); 332 333 Assert.throws(() => { 334 cookie.add({ name: "fail", value: "value6", domain: "domain6" }); 335 }, /UnableToSetCookieError/); 336 }); 337 338 add_task(function test_remove() { 339 cookie.manager.cookies = []; 340 341 let crumble = { 342 name: "test_remove", 343 value: "value", 344 domain: "domain", 345 path: "/custom/path", 346 }; 347 348 equal(0, cookie.manager.cookies.length); 349 cookie.add(crumble); 350 equal(1, cookie.manager.cookies.length); 351 352 cookie.remove(crumble); 353 equal(0, cookie.manager.cookies.length); 354 equal(undefined, cookie.manager.cookies[0]); 355 }); 356 357 add_task(function test_iter() { 358 cookie.manager.cookies = []; 359 let tomorrow = new Date(); 360 tomorrow.setHours(tomorrow.getHours() + 24); 361 362 cookie.add({ 363 expiry: tomorrow, 364 name: "0", 365 value: "", 366 domain: "foo.example.com", 367 }); 368 cookie.add({ 369 expiry: tomorrow, 370 name: "1", 371 value: "", 372 domain: "bar.example.com", 373 }); 374 375 let fooCookies = [...cookie.iter("foo.example.com")]; 376 equal(1, fooCookies.length); 377 equal(".foo.example.com", fooCookies[0].domain); 378 equal(true, fooCookies[0].hasOwnProperty("expiry")); 379 380 cookie.add({ 381 name: "aSessionCookie", 382 value: "", 383 domain: "session.com", 384 }); 385 386 let sessionCookies = [...cookie.iter("session.com")]; 387 equal(1, sessionCookies.length); 388 equal("aSessionCookie", sessionCookies[0].name); 389 equal(false, sessionCookies[0].hasOwnProperty("expiry")); 390 391 cookie.add({ 392 name: "2", 393 value: "", 394 domain: "samesite.example.com", 395 sameSite: "Lax", 396 }); 397 398 let sameSiteCookies = [...cookie.iter("samesite.example.com")]; 399 equal(1, sameSiteCookies.length); 400 equal("Lax", sameSiteCookies[0].sameSite); 401 });