Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[presentation-api] Stop using EventWatcher for IndexedDB #9046

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
notice.parentNode.removeChild(notice);
stash.stop();

//history.back();
// history.back();
document.cookie = 'PresentationApiTest=true; Expires=' + new Date().toUTCString();
sessionStorage.removeItem('presentation_api_test');
localStorage.removeItem('presentation_api_test');
Expand Down Expand Up @@ -115,6 +115,8 @@
};
reg.active.postMessage('', [channel.port2]);
}
else
resolve([]);
});
});
};
Expand Down Expand Up @@ -249,7 +251,7 @@
// Check accessibility to window clients before terminating a presentation
return getClientUrls().then(urls => {
assert_true(urls.length === clientUrls.length && urls.every((value, index) => { return clientUrls[index] === value}),
'A window client in a receiving user agent is not accessible to a service worker on a controlling user agent.')
'A window client in a receiving user agent is not accessible to a service worker on a controlling user agent.');
const eventWatcher = new EventWatcher(t, connection, 'terminate');
connection.terminate();
return eventWatcher.wait_for('terminate');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,27 +106,30 @@
let db;
const checkIndexedDB = () => {
if ('indexedDB' in window) {
let req = indexedDB.open(dbName, 1), store;
let eventWatcher = new EventWatcher(t, req, ['upgradeneeded', 'success']);
return eventWatcher.wait_for('upgradeneeded').then(() => {
db = req.result;
const store = db.createObjectStore(storeName, { keyPath: 'id' });
return eventWatcher.wait_for('success');
}).then(() => {
db = req.result;
const transaction = db.transaction(storeName, 'readwrite');
store = transaction.objectStore(storeName);
req = store.openCursor();
eventWatcher = new EventWatcher(t, req, 'success');
return eventWatcher.wait_for('success');
}).then(() => {
assert_equals(req.result, null, 'Indexed Database is set to an empty storage.');
req = store.put(storeData.parent);
eventWatcher = new EventWatcher(t, req, 'success');
return eventWatcher.wait_for('success');
}).then(() => {
db.close();
db = null;
let req = indexedDB.open(dbName, 1), store, transaction;
return new Promise((resolve, reject) => {
// The test would fail when the database is already created by the controlling UA
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the IndexedDB spec, you can test for existence of a database by a non-empty version property on the result object.

https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase

Perhaps the test would be simpler by just checking whether a database already exists (thus indicating whether the database was leaked across receiving browsing contexts).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea. Regarding IndexedDB, we can simply check version of a database. I'll simplify and submit these codes later.

BTW, I'm afraid that the MDN article might be incorrect. With regard to indexedDB.open, the IndexedDB spec says:

If version is not given and no database with that name exists, a new database will be created with version equal to 1.

Anyway, we can still check whether the database has been previously created or not by looking at version of the database.

let upgradeNeeded = false;

req.onupgradeneeded = () => {
upgradeNeeded = true;
db = req.result;
store = db.createObjectStore(storeName, { keyPath: 'id' });
store.add(storeData.parent);
};
req.onsuccess = () => {
if (!upgradeNeeded)
reject(null);
db.close();
db = null;
resolve();
};
req.onerror = reject;
}).catch(e => {
if (!e)
assert_unreached('Indexed Database is set to an empty storage.');
else
throw e;
});
}
else
Expand Down Expand Up @@ -253,29 +256,33 @@
// Indexed Database
const checkUpdatedIndexedDB = () => {
if ('indexedDB' in window) {
let req = indexedDB.open(dbName, 1), store;
let eventWatcher = new EventWatcher(t, req, 'success');
let req, store;
message = 'Indexed Database is shared by top-level and nested browsing contexts.';
const checkItem = event => {
assert_true(event.target.result instanceof IDBCursorWithValue, message);
const cursor = event.target.result;
const item = cursor.value;
assert_equals(storeData[item.id].data, item.data, message);
delete storeData[item.id]
cursor.continue();
return eventWatcher.wait_for('success');
};
return eventWatcher.wait_for('success').then(() => {
db = req.result;
const transaction = db.transaction(storeName, 'readwrite');
store = transaction.objectStore(storeName);
req = store.openCursor();
eventWatcher = new EventWatcher(t, req, 'success');
return eventWatcher.wait_for('success');
}).then(checkItem)
.then(checkItem)
.then(event => {
assert_equals(event.target.result, null, message);
return new Promise((resolve, reject) => {
req = indexedDB.open(dbName, 1);
req.onsuccess = () => {
let results = [];
db = req.result;
const transaction = db.transaction(storeName, 'readwrite');
store = transaction.objectStore(storeName);
req = store.openCursor();
req.onsuccess = () => {
if (req.result) {
const item = req.result.value;
results.push(item);
req.result.continue();
}
else
resolve(results);
};
req.onerror = reject;
};
req.onerror = reject;
}).then(results => {
results.forEach(item => {
assert_equals(storeData[item.id].data, item.data, message);
delete storeData[item.id]
});
assert_equals(Object.keys(storeData).length, 0, message);
db.close();
db = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
modal.textContent = 'confirm()';
confirm(message);
modal.textContent = 'print()';
//print();
print();
modal.textContent = 'prompt()';
prompt(message);
notice.style.display = 'none';
Expand All @@ -61,31 +61,43 @@

// Indexed Database
let db;
const storeName = 'store-controlling-ua';
const checkIndexedDB = () => {
if ('indexedDB' in window) {
message = 'Indexed Database is shared by top-level and nested browsing contexts.';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this required by same-origin policy? Do we need to test this here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention of this is to check if both top-level and nested browsing contexts share the same storage, according to the following spec described in Creating a receiving browsing context:

All nested browsing contexts created by the presented document, i.e. that have the receiving browsing context as their top-level browsing context, [...] MUST also share the same browsing state (storage) for features 5-10 listed above.

let req = indexedDB.open('db-presentation-api', 1), store;
let eventWatcher = new EventWatcher(t, req, 'success');
return eventWatcher.wait_for('success').then(() => {
db = req.result;
const transaction = db.transaction('store-controlling-ua', 'readwrite');
store = transaction.objectStore('store-controlling-ua');
req = store.openCursor();
eventWatcher = new EventWatcher(t, req, 'success');
return eventWatcher.wait_for('success');
}).then(() => {
assert_true(req.result instanceof IDBCursorWithValue, message);
const cursor = req.result;
const item = cursor.value;
return new Promise((resolve, reject) => {
req.onsuccess = () => {
let results = [];
db = req.result;
const transaction = db.transaction(storeName, 'readwrite');
store = transaction.objectStore(storeName);
req = store.openCursor();
req.onsuccess = () => {
if (req.result) {
const item = req.result.value;
results.push(item);
req.result.continue();
}
else
resolve(results);
};
req.onerror = reject;
};
req.onerror = reject;
}).then(results => {
assert_equals(results.length, 1, message);
const item = results[0];
assert_equals(item.id, 'parent', message);
assert_equals(item.data, 'receiving user agent', message);
cursor.continue();
return eventWatcher.wait_for('success');
}).then(() => {
assert_equals(req.result, null, message);
req = store.put({ id: 'child', data: 'nested browsing context' });
eventWatcher = new EventWatcher(t, req, 'success');
return eventWatcher.wait_for('success');

return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
store = transaction.objectStore(storeName);
req = store.put({ id: 'child', data: 'nested browsing context' });
req.onsuccess = resolve;
req.onerror = reject;
});
}).then(() => {
db.close();
db = null;
Expand Down