| // META: script=/common/get-host-info.sub.js |
| // META: script=/common/utils.js |
| // META: script=/common/dispatcher/dispatcher.js |
| // META: script=/html/cross-origin-embedder-policy/credentialless/resources/common.js |
| // META: script=./resources/common.js |
| |
| // A script acquiring a lock. It can be released using window.releaseLocks |
| const acquire_script = (key, response) => ` |
| window.releaseLocks ||= []; |
| navigator.locks.request("${key}", async lock => { |
| send("${response}", "locked") |
| await new Promise(r => releaseLocks.push(r)); |
| send("${response}", "unlocked"); |
| }); |
| `; |
| |
| const release_script = (response) => ` |
| for (release of releaseLocks) |
| release(); |
| `; |
| |
| // Assert that |context| holds |expected_keys|. |
| const assertHeldKeys = async (context, expected_keys) => { |
| const queue = token(); |
| send(context, ` |
| const list = await navigator.locks.query(); |
| send("${queue}", JSON.stringify(list)); |
| `); |
| const state = JSON.parse(await receive(queue)); |
| const held = state.held.map(x => x.name); |
| assert_equals(held.length, expected_keys.length); |
| assert_array_equals(held.sort(), expected_keys.sort()); |
| } |
| |
| promise_test(async test => { |
| const origin = get_host_info().HTTPS_REMOTE_ORIGIN; |
| const key_1 = token(); |
| const key_2 = token(); |
| |
| // 2 actors: A credentialless iframe and a normal one. |
| const iframe_credentialless = newIframeCredentialless(origin); |
| const iframe_normal = newIframe(origin); |
| const response_queue_1 = token(); |
| const response_queue_2 = token(); |
| |
| // 1. Hold two different locks on both sides. |
| send(iframe_credentialless, acquire_script(key_1, response_queue_1)); |
| send(iframe_normal, acquire_script(key_2, response_queue_2)); |
| assert_equals(await receive(response_queue_1), "locked"); |
| assert_equals(await receive(response_queue_2), "locked"); |
| await assertHeldKeys(iframe_credentialless, [key_1]); |
| await assertHeldKeys(iframe_normal, [key_2]); |
| |
| // 2. Try to acquire the lock with the same key on the opposite side. It |
| // shouldn't block, because they are partitioned. |
| send(iframe_credentialless , acquire_script(key_2, response_queue_1)); |
| send(iframe_normal, acquire_script(key_1, response_queue_2)); |
| assert_equals(await receive(response_queue_1), "locked"); |
| assert_equals(await receive(response_queue_2), "locked"); |
| await assertHeldKeys(iframe_credentialless, [key_1, key_2]); |
| await assertHeldKeys(iframe_normal, [key_1, key_2]); |
| |
| // 3. Cleanup: release the 4 locks (2 on each sides). |
| send(iframe_credentialless, release_script(response_queue_1)); |
| assert_equals(await receive(response_queue_1), "unlocked"); |
| assert_equals(await receive(response_queue_1), "unlocked"); |
| await assertHeldKeys(iframe_credentialless, []); |
| await assertHeldKeys(iframe_normal, [key_1, key_2]); |
| |
| send(iframe_normal, release_script(response_queue_2)); |
| assert_equals(await receive(response_queue_2), "unlocked"); |
| assert_equals(await receive(response_queue_2), "unlocked"); |
| await assertHeldKeys(iframe_credentialless, []); |
| await assertHeldKeys(iframe_normal, []); |
| }) |