cookie-helper.sub.js (12252B)
1 // Set up exciting global variables for cookie tests. 2 (_ => { 3 var HOST = "{{host}}"; 4 var INSECURE_PORT = ":{{ports[http][0]}}"; 5 var SECURE_PORT = ":{{ports[https][0]}}"; 6 var CROSS_ORIGIN_HOST = "{{hosts[alt][]}}"; 7 8 window.INSECURE_ORIGIN = "http://" + HOST + INSECURE_PORT; 9 10 //For secure cookie verification 11 window.SECURE_ORIGIN = "https://" + HOST + SECURE_PORT; 12 13 //standard references 14 window.SECURE_SUBDOMAIN_ORIGIN = "https://{{domains[www1]}}" + SECURE_PORT; 15 window.SECURE_CROSS_SITE_ORIGIN = "https://" + CROSS_ORIGIN_HOST + SECURE_PORT; 16 window.CROSS_SITE_HOST = CROSS_ORIGIN_HOST; 17 18 // Set the global cookie name. 19 window.HTTP_COOKIE = "cookie_via_http"; 20 })(); 21 22 // A tiny helper which returns the result of fetching |url| with credentials. 23 function credFetch(url) { 24 return fetch(url, {"credentials": "include"}) 25 .then(response => { 26 if (response.status !== 200) { 27 throw new Error(response.statusText); 28 } 29 return response; 30 }); 31 } 32 33 // Returns a URL on |origin| which redirects to a given absolute URL. 34 function redirectTo(origin, url) { 35 return origin + "/cookies/resources/redirectWithCORSHeaders.py?status=307&location=" + encodeURIComponent(url); 36 } 37 38 // Returns a URL on |origin| which navigates the window to the given URL (by 39 // setting window.location). 40 function navigateTo(origin, url) { 41 return origin + "/cookies/resources/navigate.html?location=" + encodeURIComponent(url); 42 } 43 44 // Returns whether a cookie with name `name` with value `value` is in the cookie 45 // string (presumably obtained via document.cookie). 46 function cookieStringHasCookie(name, value, cookieString) { 47 return new RegExp(`(?:^|; )${name}=${value}(?:$|;)`).test(cookieString); 48 } 49 50 // Asserts that `document.cookie` contains or does not contain (according to 51 // the value of |present|) a cookie named |name| with a value of |value|. 52 function assert_dom_cookie(name, value, present) { 53 assert_equals(cookieStringHasCookie(name, value, document.cookie), present, "`" + name + "=" + value + "` in `document.cookie`"); 54 } 55 56 function assert_cookie(origin, obj, name, value, present) { 57 assert_equals(obj[name], present ? value : undefined, "`" + name + "=" + value + "` in request to `" + origin + "`."); 58 } 59 60 // Remove the cookie named |name| from |origin|, then set it on |origin| anew. 61 // If |origin| matches `self.origin`, also assert (via `document.cookie`) that 62 // the cookie was correctly removed and reset. 63 async function create_cookie(origin, name, value, extras) { 64 alert("Create_cookie: " + origin + "/cookies/resources/drop.py?name=" + name); 65 await credFetch(origin + "/cookies/resources/drop.py?name=" + name); 66 if (origin == self.origin) 67 assert_dom_cookie(name, value, false); 68 await credFetch(origin + "/cookies/resources/set.py?" + name + "=" + value + ";path=/;" + extras); 69 if (origin == self.origin) 70 assert_dom_cookie(name, value, true); 71 } 72 73 // 74 // Prefix-specific test helpers 75 // 76 window.dom_prefix_counter = 0; 77 function set_prefixed_cookie_via_dom_test(options) { 78 promise_test(t => { 79 var name = options.prefix + "prefixtestcookie"; 80 erase_cookie_from_js(name, options.params); 81 t.add_cleanup(() => erase_cookie_from_js(name, options.params)); 82 var value = "foo" + ++window.dom_prefix_counter; 83 document.cookie = name + "=" + value + ";" + options.params; 84 85 assert_dom_cookie(name, value, options.shouldExistInDOM); 86 87 return credFetch("/cookies/resources/list.py") 88 .then(r => r.json()) 89 .then(cookies => assert_equals(cookies[name], options.shouldExistViaHTTP ? value : undefined)); 90 }, options.title); 91 } 92 93 window.http_prefix_counter = 0; 94 function set_prefixed_cookie_via_http_test(options) { 95 promise_test(t => { 96 var name = options.prefix + "prefixtestcookie"; 97 var value = "bar" + ++window.http_prefix_counter; 98 99 t.add_cleanup(() => { 100 var cookie = name + "=0;expires=" + new Date(0).toUTCString() + ";" + 101 options.params; 102 103 return credFetch(options.origin + "/cookies/resources/set.py?" + cookie); 104 }); 105 106 return credFetch(options.origin + "/cookies/resources/set.py?" + name + "=" + value + ";" + options.params) 107 .then(_ => credFetch(options.origin + "/cookies/resources/list.py")) 108 .then(r => r.json()) 109 .then(cookies => assert_equals(cookies[name], options.shouldExistViaHTTP ? value : undefined)); 110 }, options.title); 111 } 112 113 // 114 // SameSite-specific test helpers: 115 // 116 117 // status for "network" cookies. 118 window.SameSiteStatus = { 119 CROSS_SITE: "cross-site", 120 LAX: "lax", 121 STRICT: "strict" 122 }; 123 // status for "document.cookie". 124 window.DomSameSiteStatus = { 125 CROSS_SITE: "cross-site", 126 SAME_SITE: "same-site", 127 }; 128 129 const wait_for_message = (type, origin) => { 130 return new Promise((resolve, reject) => { 131 window.addEventListener('message', e => { 132 if (origin && e.origin != origin) { 133 reject("Message from unexpected origin in wait_for_message:" + e.origin); 134 return; 135 } 136 137 if (e.data.type && e.data.type === type) 138 resolve(e); 139 }, { once: true }); 140 }); 141 }; 142 143 // Reset SameSite test cookies on |origin|. If |origin| matches `self.origin`, assert 144 // (via `document.cookie`) that they were properly removed and reset. 145 async function resetSameSiteCookies(origin, value) { 146 let w = window.open(origin + "/cookies/samesite/resources/puppet.html"); 147 try { 148 await wait_for_message("READY", origin); 149 w.postMessage({type: "drop", useOwnOrigin: true}, "*"); 150 await wait_for_message("drop-complete", origin); 151 if (origin == self.origin) { 152 assert_dom_cookie("samesite_strict", value, false); 153 assert_dom_cookie("samesite_lax", value, false); 154 assert_dom_cookie("samesite_none", value, false); 155 assert_dom_cookie("samesite_unspecified", value, false); 156 } 157 158 w.postMessage({type: "set", value: value, useOwnOrigin: true}, "*"); 159 await wait_for_message("set-complete", origin); 160 if (origin == self.origin) { 161 assert_dom_cookie("samesite_strict", value, true); 162 assert_dom_cookie("samesite_lax", value, true); 163 assert_dom_cookie("samesite_none", value, true); 164 assert_dom_cookie("samesite_unspecified", value, true); 165 } 166 } finally { 167 w.close(); 168 } 169 } 170 171 // Given an |expectedStatus| and |expectedValue|, assert the |cookies| contains 172 // the proper set of cookie names and values. Expects SameSite-Lax-by-default. 173 function verifySameSiteCookieState(expectedStatus, expectedValue, cookies, domCookieStatus) { 174 assert_equals(cookies["samesite_none"], expectedValue, "SameSite=None cookies are always sent."); 175 if (expectedStatus == SameSiteStatus.CROSS_SITE) { 176 assert_not_equals(cookies["samesite_strict"], expectedValue, "SameSite=Strict cookies are not sent with cross-site requests."); 177 assert_not_equals(cookies["samesite_lax"], expectedValue, "SameSite=Lax cookies are not sent with cross-site requests."); 178 assert_not_equals(cookies["samesite_unspecified"], expectedValue, "Unspecified-SameSite cookies are not sent with cross-site requests."); 179 } else if (expectedStatus == SameSiteStatus.LAX) { 180 assert_not_equals(cookies["samesite_strict"], expectedValue, "SameSite=Strict cookies are not sent with lax requests."); 181 assert_equals(cookies["samesite_lax"], expectedValue, "SameSite=Lax cookies are sent with lax requests."); 182 assert_equals(cookies["samesite_unspecified"], expectedValue, "Unspecified-SameSite cookies are are sent with lax requests.") 183 } else if (expectedStatus == SameSiteStatus.STRICT) { 184 assert_equals(cookies["samesite_strict"], expectedValue, "SameSite=Strict cookies are sent with strict requests."); 185 assert_equals(cookies["samesite_lax"], expectedValue, "SameSite=Lax cookies are sent with strict requests."); 186 assert_equals(cookies["samesite_unspecified"], expectedValue, "Unspecified-SameSite cookies are are sent with strict requests.") 187 } 188 189 if (cookies["domcookies"]) { 190 verifyDocumentCookieSameSite(domCookieStatus, expectedValue, cookies['domcookies']); 191 } 192 } 193 194 function verifyDocumentCookieSameSite(expectedStatus, expectedValue, domcookies) { 195 const cookies = domcookies.split(";") 196 .map(cookie => cookie.trim().split("=")) 197 .reduce((obj, cookie) => { 198 obj[cookie[0]] = cookie[1]; 199 return obj; 200 }, {}); 201 202 if (expectedStatus == DomSameSiteStatus.SAME_SITE) { 203 assert_equals(cookies["samesite_none"], expectedValue, "SameSite=None cookies are always included in document.cookie."); 204 assert_equals(cookies["samesite_unspecified"], expectedValue, "Unspecified-SameSite cookies are always included in document.cookie."); 205 assert_equals(cookies["samesite_strict"], expectedValue, "SameSite=Strict cookies are always included in document.cookie."); 206 assert_equals(cookies["samesite_lax"], expectedValue, "SameSite=Lax cookies are always included in document.cookie."); 207 } else if (expectedStatus == DomSameSiteStatus.CROSS_SITE) { 208 assert_equals(cookies["samesite_none"], expectedValue, "SameSite=None cookies are always included in document.cookie."); 209 assert_not_equals(cookies["samesite_unspecified"], expectedValue, "Unspecified-SameSite cookies are not included in document.cookie when cross-site."); 210 assert_not_equals(cookies["samesite_strict"], expectedValue, "SameSite=Strict cookies are not included in document.cookie when cross-site."); 211 assert_not_equals(cookies["samesite_lax"], expectedValue, "SameSite=Lax cookies are not included in document.cookie when cross-site."); 212 } 213 } 214 215 // 216 // LeaveSecureCookiesAlone-specific test helpers: 217 // 218 219 window.SecureStatus = { 220 INSECURE_COOKIE_ONLY: "1", 221 BOTH_COOKIES: "2", 222 }; 223 224 //Reset SameSite test cookies on |origin|. If |origin| matches `self.origin`, assert 225 //(via `document.cookie`) that they were properly removed and reset. 226 function resetSecureCookies(origin, value) { 227 return credFetch(origin + "/cookies/resources/dropSecure.py") 228 .then(_ => { 229 if (origin == self.origin) { 230 assert_dom_cookie("alone_secure", value, false); 231 assert_dom_cookie("alone_insecure", value, false); 232 } 233 }) 234 .then(_ => { 235 return credFetch(origin + "/cookie/resources/setSecure.py?" + value) 236 }) 237 } 238 239 // Reset SameSite=None test cookies on |origin|. If |origin| matches 240 // `self.origin`, assert (via `document.cookie`) that they were properly 241 // removed. 242 function resetSameSiteNoneCookies(origin, value) { 243 return credFetch(origin + "/cookies/resources/dropSameSiteNone.py") 244 .then(_ => { 245 if (origin == self.origin) { 246 assert_dom_cookie("samesite_none_insecure", value, false); 247 assert_dom_cookie("samesite_none_secure", value, false); 248 } 249 }) 250 .then(_ => { 251 return credFetch(origin + "/cookies/resources/setSameSiteNone.py?" + value); 252 }) 253 } 254 255 // Reset test cookies with multiple SameSite attributes on |origin|. 256 // If |origin| matches `self.origin`, assert (via `document.cookie`) 257 // that they were properly removed. 258 function resetSameSiteMultiAttributeCookies(origin, value) { 259 return credFetch(origin + "/cookies/resources/dropSameSiteMultiAttribute.py") 260 .then(_ => { 261 if (origin == self.origin) { 262 assert_dom_cookie("samesite_unsupported", value, false); 263 assert_dom_cookie("samesite_unsupported_none", value, false); 264 assert_dom_cookie("samesite_unsupported_lax", value, false); 265 assert_dom_cookie("samesite_unsupported_strict", value, false); 266 assert_dom_cookie("samesite_none_unsupported", value, false); 267 assert_dom_cookie("samesite_lax_unsupported", value, false); 268 assert_dom_cookie("samesite_strict_unsupported", value, false); 269 assert_dom_cookie("samesite_lax_none", value, false); 270 } 271 }) 272 .then(_ => { 273 return credFetch(origin + "/cookies/resources/setSameSiteMultiAttribute.py?" + value); 274 }) 275 } 276 277 // 278 // DOM based cookie manipulation APIs 279 // 280 281 // erase cookie value and set for expiration 282 function erase_cookie_from_js(name, params) { 283 document.cookie = `${name}=0; expires=${new Date(0).toUTCString()}; ${params};`; 284 var re = new RegExp("(?:^|; )" + name); 285 assert_equals(re.test(document.cookie), false, "Sanity check: " + name + " has been deleted."); 286 }