blob: d2f22f196445ee944e3784b5c9c795f338ce9d1f [file] [log] [blame] [edit]
<!DOCTYPE html>
<meta charset="utf-8"/>
<title>Web Locks API: Partitioned WebLocks</title>
<!-- Pull in get_host_info() -->
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="resources/helpers.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
const { HTTPS_ORIGIN, HTTPS_NOTSAMESITE_ORIGIN } = get_host_info();
// Map of lock_id => function that releases a lock.
const held = new Map();
let next_lock_id = 1;
async function third_party_test(t) {
let target_url = HTTPS_ORIGIN + '/web-locks/resources/iframe.html';
target_url = new URL(
`./resources/partitioned-parent.html?target=${encodeURIComponent(target_url)}`,
HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname);
navigator.locks.request('testLock', {mode: 'exclusive', ifAvailable: true},
lock => {
if (lock === null) {
assert_true(false)
return;
}
let lock_id = next_lock_id++;
let release;
const promise = new Promise(r => { release = r; });
held.set(lock_id, release);
return promise;
});
const w = window.open(target_url);
const result = await new Promise(resolve => window.onmessage = resolve);
// When 3rd party storage partitioning is enabled, the iframe should be able
// to aquire a lock with the same name as one exclusively held by the opener
// of its top window, even when that opener has the same origin.
assert_equals(result.data.failed, undefined,
'The 1p iframe failed to acquire the lock');
t.add_cleanup(() => {
w.close()
for(let i = 1; i < next_lock_id; i++){
held.get(i)();
}
});
}
promise_test(t => {
return third_party_test(t);
}, 'WebLocks of an iframe under a 3rd-party site are partitioned');
// Optional Test: Checking for partitioned web locks in an A->B->A
// (nested-iframe with cross-site ancestor chain) scenario.
// Map of lock_id => function that releases a lock.
const held_2 = new Map();
let next_lock_id_2 = 1;
async function nested_iframe_test(t) {
// Create innermost child iframe (leaf).
let leaf_url = HTTPS_ORIGIN + '/web-locks/resources/iframe.html';
// Wrap the child iframe in its cross-origin parent (middle).
let middle_url = new URL(
`./resources/iframe-parent.html?target=${encodeURIComponent(leaf_url)}`,
HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname);
// Embed the parent iframe in the top-level site (top).
let top_url = new URL(
`./resources/partitioned-parent.html?target=${encodeURIComponent(middle_url)}`,
HTTPS_ORIGIN + self.location.pathname);
// Request the weblock for the top-level site.
navigator.locks.request('testLock', {mode: 'exclusive', ifAvailable: true},
lock => {
if (lock === null) {
assert_true(false)
return;
}
// Obtain and store the release functions for clean-up.
let lock_id = next_lock_id_2++;
let release;
const promise = new Promise(r => { release = r; });
held_2.set(lock_id, release);
return promise;
}).catch(error => alert(error.message));
// Open the nested iframes. The script in the innermost child iframe
// will attempt to obtain the same weblock as above.
const w = window.open(top_url);
const result = await new Promise(resolve => window.onmessage = resolve);
// With third-party storage partitioning enabled, the same-site iframe
// should be able to acquire the lock as it has a cross-site ancestor
// and is partitioned separately from the top-level site.
assert_equals(result.data.failed, undefined,
'The 1p iframe failed to acquire the lock');
t.add_cleanup(() => {
w.close()
for(let i = 1; i < next_lock_id_2; i++){
held_2.get(i)();
}
});
}
promise_test(t => {
return nested_iframe_test(t);
}, 'WebLocks of a nested iframe with a cross-site ancestor are partitioned');
</script>
</body>