1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
// 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, []);
})
|