summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/web-locks/partitioned-web-locks.tentative.https.html
blob: d2f22f196445ee944e3784b5c9c795f338ce9d1f (plain)
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<!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>