frames.https.html (8295B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <title>Web Locks API: Frames</title> 4 <link rel=help href="https://w3c.github.io/web-locks/"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="resources/helpers.js"></script> 8 <style>iframe { display: none; }</style> 9 <script> 10 'use strict'; 11 12 promise_test(async t => { 13 assert_implements(navigator.locks); 14 const res = uniqueName(t); 15 16 const frame = await iframe('resources/iframe.html'); 17 t.add_cleanup(() => { frame.remove(); }); 18 19 const lock_id = (await postToFrameAndWait( 20 frame, {op: 'request', name: res, mode: 'shared'})).lock_id; 21 22 await navigator.locks.request(res, {mode: 'shared'}, async lock => { 23 await postToFrameAndWait(frame, {op: 'release', lock_id}); 24 }); 25 26 }, 'Window and Frame - shared mode'); 27 28 promise_test(async t => { 29 assert_implements(navigator.locks); 30 const res = uniqueName(t); 31 32 const frame = await iframe('resources/iframe.html'); 33 t.add_cleanup(() => { frame.remove(); }); 34 35 // frame acquires the lock. 36 const lock_id = (await postToFrameAndWait( 37 frame, {op: 'request', name: res})).lock_id; 38 39 // This request should be blocked. 40 let lock_granted = false; 41 const blocked = navigator.locks.request(res, lock => { lock_granted = true; }); 42 43 // Verify that we can't get it. 44 let available = undefined; 45 await navigator.locks.request( 46 res, {ifAvailable: true}, lock => { available = lock !== null; }); 47 assert_false(available); 48 assert_false(lock_granted); 49 50 // Ask the frame to release it. 51 await postToFrameAndWait(frame, {op: 'release', lock_id}); 52 53 await blocked; 54 // Now we've got it. 55 assert_true(lock_granted); 56 }, 'Window and Frame - exclusive mode'); 57 58 promise_test(async t => { 59 assert_implements(navigator.locks); 60 const res = uniqueName(t); 61 62 const frame1 = await iframe('resources/iframe.html'); 63 const frame2 = await iframe('resources/iframe.html'); 64 65 // frame1 acquires the lock. 66 const lock_id = (await postToFrameAndWait( 67 frame1, {op: 'request', name: res})).lock_id; 68 69 // frame2's request should be blocked. 70 let lock_granted = false; 71 const blocked = postToFrameAndWait( 72 frame2, {op: 'request', name: res}); 73 blocked.then(f => { lock_granted = true; }); 74 75 // Verify that frame2 can't get it. 76 assert_true((await postToFrameAndWait(frame2, { 77 op: 'request', name: res, ifAvailable: true 78 })).failed, 'Lock request should have failed'); 79 assert_false(lock_granted); 80 81 // Ask frame1 to release it. 82 await postToFrameAndWait(frame1, {op: 'release', lock_id}); 83 84 await blocked; 85 // Now frame2 can get it. 86 assert_true(lock_granted); 87 frame1.parentElement.removeChild(frame1); 88 frame2.parentElement.removeChild(frame2); 89 }, 'Frame and Frame - exclusive mode'); 90 91 promise_test(async t => { 92 assert_implements(navigator.locks); 93 const res = uniqueName(t); 94 95 const frame = await iframe('resources/iframe.html'); 96 97 // Frame acquires the lock. 98 await postToFrameAndWait(frame, {op: 'request', name: res}); 99 100 // This request should be blocked. 101 let lock_granted = false; 102 const blocked = navigator.locks.request( 103 res, lock => { lock_granted = true; }); 104 105 // Verify that we can't get it. 106 let available = undefined; 107 await navigator.locks.request( 108 res, {ifAvailable: true}, lock => { available = lock !== null; }); 109 assert_false(available); 110 assert_false(lock_granted); 111 112 // Implicitly release it by terminating the frame. 113 frame.remove(); 114 await blocked; 115 // Now we've got it. 116 assert_true(lock_granted); 117 118 }, 'Terminated Frame with held lock'); 119 120 promise_test(async t => { 121 assert_implements(navigator.locks); 122 const res = uniqueName(t); 123 124 const frame = await iframe('resources/iframe.html'); 125 126 // Frame acquires the lock. 127 await postToFrameAndWait(frame, {op: 'request', name: res}); 128 129 // This request should be blocked. 130 let lock_granted = false; 131 const blocked = navigator.locks.request( 132 res, lock => { lock_granted = true; }); 133 134 // Verify that we can't get it. 135 let available = undefined; 136 await navigator.locks.request( 137 res, {ifAvailable: true}, lock => { available = lock !== null; }); 138 assert_false(available); 139 assert_false(lock_granted); 140 141 // Implicitly release it by navigating the frame. 142 frame.src = 'about:blank'; 143 await blocked; 144 // Now we've got it. 145 assert_true(lock_granted); 146 147 }, 'Navigated Frame with held lock'); 148 149 promise_test(async t => { 150 assert_implements(navigator.locks); 151 const res = uniqueName(t); 152 153 // frame1 requests and holds res - should be granted immediately. 154 // frame2 requests res - should be blocked. 155 // frame3 requests res - should be blocked. 156 // frame2 is navigated. 157 // frame1 releases res. 158 // frame3's request should be granted. 159 160 const frame1 = await iframe('resources/iframe.html'); 161 const frame2 = await iframe('resources/iframe.html'); 162 const frame3 = await iframe('resources/iframe.html'); 163 t.add_cleanup(() => { frame1.remove(); }); 164 t.add_cleanup(() => { frame2.remove(); }); 165 t.add_cleanup(() => { frame3.remove(); }); 166 167 // frame1 requests and holds res - should be granted immediately. 168 const lock_id = (await postToFrameAndWait( 169 frame1, {op: 'request', name: res})).lock_id; 170 171 // frame2 requests res - should be blocked. 172 // (don't attach listeners as they will keep the frame alive) 173 frame2.contentWindow.postMessage({op: 'request', name: res}, '*'); 174 175 // frame3 requests res - should be blocked. 176 let lock_granted = false; 177 const blocked = postToFrameAndWait(frame3, {op: 'request', name: res}); 178 blocked.then(f => { lock_granted = true; }); 179 180 // Verify that frame3 can't get it. 181 assert_true((await postToFrameAndWait(frame3, { 182 op: 'request', name: res, ifAvailable: true 183 })).failed, 'Lock request should have failed'); 184 assert_false(lock_granted); 185 186 // Navigate frame2. 187 frame2.src = 'about:blank'; 188 189 // frame1 releases lock 190 await postToFrameAndWait(frame1, {op: 'release', lock_id}); 191 192 // frame3's request should be granted. 193 await blocked; 194 assert_true(lock_granted); 195 196 }, 'Navigated Frame with pending request'); 197 198 promise_test(async t => { 199 assert_implements(navigator.locks); 200 const res = uniqueName(t); 201 202 // frame1 requests and holds res - should be granted immediately. 203 // frame2 requests res - should be blocked. 204 // frame3 requests res - should be blocked. 205 // frame2 is removed. 206 // frame1 drops lock. 207 // frame3's request should be granted. 208 209 const frame1 = await iframe('resources/iframe.html'); 210 const frame2 = await iframe('resources/iframe.html'); 211 const frame3 = await iframe('resources/iframe.html'); 212 t.add_cleanup(() => { frame1.remove(); }); 213 t.add_cleanup(() => { frame3.remove(); }); 214 215 // frame1 requests and holds res - should be granted immediately. 216 const lock_id = (await postToFrameAndWait( 217 frame1, {op: 'request', name: res})).lock_id; 218 219 // frame2 requests res - should be blocked. 220 // (don't attach listeners as they will keep the frame alive) 221 frame2.contentWindow.postMessage({op: 'request', name: res}, '*'); 222 223 // frame3 requests res - should be blocked. 224 let lock_granted = false; 225 const blocked = postToFrameAndWait(frame3, {op: 'request', name: res}); 226 blocked.then(f => { lock_granted = true; }); 227 228 // So frame3 can't get it 229 assert_true((await postToFrameAndWait(frame3, { 230 op: 'request', name: res, ifAvailable: true 231 })).failed, 'Lock request should have failed'); 232 assert_false(lock_granted); 233 234 // Remove frame2. 235 frame2.remove(); 236 237 // frame1 releases lock 238 await postToFrameAndWait(frame1, {op: 'release', lock_id}); 239 240 // frame3's request should be granted. 241 await blocked; 242 assert_true(lock_granted); 243 244 }, 'Removed Frame with pending request'); 245 246 promise_test(async t => { 247 assert_implements(navigator.locks); 248 const res = uniqueName(t); 249 250 const frame = await iframe('about:blank'); 251 252 // Remove a frame while it is in the process of requesting a lock. 253 // The promise returned by `request` will never resolve since its frame no 254 // longer exists, but the lock should still be released. 255 await new Promise(resolve => { 256 frame.contentWindow.navigator.locks.request(res, () => { 257 frame.remove(); 258 resolve(); 259 }); 260 }); 261 262 assert_false((await navigator.locks.query()).held.includes(res)); 263 }, 'Removed Frame as lock is granted'); 264 265 </script>