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