diff --git a/speculation-rules/prerender/resources/session-storage-carry-over-to-prerender-page.html b/speculation-rules/prerender/resources/session-storage-carry-over-to-prerender-page.html new file mode 100644 index 00000000000000..39df79c84762fd --- /dev/null +++ b/speculation-rules/prerender/resources/session-storage-carry-over-to-prerender-page.html @@ -0,0 +1,23 @@ + + + + + + diff --git a/speculation-rules/prerender/resources/session-storage-isolated-while-prerendering.html b/speculation-rules/prerender/resources/session-storage-isolated-while-prerendering.html new file mode 100644 index 00000000000000..46170393deb4ad --- /dev/null +++ b/speculation-rules/prerender/resources/session-storage-isolated-while-prerendering.html @@ -0,0 +1,44 @@ + + + + + + diff --git a/speculation-rules/prerender/resources/session-storage-no-leak-to-initiator-page.html b/speculation-rules/prerender/resources/session-storage-no-leak-to-initiator-page.html new file mode 100644 index 00000000000000..6c0ee4c4adbab9 --- /dev/null +++ b/speculation-rules/prerender/resources/session-storage-no-leak-to-initiator-page.html @@ -0,0 +1,38 @@ + + + + + + diff --git a/speculation-rules/prerender/resources/session-storage-swap-after-activate.html b/speculation-rules/prerender/resources/session-storage-swap-after-activate.html new file mode 100644 index 00000000000000..c5e443721491a7 --- /dev/null +++ b/speculation-rules/prerender/resources/session-storage-swap-after-activate.html @@ -0,0 +1,79 @@ + + + + + + diff --git a/speculation-rules/prerender/resources/session-storage-utils.js b/speculation-rules/prerender/resources/session-storage-utils.js new file mode 100644 index 00000000000000..06688e3bd4cf6e --- /dev/null +++ b/speculation-rules/prerender/resources/session-storage-utils.js @@ -0,0 +1,72 @@ +function getSessionStorageKeys() { + let keys = []; + let txt = ''; + for (let i = 0; i < sessionStorage.length; ++i) { + keys.push(sessionStorage.key(i)); + } + keys.sort(); + keys.forEach((key) => { + if (txt.length) { + txt += ', '; + } + txt += key; + }); + return txt; +} + +function getNextMessage(channel) { + return new Promise(resolve => { + channel.addEventListener('message', e => { + resolve(e.data); + }, {once: true}); + }); +} + +// session_storage_test() is a utility function for running session storage +// related tests that open a initiator page using window.open(). +function session_storage_test(testPath, uid) { + promise_test(async t => { + const testChannel = new PrerenderChannel('test-channel', uid); + t.add_cleanup(() => { + testChannel.close(); + }); + const gotMessage = getNextMessage(testChannel); + const url = 'resources/' + testPath + '?uid=' + uid; + window.open(url, '_blank', 'noopener'); + assert_equals(await gotMessage, 'Done'); + }, testPath); +} + +// RunSessionStorageTest() is a utility function for running session storage +// related tests that requires coordinated code execution on both the initiator +// page and the prerendering page. The passed |func| function will be called +// with the following arguments: +// - isPrerendering: Whether the |func| is called in the prerendering page. +// - url: The URL of the prerendering page. |func| should call +// startPrerendering(url) when |isPrerendering| is false to start the +// prerendering. +// - channel: A PrerenderChannel which can be used to coordinate the code +// execution on the initiator page and the prerendering page. +// - done: A function that should be called when the test completes +// successfully. +async function RunSessionStorageTest(func, uid) { + const url = new URL(document.URL); + url.searchParams.set('prerendering', ''); + const params = new URLSearchParams(location.search); + // The main test page loads the initiator page, then the initiator page will + // prerender itself with the `prerendering` parameter. + const isPrerendering = params.has('prerendering'); + const prerenderChannel = new PrerenderChannel('prerender-channel', uid); + const testChannel = new PrerenderChannel('test-channel', uid); + window.addEventListener('pagehide', () => { + prerenderChannel.close(); + testChannel.close(); + }); + try { + await func(isPrerendering, url.toString(), prerenderChannel, () => { + testChannel.postMessage('Done'); + }) + } catch (e) { + testChannel.postMessage(e.toString()); + } +} diff --git a/speculation-rules/prerender/session-storage.tentative.html b/speculation-rules/prerender/session-storage.tentative.html new file mode 100644 index 00000000000000..92d73285cce8df --- /dev/null +++ b/speculation-rules/prerender/session-storage.tentative.html @@ -0,0 +1,30 @@ + + +Same-origin prerendering can access sessionStorage + + + + + + + + +