summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fenced-frame/storage-partitioning.https.html
blob: 36b4395339381e74abc7061946f458cb09a5d291 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<!DOCTYPE html>
<title>Test storage partitioning in fenced frames</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="resources/utils.js"></script>

<body>
<script>

// `getter(key)` : reads the value of `key`, null if not set
// `setter(key, value)`: sets `key` to `value`
async function runTest(getter, setter) {
  const key = "key";
  const outer_value = "outer";
  const inner_value = "inner";

  // Set the value in the top-level frame, and check that it worked.
  await setter(key, outer_value);
  assert_equals(await getter(key), outer_value,
      "Stored the value in the top-level frame.");

  // Attach a fenced frame.
  const frame = attachFencedFrameContext();

  // Check that the outer value isn't visible.
  const inner_before_set = await frame.execute(getter, [key]);
  assert_equals(inner_before_set, null,
      "The outer value isn't visible inside the fenced frame.");

  // Set the value inside the fenced frame, and check that it worked.
  await frame.execute(setter, [key, inner_value]);
  const inner_after_set = await frame.execute(getter, [key]);
  assert_equals(inner_after_set, inner_value,
      "Stored the value in the fenced frame.");

  // Check that the inner value isn't visible in the top-level frame.
  assert_equals(await getter(key), outer_value,
      "The inner value isn't visible outside the fenced frame.");

  // Perform an embedder-initiated navigation that will fail.
  const original_config = frame.config;
  frame.config = new FencedFrameConfig("resources/response-204.py");
  await step_timeout(() => {}, 1000);

  // Check that the failed navigation didn't change the storage partition.
  // (The partition nonce should be reinitialized on navigation commit.)
  const inner_after_failure = await frame.execute(getter, [key]);
  assert_equals(inner_after_failure, inner_value,
      "The inner value is still present after the failed navigation.");

  // Refresh the fenced frame from within.
  await frame.execute(() => {
    window.executor.suspend(() => { location.href = location.href; });
  });

  // Check that the storage partition is the same.
  const inner_after_inner_refresh = await frame.execute(getter, [key]);
  assert_equals(inner_after_inner_refresh, inner_value,
      "The inner value is the same after a fencedframe-initiated refresh.");

  // Refresh the fenced frame from the embedder.
  await frame.execute(() => window.executor.suspend(() => {}));
  frame.element.config = original_config;

  // Check that there is a blank slate.
  const inner_after_embedder_refresh = await frame.execute(getter, [key]);
  assert_equals(inner_after_embedder_refresh, null,
      "The inner value is gone after an embedder-initiated refresh.");
}

promise_test(async () => {
  return runTest(
    (_) => { return document.cookie || null; },
    (_, value) => { document.cookie = value;}
  );
}, 'document.cookie');

promise_test(async () => {
  return runTest(
    (key) => { return localStorage.getItem(key); },
    (key, value) => { return localStorage.setItem(key, value); }
  );
}, 'localStorage');

promise_test(async () => {
  return runTest(
    (key) => { return sessionStorage.getItem(key); },
    (key, value) => { return sessionStorage.setItem(key, value); }
  );
}, 'sessionStorage');

promise_test(async () => {
  return runTest(
    async (key) => {
      const newCache = await caches.open('test-cache');
      const response = await newCache.match(key);
      if (!response) {
        return null;
      }
      return response.text();
    },
    async (key, value) => {
      const newCache = await caches.open('test-cache');
      return newCache.put(key, new Response(value));
    }
  );
}, 'Cache API');

promise_test(async () => {
  return runTest(
    async (key) => {
      const root = await navigator.storage.getDirectory();
      const draftHandle = await root.getFileHandle(key, { create: true });
      const file = await draftHandle.getFile();
      const text = await file.text();
      return text || null;
    },
    async (key, value) => {
      const root = await navigator.storage.getDirectory();
      const draftHandle = await root.getFileHandle(key, { create: true });
      const writable = await draftHandle.createWritable()
      await writable.truncate(0);
      await writable.write(value);
      await writable.close();
    }
  );
}, 'File System Access API');

promise_test(async () => {
  return runTest(
    async (key) => {
      const openRequest = indexedDB.open('test-db', 2);
      const db = await new Promise((resolve) => {
        openRequest.onsuccess = (event) => {
          resolve(event.target.result);
        };
        openRequest.onupgradeneeded = (event) => {
          const db = event.target.result;
          const objStore = db.createObjectStore('test-tbl', {keyPath: 'key'});
          objStore.transaction.oncomplete = (event) => {
            resolve(db);
          };
        };
      });
      const readRequest = db.transaction(['test-tbl'])
                            .objectStore('test-tbl')
                            .get(key);
      return new Promise((resolve) => {
        readRequest.onsuccess = (event) => {
          if (!event.target.result) {
            resolve(null);
          } else {
            resolve(event.target.result['value']);
          }
        };
      });
    },
    async (key, value) => {
      const openRequest = indexedDB.open('test-db', 2);
      const db = await new Promise((resolve) => {
        openRequest.onsuccess = (event) => {
          resolve(event.target.result);
        };
        openRequest.onupgradeneeded = (event) => {
          const db = event.target.result;
          const objStore = db.createObjectStore('test-tbl', {keyPath: 'key'});
          objStore.transaction.oncomplete = (event) => {
            resolve(db);
          };
        };
      });
      const writeRequest = db.transaction(['test-tbl'], 'readwrite')
                             .objectStore('test-tbl')
                             .add({'key': key, 'value': value});
      return new Promise((resolve) => {
        writeRequest.onsuccess = (event) => {
          resolve(event.target.result);
        };
      });
    }
  );
}, 'IndexedDB');

</script>
</body>