storage-partitioning.https.html (6437B)
1 <!DOCTYPE html> 2 <title>Test storage partitioning in fenced frames</title> 3 <meta name="timeout" content="long"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="/common/utils.js"></script> 7 <script src="/common/dispatcher/dispatcher.js"></script> 8 <script src="resources/utils.js"></script> 9 10 <body> 11 <script> 12 13 // `getter(key)` : reads the value of `key`, null if not set 14 // `setter(key, value)`: sets `key` to `value` 15 async function runTest(getter, setter) { 16 const key = "key"; 17 const outer_value = "outer"; 18 const inner_value = "inner"; 19 20 // Set the value in the top-level frame, and check that it worked. 21 await setter(key, outer_value); 22 assert_equals(await getter(key), outer_value, 23 "Stored the value in the top-level frame."); 24 25 // Attach a fenced frame. 26 const frame = attachFencedFrameContext(); 27 28 // Check that the outer value isn't visible. 29 const inner_before_set = await frame.execute(getter, [key]); 30 assert_equals(inner_before_set, null, 31 "The outer value isn't visible inside the fenced frame."); 32 33 // Set the value inside the fenced frame, and check that it worked. 34 await frame.execute(setter, [key, inner_value]); 35 const inner_after_set = await frame.execute(getter, [key]); 36 assert_equals(inner_after_set, inner_value, 37 "Stored the value in the fenced frame."); 38 39 // Check that the inner value isn't visible in the top-level frame. 40 assert_equals(await getter(key), outer_value, 41 "The inner value isn't visible outside the fenced frame."); 42 43 // Perform an embedder-initiated navigation that will fail. 44 const original_config = frame.config; 45 frame.config = new FencedFrameConfig("resources/response-204.py"); 46 await step_timeout(() => {}, 1000); 47 48 // Check that the failed navigation didn't change the storage partition. 49 // (The partition nonce should be reinitialized on navigation commit.) 50 const inner_after_failure = await frame.execute(getter, [key]); 51 assert_equals(inner_after_failure, inner_value, 52 "The inner value is still present after the failed navigation."); 53 54 // Refresh the fenced frame from within. 55 await frame.execute(() => { 56 window.executor.suspend(() => { location.href = location.href; }); 57 }); 58 59 // Check that the storage partition is the same. 60 const inner_after_inner_refresh = await frame.execute(getter, [key]); 61 assert_equals(inner_after_inner_refresh, inner_value, 62 "The inner value is the same after a fencedframe-initiated refresh."); 63 64 // Refresh the fenced frame from the embedder. 65 await frame.execute(() => window.executor.suspend(() => {})); 66 frame.element.config = original_config; 67 68 // Check that there is a blank slate. 69 const inner_after_embedder_refresh = await frame.execute(getter, [key]); 70 assert_equals(inner_after_embedder_refresh, null, 71 "The inner value is gone after an embedder-initiated refresh."); 72 } 73 74 promise_test(async () => { 75 return runTest( 76 (_) => { return document.cookie || null; }, 77 (_, value) => { document.cookie = value;} 78 ); 79 }, 'document.cookie'); 80 81 promise_test(async () => { 82 return runTest( 83 (key) => { return localStorage.getItem(key); }, 84 (key, value) => { return localStorage.setItem(key, value); } 85 ); 86 }, 'localStorage'); 87 88 promise_test(async () => { 89 return runTest( 90 (key) => { return sessionStorage.getItem(key); }, 91 (key, value) => { return sessionStorage.setItem(key, value); } 92 ); 93 }, 'sessionStorage'); 94 95 promise_test(async () => { 96 return runTest( 97 async (key) => { 98 const newCache = await caches.open('test-cache'); 99 const response = await newCache.match(key); 100 if (!response) { 101 return null; 102 } 103 return response.text(); 104 }, 105 async (key, value) => { 106 const newCache = await caches.open('test-cache'); 107 return newCache.put(key, new Response(value)); 108 } 109 ); 110 }, 'Cache API'); 111 112 promise_test(async () => { 113 return runTest( 114 async (key) => { 115 const root = await navigator.storage.getDirectory(); 116 const draftHandle = await root.getFileHandle(key, { create: true }); 117 const file = await draftHandle.getFile(); 118 const text = await file.text(); 119 return text || null; 120 }, 121 async (key, value) => { 122 const root = await navigator.storage.getDirectory(); 123 const draftHandle = await root.getFileHandle(key, { create: true }); 124 const writable = await draftHandle.createWritable() 125 await writable.truncate(0); 126 await writable.write(value); 127 await writable.close(); 128 } 129 ); 130 }, 'File System Access API'); 131 132 promise_test(async () => { 133 return runTest( 134 async (key) => { 135 const openRequest = indexedDB.open('test-db', 2); 136 const db = await new Promise((resolve) => { 137 openRequest.onsuccess = (event) => { 138 resolve(event.target.result); 139 }; 140 openRequest.onupgradeneeded = (event) => { 141 const db = event.target.result; 142 const objStore = db.createObjectStore('test-tbl', {keyPath: 'key'}); 143 objStore.transaction.oncomplete = (event) => { 144 resolve(db); 145 }; 146 }; 147 }); 148 const readRequest = db.transaction(['test-tbl']) 149 .objectStore('test-tbl') 150 .get(key); 151 return new Promise((resolve) => { 152 readRequest.onsuccess = (event) => { 153 if (!event.target.result) { 154 resolve(null); 155 } else { 156 resolve(event.target.result['value']); 157 } 158 }; 159 }); 160 }, 161 async (key, value) => { 162 const openRequest = indexedDB.open('test-db', 2); 163 const db = await new Promise((resolve) => { 164 openRequest.onsuccess = (event) => { 165 resolve(event.target.result); 166 }; 167 openRequest.onupgradeneeded = (event) => { 168 const db = event.target.result; 169 const objStore = db.createObjectStore('test-tbl', {keyPath: 'key'}); 170 objStore.transaction.oncomplete = (event) => { 171 resolve(db); 172 }; 173 }; 174 }); 175 const writeRequest = db.transaction(['test-tbl'], 'readwrite') 176 .objectStore('test-tbl') 177 .add({'key': key, 'value': value}); 178 return new Promise((resolve) => { 179 writeRequest.onsuccess = (event) => { 180 resolve(event.target.result); 181 }; 182 }); 183 } 184 ); 185 }, 'IndexedDB'); 186 187 </script> 188 </body>