
<!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;

// How this test works:
// Step 1 (top-frame): request an exclusive web-lock and store its id
// and release for clean-up.
// Step 2 (top-frame): open a pop-up window and load a not-same-site
// ./web-locks/resources/partitioned-parent.html
// Step 3 (pop-up): load a same-site iframe inside the pop-up.
// Step 4 (pop-up): send a web-lock request to the same-site iframe.
// Step 5 (iframe): process the web-lock request and message the result
// back to the pop-up.
// Step 6 (pop-up): intercept the result message from the iframe and
// send it to the top-frame.
// Step 7 (top-frame): add cleanup hook.
// Step 8 (top-frame): ensure that the same-site iframe's web-lock
// request succeeds since it and the top-level site are successfully
// partitioned and each can hold an exclusive lock.

async function third_party_test(t) {
  let target_url = HTTPS_ORIGIN + '/web-locks/resources/iframe.html';
  target_url = new URL(
    `/web-locks/resources/partitioned-parent.html?target=${encodeURIComponent(target_url)}`,
    HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname);

  // Step 1.
  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;
        });

  // Step 2.
  const w = window.open(target_url);
  const result = await new Promise(resolve => window.onmessage = resolve);

  // Step 7.
  t.add_cleanup(() => {
    w.close()
    for(let i = 1; i < next_lock_id; i++){
      held.get(i)();
    }
  });

  // Step 8.
  // When 3rd party storage partitioning is enabled, the iframe should be able
  // to acquire 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');
}

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.
//
// How this test works:
// Nested Step 1 (top frame): request an exclusive web-lock and
// store its id and release for clean-up.
// Nested Step 2 (top frame): open a pop-up window and load a
// same-site /web-locks/resources/partitioned-parent.html.
// Nested Step 3 (pop-up): load a not-same-site "parent" iframe (A->B)
// (/web-locks/resources/iframe-parent.html) inside the pop-up.
// Nested Step 4 (pop-up): send a web-lock request to the parent iframe.
// Nested Step 5 (parent iframe): load a "child" iframe (A->B->A)
// (/web-locks/resources/iframe.html) that is same-site with the
// pop-up inside the "parent" iframe.
// Nested Step 6 (parent iframe): pass on the web-lock request message to
// the "child" iframe.
// Nested Step 7 (child iframe): process the web-lock request and message
// the result to the parent iframe.
// Nested Step 8 (parent iframe): intercept the result message from the
// child iframe and send it to the pop-up.
// Nested Step 9 (pop-up): intercept the result message from the parent
// iframe and send it to the top frame.
// Nested Step 10 (top frame): add cleanup hook
// Nested Step 11 (top frame): ensure that the same-site iframe's web-lock
// request succeeds since it and the top-level are successfully
// partitioned and each can hold an exclusive lock.

// 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(
    `/web-locks/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(
    `/web-locks/resources/partitioned-parent.html?target=${encodeURIComponent(middle_url)}`,
    HTTPS_ORIGIN + self.location.pathname);

  // Nested Step 1.
  // 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));

  // Nested Step 2.
  // 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);

  // Nested Step 10.
  t.add_cleanup(() => {
    w.close()
    for(let i = 1; i < next_lock_id_2; i++){
      held_2.get(i)();
    }
  });

  // Nested Step 11.
  // 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');
}

promise_test(t => {
  return nested_iframe_test(t);
}, 'WebLocks of a nested iframe with a cross-site ancestor are partitioned');
</script>
</body>
