browser_chips_partition_cap_child.js (11109B)
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 const URL_EXAMPLE = 6 "https://example.com/browser/netwerk/cookie/test/browser/cookie-set-dom.html"; 7 8 registerCleanupFunction(() => { 9 Services.prefs.clearUserPref("network.cookie.cookieBehavior"); 10 Services.prefs.clearUserPref( 11 "network.cookie.cookieBehavior.optInPartitioning" 12 ); 13 Services.prefs.clearUserPref("network.cookie.chips.partitionLimitEnabled"); 14 Services.prefs.clearUserPref( 15 "network.cookie.chips.partitionLimitByteCapacity" 16 ); 17 Services.prefs.clearUserPref("network.cookie.CHIPS.enabled"); 18 Services.prefs.clearUserPref("network.cookie.chips.partitionLimitDryRun"); 19 Services.cookies.removeAll(); 20 }); 21 22 // enable chips and chips partition limit 23 add_setup(async () => { 24 Services.prefs.setIntPref("network.cookie.cookieBehavior", 5); 25 Services.prefs.setBoolPref( 26 "network.cookie.cookieBehavior.optInPartitioning", 27 true 28 ); 29 Services.prefs.setBoolPref("network.cookie.CHIPS.enabled", true); 30 Services.prefs.setBoolPref( 31 "network.cookie.chips.partitionLimitEnabled", 32 true 33 ); 34 Services.prefs.setBoolPref( 35 "network.cookie.chips.partitionLimitDryRun", 36 false 37 ); 38 }); 39 40 const PATH = "/browser/netwerk/cookie/test/browser/"; 41 const PATH_EMPTY = PATH + "file_empty.html"; 42 43 const FIRST_PARTY = "example.com"; 44 const THIRD_PARTY = "example.org"; 45 46 const URL_DOCUMENT_FIRSTPARTY = "https://" + FIRST_PARTY + PATH_EMPTY; 47 const URL_DOCUMENT_THIRDPARTY = "https://" + THIRD_PARTY + PATH_EMPTY; 48 49 const COOKIE_PARTITIONED = 50 "cookie=partitioned; Partitioned; Secure; SameSite=None;"; 51 const COOKIE_UNPARTITIONED = "cookie=unpartitioned; Secure; SameSite=None;"; 52 53 function createOriginAttributes(partitionKey) { 54 return JSON.stringify({ 55 firstPartyDomain: "", 56 geckoViewSessionContextId: "", 57 inIsolatedMozBrowser: false, 58 partitionKey, 59 privateBrowsingId: 0, 60 userContextId: 0, 61 }); 62 } 63 64 function createPartitionKey(url) { 65 let uri = NetUtil.newURI(url); 66 return `(${uri.scheme},${uri.host})`; 67 } 68 69 function createSameSiteForeignPartitionKey(url) { 70 let uri = NetUtil.newURI(url); 71 return `(${uri.scheme},${uri.host},f)`; 72 } 73 74 // OriginAttributes used to access partitioned and unpartitioned cookie jars 75 // in all tests. 76 const partitionedOAs = createOriginAttributes( 77 createPartitionKey(URL_DOCUMENT_FIRSTPARTY) 78 ); 79 const partitionedSameSiteForeignOAs = createOriginAttributes( 80 createSameSiteForeignPartitionKey(URL_DOCUMENT_FIRSTPARTY) 81 ); 82 const unpartitionedOAs = createOriginAttributes(""); 83 84 // cookie bytes >= 4013 85 var staticCount = 0; 86 function uniqueLargeCookie(partitioned) { 87 ++staticCount; 88 var cookie = "largecookie" 89 .concat(staticCount) 90 .concat("=") 91 .concat("1234567890".repeat(400)) 92 .concat("; Secure; SameSite=None;"); 93 if (partitioned) { 94 return cookie.concat("; Partitioned"); 95 } 96 return cookie; 97 } 98 99 async function setCookieViaDomOnChild(browser, cookie) { 100 await SpecialPowers.spawn(browser, [cookie], cookie => { 101 content.document.cookie = cookie; 102 }); 103 } 104 105 // child-side document sets are byte-limited 106 add_task(async function test_chips_limit_document_first_party_child() { 107 const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY); 108 const browser = gBrowser.getBrowserForTab(tab); 109 await BrowserTestUtils.browserLoaded(browser); 110 111 // Set partitioned and unpartitioned cookie from document child-side 112 // 10240 * 1.2 -> 12288 113 // fourth will cause purge (> 12288 Bytes) 114 // and we will purge down to the soft maximum (quota) (10240 Bytes) 115 await setCookieViaDomOnChild(browser, uniqueLargeCookie(true)); 116 await setCookieViaDomOnChild(browser, uniqueLargeCookie(true)); 117 await setCookieViaDomOnChild(browser, uniqueLargeCookie(true)); 118 await setCookieViaDomOnChild(browser, uniqueLargeCookie(true)); 119 120 await setCookieViaDomOnChild(browser, uniqueLargeCookie(false)); 121 await setCookieViaDomOnChild(browser, uniqueLargeCookie(false)); 122 await setCookieViaDomOnChild(browser, uniqueLargeCookie(false)); 123 await setCookieViaDomOnChild(browser, uniqueLargeCookie(false)); 124 125 // Get cookies from partitioned jar 126 let partitioned = Services.cookies.getCookiesWithOriginAttributes( 127 partitionedOAs, 128 FIRST_PARTY 129 ); 130 131 // Get cookies from unpartitioned jar 132 let unpartitioned = Services.cookies.getCookiesWithOriginAttributes( 133 unpartitionedOAs, 134 FIRST_PARTY 135 ); 136 137 // check that partitioned cookies are purged at maximum 138 // check that unpartitioned cookies are not 139 Assert.equal(partitioned.length, 2); 140 Assert.equal(unpartitioned.length, 4); 141 142 // Cleanup 143 BrowserTestUtils.removeTab(tab); 144 Services.cookies.removeAll(); 145 }); 146 147 // chips partitioned 3rd party cookies are subject to chips partition limit 148 add_task(async function test_chips_limit_third_party() { 149 const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY); 150 const browser = gBrowser.getBrowserForTab(tab); 151 await BrowserTestUtils.browserLoaded(browser); 152 153 // Spawn document bc 154 await SpecialPowers.spawn(browser, [URL_DOCUMENT_THIRDPARTY], async url => { 155 let ifr = content.document.createElement("iframe"); 156 let loadPromise = ContentTaskUtils.waitForEvent(ifr, "load"); 157 ifr.src = url; 158 content.document.body.appendChild(ifr); 159 await loadPromise; 160 161 // Spawn iframe bc 162 await SpecialPowers.spawn(await ifr.browsingContext, [], async () => { 163 function largeCookie(partitioned, index) { 164 var cookie = "largecookie" 165 .concat(index) 166 .concat("=") 167 .concat("1234567890".repeat(400)) 168 .concat("; Secure; SameSite=None;"); 169 if (partitioned) { 170 return cookie.concat("; Partitioned"); 171 } 172 return cookie; 173 } 174 content.document.cookie = largeCookie(true, 0); 175 content.document.cookie = largeCookie(true, 1); 176 content.document.cookie = largeCookie(true, 2); 177 content.document.cookie = largeCookie(true, 3); 178 content.document.cookie = largeCookie(false, 0); 179 content.document.cookie = largeCookie(false, 1); 180 content.document.cookie = largeCookie(false, 2); 181 content.document.cookie = largeCookie(false, 3); 182 }); 183 }); 184 185 // Get cookies from partitioned jar 186 let partitioned = Services.cookies.getCookiesWithOriginAttributes( 187 partitionedOAs, 188 THIRD_PARTY 189 ); 190 // Get cookies from unpartitioned jar 191 let unpartitioned = Services.cookies.getCookiesWithOriginAttributes( 192 unpartitionedOAs, 193 THIRD_PARTY 194 ); 195 196 // third party partitioned cookies are subject to the byte limit 197 // while unpartitioned are blocked 198 Assert.equal(partitioned.length, 2); 199 Assert.equal(unpartitioned.length, 0); 200 201 // Cleanup 202 BrowserTestUtils.removeTab(tab); 203 Services.cookies.removeAll(); 204 }); 205 206 // same-site foreign partitioned cookies are subject to the limit 207 // This is ABA scenario: A contains B iframe, which contains A iframe 208 add_task(async function test_chips_limit_samesite_foreign() { 209 const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY); 210 const browser = gBrowser.getBrowserForTab(tab); 211 await BrowserTestUtils.browserLoaded(browser); 212 213 // content process (top-level) 214 await SpecialPowers.spawn( 215 browser, 216 [URL_DOCUMENT_THIRDPARTY, URL_DOCUMENT_FIRSTPARTY], 217 async (url, urlInner) => { 218 let ifr = content.document.createElement("iframe"); 219 let loadPromise = ContentTaskUtils.waitForEvent(ifr, "load"); 220 ifr.src = url; 221 content.document.body.appendChild(ifr); 222 await loadPromise; 223 224 // Spawn iframe bc (third-party to top-level) 225 await SpecialPowers.spawn( 226 await ifr.browsingContext, 227 [urlInner], 228 async urlInner => { 229 let ifr = content.document.createElement("iframe"); 230 let loadPromise = ContentTaskUtils.waitForEvent(ifr, "load"); 231 ifr.src = urlInner; 232 content.document.body.appendChild(ifr); 233 await loadPromise; 234 235 // spawn inner iframe (same-site as top-level) 236 await SpecialPowers.spawn(await ifr.browsingContext, [], async () => { 237 function largeCookie(partitioned, index) { 238 var cookie = "largecookie" 239 .concat(index) 240 .concat("=") 241 .concat("1234567890".repeat(400)) 242 .concat("; Secure; SameSite=None;"); 243 if (partitioned) { 244 return cookie.concat("; Partitioned"); 245 } 246 return cookie; 247 } 248 content.document.cookie = largeCookie(true, 0); 249 content.document.cookie = largeCookie(true, 1); 250 content.document.cookie = largeCookie(true, 2); 251 content.document.cookie = largeCookie(true, 3); 252 content.document.cookie = largeCookie(false, 0); 253 content.document.cookie = largeCookie(false, 1); 254 content.document.cookie = largeCookie(false, 2); 255 content.document.cookie = largeCookie(false, 3); 256 }); 257 } 258 ); 259 } 260 ); 261 262 // Get cookies from partitioned jar 263 let partitioned = Services.cookies.getCookiesWithOriginAttributes( 264 partitionedSameSiteForeignOAs, 265 FIRST_PARTY 266 ); 267 // Get cookies from unpartitioned jar 268 let unpartitioned = Services.cookies.getCookiesWithOriginAttributes( 269 unpartitionedOAs, // no such thing as unpartitioned with foreign bit 270 FIRST_PARTY 271 ); 272 273 // same-site foreign partitioned cookies are subject to the byte limit 274 // unpartitioned are blocked 275 Assert.equal(partitioned.length, 2); 276 Assert.equal(unpartitioned.length, 0); 277 278 // Cleanup 279 BrowserTestUtils.removeTab(tab); 280 Services.cookies.removeAll(); 281 }); 282 283 // reducing the byte limit pref affects the amount of cookie bytes we trigger at 284 add_task(async function test_chips_limit_change_byte_limit() { 285 Services.prefs.setIntPref( 286 "network.cookie.chips.partitionLimitByteCapacity", 287 5120 // half the default 288 ); 289 const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY); 290 const browser = gBrowser.getBrowserForTab(tab); 291 await BrowserTestUtils.browserLoaded(browser); 292 293 // two cookies of this size will exceed the new limit 294 await setCookieViaDomOnChild(browser, uniqueLargeCookie(true)); 295 await setCookieViaDomOnChild(browser, uniqueLargeCookie(true)); 296 // unpartitioned will be unaffected 297 await setCookieViaDomOnChild(browser, uniqueLargeCookie(false)); 298 await setCookieViaDomOnChild(browser, uniqueLargeCookie(false)); 299 300 // Get cookies from partitioned jar 301 let partitioned = Services.cookies.getCookiesWithOriginAttributes( 302 partitionedOAs, 303 FIRST_PARTY 304 ); 305 306 // Get cookies from unpartitioned jar 307 let unpartitioned = Services.cookies.getCookiesWithOriginAttributes( 308 unpartitionedOAs, 309 FIRST_PARTY 310 ); 311 312 // check that partitioned cookies are purged at maximum 313 // check that unpartitioned cookies are not 314 Assert.equal(partitioned.length, 1); 315 Assert.equal(unpartitioned.length, 2); 316 317 // Cleanup 318 BrowserTestUtils.removeTab(tab); 319 Services.cookies.removeAll(); 320 });