Skip to content

Commit

Permalink
Prerender: Upstream tests for storage APIs in same-origin prerendered…
Browse files Browse the repository at this point in the history
… pages (1)

This CL upstreams tests for storage APIs (Cache Storage, IndexedDB,
Local Storage) in same-origin prerendered pages to the WPT. The behavior
of these APIs is not defined in the spec yet, but we already reached a
consensus that the storage APIs in same-origin prerendered pages are
just allowed.

See the GitHub issue for details:
WICG/nav-speculation#7 (comment)

Tests for remaining storage APIs (e.g., Storage Foundation) will be
upstreamed by subsequent CLs.

Bug: 1253158
Change-Id: I25482404b7bbee2566297bd917dfe824502052cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3226443
Reviewed-by: Kouhei Ueno <[email protected]>
Reviewed-by: Lingqi Chi <[email protected]>
Commit-Queue: Hiroki Nakagawa <[email protected]>
Cr-Commit-Position: refs/heads/main@{#932415}
  • Loading branch information
nhiroki authored and Gabisampaio committed Nov 18, 2021
1 parent 43e2dc0 commit 2f9a193
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 0 deletions.
42 changes: 42 additions & 0 deletions speculation-rules/prerender/cache-storage.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<title>Same-origin prerendering can access cache storage</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/utils.js"></script>
<body>
<script>

setup(() => assertSpeculationRulesIsSupported());

promise_test(async t => {
const bc = new BroadcastChannel('prerender-channel');

const gotMessage = new Promise(resolve => {
bc.addEventListener('message', e => {
resolve(e.data);
}, {
once: true
});
});

const cacheName = 'checkallowed';
const cache = await caches.open(cacheName);
await cache.add('resources/cache.txt');
const response = await cache.match('resources/cache.txt');
const cacheText = await (response ? response.text() : 'primary cache match failed');

// Start prerendering a page that attempts to access cache storage.
startPrerendering(`resources/cache-storage-access.https.html`);
const result = await gotMessage;

assert_equals(
result, cacheText,
'prerendering page should be able to read from cache storage.');
await caches.delete(cacheName);

bc.close();
}, 'prerendering page should be able to access cache storage')

</script>
</body>
44 changes: 44 additions & 0 deletions speculation-rules/prerender/indexeddb.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<title>Same-origin prerendering can access Indexed Database</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/utils.js"></script>
<script src="resources/indexedb-utils.js"></script>
<body>
<script>

setup(() => assertSpeculationRulesIsSupported());

promise_test(async t => {
const bc = new BroadcastChannel('prerender-channel');

const gotMessage = new Promise(resolve => {
bc.addEventListener('message', e => {
resolve(e.data);
}, {
once: true
});
});

const db = await openIndexedDatabase();
assert_not_equals(db, null, 'Failed to open database.');
await addData(db, INITIATOR_KEY, INITIATOR_VALUE);

// Start prerendering a page that attempts to access the IndexedDB API.
startPrerendering(`resources/indexeddb-access.html`);

const prerenderReadResult = await gotMessage;
assert_equals(
prerenderReadResult, INITIATOR_VALUE,
'prerendering page should be able to read from Indexed DataBase');
const initiatorReadResult = await readData(db, PRERENDER_KEY);
assert_equals(
initiatorReadResult, PRERENDER_VALUE,
'prerendering page should be able to write to Indexed DataBase');
db.close();
bc.close();
}, 'prerendering page should be able to access Indexed DataBase')

</script>
</body>
36 changes: 36 additions & 0 deletions speculation-rules/prerender/local-storage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<title>Same-origin prerendering can access localStorage</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/utils.js"></script>
<body>
<script>

setup(() => assertSpeculationRulesIsSupported());

promise_test(async t => {
const bc = new BroadcastChannel('prerender-channel');

const gotMessage = new Promise(resolve => {
bc.addEventListener('message', e => {
resolve(e.data);
}, {once:true});
});

const initialValue = "initial_set";
window.localStorage.setItem('initial', initialValue);

// Start prerendering a page that attempts to access localStorage API.
startPrerendering(`resources/local-storage-access.html`);
const result = await gotMessage;
assert_equals(
result, initialValue,
'prerendering page should be able to read from local storage');
assert_equals(
window.localStorage.getItem('prerender'), 'prerender_set',
'prerendering page should be able to write to local storage');
}, 'prerendering page should be able to access local storage');

</script>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>

const bc = new BroadcastChannel('prerender-channel');
assert_true(document.prerendering);

const cacheName = 'checkallowed';
caches.open(cacheName).then(cache => cache.match('cache.txt'))
.then(response => response.text())
.then(result => {
bc.postMessage(result);
bc.close();
});

</script>
1 change: 1 addition & 0 deletions speculation-rules/prerender/resources/cache.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, Prerender API!
56 changes: 56 additions & 0 deletions speculation-rules/prerender/resources/indexedb-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const STORAGE_NAME = 'prerender_test';
const INITIATOR_KEY = 'initiator';
const INITIATOR_VALUE = INITIATOR_KEY + '_set';
const PRERENDER_KEY = 'prerender';
const PRERENDER_VALUE = PRERENDER_KEY + '_set';

async function openIndexedDatabase() {
return new Promise(resolve => {
const request = window.indexedDB.open(STORAGE_NAME);
request.onupgradeneeded = e => {
const db = e.target.result;
const objectStore =
db.createObjectStore(STORAGE_NAME, {autoIncrement: true});
objectStore.createIndex('key', 'key', {unique: true});
};
request.onerror = e => {
resolve(null);
};
request.onsuccess = e => {
resolve(e.target.result);
};
});
}

async function addData(db, key, value) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(STORAGE_NAME, 'readwrite');
const request =
transaction.objectStore(STORAGE_NAME).add({'key': key, 'value': value});
// Use `transaction.oncomplete` rather than `request.onsuccess` to ensure
// that IndexedDB has flushed to disk.
transaction.oncomplete = e => {
resolve(true);
};
transaction.onerror = e => {
reject(e.target.error);
};
});
}

async function readData(db, key) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(STORAGE_NAME);
const request = transaction.objectStore(STORAGE_NAME).index('key').get(key);
request.onsuccess = e => {
if (e.target.result) {
resolve(e.target.result.value);
} else {
reject(new Error('Empty result.'));
}
};
request.onerror = e => {
reject(e.target.error);
};
});
}
24 changes: 24 additions & 0 deletions speculation-rules/prerender/resources/indexeddb-access.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="indexedb-utils.js"></script>
<script>

assert_true(document.prerendering);

async function operateDatabase(){
const bc = new BroadcastChannel('prerender-channel');

const db = await openIndexedDatabase();
assert_not_equals(db, null, 'Failed to open database.');

await addData(db, PRERENDER_KEY, PRERENDER_VALUE);
const result = await readData(db, INITIATOR_KEY);
bc.postMessage(result);
bc.close();
db.close();
}

operateDatabase();

</script>
15 changes: 15 additions & 0 deletions speculation-rules/prerender/resources/local-storage-access.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>

const bc = new BroadcastChannel('prerender-channel');
assert_true(document.prerendering);

window.localStorage.setItem('prerender', 'prerender_set');
const result = window.localStorage.getItem('initial');

bc.postMessage(result);
bc.close();

</script>

0 comments on commit 2f9a193

Please sign in to comment.